Back
to Richel Bilderbeek's homepage.
Back
to Richel Bilderbeek's Code Snippets.
Rotates
an image under any angle.
* View the 'Rotate' function code for CLX in plain text
* View the 'Rotate' function code for VCL in plain text
* Go to the page of the tool 'Image Rotater' that
uses the Rotate function.
Assumes
you have already defind GetPixel, SetPixel and GetAngle.
View the 'Rotate' function code for CLX in plain text
//From
http://www.richelbilderbeek.nl/CppRotate.htm
void Rotate(
const TImage * const imageOriginal,
TImage * const imageResult,
const double angle)
{
const int maxx = imageResult->Picture->Bitmap->Width;
const int maxy = imageResult->Picture->Bitmap->Height;
const double midx = static_cast<double>(maxx) / 2.0;
const double midy = static_cast<double>(maxy) / 2.0;
for (int y=0; y!=maxy; ++y)
{
for(int x=0; x!=maxx; ++x)
{
const double dx1 = static_cast<double>(x)
- midx;
const double dy1 = static_cast<double>(y)
- midy;
double dx2, dy2; //Coordinats in original
Translate(dx1,dy1,angle,dx2,dy2);
const double x2
= (static_cast<double>(imageOriginal->Picture->Bitmap->Width
)
/ 2.0) + dx2;
const double y2
= (static_cast<double>(imageOriginal->Picture->Bitmap->Height)
/ 2.0) + dy2;
if ( x2 < 1.0
|| y2 < 1.0
|| x2 >= imageOriginal->Picture->Bitmap->Width
- 1.0
|| y2 >= imageOriginal->Picture->Bitmap->Height
- 1.0
)
{ //Out of range
SetPixel(imageResult,x,y,0,0,0);
continue;
}
unsigned char r,g,b;
GetPixel(imageOriginal,x2,y2,r,g,b);
SetPixel(imageResult,x,y,r,g,b);
}
}
}
//---------------------------------------------------------------------------
//From
http://www.richelbilderbeek.nl/CppRotate.htm
void GetPixel(
const TImage * const image,
const double x,
const double y,
unsigned char& red,
unsigned char& green,
unsigned char& blue)
{
const double xRemainder = x - static_cast<int>(x);
const double yRemainder = y - static_cast<int>(y);
const int x_tl = ( xRemainder > 0.5 ? x : x-1);
const int y_tl = ( yRemainder > 0.5 ? y : y-1);
const double left = ( xRemainder > 0.5 ? 1.5 - xRemainder : 0.5 -
xRemainder);
const double top = ( yRemainder
> 0.5 ? 1.5 - yRemainder : 0.5 -
yRemainder);
return GetPixel(image,x_tl,y_tl,left,top,red,green,blue);
}
//---------------------------------------------------------------------------
//From
http://www.richelbilderbeek.nl/CppRotate.htm
void GetPixel(
const TImage * const image,
const int x_tl,
const int y_tl,
const double left,
const double top,
unsigned char& red,
unsigned char& green,
unsigned char& blue)
{
const double right = 1.0 - left;
const double bottom = 1.0 - top;
assert(left >= 0.0
&& left <=1.0);
assert(top >= 0.0
&& top <=1.0);
assert(right >= 0.0
&& right <=1.0);
assert(bottom >= 0.0 && bottom <=1.0);
unsigned char r_tl, g_tl, b_tl;
unsigned char r_tr, g_tr, b_tr;
unsigned char r_bl, g_bl, b_bl;
unsigned char r_br, g_br, b_br;
GetPixel(image,x_tl+0,y_tl+0,r_tl,g_tl,b_tl);
GetPixel(image,x_tl+1,y_tl+0,r_tr,g_tr,b_tr);
GetPixel(image,x_tl+0,y_tl+1,r_bl,g_bl,b_bl);
GetPixel(image,x_tl+1,y_tl+1,r_br,g_br,b_br);
const double rTotal
= (top * left * static_cast<double>(r_tl))
+ (top * right *
static_cast<double>(r_tr))
+ (bottom * left *
static_cast<double>(r_bl))
+ (bottom * right * static_cast<double>(r_br));
const double gTotal
= (top * left * static_cast<double>(g_tl))
+ (top * right *
static_cast<double>(g_tr))
+ (bottom * left *
static_cast<double>(g_bl))
+ (bottom * right * static_cast<double>(g_br));
const double bTotal
= (top * left * static_cast<double>(b_tl))
+ (top * right *
static_cast<double>(b_tr))
+ (bottom * left *
static_cast<double>(b_bl))
+ (bottom * right * static_cast<double>(b_br));
assert(rTotal >= 0.0 && rTotal < 256.0);
assert(gTotal >= 0.0 && gTotal < 256.0);
assert(bTotal >= 0.0 && bTotal < 256.0);
red = static_cast<unsigned
char>(rTotal);
green = static_cast<unsigned char>(gTotal);
blue = static_cast<unsigned
char>(bTotal);
}
//---------------------------------------------------------------------------
//From
http://www.richelbilderbeek.nl/CppRotate.htm
void Translate(
const double dx1,
const double dy1,
const double dAngle,
double& dx2,
double& dy2)
{
const double oldAngle = GetAngle(dx1,dy1);
const double newAngle = oldAngle + dAngle;
const double ray = std::sqrt((dx1 * dx1) + (dy1 * dy1)); //Pythagoras
dx2 = std::sin(newAngle) * ray;
dy2 = -std::cos(newAngle) * ray;
}
//---------------------------------------------------------------------------
Under
construction
Assumes
you have already defind GetPixel, SetPixel and GetAngle.
In
the code below, I have given 'SetPixel' the name 'SetPixelVcl'.
View the 'Rotate' function code for VCL in plain text.
//From
http://www.richelbilderbeek.nl/CppRotate.htm
void Rotate(
const TImage * const imageOriginal,
TImage * const imageResult,
const double angle)
{
const int maxx = imageResult->Picture->Bitmap->Width;
const int maxy = imageResult->Picture->Bitmap->Height;
const double midx = static_cast<double>(maxx)
/ 2.0;
const double midy = static_cast<double>(maxy)
/ 2.0;
for (int y=0; y!=maxy; ++y)
{
for(int x=0; x!=maxx; ++x)
{
const double dx1 = static_cast<double>(x)
- midx;
const double dy1 = static_cast<double>(y)
- midy;
double dx2, dy2; //Coordinats in original
Translate(dx1,dy1,angle,dx2,dy2);
const double x2 =
(static_cast<double>(imageOriginal->Picture->Bitmap->Width
) /
2.0) + dx2;
const double y2 =
(static_cast<double>(imageOriginal->Picture->Bitmap->Height)
/
2.0) + dy2;
if ( x2 < 1.0
|| y2 < 1.0
|| x2 >= imageOriginal->Picture->Bitmap->Width
- 1.0
|| y2 >= imageOriginal->Picture->Bitmap->Height
- 1.0
)
{ //Out of range
SetPixelVcl(imageResult,x,y,0,0,0); //The VCL version of
SetPixel
continue;
}
unsigned char r,g,b;
GetPixel(imageOriginal,x2,y2,r,g,b);
SetPixelVcl(imageResult,x,y,r,g,b);
}
}
}
//---------------------------------------------------------------------------
//From
http://www.richelbilderbeek.nl/CppRotate.htm
void GetPixel(
const TImage * const image,
const double x,
const double y,
unsigned char& red,
unsigned char& green,
unsigned char& blue)
{
const double xRemainder = x - static_cast<int>(x);
const double yRemainder = y - static_cast<int>(y);
const int x_tl = ( xRemainder > 0.5 ? x : x-1);
const int y_tl = ( yRemainder > 0.5 ? y : y-1);
const double left = ( xRemainder > 0.5 ? 1.5 - xRemainder :
0.5 -
xRemainder);
const double top = (
yRemainder > 0.5 ? 1.5 - yRemainder : 0.5 -
yRemainder);
return GetPixel(image,x_tl,y_tl,left,top,red,green,blue);
}
//---------------------------------------------------------------------------
//From
http://www.richelbilderbeek.nl/CppRotate.htm
void GetPixel(
const TImage * const image,
const int x_tl,
const int y_tl,
const double left,
const double top,
unsigned char& red,
unsigned char& green,
unsigned char& blue)
{
const double right = 1.0 - left;
const double bottom = 1.0 - top;
assert(left >= 0.0
&& left <=1.0);
assert(top >= 0.0
&& top <=1.0);
assert(right >= 0.0
&& right <=1.0);
assert(bottom >= 0.0 && bottom <=1.0);
unsigned char r_tl, g_tl, b_tl;
unsigned char r_tr, g_tr, b_tr;
unsigned char r_bl, g_bl, b_bl;
unsigned char r_br, g_br, b_br;
GetPixel(image,x_tl+0,y_tl+0,r_tl,g_tl,b_tl);
GetPixel(image,x_tl+1,y_tl+0,r_tr,g_tr,b_tr);
GetPixel(image,x_tl+0,y_tl+1,r_bl,g_bl,b_bl);
GetPixel(image,x_tl+1,y_tl+1,r_br,g_br,b_br);
const double rTotal
= (top * left * static_cast<double>(r_tl))
+ (top * right * static_cast<double>(r_tr))
+ (bottom * left * static_cast<double>(r_bl))
+ (bottom * right * static_cast<double>(r_br));
const double gTotal
= (top * left * static_cast<double>(g_tl))
+ (top * right * static_cast<double>(g_tr))
+ (bottom * left * static_cast<double>(g_bl))
+ (bottom * right * static_cast<double>(g_br));
const double bTotal
= (top * left * static_cast<double>(b_tl))
+ (top * right * static_cast<double>(b_tr))
+ (bottom * left * static_cast<double>(b_bl))
+ (bottom * right * static_cast<double>(b_br));
assert(rTotal >= 0.0 && rTotal < 256.0);
assert(gTotal >= 0.0 && gTotal < 256.0);
assert(bTotal >= 0.0 && bTotal < 256.0);
red = static_cast<unsigned
char>(rTotal);
green = static_cast<unsigned char>(gTotal);
blue = static_cast<unsigned
char>(bTotal);
}
//---------------------------------------------------------------------------
//From
http://www.richelbilderbeek.nl/CppRotate.htm
void Translate(
const double dx1,
const double dy1,
const double dAngle,
double& dx2,
double& dy2)
{
const double oldAngle = GetAngle(dx1,dy1);
const double newAngle = oldAngle - dAngle; //NEW: Must be a minus
to rotate clockwise
const double ray = std::sqrt((dx1 * dx1) + (dy1 * dy1));
//Pythagoras
dx2 = std::sin(newAngle) * ray;
dy2 = -std::cos(newAngle) * ray;
}
Back
to Richel Bilderbeek's Code Snippets.
Back
to Richel Bilderbeek's homepage.