Skip to content
This repository has been archived by the owner on Mar 30, 2019. It is now read-only.

SharpDX.WIC.Bitmap.CopyPixels<T>() implementation throws "output.Length must be equal to Width * Height", which makes no sense #299

Closed
dilyanrusev opened this issue Mar 4, 2014 · 4 comments

Comments

@dilyanrusev
Copy link

Description

The generic methods for copying the pixels of a WIC bitmap are wrong. They assume that there is one byte per pixel, and set a requirement that the native code does not have. When you have create a 32-bit (4 bytes per pixel) WIC bitmap, and then try to extract the pixels into a byte array, you'd create a width_height_bytes per pixel array and copy the data in it. However, when you do that, SharpDX complains wrongly. When you use unsafe code, everything works, as expected.

What should be changed

Remove or fix the unnecessary checks in generic CopyPixels methods:

if (size.Width * size.Height != output.Length)
{
    throw new ArgumentException("output.Length must be equal to Width * Height");
}

Reproducing the problem

Setup code

using WicBitmap = SharpDX.WIC.Bitmap;
using WicPixeFormat = SharpDX.WIC.PixelFormat;

byte[] data;

bitmap = new WicBitmap(imgFactory, sideLength, sideLength,
                WicPixeFormat.Format32bppPBGRA, BitmapCreateCacheOption.CacheOnLoad);

data = new byte[sideLength * sideLength * 4];

What works

unsafe 
{
    fixed (void* ptr = data)
    {
        bitmap.CopyPixels(sideLength * 4, (IntPtr)ptr, data.Length);
    }
}

What doesn't, but should work

bitmap.CopyPixels(data);
@jwollen
Copy link
Contributor

jwollen commented Mar 4, 2014

The generic CopyPixels(T) methods expect the array length to equal the number of pixels written and a template argument that matches the pixel format. For 32-bit images you will want to provide a buffer of type Color[] or ColorBGRA[] and length (height * width).

@xoofx
Copy link
Member

xoofx commented Mar 5, 2014

Sorry, it is not described in the doc, but the CopyPixels<T> methods are expecting the T generic to be the pixel type.This allow to copy pixels without specifying the stride (as the stride is automatically calculated by sizeof(T) * width) If you need to copy to a byte[] buffer, you have to use the CopyPixels(int stride, IntPtr dataPointer, int size) method (and unsafe code unfortunately). Though, we could introduce a method CopyPixels(int stride, byte[] buffer) if you need this scenario?

@dilyanrusev
Copy link
Author

Well, I didn't expect this to work like in XNA. Both options would be nice - include it in the documentation or add the new method overload. I would personally prefer to have an additional method overload, that would certainly ring a bell about the other methods.

xoofx added a commit that referenced this issue Mar 15, 2014
@xoofx
Copy link
Member

xoofx commented Mar 15, 2014

This should be fixed by commit 0ef5100

@xoofx xoofx closed this as completed Mar 15, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants