Frank Weber
Frank Weber

Reputation: 41

Java BufferedImage gray to RGB conversion

I have a 8 bit gray scale bitmap on which I need to do some pattern recognition. I created a first test frame work in java and it worked fine.

After that I ported everything to C++ and found out that my patterns are no longer found.

After some investigation I realized that in the java code there was a "hidden" format change from TYPE_BYTE_GRAY to TYPE_3BYTE_BGR.

I could brake it down to the following test function:

public static void ConvertFiles(File dir, String format)
{
    File[] images = getOrderedFiles(dir, format);
    for (int i = 0; i < images.length; i++)
    {
        try
        {
            BufferedImage img = ImageIO.read(images[i]);
            BufferedImage dst = new BufferedImage(img.getWidth() , img.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
            for (int xTarget = 0; xTarget <img.getWidth(); xTarget++)
            {
                for (int yTarget = 0; yTarget <img.getHeight(); yTarget++)
                {
                    int val = img.getRGB(xTarget, yTarget); 
                    dst.setRGB(xTarget,yTarget, val);
                }
            }
            ImageIO.write(dst, "bmp", new File(correctSlash(images[i].getParent()) + "Convert\\" + images[i].getName()));
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

The resulting file seems to be "brighter" (can't post the images, sorry. I can sen them on request). When I use TYPE_BYTE_GRAY when creating the new image no change appears, so it is obvious how to avoid the effect in Java.

Problem is now, I like the "brightened" image better and would like to know what is happening here so I can reproduce this as some kind of image enhancement.

Thx in advance.

Upvotes: 2

Views: 549

Answers (1)

Frank Weber
Frank Weber

Reputation: 41

Found it by digging into the java code (getRGB()) with a colleague (thank you Holger).

There is a conversion applied to the originally gray value by a look up table which is generated like this:

l8Tos8 = new byte[256];
float input, output;
// algorithm for linear RGB to nonlinear sRGB conversion
// is from the IEC 61966-2-1 International Standard,
// Colour Management - Default RGB colour space - sRGB,
// First Edition, 1999-10,
// avaiable for order at http://www.iec.ch
for (int i = 0; i <= 255; i++) {
    input = ((float) i) / 255.0f;
    if (input <= 0.0031308f) {
        output = input * 12.92f;
    } else {
        output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4)))
                 - 0.055f;
    }
    l8Tos8[i] = (byte) Math.round(output * 255.0f);
} 

So at least in parts gamma correction.

I can apply this on the C++ side an get the same result.

Upvotes: 2

Related Questions