我当前的代码是将一个小的Pbgra32位图映射到一个较大的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();
        }
    }

最佳答案

我想到了。关键是要了解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)
        {

        }
    }

关于c# - Alpha channel 无法与WriteableBitmap一起使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22643508/

10-12 00:53