0

BitmapSource から BitmapImage をロードしていますが、BitmapImage のフォーマットが BitmapSource の Bgra32 ではなく Bgr32 であることが常にわかります。ここに同様のスレッドがあります: BitmapImage from file PixelFormat is always bgr32

しかし、スレッドで提案されているように、 BitmapCreateOptions.PreservePixelFormat を使用してもうまくいきませんでした。ここに私がやっていることがあります:

// I have verified that b is a valid BitmapSource and its format is Bgra32
// the following code produces a file (testbmp2.bmp) with an alpha channel as expected
// placing a breakpoint here and querying b.Format in the Immediate window also produces
// a format of Bgra32
BmpBitmapEncoder test = new BmpBitmapEncoder();
FileStream stest = new FileStream(@"c:\temp\testbmp2.bmp", FileMode.Create);
test.Frames.Add(BitmapFrame.Create(b));
test.Save(stest); 
stest.Close();

// however, this following snippet results in bmp.Format being Bgr32
BitmapImage bmp = new BitmapImage();
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
MemoryStream stream = new MemoryStream();

encoder.Frames.Add(BitmapFrame.Create(b));
encoder.Save(stream);

bmp.BeginInit();
bmp.StreamSource = new MemoryStream(stream.ToArray());
bmp.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
bmp.CacheOption = BitmapCacheOption.None;
bmp.EndInit();

stream.Close();

BitmapSource から BitmapImage を作成し、アルファ チャネルを維持する方法はありますか?

更新: 他のスレッドに投稿された同じコードを使用してファイルから testbmp2.bmp をロードしました。ロード後、Format プロパティは Bgr32 です。

BitmapImage b1 = new BitmapImage();
b1.BeginInit();
b1.UriSource = new Uri(@"c:\temp\testbmp2.bmp");
b1.CreateOptions = BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreImageCache;
b1.CacheOption = BitmapCacheOption.OnLoad;
b1.EndInit();

だから多分私は FileStream/MemoryStream を正しく保存していませんか? FileStream を保存した後、Photoshop で testbmp2.bmp を開いてアルファ チャネルを確認できるため、これは正しくないようです。

更新 2: 私が抱えている問題を言い直す必要があると思います。テクスチャの個別のチャンネルを表示しようとしています。Image コントロールを介してビットマップを表示しています。チャネル ベースのユーザー入力をマスクする Image の Effect プロパティに割り当てられた単純な HLSL コンパイル済みシェーダーがあります。アルファ チャネルを保持しながら BitmapSource を BitmapImage に取得できないことは、問題の一部に過ぎませんでした。元の BitmapSource の Format は Bgra32 だったので、それを Image の Source プロパティに直接割り当てることができることに気付きました。問題は、Image オブジェクトが事前に乗算されたアルファを持つテクセルのみを表示することです...? ここに私のシェーダーコードがあります:

sampler2D  inputImage : register(s0);
float4 channelMasks : register(c0);

float4 main (float2 uv : TEXCOORD) : COLOR0
{
    float4 outCol = tex2D(inputImage, uv);  

    if (!any(channelMasks.rgb - float3(1, 0, 0)))
    {
        outCol.rgb = float3(outCol.r, outCol.r, outCol.r);
    }
    else if (!any(channelMasks.rgb - float3(0, 1, 0)))
    {
        outCol.rgb = float3(outCol.g, outCol.g, outCol.g);
    }
    else if (!any(channelMasks.rgb - float3(0, 0, 1)))
    {
        outCol.rgb = float3(outCol.b, outCol.b, outCol.b);
    }
    else
    {
        outCol *= channelMasks; 
    }


    if (channelMasks.a == 1.0)
    {
        outCol.r = outCol.a; // * 0.5 + 0.5;
        outCol.g = outCol.a;
        outCol.b = outCol.a;
    }

    outCol.a = 1;

    return outCol;
}

私はそれをかなり広範囲にテストしましたが、outCol 値が適切に設定されていることを確信しています。(1.0, 1.0, 1.0, 0.0) のチャネル マスク値を渡すと、表示されるイメージは RGB チャネルで、アルファの領域が黒く描画されます。 RGBチャンネルに。事前に乗算されたアルファなしで Image に BitmapSource を表示する方法を知っている人はいますか? もっと言えば、アルファの事前乗算が発生する前にエフェクトにテクスチャを受け取る方法はありますか? どのような順序で処理が行われるかはわかりませんが、テクスチャが s0 レジスタに書き込まれ、シェーダーが処理を開始する前に事前乗算が行われるようです。

4

1 に答える 1