使用JAI / ImageIO编写时,GrayScale图像渲染到暗区

时间:2014-10-24 23:22:46

标签: java graphics rendering javax.imageio

任何人都可以解释为什么会这样。我读了一个图像并将其渲染成输出编写器。如果它是一个颜色文件(或黑色和白色),它呈现正常。但是,如果源图像是灰度,我得到的只是一个黑盒子。

https://www.dropbox.com/sh/kyfsh5curobwxrw/AACfWr1NhX8lPUZpzVGWIPQia?dl=0

处提供的示例文件

我的pom插件依赖片段如下。

    <dependency>
        <groupId>javax.media</groupId>
        <artifactId>jai_core</artifactId>
        <version>1.1.3</version>
    </dependency>
    <dependency>
        <groupId>com.sun.media</groupId>
        <artifactId>jai_imageio</artifactId>
        <version>1.1</version>
    </dependency>

测试程序。我知道这段代码本身并没有什么价值,但实际上它是更大的一系列操作的一部分。这段代码代表了我将问题缩小到一小段代码的努力。

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class GrayScaleImaging {
public static void main(String[] args)
        throws IOException {

    //works
//        final File inputFile = new File("/home/vinayb/Downloads/page1_color.tif");
//        final File outputFile = new File("/home/vinayb/Downloads/page1_color_mod.tif");

    //doesn't work
    final File inputFile = new File("/home/vinayb/Downloads/page1_grayscale.tif");
    final File outputFile = new File("/home/vinayb/Downloads/page1_grayscale_mod.tif");
    if (outputFile.exists()) {
        outputFile.delete();
    }

    ImageReader imageReader = null;
    ImageWriter imageWriter = null;
    Graphics2D g = null;

    try (final ImageInputStream imageInputStream = ImageIO.createImageInputStream(inputFile);
         final ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(outputFile);) {


        //setup reader
        imageReader = ImageIO.getImageReaders(imageInputStream).next();
        imageReader.setInput(imageInputStream);

        //read image
        final BufferedImage initialImage = imageReader.read(0);

        //prepare graphics for the output
        final BufferedImage finalImage = new BufferedImage(initialImage.getWidth(), initialImage.getHeight(), imageType(initialImage));
        g = finalImage.createGraphics();

        //do something to the image
        //doSomething(g)

        //draw image
        g.drawImage(initialImage, 0, 0, initialImage.getWidth(), initialImage.getHeight(), null);

        //setup writer based on reader
        imageWriter = ImageIO.getImageWriter(imageReader);
        imageWriter.setOutput(imageOutputStream);

        //write
        imageWriter.write(null, new IIOImage(initialImage, null, imageReader.getImageMetadata(0)), imageWriter.getDefaultWriteParam());
    } finally {
        //cleanup

        if (imageWriter != null) {
            imageWriter.dispose();
        }

        if (imageReader != null) {
            imageReader.dispose();
        }

        if (g != null) {
            g.dispose();
        }
    }
}

private static int imageType(BufferedImage bufferedImage) {
    return bufferedImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : bufferedImage.getType();
}
}

1 个答案:

答案 0 :(得分:1)

好的,我现在修复了我的解码器,感谢您的示例文件! :-)

无论如何,经过一些研究,我得出结论,问题肯定是样本文件,而不是你的代码,也不是你正在使用的库。

此文件的问题是TIFF元数据包含PhotometricInterpretation == 3 / Palette和ColorMap标记。 IE浏览器。图像使用索引颜色模型/调色板。如果根据(我的理解)规格读取图像,使用提供的颜色图,图像全黑。如果我忽略了这一点,而是将其视为灰度(假设为PhotometricInterpretation == 1 / BlackIsZero),则在白色(浅灰色)背景上显示为黑色文本。

编辑:

更好的解释是,颜色映射中的值都是8位数量(使用每个颜色条目的低8位)而不是使用完整的16位...如果我在读取时检测到这一点并且仅使用低8位创建调色板,图像按预期出现(如在DropBox中)。根据规范,这仍然是一个糟糕的图像,但可以检测到。