Reading black and white PNG images without distortion

I need to read and process a large number of PNG files that have shades of gray. By this I mean that if they are open in Photoshop or GIMP, the image mode - Grayscale - is not an RGB image with shades of gray.

ImageIO does not seem to achieve this. It seems that all image files are treated as sRGB. This changes the shades of gray. I need to read and process these PNG files, where (in my code) each pixel has exactly the same meaning as if I opened the file in grayscale in Photoshop or GIMP. Does anyone know of some open source software that can do this, please? Or better, how to achieve this using ImageIO.

Additional Information:

I am using getRGB () for BufferedImage. The base pixel in the image file is 0x86. I understand that this does not necessarily correspond to an ARGB pixel containing 0xFF868686, since it depends on brightness / gamma. However, in the absence of a getter with an argument of type gamma, I expected the default mapping to match ARGB = 0xFF868686. If I use GIMP or Photoshop to convert a grayscale image containing a pixel with a value of 0x86 to RGB, then the pixel becomes 0xFF868686. This is an obvious default.

However, ImageIO seems to use a weird gamma (whether you like it or not) with grayscale images, which makes grayscale pixels very, very light after comparing with ARGB. In this case, 0x86 maps to 0xFFC0C0C0. This is not only very easy, but can also lead to significant data loss, since many grayscale values ​​can be matched with fewer ARGB values. The only time this distortion does not result in data loss is for very dark grayscale images. The corresponding gamma depends on the context, different physical environments will distort the brightness in different ways. However, in the absence of context, the display: 0x86 → 0xFF868686 is of the greatest importance - testify to the choices made for GIMP and Photoshop.

getRGB() , ( ImageIO.read(imageFile)), getType() BufferedImage Type = 0 (Custom), Type = 10 (TYPE_BYTE_GRAY) .

, ImageIO, , . , Rasters, ICC, .. , RGB. , , load() API BufferedImage, , GIMP Photoshop. . , , Java ImageIO.

:

:

final File imageFile = new File( "test.png" );
final BufferedImage image = ImageIO.read( imageFile );
// --- Confirm that image has ColorSpace Type is GRAY and PixelSize==16
final Raster raster = image.getData();
// --- Confirm that: raster.getTransferType() == DataBuffer.TYPE_BYTE

for( int x=0, xLimit=image.getWidth(); x < xLimit; x++ ) {
    for( int y=0, yLimit=image.getHeight(); y < yLimit; y++ ) {

        final Object dataObject = raster.getDataElements( x, y, null );
        // --- Confirm that dataObject is instance of byte[]
        final byte[] pixelData = (byte[]) dataObject;
        // --- Confirm that: pixelData.length == 2

        final int grayscalePixelValue = pixelData[0] & 0xFF;
        final int grayscalePixelAlpha = pixelData[1] & 0xFF;

        // --- Do something with the grayscale pixel data
    }
}

javadoc , , , , , .

+1
2

() lib: https://github.com/leonbloy/pngj/

, (8 , , , ), :

    PngReaderByte pngr = new PngReaderByte(new File(filename)); // 
    if (pngr.imgInfo.channels!=1 || pngr.imgInfo.bitDepth != 8 || pngr.imgInfo.indexed)
        throw new RuntimeException("This method is for gray images");
    for (int row = 0; row < pngr.imgInfo.rows; row++) { 
        ImageLineByte line = pngr.readRowByte();
        byte [] buf = line.getScanlineByte();
        // do what you want
    }
    pngr.end(); 
+2

Source: https://habr.com/ru/post/1616180/


All Articles