简体   繁体   English

有没有办法让 Java 将 PNG 读取为 TYPE_INT_RGB / TYPE_INT_ARGB?

[英]Is there a way to get Java to read a PNG as TYPE_INT_RGB / TYPE_INT_ARGB?

When I read a PNG image in Java using javax.imageio.ImageIO.read() , the resulting BufferedImage is of TYPE_3BYTE_BGR or TYPE_4BYTE_ABGR depending on transparency.当我使用javax.imageio.ImageIO.read()读取 Java 中的 PNG 图像时,生成的BufferedImageTYPE_3BYTE_BGRTYPE_4BYTE_ABGR ,具体取决于透明度。

I'm processing very large images (64+ megapixels), and need them in TYPE_INT_RGB / TYPE_INT_ARGB format, which requires an expensive and very-large-chunk-of-memory hogging repainting of the image onto a new image in the correct format, which is causing OOMs.我正在处理非常大的图像(64+ 百万像素),并且需要TYPE_INT_RGB / TYPE_INT_ARGB格式,这需要以正确的格式将图像重新绘制到新图像上的昂贵且非常大的内存块占用,这是导致 OOM 的原因。

It would be much better if I could somehow persuade ImageIO to read the image in the desired format from the get-go - is there any way of doing that?如果我能以某种方式说服ImageIO从一开始就以所需格式读取图像,那就更好了——有什么办法吗? Thanks!谢谢!

Yes, it is possible to read into a predefined type of BufferedImage , given that the type is supported by and compatible with the reader plugin.是的,可以读入预定义类型的BufferedImage ,前提是该类型受阅读器插件支持并与之兼容。 Most often the TYPE_#BYTE_* types are compatible with the TYPE_INT_* types, and this is the case for the standard PNGImageReader .大多数情况下, TYPE_#BYTE_*类型与TYPE_INT_*类型兼容,标准PNGImageReader就是这种情况。

To make it work, you need access to the ImageReader directly, and use the read method that takes an ImageReadParam to control the type of image.要使其工作,您需要直接访问ImageReader ,并使用采用ImageReadParamread方法来控制图像类型。 It's possible to read into a pre-allocated image by using the ImageReadParam.setDestination(..) method, or to just specify the type of image and let the reader plugin allocate it for you by using ImageReadParam.setDestinationType(..) like I will show below.可以使用ImageReadParam.setDestination(..)方法读取预分配的图像,或者只指定图像类型,让阅读器插件使用ImageReadParam.setDestinationType(..)为您分配它,就像我一样将在下面显示。

Here's a short stand-alone code sample that shows how to read into a specific image type:下面是一个简短的独立代码示例,展示了如何读入特定图像类型:

public static void main(String[] args) throws IOException {
    File input = new File(args[0]);

    try (ImageInputStream stream = ImageIO.createImageInputStream(input)) {
        // Find a suitable reader
        Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
        if (!readers.hasNext()) {
            throw new IIOException("No reader for " + input);
        }

        ImageReader reader = readers.next();
        try {
            reader.setInput(stream);

            // Query the reader for types and select the best match
            ImageTypeSpecifier intPackedType = getIntPackedType(reader);
            System.out.println("intPackedType = " + intPackedType);

            // Pass the type to the reader using read param
            ImageReadParam param = reader.getDefaultReadParam();
            param.setDestinationType(intPackedType);

            // Finally read the image
            BufferedImage image = reader.read(0, param);
            System.out.println("image = " + image);
        }
        finally {
            reader.dispose();
        }
    }
}

private static ImageTypeSpecifier getIntPackedType(ImageReader reader) throws IOException {
    Iterator<ImageTypeSpecifier> types = reader.getImageTypes(0);

    while (types.hasNext()) {
        ImageTypeSpecifier spec = types.next();

        switch (spec.getBufferedImageType()) {
            case BufferedImage.TYPE_INT_RGB:
            case BufferedImage.TYPE_INT_ARGB:
                return spec;
            default:
                // continue searching
        }
    }

    return null;
}

Sample output from one of my runs using a PNG as input:使用 PNG 作为输入从我的一次运行中采样 output:

intPackedType = javax.imageio.ImageTypeSpecifier$Packed@707084ba
image = BufferedImage@45ff54e6: type = 2 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=ff000000 IntegerInterleavedRaster: width = 100 height = 100 #Bands = 4 xOff = 0 yOff = 0 dataOffset[0] 0

Where type = 2 means BufferedImage.TYPE_INT_ARGB .其中type = 2表示BufferedImage.TYPE_INT_ARGB

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM