Skip to main content
 首页 » 编程设计

c#之操纵 WriteableBitmap 像素

2024年02月20日30lexus

我正在尝试将我拥有的两个图像合并为 WriteableBitmaps。我想对每个像素值进行平方,将其添加到另一个图像,然后取第二个根(+ 检查,如果该值高于 255)。 由于我没有使用 WriteableBitmapEx 和 ForEach()(Sobel operator & Convolution with WriteableBitmapEx)(这似乎也很慢)这样做,所以我尝试使用 BitmapDecoder 直接操作像素。不幸的是,我似乎无法将 Pixelstream 写回 WriteableBitmap,因为我收到错误:

'Windows.Storage.Streams.IBuffer' does not contain a definition for 'AsStream' and the best extension method overload 'System.IO.WindowsRuntimeStreamExtensions.AsStream(Windows.Storage.Streams.IRandomAccessStream)' has some invalid arguments

和

Instance argument: cannot convert from 'Windows.Storage.Streams.IBuffer' to 'Windows.Storage.Streams.IRandomAccessStream'

对于这些行

using (Stream stream = bmp.PixelBuffer.AsStream()) 
{ 
   await stream.WriteAsync(pixels1, 0, pixels1.Length); 
} 

这可能是 WriteableBitmapEx 库破坏的东西吗?

此外,我想知道如何将我的 WriteableBitmaps 放入 BitmapDecoders 中。我从 Win8 编码书中获取了这段代码。

到目前为止,这是我的完整代码:

    async Task SobelCombine(BitmapDecoder decoder1, BitmapDecoder decoder2) 
    { 
        PixelDataProvider provider1 = await decoder1.GetPixelDataAsync( 
            BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, new BitmapTransform(), 
            ExifOrientationMode.RespectExifOrientation, ColorManagementMode.ColorManageToSRgb); 
        byte[] pixels1 = provider1.DetachPixelData(); 
        PixelDataProvider provider2 = await decoder1.GetPixelDataAsync( 
            BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, new BitmapTransform(), 
            ExifOrientationMode.RespectExifOrientation, ColorManagementMode.ColorManageToSRgb); 
        byte[] pixels2 = provider1.DetachPixelData(); 
 
 
 
        for (int i = 0; i < pixels1.Length; i += 4){ 
            pixels1[i]      = (byte)((byte)Math.Sqrt((Math.Pow(pixels1[i], 2) + Math.Pow(pixels2[i], 2))) % byte.MaxValue); 
            pixels1[i + 1] =  (byte)((byte)Math.Sqrt((Math.Pow(pixels1[i + 1], 2) + Math.Pow(pixels2[i + 1], 2))) % byte.MaxValue); 
            pixels1[i + 2] =  (byte)((byte)Math.Sqrt((Math.Pow(pixels1[i + 2], 2) + Math.Pow(pixels2[i + 2], 2))) % byte.MaxValue); 
        } 
 
        WriteableBitmap bmp = new WriteableBitmap((int)decoder1.OrientedPixelWidth, (int)decoder1.OrientedPixelHeight); 
 
        using (Stream stream = bmp.PixelBuffer.AsStream()) 
        { 
            await stream.WriteAsync(pixels1, 0, pixels1.Length); 
        } 
 
   }  

请您参考如下方法:

IBuffer.AsStream() 是一种扩展方法。如果你想使用它,你需要在定义它的地方包含命名空间:

using System.Runtime.InteropServices.WindowsRuntime; 

更新: 正如我在下面的评论中提到的,我对可写位图的处理不多。但是,您的代码没有设置透明度值。这可能至少是问题的一部分:

for (int i = 0; i < pixels1.Length; i += 4){ 
    pixels1[i]      = (byte)((byte)Math.Sqrt((Math.Pow(pixels1[i], 2) + Math.Pow(pixels2[i], 2))) % byte.MaxValue); 
    pixels1[i + 1] =  (byte)((byte)Math.Sqrt((Math.Pow(pixels1[i + 1], 2) + Math.Pow(pixels2[i + 1], 2))) % byte.MaxValue); 
    pixels1[i + 2] =  (byte)((byte)Math.Sqrt((Math.Pow(pixels1[i + 2], 2) + Math.Pow(pixels2[i + 2], 2))) % byte.MaxValue); 
} 

应该是:

for (int i = 0; i < pixels1.Length; i += 4){ 
    pixels1[i]      = (byte)((byte)Math.Sqrt((Math.Pow(pixels1[i], 2) + Math.Pow(pixels2[i], 2))) % byte.MaxValue); 
    pixels1[i + 1] =  (byte)((byte)Math.Sqrt((Math.Pow(pixels1[i + 1], 2) + Math.Pow(pixels2[i + 1], 2))) % byte.MaxValue); 
    pixels1[i + 2] =  (byte)((byte)Math.Sqrt((Math.Pow(pixels1[i + 2], 2) + Math.Pow(pixels2[i + 2], 2))) % byte.MaxValue); 
    pixels1[i + 3] = 255; // or some combination of the source data. 0 == completely transparent. 
}