1

gdk-pixbufが作成されたC++プログラムがあります。画像として出力したいので、と呼びますgdk_pixbuf_save_to_stream(pixbuf,stream,type,NULL,&err,NULL)。これは、「type」がpngまたはtiffの場合は正常に機能しますが、jpegまたはbmpを使用すると、黒い四角が生成されます。元のpixbufはblack-on-transparentで構成されている(そしてgdk_pixbuf_get_has_alphatrueを返す)ので、問題はアルファマスクにあると推測しています。

GdkPixbufにはアルファチャネルを追加する機能がありますが、それを再び削除する機能、または(これは同じくらい良いかもしれませんが)反転する機能がありません。

jpegおよびbmp形式を正しく機能させる簡単な方法はありますか?

(私はこのような適切なプログラミングに非常に慣れていないということを言わなければなりません。)

4

2 に答える 2

2

JPEGには、アルファチャネルや透明度の概念はまったくありません。アルファチャネルは、JPEGへの変換中に削除されます。BMPにも同じ制限があります。

透明性はあなたにとって重要なので、プログラムはPNGの生成に固執する必要があります。

タイトルで提起した質問に関する限り、アルファチャネルの削除は手動で行うことができます。秘訣は、GdkPixbufのデータがどのように保存されるかを理解することです。アルファチャネル(RGBAとも呼ばれる)を備えたRGB pixbufがある場合、ピクセルは32ビット値として格納されます。4バイト、色ごとに1バイト、4番目はアルファチャネルです。RGB pixbufsは、色ごとに1バイトの24ビット値として保存されます。

したがって、一時バイトバッファーを作成し、各RGBAピクセルの最初の3バイトをコピーして、4番目をドロップすると、その一時バッファーは純粋なRGBになります。少し図解するには:

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

一時バッファをパックする必要があることに注意してください。[B]バイトと次の[R]バイトの間にスペアバイトはありません。

次に、このRGBバッファーを渡して新しいGdkPixbufを作成し、アルファチャネルを削除しました。

RGBAバッファーにアクセスするにはgdk_pixbuf_get_pixels()を、RGBpixbufを作成するにはgdk_pixbuf_new_from_data()を参照してください。パックされたデータがGdkPixbuf内にどのように格納されるかについての詳細は、ここを参照してください。

于 2012-05-23T07:18:33.507 に答える
-1

これは(かなり非効率的で醜い)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;
    }
于 2012-05-24T02:28:39.440 に答える