tags:

views:

1473

answers:

5

I have an array of ushort pixel data (16-bit grayscale values), and I am trying to save it as a jpeg image. However my code is crashing at the Save command with "A generic error occurred in GDI+". I can't figure out how to fix this. The directory I am saving to is created by my application and I write other files to it; so I know it's not a permissions problem. Is it maybe a data corruption problem? Am I doing something wrong in the steps to get the ushort data into the Bitmap object? Because I have ushort data I found it took some effort to figure out how to get it into the Bitmap object, and I am possibly doing it wrong.

Here is my code:

Bitmap img = new Bitmap(width, height, PixelFormat.Format16bppGrayScale);
Rectangle rect = new Rectangle(0,0, width, height);
BitmapData picData = img.LockBits(rect, ImageLockMode.ReadWrite, img.PixelFormat);
IntPtr pixelStartAddress = picData.Scan0;

WriteableBitmap pic = new WriteableBitmap(width, height, 96.0, 96.0, System.Windows.Media.PixelFormats.Gray16, null);

int stride = (thumb.XSize * pic.Format.BitsPerPixel + 7) / 8;
pic.WritePixels(new System.Windows.Int32Rect(0, 0, width, height), dataArray, stride, 0);  

pic.CopyPixels(new System.Windows.Int32Rect(0,0,thumb.XSize, thumb.YSize),pixelStartAddress, dataArray.Length * sizeof(ushort), stride);

img.UnlockBits(picData);
img.Save(path, ImageFormat.Jpeg);

This hole thing has become very frustrating. Please help?!

A: 

I am willing to bet that this is permissions problem. GDI+ is native component and I believe it requires different permissions than regular file saving or something like this. Is this ASP.NET app? If so make sure you give permissions to the IIS process for that folder.

Stilgar
A: 

I've seen this happen when the dimensions I was saving to weren't valid. Like a width of 0.

Jake Pearson
+1  A: 

I'm, afraid it has something to do with the grayscale / JPG. I don't know if JPEG supports grayscales.

I would try declaring the bitmap as a normal color one. And testing.

tekBlues
Thats seems to be the problem. When I change the PixelFormat to some color format it doesn't crash. However, the resulting jpeg image isn't in color and detail is lost.
Dan Vogel
I meant "is in color" not "isn't"
Dan Vogel
Jpeg supports 8 bit grayscale.
Brian
Bitmap doesn't have an 8 bit grayscale PixelFormat. How should I convert my 16 bit grayscale values so that they can be saved as a jpeg while still representing the same image?
Dan Vogel
+1  A: 

I have found that any bitmap that I had drawn on, no matter which way, had an occasional problem with being saved as JPEG (with the exception you are seeing). What helped was to clone the image first:

img.Clone(); // or:
img.Clone(rectangle, img.PixelFormat);

Maybe by doing this you can also try to change the pixel format, because I also assume, just like tekBlues, that there may be issues with greyscale.

Thomas Jung
+1  A: 

Regarding your comment about image quality (I would have responded as a comment, but it loses the code formatting):

You are saving with the default settings for JPEG export. You can create your own EncoderParameters instance with a higher quality setting:

var encParams = new EncoderParameters(1);
var encParams.Param[0] = new EncoderParameter(Encoder.Quality, 91L);
// get jpegEncoder by looping through ImageCodecInfo.GetImageEncoders())
image.Save("path to file", jpegEncoder, encParams);
Thomas Jung
the quality is lost because the 16 bit grayscale values are being used as something else. so the 16 bits are not utilizes as one value but 3 values.
Dan Vogel