훈, IT 공부/C,C++,MFC

C++, Gdiplus 사용하여 png 생성하기

IT훈이 2018. 9. 9.
반응형

GDI+ 활용

 

회사에서 워터마크 관련하여 작업하는 중에 GDI+를 찾게 되었고, 이걸 이용해서 문제를 해결하였다. 

 

#include<Gdiplus.h>
using  namespace Gdiplus;

우선 Gdiplus를 사용하기 위해서는 헤더파일을 먼저 선언 해주어야한다.

 

 

▶ Gdiplus png 이미지파일 생성하기 

// GDI+ 을 사용하기위한 설정
    GdiplusInit gdiplusinit;
    ULONG_PTR gpToken;
    GdiplusStartupInput gpsi;
 
    if(GdiplusStartup(&gpToken, &gpsi, NULL) != Ok)
    {
        TRACE(_T("Do Not GDI+ initizlize!"));
        return ;
    }
 
    //GDI+ 폰트 생성
    REAL rSize = 30;
    Gdiplus::Font gdiFont(_T("Arial"),rSize, FontStyleBold, Gdiplus::UnitPixel);
                          // 폰트이름, 글꼴크기 ,Unit이 지정한 단위 사용, 
    
    //GDI+ Graphics 생성
    Graphics gFontWidth( GetDC(NULL) );
 
    // 문자열 크기 저장
    TCHAR szWaterMark[1024] = _T("administrator/192.168.*.*/Park-PC/SOFTWARE");
    RectF rbound;
    gFontWidth.MeasureString(szWaterMark, -1, &gdiFont, PointF(0,0), &rbound);            // Measure 뜻은 측정하다, 법안
 
    // png 생성을 위한 비트맵 생성
    Bitmap bitmap( (int)rbound.Width, (int)rbound.Height, PixelFormat32bppARGB);    
    Graphics graphics_mark( &bitmap);
 
    // 폰트의 각도설정
    REAL rAngle = 0;
    graphics_mark.RotateTransform(rAngle);
 
    // 부드러움 모드 설정
    graphics_mark.SetSmoothingMode(SmoothingModeAntiAlias);
 
    // 텍스트의 브러쉬 설정
    SolidBrush sBrush(Color(255,0,0,0));
 
    // 텍스트 그리기
    PointF ptText(0, 0);
    graphics_mark.DrawString(szWaterMark, -1, &gdiFont, ptText, &sBrush);
 
    CLSID pngClsid;
    int result = GetEncoderClsid( L"image/png", &pngClsid );
    if ( result == -1 )
    {
        TRACE("Encoder Error!!");
        return ;
    }    
    bitmap.Save( L"C:\\test\\test.png", &pngClsid, NULL );
 
    GdiplusShutdown(gpToken);

 

GdiplusStartupInput(), GdiplusShutdown()

//함수원형
Status GdiplusStartup(
  OUT ULONG_PTR             *token,
  const GdiplusStartupInput *input,
  OUT GdiplusStartupOutput  *output
);

void GdiplusShutdown(
  ULONG_PTR token
);

2행 ~10행, 52행을 보면 GdiplusStartupInput(), GdiplusShutdown() 함수가 있다. 이 두 함수GDI+를 초기에 사용하고 해제하기 위해서 사용된다. 프로그램을 끝낼 때 반드시 GdiplusShutdown함수를 호출하여 GDI+라이브러리를 셧다운 하여야한다. GDI+는 실행중에 많은 리소스를 할당하는데 이 리소스를 반드시 해제해야한다. 

 GdiplusStartupInput() 함수의 인자 output은 초기화 결과를 돌려 주기 위한 구조체 인데, 필요없을 경우 NULL로 주어도 된다. Status형의 열거형으로 리턴하는데, 성공했을 경우 Ok가 리턴된다. Ok가 아닌 경우에는 GDI+를 사용할 수 없으므로 적절한 에러처리가 필요한다.

struct GdiplusInit {
    GdiplusInit() {
        GdiplusStartupInput inp;
        GdiplusStartupOutput outp;
        if ( Ok != GdiplusStartup( &token_, &inp, &outp ) )
        {}
    }
    ~GdiplusInit() {
        GdiplusShutdown( token_ );
    }
private:
    ULONG_PTR token_;
};

 

2행 ~ 10행, 52행을 이런식으로 미리 코딩하여 사용할 수도 있다.

 

Gdiplus::Font

//함수원형
Font(
  [in]  const WCHAR *familyName,
  [in]  REAL emSize,
  [in]  INT style,
  [in]  Unit unit,
  [in]  const FontCollection *fontCollection
);

14행에서 생성한 폰트이다. 생성자 종류는 8개가 있는데, 그 중에서 사용한 생성 방식이다. 

파라미터로는 순서대로 폰트이름, 폰트사이즈, 폰트스타일, Unit이 지정할 단위, 사용자 정의폰트

 

Gdiplus::MeasureString

//함수원형
Status MeasureString(
  [in]       const WCHAR *string,
  [in]       INT length,
  [in]       const Font *font,
  [in, ref]  const RectF &layoutRect,
  [out]      RectF *boundingBox
) const;

//The Graphics::MeasureString method measures the extent of the string in the specified font and layout rectangle

23행에서 사용된 함수이다. 이 함수는 문자열에 관한 정보를 측정하는 기능을한다. 지정된 글꼴을 직사각형에서의 문자열 범위를 측정한다. 

문자열을 DC상에 그려낼때 크기가 필요하기에 사용된다.

 

 

GetEncoderClisid() 

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
   UINT  num = 0;          // number of image encoders
   UINT  size = 0;         // size of the image encoder array in bytes
 
   ImageCodecInfo* pImageCodecInfo = NULL;
 
   GetImageEncodersSize(&num, &size);
   if(size == 0)
      return -1;  // Failure
 
   pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
   if(pImageCodecInfo == NULL)
      return -1;  // Failure
 
   GetImageEncoders(num, size, pImageCodecInfo);
 
   for(UINT j = 0; j < num; ++j)
   {
      if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
      {
         *pClsid = pImageCodecInfo[j].Clsid;
         free(pImageCodecInfo);
         return j;  // Success
      }    
   }
 
   free(pImageCodecInfo);
   return -1;  // Failure
}

 44행 GetEncoderClisid함수는 API함수가 아닌 사용자가 정의한 함수를 호출한 것이다.

 

 

 

 

 

 

 

 

반응형

댓글