我有一个字节数组,表示 Windows BMP 格式的图像,我希望我的库将其作为 Java 应用程序呈现 BufferedImage, 没有 复制像素数据。

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

最明显的“解决方案”是设置 SampleModelscanlineStride 属性设置为负值并更改带偏移(或 DataBuffer的数组偏移量)指向左上角像素,即数组中最后一行的第一个像素。不幸的是这不起作用,因为所有的 SampleModel 如果给定负数,构造函数会抛出异常 scanlineStride 争论。

我目前正在通过强制解决这个问题 scanlineStride 使用反射将字段设置为负值,但如果可能的话,我想以更干净、更便携的方式来实现。例如还有其他方法可以愚弄 Raster 或者 SampleModel 按自下而上的顺序排列像素但不破坏封装?或者是否有一个图书馆可以包装 RasterSampleModel, ,以相反的顺序呈现像素行?

我宁愿避免以下方法:

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

解决方案

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

这不是必需的 MultiPixelPackedSampleModel 或者 SinglePixelPackedSampleModel, ,因为他们确实接受负面的 scanlineStride. 。它们没有频带偏移,但这可以通过在频带上设置偏移来解决 DataBuffer.

其他提示

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

更好的是,听起来应用程序不需要实际显示图像?为什么要费心去翻转它,以便它在屏幕上看起来是正确的呢?只需编写逻辑即可在您拥有的版本上工作?也不需要这样的 BufferedImage,直接在数组上工作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top