8 Replies Latest reply: Aug 1, 2007 9:46 AM by 800306 RSS

    IllegalArgument when trying to create a packed Raster of 16-bit data

    800306
      Hi,

      I have a class that does some image processing, and I'm trying to create a BufferedImage with some int[] data. The data is 16-bit data, but inside an int[], not a short[] (no, I do not want to convert back to short[]).

      I am trying to use the Raster.createPackedRaster(DataBuffer, int, int, int, Point) method to create a MultiPixelPackedSampleModel. I am getting an IllegalArgumentException when I try to create a new BufferedImage with the WritableRaster, and I have no idea why, although I've checked the API docs multiple times.

      Here is the exception:
      java.lang.IllegalArgumentException: Raster sun.awt.image.SunWritableRaster@9e5c73 is incompatible with ColorModel ColorModel: #pixelBits = 32 numComponents = 1 color space = java.awt.color.ICC_ColorSpace@c791b9 transparency = 1 has alpha = false isAlphaPre = false
              at java.awt.image.BufferedImage.<init>(BufferedImage.java:611)
              at service.ImageProcessor.toImage(ImageProcessor.java:88)
              at service.ImageProcessor.createAndSaveImage(ImageProcessor.java:93)
      etc........
      Here is the method I am using to create a new BufferedImage:
      private static BufferedImage toImage(byte[] data, int w, int h, int bitsPerPixel, boolean correctBitOrder) {
              DataBuffer buffer;
              ColorSpace cs =     ColorSpace.getInstance(ColorSpace.CS_GRAY);
              ColorModel cm;
              WritableRaster raster;
              buffer = new DataBufferInt(convertBytesToInts(data, correctBitOrder), data.length/2);
              cm = new ComponentColorModel(cs, false, true, Transparency.OPAQUE, DataBuffer.TYPE_INT);
              raster = Raster.createPackedRaster(buffer, w, h, bitsPerPixel, null);
              return new BufferedImage(cm, raster, false, null);
      }
      byte[] data = the data I receive. This is converted to ints with the convertBytesToInts method (this method works fine).
      int w = width of image
      int h = height of image
      int bitsPerPixel = 16 in this case
      boolean correctBitOrder = irrelevant here

      The exception says the error occurs at line 88; this is my return statement where I try to create the new BufferedImage.

      I'm pretty much out of ideas here, so any advice would be truly appreciated.

      Thanks,
      Dan

      Message was edited by:
      Djaunl

      Message was edited by:
      Djaunl
        • 1. Re: IllegalArgument when trying to create a packed Raster of 16-bit data
          796365
          Most probably this line is the cause:
          buffer = new DataBufferInt(convertBytesToInts(data, correctBitOrder), data.length/2);
          How do you know convertBytesToInts "works fine"?
          • 2. Re: IllegalArgument when trying to create a packed Raster of 16-bit data
            800306
            Most probably this line is the cause:
            buffer = new
            DataBufferInt(convertBytesToInts(data,
            correctBitOrder), data.length/2);
            How do you know convertBytesToInts "works
            fine"?
            Well I suppose I don't know with 100% certainty. I tested it by outputting all the resulting int values to make sure they were 16-bit, which they are. I'm not too sure how I could troubleshoot that.

            Here is the method:
                 public static int[] convertBytesToInts(byte[] data, boolean correctBitOrder) {
                      int[] convertedData = new int[data.length/2];
                      if (correctBitOrder) {
                           for (int i = 0; i < data.length-1; i++) {
                                convertedData[i] = (int)((data[i] << 8) | (data[i+1] & 0xff));
                                convertedData[i] = (int)((int)convertedData[i] & 0xffff);
                           }
                      } else {
                           for (int i = 0; i < data.length-1; i++) {
                                convertedData[i] = (int)((data[i+1] << 8) | (data[i] & 0xff));
                                convertedData[i] = (int)((int)convertedData[i] & 0xffff);
                           }
                      }
                      return convertedData;
                 }
            correctBitOrder = true for this program.

            I'm taking in a byte[], and converting every two bytes into one int (e.g. byteArray[0] + byteArray[1] = intArray[0]). Then, I AND the bits with 0xffff so the bits are expressed as unsigned in the int[].

            Is the rest of the code (in the toImage() method) fine?
            • 3. Re: IllegalArgument when trying to create a packed Raster of 16-bit data
              796365
              This looks suspicious
              int[] convertedData = new int[data.length/2];
              You have specified data[] as bytes, but want an int[] - why divide by 2? shouldn't it be divide by 4?

              You need to fully debug this method. Do some testing using individual values (not arrays) of bytes, ints, etc and verify that it works correctly. Use print statements to see what is happening at each step in the method.
              • 4. Re: IllegalArgument when trying to create a packed Raster of 16-bit data
                800306
                This looks suspicious
                int[] convertedData = new
                int[data.length/2];
                You have specified data[] as bytes, but want an int[]
                - why divide by 2? shouldn't it be divide by 4?

                You need to fully debug this method. Do some testing
                using individual values (not arrays) of bytes, ints,
                etc and verify that it works correctly. Use print
                statements to see what is happening at each step in
                the method.
                It's divided by two because I'm putting two bytes into one int, not four bytes into one int. This is so I can transport the data into an external application and "eliminate" the signed bit.

                I will debug the method and reply back.
                • 5. Re: IllegalArgument when trying to create a packed Raster of 16-bit data
                  796365
                  Okay. Note that I asked because

                  1 int = 2 shorts = 4 bytes

                  therefore equivalent arrays would differ by a factor of 4
                  • 6. Re: IllegalArgument when trying to create a packed Raster of 16-bit data
                    800306
                    Okay. Note that I asked because

                    1 int = 2 shorts = 4 bytes

                    therefore equivalent arrays would differ by a factor
                    of 4
                    Yes, I understand.

                    It turns out you were right about my method. I needed to increment i by two, not by one, as incrementing by one is wrong, basically. I changed the method to:
                         public static int[] convertBytesToInts(byte[] data, boolean correctBitOrder) {
                              System.out.println("INITIALIZE bytes to ints");
                              int[] convertedData = new int[data.length/2];
                              System.out.println("int[] created.");
                              if (correctBitOrder) {
                                   System.out.println("correct bit order.");
                                   int j = 0;
                                   for (int i = 0; i <= data.length; i += 2) {
                                        convertedData[j] = (int)((data[i] << 8) | (data[i+1] & 0xff));
                                        convertedData[j] = (int)((int)convertedData[j] & 0xffff);
                                        System.out.print(convertedData[j] + " ");
                                   }
                              } else {
                                   System.out.println("incorrect bit order.");
                                   int j = 0;
                                   for (int i = 0; i < data.length-1; i++) {
                                        convertedData[j] = (int)((data[i+1] << 8) | (data[i] & 0xff));
                                        convertedData[j] = (int)((int)convertedData[j] & 0xffff);
                                        //System.out.print(convertedData[j] + " ");
                                   }
                              }
                              System.out.println("double you tee eff?");
                              return convertedData;
                         }
                    I'm getting the same error. In fact, the print statement after I declare the int[] isn't even being displayed. Something is messed up that is out of the scope of this problem at the moment; I'll have to get back on this.
                    • 7. Re: IllegalArgument when trying to create a packed Raster of 16-bit data
                      800306
                      I've determined that the convertBytesToInts method works fine. I verified this by using it with the data externally to my ImageProcessor class, porting the converted data to MATLAB,
                      and displaying an image. The image I display in MATLAB with the convertBytesToInts method is correct.

                      Therefore, I have determined that I am screwing up the creation of the Raster or ColorModel somehow, and I'm flat out of ideas. I've read through the API docs for Raster, WritableRaster,
                      ColorModel, ColorSpace, ComponentColorModel, etc., and I have no clue where to go.

                      I have pasted that convertBytesToInts method into another class and used it on the data, and it works fine. When I use it in my image processing class, it fails to execute (probably
                      because of the service I am getting my data from recognizing an error) and throws the exception from the OP.

                      I am just shit out of ideas.

                      Here is the entire toImage method in my ImageProcessor class, copied verbatim:
                          private static BufferedImage toImage(byte[] data, int w, int h, int bitsPerPixel, boolean correctBitOrder) {
                                DataBuffer buffer;
                              ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
                              ColorModel cm;
                              WritableRaster raster;
                                if (bitsPerPixel < 8) {
                                   buffer = new DataBufferByte(data, data.length);
                                       cm = new ComponentColorModel(cs, false, true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
                                       raster = Raster.createInterleavedRaster(buffer, w, h, w, 1, new int[] {0}, null);
                                } else if ((bitsPerPixel < 16)) {
                                     System.out.println("Databuffer UShort");
                                     buffer = new DataBufferUShort(packBytesToShorts(data, correctBitOrder), data.length/2);
                                       cm = new ComponentColorModel(cs, false, true, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
                                       raster = Raster.createInterleavedRaster(buffer, w, h, w, 1, new int[] {0}, null);
                                } else {
                                     System.out.println("Databuffer int");
                                     buffer = new DataBufferInt(convertBytesToInts(data, correctBitOrder), data.length);
                                     cm = new ComponentColorModel(cs, false, true, Transparency.OPAQUE, DataBuffer.TYPE_INT);
                                     raster = Raster.createPackedRaster(buffer, w, h, bitsPerPixel, null);
                                     //raster = Raster.createInterleavedRaster(buffer, w, h, w, 1, new int[] {0}, null);
                                }
                              /*raster = Raster.createInterleavedRaster(buffer, w, h, w,
                              1, new int[] {
                                  0
                              } , null);*/
                              System.out.println("BBBBBBBBBBBBBBBBBBBBBBB");
                              return new BufferedImage(cm, raster, false, null);
                          }
                      Note that the System.out.println("BBBBBB...") is just a check for me.

                      When I try to run my program, the output is:

                      Databuffer int
                      INITIALIZE bytes to ints
                      BBBBBBBBBBBBBBBBBBBBBBB
                      Exception from OP

                      It does NOT print out anything from the convertBytesToInts method except for the first print statement, and I have no freakin' idea why.

                      I'm completely lost, so any advice would be great.

                      Thanks

                      Message was edited by:
                      Djaunl
                      • 8. Re: IllegalArgument when trying to create a packed Raster of 16-bit data
                        800306
                        Ah-hah! Kind of. In the ColorModel API, it says:

                        For BufferedImages, the transfer type of its Raster and of the Raster object's SampleModel (available from the getTransferType methods of these classes) must
                        match that of the ColorModel.


                        However, when I add some System.out.println(ColorModel.getTransferType()) statements and some System.out.println(Raster.getTransferType()) statements,
                        they are different! The transfer type for the ColorModel is 3, whereas the transfer type for the Raster is 1.

                        So...I'm still confused. What does this mean? How can I solve this?

                        Message was edited by:
                        Djaunl