bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream); if (NULL == imageSrc) { return false; } SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc); CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL); if (NULL == image) { return false; } SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image); const int width = SkToInt(CGImageGetWidth(image)); const int height = SkToInt(CGImageGetHeight(image)); bm->setInfo(SkImageInfo::MakeN32Premul(width, height)); if (SkImageDecoder::kDecodeBounds_Mode == mode) { return true; } if (!this->allocPixelRef(bm, NULL)) { return false; } SkAutoLockPixels alp(*bm); if (!SkCopyPixelsFromCGImage(bm->info(), bm->rowBytes(), bm->getPixels(), image)) { return false; } CGImageAlphaInfo info = CGImageGetAlphaInfo(image); switch (info) { case kCGImageAlphaNone: case kCGImageAlphaNoneSkipLast: case kCGImageAlphaNoneSkipFirst: SkASSERT(SkBitmap::ComputeIsOpaque(*bm)); bm->setAlphaType(kOpaque_SkAlphaType); break; default: // we don't know if we're opaque or not, so compute it. if (SkBitmap::ComputeIsOpaque(*bm)) { bm->setAlphaType(kOpaque_SkAlphaType); } } if (!bm->isOpaque() && this->getRequireUnpremultipliedColors()) { // CGBitmapContext does not support unpremultiplied, so the image has been premultiplied. // Convert to unpremultiplied. for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j) { uint32_t* addr = bm->getAddr32(i, j); *addr = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*addr); } } bm->setAlphaType(kUnpremul_SkAlphaType); } return true; }
bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream); if (NULL == imageSrc) { return false; } SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc); CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL); if (NULL == image) { return false; } SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image); const int width = CGImageGetWidth(image); const int height = CGImageGetHeight(image); bm->setConfig(SkBitmap::kARGB_8888_Config, width, height); if (SkImageDecoder::kDecodeBounds_Mode == mode) { return true; } if (!this->allocPixelRef(bm, NULL)) { return false; } bm->lockPixels(); bm->eraseColor(SK_ColorTRANSPARENT); // use the same colorspace, so we don't change the pixels at all CGColorSpaceRef cs = CGImageGetColorSpace(image); CGContextRef cg = CGBitmapContextCreate(bm->getPixels(), width, height, 8, bm->rowBytes(), cs, BITMAP_INFO); if (NULL == cg) { // perhaps the image's colorspace does not work for a context, so try just rgb cs = CGColorSpaceCreateDeviceRGB(); cg = CGBitmapContextCreate(bm->getPixels(), width, height, 8, bm->rowBytes(), cs, BITMAP_INFO); CFRelease(cs); } CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image); CGContextRelease(cg); CGImageAlphaInfo info = CGImageGetAlphaInfo(image); switch (info) { case kCGImageAlphaNone: case kCGImageAlphaNoneSkipLast: case kCGImageAlphaNoneSkipFirst: SkASSERT(SkBitmap::ComputeIsOpaque(*bm)); bm->setIsOpaque(true); break; default: // we don't know if we're opaque or not, so compute it. bm->computeAndSetOpaquePredicate(); } bm->unlockPixels(); return true; }
bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream); if (NULL == imageSrc) { return false; } SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc); CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL); if (NULL == image) { return false; } SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image); const int width = CGImageGetWidth(image); const int height = CGImageGetHeight(image); bm->setConfig(SkBitmap::kARGB_8888_Config, width, height); if (SkImageDecoder::kDecodeBounds_Mode == mode) { return true; } if (!this->allocPixelRef(bm, NULL)) { return false; } bm->lockPixels(); bm->eraseColor(0); // use the same colorspace, so we don't change the pixels at all CGColorSpaceRef cs = CGImageGetColorSpace(image); CGContextRef cg = CGBitmapContextCreate(bm->getPixels(), width, height, 8, bm->rowBytes(), cs, BITMAP_INFO); CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image); CGContextRelease(cg); bm->unlockPixels(); return true; }
bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream); if (NULL == imageSrc) { return false; } SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc); CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL); if (NULL == image) { return false; } SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image); const int width = SkToInt(CGImageGetWidth(image)); const int height = SkToInt(CGImageGetHeight(image)); bm->setConfig(SkBitmap::kARGB_8888_Config, width, height); if (SkImageDecoder::kDecodeBounds_Mode == mode) { return true; } if (!this->allocPixelRef(bm, NULL)) { return false; } bm->lockPixels(); bm->eraseColor(SK_ColorTRANSPARENT); CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); CGContextRef cg = CGBitmapContextCreate(bm->getPixels(), width, height, 8, bm->rowBytes(), cs, BITMAP_INFO); CFRelease(cs); CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image); CGContextRelease(cg); CGImageAlphaInfo info = CGImageGetAlphaInfo(image); switch (info) { case kCGImageAlphaNone: case kCGImageAlphaNoneSkipLast: case kCGImageAlphaNoneSkipFirst: SkASSERT(SkBitmap::ComputeIsOpaque(*bm)); bm->setAlphaType(kOpaque_SkAlphaType); break; default: // we don't know if we're opaque or not, so compute it. if (SkBitmap::ComputeIsOpaque(*bm)) { bm->setAlphaType(kOpaque_SkAlphaType); } } if (!bm->isOpaque() && this->getRequireUnpremultipliedColors()) { // CGBitmapContext does not support unpremultiplied, so the image has been premultiplied. // Convert to unpremultiplied. for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j) { uint32_t* addr = bm->getAddr32(i, j); *addr = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*addr); } } bm->setAlphaType(kUnpremul_SkAlphaType); } bm->unlockPixels(); return true; }