From 7a632f1056d7894daca7342394c1db9b61f6aecf Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Sun, 6 Feb 2000 14:51:36 +0000 Subject: [PATCH] Added rotation to wxImage git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5872 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/image.tex | 10 ++ include/wx/image.h | 5 + samples/rotate/Makefile.in | 21 ++++ samples/rotate/kclub.bmp | Bin 0 -> 12118 bytes samples/rotate/makefile.b32 | 16 +++ samples/rotate/makefile.g95 | 16 +++ samples/rotate/makefile.unx | 35 +++++++ samples/rotate/makefile.vc | 18 ++++ samples/rotate/makefile.wat | 15 +++ samples/rotate/mondrian.ico | Bin 0 -> 766 bytes samples/rotate/rotate.cpp | 120 ++++++++++++++++++++++ samples/rotate/rotate.rc | 3 + src/common/image.cpp | 195 ++++++++++++++++++++++++++++++++++++ 13 files changed, 454 insertions(+) create mode 100644 samples/rotate/Makefile.in create mode 100644 samples/rotate/kclub.bmp create mode 100644 samples/rotate/makefile.b32 create mode 100644 samples/rotate/makefile.g95 create mode 100644 samples/rotate/makefile.unx create mode 100644 samples/rotate/makefile.vc create mode 100644 samples/rotate/makefile.wat create mode 100644 samples/rotate/mondrian.ico create mode 100644 samples/rotate/rotate.cpp create mode 100644 samples/rotate/rotate.rc diff --git a/docs/latex/wx/image.tex b/docs/latex/wx/image.tex index ca43c0fbcc..f913b2b6ba 100644 --- a/docs/latex/wx/image.tex +++ b/docs/latex/wx/image.tex @@ -505,6 +505,16 @@ Returns the (modified) image itself. \helpref{Scale}{wximagescale} +\membersection{wxImage::Rotate}\label{wximagererotate} + +\func{wxImage}{Rotate}{\param{double}{ angle}, \param{const wxPoint\& }{rotationCentre}, + \param{bool}{ interpolating = TRUE}, \param{wxPoint*}{ offsetAfterRotation = NULL}} + +Rotates the image about the given point, by {\it angle} radians. Passing TRUE +to {\it interpolating} results in better image quality, but is slower. + +Returns the rotated image, leaving this image intact. + \membersection{wxImage::Scale}\label{wximagescale} \constfunc{wxImage}{Scale}{\param{int}{ width}, \param{int}{ height}} diff --git a/include/wx/image.h b/include/wx/image.h index 7f2b0904ea..09aa6ed4a2 100644 --- a/include/wx/image.h +++ b/include/wx/image.h @@ -117,6 +117,11 @@ public: // rescales the image in place wxImage& Rescale( int width, int height ) { return *this = Scale(width, height); } + // Rotates the image about the given point, 'angle' radians. + // Returns the rotated image, leaving this image intact. + wxImage Rotate(double angle, const wxPoint & centre_of_rotation, + bool interpolating = TRUE, wxPoint * offset_after_rotation = (wxPoint*) NULL) const ; + // replace one colour with another void Replace( unsigned char r1, unsigned char g1, unsigned char b1, unsigned char r2, unsigned char g2, unsigned char b2 ); diff --git a/samples/rotate/Makefile.in b/samples/rotate/Makefile.in new file mode 100644 index 0000000000..a7c8e4fcd8 --- /dev/null +++ b/samples/rotate/Makefile.in @@ -0,0 +1,21 @@ +# +# File: makefile.unx +# Author: Julian Smart +# Created: 1998 +# Updated: +# Copyright: (c) 1998 Julian Smart +# +# "%W% %G%" +# +# Makefile for rotate example (UNIX). + +top_srcdir = @top_srcdir@/.. +top_builddir = ../.. +program_dir = samples/rotate + +PROGRAM=rotate + +OBJECTS=$(PROGRAM).o + +include ../../src/makeprog.env + diff --git a/samples/rotate/kclub.bmp b/samples/rotate/kclub.bmp new file mode 100644 index 0000000000000000000000000000000000000000..2a4aa03a4bab0bc5fd723b28a0dd39d9f01af7f7 GIT binary patch literal 12118 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 (wxColour (0,80,60)); + + frame->Show (TRUE); + SetTopWindow (frame); + return TRUE; +} + +MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) + : wxFrame((wxFrame *)NULL, -1, title, pos, size) +{ + wxMenu *menuFile = new wxMenu; + menuFile->Append (ID_Quit, "E&xit"); + + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append (menuFile, "&File"); + + SetMenuBar (menuBar); +} + +void MyFrame::OnQuit (wxCommandEvent &) +{ + Close (TRUE); +} + + +// Rotate with interpolation and with offset correction +void MyFrame::OnMouseLeftUp (wxMouseEvent & event) +{ + static double angle = 0.1; + const double pi = 3.14159265359; + + wxImage img ("kclub.bmp", wxBITMAP_TYPE_BMP); + + wxPoint offset; + wxImage img2 = img.Rotate(angle, wxPoint(img.GetWidth()/2, img.GetHeight()/2), TRUE, &offset); + angle += 0.05; + + wxBitmap bmp = img2.ConvertToBitmap (); + + wxClientDC dc (this); + dc.DrawBitmap (bmp, event.m_x + offset.x, event.m_y + offset.y); + + return; +} + +// without interpolation, and without offset correction +void MyFrame::OnMouseRightUp (wxMouseEvent & event) +{ + static double angle = 0.1; + const double pi = 3.14159265359; + + wxImage img ("kclub.bmp", wxBITMAP_TYPE_BMP); + + wxImage img2 = img.Rotate(angle, wxPoint(img.GetWidth()/2, img.GetHeight()/2), FALSE); + angle += 0.05; + + wxBitmap bmp = img2.ConvertToBitmap (); + + wxClientDC dc (this); + dc.DrawBitmap (bmp, event.m_x, event.m_y); + + return; +} diff --git a/samples/rotate/rotate.rc b/samples/rotate/rotate.rc new file mode 100644 index 0000000000..7655c62a4c --- /dev/null +++ b/samples/rotate/rotate.rc @@ -0,0 +1,3 @@ +mondrian ICON "mondrian.ico" +#include "wx/msw/wx.rc" + diff --git a/src/common/image.cpp b/src/common/image.cpp index 58dec0c3b6..f73c76bfae 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -30,6 +30,7 @@ // For memcpy #include +#include #ifdef __SALFORDC__ #undef FAR @@ -2682,4 +2683,198 @@ unsigned long wxImage::ComputeHistogram( wxHashTable &h ) return nentries; } +/* + * Rotation code by Carlos Moreno + */ + +struct wxRotationPixel +{ + unsigned char rgb[3]; +}; + +struct wxRotationPoint +{ + wxRotationPoint (double _x, double _y) : x(_x), y(_y) {} + wxRotationPoint (const wxPoint & p) : x(p.x), y(p.y) {} + double x, y; +}; + +static const wxRotationPixel gs_BlankPixel = {0,0,0}; +static const double gs_Epsilon = 1e-10; + +static inline int wxCint (double x) +{ + return (x > 0) ? (int) (x + 0.5) : (int) (x - 0.5); +} + + +// Auxiliary function to rotate a point (x,y) with respect to point p0 +// make it inline and use a straight return to facilitate optimization +// also, the function receives the sine and cosine of the angle to avoid +// repeating the time-consuming calls to these functions -- sin/cos can +// be computed and stored in the calling function. + +inline wxRotationPoint rotated_point (const wxRotationPoint & p, double cos_angle, double sin_angle, const wxRotationPoint & p0) +{ + return wxRotationPoint (p0.x + (p.x - p0.x) * cos_angle - (p.y - p0.y) * sin_angle, + p0.y + (p.y - p0.y) * cos_angle + (p.x - p0.x) * sin_angle); +} + +inline wxRotationPoint rotated_point (double x, double y, double cos_angle, double sin_angle, const wxRotationPoint & p0) +{ + return rotated_point (wxRotationPoint(x,y), cos_angle, sin_angle, p0); +} + +wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool interpolating, wxPoint * offset_after_rotation) const +{ + const wxImage& img = * this; + int i; + angle = -angle; // screen coordinates are a mirror image of "real" coordinates + + // Create pointer-based array to accelerate access to wxImage's data + wxRotationPixel ** data = new wxRotationPixel * [img.GetHeight()]; + + data[0] = (wxRotationPixel *) img.GetData(); + + for (i = 1; i < img.GetHeight(); i++) + { + data[i] = data[i - 1] + img.GetWidth(); + } + + // pre-compute coefficients for rotation formula (sine and cosine of the angle) + const double cos_angle = cos(angle); + const double sin_angle = sin(angle); + + // Create new Image to store the result + // First, find rectangle that covers the rotated image; to do that, + // rotate the four corners + + const wxRotationPoint & p0 = centre_of_rotation; + + wxRotationPoint p1 = rotated_point (0, 0, cos_angle, sin_angle, p0); + wxRotationPoint p2 = rotated_point (0, img.GetHeight(), cos_angle, sin_angle, p0); + wxRotationPoint p3 = rotated_point (img.GetWidth(), 0, cos_angle, sin_angle, p0); + wxRotationPoint p4 = rotated_point (img.GetWidth(), img.GetHeight(), cos_angle, sin_angle, p0); + + int x1 = floor (min (min(p1.x, p2.x), min(p3.x, p4.x))); + int y1 = floor (min (min(p1.y, p2.y), min(p3.y, p4.y))); + + int x2 = ceil (max (max(p1.x, p2.x), max(p3.x, p4.x))); + int y2 = ceil (max (max(p1.y, p2.y), max(p3.y, p4.y))); + + wxImage rotated (x2 - x1 + 1, y2 - y1 + 1); + + if (offset_after_rotation != NULL) + { + *offset_after_rotation = wxPoint (x1, y1); + } + + + wxRotationPixel ** result_data = new wxRotationPixel * [rotated.GetHeight()]; + + result_data[0] = (wxRotationPixel *) rotated.GetData(); + + for (i = 1; i < rotated.GetHeight(); i++) + { + result_data[i] = result_data[i - 1] + rotated.GetWidth(); + } + + // Now, for each point of the rotated image, find where it came from, by + // performing an inverse rotation (a rotation of -angle) and getting the + // pixel at those coordinates + + int x; + for (x = 0; x < rotated.GetWidth(); x++) + { + for (int y = 0; y < rotated.GetHeight(); y++) + { + wxRotationPoint src = rotated_point (x + x1, y + y1, cos_angle, -sin_angle, p0); + + if (interpolating) + { + if (0 < src.x && src.x < img.GetWidth() - 1 && + 0 < src.y && src.y < img.GetHeight() - 1) + { + // interpolate using the 4 enclosing grid-points. Those + // points can be obtained using floor and ceiling of the + // exact coordinates of the point + + const int x1 = wxCint(floor(src.x)); + const int y1 = wxCint(floor(src.y)); + const int x2 = wxCint(ceil(src.x)); + const int y2 = wxCint(ceil(src.y)); + + // get four points and the distances (square of the distance, + // for efficiency reasons) for the interpolation formula + const wxRotationPixel & v1 = data[y1][x1]; + const wxRotationPixel & v2 = data[y1][x2]; + const wxRotationPixel & v3 = data[y2][x2]; + const wxRotationPixel & v4 = data[y2][x1]; + + const double d1 = (src.x - x1) * (src.x - x1) + (src.y - y1) * (src.y - y1); + const double d2 = (src.x - x2) * (src.x - x2) + (src.y - y1) * (src.y - y1); + const double d3 = (src.x - x2) * (src.x - x2) + (src.y - y2) * (src.y - y2); + const double d4 = (src.x - x1) * (src.x - x1) + (src.y - y2) * (src.y - y2); + + // Now interpolate as a weighted average of the four surrounding + // points, where the weights are the distances to each of those points + + // If the point is exactly at one point of the grid of the source + // image, then don't interpolate -- just assign the pixel + + if (d1 < gs_Epsilon) // d1,d2,d3,d4 are positive -- no need for abs() + { + result_data[y][x] = v1; + } + else if (d2 < gs_Epsilon) + { + result_data[y][x] = v2; + } + else if (d3 < gs_Epsilon) + { + result_data[y][x] = v3; + } + else if (d4 < gs_Epsilon) + { + result_data[y][x] = v4; + } + else + { + // weights for the weighted average are proportional to the inverse of the distance + const w1 = 1/d1, w2 = 1/d2, w3 = 1/d3, w4 = 1/d4; + + for (int i = 0; i < 3; i++) // repeat calculation for R, G, and B + { + result_data[y][x].rgb[i] = + static_cast ( (w1 * v1.rgb[i] + w2 * v2.rgb[i] + + w3 * v3.rgb[i] + w4 * v4.rgb[i]) / + (w1 + w2 + w3 + w4) ); + } + } + } + else + { + result_data[y][x] = gs_BlankPixel; + } + } + else + { + const int & xs = wxCint (src.x); // wxCint performs rounding to the + const int & ys = wxCint (src.y); // closest integer + + if (0 <= xs && xs < img.GetWidth() && + 0 <= ys && ys < img.GetHeight()) + { + result_data[y][x] = data[ys][xs]; + } + else + { + result_data[y][x] = gs_BlankPixel; + } + } + } + } + + return rotated; +} -- 2.45.2