JDK-4937376 : class cast exception in fetching images
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic,windows_2000
  • CPU: generic,x86
  • Submitted: 2003-10-14
  • Updated: 2014-11-19
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
Other
5.0-poolUnresolved
Description

Name: dk106046			Date: 10/14/2003

The problem is best described on this forum entry:
http://forum.java.sun.com/thread.jsp?forum=4&thread=289012

The customer is loading an 8 bit image, the ImageFetcher starts , and is working on the image,  it goes into PixelStore, and then PixelStore8, where it calls replayLines
The lines are replayed, and we find that the AreaAveragingScaleFilter is working with an ImageRepresentation containing an Indexed color model, and a byte array, so it
all works fine.
We can see in accumPixels that the test is made to see if the array is bytes or ints, and the right RGB values are found. At the bottom of the loop, where dyrem becomes 
zero, computeRow is called to get an INT array, and the corresponding setPixels for an int array is called, passing the default RGB colormodel, and the int array.
At this point, in setPixels, the internal color model is still Indexed, so a convert to RGB is required.  The internal byte array biRaster is replaced by an int array, and
each item is computed using getRGB with the indexedColorModel, so again we are all fine.
Now what happens next is not fine. We have now converted to DirectColorModel, and the array is ints, but the next time through accumPixels, the model is set back to
an IndexedColorModel, but the int array remains.
setPixels of int is called, and it recognises the IndexedColorModel, so calls converttoRGB, which tries to use the color model with each element of the biRaster, but thats
an int array, so it throws a ClassCastException: 

java.lang.ClassCastException: java.lang.Object
	at java.awt.image.ColorModel.getAlpha(ColorModel.java:856)
	at java.awt.image.ColorModel.getRGB(ColorModel.java:901)
	at sun.awt.image.ImageRepresentation.convertToRGB(ImageRepresentation.java:312)
	at sun.awt.image.ImageRepresentation.setPixels(ImageRepresentation.java:527)
	at java.awt.image.AreaAveragingScaleFilter.accumPixels(AreaAveragingScaleFilter.java:229)
	at java.awt.image.AreaAveragingScaleFilter.setPixels(AreaAveragingScaleFilter.java:268)
	at sun.awt.image.PixelStore8.replayLines(PixelStore8.java:69)
	at sun.awt.image.PixelStore.replay(PixelStore.java:248)
	at sun.awt.image.PixelStore.replay(PixelStore.java:177)
	at sun.awt.image.InputStreamImageSource.updateFromStore(InputStreamImageSource.java:334)
	at sun.awt.image.InputStreamImageSource.doFetch(InputStreamImageSource.java:283)
	at sun.awt.image.ImageFetcher.fetchloop(ImageFetcher.java:205)
	at sun.awt.image.ImageFetcher.run(ImageFetcher.java:173)
======================================================================

Comments
Unclear is it affecting 9 or not
2014-11-19

Please re-open if - if fix is in progress or on the plan to fix soon - if this is a P3 (file as P3, not P4)
2014-03-18

WORK AROUND Name: dk106046 Date: 10/14/2003 The forum suggests this will fix it in the customer code: imagei = imagei.getScaledInstance( scaledWidth , scaledHeight, Image.SCALE_SMOOTH ); Changed to: imagei = imagei.getScaledInstance( scaledWidth , scaledHeight, Image.SCALE_REPLICATE ); ======================================================================
2004-06-20

SUGGESTED FIX From Customer: I can see that in ConvertToRGB, one could alter the code such that it checks for an IndexedColorModel and an Int array, and instead of cmodel, it uses getRGBDefault , something like this: else { Object srcpixels = null; ColorModel cm; if ( cmodel instanceof IndexColorModel && !(biRaster instanceof ByteComponentRaster)) { cm = ColorModel.getRGBdefault(); } else { cm = cmodel; } int off=0; for (int y=0; y < h; y++) { for (int x=0; x < w; x++) { srcpixels=biRaster.getDataElements(x, y, srcpixels); newpixels[off++] = cm.getRGB(srcpixels); } } } But I have two doubts. Firstly, is it more just a case of telling the system that the raster has changed, by using bct.notifyChanged();, as in the byte[] version of setPixels?. Secondly, is this just hiding the original problem that the color model should not have got set back to Indexed without the biRaster getting set back to bytes? I am sorry I have not been able to derive a small test case for this, we are working on it, but the customers application is big, and the images are computed, not stored.
2004-06-20

