我正在使用 C# 和 P/Invoke 来访问 GDK 库。我的目标是将一组 SVG 文件转换为光栅图像(特别是 png),并且使用 GDK 库似乎是最可靠/准确的。
在阅读了一些 Gnome/Cairo 文档之后,我发现了两种基本方法来实现这一点。其中一种方法使用不推荐使用的函数,而另一种则不使用。
第一种方法已被弃用,但可以说更简单/直接,基本上看起来像这样:
bool result = false;
ptrPixbuf = rsvg_pixbuf_from_file_at_size(svgFilePath, width, height, out ptrError);
if (ptrError == UIntPtr.Zero && ptrPixbuf != UIntPtr.Zero)
{
bool isSaved = gdk_pixbuf_save(ptrPixbuf, outputFilePath, out ptrError, UIntPtr.Zero);
if (ptrError == UIntPtr.Zero && isSaved == true)
{
result = true;
}
}
return result;
第二种方法并未被弃用,它涉及设置 Cairo Surface,渲染它,然后将其保存到文件中。它看起来基本上是这样的:
bool result = false;
ptrRsvgHandle = rsvg_handle_new_from_file(svgFilePath, out ptrError);
if (ptrError == UIntPtr.Zero)
{
ptrCairoSurface = cairo_image_surface_create(CairoFormat.CAIRO_FORMAT_ARGB32, width, height);
if ((cairo_surface_status(ptrCairoSurface) == CairoStatus.CAIRO_STATUS_SUCCESS)
{
ptrcairoContext = cairo_create(ptrCairoSurface);
if ((cairo_status(ptrCairoContext) == CairoStatus.CAIRO_STATUS_SUCCESS))
{
bool isRendered = rsvg_handle_render_cairo(ptrRsvgHandle, ptrCairoContext);
if (isRendered)
{
ptrPixbuf = rsvg_handle_get_pixbuf(ptrRsvgHandle);
if (ptrPixbuf != UIntPtr.Zero)
{
bool isSaved = gdk_pixbuf_save(ptrPixbuf, outputFilePath, out ptrError, UIntPtr.Zero);
if (ptrError == UIntPtr.Zero && isSaved == true)
{
result = true;
}
}
}
}
}
}
return result;
这两种方法似乎都有效 - 它们生成正确的光栅图像输出(尽管当我尝试并行执行一堆操作时,“Cairo 方式”存在一些错误 - 我最终会耗尽内存)。
我的问题是:为什么旧的/不推荐使用的方式(rsvg_pixbuf_from_file_at_size
)明显快于新的/开罗方式?我的测试显示第一种方法更快(一个文件/多个文件,标准 C# ForEach/Parallel.ForEach)。
例如,对于 16 个输入文件(输出尺寸为 6000x4200)并且没有并行处理,第一种方法需要大约 2:15.89 秒。第二种方法大约需要 2:37.95。使用并行处理(Parallel.Foreach 调用我的 P/Invoke 代码),结果是相似的——MaxDegreesOfParallelism
设置为默认值时,不推荐使用的方法需要 30.7 秒,而 Cairo 方法需要 36.95 秒。
开罗似乎也使用了更多的内存。此外,除了简单地为每次转换使用更多资源之外,Cairo 似乎也不知道如何避免使用我所有的 RAM。例如,如果我将输入文件的数量从 16 个增加到 720 个,并使用 Parallel.ForEach 循环,我最终会得到 0 MB 的可用 RAM,并且系统会停止运行(最终,调试进程退出,我的系统又回来了……但它锁定了一分钟左右)。
我的问题的简单答案是只使用不推荐使用的方法,但为什么不推荐使用它?开罗方法在任何方面都更好吗?
如果有人想查看更多我的代码,请告诉我,我会添加它。我试图将我发布的代码缩减为相关位(实际的 P/Invoke 代码,而不是调用它的 C# 代码)。