Chromium Code Reviews| Index: src/utils/mac/SkCreateCGImageRef.cpp |
| diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp |
| index 00166e9ed7488b4976d8c426a90061a7d3b40fd3..89cae2beefda37155673a0ffeeb8cca73d898ad9 100644 |
| --- a/src/utils/mac/SkCreateCGImageRef.cpp |
| +++ b/src/utils/mac/SkCreateCGImageRef.cpp |
| @@ -9,6 +9,40 @@ |
| #include "SkBitmap.h" |
| #include "SkColorPriv.h" |
| +static uint32_t ComputeCGAlphaInfo_RGBA(SkAlphaType at) { |
|
scroggo
2014/04/22 14:58:17
Should these return CGBitmapInfo for documentation
reed1
2014/04/22 17:51:39
Done.
|
| + uint32_t 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 uint32_t ComputeCGAlphaInfo_BGRA(SkAlphaType at) { |
| + uint32_t 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; |
| @@ -22,54 +56,35 @@ static bool getBitmapInfo(const SkBitmap& bm, |
| *upscaleTo32 = false; |
| } |
| + const bool opaque = kOpaque_SkAlphaType == bm.alphaType(); |
|
scroggo
2014/04/22 14:58:17
It seems like this could go in the 4444 case (the
reed1
2014/04/22 17:51:39
Done.
|
| + const bool premul = kUnpremul_SkAlphaType != bm.alphaType(); |
|
scroggo
2014/04/22 14:58:17
This variable is unused.
reed1
2014/04/22 17:51:39
Done.
|
| + |
| switch (bm.colorType()) { |
| case kRGB_565_SkColorType: |
| #if 0 |
| // 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: |
| - *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; |
| - } |
| + // now treat like RGBA |
| + *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; |
| - if (bm.isOpaque()) { |
| + if (opaque) { |
| *info |= kCGImageAlphaNoneSkipLast; |
| } else { |
| *info |= kCGImageAlphaPremultipliedLast; |
| @@ -231,3 +246,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; |
| +} |
| + |