Fix creating CGImage from bitmap data
Alpha channel values of created CGImage should be a superposition of the actual alpha channel values and bitmap mask (if exists). See #18498.
This commit is contained in:
@@ -529,7 +529,7 @@ IconRef wxBitmapRefData::GetIconRef()
|
|||||||
|
|
||||||
if ( mask )
|
if ( mask )
|
||||||
{
|
{
|
||||||
a = 0xFF - *masksource++ ;
|
a = *masksource++ ;
|
||||||
}
|
}
|
||||||
else if ( !hasAlpha )
|
else if ( !hasAlpha )
|
||||||
a = 0xFF ;
|
a = 0xFF ;
|
||||||
@@ -610,7 +610,7 @@ IconRef wxBitmapRefData::GetIconRef()
|
|||||||
*dest++ = b ;
|
*dest++ = b ;
|
||||||
|
|
||||||
if ( mask )
|
if ( mask )
|
||||||
*maskdest++ = 0xFF - *masksource++ ;
|
*maskdest++ = *masksource++ ;
|
||||||
else if ( hasAlpha )
|
else if ( hasAlpha )
|
||||||
*maskdest++ = a ;
|
*maskdest++ = a ;
|
||||||
else
|
else
|
||||||
@@ -652,103 +652,24 @@ CGImageRef wxBitmapRefData::CreateCGImage() const
|
|||||||
CGImageRef image ;
|
CGImageRef image ;
|
||||||
if ( m_rawAccessCount > 0 || m_cgImageRef == NULL )
|
if ( m_rawAccessCount > 0 || m_cgImageRef == NULL )
|
||||||
{
|
{
|
||||||
if (m_nsImage)
|
if ( m_hBitmap )
|
||||||
{
|
{
|
||||||
image = wxOSXCreateCGImageFromImage(m_nsImage);
|
image = CGBitmapContextCreateImage(m_hBitmap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (GetDepth() != 1 && m_bitmapMask == NULL)
|
image = wxOSXCreateCGImageFromImage(m_nsImage);
|
||||||
{
|
}
|
||||||
#if 0
|
|
||||||
// in order for this code to work properly, wxMask would have to invert black and white
|
|
||||||
// in the native bitmap
|
|
||||||
if ( m_bitmapMask )
|
|
||||||
{
|
|
||||||
CGImageRef tempImage = CGBitmapContextCreateImage( m_hBitmap );
|
|
||||||
CGImageRef tempMask = CGBitmapContextCreateImage((CGContextRef) m_bitmapMask->GetHBITMAP() );
|
|
||||||
image = CGImageCreateWithMask( tempImage, tempMask );
|
|
||||||
CGImageRelease(tempMask);
|
|
||||||
CGImageRelease(tempImage);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
image = CGBitmapContextCreateImage(m_hBitmap);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
size_t imageSize = GetHeight() * GetBytesPerRow();
|
|
||||||
|
|
||||||
int w = GetWidth();
|
if ( m_bitmapMask )
|
||||||
int h = GetHeight();
|
{
|
||||||
CGImageAlphaInfo alphaInfo = kCGImageAlphaNoneSkipFirst;
|
CGImageRef imageMask = CGBitmapContextCreateImage(m_bitmapMask->GetHBITMAP());
|
||||||
wxMemoryBuffer membuf;
|
CGImageRef imageBmp = image;
|
||||||
|
|
||||||
if (m_bitmapMask)
|
image = CGImageCreateWithMask(imageBmp, imageMask);
|
||||||
{
|
|
||||||
alphaInfo = kCGImageAlphaFirst;
|
|
||||||
unsigned char* destalphastart = (unsigned char*)membuf.GetWriteBuf(imageSize);
|
|
||||||
memcpy(destalphastart, GetRawAccess(), imageSize);
|
|
||||||
unsigned char* sourcemaskstart = (unsigned char*)m_bitmapMask->GetRawAccess();
|
|
||||||
int maskrowbytes = m_bitmapMask->GetBytesPerRow();
|
|
||||||
for (int y = 0; y < h; ++y, destalphastart += GetBytesPerRow(), sourcemaskstart += maskrowbytes)
|
|
||||||
{
|
|
||||||
unsigned char* sourcemask = sourcemaskstart;
|
|
||||||
unsigned char* destalpha = destalphastart;
|
|
||||||
for (int x = 0; x < w; ++x, sourcemask += kMaskBytesPerPixel, destalpha += 4)
|
|
||||||
{
|
|
||||||
*destalpha = 0xFF - *sourcemask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
membuf.UngetWriteBuf(imageSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (HasAlpha())
|
|
||||||
{
|
|
||||||
#if wxOSX_USE_PREMULTIPLIED_ALPHA
|
|
||||||
alphaInfo = kCGImageAlphaPremultipliedFirst;
|
|
||||||
#else
|
|
||||||
alphaInfo = kCGImageAlphaFirst;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
memcpy(membuf.GetWriteBuf(imageSize), GetRawAccess(), imageSize);
|
|
||||||
membuf.UngetWriteBuf(imageSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
CGDataProviderRef dataProvider = NULL;
|
CGImageRelease(imageBmp);
|
||||||
if (GetDepth() == 1)
|
CGImageRelease(imageMask);
|
||||||
{
|
|
||||||
// TODO CHECK ALIGNMENT
|
|
||||||
wxMemoryBuffer maskBuf;
|
|
||||||
unsigned char* maskBufData = (unsigned char*)maskBuf.GetWriteBuf(GetWidth() * GetHeight());
|
|
||||||
unsigned char* bufData = (unsigned char*)membuf.GetData();
|
|
||||||
// copy one color component
|
|
||||||
size_t i = 0;
|
|
||||||
for (int y = 0; y < GetHeight(); bufData += GetBytesPerRow(), ++y)
|
|
||||||
{
|
|
||||||
unsigned char* bufDataIter = bufData + 3;
|
|
||||||
for (int x = 0; x < GetWidth(); bufDataIter += 4, ++x, ++i)
|
|
||||||
{
|
|
||||||
maskBufData[i] = *bufDataIter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
maskBuf.UngetWriteBuf(GetWidth() * GetHeight());
|
|
||||||
|
|
||||||
dataProvider = wxMacCGDataProviderCreateWithMemoryBuffer(maskBuf);
|
|
||||||
|
|
||||||
image = ::CGImageMaskCreate(w, h, 8, 8, GetWidth(), dataProvider, NULL, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CGColorSpaceRef colorSpace = wxMacGetGenericRGBColorSpace();
|
|
||||||
dataProvider = wxMacCGDataProviderCreateWithMemoryBuffer(membuf);
|
|
||||||
image = ::CGImageCreate(
|
|
||||||
w, h, 8, 32, GetBytesPerRow(), colorSpace, alphaInfo,
|
|
||||||
dataProvider, NULL, false, kCGRenderingIntentDefault);
|
|
||||||
}
|
|
||||||
CGDataProviderRelease(dataProvider);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1628,7 +1549,7 @@ bool wxMask::InitFromMonoBitmap(const wxBitmap& bitmap)
|
|||||||
{
|
{
|
||||||
int v = p.Red() + p.Green() + p.Blue();
|
int v = p.Red() + p.Green() + p.Blue();
|
||||||
wxASSERT_MSG( v == 0 || v == 3*0xFF, "Non-monochrome bitmap supplied" );
|
wxASSERT_MSG( v == 0 || v == 3*0xFF, "Non-monochrome bitmap supplied" );
|
||||||
*destdata++ = v < (3 * 0xFF) / 2 ? 0xFF : 0;
|
*destdata++ = v < (3 * 0xFF) / 2 ? 0 : 0xFF;
|
||||||
}
|
}
|
||||||
p = rowStart;
|
p = rowStart;
|
||||||
p.OffsetY(data, 1);
|
p.OffsetY(data, 1);
|
||||||
@@ -1665,9 +1586,9 @@ bool wxMask::InitFromColour(const wxBitmap& bitmap, const wxColour& colour)
|
|||||||
for ( int x = 0 ; x < m_width ; ++x, ++p )
|
for ( int x = 0 ; x < m_width ; ++x, ++p )
|
||||||
{
|
{
|
||||||
if ( wxColour( p.Red(), p.Green(), p.Blue() ) == colour )
|
if ( wxColour( p.Red(), p.Green(), p.Blue() ) == colour )
|
||||||
*destdata++ = 0xFF ;
|
*destdata++ = 0x0 ;
|
||||||
else
|
else
|
||||||
*destdata++ = 0x00 ;
|
*destdata++ = 0xFF ;
|
||||||
}
|
}
|
||||||
p = rowStart;
|
p = rowStart;
|
||||||
p.OffsetY(data, 1);
|
p.OffsetY(data, 1);
|
||||||
@@ -1702,7 +1623,7 @@ wxBitmap wxMask::GetBitmap() const
|
|||||||
{
|
{
|
||||||
const unsigned char byte = *src;
|
const unsigned char byte = *src;
|
||||||
wxASSERT( byte == 0 || byte == 0xFF );
|
wxASSERT( byte == 0 || byte == 0xFF );
|
||||||
p.Red() = p.Green() = p.Blue() = ~byte;
|
p.Red() = p.Green() = p.Blue() = byte;
|
||||||
}
|
}
|
||||||
p = rowStart;
|
p = rowStart;
|
||||||
p.OffsetY(data, 1);
|
p.OffsetY(data, 1);
|
||||||
|
Reference in New Issue
Block a user