Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7116979

Unexpected pixel colour when converting images to TYPE_BYTE_INDEXED

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P4
    • Resolution: Fixed
    • Affects Version/s: 7
    • Fix Version/s: 9
    • Component/s: client-libs
    • Labels:
    • Subcomponent:
      2d
    • Resolved In Build:
      b118
    • CPU:
      generic
    • OS:
      generic

      Description

      SYNOPSIS
      --------
      Unexpected pixel colour when converting images to TYPE_BYTE_INDEXED

      OPERATING SYSTEM
      ----------------
      All (tested on Windows and Linux)

      FULL JDK VERSION
      ----------------
      All (tested with latest 5.0, 6 and 7)

      DESCRIPTION
      -----------
      The attached testcase creates an image that is totally black, then converts it between two image formats. A number of different combinations are tested, and most of them convert as expected. However, when converting to TYPE_BYTE_INDEXED, some pixels change in colour from 0x000000 (black) to 0x121212 (a dark grey). The affected pixels are not random - they appear to follow a pattern, almost like dithering.

      REPRODUCTION INSTRUCTIONS
      -------------------------
      1. Compile and run attached test program
           > javac ImageTest2.java
           > java ImageTest2

      2. The testcase will indicate which conversions were successful. Failed
         conversions are saved to files for viewing afterwards. (successfully
         converted (black) pixels are converted to be transparent, so that
         the incorrectly converted pixels stand out.)

      3. Open the files in an image editor / browser.

      Expected result:
      All image types should be converted properly, without the change in pixel colour. No files should be written.

      Observed result:
      All conversions to TYPE_BYTE_INDEXED feature a pattern of pixels which have changed colour from 0x000000 (black) to 0x121212 (a dark grey).

      TESTCASE
      --------
      import java.io.*;
      import java.util.*;
      import java.awt.*;
      import java.awt.image.*;
      import javax.imageio.ImageIO;

      public class ImageTest2 {
          static final int[] types = new int[]{
              BufferedImage.TYPE_INT_RGB,
              BufferedImage.TYPE_INT_ARGB,
              BufferedImage.TYPE_INT_ARGB_PRE,
              BufferedImage.TYPE_INT_BGR,
              BufferedImage.TYPE_3BYTE_BGR,
              BufferedImage.TYPE_4BYTE_ABGR,
              BufferedImage.TYPE_4BYTE_ABGR_PRE,
              BufferedImage.TYPE_USHORT_565_RGB,
              BufferedImage.TYPE_USHORT_555_RGB,
              BufferedImage.TYPE_BYTE_GRAY,
              BufferedImage.TYPE_USHORT_GRAY,
              BufferedImage.TYPE_BYTE_BINARY,
              BufferedImage.TYPE_BYTE_INDEXED};

          static final String[] type_name = new String[]{
              "INT_RGB",
              "INT_ARGB",
              "INT_ARGB_PRE",
              "INT_BGR",
              "3BYTE_BGR",
              "4BYTE_ABGR",
              "4BYTE_ABGR_PRE",
              "USHORT_565_RGB",
              "USHORT_555_RGB",
              "BYTE_GRAY",
              "USHORT_GRAY",
              "BYTE_BINARY",
              "BYTE_INDEXED"};

          static Hashtable<Integer,String> type_table = new Hashtable<Integer,String>();

          static {
              for(int i = 0; i < types.length; i++){
                  type_table.put(new Integer(types[i]), type_name[i]);
              }
          }

          static int w_size = 100;
          static int h_size = 100;

          ImageTest2(String prefix, int type1, int type2) throws Exception {
              BufferedImage img1 = new BufferedImage(w_size, h_size, type1);
              Graphics2D img1_g2d = img1.createGraphics();
              img1_g2d.setColor(Color.BLACK);
              img1_g2d.fillRect(0, 0, img1.getWidth(), img1.getHeight());

              BufferedImage img2 = new BufferedImage(img1.getWidth(), img1.getHeight(), type2);
              Graphics2D img2_g2d = (Graphics2D) img2.getGraphics();
              img2_g2d.drawImage(img1, 0, 0, null);

              BufferedImage argb = new BufferedImage(img2.getWidth(), img2.getHeight(), BufferedImage.TYPE_INT_ARGB);
              Graphics2D argb_g2d = (Graphics2D) argb.getGraphics();
              argb_g2d.drawImage(img2, 0, 0, null);

              boolean isBlack = true;
              for (int i = 0; i < argb.getHeight(); i++) {
                  for (int j = 0; j < argb.getWidth(); j++) {
                      if (Color.BLACK.getRGB() == argb.getRGB(j, i)) {
                          // Make black pixels transparent so that any bad pixels (which are dark grey) stand out
                          argb.setRGB(j, i, 0);
                      } else {
                          // Found a non-black pixel
                          isBlack = false;
                      }
                   
                  }
              }
             
              if (isBlack == false) {
                  System.out.print("FAILED: " + type_table.get(type1) + " -> " + type_table.get(type2));
                  String outfile = prefix + "_" + type_table.get(type1) + "-" + type_table.get(type2) + ".png";
                  File f = new File(outfile);
                  ImageIO.write(argb, "PNG", f);
                  System.out.println(" (Image written as: " + f.getCanonicalPath() + ")");
              } else {
                  System.out.println("PASSED: " + type_table.get(type1) + " -> " + type_table.get(type2));
              }

          }

          public static void main(String args[]) throws Exception {
              String prefix = args.length > 0 ? args[0] : "img";
              for(int i = 0; i < types.length; i++) {
                  for(int j = 0; j < types.length; j++) {
                      new ImageTest2(prefix, types[i], types[j]);
                  }
              }
          }
      }

        Attachments

          Activity

            People

            Assignee:
            jdv Jayathirth D V
            Reporter:
            dkorbel David Korbel (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: