Tk_PhotoPutBlock 无法正确渲染我的 svg 文件

问题描述 投票:0回答:1

我正在尝试使用 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;

result

如您所见,左侧 svg 中的颜色与 Tk 右侧图像中的颜色不同。
也许问题来自我的

imgData
变量,作者在他的示例中似乎正在重新转换开罗表面的数据。我对图像变换的知识相当有限,所以我不知道在
Tk
方面该怎么做。

c image tcl tk-toolkit
1个回答
0
投票

我终于开始正确地测试这个了;我创建了一个与您建议的内容完全相同的 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 的错误或您使用它的方式的错误;一个合适的选项完全有可能使其行为正确。我不太了解,无法确定。


感谢您提出这个问题!这促使我在这方面更彻底地测试 Tk;我现在相当确信 Tk 正在做正确的事情。我很想知道,因为过去我们确实遇到过一些有关此问题的报道,但令人沮丧的是,要追捕它们却非常困难!这个案例很简单,我可以正确地交叉检查并理解结果肯定符合预期。

我无法控制第三方代码的功能,我也不会猜测如何修复它。

© www.soinside.com 2019 - 2024. All rights reserved.