2016-12-17 16 views
2

Visual StudioのC#プロジェクトで作業しています。私はパワーポイントアドインに多数のボタンを作成しています。これらのボタンのそれぞれは、パワーポイントプレゼンテーションのライブラリからのスライドから作成されたイメージを持っています。ボタンの数が450を超えると、メモリ不足の例外が発生しても常にクラッシュします。c#大量の画像を読み込む際にメモリ不足の例外が発生する

私は問題を調査し、メモリを解放するために何かを処分する必要があることを理解しています。私はこれを行う方法については明確ではない。

これはイメージを作成するために使用しているコードです。各イメージは作成時にボタンに追加されます。これは、行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に' 任意の助けいただければ幸いです。

EDIT:

ここで私は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); 
} 

EDIT: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; 
    } 
+0

'Bitmap'オブジェクトは、' IDisposable'あります。それらも処分していますか? – Enigmativity

+0

同じイメージを2つ作成するのはなぜですか? 1つだけを使用してください。 –

+0

アレクサンダー、私は2つの同一の画像を作成しません、すべての画像が異なります。 – kwibbler

答えて

2

あなたがもし(IMGに(

  • CreateNonIndexedImage
  • resizeImage内の各画像の3つのインスタンスを作成します。幅> maxWidth))
  • resizeImage((img.Height>のmaxHeight)の場合で)

あなたはリサイズ後に古いイメージを処分することができるし、その後

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

ありがとう!この解決方法と上記の解決方法は、この問題を解決するのに役立ちました。 – kwibbler

0

以下のようにIMG変数に問題を新しいインスタンスを設定しました。内部resizeImage。

  1. 私はわからないんだけど、これはXAML/WPF環境であれば、あなたが戻ってディスクへの最終的な画像を保存して、あなたのボタン与えるべき
  2. を返す前にresizeImage目的球内部のimgパラメータを処分WPFはメモリに表示されている画像のみを読み込みます。 (サイズ変更されたイメージがまだ存在しない場合にのみ、サイズを変更したイメージをロードして保存する必要があります)。
  3. また、描画操作が1つ必要です。現在は3つあります。これはCPUを節約します。[1]メモリの問題。あなたはそれを理解できるはずです。

更新されたコード:

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; 
} 
+0

ありがとうございます。このソリューション(および以下のソリューション)は、この問題を解決するのに役立ちました。 – kwibbler

関連する問題