4 Replies - 1744 Views - Last Post: 24 October 2012 - 07:50 PM Rate Topic: -----

#1 Destro224  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 27
  • Joined: 20-June 12

BufferedImageOp.filter() Throwing Channel Errors

Posted 14 October 2012 - 10:56 AM

NOTE: I have cross-posted this problem over at StackExchange, but not received any repsonses after several days. The text between the two posts is essentially unchanged. (I hope there's nothing wrong with that?)

I'm trying to implement the algorithm used to invert the blue portion of each pixel in a BufferedImage using the BufferedImageOp class, as explained here. My attempt resulted in the creation of this method:

private BufferedImage getInvertedVersion(BufferedImage source) {
     short[] invert = new short[256];
     short[] straight = new short[256];
     for (int i = 0; i < 256; i++) {
        invert[i] = (short)(255 - i);
        straight[i] = (short)i;
     }

     short[][] blueInvert = new short[][] { straight, straight, invert }; //Red stays the same, Green stays the same, Blue is inverted
     BufferedImageOp blueInvertOp = new LookupOp(new ShortLookupTable(0, blueInvert), null);

     //This produces error #1 when uncommented
     /*blueInvertOp.filter(source, source);
     return source;*/

     //This produces error #2 instead when uncommented
     /*return blueInvertOp.filter(source, null);*/
}

However, I'm getting errors related to the number of channels or bytes when I call the .filter method of my BufferedImageOp class. The commented sections of code above produce these respective errors:

Error #1:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Number of channels in the src (4) does not match number of channels in the destination (2)
at java.awt.image.LookupOp.filter(LookupOp.java:273)
at java.awt.image.LookupOp.filter(LookupOp.java:221)

Error #2:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Number of color/alpha components should be 4 but length of bits array is 2
at java.awt.image.ColorModel.<init>(ColorModel.java:336)
at java.awt.image.ComponentColorModel.<init>(ComponentColorModel.java:273)
at java.awt.image.LookupOp.createCompatibleDestImage(LookupOp.java:413)

The code in the link is very old, (it was written in 1998!) so I assume something has changed since then, which is why the code no longer works. However, I haven't been able to find another source that explains the concept nearly as well, which is a primary concern of mine.

Can anyone explain what these errors mean and how to fix them? Or better yet, point me to a more up-to-date, but still thorough, tutorial on how to manipulate images?

Addendum: I've searched other tutorials since posting at StackExchange, which perform similar tasks. They seem to agree with the code I wrote originally. The SE7 Java API also seems to agree with the specific classes used and how they're constructed, as far as I can tell.

Is This A Good Question/Topic? 0
  • +

Replies To: BufferedImageOp.filter() Throwing Channel Errors

#2 Destro224  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 27
  • Joined: 20-June 12

Re: BufferedImageOp.filter() Throwing Channel Errors

Posted 19 October 2012 - 06:38 AM

Does anyone at least have an idea how to start troubleshooting this problem?
Was This Post Helpful? 0
  • +
  • -

#3 Destro224  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 27
  • Joined: 20-June 12

Re: BufferedImageOp.filter() Throwing Channel Errors

Posted 24 October 2012 - 06:59 PM

I've done still more research and discovered something: From my experimenting, it (appears) that BufferedImageOp.filter() does not support buffered images of TYPE_INT_ARGB. When I pass in an image of TYPE_INT_RGB the filter() method doesn't throw an error and seems to work fine.

That's still a problem for me though, because I would like to filter images with an alpha component. I really hope this thread just got passed over and there actually is someone who knows how to help with this method.

Edit: From the Java SE 7 Documentation, there's a small comment that says:

Quote

Images with an IndexColorModel cannot be used.

Could this be related to the problem in some way? I'm having trouble understanding what exactly an IndexColorModel is and what purpose it serves at the moment.

This post has been edited by Destro224: 24 October 2012 - 07:08 PM

Was This Post Helpful? 0
  • +
  • -

#4 Destro224  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 27
  • Joined: 20-June 12

Re: BufferedImageOp.filter() Throwing Channel Errors

Posted 24 October 2012 - 07:26 PM

I'm sorry for the back-to-back posts; I'm unable to edit my previous posts to include new information.

I got my code to work, albeit in a hackish way! I'm not entirely sure why it works, however. My new code is:
private BufferedImage getInvertedVersion(BufferedImage source) {
         short[] invert = new short[256];
         short[] straight = new short[256];
         for (int i = 0; i < 256; i++) {
            invert[i] = (short)(255 - i);
            straight[i] = (short)i;
         }
         
         short[][] blueInvert = new short[][] { straight, straight, invert, straight }; //I believe these affect (in order) Red, Green, Blue, Alpha
         BufferedImageOp blueInvertOp = new LookupOp(new ShortLookupTable(0, blueInvert), null);
         
         BufferedImage tempImage = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_ARGB); //This apparently creates a BufferedImage without whatever property is causing filter() to throw an error
         tempImage.setData(source.getData()); //Transferring only the data over into the new image lets filter() run just fine
         
         return blueInvertOp.filter(source, null);
    }



Analyzing the data structures during run-time presents three differences (to me):
  • The source image has a colorModel of type ComponentColorModel while the "blank" image created in the method has a colorModel of type DirectColorModel. I still don't know what the difference is or why they're different to begin with.
  • The source image has a Hashtable named "properties" while the created image does not (it's null). Again, I don't have a clue what this might mean.
  • The former has an imageType value of 6 while the latter has an imageType value of 2.


I'm now looking for a more in-depth tutorial on how BufferedImages are constructed to hopefully explain some of this. I'd be very grateful if anyone knows of a good one off-hand.

This post has been edited by Destro224: 24 October 2012 - 07:28 PM

Was This Post Helpful? 0
  • +
  • -

#5 Destro224  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 27
  • Joined: 20-June 12

Re: BufferedImageOp.filter() Throwing Channel Errors

Posted 24 October 2012 - 07:50 PM

I left in one small error in the code I posted a few minutes ago. I can't edit it now, so I'm forced to add yet another post to this thread...

View PostDestro224, on 24 October 2012 - 07:26 PM, said:

private BufferedImage getInvertedVersion(BufferedImage source) {
         short[] invert = new short[256];
         short[] straight = new short[256];
         for (int i = 0; i < 256; i++) {
            invert[i] = (short)(255 - i);
            straight[i] = (short)i;
         }
         
         short[][] blueInvert = new short[][] { straight, straight, invert, straight }; //I believe these affect (in order) Red, Green, Blue, Alpha
         BufferedImageOp blueInvertOp = new LookupOp(new ShortLookupTable(0, blueInvert), null);
         
         BufferedImage tempImage = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_ARGB); //This apparently creates a BufferedImage without whatever property is causing filter() to throw an error
         tempImage.setData(source.getData()); //Transferring only the data over into the new image lets filter() run just fine
         
         return blueInvertOp.filter(source, null);
    }



The very last line:
return blueInvertOp.filter(source, null);


should instead be:
return blueInvertOp.filter(tempImage, null);


Otherwise it throws the original error.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1