在Java中以自下而上的顺序存储图像像素的最佳方法

时间:2010-03-17 10:04:53

标签: java bufferedimage java-2d raster

我有一个以Windows BMP格式表示图像的字节数组,我希望我的库以BufferedImage的形式将它呈现给Java应用程序而不用复制像素数据。

主要问题是JDK中Raster的所有实现都以自上而下,从左到右的顺序对像素进行成像,而BMP像素数据则自下而上,从左到右存储。如果未对此进行补偿,则生成的图像将垂直翻转。

最明显的“解决方案”是将SampleModel的{​​{1}}属性设置为负值,并将波段偏移量(或scanlineStride的数组偏移量)更改为点到左上角的像素,即阵列中最后一行的第一个像素。不幸的是,这不起作用,因为如果给出负DataBuffer参数,所有SampleModel构造函数都会抛出异常。

我目前正在通过使用反射强制scanlineStride字段为负值来解决它,但如果可能的话,我希望以更干净,更便携的方式进行。 例如是否有另一种方法来欺骗scanlineStrideRaster以自下而上的顺序排列像素但不破坏封装?或者是否有一个库将包裹SampleModelRaster,以相反的顺序呈现像素行?

我宁愿避免以下方法:

  • 复制整个图像(出于性能原因。代码必须每秒处理数百个大型(> = 1M像素)图像,尽管整个图像必须可供应用程序使用,但它通常只能访问一小部分(但很难) - 预测)图像的一部分。)
  • 修改SampleModel以执行坐标转换(这实际上有效但是另一个“脏”解决方案,因为缓冲区不需要知道扫描线/像素布局。)
  • 从头开始重新实现DataBuffer和/或Raster接口(因为实现了兼容性检查的方式(至少在Sun JDK中),需要SampleModel的特定子类所以通用SampleModel包装类不起作用。)

3 个答案:

答案 0 :(得分:1)

我发现我只能使用一个新类来实现它,我将其命名为BottomUpComponentSampleModel。它扩展ComponentSampleModel并在调用超类构造函数后否定scanlineStride字段的值(幸运的是,protected而不是private)。所有的像素地址计算都可以正常工作,尽管Raster.createWritableRaster中的验证没有(它可能无法检测到你是否给它一个太小的数组),但这不是一个严重的问题。

MultiPixelPackedSampleModelSinglePixelPackedSampleModel不需要这样做,因为它们接受否定scanlineStride。它们没有波段偏移,但可以通过在DataBuffer上设置偏移来解决这个问题。

答案 1 :(得分:0)

当访问图像的微小(但难以预测)部分时,让应用程序(或访问层)在其副本上进行翻译和翻转工作会怎样?

答案 2 :(得分:0)

更好,听起来应用程序不需要实际显示图像? 为什么要首先将它翻转以便在屏幕上显示正确?只需编写逻辑来处理您拥有的版本? 不需要那样的BufferedImage,直接在数组上工作。