Back to Richel Bilderbeek's homepage.

Back to Richel Bilderbeek's Code Snippets.

 

 

 

Rotate

 

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.

 

CLX

 

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;

}

//---------------------------------------------------------------------------

 

STL

Under construction

 

 

VCL

 

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.