3

다음 코드를 사용하여 이미지를 축소판으로 FlowLayoutPanel 컨트롤에로드합니다. 불행히도 OutOfMemory 예외가 발생합니다.이미지로드 중 메모리 부족 예외

당신은 이미 메모리 누수가

Pedit.Image = System.Drawing.Image.FromStream(fs) 

그래서 내가 어떻게 다음 코드를 최적화 할 수있는 선에서 발견되는 생각으로?

Private Sub LoadImagesCommon(ByVal FlowPanel As FlowLayoutPanel, ByVal fi As FileInfo) 
     Pedit = New DevExpress.XtraEditors.PictureEdit 
     Pedit.Width = txtIconsWidth.EditValue 
     Pedit.Height = Pedit.Width/(4/3) 
     Dim fs As System.IO.FileStream 
     fs = New System.IO.FileStream(fi.FullName, IO.FileMode.Open, IO.FileAccess.Read) 
     Pedit.Image = System.Drawing.Image.FromStream(fs) 
     fs.Close() 
     fs.Dispose() 
     Pedit.Properties.SizeMode = DevExpress.XtraEditors.Controls.PictureSizeMode.Zoom 

     If FlowPanel Is flowR Then 
      AddHandler Pedit.MouseClick, AddressOf Pedit_MouseClick 
      AddHandler Pedit.MouseEnter, AddressOf Pedit_MouseEnter 
      AddHandler Pedit.MouseLeave, AddressOf Pedit_MouseLeave 
     End If 

     FlowPanel.Controls.Add(Pedit) 
    End Sub 

업데이트 : 이미지의 수를로드하는 동안 문제가 발생합니다 (300DPI에서 3264x2448px을 - 각각의 이미지가 3MB의에 관한 것입니다)

+0

이 모든 불필요한 코드를 제거하고 이미지를로드 만 시도하여 문제를 분리 봤어 :

여기 내 방법입니까? 로드 된 이미지를 '정상'이미지 디스플레이 컨트롤에 할당하려고 했습니까? –

+1

하나의 이미지를로드 할 때 또는 많은 이미지를로드 할 때 메모리가 부족합니까? 이미지를로드하려고 할 때 특정 이미지가 문제를 일으키는 지 아니면 실패합니까? 이미지가 예외적으로 큽니까? 제발, 더 자세한 내용이나 우리가 할 수있는 최선은 추측입니다. –

+0

@ 짐.안녕하세요, 업데이트를 확인해 주시겠습니까? – OrElse

답변

3

당신은 몇 단계에서이 문제를 해결 할 수 있습니다

  • 이 파일 종속성에서 무료로 얻을, 당신은 이미지를 복사해야합니다. 실제로 그것을 새로운 Bitmap으로 그리면 그냥 복사 할 수 없습니다.
  • 축소판을 원하고 원본 비트 맵이 크기 때문에 이미지를 축소하는 데 결합하십시오.
+0

을로드하는 텍스트 파일을 가지고 있었고 세 번째 관련 질문을 게시 할 준비가되었습니다 ... "ACDSee"유형의 프로그램이 어떻게 관리합니까? – OrElse

+0

@chocol : ACDsee 등이 미리보기 이미지를 만들고 나머지는 주문형 (load-on-demand)이라고 생각합니다. –

5

문서 (당신의 FromStream 관련이있다) Image.FromFile 위해이 그것이 것 말한다 파일이 유효한 이미지 형식이 아니거나 GDI +가 픽셀 형식을 지원하지 않는 경우 OutOfMemoryException을 반환합니다. 지원되지 않는 이미지 유형을로드하려고 할 가능성이 있습니까?

Image.FromStream에 대한 설명서에 따르면 이미지 수명 동안 스트림을 열어 두어야하므로 코드가 이미지를로드하더라도 이미지가 표시되는 동안 파일을 닫을 때 오류가 발생할 수 있습니다. 여전히 활성화되어 있습니다. http://msdn.microsoft.com/en-us/library/93z9ee4x.aspx을 참조하십시오. 생각의

+0

+1 - 나는 – blak3r

3

커플 :

우선은 MSDN 페이지에서 언급으로 스트림이 이미지의 수명을 위하여 개방한다 Image.FromStream 사용할 때 짐은 주장했다한다. 따라서 파일의 내용을 MemoryStream으로 복사하고 후자를 사용하여 Image 인스턴스를 만드는 것이 좋습니다. 따라서 파일 핸들을 가능한 빨리 풀 수 있습니다.

두 번째로, 사용중인 이미지는 다소 크기가 크므로 압축되지 않은 상태 여야합니다 (너비 x 높이 x BytesPerPixel). 사용하는 컨텍스트가 크기가 작을 수 있다고 가정하면 크기 조정을 고려하고 잠재적으로 나중에 사용하기 위해 크기가 조정 된 버전을 캐싱 할 수 있습니다.

마지막으로 이미지와 스트림이 더 이상 필요하지 않을 때 폐기하는 것을 잊지 마십시오.

0

나는 동일한 문제가있었습니다. Jim Mischel의 대답으로 인해 무고한 .txt 파일을로드하는 것이 원인이었습니다. 누군가가 관심이있는 경우를 대비하여 내 방법이 있습니다.

/// <summary> 
/// Loads every image from the folder specified as param. 
/// </summary> 
/// <param name="pDirectory">Path to the directory from which you want to load images. 
/// NOTE: this method will throws exceptions if the argument causes 
/// <code>Directory.GetFiles(path)</code> to throw an exception.</param> 
/// <returns>An ImageList, if no files are found, it'll be empty (not null).</returns> 
public static ImageList InitImageListFromDirectory(string pDirectory) 
{ 
    ImageList imageList = new ImageList(); 

    foreach (string f in System.IO.Directory.GetFiles(pDirectory)) 
    { 
     try 
     { 
      Image img = Image.FromFile(f); 
      imageList.Images.Add(img); 
     } 
     catch 
     { 
      // Out of Memory Exceptions are thrown in Image.FromFile if you pass in a non-image file. 
     } 
    } 

    return imageList; 
}