답변 감사합니다.
몇가지 질문할 게 더 있어서 질문드립니다.. ㅠㅠ
일단 C++로 다 옮기는데는 성공했습니다만 회전한 이미지가 아얘 나타나질 않습니다.
일단
[1] SetColor32에서 맨 마지막의 Move가 어떤 작업을 수행하는 건지 알고 싶습니다.
(제 나름대로 해석해서 코딩했습니다만 결국 *pd에 대해서 나온 결과를 쓰질 않는 것 같습니다..)
[2] (...) div 2 는 (...)를 2로 나눈다는 뜻(즉, (...)/2와 같은 뜻)인가요?
[3] 델파이에서 High(x)가 x의 할당 개수를 의미하는게 맞나요?? (#define으로 정의해 버렸습니다만...)
[4] 이 밖에 함수 선언이 올바르게 되었는지 알고 싶습니다.. 어떤 거는 function이고 어떤거는 procedure이던데 procedure가 return(즉 result를 적는 코드)이 없어 그냥 void로 처리해 버렸습니다. 맞는지 확인해 주시면 감사하겠습니다.. ㅠㅠ
아래는 변환해 본 소스 코드입니다.. 감사합니다.
ps. 157번째 줄부터 제대로 안나오네요... 157번쨰 줄~FormDestroy 부분은 여기다 올리겠습니다...
for (iy = dstR.Top; iy<dstR.Bottom; iy++) {
for (ix = dstR.Left; ix<dstR.Right; ix++) {
pt = Point(ix, iy);
pt = RotatePoint(-sn, cs, Xc, Yc, pt);
if (!PtInRct(pt, srcR)) continue;
SetColor32(dst, ix+Xofs, iy+Yofs, GetColor32(src, pt.x, pt.y));
}
}
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
srcbmp = new Graphics::TBitmap;
srcbmp->PixelFormat = pf32bit;
srcbmp->Width = 300;
srcbmp->Height = 300;
srcbmp->LoadFromFile("C:\\Test.bmp");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete srcbmp;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include
#include
#pragma hdrstop
#include "Unit1.h"
#define pi 3.141592
#define High(x) ( sizeof((x)) / sizeof((x)[0]) )
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
TRGBQuad __fastcall GetColor32(Graphics::TBitmap *bmp,int x,int y)
{
TRGBQuad * ps;
ps = (TRGBQuad *)bmp->ScanLine[y];
ps=ps+x;
return *ps;
}
void SetColor32(Graphics::TBitmap *bmp, int x, int y, TColor color)
{
TRGBQuad c;
COLORREF k;
TRGBQuad * pd; // PRGBQuad
k = ColorToRGB(color);
c.rgbBlue = GetBValue(k);
c.rgbGreen = GetGValue(k);
c.rgbRed = GetRValue(k);
c.rgbReserved = 0;
pd = (TRGBQuad *)bmp->ScanLine[y];
pd = pd+x;
*pd = c; //Move(c,pd^,SizeOf(TRGBQuad));
}
void SetColor32(Graphics::TBitmap *bmp, int x, int y, const TRGBQuad rgbq)
{
TRGBQuad * pd;
pd = (TRGBQuad *)bmp->ScanLine[y];
pd = pd + x;
*pd = rgbq; // Move(rgbq,pd^,SizeOf(TRGBQuad));
}
TRect GetBoundRect(const TPoint pts[])
{
int i, Xmax, Xmin, Ymax, Ymin;
Xmax = pts[0].x; Xmin = pts[0].x;
Ymax = pts[0].y; Ymin = pts[0].y;
for (i=1; i<=High(pts); i++) {
if (pts[i].x > Xmax) Xmax = pts[i].x;
if (pts[i].x < Xmin) Xmin = pts[i].x;
if (pts[i].y > Ymax) Ymax = pts[i].y;
if (pts[i].y < Ymin) Ymin = pts[i].y;
}
return Rect(Xmin, Ymin, Xmax, Ymax);
}
TPoint RotatePoint(const double sn, const double cs, int Xc, int Yc, TPoint pt)
{
TPoint tmppt;
tmppt.x = (Xc+cs*(pt.x-Xc)-sn*(pt.y-Yc))+0.5;
tmppt.y = (Yc+sn*(pt.x-Xc)+cs*(pt.y-Yc))+0.5;
return tmppt;
}
TPoint RotatePoint(double deg, int Xc, int Yc, TPoint pt)
{
double sn, cs;
sn = sin(pi*deg/180);
cs = cos(pi*deg/180);
TPoint tmppt;
tmppt.x = (Xc+cs*(pt.x-Xc)-sn*(pt.y-Yc))+0.5;
tmppt.y = (Yc+sn*(pt.x-Xc)+cs*(pt.y-Yc))+0.5;
return tmppt;
}
void OffsetPoints(TPoint pt[], int dx, int dy)
{
int i;
for (i=0; i<=High(pt); i++) {
pt[i] = Point(pt[i].x+dx, pt[i].y+dy);
}
}
bool PtInRct(const TPoint pt, const TRect r)
{
return ((pt.x >= r.Left) && (pt.x < r.Right) &&
(pt.y >= r.Top) && (pt.y < r.Bottom));
}
void RotatePoints(double deg, TPoint pts[])
{
int i, Xc, Yc;
TRect r;
Double sn, cs;
r = GetBoundRect(pts);
Xc = (r.Left + r.Right) / 2;
Yc = (r.Top + r.Bottom) / 2;
sn = sin(pi*deg/180);
cs = cos(pi*deg/180);
for (i=0; i<=High(pts); i++) {
pts[i] = RotatePoint(sn, cs, Xc, Yc, pts[i]);
}
}
//--------------------------------------------------------
void RotateBMP32(double deg, Graphics::TBitmap *src, Graphics::TBitmap *dst, TColor bkColor)
{
TRect srcR, dstR;
TPoint pts[3];
int Xofs, Yofs, w, h;
int ix, iy, Xc, Yc;
TPoint pt;
double sn, cs;
srcR = Rect(0, 0, src->Width, src->Height);
Xc = src->Width / 2;
Yc = src->Height / 2;
pts[0] = Point(0, 0);
pts[1] = Point(src->Width, 0);
pts[2] = Point(src->Width, src->Height);
pts[3] = Point(0, src->Height);
RotatePoints(deg, pts);
dstR = GetBoundRect(pts);
Xofs = -dstR.Left;
Yofs = -dstR.Top;
w = dstR.Right - dstR.Left;
h = dstR.Bottom - dstR.Top;
dst->PixelFormat = pf32bit;
dst->Width = w;
dst->Height = h;
dst->Canvas->Brush->Color = bkColor;
dst->Canvas->FillRect(Rect(0, 0, w, h));
sn = sin(pi*deg/180);
cs = cos(pi*deg/180);
for (iy = dstR.Top; iyPixelFormat = pf32bit;
srcbmp->Width = 300;
srcbmp->Height = 300;
srcbmp->LoadFromFile("C:\\Test.bmp");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete srcbmp;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Graphics::TBitmap * bmp;
bmp = new Graphics::TBitmap;
Canvas->Draw(5, 5, srcbmp);
RotateBMP32(-35, srcbmp, bmp, clRed);
bmp->TransparentColor = clRed;
bmp->Transparent = true;
Canvas->Draw(300, 300, bmp);
delete bmp;
}
//---------------------------------------------------------------------------
장성호 님이 쓰신 글 :
: Object-Pascal의 꺽쇄(^)는 C++의 포인터(*)와 같습니다.
:
:
: function GetColor32(bmp:TBitmap; x,y:integer):TRGBQuad;
: var
: ps:PRGBQuad; //TRGBQuad * 형 ps선언
: begin
: ps := bmp.Scanline[y]; //y번째 줄의 시작 포인터 가져옴
: Inc(ps,x); //x만큼 포인터를 이동
: Move(ps^,result,SizeOf(TRGBQuad)); // 포인터의 값을 result에 복사
: end;
: //Object-Pascal의 function에서는 Result가 return값이 됩니다.
:
:
: 위 함수를 C++로 바꾸면
:
: TRGBQuad __fastcall GetColor32(Graphics::TBitmap *bmp,int x,int y)
: {
: TRGBQuad * ps;
: ps = (TRGBQuad *)bmp->ScanLine[y];
: ps=ps+x;
: return *ps;
: }
:
: 뭐 대충 위와 같이 하면 될것 같습니다.
:
:
: 그리고 pascal에서 overload 라고 되어있는것은
: C++에서는 함수 overload를 기본 지원하는것이니 빼도 됩니다.
:
: override란 함수이름은 같구 파라메터가 다른경우에 해당하는것입니다.
:
: 그리고 image 회전을 할때
: 기본적으로 Graphic32 에서도 90도의 배수만 지원하는걸로 알고 있습니다.
:
: 다른 각도는 직접 구현하셔야 합니다.
: 정확히 대칭되는 pixcel이 없기때문에 보간법을 이용하여 구현하곤 합니다.
:
: 님께서 찾은 delphi코드가 아무각도에서는 이미지가 회전되는 코드입니다.
:
: 델마당에 조무영님의 비dx강좌링크에 delphi로 된 image회전이 나와있습니다.
:
http://www.delmadang.com/community/bbs_view.asp?bbsNo=29&bbsCat=0&st=S&keyword=%uBE44DX&indx=198680&keyword1=비DX&keyword2=&page=2
:
:
: 그럼...
:
: 위 함수는
: ant 님이 쓰신 글 :
: : 안녕하세요.
: : 다름아니라 TImage를 회전하려고 찾다가 아래 소스를 발견했는데요..
: : pascal이라서 c++로 옮기려다 난해한 부분들이 있어서 질문 드립니다.
: :
: : [1] 아래에서 예를들어
: : function GetColor32(bmp:TBitmap; x,y:integer):TRGBQuad;
: : var
: : ps:PRGBQuad;
: : begin
: : ps := bmp.Scanline[y];
: : Inc(ps,x);
: : Move(ps^,result,SizeOf(TRGBQuad));
: : end;
: :
: : 이게 return값이 뭔지, ps^에서 ^가 가리키는게 뭔지 등등... 잘 모르겠습니다 ㅠㅠ;;
: : C++이랑 비슷한 것 같으면서도 고치기가 많이 힘드네요.. ㅠㅠ
: :
: : 그리고
: : [2] 어떤 함수는 옆에 overload; 이렇게 되어 있는데 이것도 c++로 어떻게 바꿔야 하는지 등등
: : 자세히 알려주시면 감사하겠습니다.. ㅠㅠ
: :
: : ps. Graphic32는 이미지 위의 이미지가 투명 처리가 안되더군요... 게다가 저는 rotate를 90도, 180도, 270도 등 뿐만 아니라 특정 각도까지 구현해야 되는 상황인데, Graphic32에는 Rotate90, Rotate180, Rotate270밖에 없었습니다...
: :
: : 출처는
http://blog.livedoor.jp/junki560/archives/19004116.html 이구요
: : 아래는 전체 소스코드 입니다...
: :
: :
: : unit Main;
: :
: : interface
: :
: : uses
: : Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
: : Dialogs, StdCtrls;
: :
: : type
: : TForm1 = class(TForm)
: : Button1: TButton;
: : procedure FormCreate(Sender: TObject);
: : procedure FormDestroy(Sender: TObject);
: : procedure Button1Click(Sender: TObject);
: : private
: : { Private 宣言 }
: : public
: : srcbmp:TBitmap;
: : end;
: :
: : var
: : Form1: TForm1;
: :
: : implementation
: :
: : {$R *.dfm}
: :
: : uses
: : Jpeg;
: :
: : function GetColor32(bmp:TBitmap; x,y:integer):TRGBQuad;
: : var
: : ps:PRGBQuad;
: : begin
: : ps := bmp.Scanline[y];
: : Inc(ps,x);
: : Move(ps^,result,SizeOf(TRGBQuad));
: : end;
: :
: : procedure SetColor32(bmp:TBitmap; x,y:integer; color:TColor);overload;
: : var
: : c:TRGBQuad;
: : k:COLORREF;
: : pd:PRGBQuad;
: : begin
: : k := ColorToRGB(color);
: : c.rgbBlue := GetBValue(k);
: : c.rgbGreen := GetGValue(k);
: : c.rgbRed := GetRValue(k);
: : c.rgbReserved := 0;
: : pd := bmp.Scanline[y];
: : Inc(pd,x);
: : Move(c,pd^,SizeOf(TRGBQuad));
: : end;
: :
: : procedure SetColor32(bmp:TBitmap; x,y:integer;const rgbq:TRGBQuad);overload;
: : var
: : pd:PRGBQuad;
: : begin
: : pd := bmp.Scanline[y];
: : Inc(pd,x);
: : Move(rgbq,pd^,SizeOf(TRGBQuad));
: : end;
: :
: : function GetBoundRect(const pts:array of TPoint):TRect;
: : var
: : i,Xmax,Xmin,Ymax,Ymin:integer;
: : begin
: : Xmax := pts[0].X; Xmin := pts[0].X;
: : Ymax := pts[0].Y; Ymin := pts[0].Y;
: : for i := 1 to High(pts) do
: : begin
: : if pts[i].X > Xmax then Xmax := pts[i].X;
: : if pts[i].X < Xmin then Xmin := pts[i].X;
: : if pts[i].Y > Ymax then Ymax := pts[i].Y;
: : if pts[i].Y < Ymin then Ymin := pts[i].Y;
: : end;
: : result := Rect(Xmin,Ymin,Xmax,Ymax);
: : end;
: :
: : function RotatePoint(const sn,cs:Double;Xc,Yc:integer;pt:TPoint):TPoint;overload;
: : begin
: : result.X := Round(Xc+cs*(pt.X-Xc)-sn*(pt.Y-Yc));
: : result.Y := Round(Yc+sn*(pt.X-Xc)+cs*(pt.Y-Yc));
: : end;
: :
: : function RotatePoint(deg:Double;Xc,Yc:integer;pt:TPoint):TPoint;overload;
: : var
: : sn,cs:Double;
: : begin
: : sn := sin(pi*deg/180);
: : cs := cos(pi*deg/180);
: :
: : result.X := Round(Xc+cs*(pt.X-Xc)-sn*(pt.Y-Yc));
: : result.Y := Round(Yc+sn*(pt.X-Xc)+cs*(pt.Y-Yc));
: : end;
: :
: : procedure OffsetPoints(var pt:array of TPoint;dx,dy:integer);
: : var
: : i:integer;
: : begin
: : for i := 0 to High(pt) do
: : pt[i] := Point(pt[i].X+dx,pt[i].Y+dy)
: : end;
: :
: : function PtInRct(const pt:TPoint; const r:TRect):Boolean;
: : begin
: : result := (pt.X>=r.Left) and (pt.X<r.Right) and
: : (pt.Y>=r.Top) and (pt.Y<r.Bottom);
: : end;
: :
: : procedure RotatePoints(deg:Double ;var pts:array of TPoint);
: : var
: : i,Xc,Yc:integer;
: : r:TRect;
: : sn,cs:Double;
: : begin
: : r := GetBoundRect(pts);
: :
: : Xc := (r.Left+r.Right) div 2;
: : Yc := (r.Top+r.Bottom) div 2;
: :
: : sn := sin(pi*deg/180);
: : cs := cos(pi*deg/180);
: :
: : for i := 0 to High(pts) do
: : pts[i] := RotatePoint(sn,cs,Xc,Yc,pts[i]);
: : end;
: :
: : //--------------------------------------------------------
: :
: : procedure RotateBMP32(deg:Double; src,dst:TBitmap; bkColor:TColor);
: : var
: : srcR,dstR:TRect;
: : pts:array[0..3] of TPoint;
: : Xofs,Yofs,w,h:integer;
: : ix,iy,Xc,Yc:integer;
: : pt:TPoint;
: : sn,cs:Double;
: : begin
: : srcR := Rect(0,0,src.Width,src.Height);
: : Xc := src.Width div 2;
: : Yc := src.Height div 2;
: :
: : pts[0] := Point(0,0);
: : pts[1] := Point(src.Width,0);
: : pts[2] := Point(src.Width,src.Height);
: : pts[3] := Point(0,src.Height);
: :
: : RotatePoints(deg,pts);
: : dstR := GetBoundRect(pts);
: : Xofs := -dstR.Left;
: : Yofs := -dstR.Top;
: : w := dstR.Right-dstR.Left;
: : h := dstR.Bottom-dstR.Top;
: :
: : dst.PixelFormat := pf32bit;
: : dst.Width := w;
: : dst.Height := h;
: : dst.Canvas.Brush.Color := bkColor;
: : dst.Canvas.FillRect(Rect(0,0,w,h));
: :
: : sn := sin(pi*deg/180);
: : cs := cos(pi*deg/180);
: :
: : for iy := dstR.Top to dstR.Bottom-1 do
: : for ix := dstR.Left to dstR.Right-1 do
: : begin
: : pt := Point(ix,iy);
: : pt := RotatePoint(-sn,cs,Xc,Yc,pt);
: : if not PtInRct(pt,srcR) then continue;
: : SetColor32(dst,ix+Xofs,iy+Yofs,GetColor32(src,pt.X,pt.Y));
: : end;
: : end;
: :
: : procedure TForm1.FormCreate(Sender: TObject);
: : var
: : jpg:TJpegImage;
: : begin
: : srcbmp := TBitmap.Create;
: : jpg := TJpegImage.Create;
: : try
: : jpg.LoadFromFile(ExtractFilePath(ParamStr(0))+'Test.jpg');
: : srcbmp.PixelFormat := pf32bit;
: : srcbmp.Width := jpg.Width;
: : srcbmp.Height := jpg.Height;
: : srcbmp.Canvas.Draw(0,0,jpg);
: : finally
: : jpg.Free;
: : end;
: : end;
: :
: : procedure TForm1.FormDestroy(Sender: TObject);
: : begin
: : srcbmp.Free;
: : end;
: :
: : procedure TForm1.Button1Click(Sender: TObject);
: : var
: : bmp:TBitmap;
: : begin
: : bmp := TBitmap.Create;
: : try
: : Canvas.Draw(5,5,srcbmp);
: : RotateBMP32(-35,srcbmp,bmp,clRed);
: : bmp.TransparentColor := clRed;
: : bmp.Transparent := true;
: : Canvas.Draw(5,srcbmp.Height+10,bmp);
: : finally
: : bmp.Free;
: : end;
: : end;
: :
: : end.
: :