none
Stride issue with WriteableBitmap.PixelBuffer.AsStream()

    Question

  • I am seeing some strange effects when manipulating pixels directly using a WriteableBitmap when I am trying to modify pixels from a loaded image vs pixels from an empty created WriteableBitmap.

    When I create an empty WriteableBitmap setting pixels via the usual pixels[ (x + width * y)<<2] method works just as expected, but when I am trying to modify a PixelBuffer of a loaded image instead which has identical dimensions the same pixel setting method does set the pixels with a sheared offset and I have to manually adjust the stride by a fixed value (which varies with each loaded image file) in order to get the same result: pixels[ (x + (width + adjustment) * y)<<2]. What makes this so strange is that the length of the pixel buffer is identical in both cases.

    So I suspect there might be some kind of conversion or padding going on in the Stream.write() or Stream.read() methods, but I cannot really make sense of it.

    I am using the following methods to access the data:

    // Read PixelBuffer from a WriteableBitmap: 
    Width = map.PixelHeight; 
    Height= map.PixelWidth;
    Stream stream = map.PixelBuffer.AsStream(); 
    byte[] pixels = new byte[stream.Length];
    stream.Seek(0, 0); 
    stream.Read(pixels, 0, pixels.Length); 
    
    [...]
    
    //Write PixelBuffer back 
    Stream stream = map.PixelBuffer.AsStream();
    stream.Seek(0, 0); 
    stream.Write(pixels, 0, pixels.Length);
    map.Invalidate();
    
    [...]
    
    //Create an empty WriteableBitmap
    pixels = new byte[ Width * Height << 2];
    WriteableBitmap map = new WriteableBitmap(Width,Height);
    Stream stream = map.PixelBuffer.AsStream();
    stream.Seek(0, 0);
    stream.Write(pixels, 0, pixels.Length);
    map.Invalidate();
    
    [...]
    
    //set pixel 
    public void setPixel(int x, int y, uint rgba) { 
    int stride = Width; 
    int index = (y * stride + x) << 2; 
    pixels[index] = (byte)((rgba >> 24) & 0xff);
    pixels[index+1] = (byte)((rgba >> 16) & 0xff);
    pixels[index+2] = (byte)((rgba >> 8) & 0xff);
    pixels[index+3] = (byte)(rgba & 0xff); 
    }






    Monday, April 09, 2012 1:13 PM

All replies

  • It looks indeed like the problem is somewhere in Stream.write() - I a have switched to using BitmapDecoder to read the image file and the stride problem has gone away:

    ImageProperties props = await file.Properties.GetImagePropertiesAsync();
    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(await file.OpenAsync(FileAccessMode.Read));
    BitmapTransform transform = new BitmapTransform();
    transform.Bounds = new BitmapBounds() { Width = props.Width, Height = props.Height };
    PixelDataProvider pixelData = await decoder.GetPixelDataAsync(BitmapPixelFormat.Rgba8, decoder.BitmapAlphaMode, new BitmapTransform(), ExifOrientationMode.RespectExifOrientation, ColorManagementMode.DoNotColorManage);
    byte[] pixels = flipRGBA( pixelData.DetachPixelData());
    WriteableBitmap map = new WriteableBitmap(props.Width, props.Height);
    Stream stream = map.PixelBuffer.AsStream();
    stream.Seek(0, 0);
    stream.Write(pixels, 0, pixels.Length);
    map.Invalidate();            

    Monday, April 09, 2012 2:06 PM
  • Hello Quasimondo,

    Do you feel that your stride question is answerd by using the BitmapDecoder? This certainly sounds like the way to go.

    Thanks,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Wednesday, April 11, 2012 11:42 PM
    Moderator
  • Well, BitmapDecoder surely solves it for me, but just out of curiosity I still would like to know what happens under the hood with the Stream method and why it causes this effect.
    Thursday, April 12, 2012 8:53 AM