blob: a2fe6a40efd78dedc19f6df9ab3c773ce5110d17 [file] [log] [blame]
msarett18976312016-03-09 14:20:58 -08001/*
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"
msarett18976312016-03-09 14:20:58 -08009
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
20static 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
31SkImageGenerator* SkImageGeneratorCG::NewFromEncodedCG(SkData* data) {
32 CGImageSourceRef imageSrc = data_to_CGImageSrc(data);
33 if (!imageSrc) {
34 return nullptr;
35 }
halcanary9d524f22016-03-29 09:03:52 -070036
msarett18976312016-03-09 14:20:58 -080037 // 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 }
halcanary9d524f22016-03-29 09:03:52 -070045
msarett18976312016-03-09 14:20:58 -080046 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 }
halcanary9d524f22016-03-29 09:03:52 -070061
msarett18976312016-03-09 14:20:58 -080062 SkAlphaType alphaType = hasAlpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType;
Matt Sarett1e86044d2016-12-16 09:02:18 -050063 SkImageInfo info = SkImageInfo::MakeS32(width, height, alphaType);
msarett18976312016-03-09 14:20:58 -080064
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
mtklein18300a32016-03-16 13:53:35 -070069 return new SkImageGeneratorCG(info, autoImageSrc.release(), data);
msarett18976312016-03-09 14:20:58 -080070}
71
72SkImageGeneratorCG::SkImageGeneratorCG(const SkImageInfo& info, const void* imageSrc, SkData* data)
73 : INHERITED(info)
74 , fImageSrc(imageSrc)
75 , fData(SkRef(data))
76{}
77
Brian Osman2feb7962017-04-25 16:41:47 -040078SkData* SkImageGeneratorCG::onRefEncodedData() {
msarett18976312016-03-09 14:20:58 -080079 return SkRef(fData.get());
80}
81
82bool SkImageGeneratorCG::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
Matt Sarettebb1b5c2017-05-12 11:41:27 -040083 const Options&) {
msarett18976312016-03-09 14:20:58 -080084 if (kN32_SkColorType != info.colorType()) {
85 // FIXME: Support other colorTypes.
86 return false;
87 }
halcanary9d524f22016-03-29 09:03:52 -070088
msarett18976312016-03-09 14:20:58 -080089 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 }
halcanary9d524f22016-03-29 09:03:52 -0700100
msarett18976312016-03-09 14:20:58 -0800101 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}