我正在尝试使用 C Tk API 来实现用 C 编写的这个 example。 我的目标是尝试使用这个 library 将
svg
文件转换为照片 Tk 以在框架 Tk 中读取。下面是我的 svg 文件:
<svg id="svg1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle r="32" cx="35" cy="65" fill="#F00" opacity="0.5"/>
<circle r="32" cx="65" cy="65" fill="#0F0" opacity="0.5"/>
<circle r="32" cx="50" cy="35" fill="#00F" opacity="0.5"/>
</svg>
和我的 C 代码:
Tk_PhotoHandle source;
unsigned char *imgData;
// PhotoObj : set photo [image create photo]; # tcl code
// FileObj : file.svg
source = Tk_FindPhoto(interp, Tcl_GetString(PhotoObj));
if (source == NULL) {
Tcl_SetResult(interp, "photo not found", TCL_STATIC);
return TCL_ERROR;
}
char *sp = Tcl_GetString(FileObj);
resvg_init_log;
resvg_options *opt = resvg_options_create();
resvg_options_load_system_fonts(opt);
resvg_render_tree *tree;
int err = resvg_parse_tree_from_file(sp, opt, &tree);
resvg_options_destroy(opt);
if (err != RESVG_OK) {
printf("Error id: %i\n", err);
return TCL_ERROR;
}
resvg_size size = resvg_get_image_size(tree);
int width = (int)size.width;
int height = (int)size.height;
imgData = (unsigned char *)Tcl_Alloc(width*height*4);
if (imgData == NULL) {
Tcl_SetResult(interp, "cannot alloc image buffer", TCL_STATIC);
return TCL_ERROR;
}
resvg_render(tree, resvg_transform_identity(), width, height, imgData);
Tk_PhotoImageBlock block;
Tk_PhotoGetImage(source, &block);
block.pixelPtr = imgData;
block.width = width;
block.height = height;
block.pitch = width * 4;
block.pixelSize = 4;
block.offset[0] = 0;
block.offset[1] = 1;
block.offset[2] = 2;
block.offset[3] = 3;
if (Tk_PhotoSetSize(interp, source, width, height) != TCL_OK) {
return TCL_ERROR;
}
Tk_PhotoPutBlock(interp, source, &block, 0, 0, width, height, TK_PHOTO_COMPOSITE_SET);
resvg_tree_destroy(tree);
return TCL_OK;
。
如您所见,左侧 svg 中的颜色与 Tk 右侧图像中的颜色不同。
也许问题来自我的
imgData
变量,作者在他的示例中似乎正在重新转换开罗表面的数据。我对图像变换的知识相当有限,所以我不知道在Tk
方面该怎么做。
我终于开始正确地测试这个了;我创建了一个与您建议的内容完全相同的 SVG 文件,然后运行此脚本:
puts [info patchlevel]
image create photo foo -file svgtestimg.svg
foo write svgtestimg.png
pack [label .foo -background white -image foo]
pack [label .foo2 -background black -image foo]
报告说我运行了Tcl: 9.0a4, Tk: 9.0b1
(是的,一个奇怪的组合;我的开发机器并不处于完全一致的状态)输出截图是这样的:
生成的PNG是这样的:
我还使用多种图像查看工具(浏览器)查看了所有图像。这个实验的
结果是我知道Tk正确地渲染了SVG(或者至少非常接近它),无论是浅色背景还是深色背景,并且底层图像模型具有正确的数据,因为PNG(具有透明度)被正确书写。这对我来说是一个巨大的解脱!
那么你的问题是怎么回事?好吧,我正在使用 Tk 8.7 中的内置 SVG 渲染器(9.0 本质上是相同的),它完全了解照片图像的内部 RGBA 模型,并且您正在使用其他一些 SVG 渲染器(resvg),它似乎使关于图像背景颜色应该是什么的假设。这些假设(似乎偏向黑暗的一端)显然是错误的;照片是完整的RGBA,与背景的合成可以留给Tk。我不确定这是否是 resvg 的错误或您使用它的方式的错误;一个合适的选项完全有可能使其行为正确。我不太了解,无法确定。
我无法控制第三方代码的功能,我也不会猜测如何修复它。