将图像保存到 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 仅代表一大块托管内存,因此依靠垃圾收集器进行清理是安全的。一个好的经验法则是始终处理一次性对象,但是当您知道该对象仅拥有托管资源(如内存)时,这就不那么重要了。