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:
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user