aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-04-22 20:24:33 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-04-22 20:24:33 +0000
commit60b5dce19984a5165f6b2f1d6d477f5e8a940761 (patch)
treeb54e4d9df7b9b1e03307be9f5043b0be92df6a2f /src
parent945ec3a2bec668ca845071a65df8ec55e8f43819 (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.cpp3
-rw-r--r--src/ports/SkImageDecoder_CG.cpp19
-rw-r--r--src/utils/mac/SkCreateCGImageRef.cpp147
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;
+}
+