X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/878f28d8c8ae550e5b07916a0c22374850b5091f..8b3eb4a0699f201d864c0b151d0f57269cf6316f:/src/common/image.cpp?ds=sidebyside diff --git a/src/common/image.cpp b/src/common/image.cpp index 4a07012039..28e43c26d3 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -253,6 +253,43 @@ wxObjectRefData* wxImage::CloneRefData(const wxObjectRefData* that) const return refData_new; } +// returns a new image with the same dimensions, alpha, and mask as *this +// if on_its_side is true, width and height are swapped +wxImage wxImage::MakeEmptyClone(int flags) const +{ + wxImage image; + + wxCHECK_MSG( Ok(), image, wxS("invalid image") ); + + long height = M_IMGDATA->m_height; + long width = M_IMGDATA->m_width; + + if ( flags & Clone_SwapOrientation ) + wxSwap( width, height ); + + if ( !image.Create( width, height, false ) ) + { + wxFAIL_MSG( wxS("unable to create image") ); + return image; + } + + if ( M_IMGDATA->m_alpha ) + { + image.SetAlpha(); + wxCHECK2_MSG( image.GetAlpha(), return wxImage(), + wxS("unable to create alpha channel") ); + } + + if ( M_IMGDATA->m_hasMask ) + { + image.SetMaskColour( M_IMGDATA->m_maskRed, + M_IMGDATA->m_maskGreen, + M_IMGDATA->m_maskBlue ); + } + + return image; +} + wxImage wxImage::Copy() const { wxImage image; @@ -295,11 +332,11 @@ wxImage wxImage::ShrinkBy( int xFactor , int yFactor ) const bool hasMask = false ; unsigned char maskRed = 0; unsigned char maskGreen = 0; - unsigned char maskBlue =0 ; + unsigned char maskBlue = 0 ; - unsigned char *source_data = M_IMGDATA->m_data; + const unsigned char *source_data = M_IMGDATA->m_data; unsigned char *target_data = data; - unsigned char *source_alpha = 0 ; + const unsigned char *source_alpha = 0 ; unsigned char *target_alpha = 0 ; if (M_IMGDATA->m_hasMask) { @@ -337,7 +374,7 @@ wxImage wxImage::ShrinkBy( int xFactor , int yFactor ) const long y_offset = (y * yFactor + y1) * old_width; for ( int x1 = 0 ; x1 < xFactor ; ++x1 ) { - unsigned char *pixel = source_data + 3 * ( y_offset + x * xFactor + x1 ) ; + const unsigned char *pixel = source_data + 3 * ( y_offset + x * xFactor + x1 ) ; unsigned char red = pixel[0] ; unsigned char green = pixel[1] ; unsigned char blue = pixel[2] ; @@ -462,9 +499,9 @@ wxImage wxImage::ResampleNearest(int width, int height) const wxCHECK_MSG( data, image, wxT("unable to create image") ); - unsigned char *source_data = M_IMGDATA->m_data; + const unsigned char *source_data = M_IMGDATA->m_data; unsigned char *target_data = data; - unsigned char *source_alpha = 0 ; + const unsigned char *source_alpha = 0 ; unsigned char *target_alpha = 0 ; if ( !M_IMGDATA->m_hasMask ) @@ -487,14 +524,14 @@ wxImage wxImage::ResampleNearest(int width, int height) const long y = 0; for ( long j = 0; j < height; j++ ) { - unsigned char* src_line = &source_data[(y>>16)*old_width*3]; - unsigned char* src_alpha_line = source_alpha ? &source_alpha[(y>>16)*old_width] : 0 ; + const unsigned char* src_line = &source_data[(y>>16)*old_width*3]; + const unsigned char* src_alpha_line = source_alpha ? &source_alpha[(y>>16)*old_width] : 0 ; long x = 0; for ( long i = 0; i < width; i++ ) { - unsigned char* src_pixel = &src_line[(x>>16)*3]; - unsigned char* src_alpha_pixel = source_alpha ? &src_alpha_line[(x>>16)] : 0 ; + const unsigned char* src_pixel = &src_line[(x>>16)*3]; + const unsigned char* src_alpha_pixel = source_alpha ? &src_alpha_line[(x>>16)] : 0 ; dest_pixel[0] = src_pixel[0]; dest_pixel[1] = src_pixel[1]; dest_pixel[2] = src_pixel[2]; @@ -525,8 +562,8 @@ wxImage wxImage::ResampleBox(int width, int height) const const int scale_factor_x_2 = (int)(scale_factor_x / 2); const int scale_factor_y_2 = (int)(scale_factor_y / 2); - unsigned char* src_data = M_IMGDATA->m_data; - unsigned char* src_alpha = M_IMGDATA->m_alpha; + const unsigned char* src_data = M_IMGDATA->m_data; + const unsigned char* src_alpha = M_IMGDATA->m_alpha; unsigned char* dst_data = ret_image.GetData(); unsigned char* dst_alpha = NULL; @@ -599,8 +636,8 @@ wxImage wxImage::ResampleBilinear(int width, int height) const { // This function implements a Bilinear algorithm for resampling. wxImage ret_image(width, height, false); - unsigned char* src_data = M_IMGDATA->m_data; - unsigned char* src_alpha = M_IMGDATA->m_alpha; + const unsigned char* src_data = M_IMGDATA->m_data; + const unsigned char* src_alpha = M_IMGDATA->m_alpha; unsigned char* dst_data = ret_image.GetData(); unsigned char* dst_alpha = NULL; @@ -652,21 +689,21 @@ wxImage wxImage::ResampleBilinear(int width, int height) const int src_pixel_index10 = y_offset2 * M_IMGDATA->m_width + x_offset1; int src_pixel_index11 = y_offset2 * M_IMGDATA->m_width + x_offset2; - //first line + // first line r1 = src_data[src_pixel_index00 * 3 + 0] * dx1 + src_data[src_pixel_index01 * 3 + 0] * dx; g1 = src_data[src_pixel_index00 * 3 + 1] * dx1 + src_data[src_pixel_index01 * 3 + 1] * dx; b1 = src_data[src_pixel_index00 * 3 + 2] * dx1 + src_data[src_pixel_index01 * 3 + 2] * dx; if ( src_alpha ) a1 = src_alpha[src_pixel_index00] * dx1 + src_alpha[src_pixel_index01] * dx; - //second line + // second line r2 = src_data[src_pixel_index10 * 3 + 0] * dx1 + src_data[src_pixel_index11 * 3 + 0] * dx; g2 = src_data[src_pixel_index10 * 3 + 1] * dx1 + src_data[src_pixel_index11 * 3 + 1] * dx; b2 = src_data[src_pixel_index10 * 3 + 2] * dx1 + src_data[src_pixel_index11 * 3 + 2] * dx; if ( src_alpha ) a2 = src_alpha[src_pixel_index10] * dx1 + src_alpha[src_pixel_index11] * dx; - //result lines + // result lines dst_data[0] = static_cast(r1 * dy1 + r2 * dy); dst_data[1] = static_cast(g1 * dy1 + g2 * dy); @@ -729,8 +766,8 @@ wxImage wxImage::ResampleBicubic(int width, int height) const ret_image.Create(width, height, false); - unsigned char* src_data = M_IMGDATA->m_data; - unsigned char* src_alpha = M_IMGDATA->m_alpha; + const unsigned char* src_data = M_IMGDATA->m_data; + const unsigned char* src_alpha = M_IMGDATA->m_alpha; unsigned char* dst_data = ret_image.GetData(); unsigned char* dst_alpha = NULL; @@ -813,26 +850,14 @@ wxImage wxImage::ResampleBicubic(int width, int height) const // Blur in the horizontal direction wxImage wxImage::BlurHorizontal(int blurRadius) const { - wxImage ret_image; - ret_image.Create(M_IMGDATA->m_width, M_IMGDATA->m_height, false); + wxImage ret_image(MakeEmptyClone()); - unsigned char* src_data = M_IMGDATA->m_data; - unsigned char* dst_data = ret_image.GetData(); - unsigned char* src_alpha = M_IMGDATA->m_alpha; - unsigned char* dst_alpha = NULL; + wxCHECK( ret_image.Ok(), ret_image ); - // Check for a mask or alpha - if ( src_alpha ) - { - ret_image.SetAlpha(); - dst_alpha = ret_image.GetAlpha(); - } - else if ( M_IMGDATA->m_hasMask ) - { - ret_image.SetMaskColour(M_IMGDATA->m_maskRed, - M_IMGDATA->m_maskGreen, - M_IMGDATA->m_maskBlue); - } + const unsigned char* src_data = M_IMGDATA->m_data; + unsigned char* dst_data = ret_image.GetData(); + const unsigned char* src_alpha = M_IMGDATA->m_alpha; + unsigned char* dst_alpha = ret_image.GetAlpha(); // number of pixels we average over const int blurArea = blurRadius*2 + 1; @@ -928,26 +953,14 @@ wxImage wxImage::BlurHorizontal(int blurRadius) const // Blur in the vertical direction wxImage wxImage::BlurVertical(int blurRadius) const { - wxImage ret_image; - ret_image.Create(M_IMGDATA->m_width, M_IMGDATA->m_height, false); + wxImage ret_image(MakeEmptyClone()); - unsigned char* src_data = M_IMGDATA->m_data; - unsigned char* dst_data = ret_image.GetData(); - unsigned char* src_alpha = M_IMGDATA->m_alpha; - unsigned char* dst_alpha = NULL; + wxCHECK( ret_image.Ok(), ret_image ); - // Check for a mask or alpha - if ( src_alpha ) - { - ret_image.SetAlpha(); - dst_alpha = ret_image.GetAlpha(); - } - else if ( M_IMGDATA->m_hasMask ) - { - ret_image.SetMaskColour(M_IMGDATA->m_maskRed, - M_IMGDATA->m_maskGreen, - M_IMGDATA->m_maskBlue); - } + const unsigned char* src_data = M_IMGDATA->m_data; + unsigned char* dst_data = ret_image.GetData(); + const unsigned char* src_alpha = M_IMGDATA->m_alpha; + unsigned char* dst_alpha = ret_image.GetAlpha(); // number of pixels we average over const int blurArea = blurRadius*2 + 1; @@ -1055,38 +1068,33 @@ wxImage wxImage::Blur(int blurRadius) const wxImage wxImage::Rotate90( bool clockwise ) const { - wxImage image; - - wxCHECK_MSG( Ok(), image, wxT("invalid image") ); + wxImage image(MakeEmptyClone(Clone_SwapOrientation)); - image.Create( M_IMGDATA->m_height, M_IMGDATA->m_width, false ); - - unsigned char *data = image.GetData(); - - wxCHECK_MSG( data, image, wxT("unable to create image") ); + wxCHECK( image.Ok(), image ); - unsigned char *source_data = M_IMGDATA->m_data; - unsigned char *target_data; - unsigned char *alpha_data = 0 ; - unsigned char *source_alpha = 0 ; - unsigned char *target_alpha = 0 ; + long height = M_IMGDATA->m_height; + long width = M_IMGDATA->m_width; - if (M_IMGDATA->m_hasMask) + if ( HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_X) ) { - image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue ); + int hot_x = GetOptionInt( wxIMAGE_OPTION_CUR_HOTSPOT_X ); + image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, + clockwise ? hot_x : width - 1 - hot_x); } - else + + if ( HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y) ) { - source_alpha = M_IMGDATA->m_alpha ; - if ( source_alpha ) - { - image.SetAlpha() ; - alpha_data = image.GetAlpha() ; - } + int hot_y = GetOptionInt( wxIMAGE_OPTION_CUR_HOTSPOT_Y ); + image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, + clockwise ? height - 1 - hot_y : hot_y); } - long height = M_IMGDATA->m_height; - long width = M_IMGDATA->m_width; + unsigned char *data = image.GetData(); + const unsigned char *source_data = M_IMGDATA->m_data; + unsigned char *target_data; + unsigned char *alpha_data = image.GetAlpha(); + const unsigned char *source_alpha = M_IMGDATA->m_alpha; + unsigned char *target_alpha = 0 ; for (long j = 0; j < height; j++) { @@ -1095,19 +1103,19 @@ wxImage wxImage::Rotate90( bool clockwise ) const if (clockwise) { target_data = data + (((i+1)*height) - j - 1)*3; - if(source_alpha) + if (source_alpha) target_alpha = alpha_data + (((i+1)*height) - j - 1); } else { target_data = data + ((height*(width-1)) + j - (i*height))*3; - if(source_alpha) + if (source_alpha) target_alpha = alpha_data + ((height*(width-1)) + j - (i*height)); } memcpy( target_data, source_data, 3 ); source_data += 3; - if(source_alpha) + if (source_alpha) { memcpy( target_alpha, source_alpha, 1 ); source_alpha += 1; @@ -1118,32 +1126,71 @@ wxImage wxImage::Rotate90( bool clockwise ) const return image; } -wxImage wxImage::Mirror( bool horizontally ) const +wxImage wxImage::Rotate180() const { - wxImage image; + wxImage image(MakeEmptyClone()); - wxCHECK_MSG( Ok(), image, wxT("invalid image") ); + wxCHECK( image.Ok(), image ); - image.Create( M_IMGDATA->m_width, M_IMGDATA->m_height, false ); + long height = M_IMGDATA->m_height; + long width = M_IMGDATA->m_width; + + if ( HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_X) ) + { + image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, + width - 1 - GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X)); + } + + if ( HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y) ) + { + image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, + height - 1 - GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y)); + } unsigned char *data = image.GetData(); - unsigned char *alpha = NULL; + unsigned char *alpha = image.GetAlpha(); + const unsigned char *source_data = M_IMGDATA->m_data; + unsigned char *target_data = data + width * height * 3; - wxCHECK_MSG( data, image, wxT("unable to create image") ); + for (long j = 0; j < height; j++) + { + for (long i = 0; i < width; i++) + { + target_data -= 3; + memcpy( target_data, source_data, 3 ); + source_data += 3; + } + } - if (M_IMGDATA->m_alpha != NULL) { - image.SetAlpha(); - alpha = image.GetAlpha(); - wxCHECK_MSG( alpha, image, wxT("unable to create alpha channel") ); + if ( alpha ) + { + const unsigned char *src_alpha = M_IMGDATA->m_alpha; + unsigned char *dest_alpha = alpha + width * height; + + for (long j = 0; j < height; ++j) + { + for (long i = 0; i < width; ++i) + { + *(--dest_alpha) = *(src_alpha++); + } + } } - if (M_IMGDATA->m_hasMask) - image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue ); + return image; +} + +wxImage wxImage::Mirror( bool horizontally ) const +{ + wxImage image(MakeEmptyClone()); + + wxCHECK( image.Ok(), image ); long height = M_IMGDATA->m_height; long width = M_IMGDATA->m_width; - unsigned char *source_data = M_IMGDATA->m_data; + unsigned char *data = image.GetData(); + unsigned char *alpha = image.GetAlpha(); + const unsigned char *source_data = M_IMGDATA->m_data; unsigned char *target_data; if (horizontally) @@ -1188,7 +1235,7 @@ wxImage wxImage::Mirror( bool horizontally ) const source_data += 3*width; } - if (alpha != NULL) + if ( alpha ) { // src_alpha starts at the first pixel and increases by 1 width after each step // (a step here is the copy of the alpha channel of an entire line) @@ -1231,7 +1278,7 @@ wxImage wxImage::GetSubImage( const wxRect &rect ) const wxCHECK_MSG( subdata, image, wxT("unable to create image") ); - if (src_alpha != NULL) { + if ( src_alpha ) { image.SetAlpha(); subalpha = image.GetAlpha(); wxCHECK_MSG( subalpha, image, wxT("unable to create alpha channel")); @@ -1350,10 +1397,10 @@ void wxImage::Paste( const wxImage &image, int x, int y ) (GetMaskGreen()==image.GetMaskGreen()) && (GetMaskBlue()==image.GetMaskBlue())))) { - unsigned char* source_data = image.GetData() + xx*3 + yy*3*image.GetWidth(); + const unsigned char* source_data = image.GetData() + 3*(xx + yy*image.GetWidth()); int source_step = image.GetWidth()*3; - unsigned char* target_data = GetData() + (x+xx)*3 + (y+yy)*3*M_IMGDATA->m_width; + unsigned char* target_data = GetData() + 3*((x+xx) + (y+yy)*M_IMGDATA->m_width); int target_step = M_IMGDATA->m_width*3; for (int j = 0; j < height; j++) { @@ -1369,7 +1416,7 @@ void wxImage::Paste( const wxImage &image, int x, int y ) if ( !HasAlpha() ) InitAlpha(); - unsigned char* source_data = image.GetAlpha() + xx + yy*image.GetWidth(); + const unsigned char* source_data = image.GetAlpha() + xx + yy*image.GetWidth(); int source_step = image.GetWidth(); unsigned char* target_data = GetAlpha() + (x+xx) + (y+yy)*M_IMGDATA->m_width; @@ -1389,10 +1436,10 @@ void wxImage::Paste( const wxImage &image, int x, int y ) unsigned char g = image.GetMaskGreen(); unsigned char b = image.GetMaskBlue(); - unsigned char* source_data = image.GetData() + xx*3 + yy*3*image.GetWidth(); + const unsigned char* source_data = image.GetData() + 3*(xx + yy*image.GetWidth()); int source_step = image.GetWidth()*3; - unsigned char* target_data = GetData() + (x+xx)*3 + (y+yy)*3*M_IMGDATA->m_width; + unsigned char* target_data = GetData() + 3*((x+xx) + (y+yy)*M_IMGDATA->m_width); int target_step = M_IMGDATA->m_width*3; for (int j = 0; j < height; j++) @@ -1444,47 +1491,33 @@ wxImage wxImage::ConvertToGreyscale(void) const wxImage wxImage::ConvertToGreyscale(double weight_r, double weight_g, double weight_b) const { - wxImage image; + wxImage image(MakeEmptyClone()); - wxCHECK_MSG( Ok(), image, wxT("invalid image") ); - - image.Create(M_IMGDATA->m_width, M_IMGDATA->m_height, false); + wxCHECK( image.Ok(), image ); + const unsigned char *src = M_IMGDATA->m_data; unsigned char *dest = image.GetData(); - wxCHECK_MSG( dest, image, wxT("unable to create image") ); - - unsigned char *src = M_IMGDATA->m_data; - bool hasMask = M_IMGDATA->m_hasMask; - unsigned char maskRed = M_IMGDATA->m_maskRed; - unsigned char maskGreen = M_IMGDATA->m_maskGreen; - unsigned char maskBlue = M_IMGDATA->m_maskBlue; - - if ( hasMask ) - image.SetMaskColour(maskRed, maskGreen, maskBlue); + const bool hasMask = M_IMGDATA->m_hasMask; + const unsigned char maskRed = M_IMGDATA->m_maskRed; + const unsigned char maskGreen = M_IMGDATA->m_maskGreen; + const unsigned char maskBlue = M_IMGDATA->m_maskBlue; const long size = M_IMGDATA->m_width * M_IMGDATA->m_height; for ( long i = 0; i < size; i++, src += 3, dest += 3 ) { memcpy(dest, src, 3); - // don't modify the mask - if ( hasMask && src[0] == maskRed && src[1] == maskGreen && src[2] == maskBlue ) - { - } - else + // only modify non-masked pixels + if ( !hasMask || src[0] != maskRed || src[1] != maskGreen || src[2] != maskBlue ) { wxColour::MakeGrey(dest + 0, dest + 1, dest + 2, weight_r, weight_g, weight_b); } } // copy the alpha channel, if any - if (HasAlpha()) + if ( image.HasAlpha() ) { - const size_t alphaSize = GetWidth() * GetHeight(); - unsigned char *alpha = (unsigned char*)malloc(alphaSize); - memcpy(alpha, GetAlpha(), alphaSize); - image.InitAlpha(); - image.SetAlpha(alpha); + memcpy( image.GetAlpha(), GetAlpha(), GetWidth() * GetHeight() ); } return image;