• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkImageGeneratorCG.h"
9 
10 #ifdef SK_BUILD_FOR_MAC
11 #include <ApplicationServices/ApplicationServices.h>
12 #endif
13 
14 #ifdef SK_BUILD_FOR_IOS
15 #include <CoreGraphics/CoreGraphics.h>
16 #include <ImageIO/ImageIO.h>
17 #include <MobileCoreServices/MobileCoreServices.h>
18 #endif
19 
data_to_CGImageSrc(SkData * data)20 static CGImageSourceRef data_to_CGImageSrc(SkData* data) {
21     CGDataProviderRef cgData = CGDataProviderCreateWithData(data, data->data(), data->size(),
22             nullptr);
23     if (!cgData) {
24         return nullptr;
25     }
26     CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(cgData, 0);
27     CGDataProviderRelease(cgData);
28     return imageSrc;
29 }
30 
NewFromEncodedCG(SkData * data)31 SkImageGenerator* SkImageGeneratorCG::NewFromEncodedCG(SkData* data) {
32     CGImageSourceRef imageSrc = data_to_CGImageSrc(data);
33     if (!imageSrc) {
34         return nullptr;
35     }
36 
37     // Make sure we call CFRelease to free the imageSrc.  Since CFRelease actually takes
38     // a const void*, we must cast the imageSrc to a const void*.
39     SkAutoTCallVProc<const void, CFRelease> autoImageSrc(imageSrc);
40 
41     CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSrc, 0, nullptr);
42     if (!properties) {
43         return nullptr;
44     }
45 
46     CFNumberRef widthRef = (CFNumberRef) (CFDictionaryGetValue(properties,
47             kCGImagePropertyPixelWidth));
48     CFNumberRef heightRef = (CFNumberRef) (CFDictionaryGetValue(properties,
49             kCGImagePropertyPixelHeight));
50     if (nullptr == widthRef || nullptr == heightRef) {
51         return nullptr;
52     }
53     bool hasAlpha = (bool) (CFDictionaryGetValue(properties,
54             kCGImagePropertyHasAlpha));
55 
56     int width, height;
57     if (!CFNumberGetValue(widthRef, kCFNumberIntType, &width) ||
58             !CFNumberGetValue(heightRef, kCFNumberIntType, &height)) {
59         return nullptr;
60     }
61 
62     SkAlphaType alphaType = hasAlpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType;
63     SkImageInfo info = SkImageInfo::MakeS32(width, height, alphaType);
64 
65     // FIXME: We have the opportunity to extract color space information here,
66     //        though I think it makes sense to wait until we understand how
67     //        we want to communicate it to the generator.
68 
69     return new SkImageGeneratorCG(info, autoImageSrc.release(), data);
70 }
71 
SkImageGeneratorCG(const SkImageInfo & info,const void * imageSrc,SkData * data)72 SkImageGeneratorCG::SkImageGeneratorCG(const SkImageInfo& info, const void* imageSrc, SkData* data)
73     : INHERITED(info)
74     , fImageSrc(imageSrc)
75     , fData(SkRef(data))
76 {}
77 
onRefEncodedData()78 SkData* SkImageGeneratorCG::onRefEncodedData() {
79     return SkRef(fData.get());
80 }
81 
onGetPixels(const SkImageInfo & info,void * pixels,size_t rowBytes,const Options &)82 bool SkImageGeneratorCG::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
83         const Options&) {
84     if (kN32_SkColorType != info.colorType()) {
85         // FIXME: Support other colorTypes.
86         return false;
87     }
88 
89     switch (info.alphaType()) {
90         case kOpaque_SkAlphaType:
91             if (kOpaque_SkAlphaType != this->getInfo().alphaType()) {
92                 return false;
93             }
94             break;
95         case kPremul_SkAlphaType:
96             break;
97         default:
98             return false;
99     }
100 
101     CGImageRef image = CGImageSourceCreateImageAtIndex((CGImageSourceRef) fImageSrc.get(), 0,
102             nullptr);
103     if (!image) {
104         return false;
105     }
106     SkAutoTCallVProc<CGImage, CGImageRelease> autoImage(image);
107 
108     // FIXME: Using this function (as opposed to swizzling ourselves) greatly
109     //        restricts the color and alpha types that we support.  If we
110     //        swizzle ourselves, we can add support for:
111     //            kUnpremul_SkAlphaType
112     //            16-bit per component RGBA
113     //            kGray_8_SkColorType
114     //            kIndex_8_SkColorType
115     //        Additionally, it would be interesting to compare the performance
116     //        of SkSwizzler with CG's built in swizzler.
117     if (!SkCopyPixelsFromCGImage(info, rowBytes, pixels, image)) {
118         return false;
119     }
120 
121     return true;
122 }
123