将图像保存到 MemoryStream 时 GDI+ 中出现一般错误
A generic error occurred in GDI+ while saving image to MemoryStream
您好,我在尝试将 JPEG 文件保存到内存流时遇到以下异常 'System.Runtime.InteropServices.ExternalException at System.Drawing.Image.Save'。
images = new List<Bitmap>(seriesDataList.Count());
foreach (var seriesData in seriesDataList)
{
using (chart = new Chart { Width = ChartWidth, Height = ChartHeight })
{
chart.ChartAreas.Add(new ChartArea(seriesData.Key));
var series = new Series(seriesData.Key)
{
ChartType = SeriesChartType.Doughnut,
Font = ChartTextFont,
LegendText = "#VALX (#PERCENT)",
};
BindSeriesData(seriesData.ToList(), series);
series["PieLabelStyle"] = seriesData.Count() <= MaxValuesForShowingLabels ? "Outside" : "Disabled";
series["PieLineColor"] = "Black";
chart.Series.Add(series);
var legend = new Legend(seriesData.Key)
{
Enabled = true,
Font = ChartTextFont,
Docking = Docking.Right,
Title = seriesData.Key,
TitleFont = ChartTitleFont,
TitleAlignment = StringAlignment.Near
};
chart.Legends.Add(legend);
using (var memoryStream = new MemoryStream())
{
chart.SaveImage(memoryStream, ChartImageFormat.Jpeg); // Working fine
images.Add(new Bitmap(memoryStream));
}
}
}
using (var fullImage = MergeImages(images))
{
using (var memoryStream = new MemoryStream())
{
fullImage.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Jpeg); // ERROR HERE
return Convert.ToBase64String(memoryStream.ToArray());
}
}
在其他情况下,不是从许多图像构建完整图像的情况下,流程是有效的。仅此图像类型失败率低。
看到其他相关问题建议用 'using' 包装 memoryStream,我已经在做。
有什么建议吗?
正如 Klaus Gütter 在评论中提到的,您不能在位图之前处理流。
解决此问题的一个选项是 return 位图的 clone,这应确保所有 pixel-data 都复制到单独的缓冲区,从而允许原始流获得自由。
using var bmp = new Bitmap(memoryStream);
images.Add(bmp.Clone(new Rectangle(0,0, bmp.Width, bmp.Height), PixelFormat.Format32bppArgb);
另一种选择可能是不处理内存流。由于 MemoryStream 仅代表一大块托管内存,因此依靠垃圾收集器进行清理是安全的。一个好的经验法则是始终处理一次性对象,但是当您知道该对象仅拥有托管资源(如内存)时,这就不那么重要了。
您好,我在尝试将 JPEG 文件保存到内存流时遇到以下异常 'System.Runtime.InteropServices.ExternalException at System.Drawing.Image.Save'。
images = new List<Bitmap>(seriesDataList.Count());
foreach (var seriesData in seriesDataList)
{
using (chart = new Chart { Width = ChartWidth, Height = ChartHeight })
{
chart.ChartAreas.Add(new ChartArea(seriesData.Key));
var series = new Series(seriesData.Key)
{
ChartType = SeriesChartType.Doughnut,
Font = ChartTextFont,
LegendText = "#VALX (#PERCENT)",
};
BindSeriesData(seriesData.ToList(), series);
series["PieLabelStyle"] = seriesData.Count() <= MaxValuesForShowingLabels ? "Outside" : "Disabled";
series["PieLineColor"] = "Black";
chart.Series.Add(series);
var legend = new Legend(seriesData.Key)
{
Enabled = true,
Font = ChartTextFont,
Docking = Docking.Right,
Title = seriesData.Key,
TitleFont = ChartTitleFont,
TitleAlignment = StringAlignment.Near
};
chart.Legends.Add(legend);
using (var memoryStream = new MemoryStream())
{
chart.SaveImage(memoryStream, ChartImageFormat.Jpeg); // Working fine
images.Add(new Bitmap(memoryStream));
}
}
}
using (var fullImage = MergeImages(images))
{
using (var memoryStream = new MemoryStream())
{
fullImage.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Jpeg); // ERROR HERE
return Convert.ToBase64String(memoryStream.ToArray());
}
}
在其他情况下,不是从许多图像构建完整图像的情况下,流程是有效的。仅此图像类型失败率低。 看到其他相关问题建议用 'using' 包装 memoryStream,我已经在做。
有什么建议吗?
正如 Klaus Gütter 在评论中提到的,您不能在位图之前处理流。
解决此问题的一个选项是 return 位图的 clone,这应确保所有 pixel-data 都复制到单独的缓冲区,从而允许原始流获得自由。
using var bmp = new Bitmap(memoryStream);
images.Add(bmp.Clone(new Rectangle(0,0, bmp.Width, bmp.Height), PixelFormat.Format32bppArgb);
另一种选择可能是不处理内存流。由于 MemoryStream 仅代表一大块托管内存,因此依靠垃圾收集器进行清理是安全的。一个好的经验法则是始终处理一次性对象,但是当您知道该对象仅拥有托管资源(如内存)时,这就不那么重要了。