OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "SkCGUtils.h" | 8 #include "SkCGUtils.h" |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
11 | 11 |
| 12 static CGBitmapInfo ComputeCGAlphaInfo_RGBA(SkAlphaType at) { |
| 13 CGBitmapInfo info = kCGBitmapByteOrder32Big; |
| 14 switch (at) { |
| 15 case kOpaque_SkAlphaType: |
| 16 case kIgnore_SkAlphaType: |
| 17 info |= kCGImageAlphaNoneSkipLast; |
| 18 break; |
| 19 case kPremul_SkAlphaType: |
| 20 info |= kCGImageAlphaPremultipliedLast; |
| 21 break; |
| 22 case kUnpremul_SkAlphaType: |
| 23 info |= kCGImageAlphaLast; |
| 24 break; |
| 25 } |
| 26 return info; |
| 27 } |
| 28 |
| 29 static CGBitmapInfo ComputeCGAlphaInfo_BGRA(SkAlphaType at) { |
| 30 CGBitmapInfo info = kCGBitmapByteOrder32Little; |
| 31 switch (at) { |
| 32 case kOpaque_SkAlphaType: |
| 33 case kIgnore_SkAlphaType: |
| 34 info |= kCGImageAlphaNoneSkipFirst; |
| 35 break; |
| 36 case kPremul_SkAlphaType: |
| 37 info |= kCGImageAlphaPremultipliedFirst; |
| 38 break; |
| 39 case kUnpremul_SkAlphaType: |
| 40 info |= kCGImageAlphaFirst; |
| 41 break; |
| 42 } |
| 43 return info; |
| 44 } |
| 45 |
12 static void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size)
{ | 46 static void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size)
{ |
13 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info); | 47 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info); |
14 delete bitmap; | 48 delete bitmap; |
15 } | 49 } |
16 | 50 |
17 static bool getBitmapInfo(const SkBitmap& bm, | 51 static bool getBitmapInfo(const SkBitmap& bm, |
18 size_t* bitsPerComponent, | 52 size_t* bitsPerComponent, |
19 CGBitmapInfo* info, | 53 CGBitmapInfo* info, |
20 bool* upscaleTo32) { | 54 bool* upscaleTo32) { |
21 if (upscaleTo32) { | 55 if (upscaleTo32) { |
22 *upscaleTo32 = false; | 56 *upscaleTo32 = false; |
23 } | 57 } |
24 | 58 |
25 switch (bm.colorType()) { | 59 switch (bm.colorType()) { |
26 case kRGB_565_SkColorType: | 60 case kRGB_565_SkColorType: |
27 #if 0 | 61 #if 0 |
28 // doesn't see quite right. Are they thinking 1555? | 62 // doesn't see quite right. Are they thinking 1555? |
29 *bitsPerComponent = 5; | 63 *bitsPerComponent = 5; |
30 *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone; | 64 *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone; |
31 break; | 65 #else |
32 #endif | |
33 if (upscaleTo32) { | 66 if (upscaleTo32) { |
34 *upscaleTo32 = true; | 67 *upscaleTo32 = true; |
35 } | 68 } |
36 // fall through | 69 // now treat like RGBA |
37 case kN32_SkColorType: | |
38 *bitsPerComponent = 8; | 70 *bitsPerComponent = 8; |
39 #if SK_PMCOLOR_BYTE_ORDER(R,G,B,A) | 71 *info = ComputeCGAlphaInfo_RGBA(kOpaque_SkAlphaType); |
40 *info = kCGBitmapByteOrder32Big; | |
41 if (bm.isOpaque()) { | |
42 *info |= kCGImageAlphaNoneSkipLast; | |
43 } else { | |
44 *info |= kCGImageAlphaPremultipliedLast; | |
45 } | |
46 #elif SK_PMCOLOR_BYTE_ORDER(B,G,R,A) | |
47 // Matches the CGBitmapInfo that Apple recommends for best | |
48 // performance, used by google chrome. | |
49 *info = kCGBitmapByteOrder32Little; | |
50 if (bm.isOpaque()) { | |
51 *info |= kCGImageAlphaNoneSkipFirst; | |
52 } else { | |
53 *info |= kCGImageAlphaPremultipliedFirst; | |
54 } | |
55 #else | |
56 // ...add more formats as required... | |
57 #warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \ | |
58 This will probably not work. | |
59 // Legacy behavior. Perhaps turn this into an error at some | |
60 // point. | |
61 *info = kCGBitmapByteOrder32Big; | |
62 if (bm.isOpaque()) { | |
63 *info |= kCGImageAlphaNoneSkipLast; | |
64 } else { | |
65 *info |= kCGImageAlphaPremultipliedLast; | |
66 } | |
67 #endif | 72 #endif |
68 break; | 73 break; |
| 74 case kRGBA_8888_SkColorType: |
| 75 *bitsPerComponent = 8; |
| 76 *info = ComputeCGAlphaInfo_RGBA(bm.alphaType()); |
| 77 break; |
| 78 case kBGRA_8888_SkColorType: |
| 79 *bitsPerComponent = 8; |
| 80 *info = ComputeCGAlphaInfo_BGRA(bm.alphaType()); |
| 81 break; |
69 case kARGB_4444_SkColorType: | 82 case kARGB_4444_SkColorType: |
70 *bitsPerComponent = 4; | 83 *bitsPerComponent = 4; |
71 *info = kCGBitmapByteOrder16Little; | 84 *info = kCGBitmapByteOrder16Little; |
72 if (bm.isOpaque()) { | 85 if (bm.isOpaque()) { |
73 *info |= kCGImageAlphaNoneSkipLast; | 86 *info |= kCGImageAlphaNoneSkipLast; |
74 } else { | 87 } else { |
75 *info |= kCGImageAlphaPremultipliedLast; | 88 *info |= kCGImageAlphaPremultipliedLast; |
76 } | 89 } |
77 break; | 90 break; |
78 default: | 91 default: |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 CGColorSpaceRelease(cs); | 237 CGColorSpaceRelease(cs); |
225 | 238 |
226 if (ctx) { | 239 if (ctx) { |
227 CGContextDrawPDFPage(ctx, page); | 240 CGContextDrawPDFPage(ctx, page); |
228 CGContextRelease(ctx); | 241 CGContextRelease(ctx); |
229 } | 242 } |
230 | 243 |
231 output->swap(bitmap); | 244 output->swap(bitmap); |
232 return true; | 245 return true; |
233 } | 246 } |
| 247 |
| 248 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 249 |
| 250 SK_API bool SkCopyPixelsFromCGImage(const SkImageInfo& info, size_t rowBytes, vo
id* pixels, |
| 251 CGImageRef image) { |
| 252 CGBitmapInfo cg_bitmap_info = 0; |
| 253 size_t bitsPerComponent = 0; |
| 254 switch (info.colorType()) { |
| 255 case kRGBA_8888_SkColorType: |
| 256 bitsPerComponent = 8; |
| 257 cg_bitmap_info = ComputeCGAlphaInfo_RGBA(info.alphaType()); |
| 258 break; |
| 259 case kBGRA_8888_SkColorType: |
| 260 bitsPerComponent = 8; |
| 261 cg_bitmap_info = ComputeCGAlphaInfo_BGRA(info.alphaType()); |
| 262 break; |
| 263 default: |
| 264 return false; // no other colortypes are supported (for now) |
| 265 } |
| 266 |
| 267 CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); |
| 268 CGContextRef cg = CGBitmapContextCreate(pixels, info.width(), info.height(),
bitsPerComponent, |
| 269 rowBytes, cs, cg_bitmap_info); |
| 270 CFRelease(cs); |
| 271 if (NULL == cg) { |
| 272 return false; |
| 273 } |
| 274 |
| 275 // use this blend mode, to avoid having to erase the pixels first, and to av
oid CG performing |
| 276 // any blending (which could introduce errors and be slower). |
| 277 CGContextSetBlendMode(cg, kCGBlendModeCopy); |
| 278 |
| 279 CGContextDrawImage(cg, CGRectMake(0, 0, info.width(), info.height()), image)
; |
| 280 CGContextRelease(cg); |
| 281 return true; |
| 282 } |
| 283 |
| 284 bool SkCreateBitmapFromCGImage(SkBitmap* dst, CGImageRef image, SkISize* scaleTo
Fit) { |
| 285 const int width = scaleToFit ? scaleToFit->width() : SkToInt(CGImageGetWidth
(image)); |
| 286 const int height = scaleToFit ? scaleToFit->height() : SkToInt(CGImageGetHei
ght(image)); |
| 287 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); |
| 288 |
| 289 SkBitmap tmp; |
| 290 if (!tmp.allocPixels(info)) { |
| 291 return false; |
| 292 } |
| 293 |
| 294 if (!SkCopyPixelsFromCGImage(tmp.info(), tmp.rowBytes(), tmp.getPixels(), im
age)) { |
| 295 return false; |
| 296 } |
| 297 |
| 298 CGImageAlphaInfo cgInfo = CGImageGetAlphaInfo(image); |
| 299 switch (cgInfo) { |
| 300 case kCGImageAlphaNone: |
| 301 case kCGImageAlphaNoneSkipLast: |
| 302 case kCGImageAlphaNoneSkipFirst: |
| 303 SkASSERT(SkBitmap::ComputeIsOpaque(tmp)); |
| 304 tmp.setAlphaType(kOpaque_SkAlphaType); |
| 305 break; |
| 306 default: |
| 307 // we don't know if we're opaque or not, so compute it. |
| 308 if (SkBitmap::ComputeIsOpaque(tmp)) { |
| 309 tmp.setAlphaType(kOpaque_SkAlphaType); |
| 310 } |
| 311 } |
| 312 |
| 313 *dst = tmp; |
| 314 return true; |
| 315 } |
| 316 |
OLD | NEW |