SkCreateCGImageRef.cpp revision 40443b2371ecc61e04ad496f69919dc1e30036f5
1#include "SkCGUtils.h" 2#include "SkBitmap.h" 3#include "SkColorPriv.h" 4 5extern CGImageRef SkCreateCGImageRef(const SkBitmap&); 6 7static void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) { 8 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info); 9 delete bitmap; 10} 11 12#define HAS_ARGB_SHIFTS(a, r, g, b) \ 13 (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \ 14 && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b)) 15 16static SkBitmap* prepareForImageRef(const SkBitmap& bm, 17 size_t* bitsPerComponent, 18 CGBitmapInfo* info) { 19#if 0 20 SkDebugf("---- %d %d %d %d\n", SK_A32_SHIFT, SK_R32_SHIFT, 21 SK_G32_SHIFT, SK_B32_SHIFT); 22#endif 23 24 switch (bm.config()) { 25 case SkBitmap::kARGB_8888_Config: 26 *bitsPerComponent = 8; 27#if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 0, 8, 16) \ 28 || defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(0, 24, 16, 8) 29 *info = kCGBitmapByteOrder32Big | 30 kCGImageAlphaPremultipliedLast; 31#elif defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) \ 32 || defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) 33 // Matches the CGBitmapInfo that Apple recommends for best 34 // performance, used by google chrome. 35 *info = kCGBitmapByteOrder32Host | 36 kCGImageAlphaPremultipliedFirst; 37#else 38// ...add more formats as required... 39#warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \ 40 This will probably not work. 41 // Legacy behavior. Perhaps turn this into an error at some 42 // point. 43 *info = kCGBitmapByteOrder32Big | 44 kCGImageAlphaPremultipliedLast; 45#endif 46 break; 47 case SkBitmap::kRGB_565_Config: 48 // doesn't see quite right. Are they thinking 1555? 49 *bitsPerComponent = 5; 50 *info = kCGBitmapByteOrder16Little; 51 break; 52 case SkBitmap::kARGB_4444_Config: 53 *bitsPerComponent = 4; 54 *info = kCGBitmapByteOrder16Little | kCGImageAlphaPremultipliedLast; 55 break; 56 default: 57 return NULL; 58 } 59 60 return new SkBitmap(bm); 61} 62 63#undef HAS_ARGB_SHIFTS 64 65CGImageRef SkCreateCGImageRef(const SkBitmap& bm) { 66 size_t bitsPerComponent; 67 CGBitmapInfo info; 68 69 SkBitmap* bitmap = prepareForImageRef(bm, &bitsPerComponent, &info); 70 if (NULL == bitmap) { 71 return NULL; 72 } 73 74 const int w = bitmap->width(); 75 const int h = bitmap->height(); 76 const size_t s = bitmap->getSize(); 77 78 // our provider "owns" the bitmap*, and will take care of deleting it 79 // we initially lock it, so we can access the pixels. The bitmap will be deleted in the release 80 // proc, which will in turn unlock the pixels 81 bitmap->lockPixels(); 82 CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s, 83 SkBitmap_ReleaseInfo); 84 85 CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 86 CGImageRef ref = CGImageCreate(w, h, bitsPerComponent, 87 bitmap->bytesPerPixel() * 8, 88 bitmap->rowBytes(), space, info, dataRef, 89 NULL, false, kCGRenderingIntentDefault); 90 CGColorSpaceRelease(space); 91 CGDataProviderRelease(dataRef); 92 return ref; 93} 94 95 96