2017-10-16 56 views
-2

저는 비트 맵에 이미지를 저장합니다. 내 개체의 크기를 조정할 때 이미지의 크기도 조정해야합니다. 이미지 크기를 원하는 크기로 조정하는 함수를 만들었습니다.C#에서 드로잉의 메모리 비용 절감

이미지의 크기를 절대적으로 조정해야하는 경우에만이 함수를 호출하지만이 이미지의 크기와 관련하여 지속적으로 메모리 비용이 50MB에서 1GB 이상으로 빠르게 이동합니다. 이 메서드는 마우스 버튼을 누르고있을 때마다 밀리 초마다 호출되어야합니다.

Graphicsusing에 있는데,이 경우에는 거의 도움이되지 않습니다. GC.Collect(2)을 호출하면 도움이되지만 GUI가 상당히 느려지고 비 차단으로 설정하면 전혀 도움이되지 않습니다.

이 함수의 마지막 인스턴스에서 여전히 사용되지 않는 메모리를 확보 할 수있는 방법이 있습니까? 아니면 코드를 변경하고 다른 방식으로 변경해야합니까? 더 나은 방법이 있다면 GDI가 누설되거나 내 방법이 매우 비효율적으로 보이기 때문에 도움을 주시면 감사하겠습니다.

MY CODE : 기본 폼

public int getWidth() 
{ 
    return width; 
} 

public int getHeight() 
{ 
    return height; 
} 

public void createScaledImage() 
{ 
    var cr = new c_returnGraphicSettings(); 
    if (getWidth() > 20 && getHeight() > 20) 
    { 
     scaledImage = new Bitmap(getWidth(), getHeight()); 
     using (Graphics g = Graphics.FromImage(scaledImage)) 
     { 
      /* 
      g.InterpolationMode = cr.getIM(); 
      g.PixelOffsetMode = cr.getPOM(); 
      g.SmoothingMode = cr.getSM(); 
      /*--*/ 

      g.DrawImage(image, new Rectangle(new Point(0, 0), scaledImage.Size), new Rectangle(new Point(0, 0), image.Size), GraphicsUnit.Pixel); 
      g.Dispose(); 
     } 

     //GC.Collect(2, GCCollectionMode.Forced, true); 

    } 
} 

public Bitmap getScaledImage() 
{ 
    //createScaledImage(); 
    return scaledImage; 
} 

public void resizeImage() 
{ 
    if(image != null) 
    { 
     createScaledImage(); 
    } 
} 

CODE :

protected override void OnPaint(PaintEventArgs e) 
{ 
    base.OnPaint(e); 

    //TODO: PAINT!! 
    organizeImageList(); 
    foreach (c_ImageHolder c in Limages) 
    { 
     if (c != null) 
     { 
      e.Graphics.DrawImage(c.getScaledImage(), c.Position); 
      ... 
     } 
    } 
} 


private void f_Screen_MouseDown(object sender, MouseEventArgs e) 
{ 
    Limages.Sort(new intComparerDesc()); 
    foreach (c_ImageHolder c in Limages) 
    { 
     if (renhan.pointInPosition(e.Location, new Rectangle(c.Position, c.Size))) 
     { 
      c.select(); 
      selectedImage = c; 
      imageDragPoint = new Point(e.X - c.Left, e.Y - c.Top); 
      if (!c.isOverAnEdge(imageDragPoint) && !c.isOverACorner(imageDragPoint)) 
      { 
       resize = false; 
       cResizer = null; 
       ed = edges.none; 
       cor = corners.none; 
      } 
      else 
      { 
       resize = true; 
       cResizer = c; 
       if (c.isOverAnEdge(imageDragPoint)) 
       { 
        ed = c.overWhichEdge(imageDragPoint); 
        cor = corners.none; 
       } 
       else 
       { 
        cor = c.overWhichCorner(imageDragPoint); 
        ed = edges.none; 
       } 
      } 
      mdown = true; 
      break; 
     } 
    } 
    Invalidate(); 
} 

