我有一个WebAPI端点(在IIS中托管),它从数据库(字节数组)读取图像并以PNG格式返回它们。这段代码很简单:
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;
}
我有三个网络服务器,其中一个上面的代码导致此错误:A generic error occurred in GDI+.
位于at System.Drawing.Image.Save()
。
服务器正在运行不同的操作系统版本:
我更改了上面的代码以返回JPEG而不是PNG,并解决了这个问题。
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
我必须发送PNG图像,所以我需要找到根本原因。
我将代码转换为使用WPF类(System.Windows.Media)而不是Windows Form类。结果很有趣:我在创建PNG时也出错了。这次错误在The component registration is invalid. (Exception from HRESULT: 0x88982F8A)
System.Windows.Media.Imaging.BitmapEncoder.SaveFrame()
可能是我的服务器缺少保存PNG所需的低级组件吗?
由于
@Chris Pratt要求查看从字节数组创建图像的代码。 WebAPI代码和SqlDataReader调用之间有几个层,但这里是转换从数据库读取的字节数组的代码。
/// <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);
}
}
}
答案 0 :(得分:1)
System.Drawing 命名空间在处理图像方面有很多已知的缺点。请参阅 this article 的详细解释。
在处理此命名空间时,您必须非常小心处理内存流、位图等。您的问题听起来似乎与这些一次性对象有关。
也就是说,一个不错的选择是使用 ImageSharp library,它可以很好地处理从字节数组中读取图像并将其保存为 png。
您可以使用 Image.Load method:
var img = Image.Load(ImageHelper.ReadFromDatabaseAsByteArray());
和 save it as png 到 MemoryStream 以供进一步使用:
using (var memStream = new MemoryStream())
{
image.SaveAsPng(memStream);
// Do something with the memStream, for example prepare http response
}
答案 1 :(得分:0)
1).NET框架&gt; = 3.0应该有一个内置编码器。检查是否有适合图像mime类型的编码器。
public static ImageCodecInfo GetEncoderInfo(string mimeType)
{
string lookupKey = mimeType.ToLower();
ImageCodecInfo foundCodec = null;
if (Encoders.ContainsKey(lookupKey))
{
foundCodec = Encoders[lookupKey];
}
return foundCodec;
}
(您需要查找编码器)
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;
}
}
然后您可以尝试使用您喜欢的编码器保存或获取字节
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)有时我在保存索引图像时遇到问题。看看 yourImage.PixelFormat 并尝试在需要时将图片转换为其他图片。