【问题标题】:How do I remove (or apply) transparency on a gdk-pixbuf?如何在 gdk-pixbuf 上删除(或应用)透明度?
【发布时间】:2012-05-24 10:28:39
【问题描述】:

我有一个 c++ 程序,其中创建了一个 gdk-pixbuf。我想把它输出为图像,所以我打电话给gdk_pixbuf_save_to_stream(pixbuf,stream,type,NULL,&err,NULL)。当“类型”是 png 或 tiff 时,这工作正常,但使用 jpeg 或 bmp 它只会产生一个黑色方块。原始的 pixbuf 由黑色透明(gdk_pixbuf_get_has_alpha 返回 true)组成,所以我猜测问题出在 alpha 掩码上。

GdkPixbuf 具有添加 Alpha 通道的功能,但我看不到可以再次删除它,或者(可能同样好)反转它。

有没有一种简单的方法可以让 jpeg 和 bmp 格式正常工作?

(我应该说我对这样的正确编程很陌生。)

【问题讨论】:

  • 不确定gdk-pixbuf,但您可能想尝试libcairo,它通常基于gdk-pixbuf,并具有所有这些jpeg、bmp、...相关的东西例程。
  • 谢谢,但扫描文档并没有显示任何保存到 jpeg &c 的功能,仅用于从中导入。

标签: c++ gdk


【解决方案1】:

JPEG 根本没有任何 Alpha 通道或透明度的概念。 Alpha 通道在转换为 JPEG 期间被剥离。 BMP 也有同样的限制。

由于透明度对您很重要,您的程序应该坚持生成 PNG。

就您在标题中提出的问题而言,可以手动移除 Alpha 通道。诀窍是了解 GdkPixbuf 中的数据是如何存储的。当您有一个带有 alpha 通道(也称为 RGBA)的 RGB pixbuf 时,像素存储为 32 位值:4 个字节,每种颜色一个字节,第四个是 alpha 通道。 RGB pixbuf 存储为 24 位值,每种颜色一个字节。

因此,如果您创建一个临时字节缓冲区并复制每个 RGBA 像素的前三个字节并删除第四个字节,那么该临时缓冲区就是纯 RGB。稍微画一下:

[R][G][B][A][R][G][B][A]... => [R][G][B][R][G][B] ...

注意,你必须打包临时缓冲区; [B] 字节和下一个 [R] 字节之间没有备用字节。

然后,您通过将这个 RGB 缓冲区交给它来创建一个新的 GdkPixbuf,并且您已经删除了 alpha 通道。

参见 gdk_pixbuf_get_pixels() 来访问 RGBA 缓冲区和 gdk_pixbuf_new_from_data() 来创建 RGB pixbuf。有关打包数据如何存储在 GdkPixbuf 中的更多讨论,请参阅 here

【讨论】:

  • 你要去拿考古徽章吗!我完全忘记了这个问题。感谢您的回答 - 非常清楚。当我回到这个项目时,我会记住这一点。
【解决方案2】:

这是(相当低效和丑陋的)Vala 应用程序,它从图像中删除透明度并将其保存为指定的格式。注意:在 gdk_pixbuf_new_from_data() 的 vala 绑定中有一个小错误,会导致生成的图像损坏。我很快就会解决这个问题,但这只是为了演示目的(除了问题是关于 C++ 的):

    public static int main (string[] args) {
        if (args.length < 4) {
            print ("Usage: %s SOURCE DESTINATION FORMAT\n", args[0]);
            return -1;
        }

        var src_path = args[1];
        var destination_path = args[2];
        var dest_type = args[3];

        var pixbuf = new Gdk.Pixbuf.from_file_at_scale (src_path, 48, 48, false);

        // Remove alpha channel
        if (pixbuf.get_has_alpha () && pixbuf.get_n_channels () == 4 && pixbuf.get_bits_per_sample () == 8) {
            var width = pixbuf.get_width ();
            var height = pixbuf.get_height ();
            var rowstride = pixbuf.get_rowstride ();
            unowned uint8[] orig_pixels = pixbuf.get_pixels ();
            var pixels = new uint8[rowstride * height];

            for (var i = 0; i < height; i++) {
                for (var j = 0, k = 0; j < width * 4; j += 4, k += 3) {
                    var orig_index = rowstride * i + j;
                    var index = rowstride * i + k;

                    if (orig_pixels[orig_index] == 0 &&
                        orig_pixels[orig_index + 1] == 0 &&
                        orig_pixels[orig_index + 2] == 0 &&
                        orig_pixels[orig_index + 3] == 0) {
                        pixels[index] = 0xFF;
                        pixels[index + 1] = 0xFF;
                        pixels[index + 2] = 0xFF;
                    } else {
                        pixels[index] = orig_pixels[orig_index];
                        pixels[index + 1] = orig_pixels[orig_index + 1];
                        pixels[index + 2] = orig_pixels[orig_index + 2];
                    }
                }
            }

            pixbuf = new Gdk.Pixbuf.from_data (pixels,
                                               pixbuf.get_colorspace (),
                                               false,
                                               8,
                                               width,
                                               height,
                                               rowstride,
                                               null);
        }

        pixbuf.save (destination_path, dest_type);

        return 0;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-14
    • 1970-01-01
    • 2014-03-03
    • 2013-11-17
    • 1970-01-01
    相关资源
    最近更新 更多