【问题标题】:How to extract a pixel from a png file using c++?如何使用 C++ 从 png 文件中提取像素?
【发布时间】:2011-10-16 23:41:18
【问题描述】:

是否有可用的图像库允许用户从已加载到磁盘上的 png 文件中提取像素而无需解压缩?

所以我有 100k 8bit 大小为 512x512 的图像,其中每个 png 格式的图像约为 10kb。这意味着我只需要 1GB 的 RAM 就可以在运行时为我正在编写的程序存储所有图像。

是否可以有效地从这样的图像中检索像素? IE。假设我有一个数组 images,其中 images[i] 引用了一个已加载但未解压缩到 RAM 的 png 图像(加载 png 图像时会发生这种情况吗?)

那么理想情况下,我想写一些类似

的东西
pixel = images[i].getPixel(x,y);

有人知道这是否可能吗?哪个图书馆?我的假设在哪里是错误的?

【问题讨论】:

  • 从已加载到磁盘上的 png 文件中提取像素而不解压缩它怎么可能做到这一点?
  • 解压是指创建一个 512x512 字节的数组。我很确定可以从图像中提取单个像素值而不提取整个图像,但也许我弄错了。
  • 我很确定你不应该解压缩整个东西。 PNG 使用 zlib 压缩,因此最坏的情况是您需要解压缩前面的数据。

标签: c++ png extract pixel


【解决方案1】:

我认为如果不至少解压缩图像的前一部分,您将无法获得像素。当您打开一个文件时,它只会指向磁盘上的压缩数据。当你通过PNG库运行它时,它会被解压。

我认为,您最好的选择以及用于读写 PNG 的规范库是 libpng。它提供了对图像数据和元数据的极好的低级访问,并且可能是最快/最有效的选择。它允许您逐行解压缩数据(也许逐块解压缩——我不记得了),因此您可能可以解压缩直到获得像素,然后折腾解压缩的数据并移动到下一张图像。

缺点是它可能不像其他一些选项那样对程序员友好。 IMO 的文档非常全面,以至于有点乏味,但那里可能有更简单的教程。另一方面,你可能需要手册中的所有细节来完成你想要的最小减压。它还将有助于解释 PNG 文件格式,以便您可以更好地管理数据到块级别。

【讨论】:

  • 是否可以选择解压哪一行?这对我来说似乎是一个足够好的解决方案。
  • 我不这么认为。我认为您需要为某些行数调用png_read_row()
  • 至少,我认为 libpng 是这样构建的。如果您深入了解细节(可能会更改源),您也许可以阅读标题,跳过一些IDAT 块,然后解压缩一些较小的像素组,但我现在只是推测。跨度>
【解决方案2】:

我认为您的要求不切实际。幸运的是,这也是不必要的,只要你不将所有未压缩的图片同时保存在内存中

您不能按需简单地(加载和)解压缩,然后在不再需要时立即释放内存吗?

【讨论】:

  • 我完全同意它不实用。这是一个不平凡的问题,这就是为什么我有点卡住了。问题是我必须在一个循环中从所有图像中加载数百万次像素值(它是用于构建树的熵分裂计算),并且硬盘访问时间会使从磁盘加载完全不可行。
  • @twerdster 我不明白 - 除非这些 PNG 以某种方式动态生成,否则您必须以一种或另一种方式从磁盘加载它们。这只是时间问题。
【解决方案3】:

首先,我不确定我是否理解您关于不将图像解压缩到 RAM 中的要求......

虽然它可能比您正在寻找的库更多,但 Cinder 库将允许您轻松加载图像并使用 Surface 类迭代像素。

这是一个很好的教程:

http://libcinder.org/docs/v0.8.3/guide___images.html

【讨论】:

    【解决方案4】:

    我认为满足这些要求的最佳方法是将所有 PNG 压缩在内存中(如您所示,大约为 1GB),并且在您想从中获取像素时一次只解压缩一个。解压后的 512x512 8 位灰度图像的缓冲区大小为 256KB。如果图像是 RGB,则大小为 768KB。如果您还有 Alpha 通道,则大小为 1MB。

    你可以找到一个非常轻量级和简单的解压缩PNG的库here

    如果您想隐藏图像在内存中被压缩的事实,您可以将压缩的 PNG 数据放在图像类中。如果图像被压缩,该类中的getPixel(x, y) 方法将触发解压缩。此类中的类成员可以跟踪已解压的图像,当需要解压另一张图像时,前一张图像可以丢弃其解压缓冲区。

    这样的解决方案可能会遇到的唯一问题是,如果您遍历 100K 图像只要求一个像素,则系统可以thrash,然后移动到下一个像素。为避免这种情况,您需要从一张图片中获取所需的所有信息,然后转到下一张图片。

    【讨论】:

    • 那么使用 pngs 没有先提取整个图像就无法提取像素值?
    • 图像被压缩,因此像素值不容易访问,因为它们以有效的方式编码。获得单个像素值的唯一方法是解压缩。您可能会解压缩图像的某些部分(直到达到像素为止的最低限度),但为此您需要一个自定义解码器。我提出的解决方案可以让你做你想做的事,但你必须一次解压一张图片。
    猜你喜欢
    • 2011-09-20
    • 1970-01-01
    • 2015-04-20
    • 2016-05-18
    • 1970-01-01
    • 1970-01-01
    • 2018-01-12
    • 2016-06-18
    • 2010-10-17
    相关资源
    最近更新 更多