1

I'm trying to merge two images I have as WriteableBitmaps. I want to square each pixel value, add it to the other image and then take the 2nd root (+ check, if the value is above 255). As I had no luck doing so using WriteableBitmapEx and ForEach() (Sobel operator & Convolution with WriteableBitmapEx) (which also seems to be pretty slow) I tried manipulating the pixels directly using BitmapDecoder. Unfortunately I can't seem to write the Pixelstream back to a WriteableBitmap, as I get the Errors:

'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

and

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

for these lines

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

Might this be something that's broken by the WriteableBitmapEx library?

Furthermore I'm wondering how to get my WriteableBitmaps into the BitmapDecoders. I have taken this code from a Win8 Coding book.

Here's my complete code so far:

    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);
        }

   } 
Community
  • 1
  • 1
Thomas
  • 4,030
  • 4
  • 40
  • 79
  • As far as I know it's just not possible to write pixels directly to a BitmapDecoder. Why do you want to do that by the way? You have a WriteableBitmap to display it somewhere. You could write the pixels to a BitmapEncoder to save the bitmap. What else would you like to do? – Jürgen Bayer Feb 17 '13 at 08:05

1 Answers1

4

IBuffer.AsStream() is an extension method. If you want to use it, you need to include the namespace where it is defined:

using System.Runtime.InteropServices.WindowsRuntime;

Update: As I mention below in my comment, I haven't done a lot with writeable bitmaps. However, your code doesn't set the transparency value. This may at least be part of the problem:

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);
}

Should be:

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.
}
chue x
  • 18,573
  • 7
  • 56
  • 70
  • Thanks, that's it. But can you also tell me how to get my WriteableBitmap into the BitmapDecoder? – Thomas Feb 15 '13 at 12:26
  • Sorry, I haven't done a lot with `WriteableBitmap`. Everything that I've seen involves going from `BitmapDecoder` to `WriteableBitmap`, **not** from `WriteableBitmap` to `BitmapDecoder`. For example, http://stackoverflow.com/questions/14718855/how-to-create-writeablebitmap-from-bitmapimage – chue x Feb 15 '13 at 15:43
  • Same here, hence the question :) – Thomas Feb 15 '13 at 16:24
  • @Thomas - see my update above. it may not solve your problem, but hopefully it gets you a little farther. good luck. – chue x Feb 15 '13 at 16:43