Handle alpha channel in wxImage::Mirror() and GetSubImage() (patch 1469817)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38762 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2006-04-16 21:37:39 +00:00
parent 2936a6b18c
commit 051924b886
2 changed files with 73 additions and 14 deletions

View File

@@ -106,6 +106,7 @@ All (GUI):
- wxCalendarCtrl positioning and hit-testing fixes for dimensions other than - wxCalendarCtrl positioning and hit-testing fixes for dimensions other than
best size. best size.
- wxCalendarCtrl colour schema changed and adjusted to system settings. - wxCalendarCtrl colour schema changed and adjusted to system settings.
- wxImage::Mirror() and GetSubBitmap() now support alpha (Mickey Rose)
- More checking of image validity before loading into wxImage. - More checking of image validity before loading into wxImage.
- Added wxImage::ConvertToGreyscale. - Added wxImage::ConvertToGreyscale.
- Added ability to use templates with static event tables - Added ability to use templates with static event tables

View File

@@ -250,9 +250,9 @@ wxImage wxImage::Copy() const
image.SetMask( M_IMGDATA->m_hasMask ); image.SetMask( M_IMGDATA->m_hasMask );
memcpy( data, GetData(), M_IMGDATA->m_width*M_IMGDATA->m_height*3 ); memcpy( data, GetData(), M_IMGDATA->m_width*M_IMGDATA->m_height*3 );
wxImageRefData *imgData = (wxImageRefData *)image.m_refData; wxImageRefData *imgData = (wxImageRefData *)image.m_refData;
// also copy the alpha channel // also copy the alpha channel
if (HasAlpha()) if (HasAlpha())
{ {
@@ -260,7 +260,7 @@ wxImage wxImage::Copy() const
unsigned char* alpha = image.GetAlpha(); unsigned char* alpha = image.GetAlpha();
memcpy( alpha, GetAlpha(), M_IMGDATA->m_width*M_IMGDATA->m_height ); memcpy( alpha, GetAlpha(), M_IMGDATA->m_width*M_IMGDATA->m_height );
} }
// also copy the image options // also copy the image options
imgData->m_optionNames = M_IMGDATA->m_optionNames; imgData->m_optionNames = M_IMGDATA->m_optionNames;
imgData->m_optionValues = M_IMGDATA->m_optionValues; imgData->m_optionValues = M_IMGDATA->m_optionValues;
@@ -549,9 +549,16 @@ wxImage wxImage::Mirror( bool horizontally ) const
image.Create( M_IMGDATA->m_width, M_IMGDATA->m_height, false ); image.Create( M_IMGDATA->m_width, M_IMGDATA->m_height, false );
unsigned char *data = image.GetData(); unsigned char *data = image.GetData();
unsigned char *alpha = NULL;
wxCHECK_MSG( data, image, wxT("unable to create image") ); wxCHECK_MSG( data, image, wxT("unable to create image") );
if (M_IMGDATA->m_alpha != NULL) {
image.SetAlpha();
alpha = image.GetAlpha();
wxCHECK_MSG( alpha, image, wxT("unable to create alpha channel") );
}
if (M_IMGDATA->m_hasMask) if (M_IMGDATA->m_hasMask)
image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue ); image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue );
@@ -574,6 +581,25 @@ wxImage wxImage::Mirror( bool horizontally ) const
target_data -= 3; target_data -= 3;
} }
} }
if (alpha != NULL)
{
// src_alpha starts at the first pixel and increases by 1 after each step
// (a step here is the copy of the alpha value of one pixel)
const unsigned char *src_alpha = M_IMGDATA->m_alpha;
// dest_alpha starts just beyond the first line, decreases before each step,
// and after each line is finished, increases by 2 widths (skipping the line
// just copied and the line that will be copied next)
unsigned char *dest_alpha = alpha + width;
for (long jj = 0; jj < height; ++jj)
{
for (long i = 0; i < width; ++i) {
*(--dest_alpha) = *(src_alpha++); // copy one pixel
}
dest_alpha += 2 * width; // advance beyond the end of the next line
}
}
} }
else else
{ {
@@ -583,6 +609,23 @@ wxImage wxImage::Mirror( bool horizontally ) const
memcpy( target_data, source_data, (size_t)3*width ); memcpy( target_data, source_data, (size_t)3*width );
source_data += 3*width; source_data += 3*width;
} }
if (alpha != NULL)
{
// 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)
const unsigned char *src_alpha = M_IMGDATA->m_alpha;
// dest_alpha starts just beyond the last line (beyond the whole image)
// and decreases by 1 width before each step
unsigned char *dest_alpha = alpha + width * height;
for (long jj = 0; jj < height; ++jj)
{
dest_alpha -= width;
memcpy( dest_alpha, src_alpha, (size_t)width );
src_alpha += width;
}
}
} }
return image; return image;
@@ -594,32 +637,47 @@ wxImage wxImage::GetSubImage( const wxRect &rect ) const
wxCHECK_MSG( Ok(), image, wxT("invalid image") ); wxCHECK_MSG( Ok(), image, wxT("invalid image") );
wxCHECK_MSG( (rect.GetLeft()>=0) && (rect.GetTop()>=0) && (rect.GetRight()<=GetWidth()) && (rect.GetBottom()<=GetHeight()), wxCHECK_MSG( (rect.GetLeft()>=0) && (rect.GetTop()>=0) &&
(rect.GetRight()<=GetWidth()) && (rect.GetBottom()<=GetHeight()),
image, wxT("invalid subimage size") ); image, wxT("invalid subimage size") );
int subwidth=rect.GetWidth(); const int subwidth = rect.GetWidth();
const int subheight=rect.GetHeight(); const int subheight = rect.GetHeight();
image.Create( subwidth, subheight, false ); image.Create( subwidth, subheight, false );
unsigned char *subdata = image.GetData(), *data=GetData(); const unsigned char *src_data = GetData();
const unsigned char *src_alpha = M_IMGDATA->m_alpha;
unsigned char *subdata = image.GetData();
unsigned char *subalpha = NULL;
wxCHECK_MSG( subdata, image, wxT("unable to create image") ); wxCHECK_MSG( subdata, image, wxT("unable to create image") );
if (src_alpha != NULL) {
image.SetAlpha();
subalpha = image.GetAlpha();
wxCHECK_MSG( subalpha, image, wxT("unable to create alpha channel"));
}
if (M_IMGDATA->m_hasMask) if (M_IMGDATA->m_hasMask)
image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue ); image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue );
const int subleft=3*rect.GetLeft(); const int width = GetWidth();
const int width=3*GetWidth(); const int pixsoff = rect.GetLeft() + width * rect.GetTop();
subwidth*=3;
data+=rect.GetTop()*width+subleft; src_data += 3 * pixsoff;
src_alpha += pixsoff; // won't be used if was NULL, so this is ok
for (long j = 0; j < subheight; ++j) for (long j = 0; j < subheight; ++j)
{ {
memcpy( subdata, data, subwidth); memcpy( subdata, src_data, 3 * subwidth );
subdata+=subwidth; subdata += 3 * subwidth;
data+=width; src_data += 3 * width;
if (subalpha != NULL) {
memcpy( subalpha, src_alpha, subwidth );
subalpha += subwidth;
src_alpha += width;
}
} }
return image; return image;