0

I am trying to build a bitmap for a map tile by the following function from C# Visual Studio 2013 WPF.

https://msdn.microsoft.com/en-us/library/ms616045%28v=vs.110%29.aspx

public static BitmapSource Create(int pixelWidth, int pixelHeight, double dpiX, double dpiY, PixelFormat pixelFormat, BitmapPalette palette, Array pixels, int stride);

 pixelWidth = tile.Image.Width;  //value is 524288
 pixelHeight = tile.Image.Height;   //value is 524288
 dpiX  = 96;
 dpiY  = 96;
 System.Windows.Media.PixelFormat pixelFormat = new System.Windows.Media.PixelFormat();
 pixelFormat = System.Windows.Media.PixelFormats.Pbgra32;
 pngBuffer is a Byte[] that has 778 integer elements
 stride = 1024

But, I got error:

 An unhandled exception of type 'System.ArgumentException' occurred in PresentationCore.dll

 Additional information: Value does not fall within the expected range 

What "value" that I should change so that the image can be created ?

The posts of

http://stackoverflow.com/questions/28490203/throws-an-exception-when-cropping-an-image-if-window-is-maximized-wpf

http://stackoverflow.com/questions/24613246/system-argumentexception-occurred

cannot help me.

Thanks

UPDATE I have made the following changes:

pixelWidth = 256
pixelHeight = 256
stride =1024 because stride = pixelWidth * (bitsPerPixel/ 8)

I got error:

An unhandled exception of type 'System.ArgumentException' occurred in PresentationCore.dll

Additional information: Buffer size is not sufficient.
user3448011
  • 1,469
  • 1
  • 17
  • 39
  • Dimensions are probably too big as this results in a 1Gb image. With ImageMagick you can work against huge images. – aybe Dec 29 '15 at 18:55
  • @Aybe, If I changed width and height to be 256, I got error: An unhandled exception of type 'System.ArgumentException' occurred in PresentationCore.dll, Additional information: Buffer size is not sufficient. – user3448011 Dec 29 '15 at 20:25

2 Answers2

1

Stride is not an arbitrary value, it represent the width of a row of pixels or scan line, and it should be calculated. If you search the web you will encounter many formulas, note that from the link you pointed:

int stride = width/8;

but this is the one that have worked well for me:

int stride = pixelWidth * (pixelFormat.BitsPerPixel / 8); 
E-Bat
  • 4,792
  • 1
  • 33
  • 58
  • I made the change of stride, and got the error : An unhandled exception of type 'System.ArgumentException' occurred in PresentationCore.dll Additional information: Value does not fall within the expected range. – user3448011 Dec 29 '15 at 22:12
  • Also make sure that your buffer size is `stride * pixelHeight`, i.e. 262144 bytes. – Clemens Dec 30 '15 at 00:14
  • Btw, if you want the stride to be calculated correctly for all pixel formats, not only those that have an integer number of bytes per pixel, use `stride = (pixelWidth * pixelFormat.BitsPerPixel + 7) / 8`. – Clemens Dec 30 '15 at 08:52
0

@E-Bat/@Clemens answer/comment are correct though there's a bit missing to get you there :

bytesPerPixel = (bitsPerPixel + 7) / 8
stride = width * bytesPerPixel
bufferSize = stride * height

Technically the stride is the length of a scanline, which can either match your image width or be larger, see DirectX docs for more details.

BitmapSource knows that subtlety and will act accordingly, i.e. a larger buffer size is indeed a valid value but in general we don't tend to pass larger memory blocks unless doing low-level programming.

That stride term is a bit confusing, in fact its origin comes from bare metal platforms where one would typically work against a texture atlas in memory .

Here's an example, the picture of the VRAM content in a PSX:

enter image description here

Let's look at the yellowish icon, the correct stride to access this icon would is indeed the VRAM width as you can see the length between each line of the icon equals VRAM width.

aybe
  • 15,516
  • 9
  • 57
  • 105