Added support for alpha channels in interpolated
and non-interpolated image rotation.
  Added helper method for turning shades of grey
    into shades of alpha and a colour.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30604 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
			
			
This commit is contained in:
		@@ -211,6 +211,18 @@ public:
 | 
				
			|||||||
    // otherwise:
 | 
					    // otherwise:
 | 
				
			||||||
    bool ConvertAlphaToMask(unsigned char threshold = 128);
 | 
					    bool ConvertAlphaToMask(unsigned char threshold = 128);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // This method converts an image where the original alpha
 | 
				
			||||||
 | 
					    // information is only available as a shades of a colour
 | 
				
			||||||
 | 
					    // (actually shades of grey) typically when you draw anti-
 | 
				
			||||||
 | 
					    // aliased text into a bitmap. The DC drawinf routines
 | 
				
			||||||
 | 
					    // draw grey values on the black background although they
 | 
				
			||||||
 | 
					    // actually mean to draw white with differnt alpha values.
 | 
				
			||||||
 | 
					    // This method reverses it, assuming a black (!) background
 | 
				
			||||||
 | 
					    // and white text (actually only the red channel is read). 
 | 
				
			||||||
 | 
					    // The method will then fill up the whole image with the
 | 
				
			||||||
 | 
					    // colour given.
 | 
				
			||||||
 | 
					    bool ConvertColourToAlpha( unsigned char r, unsigned char g, unsigned char b ); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static bool CanRead( const wxString& name );
 | 
					    static bool CanRead( const wxString& name );
 | 
				
			||||||
    static int GetImageCount( const wxString& name, long type = wxBITMAP_TYPE_ANY );
 | 
					    static int GetImageCount( const wxString& name, long type = wxBITMAP_TYPE_ANY );
 | 
				
			||||||
    virtual bool LoadFile( const wxString& name, long type = wxBITMAP_TYPE_ANY, int index = -1 );
 | 
					    virtual bool LoadFile( const wxString& name, long type = wxBITMAP_TYPE_ANY, int index = -1 );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -804,6 +804,33 @@ unsigned char wxImage::GetAlpha(int x, int y) const
 | 
				
			|||||||
    return M_IMGDATA->m_alpha[y*w + x];
 | 
					    return M_IMGDATA->m_alpha[y*w + x];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool wxImage::ConvertColourToAlpha( unsigned char r, unsigned char g, unsigned char b )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SetAlpha( NULL );
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int w = M_IMGDATA->m_width,
 | 
				
			||||||
 | 
					        h = M_IMGDATA->m_height;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    unsigned char *alpha = GetAlpha();
 | 
				
			||||||
 | 
					    unsigned char *data = GetData();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int x,y;
 | 
				
			||||||
 | 
					    for (y = 0; y < h; y++)
 | 
				
			||||||
 | 
					        for (x = 0; x < w; x++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                *alpha = *data;
 | 
				
			||||||
 | 
					                alpha++;
 | 
				
			||||||
 | 
					                *data = r;
 | 
				
			||||||
 | 
					                data++;
 | 
				
			||||||
 | 
					                *data = g;
 | 
				
			||||||
 | 
					                data++;
 | 
				
			||||||
 | 
					                *data = b;
 | 
				
			||||||
 | 
					                data++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wxImage::SetAlpha( unsigned char *alpha )
 | 
					void wxImage::SetAlpha( unsigned char *alpha )
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    wxCHECK_RET( Ok(), wxT("invalid image") );
 | 
					    wxCHECK_RET( Ok(), wxT("invalid image") );
 | 
				
			||||||
@@ -1668,15 +1695,25 @@ 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
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    bool has_alpha = HasAlpha();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create pointer-based array to accelerate access to wxImage's data
 | 
					    // Create pointer-based array to accelerate access to wxImage's data
 | 
				
			||||||
    unsigned char ** data = new unsigned char * [GetHeight()];
 | 
					    unsigned char ** data = new unsigned char * [GetHeight()];
 | 
				
			||||||
 | 
					 | 
				
			||||||
    data[0] = GetData();
 | 
					    data[0] = GetData();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (i = 1; i < GetHeight(); i++)
 | 
					    for (i = 1; i < GetHeight(); i++)
 | 
				
			||||||
        data[i] = data[i - 1] + (3 * GetWidth());
 | 
					        data[i] = data[i - 1] + (3 * GetWidth());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Same for alpha channel    
 | 
				
			||||||
 | 
					    unsigned char ** alpha = NULL;
 | 
				
			||||||
 | 
					    if (has_alpha)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        alpha = new unsigned char * [GetHeight()];
 | 
				
			||||||
 | 
					        alpha[0] = GetAlpha();
 | 
				
			||||||
 | 
					        for (i = 1; i < GetHeight(); i++)
 | 
				
			||||||
 | 
					            alpha[i] = alpha[i - 1] + GetWidth();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // precompute coefficients for rotation formula
 | 
					    // precompute coefficients for rotation formula
 | 
				
			||||||
    // (sine and cosine of the angle)
 | 
					    // (sine and cosine of the angle)
 | 
				
			||||||
    const double cos_angle = cos(angle);
 | 
					    const double cos_angle = cos(angle);
 | 
				
			||||||
@@ -1698,7 +1735,11 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
 | 
				
			|||||||
    int x2 = (int) ceil (wxMax (wxMax(p1.x, p2.x), wxMax(p3.x, p4.x)));
 | 
					    int x2 = (int) ceil (wxMax (wxMax(p1.x, p2.x), wxMax(p3.x, p4.x)));
 | 
				
			||||||
    int y2 = (int) ceil (wxMax (wxMax(p1.y, p2.y), wxMax(p3.y, p4.y)));
 | 
					    int y2 = (int) ceil (wxMax (wxMax(p1.y, p2.y), wxMax(p3.y, p4.y)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Create rotated image
 | 
				
			||||||
    wxImage rotated (x2 - x1 + 1, y2 - y1 + 1, false);
 | 
					    wxImage rotated (x2 - x1 + 1, y2 - y1 + 1, false);
 | 
				
			||||||
 | 
					    // With alpha channel
 | 
				
			||||||
 | 
					    if (has_alpha)
 | 
				
			||||||
 | 
					        rotated.SetAlpha();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (offset_after_rotation != NULL)
 | 
					    if (offset_after_rotation != NULL)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -1710,6 +1751,10 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
 | 
				
			|||||||
    //      array here (and in fact it would be slower).
 | 
					    //      array here (and in fact it would be slower).
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
    unsigned char * dst = rotated.GetData();
 | 
					    unsigned char * dst = rotated.GetData();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    unsigned char * alpha_dst = NULL;
 | 
				
			||||||
 | 
					    if (has_alpha)
 | 
				
			||||||
 | 
					        alpha_dst = rotated.GetAlpha();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // GRG: if the original image has a mask, use its RGB values
 | 
					    // GRG: if the original image has a mask, use its RGB values
 | 
				
			||||||
    //      as the blank pixel, else, fall back to default (black).
 | 
					    //      as the blank pixel, else, fall back to default (black).
 | 
				
			||||||
@@ -1796,28 +1841,52 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
 | 
				
			|||||||
                        unsigned char *p = data[y1] + (3 * x1);
 | 
					                        unsigned char *p = data[y1] + (3 * x1);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *(p++);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *(p++);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *p;
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        if (has_alpha)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            unsigned char *p = alpha[y1] + x1;
 | 
				
			||||||
 | 
					                            *(alpha_dst++) = *p;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else if (d2 < gs_Epsilon)
 | 
					                    else if (d2 < gs_Epsilon)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        unsigned char *p = data[y1] + (3 * x2);
 | 
					                        unsigned char *p = data[y1] + (3 * x2);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *(p++);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *(p++);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *p;
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        if (has_alpha)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            unsigned char *p = alpha[y1] + x2;
 | 
				
			||||||
 | 
					                            *(alpha_dst++) = *p;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else if (d3 < gs_Epsilon)
 | 
					                    else if (d3 < gs_Epsilon)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        unsigned char *p = data[y2] + (3 * x2);
 | 
					                        unsigned char *p = data[y2] + (3 * x2);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *(p++);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *(p++);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *p;
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        if (has_alpha)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            unsigned char *p = alpha[y2] + x2;
 | 
				
			||||||
 | 
					                            *(alpha_dst++) = *p;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else if (d4 < gs_Epsilon)
 | 
					                    else if (d4 < gs_Epsilon)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        unsigned char *p = data[y2] + (3 * x1);
 | 
					                        unsigned char *p = data[y2] + (3 * x1);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *(p++);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *(p++);
 | 
				
			||||||
                        *(dst++) = *(p++);
 | 
					                        *(dst++) = *p;
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        if (has_alpha)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            unsigned char *p = alpha[y2] + x1;
 | 
				
			||||||
 | 
					                            *(alpha_dst++) = *p;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else
 | 
					                    else
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@@ -1843,6 +1912,19 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
 | 
				
			|||||||
                            ( (w1 * *v1 + w2 * *v2 +
 | 
					                            ( (w1 * *v1 + w2 * *v2 +
 | 
				
			||||||
                               w3 * *v3 + w4 * *v4) /
 | 
					                               w3 * *v3 + w4 * *v4) /
 | 
				
			||||||
                              (w1 + w2 + w3 + w4) );
 | 
					                              (w1 + w2 + w3 + w4) );
 | 
				
			||||||
 | 
					                              
 | 
				
			||||||
 | 
					                        if (has_alpha)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            unsigned char *v1 = alpha[y1] + (x1);
 | 
				
			||||||
 | 
					                            unsigned char *v2 = alpha[y1] + (x2);
 | 
				
			||||||
 | 
					                            unsigned char *v3 = alpha[y2] + (x2);
 | 
				
			||||||
 | 
					                            unsigned char *v4 = alpha[y2] + (x1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            *(alpha_dst++) = (unsigned char)
 | 
				
			||||||
 | 
					                                ( (w1 * *v1 + w2 * *v2 +
 | 
				
			||||||
 | 
					                                   w3 * *v3 + w4 * *v4) /
 | 
				
			||||||
 | 
					                                  (w1 + w2 + w3 + w4) );
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
@@ -1850,6 +1932,9 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
 | 
				
			|||||||
                    *(dst++) = blank_r;
 | 
					                    *(dst++) = blank_r;
 | 
				
			||||||
                    *(dst++) = blank_g;
 | 
					                    *(dst++) = blank_g;
 | 
				
			||||||
                    *(dst++) = blank_b;
 | 
					                    *(dst++) = blank_b;
 | 
				
			||||||
 | 
					                   
 | 
				
			||||||
 | 
					                    if (has_alpha)
 | 
				
			||||||
 | 
					                        *(alpha_dst++) = 0;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -1872,18 +1957,30 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i
 | 
				
			|||||||
                    *(dst++) = *(p++);
 | 
					                    *(dst++) = *(p++);
 | 
				
			||||||
                    *(dst++) = *(p++);
 | 
					                    *(dst++) = *(p++);
 | 
				
			||||||
                    *(dst++) = *p;
 | 
					                    *(dst++) = *p;
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    if (has_alpha)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        unsigned char *p = alpha[ys] + (xs);
 | 
				
			||||||
 | 
					                        *(alpha_dst++) = *p;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    *(dst++) = blank_r;
 | 
					                    *(dst++) = blank_r;
 | 
				
			||||||
                    *(dst++) = blank_g;
 | 
					                    *(dst++) = blank_g;
 | 
				
			||||||
                    *(dst++) = blank_b;
 | 
					                    *(dst++) = blank_b;
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    if (has_alpha)
 | 
				
			||||||
 | 
					                        *(alpha_dst++) = 255;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    delete [] data;
 | 
					    delete [] data;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (has_alpha)
 | 
				
			||||||
 | 
					        delete [] alpha;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return rotated;
 | 
					    return rotated;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user