사용자가 임의로 디자인을 변경할 수 있도록 스킨 형태의 인터페이스를 제공해야 하는 경우에는 내장된 리소스가 아니라 외부 이미지를 가져다 사용하는 것이 일반적이며 이미지를 보는 프로그램을 개발해야 하는 경우 당연히 출력 대상은 이미지 파일이 된다. GDI+ 에서는 외부 이미지 파일을 처리하려고 Image 클래스와 파생 클래스인 Bitmap 클래스를 제공하며 기본적으로 이미지를 로드하거나 저장할 때는 Image 클래스 객체를 사용하고, 이미지 프로세싱 같은 추가 기능이 필요하면 Bitmap 클래스 객체를 사용한다. 또한 다른 Image 클래스의 파생 클래스로 MetaFile 클래스가 있으며 WMF 파일이나 EMF 파일을 손쉽게 처리할 수 있다.



Image 클래스

GDI+ 의 Image 클래스는 외부 이미지 파일을 로드하여 처리하는 기본(base) 클래스이며 이와 비슷한 클래스로 CImage 클래스가 있는데 이 두 클래스가 지원하는 메서드는 상당부분 유사하다. 두 클래스는 결과적으로 같은 처리 루틴을 갖기 때문일 것이며 다음 코드는 Image클래스를 이용하여 JPG 파일을 로드 및 출력하는 예이다.

void CGdiPlusDemoView::OnPaint()
{
 CPaintDC dc(this); // device context for painting
 Graphics graphics(dc);
 graphics.SetSmoothingMode(SmoothingModeAntiAlias);

 Image Image(_T("Test.jpg"));
 
 Point pts[] ={
  Point(200,0), //왼쪽위
  Point(Image.GetWidth(),0), //오른쪽위
  Point(0,Image.GetHeight()) //왼쪽아래
 };

 graphics.DrawImage(&Image, pts, 3); //세 개의 좌표로 이미지를 출력하라 즉 평행사변형

 

}

Bitmap 클래스

Image클래스의 파생 클래스로 외부 파일을 로드하는 기능 외에 비트맵 핸들(HBITMAP)이나 아이콘 핸들(HICON)에 대한 비트맵 이미지를 생성하고 관리하는 기능을 제공하는데, 만일 외부 파일이 아니라 프로젝트에 등록된 비트맵 리소스를 로드하여 화면에 출력할 때 Bitmap 클래스를 활용하면 편리하다. 다음은 Bitmap 클래스를 이용해 출력하는 예이다.

void CGdiPlusDemoView::OnPaint()
{
 CPaintDC dc(this); // device context for painting

 Graphics graphics(dc);
 graphics.SetSmoothingMode(SmoothingModeAntiAlias);

 Bitmap bmp(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_Test));
 graphics.DrawImage(&bmp, 10,10);

 

}


CachedBitmap 클래스

JPG든 GIF파일이든 화면에 출력될 때는 모두 BMP 파일이 되며, 좀더 정확히는 장치에 의존적인 비트맵이라고 할 수 있다. 다만 장치 의존적인 비트맵으로 출력한다는 말은 출력을 위해서 비트맵 이미지의 변환 ( DIB -> DDB ) 과정이 필요하다는 것을 의미한다. 이는 Image 클래스의 파생 클래스인 Bitmap 클래스가 빠른 이미지 처리를 위해서 이미지 캐싱(Caching)을 지원하기 때문이다.

GDI 에서의 전형적인 이미지 출력 과정은 CBitmap 클래스 객체를 생성하여 비트맵 이미지(DIB)를 로드하고 화면 DC에 호환되는 메모리 DC를 만들어 SelectObject() 한 다음 BitBlt() 같은 함수를 이용해 화면 DC로(DDB) 출력한다. 이 과정에서 비트맵 이미지의 변환이 이루어지며 만일 같은 비트맵을 여러번 출력한다면 이 과정은 불필요하게 된다. 이런 불필요한 연산을 최적화하는 것이 비트맵 캐싱이며, CachedBitmap 클래스로 이 기능을 구현한다. 비트맵 캐싱이란 출력할 비트맵을 DDB로 변환해서 보관! 하는 것을 의미하며 따라서 화면에 출력할 때 별도의 변환 과정없이 화면 출력이 가능하므로 훨씬 효율적이다.
다음은 CachedBitmap 클래스를 이용해 이미지를 출력하면서 코드수행시간을 측정한 예이다. 약 3배정도의 차이가 난다.


void CGdiPlusDemoView::OnPaint()
{
 CPaintDC dc(this); // device context for painting
 Graphics graphics(dc);
 graphics.SetSmoothingMode(SmoothingModeAntiAlias);


 Bitmap bmp(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_Test2));
 CachedBitmap cachedbmp(&bmp, &graphics);

 /*코드 수행시간 계산코드*/
 CString strTmp=_T("");
 LARGE_INTEGER InFreq, InStart, InEnd, InResult;
 ::QueryPerformanceFrequency(&InFreq);

 ::QueryPerformanceCounter(&InStart);
 graphics.DrawImage(&bmp, 10,10);
 ::QueryPerformanceCounter(&InEnd);

 InResult.QuadPart = (InEnd.QuadPart - InStart.QuadPart) * 1000000 / InFreq.QuadPart;
 strTmp.Format(_T("DrawImage() Counter %u "), InResult.QuadPart);
 dc.TextOut(10,10,strTmp);

 ::QueryPerformanceCounter(&InStart);
 graphics.DrawCachedBitmap(&cachedbmp, bmp.GetWidth() + 20 , 10);
 ::QueryPerformanceCounter(&InEnd);

 InResult.QuadPart = (InEnd.QuadPart - InStart.QuadPart) * 1000000 / InFreq.QuadPart;
 strTmp.Format(_T("Drawcachedbitmap() Counter %u "), InResult.QuadPart);
 dc.TextOut(bmp.GetWidth() + 20 ,10,strTmp);
 
 


}


















 

+ Recent posts