代码之家  ›  专栏  ›  技术社区  ›  Zac

内存中像素数据的布局?

  •  1
  • Zac  · 技术社区  · 15 年前

    我正在为基于PNG的图像格式编写C++库。对于我来说,一个停止点是我不确定应该如何在内存中布局像素数据;据我所知,有两种实用的方法:

    1. 一个大小(宽度*高度)的数组;每个像素都可以通过数组[Y*宽度+X]访问。
    2. 大小(高度)数组,包含指向大小(宽度)数组的指针。

    PNG(libpng)的标准引用实现使用上面的方法2,而我见过其他人使用方法1。一种方法比另一种方法更好,或者每一种方法都有各自的优缺点,这是必须妥协的地方吗?此外,大多数图形显示系统使用哪种格式(可能是为了方便将我的库的输出用于其他API)?

    4 回复  |  直到 15 年前
        1
  •  6
  •   Georg Schölly Crazy Developer    15 年前

    在我的头顶上:

    • 有一件事会让我选择2,那就是你的记忆需求有点放松。如果您要使用1,系统将需要能够分配 height * width 数量 邻接的 记忆。然而,在2的情况下,它可以自由地分配较小的连续内存块。 width (也可以是 height )离开空闲区域。(如果将每个像素的通道数考虑在内,即使是中等大小的图像,1也可能失败。)
    • 此外,如果出于图像操作的目的(指针交换足够),交换行(或列)时可能会稍微好一点。
    • 当然,2的缺点是一个额外的间接级别,渗透到每个访问和要维护的指针数组中。但考虑到当今的处理器速度和内存,这几乎不是问题。
    • _2的第二个缺点是数据不一定彼此相邻,这使得处理器更难将正确的内存页加载到缓存中。
        2
  •  2
  •   amarillion    15 年前

    方法2(将数组分割成行)的优点在于,您可以分步骤执行内存操作,例如,调整图像的大小或对图像进行重组,而不必一次重新分配整个内存块。对于非常大的图像,这可能是一个优势。

    单个数组的优点是计算更简单,也就是说,向下一行就可以了

    pos += width;
    

    而不是必须引用指针。对于中小型图像,这可能更快。除非您处理的是数百MB的图像,否则我将使用方法1。

        3
  •  1
  •   jesup    15 年前

    我怀疑libpng这样做(样式2)有几个可能的原因:

    1. 避免大的分配(如前所述),并且可以方便地处理非常大的PNG,特别是在没有VM的系统中。
    2. (可能)允许交错解码ala交错jpeg(如果png支持)
    3. 易于进行某些转换(垂直翻转)(不太可能)
    4. 易于缩放(插入或删除行而不需要第二个完整的缓冲区,或加宽/缩小行)(不太可能,但可能)

    这种方法的问题(假设每行都是一个分配)是更多的分配/空闲开销,并且可能会鼓励内存碎片化。

    除非您有充分的理由,否则请使用样式1(单次分配),并可能四舍五入到您所使用的体系结构的“良好”边界(可能是4、8、16甚至更多字节)。请注意,许多库函数可能会寻找没有填充的样式1—考虑一下您将如何使用它以及将它们传递到哪里。

        4
  •  0
  •   Mark Ransom    15 年前

    Windows本身使用方法1的变体。图像的每一行被填充为4字节的倍数,颜色的顺序是b、g、r,而不是更正常的r、g、b。缓冲区的第一行也是图像的底行。