From: Harm <harmans@uswest.net>
Subject: Re: 2d rotaion trouble!
Date: 28 Mar 1999 00:00:00 GMT
Message-ID: <36FE5D74.C74E566C@uswest.net>
Content-Transfer-Encoding: 7bit
References: <e5bL2.456$Xc6.578@news.get2net.dk>
Content-Type: text/plain; charset=us-ascii
X-Complaints-To: harmans@uswest.net
NNTP-Posting-Date: Sun, 28 Mar 1999 10:48:22 CDT
Newsgroups: comp.graphics.algorithms
Here's Delphi pascal code to rotate an image any angle, with edge wrapping,
and anti-aliasing. Converted and added the edge wrapping, from original VB
code by Rod Stephens. At least it wasn't (shudder) C++. :)
procedure TForm1.RotateAngle(Angle: integer);
var
Theta, cosTheta, sinTheta: Single;
cx, cy : Single; //Center X, Y
sfrom_y, sfrom_x : Single; //Real number
ifrom_y, ifrom_x : Integer; //Integer version
to_y, to_x : Integer;
weight_x, weight_y : array[0..1] of Single;
weight : Single;
new_red, new_green : Integer;
new_blue : Integer;
total_red, total_green : Single;
total_blue : Single;
ix, iy : Integer;
pb, pc : pRGBArray;
begin
Screen.Cursor := crHourGlass;
CopyMe(ud,b); //Copy to the undo bitmap
CopyMe(tBufr,b); //Copy to the internal buffer bitmap
// Calculate the sine and cosine of theta for later.
Theta:=-(Angle)*Pi/180;
sinTheta:=Sin(Theta);
cosTheta:=Cos(Theta);
cx := b.Width / 2; //Center of rotation for x
cy := b.Height / 2; //Center of rotation for y
// Perform the rotation.
for to_y := 0 to b.Height-1 do begin
for to_x := 0 to b.Width-1 do begin
// Find the location (from_x, from_y) that
// rotates to position (to_x, to_y).
sfrom_x := cx +
(to_x - cx) * cosTheta -
(to_y - cy) * sinTheta;
ifrom_x := Trunc(sfrom_x);
sfrom_y := cy +
(to_x - cx) * sinTheta +
(to_y - cy) * cosTheta;
ifrom_y := Trunc(sfrom_y);
// Calculate the weights.
if sfrom_y >= 0 then begin
weight_y[1] := sfrom_y - ifrom_y;
weight_y[0] := 1 - weight_y[1];
end else begin
weight_y[0] := -(sfrom_y - ifrom_y);
weight_y[1] := 1 - weight_y[0];
end;
if sfrom_x >= 0 then begin
weight_x[1] := sfrom_x - ifrom_x;
weight_x[0] := 1 - weight_x[1];
end else begin
weight_x[0] := -(sfrom_x - ifrom_x);
Weight_x[1] := 1 - weight_x[0];
end;
if ifrom_x < 0 then
ifrom_x := b.Width -1-(-ifrom_x mod b.Width)
else if ifrom_x > b.Width-1 then
ifrom_x := ifrom_x mod b.Width;
if ifrom_y < 0 then
ifrom_y := b.Height -1-(-ifrom_y mod b.Height)
else if ifrom_y > b.Height-1 then
ifrom_y := ifrom_y mod b.Height;
// Average the color components of the four
// nearest pixels in from_canvas.
total_red := 0.0;
total_green := 0.0;
total_blue := 0.0;
for ix := 0 to 1 do begin
for iy := 0 to 1 do begin
if ifrom_y + iy < b.Height then
pc := tBufr.ScanLine[ifrom_y + iy]
else
pc := tBufr.ScanLine[b.Height - ifrom_y - iy];
if ifrom_x + ix < b.Width then begin
new_red := pc[ifrom_x + ix].rgbtRed;
new_green := pc[ifrom_x + ix].rgbtGreen;
new_blue := pc[ifrom_x + ix].rgbtBlue;
weight := weight_x[ix] * weight_y[iy];
total_red := total_red + new_red * weight;
total_green := total_green + new_green * weight;
total_blue := total_blue + new_blue * weight;
end
else begin
new_red := pc[b.Width - ifrom_x - ix].rgbtRed;
new_green := pc[b.Width - ifrom_x - ix].rgbtGreen;
new_blue := pc[b.Width - ifrom_x - ix].rgbtBlue;
weight := weight_x[ix] * weight_y[iy];
total_red := total_red + new_red * weight;
total_green := total_green + new_green * weight;
total_blue := total_blue + new_blue * weight;
end;
end;
end;
pb := b.ScanLine[to_y];
pb[to_x].rgbtRed := Round(total_red);
pb[to_x].rgbtGreen := Round(total_green);
pb[to_x].rgbtBlue := Round(total_blue);
end;
end;
imSine.Picture.Assign(b); //all done, assign the bmp to our image
Screen.Cursor := crDefault;
end;
morphix wrote:
> I have some problems figuring how to do a 2d rotation on an image. The
> resulting image has blank pixels (holes that isn't filled with color)
> could anybody please show me an algorithm that works, (pascal, c, c++ or
> pseudo)
>
> Morphix
--
Harmans
Omaha NE