1

我当前的代码是将一个小的 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();
        }
    }
4

1 回答 1

5

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

        }
    }
于 2014-03-26T16:22:00.587 回答