1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "skia/ext/skia_utils_ios.h" 6 7 #import <ImageIO/ImageIO.h> 8 #import <UIKit/UIKit.h> 9 10 #include "base/logging.h" 11 #include "base/mac/scoped_cftyperef.h" 12 #include "third_party/skia/include/utils/mac/SkCGUtils.h" 13 14 namespace gfx { 15 16 SkBitmap CGImageToSkBitmap(CGImageRef image, CGSize size, bool is_opaque) { 17 SkBitmap bitmap; 18 if (!image) 19 return bitmap; 20 21 if (!bitmap.tryAllocN32Pixels(size.width, size.height, is_opaque)) 22 return bitmap; 23 24 void* data = bitmap.getPixels(); 25 26 // Allocate a bitmap context with 4 components per pixel (BGRA). Apple 27 // recommends these flags for improved CG performance. 28 #define HAS_ARGB_SHIFTS(a, r, g, b) \ 29 (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \ 30 && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b)) 31 #if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) 32 base::ScopedCFTypeRef<CGColorSpaceRef> color_space( 33 CGColorSpaceCreateDeviceRGB()); 34 base::ScopedCFTypeRef<CGContextRef> context(CGBitmapContextCreate( 35 data, 36 size.width, 37 size.height, 38 8, 39 size.width * 4, 40 color_space, 41 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); 42 #else 43 #error We require that Skia's and CoreGraphics's recommended \ 44 image memory layout match. 45 #endif 46 #undef HAS_ARGB_SHIFTS 47 48 DCHECK(context); 49 if (!context) 50 return bitmap; 51 52 CGRect imageRect = CGRectMake(0.0, 0.0, size.width, size.height); 53 CGContextSetBlendMode(context, kCGBlendModeCopy); 54 CGContextDrawImage(context, imageRect, image); 55 56 return bitmap; 57 } 58 59 UIImage* SkBitmapToUIImageWithColorSpace(const SkBitmap& skia_bitmap, 60 CGFloat scale, 61 CGColorSpaceRef color_space) { 62 if (skia_bitmap.isNull()) 63 return nil; 64 65 // First convert SkBitmap to CGImageRef. 66 base::ScopedCFTypeRef<CGImageRef> cg_image( 67 SkCreateCGImageRefWithColorspace(skia_bitmap, color_space)); 68 69 // Now convert to UIImage. 70 return [UIImage imageWithCGImage:cg_image.get() 71 scale:scale 72 orientation:UIImageOrientationUp]; 73 } 74 75 std::vector<SkBitmap> ImageDataToSkBitmaps(NSData* image_data) { 76 DCHECK(image_data); 77 base::ScopedCFTypeRef<CFDictionaryRef> empty_dictionary( 78 CFDictionaryCreate(NULL, NULL, NULL, 0, NULL, NULL)); 79 std::vector<SkBitmap> frames; 80 81 base::ScopedCFTypeRef<CGImageSourceRef> source( 82 CGImageSourceCreateWithData((CFDataRef)image_data, empty_dictionary)); 83 84 size_t count = CGImageSourceGetCount(source); 85 for (size_t index = 0; index < count; ++index) { 86 base::ScopedCFTypeRef<CGImageRef> cg_image( 87 CGImageSourceCreateImageAtIndex(source, index, empty_dictionary)); 88 89 CGSize size = CGSizeMake(CGImageGetWidth(cg_image), 90 CGImageGetHeight(cg_image)); 91 const SkBitmap bitmap = CGImageToSkBitmap(cg_image, size, false); 92 if (!bitmap.empty()) 93 frames.push_back(bitmap); 94 } 95 96 DLOG_IF(WARNING, frames.size() != count) << "Only decoded " << frames.size() 97 << " frames for " << count << " expected."; 98 return frames; 99 } 100 101 } // namespace gfx 102