SkCreateCGImageRef.cpp revision a9caa4f932a7646571a52937b03c244f5bca9bdf
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 bool upscaleTo32 = false; 20 21 switch (bm.config()) { 22 case SkBitmap::kRGB_565_Config: 23 upscaleTo32 = true; 24 // fall through 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#if 0 48 case SkBitmap::kRGB_565_Config: 49 // doesn't see quite right. Are they thinking 1555? 50 *bitsPerComponent = 5; 51 *info = kCGBitmapByteOrder16Little; 52 break; 53#endif 54 case SkBitmap::kARGB_4444_Config: 55 *bitsPerComponent = 4; 56 *info = kCGBitmapByteOrder16Little | kCGImageAlphaPremultipliedLast; 57 break; 58 default: 59 return NULL; 60 } 61 62 SkBitmap* copy; 63 if (upscaleTo32) { 64 copy = new SkBitmap; 65 // here we make a ceep copy of the pixels, since CG won't take our 66 // 565 directly 67 bm.copyTo(copy, SkBitmap::kARGB_8888_Config); 68 } else { 69 copy = new SkBitmap(bm); 70 } 71 return copy; 72} 73 74#undef HAS_ARGB_SHIFTS 75 76CGImageRef SkCreateCGImageRef(const SkBitmap& bm) { 77 size_t bitsPerComponent; 78 CGBitmapInfo info; 79 80 SkBitmap* bitmap = prepareForImageRef(bm, &bitsPerComponent, &info); 81 if (NULL == bitmap) { 82 return NULL; 83 } 84 85 const int w = bitmap->width(); 86 const int h = bitmap->height(); 87 const size_t s = bitmap->getSize(); 88 89 // our provider "owns" the bitmap*, and will take care of deleting it 90 // we initially lock it, so we can access the pixels. The bitmap will be deleted in the release 91 // proc, which will in turn unlock the pixels 92 bitmap->lockPixels(); 93 CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s, 94 SkBitmap_ReleaseInfo); 95 96 CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 97 CGImageRef ref = CGImageCreate(w, h, bitsPerComponent, 98 bitmap->bytesPerPixel() * 8, 99 bitmap->rowBytes(), space, info, dataRef, 100 NULL, false, kCGRenderingIntentDefault); 101 CGColorSpaceRelease(space); 102 CGDataProviderRelease(dataRef); 103 return ref; 104} 105 106 107