C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 강좌/문서
C++Builder Programming Tutorial&Docments
[144] [GR32] 회전(Rotate) , 반전(Flip) 기능
이정구 [appleii] 16854 읽음    2007-10-01 21:02
이번에는 그림을 회전하고 반전해서 저장하는 기법을 알아봅시다.

Graphics32 에서는 그림을 회전시키는 방법을 4가지로 제공합니다.

1. 90도 회전 procedure Rotate90(Dst: TBitmap32);
2. 180도 회전  procedure Rotate180(Dst: TBitmap32);
3. 270도 회전  procedure Rotate270(Dst: TBitmap32);
4. AffineTransformation 회전 procedure Rotate(Cx, Cy, Alpha: Single);


4번은 임의의 각으로 회전이 가능합니다.

이번 강좌에서는 90도 회전과 270도 회전만 이용합니다.

반전 방법은 수직 반전(FlipVert) 수평반전(FlipHorz) 의 두 가지 방법을 제공합니다.

1. procedure FlipHorz(Dst: TBitmap32);
2. procedure FlipVert(Dst: TBitmap32);


그럼 이 기능을 어떻게 구현할 것인가. 기본 아이디어는 다음과 같습니다.

1. 회전기능을 가지는 폼을 화면에 보여준다.
2. 폼 생성시 임시 TBitmap32 를 생성한다.
3. 임시로 생성한 TBitmap32 를 회전시킨 후 ImgPreview 에 복사한다.
4. ImgPreview 에 회전시킨 이미지가 보여진다.


회전기능을 위한 폼은 다음과 같습니다.



Rotate 메뉴의 이벤트 핸들러는 다음과 같습니다.

void __fastcall TMainForm::Rotate1Click(TObject *Sender)
{
  UndoBitmap32->Assign(ImgView321->Bitmap); //이전의 이미지를 저장
 
  RotateForm->ImgPreview->Bitmap->Assign(MainForm->ImgView321->Bitmap);
  RotateForm->ShowModal();
 
  if(RotateForm->ModalResult == mrOk) //OK 버튼을 누르면
  {
    ImgView321->Bitmap->Assign(RotateForm->ImgPreview->Bitmap);
  }    
}


UndoBitmap32 는 회전을 실행하기 전에 현재의 이미지를 저장하는 것입니다.
RotateForm 에서 미리보기 기능을 제공하는 ImgView32 컴포넌트의 Bitmap 에 MainForm 의
ImgView32 의 Bitmap을 복사합니다. ShowModal 하면 ImgPreview 에 나타납니다.

마찬가지 원리로 OK 버튼을 누르면 앞에서와 반대로 ImgView321 의 Bitmap에 ImgPreview 의
Bitmap 을 복사합니다.

그럼 , Undo 는 어떻게 구현할까요?

TBitmap32* UndoBitmap32;
UndoBitmap32 = new TBitmap32;

void __fastcall TMainForm::Undo1Click(TObject *Sender)
{
  ImgView321->Bitmap->Assign(UndoBitmap32);
}


TBitmap32 객체를 하나 만들고, 회전을 시키기 전에 Bitmap 을 복사한 후 Undo 를 클릭하면
UndoBitmap32 의 Bitmap 을 ImgView321 의 Bitmap 에 복사하는 것입니다. 
복잡해 보이지만 의외로 쉽게 구현이 됩니다. Undo 가 여러번 되도록 할 수도 있겠지만 일단은
간단하게 구현하는 것이 목표입니다.

그럼 , 가장 중요한 Rotate 기능은 어떻게 구현할까요?
한가지 조심해야 할 것이 있습니다. 저도 꽤나 고민했던 부분입니다. Bitmap 을 그냥 돌리면
안됩니다.

TBitmap32* ImgTemp;
ImgTemp = new TBitmap32();

void __fastcall TRotateForm::btnRotatePlusClick(TObject *Sender)
{
  ImgTemp->Assign(ImgPreview->Bitmap);
  ImgTemp->Rotate90(ImgPreview->Bitmap);
}


