wxBitmap ConvertTo24Bit( wxColor bgColor, wxBitmap front ) { if( front.GetDepth() == 24 ) return front; wxBitmap result( front.GetWidth(), front.GetHeight(), 24 ); front.UseAlpha(); wxImage im_front = front.ConvertToImage(); wxImage im_result = result.ConvertToImage(); unsigned char *presult = im_result.GetData(); unsigned char *pfront = im_front.GetData(); unsigned char *afront = NULL; if( im_front.HasAlpha() ) afront = im_front.GetAlpha(); for( int i = 0; i < result.GetWidth(); i++ ) { for( int j = 0; j < result.GetHeight(); j++ ) { double alphaF = (double) ( *afront++ ) / 256.0; unsigned char r = *pfront++ * alphaF + bgColor.Red() * ( 1.0 - alphaF ); *presult++ = r; unsigned char g = *pfront++ * alphaF + bgColor.Green() * ( 1.0 - alphaF ); *presult++ = g; unsigned char b = *pfront++ * alphaF + bgColor.Blue() * ( 1.0 - alphaF ); *presult++ = b; } } result = wxBitmap( im_result ); return result; }
wxBitmap MergeBitmaps( wxBitmap back, wxBitmap front, wxSize offset ) { wxBitmap merged( back.GetWidth(), back.GetHeight(), back.GetDepth() ); // If the front bitmap has no alpha channel, then merging will accomplish nothing // So, simply return the bitmap intact wxImage im_front = front.ConvertToImage(); if(!im_front.HasAlpha()) return front; #if !wxCHECK_VERSION(2,9,4) // Manual alpha blending for broken wxWidgets alpha bitmap support, pervasive in wx2.8. merged.UseAlpha(); back.UseAlpha(); front.UseAlpha(); // wxImage im_front = front.ConvertToImage(); wxImage im_back = back.ConvertToImage(); wxImage im_result = back.ConvertToImage();// Only way to make result have alpha channel in wxW 2.8. unsigned char *presult = im_result.GetData(); unsigned char *pback = im_back.GetData(); unsigned char *pfront = im_front.GetData(); unsigned char *afront = NULL; if( im_front.HasAlpha() ) afront = im_front.GetAlpha(); unsigned char *aback = NULL; if( im_back.HasAlpha() ) aback = im_back.GetAlpha(); unsigned char *aresult = NULL; if( im_result.HasAlpha() ) aresult = im_result.GetAlpha(); // Do alpha blending, associative version of "over" operator. if(presult && pback && pfront){ for( int i = 0; i < back.GetHeight(); i++ ) { for( int j = 0; j < back.GetWidth(); j++ ) { int fX = j - offset.x; int fY = i - offset.y; bool inFront = true; if( fX < 0 || fY < 0 ) inFront = false; if( fX >= front.GetWidth() ) inFront = false; if( fY >= front.GetHeight() ) inFront = false; if( inFront ) { double alphaF = (double) ( *afront++ ) / 256.0; double alphaB = (double) ( *aback++ ) / 256.0; double alphaRes = alphaF + alphaB * ( 1.0 - alphaF ); unsigned char a = alphaRes * 256; *aresult++ = a; unsigned char r = (*pfront++ * alphaF + *pback++ * alphaB * ( 1.0 - alphaF )) / alphaRes; *presult++ = r; unsigned char g = (*pfront++ * alphaF + *pback++ * alphaB * ( 1.0 - alphaF )) / alphaRes; *presult++ = g; unsigned char b = (*pfront++ * alphaF + *pback++ * alphaB * ( 1.0 - alphaF )) / alphaRes; *presult++ = b; } else { *aresult++ = *aback++; *presult++ = *pback++; *presult++ = *pback++; *presult++ = *pback++; } } } } merged = wxBitmap( im_result ); #else wxMemoryDC mdc( merged ); mdc.DrawBitmap( back, 0, 0, true ); mdc.DrawBitmap( front, offset.x, offset.y, true ); mdc.SelectObject( wxNullBitmap ); #endif return merged; }
wxBitmap MergeBitmaps( wxBitmap back, wxBitmap front, wxSize offset ) { wxBitmap merged( back.GetWidth(), back.GetHeight(), back.GetDepth() ); #if (defined(__WXGTK__) || defined(__WXMAC__)) // Manual alpha blending for broken wxWidgets platforms. merged.UseAlpha(); back.UseAlpha(); front.UseAlpha(); wxImage im_front = front.ConvertToImage(); wxImage im_back = back.ConvertToImage(); wxImage im_result = back.ConvertToImage();// Only way to make result have alpha channel in wxW 2.8. unsigned char *presult = im_result.GetData(); unsigned char *pback = im_back.GetData(); unsigned char *pfront = im_front.GetData(); unsigned char *afront = NULL; if( im_front.HasAlpha() ) afront = im_front.GetAlpha(); unsigned char *aback = NULL; if( im_back.HasAlpha() ) aback = im_back.GetAlpha(); unsigned char *aresult = NULL; if( im_result.HasAlpha() ) aresult = im_result.GetAlpha(); // Do alpha blending, associative version of "over" operator. for( int i = 0; i < back.GetHeight(); i++ ) { for( int j = 0; j < back.GetWidth(); j++ ) { int fX = j - offset.x; int fY = i - offset.y; bool inFront = true; if( fX < 0 || fY < 0 ) inFront = false; if( fX >= front.GetWidth() ) inFront = false; if( fY >= front.GetHeight() ) inFront = false; if( inFront ) { double alphaF = (double) ( *afront++ ) / 256.0; double alphaB = (double) ( *aback++ ) / 256.0; double alphaRes = alphaF + alphaB * ( 1.0 - alphaF ); unsigned char a = alphaRes * 256; *aresult++ = a; unsigned char r = (*pfront++ * alphaF + *pback++ * alphaB * ( 1.0 - alphaF )) / alphaRes; *presult++ = r; unsigned char g = (*pfront++ * alphaF + *pback++ * alphaB * ( 1.0 - alphaF )) / alphaRes; *presult++ = g; unsigned char b = (*pfront++ * alphaF + *pback++ * alphaB * ( 1.0 - alphaF )) / alphaRes; *presult++ = b; } else { *aresult++ = *aback++; *presult++ = *pback++; *presult++ = *pback++; *presult++ = *pback++; } } } merged = wxBitmap( im_result ); #else wxMemoryDC mdc( merged ); mdc.DrawBitmap( back, 0, 0, true ); mdc.DrawBitmap( front, offset.x, offset.y, true ); mdc.SelectObject( wxNullBitmap ); #endif return merged; }