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 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 22 size.width, 23 size.height, 24 0, 25 is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); 26 27 if (!bitmap.allocPixels()) 28 return bitmap; 29 30 void* data = bitmap.getPixels(); 31 32 // Allocate a bitmap context with 4 components per pixel (BGRA). Apple 33 // recommends these flags for improved CG performance. 34 #define HAS_ARGB_SHIFTS(a, r, g, b) \ 35 (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \ 36 && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b)) 37 #if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) 38 base::ScopedCFTypeRef<CGColorSpaceRef> color_space( 39 CGColorSpaceCreateDeviceRGB()); 40 base::ScopedCFTypeRef<CGContextRef> context(CGBitmapContextCreate( 41 data, 42 size.width, 43 size.height, 44 8, 45 size.width * 4, 46 color_space, 47 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); 48 #else 49 #error We require that Skia's and CoreGraphics's recommended \ 50 image memory layout match. 51 #endif 52 #undef HAS_ARGB_SHIFTS 53 54 DCHECK(context); 55 if (!context) 56 return bitmap; 57 58 CGRect imageRect = CGRectMake(0.0, 0.0, size.width, size.height); 59 CGContextSetBlendMode(context, kCGBlendModeCopy); 60 CGContextDrawImage(context, imageRect, image); 61 62 return bitmap; 63 } 64 65 UIImage* SkBitmapToUIImageWithColorSpace(const SkBitmap& skia_bitmap, 66 CGFloat scale, 67 CGColorSpaceRef color_space) { 68 if (skia_bitmap.isNull()) 69 return nil; 70 71 // First convert SkBitmap to CGImageRef. 72 base::ScopedCFTypeRef<CGImageRef> cg_image( 73 SkCreateCGImageRefWithColorspace(skia_bitmap, color_space)); 74 75 // Now convert to UIImage. 76 return [UIImage imageWithCGImage:cg_image.get() 77 scale:scale 78 orientation:UIImageOrientationUp]; 79 } 80 81 std::vector<SkBitmap> ImageDataToSkBitmaps(NSData* image_data) { 82 DCHECK(image_data); 83 base::ScopedCFTypeRef<CFDictionaryRef> empty_dictionary( 84 CFDictionaryCreate(NULL, NULL, NULL, 0, NULL, NULL)); 85 std::vector<SkBitmap> frames; 86 87 base::ScopedCFTypeRef<CGImageSourceRef> source( 88 CGImageSourceCreateWithData((CFDataRef)image_data, empty_dictionary)); 89 90 size_t count = CGImageSourceGetCount(source); 91 for (size_t index = 0; index < count; ++index) { 92 base::ScopedCFTypeRef<CGImageRef> cg_image( 93 CGImageSourceCreateImageAtIndex(source, index, empty_dictionary)); 94 95 CGSize size = CGSizeMake(CGImageGetWidth(cg_image), 96 CGImageGetHeight(cg_image)); 97 const SkBitmap bitmap = CGImageToSkBitmap(cg_image, size, false); 98 if (!bitmap.empty()) 99 frames.push_back(bitmap); 100 } 101 102 DLOG_IF(WARNING, frames.size() != count) << "Only decoded " << frames.size() 103 << " frames for " << count << " expected."; 104 return frames; 105 } 106 107 } // namespace gfx 108