임시로 사용할 TBitmap32 객체를 만들고 ImgPreview 의 Bitmap 을 복사하고, ImgTemp 를
Rotate 시켜서 ImgPreview 의 Bitmap 에 보냅니다. 처음에는 ImgPreview 의 Bitmap 을 Rotate 시키면
될 줄 알았는데 원하는 대로 동작하지 않더군요. 예제가 많으면 참고라도 하겠는데 생각보다
많지가 않습니다. 직접 해보면서 익히는 수밖에 없습니다.

그럼 , jpg 저장은 어떻게 할까요?

이것또한 문제가 많습니다. Graphics32 는 왜 32일까요? 그것은 PixelFormat 을 32bit 로 처리하기 때문입니다.
무조건 32bit 로 처리하므로 효율이 좋아서 속도가 향상됩니다. 하지만 jpg 에서는 32bit 를 지원하지
않습니다. 빌더에서 제공하는 Jpeg 유닛에서는 8bit, 24bit 를 지원합니다. 따라서 TBitmap32 의
이미지를 Jpeg 객체에 직접 Assign 하면 에러가 납니다. Graphics32 에서는 PixelFormat 을
바꿀 수가 없습니다. 이것을 가지고 또 고민을 많이 했습니다. jpg 로 저장하는 예제가 없어서
직접 해보면서 할 수 밖에 없습니다. 뉴스그룹을 찾아서 간신히 힌트를 얻는데 성공했습니다.
뉴스그룹에서도 Tutorial 이 없는것에 불만이 많더군요. 결론은 직접해보라는 것뿐...

해결 방법은 TBitmap 객체를 만들어서 TBitmap32 객체의 이미지를 복사하는 것입니다.
TBitmap 의 이미지는 Jpeg 객체에 Assign 할 수 있습니다. 그 뒤에는 SaveToFile 하면 됩니다.

jpg 저장에 대해서 다음을 참고해 보세요.
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_faq&no=47

void __fastcall TMainForm::Save1Click(TObject *Sender)
{
  if(ImgView321->Bitmap->Empty() == true) return; //그림이 없으면 저장하지 않음

  Graphics::TBitmap* ImgTemp = new Graphics::TBitmap();
  TJPEGImage* jp = new TJPEGImage();

  try
  {
    ImgTemp->Assign(ImgView321->Bitmap);
    jp->CompressionQuality = 100; //Quality 100%
    jp->Assign(ImgTemp);
    jp->SaveToFile(ImgFileName);
  }
  __finally
  {
    delete jp;
    delete ImgTemp;
  }
}


완성되면 다음과 같이 됩니다.

김태선 [cppbuilder]   2007-10-01 21:20 X
기다리던 멋진 강좌군요.
고맙습니다. ^^
장성호 [nasilso]   2007-10-02 09:02 X
늘깔금한 이정구님의 강좌!
감사하구요
계속해서 G32강좌가 이어지길 기대합니다.

...

나도 얼렁 G32를 좀 써봐야 할텐데..
맨날 TBitmap만 가지고 놀고 있으니....
이정구 [appleii]   2007-10-02 16:22 X
꾸준히 보아주시는 분들이 계셔서 다행이네요. 감사합니다.

그나저나 Rotate270 함수에 버그가 있네요. Dst.EndUpdate; 가 없습니다. 어쩐지 이상하더라니.. 다음 버전에서 수정하겠다고 합니다. 

... 언제 나오려나?
이용태 [kidary97]   2007-10-27 20:35 X
GR32... 전 비트맵에 픽셀을 찍거나 FillRect을 이용하여 원하는 영역에 색칠할 경우 쓰는데요... 속도가 ㄷㄷㄷ 합니다.. 빌더에서 제공하는 TBitmap하곤 속도를 비교할 수 없습니다. 제가 이 GR32를 알게 된게 얼마나 다행인지 모릅니다.

+ -

관련 글 리스트
144 [GR32] 회전(Rotate) , 반전(Flip) 기능 이정구 16854 2007/10/01
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.