Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使裁剪的位图透明?_C#_Wpf_Bitmap_Transparent - Fatal编程技术网

C# 如何使裁剪的位图透明?

C# 如何使裁剪的位图透明?,c#,wpf,bitmap,transparent,C#,Wpf,Bitmap,Transparent,我有一个裁剪过的位图: CroppedBitmap crop = new CroppedBitmap(rtb, new Int32Rect(MapOffset, MapOffset, BOARD_WIDTH - 1 - MapOffset, BOARD_HEIGHT - 1 - MapOffset)); 我需要将白色设置为透明。很遗憾,这不起作用裁剪位图不包含“MakeTransparent”的定义: crop.MakeTransparent(Colors.White); 有人有什么想法/

我有一个裁剪过的位图:

 CroppedBitmap crop = new CroppedBitmap(rtb, new Int32Rect(MapOffset, MapOffset, BOARD_WIDTH - 1 - MapOffset, BOARD_HEIGHT - 1 - MapOffset));
我需要将白色设置为透明。很遗憾,这不起作用裁剪位图不包含“MakeTransparent”的定义:

crop.MakeTransparent(Colors.White);
有人有什么想法/建议吗

提前谢谢

~~~~~~~~~~~~~~~

我找到了这个密码

但是当我实施它的时候

    public void SaveMainCanvas2BMP(string filename)
    {

        // Write BMP
        VisualBrush sourceBrush = new VisualBrush(MainCanvas);
        DrawingVisual drawingVisual = new DrawingVisual();
        DrawingContext drawingContext = drawingVisual.RenderOpen();
        using (drawingContext)
        {
            drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(- MapOffset, - MapOffset), new Point(BOARD_WIDTH - 1 + MapOffset, BOARD_HEIGHT - 1 + MapOffset)));
        }

        RenderTargetBitmap rtb = new RenderTargetBitmap(BOARD_WIDTH - 1, BOARD_HEIGHT - 1, 96, 96, PixelFormats.Default);
        rtb.Render(drawingVisual);

        //crops  rectangle at position (0,0).
        CroppedBitmap crop = new CroppedBitmap(rtb, new Int32Rect(0, 0, BOARD_WIDTH - 1, BOARD_HEIGHT - 1));

        WriteableBitmap writeable = new WriteableBitmap(crop);

        // Code to turn WHITE pixels TRANSPARENT
        int pixelWidth = (int)writeable.Width;
        int pixelHeight = (int)writeable.Height;
        int Stride = pixelWidth * 4;

        BitmapSource imgSource = (BitmapSource)writeable;
        byte[] pixels = new byte[pixelHeight * Stride];
        imgSource.CopyPixels(pixels, Stride, 0);
        byte TransparentByte = byte.Parse("0");
        byte Byte255 = byte.Parse("255");
        int N = pixelWidth * pixelHeight;
        //Operate the pixels directly
        for (int i = 0; i < N; i++)
        {
            byte a = pixels[i * 4];
            byte b = pixels[i * 4 + 1];
            byte c = pixels[i * 4 + 2];
            byte d = pixels[i * 4 + 3];
            if (a == Byte255 && b == Byte255 && c == Byte255 && d == Byte255)
            {
                pixels[i * 4] = TransparentByte;
                pixels[i * 4 + 1] = TransparentByte;
                pixels[i * 4 + 2] = TransparentByte;
                pixels[i * 4 + 3] = TransparentByte;
            }
        }
        WriteableBitmap writeableBitmap = new WriteableBitmap(pixelWidth, pixelHeight, 96, 96,
            PixelFormats.Pbgra32, BitmapPalettes.Halftone256Transparent);
        writeableBitmap.WritePixels(new Int32Rect(0, 0, pixelWidth, pixelHeight), pixels, Stride, 0);



        //encode as BMP
        BitmapEncoder bmpEncoder = new BmpBitmapEncoder();

        bmpEncoder.Frames.Add(BitmapFrame.Create(writeableBitmap));

        //save to memory stream
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        bmpEncoder.Save(ms);
        ms.Close();
        System.IO.File.WriteAllBytes(filename, ms.ToArray());
    }
它不能使白色透明;它用黑色代替白色:

编辑 解决方案

解决方案就在这里问题与WPF和透明度有关:

一种可能的变体是从裁剪的位图创建可写位图:

WriteableBitmap writeable = new WriteableBitmap(cropped);

然后,您可以分析位图的每个像素,并将白色像素更改为透明像素。最快的方法是使用Lock方法获取像素缓冲区,然后使用不安全的代码在BackBuffer中循环。更简单但速度较慢的方法是使用CopyPixels和WritePixels方法。

问题在于WPF处理透明度的方式。BMP不是解决方法,PNG是

解决方案如下:

您知道有一个链接演示了如何使用锁定方法获取像素缓冲区,然后使用不安全代码在BackBuffer中循环吗?MSDN上有一个示例:请参阅页面底部示例中的DrawPixel方法。但它并不完美,因为它们将IntPtr强制转换为int,因此在64位平台上可能会失败。您应该将它改为byte*,并直接使用指针。请注意,您可以在一次锁定调用后处理所有字节,然后在最后调用Unlock。