在java中将PNG图像快速加载到数组中

发布于 2024-09-27 01:46:15 字数 255 浏览 3 评论 0原文

我想加载(和解码)PNG 图像并将它们转换为 Java 中的一维数组。显然,我可以使用 ImageIO.read() 执行此操作,然后将像素复制到数组中,但这会消耗两倍的内存(光栅+最终数组),并且涉及的处理时间比我想要的要多。

我该怎么办?最坏的情况是我可以自己实现 PNG 规范,但这似乎是一项相当复杂的任务。理想情况下,我想要一个可以“插入”的 PNG 实现。不太理想但仍然很好的是一个易于理解(与 com.sun 代码不同)的 PNG 阅读器,我可以(并且被允许)修改它。

I want to load (and decode) PNG images and convert them into a one-dimensional array in Java. I can obviously do this with ImageIO.read() and then copy the pixels into the array, but that consumes twice the memory (the raster + the final array) and it involves more processing time than I would like.

How should I go about this? Worst-case I can implement the PNG spec myself, but that seems like a rather involved task. Ideally I'd like a PNG implementation that I can "plug" into. Less ideal but still fine would be an easy to understand (unlike the com.sun code) PNG reader that I can (and would be allowed to) modify.

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

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

发布评论

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

评论(3

夜声 2024-10-04 01:46:15

如果您想要做的是以数组形式获取像素数据,那么您可以使用 ImageIO.read() 来获取 BufferedImage,然后使用 BufferedImage.getRaster().getDataBuffer() 获取DataBuffer。从那里,您需要检查您拥有的 BufferedImage 类型,以确定如何转换 DataBuffer。例如,如果您有一个 TYPE_INT_RGB 图像,那么您应该转换为 DataBufferInt,然后您可以调用 DataBufferInt.getData() 来检索 < code>int[] 其中包含数据。通过这种方式获得的不是副本,而是支持 BufferedImage 的实际数组。

但是,所有这些有一个很大的警告:ImageIO.read() 通常不会为您提供您想要的图像类型。例如,您经常会得到 TYPE_CUSTOM,除了复制到您实际想要的图像类型之外,您不能用它做任何有用的事情。

所以,如果您足够幸运的话,您只能通过 ImageIO.read() 获取图像数据,而无需制作第二个副本。 read() 为您提供所需格式的图像。如果您想检查 ImageIO 可用的类型,您可以调用 ImageIO.getImageReaders() 来获取所有读取器的 Iterator它声称能够读取您的流,然后您可以使用 ImageReader.getImageTypes(0) 来获取读取器可以读取的图像类型的 Iterator 。您可能会找到一个能够以这种方式为您提供所需图像类型的阅读器,但不要屏住呼吸。

除非您的图像很大,否则复制它们实际上非常快。不过,如果您的图像很大,那么您可能不得不使用 BufferedImage.getRGB() 将原始图像数据一次一行写入磁盘(但是对其进行压缩,使用 GZIPOutputStream ),让原始图像被垃圾收集,创建所需类型的新 BufferedImage ,最后从磁盘读回行,写入使用 BufferedImage.setRGB() 将它们添加到新图像。 (几天前我写了一些东西来做到这一点,因此细节在我的脑海中相当新鲜。它的 LGPL 源是 ​​此处。)

If what you're trying to do is get the pixel data as an array, then you can use ImageIO.read() to get a BufferedImage and then use BufferedImage.getRaster().getDataBuffer() to get the DataBuffer. From there, you need to check what type of BufferedImage you have in order to determine how to cast the DataBuffer. E.g. if you have a TYPE_INT_RGB image, then you should cast to a DataBufferInt and then you can call DataBufferInt.getData() to retrieve the int[] which contains the data. What you get this way is not a copy---it's the actual array backing the BufferedImage.

However, there is a big caveat to all of this: ImageIO.read() will often NOT give you the type of image you want. E.g., you'll frequently get TYPE_CUSTOM, which you can't do anything useful with except copy to the image type you actually want.

So, you'll only be able to get your image data via ImageIO.read() without making a second copy if you're fortunate enough that ImageIO.read() gives you the image in the format you want. If you want to check what types are available from ImageIO, you can call ImageIO.getImageReaders() to get an Iterator over all of the readers which claim to be able to read your stream, and then you can use ImageReader.getImageTypes(0) to get an Iterator over image types which the reader can read. You might find a reader which will give you the image type you want this way, but don't hold your breath.

Unless your images are huge, copying them is actually pretty fast. If your images are huge, though, you might have to resort to using BufferedImage.getRGB() to write the raw image data out to disk one row at a time (but do it compressed, use a GZIPOutputStream), let the original image be garbage collected, create a new BufferedImage of the desired type, and finally read the rows back from disk, writing them to the new image using BufferedImage.setRGB(). (I wrote something to do this just a few days ago, hence the details are rather fresh in my mind. The LGPL'd source for it is here.)

不喜欢何必死缠烂打 2024-10-04 01:46:15

为什么需要一维数组?更大的目的是什么?

任何建议都取决于此。

您通常可以将 PNG 解码为内存可访问的位图,(ImageIO.read() 返回一个 BufferedImage,正是如此),然后直接访问其像素。 . 作为一维数组(使用 BufferedImage.getRaster().getDataBuffer())。

Why do you want a 1D array? What is the bigger purpose?

On that hinges any recommendations.

You can usually decode a PNG to a memory-accessible bitmap, (ImageIO.read() returns a BufferedImage, which is precisely that) and just access its pixels directly ... as a 1D array (using BufferedImage.getRaster().getDataBuffer()).

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