in TwitterImagePipeline/TIPImageUtils.m [225:295]
BOOL TIPCGImageHasAlpha(CGImageRef imageRef, BOOL inspectPixels)
{
BOOL isLeadingByteAlpha = YES;
const CGBitmapInfo bmpInfo = CGImageGetBitmapInfo(imageRef);
const CGImageAlphaInfo alphaInfo = bmpInfo & kCGBitmapAlphaInfoMask;
switch (alphaInfo) {
case kCGImageAlphaNone:
if (CGImageIsMask(imageRef)) {
if (inspectPixels) {
break;
}
return YES; // alpha mask
}
case kCGImageAlphaNoneSkipLast:
case kCGImageAlphaNoneSkipFirst:
return NO;
case kCGImageAlphaPremultipliedLast:
case kCGImageAlphaLast:
isLeadingByteAlpha = NO;
case kCGImageAlphaPremultipliedFirst:
case kCGImageAlphaFirst:
if (inspectPixels) {
break;
}
case kCGImageAlphaOnly:
return YES;
}
if (TIP_BITMASK_HAS_SUBSET_FLAGS(bmpInfo, kCGBitmapFloatComponents)) {
return YES; // bail, only tested with 8-bit components
}
const size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
if (bitsPerComponent != 8) {
return YES; // bail
}
CGColorSpaceRef const colorSpace = CGImageGetColorSpace(imageRef);
const size_t numberOfComponents = colorSpace ? CGColorSpaceGetNumberOfComponents(colorSpace) : 0;
const CGSize size = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
const size_t expectedBytesPerRow = (numberOfComponents + 1) * (size_t)size.width * (bitsPerComponent / 8);
const size_t byteSluffPerRow = CGImageGetBytesPerRow(imageRef) - expectedBytesPerRow;
if (byteSluffPerRow > CGImageGetBytesPerRow(imageRef)) {
return YES; // bail - underflow
}
const int alphaByteIndex = _TIPImageByteIndexOfAlphaComponent(bmpInfo, numberOfComponents, isLeadingByteAlpha);
if (alphaByteIndex < 0) {
return YES; // bail
}
CGDataProviderRef const dataProvider = CGImageGetDataProvider(imageRef);
CFRetain(dataProvider);
TIPDeferRelease(dataProvider);
CFDataRef const data = CGDataProviderCopyData(dataProvider);
TIPDeferRelease(data);
const UInt8 *byteComponent = CFDataGetBytePtr(data);
for (size_t iRow = 0; iRow < (size_t)size.height; iRow++) {
const UInt8 * const endRowByte = byteComponent + expectedBytesPerRow;
while (byteComponent < endRowByte) {
if (0xFF != byteComponent[alphaByteIndex]) {
return YES;
}
byteComponent += numberOfComponents + 1;
}
byteComponent += byteSluffPerRow;
}
return NO;
}