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 uint32_t ComputeCGAlphaInfo_RGBA(SkAlphaType at) { | |
scroggo
2014/04/22 14:58:17
Should these return CGBitmapInfo for documentation
reed1
2014/04/22 17:51:39
Done.
| |
13 uint32_t 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 uint32_t ComputeCGAlphaInfo_BGRA(SkAlphaType at) { | |
30 uint32_t 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 |
59 const bool opaque = kOpaque_SkAlphaType == bm.alphaType(); | |
scroggo
2014/04/22 14:58:17
It seems like this could go in the 4444 case (the
reed1
2014/04/22 17:51:39
Done.
| |
60 const bool premul = kUnpremul_SkAlphaType != bm.alphaType(); | |
scroggo
2014/04/22 14:58:17
This variable is unused.
reed1
2014/04/22 17:51:39
Done.
| |
61 | |
25 switch (bm.colorType()) { | 62 switch (bm.colorType()) { |
26 case kRGB_565_SkColorType: | 63 case kRGB_565_SkColorType: |
27 #if 0 | 64 #if 0 |
28 // doesn't see quite right. Are they thinking 1555? | 65 // doesn't see quite right. Are they thinking 1555? |
29 *bitsPerComponent = 5; | 66 *bitsPerComponent = 5; |
30 *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone; | 67 *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone; |
31 break; | 68 #else |
32 #endif | |
33 if (upscaleTo32) { | 69 if (upscaleTo32) { |
34 *upscaleTo32 = true; | 70 *upscaleTo32 = true; |
35 } | 71 } |
36 // fall through | 72 // now treat like RGBA |
37 case kN32_SkColorType: | 73 *info = ComputeCGAlphaInfo_RGBA(kOpaque_SkAlphaType); |
74 #endif | |
75 break; | |
76 case kRGBA_8888_SkColorType: | |
38 *bitsPerComponent = 8; | 77 *bitsPerComponent = 8; |
39 #if SK_PMCOLOR_BYTE_ORDER(R,G,B,A) | 78 *info = ComputeCGAlphaInfo_RGBA(bm.alphaType()); |
40 *info = kCGBitmapByteOrder32Big; | 79 break; |
41 if (bm.isOpaque()) { | 80 case kBGRA_8888_SkColorType: |
42 *info |= kCGImageAlphaNoneSkipLast; | 81 *bitsPerComponent = 8; |
43 } else { | 82 *info = ComputeCGAlphaInfo_BGRA(bm.alphaType()); |
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 | |
68 break; | 83 break; |
69 case kARGB_4444_SkColorType: | 84 case kARGB_4444_SkColorType: |
70 *bitsPerComponent = 4; | 85 *bitsPerComponent = 4; |
71 *info = kCGBitmapByteOrder16Little; | 86 *info = kCGBitmapByteOrder16Little; |
72 if (bm.isOpaque()) { | 87 if (opaque) { |
73 *info |= kCGImageAlphaNoneSkipLast; | 88 *info |= kCGImageAlphaNoneSkipLast; |
74 } else { | 89 } else { |
75 *info |= kCGImageAlphaPremultipliedLast; | 90 *info |= kCGImageAlphaPremultipliedLast; |
76 } | 91 } |
77 break; | 92 break; |
78 default: | 93 default: |
79 return false; | 94 return false; |
80 } | 95 } |
81 return true; | 96 return true; |
82 } | 97 } |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
224 CGColorSpaceRelease(cs); | 239 CGColorSpaceRelease(cs); |
225 | 240 |
226 if (ctx) { | 241 if (ctx) { |
227 CGContextDrawPDFPage(ctx, page); | 242 CGContextDrawPDFPage(ctx, page); |
228 CGContextRelease(ctx); | 243 CGContextRelease(ctx); |
229 } | 244 } |
230 | 245 |
231 output->swap(bitmap); | 246 output->swap(bitmap); |
232 return true; | 247 return true; |
233 } | 248 } |
249 | |
250 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
251 | |
252 SK_API bool SkCopyPixelsFromCGImage(const SkImageInfo& info, size_t rowBytes, vo id* pixels, | |
253 CGImageRef image) { | |
254 CGBitmapInfo cg_bitmap_info = 0; | |
255 size_t bitsPerComponent = 0; | |
256 switch (info.colorType()) { | |
257 case kRGBA_8888_SkColorType: | |
258 bitsPerComponent = 8; | |
259 cg_bitmap_info = ComputeCGAlphaInfo_RGBA(info.alphaType()); | |
260 break; | |
261 case kBGRA_8888_SkColorType: | |
262 bitsPerComponent = 8; | |
263 cg_bitmap_info = ComputeCGAlphaInfo_BGRA(info.alphaType()); | |
264 break; | |
265 default: | |
266 return false; // no other colortypes are supported (for now) | |
267 } | |
268 | |
269 CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); | |
270 CGContextRef cg = CGBitmapContextCreate(pixels, info.width(), info.height(), bitsPerComponent, | |
271 rowBytes, cs, cg_bitmap_info); | |
272 CFRelease(cs); | |
273 if (NULL == cg) { | |
274 return false; | |
275 } | |
276 | |
277 // use this blend mode, to avoid having to erase the pixels first, and to av oid CG performing | |
278 // any blending (which could introduce errors and be slower). | |
279 CGContextSetBlendMode(cg, kCGBlendModeCopy); | |
280 | |
281 CGContextDrawImage(cg, CGRectMake(0, 0, info.width(), info.height()), image) ; | |
282 CGContextRelease(cg); | |
283 return true; | |
284 } | |
285 | |
286 bool SkCreateBitmapFromCGImage(SkBitmap* dst, CGImageRef image, SkISize* scaleTo Fit) { | |
287 const int width = scaleToFit ? scaleToFit->width() : SkToInt(CGImageGetWidth (image)); | |
288 const int height = scaleToFit ? scaleToFit->height() : SkToInt(CGImageGetHei ght(image)); | |
289 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); | |
290 | |
291 SkBitmap tmp; | |
292 if (!tmp.allocPixels(info)) { | |
293 return false; | |
294 } | |
295 | |
296 if (!SkCopyPixelsFromCGImage(tmp.info(), tmp.rowBytes(), tmp.getPixels(), im age)) { | |
297 return false; | |
298 } | |
299 | |
300 CGImageAlphaInfo cgInfo = CGImageGetAlphaInfo(image); | |
301 switch (cgInfo) { | |
302 case kCGImageAlphaNone: | |
303 case kCGImageAlphaNoneSkipLast: | |
304 case kCGImageAlphaNoneSkipFirst: | |
305 SkASSERT(SkBitmap::ComputeIsOpaque(tmp)); | |
306 tmp.setAlphaType(kOpaque_SkAlphaType); | |
307 break; | |
308 default: | |
309 // we don't know if we're opaque or not, so compute it. | |
310 if (SkBitmap::ComputeIsOpaque(tmp)) { | |
311 tmp.setAlphaType(kOpaque_SkAlphaType); | |
312 } | |
313 } | |
314 | |
315 *dst = tmp; | |
316 return true; | |
317 } | |
318 | |
OLD | NEW |