enter image description here


설명 :

은 내가가 만든 클래스를 사용하고 있습니다 저장하다 비트 맵 이미지를 크기 및 위치에 대한 데이터로 변환 한 다음이 클래스의 인스턴스를 저장하는 화면에 이미지를 그립니다.

투명성 문제로 인해이 컨트롤 (그림 상자 등)을 사용하지 않습니다.

각 인스턴스에는 다른 이미지가 포함되어 있습니다. 또한 이러한 이미지의 크기를 조정할 수 있어야합니다. 이러한 이유로 원래 비트 맵의 ​​크기가 조정 된 버전을 저장하는 두 번째 비트 맵이 있습니다.

다른 크기의 이미지를 저장하기 위해 다른 비트 맵을 사용하여 다시 크기를 조정해야하지만 이미 수정 된 이미지의 크기는 원래의 크기로 조정하지 않았습니다. (품질 유지)

크기 조정은 다음과 같이 처리됩니다. 이미지의 가장자리 위로 마우스 버튼을 누르고 있습니다. 크기를 조정할 때마다 버튼을 누르고있는 동안 마우스를 움직이는 동안 클래스는 원본 이미지를 새로운 크기로 늘리는 새로운 이미지를 생성합니다. 그 이미지는 무효화 된 메인 화면으로 돌아가고, 페인트 칠 때 화면의 배경 위에 새 이미지가 그려집니다.

배경에 이미지를 그릴 필요가 있기 때문에 문제를 해결할 수 없습니다. 나는 사본을 만들고 원본을 처분 할 수 있지만, 그 시점에서 나는 똑같은 문제가 있다고 생각한다.

마우스 버튼을 누른 상태에서 이미지를 계속해서 다시 그리는 동안 메모리가 빠르게 급증합니다. 다 끝나면 처분 할 수 있지만 이미지를 오랫동안 크기 조정하면 프로그램이 중단 될 수 있습니다.아래는 RAR 파일 보관함에 저장 내 데모 프로그램에 대한 링크가 Video and link to program

있다 : 당신은 모두 여기에서 찾을 수있는 짧은 비디오뿐만 아니라 내 문제를 보여주는 작은 훨씬 더 간단한 프로그램을 만들었습니다

비디오.

이 설명과 동영상/데모가 내 문제를 더 잘 설명하는 데 도움이되기를 바랍니다.

도움을 주려고하는 모든 사용자에게 감사드립니다.

+1

왼쪽이나 오른쪽으로 물건이 누출됩니다. 오래된 비트 맵에서'Dispose()'를 호출하십시오. 그리고'using'은 이미'g'에'Dispose()'를 호출합니다. 직접 손으로 할 필요는 없습니다. 코드가 정확하다면'GC.Collect() '를 전혀 호출 할 필요가 없다. – xxbbcc

+0

결과는 어떻게됩니까? (분명히) 더 작은 이미지를위한 * 새로운 * 비트 맵을 생성하고 있으므로, 어떤 시점 ('image'와'scaledImage')에서 처분 할 총 이미지가 2 개가됩니다. – Plutonix

+1

왜 수동으로 비트 맵의 ​​크기를 조정합니까? 보기에서 컨트롤이 크기 조절을하도록하고, 마우스를 놓은 후에 크기 조정을 완료하면 새 비트 맵을 생성하고 저장합니다. –

답변

0

도움을 주신 모든 분들께 감사드립니다. 나는 어디서 잘못되었는지 깨달았다.

컨트롤에서 이미지를 관리 할 때 원래 코드에서 함수를 유지했습니다.

새 코드를 사용하면 크기 조정을 새 Bitmap에 쓰지 않고 관리 할 수있었습니다.

5 명이 왜 나에게 똑같은 말을했는지 이해하지 못했습니다.

다시 감사드립니다.