I have a WebAPI endpoint (hosted in IIS) that reads images from a database (byte array) and returns them in the PNG format. This code is simple:
Image img = ImageHelper.ReadFromDatabase(…);
using (MemoryStream ms = new MemoryStream())
{
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new ByteArrayContent(ms.ToArray());
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
response.ConfigureResponseCachability(parseConceptVersion, TimeSpan.FromHours(1));
return response;
}
I have three web servers and on one of the them the above code causes this error: A generic error occurred in GDI+.
at at System.Drawing.Image.Save()
.
The servers are running different OS versions:
I have changed the above code to return a JPEG instead of a PNG and that fixes the problem.
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
I have to send PNG images so I need to find the root cause.
I converted the code to use WPF classes (System.Windows.Media) instead of Windows Form classes. The result is interesting: I get an error creating PNGs as well. This time the error is The component registration is invalid. (Exception from HRESULT: 0x88982F8A)
at System.Windows.Media.Imaging.BitmapEncoder.SaveFrame()
Could it be that my server is missing a low level component that is necessary to save PNGs?
Thanks
@Chris Pratt asked to see the code that creates the images from the byte array. There are several layers between the WebAPI code and the SqlDataReader invocation but here is the code that converts the byte array read from the database.
/// <summary>
/// Creates a bitmap from a byte array
/// </summary>
public static Bitmap CreateBitmapFromBytes(byte[] bytes, int width, int height)
{
// Make sure bytes were specified.
if (bytes == null ||
bytes.Length == 0)
{
return null;
}
using (MemoryStream imageStream = new MemoryStream(bytes))
{
Bitmap bitmap;
try
{
bitmap = (Bitmap)Bitmap.FromStream(imageStream);
}
catch(ArgumentException)
{
return GetEmptyBitmap(width, height);
}
using (bitmap)
{
return new Bitmap(bitmap, width, height);
}
}
}
1) The .NET framework >= 3.0 should have a built-in encoder. Check there is an encoder for the right image mime type.
public static ImageCodecInfo GetEncoderInfo(string mimeType)
{
string lookupKey = mimeType.ToLower();
ImageCodecInfo foundCodec = null;
if (Encoders.ContainsKey(lookupKey))
{
foundCodec = Encoders[lookupKey];
}
return foundCodec;
}
(you will need a lookup for encoders)
private static Dictionary<string, ImageCodecInfo> _encoders;
/// <summary>
/// A quick lookup for getting image encoders
/// </summary>
private static Dictionary<string, ImageCodecInfo> Encoders
{
get
{
if (_encoders == null)
{
_encoders = new Dictionary<string, ImageCodecInfo>();
}
if (_encoders.Count == 0)
{
foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders())
{
_encoders.Add(codec.MimeType.ToLower(), codec);
}
}
return _encoders;
}
}
Then you can try saving with your favorite encoder or get the bytes
public static void Save(string path, Image img, string mimeType)
{
using (var ms = File.OpenWrite(path))
{
ImageCodecInfo encoder = GetEncoderInfo(mimeType);
img.Save(ms, encoder, null);
}
}
2) Sometimes i had problems saving indexed images. Have a look to yourImage.PixelFormat and try converting image to a different one if needed.
User contributions licensed under CC BY-SA 3.0