4 Replies Latest reply: Feb 20, 2012 11:30 AM by Maxideon RSS

    Translucent grayscale png image looks washed out - brightness change

      I'm having trouble with translucent grayscale png images. These images are coming from a GetMap-request (request for an image) to a geoserver, and I'm trying to understand why they behave like they do.
      The thing is I have to make several image-requests like this - both color and grayscale images - and draw them all together on a new BufferedImage. But as soon as I do this with one of these grayscale images they become washed out. I have a simple code example to illustrate:
      public static void main(String[] args) throws IOException {
           String aFilename = "ortosvsweref99", aSuffix = "png";
           BufferedImage aSrcImage = ImageIO.read(new File(aFilename + "." + aSuffix));
           BufferedImage aDestImage = new BufferedImage(aSrcImage.getWidth(null), aSrcImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
           Graphics2D aDestGraphics = aDestImage.createGraphics();
           aDestGraphics.drawImage(aSrcImage, 0, 0, null);
      // Use aDestGraphics to draw other images to aDestImage here...
           ImageIO.write(aSrcImage, aSuffix, new FileOutputStream("testSrc." + aSuffix));
           ImageIO.write(aDestImage, aSuffix, new FileOutputStream("testDest." + aSuffix));
      An image example can be downloaded here: http://img214.imageshack.us/img214/5853/ortosvsweref99.png
      Using this as input, you can see that testDest.png looks different from testSrc.png.

      The things I've singled out that differs from when I load other images that are drawn correctly are these:
      aSrcImage.getType() returns BufferedImage.TYPE_CUSTOM
      aSrcImage.getColormodel().getTransparency() returns ColorModel.TRANSLUCENT
      aSrcImage.getColormodel().getColorSpace().getType() ColorSpace.TYPE_GRAY

      I've tried this example with both java- and jdk1.7.0_01 getting the same results. Anyone got an educated guess as to what's going on? Is it the TYPE_CUSTOM that causes the problem, or is it something else completely?

      Best regards,
      /Johan Lindbergh
        • 1. Re: Translucent grayscale png image looks washed out - brightness change
          I have the same type of problem on my Ubuntu instance when I go to borderless/pixel by pixel transparency. I do not have that problem in Windows 7, nor do I have the condition happen in either install with a boardered JFrame. This suggests to me that I have a driver incompatibility with pixel by pixel (boarderless) transparencies.
          • 2. Re: Translucent grayscale png image looks washed out - brightness change
            When going from a non-sRGB color space to an sRGB one, the ColorConvertOp class does a slight gamma alteration. This causes the image to come out 'brighter' then expected.

            Under most circumstances the underlying drawing routines don't do this gamma alteration. However, TYPE_CUSTOM images can cause the routines to simply call getRGB() to draw, which in turn does the same gamma alteration.

            A workaround is that anytime you detect a gray+alpha TYPE_CUSTOM image then do the image conversion manually, like so:
            BufferedImage src = //TYPE_CUSTOM gray/alpha image
            //keep the alpha
            BufferedImage dst = new BufferedImage(src.getWidth(),
            Raster srcRaster = src.getRaster();
            WritableRaster dstRaster = dst.getRaster();
            int[] gray = null, alpha = null;
            int w = srcRaster.getWidth();
            for(int y = 0; y < src.getHeight(); y++) {
                gray  = srcRaster.getSamples(0,y,w,1,0,gray);
                alpha = srcRaster.getSamples(0,y,w,1,1,alpha);
            //don't keep the alpha
            BufferedImage dst = new BufferedImage(src.getWidth(),
            int row[] = null;
            for(int y = 0; y < dst.getHeight(); y++) {
            There are more efficient ways to do the ABGR case, but that's the gist of it.
            • 3. Re: Translucent grayscale png image looks washed out - brightness change
              Thank you Maxideon, your post was really helpful!
              I tried writing directly to the destination image raster as you suggested, and it works perfectly!

              I actually tried earlier using an explicit ColorConvertOp in the drawImage call, going from TYPE_GRAY and/or CS_GRAY to TYPE_LINEAR_RGB and/or CS_sRGB but didn't get the expected image contrast. This is probably also as you say because it does a bit of gamma alteration. The question that pops up in my head then is: why? Is this a bug in Java? Or is this gamma alteration needed in other cases?

              Thanks again Maxideon!
              • 4. Re: Translucent grayscale png image looks washed out - brightness change
                My familiarity with this problem comes from trying to color convert CMYK jpeg images. Using the ColorConvertOp class the images would come out brighter then compared to other image editing software. It turned out that the ColorConvertOp class was treating ICC_Profiles with class 'output' as always having a rendering intent of 'relative colorimetric', instead of 'perceptual' (line #383). I don't know enough about color conversions nor profiles to know if this a bug with the ColorConvertOp class or if the profiles shouldn't be of class 'output.'

                The fix was to change the profile's class to 'display' before doing the conversion. But then someone noted that the fix doesn't work for gray custom format BufferedImages as you can get from the png format. Indeed I don't know why it doesn't work for gray images, nor do I know if the gamma correction is technically correct or not. All I know is that the fix for that particular case is to simply copy the raster. I've tried to find a single workaround that would satisfy both CMYK images and gray images, hoping that would get to the heart of the matter, but I've not found one.