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

发布于 2024-08-26 01:13:48 字数 992 浏览 4 评论 0原文

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

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

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

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

我宁愿避免以下方法:

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

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 SampleModel 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.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淑女气质 2024-09-02 01:13:48

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

对于 MultiPixelPackedSampleModelSinglePixelPackedSampleModel 来说,这不是必需的,因为它们确实接受负的 scanlineStride。它们没有带偏移,但这可以通过在 DataBuffer 上设置偏移来解决。

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.

扮仙女 2024-09-02 01:13:48

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

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?

缺⑴份安定 2024-09-02 01:13:48

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文