여기에서는 출력 픽셀을 입력 이미지로 매핑시키게 됩니다. 이것을 사용해 이미지의 회전을 부드럽게 할 수 있습니다.
원점 (0, 0)을 기준으로 점(x, y)를 Theta 각도만큼 회전시키려 한다면, 결과값(x', y')은 다음과 같습니다.
x' = x * cos(theta) + y * sin(theta)
y' = -x * sin(theta) + y * cos(theta)
theta에 대해 반대방향으로 회전 할 경우의 각도는 -theta입니다. 즉, 출력 픽셀을 입력 위치로 매핑시키기 위해서는 회전 된 반대 방향으로 같은 각도만큼 돌리면 될 것이며, 이렇게 하기 위해서는 -theta를 사용하면 됩니다. 만약, 출력 픽셀이 (x', y')이라면 그에 대한 입력 픽셀(x, y)는 다음과 같습니다.
x = x' * Cos(-theta) + y' * Sin(-theta)
y = -x' * Sin(-theta) + y' * Cos(-theta)
여기에서 Sin(-theta)는 -Sin(theta)이고 Cos(-theta)는 Cos(theta)와 같으므로,
x = x' * Cos(theta) - y' * Sin(theta)
y = x' * Sin(theta) + y' * Cos(theta)
의 공식을 사용해 프로그램에서 이미지를 회전시킬 수 가 있습니다.
출력 이미지의 각 픽셀에 대해서, 프로그램은 출력 픽셀에 매핑되는 입력 이미지내의 점을 찾기 위해 위의 공식을 사용합니다.
이 코드에서는 위에 설명했던것과는 조금 다르게 이미지 왼쪽 상단 모서리가 아닌, 이미지의 중심을 기준으로 해서 회전을 시킵니다. 그렇기 때문에, 계산이 진행되기 전에 출력 픽셀의 위치로부터 (to_cx, to_cy)값이 빼졌고, 결과에 (from_cx, from_cy)가 더해졌습니다.
마지막으로, 회전을 할 경우에 고려해야할 사항이 하나 더 있습니다.
회전이 되면 원본 이미지보다 바깥쪽으로 모서리가 벗어날 수 있어서 짤리게 됩니다. 180' 회전이 아니면, 거의 항상 그렇죠? 그래서, GetRotateSize라는 프로시져를 이용해 출력될 이미지의 높이와 너비를 계산하게 됩니다. 아래에 그 공식이 나와 있습니다.
> Timage component에서 이미지회전이 가능한가요..가능하면 방법좀 갈쳐주세요??
> 그럼 수고하세요
>
하이염..~~
넘 바빠서..
오랫만에.. 오는 군요...^^
아~ 옛날이여~
안녕하셔요~
델세상(http://www.freechal.com/delphiworld)의 조규춘입니다.
이미지 회전에 관한 거 적어 놓구 갈꼐용~
여기에서는 출력 픽셀을 입력 이미지로 매핑시키게 됩니다. 이것을 사용해 이미지의 회전을 부드럽게 할 수 있습니다.
원점 (0, 0)을 기준으로 점(x, y)를 Theta 각도만큼 회전시키려 한다면, 결과값(x', y')은 다음과 같습니다.
x' = x * cos(theta) + y * sin(theta)
y' = -x * sin(theta) + y * cos(theta)
theta에 대해 반대방향으로 회전 할 경우의 각도는 -theta입니다. 즉, 출력 픽셀을 입력 위치로 매핑시키기 위해서는 회전 된 반대 방향으로 같은 각도만큼 돌리면 될 것이며, 이렇게 하기 위해서는 -theta를 사용하면 됩니다. 만약, 출력 픽셀이 (x', y')이라면 그에 대한 입력 픽셀(x, y)는 다음과 같습니다.
x = x' * Cos(-theta) + y' * Sin(-theta)
y = -x' * Sin(-theta) + y' * Cos(-theta)
여기에서 Sin(-theta)는 -Sin(theta)이고 Cos(-theta)는 Cos(theta)와 같으므로,
x = x' * Cos(theta) - y' * Sin(theta)
y = x' * Sin(theta) + y' * Cos(theta)
의 공식을 사용해 프로그램에서 이미지를 회전시킬 수 가 있습니다.
출력 이미지의 각 픽셀에 대해서, 프로그램은 출력 픽셀에 매핑되는 입력 이미지내의 점을 찾기 위해 위의 공식을 사용합니다.
이 코드에서는 위에 설명했던것과는 조금 다르게 이미지 왼쪽 상단 모서리가 아닌, 이미지의 중심을 기준으로 해서 회전을 시킵니다. 그렇기 때문에, 계산이 진행되기 전에 출력 픽셀의 위치로부터 (to_cx, to_cy)값이 빼졌고, 결과에 (from_cx, from_cy)가 더해졌습니다.
마지막으로, 회전을 할 경우에 고려해야할 사항이 하나 더 있습니다.
회전이 되면 원본 이미지보다 바깥쪽으로 모서리가 벗어날 수 있어서 짤리게 됩니다. 180' 회전이 아니면, 거의 항상 그렇죠? 그래서, GetRotateSize라는 프로시져를 이용해 출력될 이미지의 높이와 너비를 계산하게 됩니다. 아래에 그 공식이 나와 있습니다.
new_width = Round(Abs(old_width * Cos(theta)) + Abs(old_height * Sin(theta)));
new_height = Round(Abs(old_width * Sin(theta)) + Abs(old_height * Cos(theta)));
음냐..... 너무 어렵지요 ^^
그래서 위의 공식을 코딩으로 하자면...
이렇게 되나봐요~
참고로 아래의 코드는 박상윤씨라구 잘생긴 분이 한거랍니다. ^^
(박상윤씨가 이글 보면 술 한잔 사주~~~)
xc:= trunc(bi^.bmiHeader.biWidth/2 ); // 이미지의 중앙을 원점으로 잡는다.
yc:= trunc(bi^.bmiHeader.biHeight/2);
radian:=degree*3.141592/180; //각도를 라디안으로 변화
for i:=-yc+1 to yc do begin
for j:=-xc+1 to xc do begin //중심이 중앙이므로 -에서 +까지 처리한다.
//+1을 한이유는 배열이 1부터이기때문
v:=(i-py); //이동 변환
u:=(j-px);
y:=(u*sin(radian)+v*cos(radian))/zy; //확대축소 및 회전 변환
x:=(u*cos(radian)-v*Sin(radian))/zx;
if y>0 then //실수 좌표에서 정수 좌표로 변환하여 차이 p,q를 구함
m:=trunc(y) //양수 일 때 와 음수 일 때 틀려지는 것은 정수점을
else //구하는 조건이 x,y를 넘지 않는 정수이기 때문이다.
m:=trunc(y-1); //음수의 경우 넘지 않는 다는 의미는 -1만큼 이동하여
if x>0 then //정수를 구해야 한다는 것을 의미한다.
n:=trunc(x)
else
n:=trunc(x-1);
q:=y-m; //실수좌표와 정수 좌표의 차이계산
p:=x-n;
if((m>=-yc+1)and(m<=yc) )and ((n>=-xc+1)and(n<=xc)) //원하는 이미지크기
then begin //만큼만 계산함
d:=trunc((1.0-q)*((1.0-p)*data[n+xc,m+yc]+p*data[n+1+xc,m+yc])
+q*((1.0-p)*data[n+xc,m+1+yc]+p*data[n+1+xc,m+1+yc]));
end //선형 보간법에 의한 데이터계산
else
d:=255
if d<0 then d:=0;
if d>255 then d:=255;
outdata[j+xc,i+yc]:=d; //계산된 데이터를 출력 화상데이터에 입력
end; //for
end; //for