Alpha通道与WriteableBitmap无法正常工作

时间:2014-03-25 18:39:10

标签: c# bitmap writeablebitmap writeablebitmapex

我目前的代码是将一个小的Pbgra32位图blit到更大的Pbgra32位图上。工作良好。我现在想做的是让那个较小的部分透明。为此,在blit之前,我将较小的一个传递给一个方法,该方法应该通过单独保留RGB值来编辑每个像素,同时将0x7F写入每个像素的A值。

然而,不是50%的透明图像,而是一个灰色方块。我做错了什么?

private void MakeTransparent(ref WriteableBitmap bmp)
    {
        int width = bmp.PixelWidth;
        int height = bmp.PixelHeight;
        int stride = bmp.BackBufferStride;
        int bytesPerPixel = (bmp.Format.BitsPerPixel + 7)/8;

        unsafe
        {
            bmp.Lock();
            byte* pImgData = (byte*) bmp.BackBuffer;

            int cRowStart = 0;
            int cColStart = 0;
            for (int row = 0; row < height; row++)
            {
                cColStart = cRowStart;
                for (int col = 0; col < width; col++)
                {
                    byte* bPixel = pImgData + cColStart;
                    UInt32* iPixel = (UInt32*) bPixel;
                    bPixel[3] = 0x7F;
                    cColStart += bytesPerPixel;
                }
                cRowStart += stride;
            }
            bmp.Unlock();
        }
    }

1 个答案:

答案 0 :(得分:3)

我明白了。关键是要实现什么是Pbgra32并且正确处理它(参见解决方案中的评论)。此方法修改了Pbgra32,以便可以像这样使用结果:

ChangeTransparency(ref wb_icon);
var iconSize = new Size(wb_icon.PixelWidth, wb_icon.PixelHeight);
wb_backgroundImage.Blit(new Rect(loc, iconSize), wb_icon, new Rect(iconSize),
   WriteableBitmapExtensions.BlendMode.Alpha);

以下是方法:

    private void ChangeTransparency(ref WriteableBitmap bmp, int newAlpha = 127)
    {
        try
        {
            int width = bmp.PixelWidth;
            int height = bmp.PixelHeight;
            int stride = bmp.BackBufferStride;
            int bytesPerPixel = (bmp.Format.BitsPerPixel + 7) / 8;

            unsafe
            {
                bmp.Lock();
                byte* pImgData = (byte*)bmp.BackBuffer;

                int cRowStart = 0;
                int cColStart = 0;
                for (int row = 0; row < height; row++)
                {
                    cColStart = cRowStart;
                    for (int col = 0; col < width; col++)
                    {
                        // the RGB values are pre-multiplied by the alpha in a Pbgra32 bitmap
                        // so I need to un-pre-multiply them with the current alpha
                        // and then re-pre-multiply them by the new alpha
                        byte* bPixel = pImgData + cColStart;

                        byte A = bPixel[3];
                        if (A > 0)
                        {
                            byte B = bPixel[0];
                            byte G = bPixel[1];
                            byte R = bPixel[2];

                            bPixel[0] = Convert.ToByte((B/A)*newAlpha);
                            bPixel[1] = Convert.ToByte((G/A)*newAlpha);
                            bPixel[2] = Convert.ToByte((R/A)*newAlpha);
                            bPixel[3] = Convert.ToByte(newAlpha);
                        }

                        cColStart += bytesPerPixel;
                    }
                    cRowStart += stride;
                }
                bmp.Unlock();
            }
        }
        catch (Exception ex)
        {

        }
    }