EVALUATION java.awt.image.* belongs to 2D. ###@###.### 2003-10-14 First, this bug is likely not to be reproducible in 1.5, since PixelStore classes and replay functionality has been removed from the source. It'd be great to get a testcase to check this. Or have IBM folks try their app on 1.5 (they should have access to beta builds). I've actually run into this exception before we took out the code, and I haven't seen it since. Here's my email exchange on this subject: -------------------------------------------------------------------- > As I understand, it's possible to have a producer call > IR.setColorModel several times with different color models. > > I'm wondering what should happen if in IR we have a raster already > (biRaster) created (by IR.createImage), and then a new color model > is set. > > Currently IR.setColorModel basically just sets a new cmodel, loosing > the information about the color model current biRaster was > associated with, so we may end up in a state with, for example, > IntegerInterleavedRaster and IndexColorModel. > > This causes ClassCastExceptions when we later attempt to > covertToRGB() because of the mismatch of cmodel and biRaster. > > Is this a bug in current implementation or am I missing something? > > Just some background: > I've run into this ClassCastException while getting rid of > PixelStore. My idea was to use OffScreenImageSource from the > BufferedImage we have in IR to replay the pixels if requested. > So IR would have a method: > public boolean replay(ImageConsumer ic) { > // replay only if the image is read completely > // this also protects against animated images > boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); > if (done && bimage != null) { > ImageProducer bip = bimage.getSource(); > bip.startProduction(ic); > bip.removeConsumer(ic); > return true; > } > return false; > } > which will be called by InputStreamImageSource.doFetch to attempt > the replay the pixels instead of re-reading it. > > Unfortunately, this somehow (I'm not yet sure how) triggered the > above mentioned exception with the following stacktrace in ImageMap > demo applet. > Uncaught error fetching image: > java.lang.ClassCastException: [I > at java.awt.image.ColorModel.getAlpha(ColorModel.java:814) > at java.awt.image.ColorModel.getRGB(ColorModel.java:859) > at sun.awt.image.ImageRepresentation.convertToRGB(ImageRepresentation.java:295) > at sun.awt.image.ImageRepresentation.setPixels(ImageRepresentation.java:532) > at java.awt.image.RGBImageFilter.filterRGBPixels(RGBImageFilter.java:183) > at java.awt.image.RGBImageFilter.setPixels(RGBImageFilter.java:217) > at ButtonFilter.setPixels(ButtonFilter.java:198) > at java.awt.image.CropImageFilter.setPixels(CropImageFilter.java:119) > at sun.awt.image.OffScreenImageSource.sendPixels(OffScreenImageSource.java:73) > at sun.awt.image.OffScreenImageSource.produce(OffScreenImageSource.java:162) > at sun.awt.image.OffScreenImageSource.addConsumer(OffScreenImageSource.java:37) > at sun.awt.image.OffScreenImageSource.startProduction(OffScreenImageSource.java:51) > at sun.awt.image.ImageRepresentation.replay(ImageRepresentation.java:897) > at sun.awt.image.InputStreamImageSource.updateFromStore(InputStreamImageSource.java:293) > at sun.awt.image.InputStreamImageSource.doFetch(InputStreamImageSource.java:237) > at sun.awt.image.ImageFetcher.fetchloop(ImageFetcher.java:172) > at sun.awt.image.ImageFetcher.run(ImageFetcher.java:136) > > It works fine if I disable the replay functionality completely, at > some performance expense, I guess. ----- Reply to this email: > As I understand, it's possible to have a producer call > IR.setColorModel several times with different color models. And it can completely ignore that value and use a completely different model in setPixels. Basically that call is a "get ready for this" kind of call, not any kind of promise. All the method says is "the model to be used for the majority of pixels delivered", but that is rather vague. You might want to just ignore it - that would be acceptable. > I'm wondering what should happen if in IR we have a raster already > (biRaster) created (by IR.createImage), and then a new color model > is set. Wait for it to get used to do anything with it. In that case, it will appear in setPixels, not setCM(). > Currently IR.setColorModel basically just sets a new cmodel, loosing > the information about the color model current biRaster was > associated with, so we may end up in a state with, for example, > IntegerInterleavedRaster and IndexColorModel. My eventual goal here was that we would have an SD for our constructed image and we would make an SD for the incoming pixels array and CM in setPixels and then just do a Blit. Any caching of the CM would not really be helpful, except that we might want to keep a soft reference to the SD used for the incoming data and if the same array and CM get used again, then we could use the previously created SD. > This causes ClassCastExceptions when we later attempt to > covertToRGB() because of the mismatch of cmodel and biRaster. > > Is this a bug in current implementation or am I missing something? I don't know which this might be without looking through the code, but hopefully my clarifications above give you the background to decide on a better way to handle all of this. > Just some background: > I've run into this ClassCastException while getting rid of > PixelStore. My idea was to use OffScreenImageSource from the > BufferedImage we have in IR to replay the pixels if requested. > So IR would have a method: > public boolean replay(ImageConsumer ic) { > // replay only if the image is read completely > // this also protects against animated images > boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); > if (done && bimage != null) { > ImageProducer bip = bimage.getSource(); > bip.startProduction(ic); > bip.removeConsumer(ic); > return true; > } > return false; > } > which will be called by InputStreamImageSource.doFetch to attempt > the replay the pixels instead of re-reading it. One problem is that the BufferedImage doesn't have much of a concept of "which pixels have been delivered (yet)", so it may replay bogus data. Eventually I wanted to get rid of replaying and simply have new consumers go with a new feeder. We are slowly deprecating the Producer/Consumer relationship anyway. For new consumers, the ISIS objects would share a cache of the bits from the image rather than sharing the decoded pixels. This is a much bigger overhaul than I think you are planning for now, but there is an idea for what could be done in the future... > It works fine if I disable the replay functionality completely, at > some performance expense, I guess. I'm guessing the exception is due to different accounting of what the "proper ColorModel is" between the IR and its BufImg and the old PixelStore. I imagine you will have to update the accounting of the IR/BufImg to match what used to be done in the PixelStore wrt the ColorModel used. See above for some suggestions for starting on a new tack... ----------------------------------------------------------------------------- Second, the code in ImageRepresentation is extremely tricky, and we'd rather not touch that code. ###@###.### 2003-10-16
2003-10-16