c#加载大量图像时内存不足异常

时间:2016-12-17 08:03:44

标签: c# visual-studio powerpoint

我正在开发一个Visual Studio c#项目。我在powerpoint插件中创建了大量按钮,每个按钮都有一个从powerpoint演示文稿库中的幻灯片创建的图像。当按钮数量超过450时,它总会因内存不足异常而崩溃。

我已经研究过这个问题并且明白我需要在某个地方处理某些东西才能释放一些内存。我不清楚如何做到这一点。

这是我用来创建图像的代码,每个图像都会在创建时添加到按钮中。它崩溃在canvas canvas.DrawImageUnscaled(sourceImage,0,0);

public static Image CreateNonIndexedImage(string path)
    {
        using (var sourceImage = Image.FromFile(path))
        {
            var targetImage = new Bitmap(sourceImage.Width, sourceImage.Height,
              PixelFormat.Format32bppArgb);
            using (var canvas = Graphics.FromImage(targetImage))
            {
                canvas.DrawImageUnscaled(sourceImage, 0, 0);
            }
            return targetImage;
        }
    }

抛出异常:System.Drawing.dll中的'System.OutOfMemoryException'

非常感谢任何帮助。

编辑:

以下是我使用CreateNonIndexedImage的代码,然后调整图像大小并将其添加到按钮中。

for (int i = 0; i < numThumbs; i++)
{
                    Image img = CreateNonIndexedImage(ThumbsPath + thumbsList[i].Name);

                    int newHeight = maxHeight;
                    int newWidth = maxWidth;

                    if (img.Width > maxWidth)
                    {
                        float ratio = (float)img.Width / maxWidth;
                        float h = img.Height / ratio;
                        newHeight = (int)h;

                        img = resizeImage(img, new Size(maxWidth, newHeight));
                    }

                    if (img.Height > maxHeight)
                    {
                        float ratio = (float)img.Height / maxHeight;
                        float w = img.Width / ratio;
                        newWidth = (int)w;

                        img = resizeImage(img, new Size(newWidth, newHeight));
                    }

                    int bW = (img.Width + 20) > minWidth ? img.Width + 20 : minWidth;

                    //CREATE BUTTON FOR SLIDE
                    Button b = new Button();
                    b.AccessibleName = thumbsList[i].Name;
                    b.Text = slideTitle;
                    b.TextAlign = ContentAlignment.BottomCenter;
                    b.Image = img;
                    b.Width = bW;
                    b.Height = img.Height + 40;
                    b.ImageAlign = ContentAlignment.TopCenter;
                    b.BackColor = Color.AliceBlue;
                    b.Click += SlideButton_Click;
                    flowLayoutPanel1.Controls.Add(b);
}

编辑:

resizeImage的源代码:

private static Image resizeImage(Image imgToResize, Size size)
    {
        int sourceWidth = imgToResize.Width;
        int sourceHeight = imgToResize.Height;

        float nPercent = 0;
        float nPercentW = 0;
        float nPercentH = 0;

        nPercentW = ((float)size.Width / (float)sourceWidth);
        nPercentH = ((float)size.Height / (float)sourceHeight);

        if (nPercentH < nPercentW)
            nPercent = nPercentH;
        else
            nPercent = nPercentW;

        int destWidth = (int)(sourceWidth * nPercent);
        int destHeight = (int)(sourceHeight * nPercent);

        Bitmap b = new Bitmap(destWidth, destHeight);
        Graphics g = Graphics.FromImage((Image)b);
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;

        g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
        g.Dispose();

        return (Image)b;
    }

2 个答案:

答案 0 :(得分:2)

中创建每个图像的三个实例
  • CreateNonIndexedImage
  • resizeImage(在if(img.Width&gt; maxWidth)中)
  • resizeImage(在if(img.Height&gt; maxHeight)中)

您可以在调整大小后处理旧图像,然后将新实例设置为img变量,如下所示

var newImg = resizeImage(img, new Size(maxWidth, newHeight));
img.Dispose();
img = newImg;

答案 1 :(得分:0)

问题出在resizeImage里面。

  1. 在返回
  2. 之前将img参数置于resizeImage功能中
  3. 我不确定,但如果这是一个XAML / WPF环境,你应该将最终图像保存回磁盘,并为你的按钮提供文件参考,然后WPF只会将显示的图像加载到内存中。 (只有在调整后的版本尚不存在的情况下,才应加载并保存已调整大小的图像。)
  4. 另外,你只需要一个绘图操作,你现在有3个 - 这将节省CPU,[1]将解决内存问题。你应该能够解决这个问题。
  5. 更新的代码:

    private static Image resizeImage(Image imgToResize, Size size)
    {
        int sourceWidth = imgToResize.Width;
        int sourceHeight = imgToResize.Height;
    
        float nPercent = 0;
        float nPercentW = 0;
        float nPercentH = 0;
    
        nPercentW = ((float)size.Width / (float)sourceWidth);
        nPercentH = ((float)size.Height / (float)sourceHeight);
    
        if (nPercentH < nPercentW)
            nPercent = nPercentH;
        else
            nPercent = nPercentW;
    
        int destWidth = (int)(sourceWidth * nPercent);
        int destHeight = (int)(sourceHeight * nPercent);
    
        Bitmap b = new Bitmap(destWidth, destHeight);
        Graphics g = Graphics.FromImage((Image)b);
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    
        g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
        g.Dispose();
    
        imgToResize.Dispose(); //IMPORTANT CHANGE HERE
    
        return (Image)b;
    }