ImageIO is really easy to use you just need to give it something - a URL or a Data provider or whatever and it will turn it into a CGImage. The only issue with CGImage is that it is not possible to get to at the pixel data. In Cello there is a fair amount of code that manipulates pixels directly - so I have to facilitate this.
A solution is to draw the image onto a bitmap where you own the pixels - CGBitmapContextCreate will create a bitmap context and the following code fragment will draw it.
In this there are a couple of wrinkles.
CGRect drawRect = ::CGRectMake(0, 0, width, height);
::CGContextTranslateCTM(context.get(), 0.0, float(height));
::CGContextScaleCTM(context.get(), 1.0, -1.0 );
::CGContextDrawImage(context.get(), drawRect, theImage);
- CGBitmapContextCreate won't work on an indexed bitmap. So all the images will be converted to either RGB32 or RGBA32. I don't see this as a big deal.
- CGBitmapContextCreate will only work with premultiplied alpha. Cello assumes the alpha is not premultiplied. The easiest thing to do is to wholesale convert the bitmap to nom-premultiplied alpha after the fact.
It is, of course, entirely non-optimized - but as this will happen as a single hit when an image is read I don't see it as being any kind of bottle neck. If it turns out to soak up time and that this is a problem I will attack it later.
inline UInt32 Unpremultiply(UInt32 c, Float32 inverseAlpha)
{
UInt32 result = UInt32(Float32(c) * inverseAlpha);
result = std::min(result, 255);
return result;
}
void BitmapClass::UnpremultiplyRGBA()
{
UInt8* pRow = reinterpret_cast(m_pBits);
for (int row = m_height; row > 0; --row)
{
UInt32* pPixel = reinterpret_cast(pRow);
for (int column = m_width; column > 0; --column)
{
UInt32 alpha = GetAValue(*pPixel);
if (alpha)
{
Float32 inverseAlpha = 255.0/alpha;
UInt32 red = Unpremultiply(GetRValue(*pPixel), inverseAlpha);
UInt32 green = Unpremultiply(GetGValue(*pPixel), inverseAlpha);
UInt32 blue = Unpremultiply(GetBValue(*pPixel), inverseAlpha);
*pPixel = RGBA(red, green, blue, alpha);
}
else
*pPixel = 0;
++pPixel;
}
pRow += m_iByteWidth;
}
}
No comments:
Post a Comment