Added support for transparency in rotation code

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5950 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Guillermo Rodriguez Garcia
2000-02-10 13:27:07 +00:00
parent b217783903
commit ad30de59f6

View File

@@ -885,9 +885,9 @@ wxBitmap wxImage::ConvertToBitmap() const
for(i=0; i<width; i++ ) for(i=0; i<width; i++ )
{ {
// was causing a code gen bug in cw : if( ( cr !=r) || (cg!=g) || (cb!=b) ) // was causing a code gen bug in cw : if( ( cr !=r) || (cg!=g) || (cb!=b) )
unsigned char cr = (*(ptdata++)) ; unsigned char cr = (*(ptdata++)) ;
unsigned char cg = (*(ptdata++)) ; unsigned char cg = (*(ptdata++)) ;
unsigned char cb = (*(ptdata++)) ; unsigned char cb = (*(ptdata++)) ;
if( ( cr !=r) || (cg!=g) || (cb!=b) ) if( ( cr !=r) || (cg!=g) || (cb!=b) )
{ {
@@ -1109,11 +1109,11 @@ wxBitmap wxImage::ConvertToBitmap() const
int g_mask = GetMaskGreen(); int g_mask = GetMaskGreen();
int b_mask = GetMaskBlue(); int b_mask = GetMaskBlue();
CGrafPtr origPort ; CGrafPtr origPort ;
GDHandle origDevice ; GDHandle origDevice ;
GetGWorld( &origPort , &origDevice ) ; GetGWorld( &origPort , &origDevice ) ;
SetGWorld( bitmap.GetHBITMAP() , NULL ) ; SetGWorld( bitmap.GetHBITMAP() , NULL ) ;
register unsigned char* data = GetData(); register unsigned char* data = GetData();
@@ -1122,15 +1122,15 @@ wxBitmap wxImage::ConvertToBitmap() const
{ {
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
{ {
unsigned char r = data[index++]; unsigned char r = data[index++];
unsigned char g = data[index++]; unsigned char g = data[index++];
unsigned char b = data[index++]; unsigned char b = data[index++];
RGBColor color ; RGBColor color ;
color.red = ( r << 8 ) + r ; color.red = ( r << 8 ) + r ;
color.green = ( g << 8 ) + g ; color.green = ( g << 8 ) + g ;
color.blue = ( b << 8 ) + b ; color.blue = ( b << 8 ) + b ;
SetCPixel( x , y , &color ) ; SetCPixel( x , y , &color ) ;
} }
} // for height } // for height
SetGWorld( origPort , origDevice ) ; SetGWorld( origPort , origDevice ) ;
@@ -2608,8 +2608,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)
unsigned long wxImage::CountColours( unsigned long stopafter ) unsigned long wxImage::CountColours( unsigned long stopafter )
{ {
wxHashTable h; wxHashTable h;
wxNode *node; wxObject dummy;
wxHNode *hnode;
unsigned char r, g, b, *p; unsigned char r, g, b, *p;
unsigned long size, nentries, key; unsigned long size, nentries, key;
@@ -2624,20 +2623,13 @@ unsigned long wxImage::CountColours( unsigned long stopafter )
b = *(p++); b = *(p++);
key = (r << 16) | (g << 8) | b; key = (r << 16) | (g << 8) | b;
hnode = (wxHNode *) h.Get(key); if (h.Get(key) == NULL)
if (!hnode)
{ {
h.Put(key, (wxObject *)(new wxHNode)); h.Put(key, &dummy);
nentries++; nentries++;
} }
} }
// delete all HNodes
h.BeginFind();
while ((node = h.Next()) != NULL)
delete (wxHNode *)node->GetData();
return nentries; return nentries;
} }
@@ -2699,7 +2691,6 @@ struct wxRotationPoint
double x, y; double x, y;
}; };
static const wxRotationPixel gs_BlankPixel = {0,0,0};
static const double gs_Epsilon = 1e-10; static const double gs_Epsilon = 1e-10;
static inline int wxCint (double x) static inline int wxCint (double x)
@@ -2731,7 +2722,7 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
int i; int i;
angle = -angle; // screen coordinates are a mirror image of "real" coordinates angle = -angle; // screen coordinates are a mirror image of "real" coordinates
// Create pointer-based array to accelerate access to wxImage's data // Create pointer-based array to accelerate access to wxImage's data
wxRotationPixel ** data = new wxRotationPixel * [img.GetHeight()]; wxRotationPixel ** data = new wxRotationPixel * [img.GetHeight()];
data[0] = (wxRotationPixel *) img.GetData(); data[0] = (wxRotationPixel *) img.GetData();
@@ -2741,13 +2732,14 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
data[i] = data[i - 1] + img.GetWidth(); data[i] = data[i - 1] + img.GetWidth();
} }
// pre-compute coefficients for rotation formula (sine and cosine of the angle) // pre-compute coefficients for rotation formula
// (sine and cosine of the angle)
const double cos_angle = cos(angle); const double cos_angle = cos(angle);
const double sin_angle = sin(angle); const double sin_angle = sin(angle);
// Create new Image to store the result // Create new Image to store the result
// First, find rectangle that covers the rotated image; to do that, // First, find rectangle that covers the rotated image; to do that,
// rotate the four corners // rotate the four corners
const wxRotationPoint p0 = centre_of_rotation; const wxRotationPoint p0 = centre_of_rotation;
@@ -2769,7 +2761,6 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
*offset_after_rotation = wxPoint (x1, y1); *offset_after_rotation = wxPoint (x1, y1);
} }
wxRotationPixel ** result_data = new wxRotationPixel * [rotated.GetHeight()]; wxRotationPixel ** result_data = new wxRotationPixel * [rotated.GetHeight()];
result_data[0] = (wxRotationPixel *) rotated.GetData(); result_data[0] = (wxRotationPixel *) rotated.GetData();
@@ -2779,9 +2770,27 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
result_data[i] = result_data[i - 1] + rotated.GetWidth(); result_data[i] = result_data[i - 1] + rotated.GetWidth();
} }
// Now, for each point of the rotated image, find where it came from, by // GRG: if the original image has a mask, use its RGB values
// performing an inverse rotation (a rotation of -angle) and getting the // as the blank pixel, else, fall back to default (black).
// pixel at those coordinates //
wxRotationPixel blankPixel = {{ 0, 0, 0 }};
if (HasMask())
{
unsigned char r = GetMaskRed();
unsigned char g = GetMaskGreen();
unsigned char b = GetMaskBlue();
rotated.SetMaskColour( r, g, b );
blankPixel.rgb[0] = r;
blankPixel.rgb[1] = g;
blankPixel.rgb[2] = b;
}
// 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
// GRG: I'd suggest to take the (interpolating) test out of the loops
int x; int x;
for (x = 0; x < rotated.GetWidth(); x++) for (x = 0; x < rotated.GetWidth(); x++)
@@ -2795,17 +2804,17 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
if (0 < src.x && src.x < img.GetWidth() - 1 && if (0 < src.x && src.x < img.GetWidth() - 1 &&
0 < src.y && src.y < img.GetHeight() - 1) 0 < src.y && src.y < img.GetHeight() - 1)
{ {
// interpolate using the 4 enclosing grid-points. Those // interpolate using the 4 enclosing grid-points. Those
// points can be obtained using floor and ceiling of the // points can be obtained using floor and ceiling of the
// exact coordinates of the point // exact coordinates of the point
const int x1 = wxCint(floor(src.x)); const int x1 = wxCint(floor(src.x));
const int y1 = wxCint(floor(src.y)); const int y1 = wxCint(floor(src.y));
const int x2 = wxCint(ceil(src.x)); const int x2 = wxCint(ceil(src.x));
const int y2 = wxCint(ceil(src.y)); const int y2 = wxCint(ceil(src.y));
// get four points and the distances (square of the distance, // get four points and the distances (square of the distance,
// for efficiency reasons) for the interpolation formula // for efficiency reasons) for the interpolation formula
const wxRotationPixel & v1 = data[y1][x1]; const wxRotationPixel & v1 = data[y1][x1];
const wxRotationPixel & v2 = data[y1][x2]; const wxRotationPixel & v2 = data[y1][x2];
const wxRotationPixel & v3 = data[y2][x2]; const wxRotationPixel & v3 = data[y2][x2];
@@ -2816,11 +2825,11 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
const double d3 = (src.x - x2) * (src.x - x2) + (src.y - y2) * (src.y - y2); 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); 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 // Now interpolate as a weighted average of the four surrounding
// points, where the weights are the distances to each of those points // 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 // If the point is exactly at one point of the grid of the source
// image, then don't interpolate -- just assign the pixel // image, then don't interpolate -- just assign the pixel
if (d1 < gs_Epsilon) // d1,d2,d3,d4 are positive -- no need for abs() if (d1 < gs_Epsilon) // d1,d2,d3,d4 are positive -- no need for abs()
{ {
@@ -2847,14 +2856,14 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
{ {
result_data[y][x].rgb[i] = result_data[y][x].rgb[i] =
(unsigned char) ( (w1 * v1.rgb[i] + w2 * v2.rgb[i] + (unsigned char) ( (w1 * v1.rgb[i] + w2 * v2.rgb[i] +
w3 * v3.rgb[i] + w4 * v4.rgb[i]) / w3 * v3.rgb[i] + w4 * v4.rgb[i]) /
(w1 + w2 + w3 + w4) ); (w1 + w2 + w3 + w4) );
} }
} }
} }
else else
{ {
result_data[y][x] = gs_BlankPixel; result_data[y][x] = blankPixel;
} }
} }
else else
@@ -2869,7 +2878,7 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
} }
else else
{ {
result_data[y][x] = gs_BlankPixel; result_data[y][x] = blankPixel;
} }
} }
} }