2013-08-05 2 views
0

디렉토리를 사용하고 새로운 "resizedDirectory"(존재하지 않는 경우)를 만들고, 모든 .bmp를 크기 조정 한 다음 " resizedDirectory ". 이것은 내가 (일부 지역을 위해 인터넷을 사용)과 같은 기능을 작성한 것은 이번이 처음이다, 여기에 코드입니다 :ASP/C#, 새로운 비트 맵() "메모리 부족"

protected void directorySelected(object sender, EventArgs e) { 
    // Make sure the directory exists 
    if (Directory.Exists(inputDirectory.Text)) { 
     string[] filePaths = Directory.GetFiles(inputDirectory.Text); 

     // Determine if there are any files in inputDirectory 
     if (filePaths.Length == 0) messageLog.InnerHtml = "<strong>No files found in:</strong> "+inputDirectory.Text; 
     else { 
      // Determine if "resizedDirectory" exists, create it if it does not exist 
      string resizedDirectory = inputDirectory.Text+"\\"+"resizedDirectory"; 
      if (!Directory.Exists(resizedDirectory)) { 
       Directory.CreateDirectory(resizedDirectory); 
       messageLog.InnerHtml = "<strong>Created:</strong> "+resizedDirectory+"<br/><br/>"; 
      } 

      // For each file in inputDirectory... 
      for (var i = 0; i < filePaths.Length; i++) { 
       string[] extensionSplit = filePaths[i].Split('.'); 

       // Make sure filePath[i] ends with the appropriate extension 
       if (extensionSplit.Length == 2 && extensionSplit[1].Equals("bmp")) { 
        Bitmap currImage = new Bitmap(filePaths[i]); 
        messageLog.InnerHtml += "<strong>"+i.ToString()+":</strong> "+filePaths[i]+"<br/><div class='indent'>"; 

        // Calculate new dimensions 
        int newWidth = maxWidth; 
        int newHeight = maxHeight; 
        if (currImage.Width > currImage.Height) newHeight = (int)(((float)maxWidth)/((float)currImage.Width)*currImage.Height); 
        else newWidth = (int)(((float)maxHeight)/((float)currImage.Height)*currImage.Width); 
        messageLog.InnerHtml += "<strong>Old dimensions:</strong> ("+currImage.Width+","+currImage.Height+")<br/><strong>New dimensions:</strong> ("+newWidth+", "+newHeight+")<br/>"; 

        // Settings before saving 
        Bitmap targetImage = new Bitmap(newWidth, newHeight); 
        using (Graphics g = Graphics.FromImage(targetImage)) { 
         g.CompositingQuality = CompositingQuality.HighQuality; 
         g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
         g.SmoothingMode = SmoothingMode.HighQuality; 
         g.DrawImage(currImage, 0, 0, newWidth, newHeight); 
        } 
        ImageCodecInfo ici = this.GetEncoderInfo(ImageFormat.Bmp); 
        Encoder eq = Encoder.Quality; 
        EncoderParameters eps = new EncoderParameters(1); 
        EncoderParameter ep = new EncoderParameter(eq, 100L); // 100L is the higest quality (goes from 0 - 100) 
        eps.Param[0] = ep; 

        // Save image 
        string targetPath = resizedDirectory+"\\foo"+i.ToString()+".bmp"; 
        targetImage.Save(targetPath, ici, eps); 
        messageLog.InnerHtml += "<strong>Saved:</strong> "+targetPath+"</div><br/>"; 
       } 
       else messageLog.InnerHtml += "<strong>IGNORED "+i.ToString()+":</strong> "+filePaths[i]+"<br/>"; 
      } 
     } 
    } 
    else if (inputDirectory.Text.Equals("")) messageLog.InnerHtml = "<strong>No directory specified</strong>"; 
    else messageLog.InnerHtml = "<strong>Cannot find:</strong> "+inputDirectory.Text; 
} 

protected ImageCodecInfo GetEncoderInfo(ImageFormat format) { 
    return ImageCodecInfo.GetImageDecoders().SingleOrDefault(c => c.FormatID == format.Guid); 
} 

이 작은 .bmps로 괜찮 았는데. 문제는 변환해야 할 .bmp 파일의 디렉토리가 크기 때문에 예제 .bmp는 16073 x 13231 (또는 608MB)입니다. 작은 .bmp와 거대한 .bmp 중 하나를 사용하여 코드를 시도하고 "resizedDirectory"를 작성하여 작은 크기의 새 크기 조정 .bmp를 만든 다음 "메모리 부족"메시지와 함께 충돌합니다.

거대한 .bmps의 크기를 조정하려면 어떻게해야합니까?

편집 : 그것은 하나의 거대한 .BMP에 실패 (하지만 작은 것들에)

+0

제발 다시 태그 질문 :이 ... 그것은 하나의 거대한 .BMP에 실패 –

답변

1

먼저, 하나의 비트 맵 코드를 테스트합니다. 크기는 크지 만 프로그램에서 한 번에 하나씩 처리 할 수 ​​있으므로 작업을 수행하는 데 많은 시간을 할애 할 필요가 없습니다. (하나의 방대한 이미지에 대해 작동하지 않는다면, 내장 된 .net 클래스보다 다른 이미지 로딩 또는 프로세싱 라이브러리를 찾아야합니다.)

하나의 이미지에서는 작동하지만 그런 다음 다음 비트 맵을로드하기 전에 한 비트 맵에서 사용하는 모든 메모리를 해제해야합니다. 근본적으로 비트 맵 처리 (루프 끝 부분에서)를 사용하면 사용중인 메모리를 해제 한 후 currImage.Dispose();으로 호출해야합니다.

그러나이 달성의 적절한 방법은 (예외가 발생하더라도) 자동으로 Dispose를 호출해야하는 using 블록 내부의 처리 코드를 작성하는 것입니다

using (Bitmap currImage = new Bitmap(filePaths[i])) 
{ 
    // Process the bitmap here 
} 
당신이 필요합니다

targetImage가 작성된 후에도 처분되는지 여부를 확인하기 위해 targetImage와 유사한 작업을 수행하십시오.

이렇게하면 비트 맵에서 사용하는 모든 메모리가 처리를 마자 즉시 해제되므로 다음 비트 맵에서 사용할 수 있습니다.

+0

하지 "ASP 클래식"입니다, 내 질문을 업데이 트 – asimes

0

모든 GDI + 리소스를 처리해야합니다. 문제는 USING 문이 Graphics 객체를 처리하지 않는다는 것입니다. 그것은 나 자신 : 나는 많은 시간을 만들었 실수입니다

http://msdn.microsoft.com/en-us/library/system.drawing.graphics.dispose.aspx

g.Dispose(); 
+0

하나의 거대한. bmp에서 실패, 내 질문을 업데이 트 – asimes

+0

이것은 innacurate입니다. 사용의 요점은 범위를 벗어날 때 객체를 처분한다는 것입니다 – ghostbust555

관련 문제