- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我目前正尝试在基于 libpng 的 C++ 中实现一个 PNG 编码器,它使用 OpenMP 来加速压缩过程。该工具已经能够从各种图像格式生成 PNG 文件。我将完整的源代码上传到 pastebin.com,这样你就可以看到我到目前为止做了什么:http://pastebin.com/8wiFzcgV
到目前为止,还不错!现在,我的问题是找到一种方法来并行生成包含压缩图像数据的 IDAT block 。通常,libpng 函数 png_write_row 在 for 循环中被调用,它带有指向包含有关 PNG 文件的所有信息的结构的指针和带有单个图像行的像素数据的行指针。
(Pastebin 文件中的第 114-117 行)
//Loop through image
for (i = 0, rp = info_ptr->row_pointers; i < png_ptr->height; i++, rp++) {
png_write_row(png_ptr, *rp);
}
然后,Libpng 逐行压缩,并用压缩后的数据填充内部缓冲区。一旦缓冲区已满,压缩数据就会以 IDAT block 的形式刷新到图像文件中。
我的方法是将图像分成多个部分,让一个线程将第 1 行压缩到第 10 行,另一个线程将第 11 行压缩到第 20 行,依此类推。但是由于 libpng 使用内部缓冲区,它并不像我最初想的那么容易 :) 我不得不以某种方式让 libpng 将压缩数据写入每个线程的单独缓冲区。之后我需要一种方法以正确的顺序连接缓冲区,以便我可以将它们一起写入输出图像文件。
那么,有人知道我如何使用 OpenMP 和对 libpng 进行一些调整吗?非常感谢!
最佳答案
这对于评论来说太长了,但也不是真正的答案--
我不确定您是否可以在不修改 libpng(或编写自己的编码器)的情况下执行此操作。无论如何,如果您了解 PNG 压缩的实现方式,将会有所帮助:
在高层次上,图像是一组像素行(通常是表示 RGBA 元组的 32 位值)。
每一行可以独立有一个filter应用于它——过滤器的唯一目的是使行更“可压缩”。例如,“子”过滤器使每个像素的值与其左侧的值之差。这种增量编码乍一看似乎很愚蠢,但如果相邻像素之间的颜色相似(往往是这种情况),那么无论它们代表的实际颜色如何,结果值都非常小。压缩此类数据更容易,因为它具有更高的重复性。
往下一层,图像数据可以看成字节流(不再区分行)。这些字节被压缩,产生另一个字节流。压缩数据被任意分解成段(任何你想要的!),每个段写入一个 IDAT block (每个 block 还有一些簿记开销,包括 CRC 校验和)。
最底层将我们带到了有趣的部分,即压缩步骤本身。 PNG 格式使用 zlib压缩数据格式。 zlib 本身只是一个真正的压缩数据格式的包装器(有更多的簿记,包括 Adler-32 校验和),deflate (zip 文件也使用它)。 deflate 支持两种压缩技术:Huffman 编码(考虑到每个不同字节在字符串中出现的频率,它将表示某些字节串所需的位数减少到最佳数量)和 LZ77 编码(它允许重复的字符串已经发生被引用而不是写入输出两次)。
关于并行 deflate 压缩的棘手部分是,通常,压缩输入流的一部分要求前一部分也可用,以防需要引用它。 但是,就像 PNG 可以有多个 IDAT block 一样,deflate 被分解成多个“ block ”。一个 block 中的数据可以引用另一个 block 中先前编码的数据,但它必须(当然,如果不这样做,它可能会影响压缩率)。
因此,并行化 deflate 的一般策略是将输入分成多个 大 部分(以便压缩率保持高),将每个部分压缩成一系列 block ,然后粘合 block 放在一起(这实际上很棘手,因为 block 并不总是以字节边界结束——但您可以放置一个空的非压缩 block (类型 00),它将与字节边界对齐,在部分之间)。然而,这并非微不足道,并且需要控制最低级别的压缩(手动创建压缩 block ),创建跨越所有 block 的适当 zlib 包装器,并将所有这些填充到 IDAT block 中。
如果您想使用自己的实现,我建议您阅读 my own zlib/deflate implementation (和 how I use it ),这是我专门为压缩 PNG 而创建的(它是用 Haxe for Flash 编写的,但应该相对容易移植到 C++)。由于 Flash 是单线程的,我没有进行任何并行化,但我确实将编码拆分为多个帧上几乎独立的部分(“虚拟”是因为部分之间保留了小数字节状态),这在很大程度上相当于同样的事情。
祝你好运!
关于c++ - 使用 C++、libpng 和 OpenMP 并行创建 PNG 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10827247/
OpenMP 中的高斯消除。我是 openmp 的新手,想知道我是否在正确的地方使用了我的编译指示和屏障。我的 x 值每次都不同。他们应该是一样的吗?? #include int num; doub
给定一个示例函数(示例在下面给出),for 循环可以使用 OpenMP 并行化或使用矢量化进行矢量化(假设编译器执行矢量化)。 示例 void function(float* a, float* b,
OpenMP 中原子和关键之间有什么区别? 我能做到 #pragma omp atomic g_qCount++; 但这和不一样吗 #pragma omp critical g_qCount++; ?
我有一个关于如何在您考虑特定依赖关系图时生成 OpenMP 伪代码的问题。 所以假设我们有这个特定的图表: 解决方案可能是这样的: #pragma omp parallel {
我正在尝试使用 openmp 计算二维矩阵的平均值。这个二维矩阵实际上是一个图像。 我正在对数据进行线程分割。例如,如果我有 N线程比我处理行/N thread0 的行数, 等等。 我的问题是:我可以
我想统计测量与 OpenMP 并行化的程序的性能。我选择在执行并行算法的测试应用程序中编写循环 MAX_EXPERIMENTS次并将时间测量报告到文件中。 问题解决方案似乎比提取外部循环上方的并行编译
我找到了 Intel's performance suggestion on Xeon Phi关于 OpenMP 中的 Collapse 子句。 #pragma omp parallel for co
如何使用 OpenMP 并行化数组移位? 我尝试了一些方法,但在以下示例中没有得到任何准确的结果(该示例旋转 Carteira 对象数组的元素,用于排列算法): void rotaciona(int
我有一系列对几个独立函数的调用。 func1(arg); func2(arg); func3(arg); 我想并行执行它们,而不是串行执行它们。我目前正在使用 #pragma omp parallel
我正在尝试使用 openmp 任务来安排基本 jacobi2d 计算的平铺执行。在 jacobi2d 中,依赖于 A(i,j) 从 A(i, j) A(i-1, j) A(i+1, j) A(i, j
我在 3 天前开始使用 OpenMP。我想知道如何使用#pragma使每个内核运行一个线程。详细信息:- int ncores = omp_get_num_procs();for(i = 0; i <
我有一段代码(它是应用程序的一部分),我正在尝试使用 OpenMP 对其进行优化,正在尝试各种调度策略。就我而言,我注意到 schedule(RUNTIME)条款比其他条款有优势(我没有指定 chun
我有一个数字运算 C/C++ 应用程序。它基本上是不同数据集的主循环。我们可以使用 openmp 和 mpi 访问一个 100 节点的集群。我想加速应用程序,但我是 mpi 和 openmp 的绝对新
在 OpenMP 中使用ompsections时,线程会被分配到sections内的 block ,还是每个线程会被分配到每个section? 当nthreads == 3时: #pragma omp
我正在尝试在 cython 中使用 openmp。我需要在 cython 中做两件事: i) 在我的 cython 代码中使用 #pragma omp single{} 作用域。 ii) 使用#pra
我正在尝试通过将循环的每次迭代作为 OpenMP 部分来并行化 OpenMP 中基于范围的 for 循环。我想这样做: #pragma omp parallel sections { for ( au
我正在尝试在 cython 中使用 openmp。我需要在 cython 中做两件事: i) 在我的 cython 代码中使用 #pragma omp single{} 作用域。 ii) 使用#pra
我想编写一个代码转换器,它采用基于 OpenMP 的并行程序并在集群上运行它。 我该如何解决这个问题?我使用哪些库?如何为此设置小型集群? 我发现很难在 Internet 上找到有关集群计算的好 Ma
我是 OpenMP 的新手。我正在尝试为 for 循环使用多个内核,但出现此编译错误: “错误 C3016:'x':OpenMP 'for' 语句中的索引变量必须具有带符号的整数类型”。 我知道 Op
如果我使用 VS 2010 编译器从 Qt Creator 构建项目,我如何启用 OpenMP(从 Visual Studio 构建时,您只需启用该功能)谢谢 最佳答案 在 .pro 文件中尝试下一步
我是一名优秀的程序员,十分优秀!