JAI TIFF编解码器创建工件

问题描述 投票:2回答:1

我一直在使用JAI来编写和读取TIFF图像,但是我最近在编码灰度图像时遇到了一个问题,我在每个条带的末尾得到7个黑色(0)像素(每个条带8行):

我只能在使用下面的SSCE设置使用放气等级DEFLATE进行0压缩时才能重现它。任何其他价值似乎都有效。

我有时也目睹了图像的条带向左移动了30个像素左右。虽然我无法对这个问题进行稳定的再现,但是如果你知道一些关于在JAI中编码TIFF的隐藏技巧,它也可能会摆脱它。

private static byte[] genImage(int width, int height) {
    byte[] pix = new byte[width * height];
    Arrays.fill(pix, (byte)0xcf);
    for (int j = 0; j < height; j++) {
        Arrays.fill(pix, j*width + width/3, j*width + 2*width/3, (byte)0x7f);
    }
    return pix;
}

public static void main(String[] args) throws Exception {
    int width = 256;
    int height = 256;
    byte[] pix = genImage(width, height);
    BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
    System.arraycopy(pix, 0, ((DataBufferByte)img.getRaster().getDataBuffer()).getData(), 0, width * height);
    TIFFEncodeParam comp = new TIFFEncodeParam();
    comp.setCompression(TIFFEncodeParam.COMPRESSION_DEFLATE);
    comp.setDeflateLevel(0); // Changing 0 to values 1-9 "solves" the problem

    FileOutputStream fos = new FileOutputStream("bugjai.tiff");
    ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", fos, comp);
    encoder.encode(img);
    fos.close();
}

编辑:

我进一步调查了8x8图像上的文件内容。我使用级别0(使用java.util.zip.Deflater)放弃了字节内容,得到了额外的11个字节。我在条带的末尾插入这些字节并修补标题以反映新的长度(值4B而不是位于4075h),并且瞧!没有更多7像素。

因此,似乎在JAI中存在误解“忘记”在放气时放置/计数字节。但是,TIFF6 specification在第15页开头说:

预计价值将从字边界开始;因此,相应的值偏移将是偶数

哪个让我困惑:“开始”是指文件中的位置? “修补”值从40切换到4B,这是不均匀的。 JAI可能会以某种方式错误估算某些东西并向下舍入吗?

附录:

当“压缩”数据大于原始数据时,似乎会出现问题:在这里,当压缩数据长度为75字节时,原始数据长度为64字节。 JAI可能假设图像的最大尺寸不能超过原始数据的大小。

java tiff deflate jai artifacts
1个回答
1
投票

因此,在问题中进行了一些额外的测试(参见EDIT和ADDENDUM)后,JAI中似乎存在一个错误,将最大字节数限制为width * heigth。我猜他们认为没有压缩会增加图像的大小...除了你用一个因子0(我理解为“存储”)放气,你得到像素,加上一个标题和尾标。由于JAI限制了写入的字节数,因此未正确写入尾数(如果有的话),并且数据未完全解码。

教训是:至少使用1的缩小因子(在BEST_SPEED中也标记为MIN_COMPRESSION / the javadoc)。

© www.soinside.com 2019 - 2024. All rights reserved.