SkCreateCGImageRef.cpp revision 0680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bf
1#include "SkCGUtils.h"
2#include "SkBitmap.h"
3
4extern CGImageRef SkCreateCGImageRef(const SkBitmap&);
5
6static const void* SkBitmap_GetBytesPointer(void* info) {
7    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
8    bitmap->lockPixels();
9    return bitmap->getPixels();
10}
11
12static void SkBitmap_ReleaseBytePointer(void* info, const void* pointer) {
13    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
14    bitmap->unlockPixels();
15}
16
17static size_t SkBitmap_GetBytesAtPosition(void* info, void* buffer,
18                                             off_t offset, size_t count) {
19    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
20    bitmap->lockPixels();
21    memcpy(buffer, (const char*)bitmap->getPixels() + offset, count);
22    bitmap->unlockPixels();
23    return count;
24}
25
26static void SkBitmap_ReleaseInfo(void* info) {
27    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
28    delete bitmap;
29}
30
31static SkBitmap* prepareForImageRef(const SkBitmap& bm,
32                                    size_t* bitsPerComponent,
33                                    CGBitmapInfo* info) {
34    switch (bm.config()) {
35        case SkBitmap::kARGB_8888_Config:
36            *bitsPerComponent = 8;
37            // try to match our argb ordering in SkColorPriv
38            *info = kCGBitmapByteOrder32Big |
39                    kCGImageAlphaPremultipliedLast;
40            break;
41        case SkBitmap::kRGB_565_Config:
42            // doesn't see quite right. Are they thinking 1555?
43            *bitsPerComponent = 5;
44            *info = kCGBitmapByteOrder16Little;
45            break;
46        case SkBitmap::kARGB_4444_Config:
47            *bitsPerComponent = 4;
48            *info = kCGBitmapByteOrder16Little | kCGImageAlphaPremultipliedLast;
49            break;
50        default:
51            return NULL;
52    }
53
54    return new SkBitmap(bm);
55}
56
57CGImageRef SkCreateCGImageRef(const SkBitmap& bm) {
58    size_t bitsPerComponent;
59    CGBitmapInfo info;
60
61    SkBitmap* bitmap = prepareForImageRef(bm, &bitsPerComponent, &info);
62    if (NULL == bitmap) {
63        return NULL;
64    }
65
66    const int w = bitmap->width();
67    const int h = bitmap->height();
68    const size_t s = bitmap->getSize();
69
70    CGDataProviderDirectCallbacks procs;
71    procs.version = 0;
72    procs.getBytePointer = SkBitmap_GetBytesPointer;
73    procs.releaseBytePointer = SkBitmap_ReleaseBytePointer;
74    procs.getBytesAtPosition = SkBitmap_GetBytesAtPosition;
75    procs.releaseInfo = SkBitmap_ReleaseInfo;
76
77    // our provider "owns" the bitmap*, and will take care of deleting it
78    CGDataProviderRef dataRef = CGDataProviderCreateDirect(bitmap, s, &procs);
79    CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
80    CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
81                                   bitmap->bytesPerPixel() * 8,
82                                   bitmap->rowBytes(), space, info, dataRef,
83                                   NULL, false, kCGRenderingIntentDefault);
84    CGColorSpaceRelease(space);
85    CGDataProviderRelease(dataRef);
86    return ref;
87}
88
89
90