Java 使用JAI/ImageIO写入时将灰度图像渲染到黑暗区域

Java 使用JAI/ImageIO写入时将灰度图像渲染到黑暗区域,java,graphics,rendering,javax.imageio,Java,Graphics,Rendering,Javax.imageio,有人能解释为什么会发生这种情况吗。我读取图像并将其渲染到输出写入器中。如果是彩色文件(或黑白文件),则渲染效果良好。然而,如果源图像是灰度的,我得到的只是一个黑匣子 示例文件可在 下面是我的pom插件依赖性片段 <dependency> <groupId>javax.media</groupId> <artifactId>jai_core</artifactId> <vers

有人能解释为什么会发生这种情况吗。我读取图像并将其渲染到输出写入器中。如果是彩色文件(或黑白文件),则渲染效果良好。然而,如果源图像是灰度的,我得到的只是一个黑匣子

示例文件可在

下面是我的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>

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

无论如何,经过一些研究,我得出结论,问题最终在于示例文件,而不是您的代码或您正在使用的库

此文件的问题在于TIFF元数据包含
photommetricinterpretation==3
/palete和
ColorMap
标记。即,图像使用索引颜色模型/调色板。如果根据(我的理解)规范,使用所提供的颜色映射,按照应该的方式读取图像,则图像将显示为全黑色。相反,如果我忽略了这一点,而是将其读取为灰度(假设
PhotometricInterpretation==1
/black为零),它将显示为白色(浅灰色)背景上的黑色文本

编辑:


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

请将相关代码(最好是a)与您的问题一起发布在此处,而不是链接中。链接可能会失效,链接可能包含大型项目,这些项目太大,无法要求志愿者进行审查。我们将非常感谢您遵守此请求,这可能会帮助您获得更好、更快的帮助。您为什么要将图像绘制到自身上?这可能不是您的意图……这只是一段工作代码。在我的实际应用程序中,我在绘制图形之前对图形进行编辑(在文本上添加黑色矩形)、调整大小等。也就是说,还有什么我应该做的吗?谢谢我的评论有意义吗,或者我还遗漏了什么?不,这是有道理的。但我还是会删除那个代码,看看它是否会改变什么,如果不会,就编辑这个问题。帮助您的助手关注您的问题,而不是非问题。:-)此外,由于TIFF阅读/写作没有与JRE捆绑在一起,您可能应该提及您正在使用的插件和版本等(我猜是JAI,但我可能错了)。非常感谢您的研究。我将研究原始图像是如何创建的(由我们使用的第三方库创建)。除此之外,我能做些什么来解决标准java/imageio库的问题吗(我猜不会)metadata@VinayB你可以。但是图像不准确,其他图像可能完全关闭。我认为你最好的选择是1:告诉第三方库写灰度而不是调色板。2:修复第三方库。3:截取colormap中的所有值并将其乘以256。或者使用我的库,由于您的问题,它现在支持此功能。:-)
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();
}
}