diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-04-22 20:24:33 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-04-22 20:24:33 +0000 |
commit | 60b5dce19984a5165f6b2f1d6d477f5e8a940761 (patch) | |
tree | b54e4d9df7b9b1e03307be9f5043b0be92df6a2f /src | |
parent | 945ec3a2bec668ca845071a65df8ec55e8f43819 (diff) |
expose CGImage -> SkBitmap
BUG=skia:
R=scroggo@google.com, halcanary@google.com
Author: reed@google.com
Review URL: https://codereview.chromium.org/243463005
git-svn-id: http://skia.googlecode.com/svn/trunk@14315 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkBitmap.cpp | 3 | ||||
-rw-r--r-- | src/ports/SkImageDecoder_CG.cpp | 19 | ||||
-rw-r--r-- | src/utils/mac/SkCreateCGImageRef.cpp | 147 |
3 files changed, 125 insertions, 44 deletions
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index 2a8c8e45e2..d19e9ca8b9 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -997,7 +997,8 @@ bool SkBitmap::canCopyTo(SkColorType dstColorType) const { switch (dstColorType) { case kAlpha_8_SkColorType: case kRGB_565_SkColorType: - case kN32_SkColorType: + case kRGBA_8888_SkColorType: + case kBGRA_8888_SkColorType: break; case kIndex_8_SkColorType: if (!sameConfigs) { diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp index c683752fdd..b82b677b66 100644 --- a/src/ports/SkImageDecoder_CG.cpp +++ b/src/ports/SkImageDecoder_CG.cpp @@ -68,7 +68,9 @@ bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { const int width = SkToInt(CGImageGetWidth(image)); const int height = SkToInt(CGImageGetHeight(image)); - bm->setConfig(SkBitmap::kARGB_8888_Config, width, height); + SkImageInfo skinfo = SkImageInfo::MakeN32Premul(width, height); + + bm->setConfig(skinfo); if (SkImageDecoder::kDecodeBounds_Mode == mode) { return true; } @@ -76,16 +78,12 @@ bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { if (!this->allocPixelRef(bm, NULL)) { return false; } + + SkAutoLockPixels alp(*bm); - 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); + if (!SkCopyPixelsFromCGImage(bm->info(), bm->rowBytes(), bm->getPixels(), image)) { + return false; + } CGImageAlphaInfo info = CGImageGetAlphaInfo(image); switch (info) { @@ -112,7 +110,6 @@ bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { } bm->setAlphaType(kUnpremul_SkAlphaType); } - bm->unlockPixels(); return true; } diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp index 00166e9ed7..f4374a4877 100644 --- a/src/utils/mac/SkCreateCGImageRef.cpp +++ b/src/utils/mac/SkCreateCGImageRef.cpp @@ -9,6 +9,40 @@ #include "SkBitmap.h" #include "SkColorPriv.h" +static CGBitmapInfo ComputeCGAlphaInfo_RGBA(SkAlphaType at) { + CGBitmapInfo info = kCGBitmapByteOrder32Big; + switch (at) { + case kOpaque_SkAlphaType: + case kIgnore_SkAlphaType: + info |= kCGImageAlphaNoneSkipLast; + break; + case kPremul_SkAlphaType: + info |= kCGImageAlphaPremultipliedLast; + break; + case kUnpremul_SkAlphaType: + info |= kCGImageAlphaLast; + break; + } + return info; +} + +static CGBitmapInfo ComputeCGAlphaInfo_BGRA(SkAlphaType at) { + CGBitmapInfo info = kCGBitmapByteOrder32Little; + switch (at) { + case kOpaque_SkAlphaType: + case kIgnore_SkAlphaType: + info |= kCGImageAlphaNoneSkipFirst; + break; + case kPremul_SkAlphaType: + info |= kCGImageAlphaPremultipliedFirst; + break; + case kUnpremul_SkAlphaType: + info |= kCGImageAlphaFirst; + break; + } + return info; +} + static void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) { SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info); delete bitmap; @@ -28,44 +62,23 @@ static bool getBitmapInfo(const SkBitmap& bm, // doesn't see quite right. Are they thinking 1555? *bitsPerComponent = 5; *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone; - break; -#endif +#else if (upscaleTo32) { *upscaleTo32 = true; } - // fall through - case kN32_SkColorType: + // now treat like RGBA *bitsPerComponent = 8; -#if SK_PMCOLOR_BYTE_ORDER(R,G,B,A) - *info = kCGBitmapByteOrder32Big; - if (bm.isOpaque()) { - *info |= kCGImageAlphaNoneSkipLast; - } else { - *info |= kCGImageAlphaPremultipliedLast; - } -#elif SK_PMCOLOR_BYTE_ORDER(B,G,R,A) - // Matches the CGBitmapInfo that Apple recommends for best - // performance, used by google chrome. - *info = kCGBitmapByteOrder32Little; - if (bm.isOpaque()) { - *info |= kCGImageAlphaNoneSkipFirst; - } else { - *info |= kCGImageAlphaPremultipliedFirst; - } -#else - // ...add more formats as required... -#warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \ -This will probably not work. - // Legacy behavior. Perhaps turn this into an error at some - // point. - *info = kCGBitmapByteOrder32Big; - if (bm.isOpaque()) { - *info |= kCGImageAlphaNoneSkipLast; - } else { - *info |= kCGImageAlphaPremultipliedLast; - } + *info = ComputeCGAlphaInfo_RGBA(kOpaque_SkAlphaType); #endif break; + case kRGBA_8888_SkColorType: + *bitsPerComponent = 8; + *info = ComputeCGAlphaInfo_RGBA(bm.alphaType()); + break; + case kBGRA_8888_SkColorType: + *bitsPerComponent = 8; + *info = ComputeCGAlphaInfo_BGRA(bm.alphaType()); + break; case kARGB_4444_SkColorType: *bitsPerComponent = 4; *info = kCGBitmapByteOrder16Little; @@ -231,3 +244,73 @@ bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output) { output->swap(bitmap); return true; } + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +SK_API bool SkCopyPixelsFromCGImage(const SkImageInfo& info, size_t rowBytes, void* pixels, + CGImageRef image) { + CGBitmapInfo cg_bitmap_info = 0; + size_t bitsPerComponent = 0; + switch (info.colorType()) { + case kRGBA_8888_SkColorType: + bitsPerComponent = 8; + cg_bitmap_info = ComputeCGAlphaInfo_RGBA(info.alphaType()); + break; + case kBGRA_8888_SkColorType: + bitsPerComponent = 8; + cg_bitmap_info = ComputeCGAlphaInfo_BGRA(info.alphaType()); + break; + default: + return false; // no other colortypes are supported (for now) + } + + CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); + CGContextRef cg = CGBitmapContextCreate(pixels, info.width(), info.height(), bitsPerComponent, + rowBytes, cs, cg_bitmap_info); + CFRelease(cs); + if (NULL == cg) { + return false; + } + + // use this blend mode, to avoid having to erase the pixels first, and to avoid CG performing + // any blending (which could introduce errors and be slower). + CGContextSetBlendMode(cg, kCGBlendModeCopy); + + CGContextDrawImage(cg, CGRectMake(0, 0, info.width(), info.height()), image); + CGContextRelease(cg); + return true; +} + +bool SkCreateBitmapFromCGImage(SkBitmap* dst, CGImageRef image, SkISize* scaleToFit) { + const int width = scaleToFit ? scaleToFit->width() : SkToInt(CGImageGetWidth(image)); + const int height = scaleToFit ? scaleToFit->height() : SkToInt(CGImageGetHeight(image)); + SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); + + SkBitmap tmp; + if (!tmp.allocPixels(info)) { + return false; + } + + if (!SkCopyPixelsFromCGImage(tmp.info(), tmp.rowBytes(), tmp.getPixels(), image)) { + return false; + } + + CGImageAlphaInfo cgInfo = CGImageGetAlphaInfo(image); + switch (cgInfo) { + case kCGImageAlphaNone: + case kCGImageAlphaNoneSkipLast: + case kCGImageAlphaNoneSkipFirst: + SkASSERT(SkBitmap::ComputeIsOpaque(tmp)); + tmp.setAlphaType(kOpaque_SkAlphaType); + break; + default: + // we don't know if we're opaque or not, so compute it. + if (SkBitmap::ComputeIsOpaque(tmp)) { + tmp.setAlphaType(kOpaque_SkAlphaType); + } + } + + *dst = tmp; + return true; +} + |