【发布时间】:2014-10-18 14:19:33
【问题描述】:
我有一个关于 C 中字符串生成的小问题。 以下代码 sn-p 是用于生成图像(mandelbrot、渐变等)的 Python/Tkinter 应用程序的 C 扩展的一部分。在有人问之前:我不想为这么简单的任务打开 Photoshop 的电源 - 矫枉过正......
我遇到的问题是在最后一个 for 循环中的 sn-p 末尾。 此函数生成一个 PPM 图像文件以供进一步处理。主要目标是生成一个包含二进制格式栅格数据的字符串,并将该字符串传回 Python,然后传回 Tkinter 图像数据以预览结果。
目前我将文件写入磁盘非常慢。 迭代器函数返回一个指向 RGB 数组的指针。 如果我现在使用
将每个颜色值写入文件fputc(col[0], outfile)
它有效(被淘汰的部分)。 为了更接近我的主要目标,我尝试将三个颜色值合并为一个字符串并将其写入文件中。 当我从我的 Python 应用程序运行该代码时,我最终得到一个仅包含标题的文件。
谁能指出我正确的方向?整个 C 类东西对我来说都很新 - 所以我几乎被困在这里......
static PyObject* py_mandelbrotppm(PyObject* self, PyObject* args)
{
//get filename from argument
char *filename;
PyArg_ParseTuple(args, "s", &filename);
//---------- open file for writing and create header
FILE *outfile = NULL;
outfile = fopen(filename, "w");
//---------- create ppm header
char header[17];
sprintf(header,"P6\n%d %d\n255\n", dim_x, dim_y);
fputs(header, outfile);
//---------- end of header generation
for(int y = 0;y<dim_y;y++)
{
for(int x = 0;x<dim_x;x++)
{
int *col = iterator(x,y);
char pixel[3] = {col[0], col[1], col[2]};
fputs(pixel, outfile);
/*
for(int i = 0;i<3;i++)
{
fputc(pixel[i], outfile);
}
*/
}
}
fclose(outfile);
Py_RETURN_NONE;
}
【问题讨论】:
-
我会先写一个纯 Python 版本:你可以使用 numpy 数组来操作数据(或 array.array,或手动生成二进制缓冲区),然后将它们转换为图像(枕头:@987654324 @,
Image.fromstring) 并在 Tkinter (ImageTk.PhotoImage) 中显示它们。 -
这就是我最初所做的,但图像计算在纯 python 中花费了大量时间。所以我决定使用 C 扩展,因为 C API 已经是 Python 的一部分,而且纯 C 代码非常快。这在计算图像时给了我巨大的减速...主要目标是将图像放在内存中而不是磁盘上。这就是为什么我想在点击保存按钮时使用带有栅格数据的大字符串进行进一步处理并写入磁盘...
-
如果您的纯 Python 版本对您的需求来说速度很慢,那么您还可以询问如何加快速度,例如,在现有 Python 函数上精心放置类型声明可以使其运行速度提高 100 倍当使用Cython 编译或使用 Numba 进行编译时(您仍然需要了解 C 才能理解并有效地更改代码)。
-
对于进程内数据交换,可以直接传递数组、图像(很容易双向转换)。
-
我想你知道
fputs()和相当多的其他相关函数将在他们看到的第一个 0 字节处停止。例如,如果您的像素具有 0 值的 R 分量,则很有可能甚至不会写入 G 和 B 分量。这可能是……有问题的……在图像中可能经常在某处出现带有 0 字节的像素。你可能需要重新考虑你的设计,除非你能保证这永远不会发生......