开发者

Best approach to storing image pixels in bottom-up order in Java

I have an array of bytes representing an image in Windows BMP format and I would like my library to present it to the Java application as a BufferedImage, without copying the pixel data.

The main problem is that all implementations of Raster in the JDK store image pixels in top-down, left-to-right order whereas BMP pixel data is stored bottom-up, left-to-right. If this is not compensated for, the resulting image will be flipped vertically.

The most obvious "solution" is to set the SampleModel's scanlineStride property to a negative value and change the band offsets (or the DataBuffer's array offset) to point to the top-left pixel, i.e. the first pixel of the last line in the array. Unfortunately this does not work because all of the SampleModel constructors throw an exception if given a negative scanlineStride argument.

I am currently working around it by forcing the scanlineStride field to a negative value using reflection, but I would like to do it in a cleaner and more portable way if possible. e.g. is there another way to fool the Raster or SampleModel into arranging the pixels in bottom-up order but without breaking encapsulation? Or is there a library somewhere that will wrap the Raster and SampleModel, presenting the pixel rows in reverse order?

I would prefer to avoid the following approaches:

  • Copying the whole image (for performance reasons. The code must process hundreds of large (>= 1Mpixels) images per second and although the whole image must be available to the application, it will normally access only a tiny (but hard-to-predict) portion of the image.)
  • Modifying the DataBuffer to perform coordinate transformation (this actually works but is another "dirty" solution because the buffer should not need to know about the scanline/pixel layout.)
  • Re-implementing the Raster and/or SampleM开发者_运维技巧odel interfaces from scratch (because of the way compatibility checking is implemented (at least in the Sun JDK), requiring specific subclasses of SampleModel so a generic BottomUpSampleModel wrapper class would not work.)


I found I can implement this using only one new class, which I named BottomUpComponentSampleModel. It extends ComponentSampleModel and negates the value of the scanlineStride field (which, luckily, is protected rather than private) after calling the superclass constructor. All of the pixel address calculations work fine, although the validation in Raster.createWritableRaster does not (it can fail to detect if you give it an array that is too small), but that is not a serious problem.

This is not necessary with MultiPixelPackedSampleModel or SinglePixelPackedSampleModel, as they do accept a negative scanlineStride. They do not have band offsets, but this can be worked around by setting an offset on the DataBuffer.


what about having the application (or access layer) do the translation and fliping work on it's copy when accessing the tiny (but hard-to-predict) portion of the image?


even better, it sounds like the application doesn't need to actually display the image? Why bother with wanting to flip it in the first place so it would look correct on screen? Just write the logic to work on the version you have? No need to have a BufferedImage that way either, work directly on the array.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