blob: 2d2c3d3bd561d88f2ce901bf4d044f15f90dd359 [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"
Leon Scroggins III0cbc10f2017-10-30 09:07:53 -04009#include "SkPixmapPriv.h"
msarett18976312016-03-09 14:20:58 -080010
11#ifdef SK_BUILD_FOR_MAC
12#include <ApplicationServices/ApplicationServices.h>
13#endif
14
15#ifdef SK_BUILD_FOR_IOS
16#include <CoreGraphics/CoreGraphics.h>
17#include <ImageIO/ImageIO.h>
18#include <MobileCoreServices/MobileCoreServices.h>
19#endif
20
21static CGImageSourceRef data_to_CGImageSrc(SkData* data) {
22 CGDataProviderRef cgData = CGDataProviderCreateWithData(data, data->data(), data->size(),
23 nullptr);
24 if (!cgData) {
25 return nullptr;
26 }
27 CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(cgData, 0);
28 CGDataProviderRelease(cgData);
29 return imageSrc;
30}
31
Leon Scroggins III0cbc10f2017-10-30 09:07:53 -040032#ifdef SK_LEGACY_NEW_FROM_ENCODED_CG
msarett18976312016-03-09 14:20:58 -080033SkImageGenerator* SkImageGeneratorCG::NewFromEncodedCG(SkData* data) {
Leon Scroggins III0cbc10f2017-10-30 09:07:53 -040034 return MakeFromEncodedCG(sk_ref_sp(data)).release();
35}
36#endif
37
38std::unique_ptr<SkImageGenerator> SkImageGeneratorCG::MakeFromEncodedCG(sk_sp<SkData> data) {
39 CGImageSourceRef imageSrc = data_to_CGImageSrc(data.get());
msarett18976312016-03-09 14:20:58 -080040 if (!imageSrc) {
41 return nullptr;
42 }
halcanary9d524f22016-03-29 09:03:52 -070043
msarett18976312016-03-09 14:20:58 -080044 // Make sure we call CFRelease to free the imageSrc. Since CFRelease actually takes
45 // a const void*, we must cast the imageSrc to a const void*.
46 SkAutoTCallVProc<const void, CFRelease> autoImageSrc(imageSrc);
47
48 CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSrc, 0, nullptr);
49 if (!properties) {
50 return nullptr;
51 }
halcanary9d524f22016-03-29 09:03:52 -070052
msarett18976312016-03-09 14:20:58 -080053 CFNumberRef widthRef = (CFNumberRef) (CFDictionaryGetValue(properties,
54 kCGImagePropertyPixelWidth));
55 CFNumberRef heightRef = (CFNumberRef) (CFDictionaryGetValue(properties,
56 kCGImagePropertyPixelHeight));
57 if (nullptr == widthRef || nullptr == heightRef) {
58 return nullptr;
59 }
msarett18976312016-03-09 14:20:58 -080060
61 int width, height;
62 if (!CFNumberGetValue(widthRef, kCFNumberIntType, &width) ||
63 !CFNumberGetValue(heightRef, kCFNumberIntType, &height)) {
64 return nullptr;
65 }
halcanary9d524f22016-03-29 09:03:52 -070066
Leon Scroggins III0cbc10f2017-10-30 09:07:53 -040067 bool hasAlpha = (bool) (CFDictionaryGetValue(properties,
68 kCGImagePropertyHasAlpha));
msarett18976312016-03-09 14:20:58 -080069 SkAlphaType alphaType = hasAlpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType;
Matt Sarett1e86044d2016-12-16 09:02:18 -050070 SkImageInfo info = SkImageInfo::MakeS32(width, height, alphaType);
msarett18976312016-03-09 14:20:58 -080071
Leon Scroggins III0cbc10f2017-10-30 09:07:53 -040072 auto origin = kDefault_SkEncodedOrigin;
73 auto orientationRef = (CFNumberRef) (CFDictionaryGetValue(properties,
74 kCGImagePropertyOrientation));
75 int originInt;
76 if (orientationRef && CFNumberGetValue(orientationRef, kCFNumberIntType, &originInt)) {
77 origin = (SkEncodedOrigin) originInt;
78 }
79
80 if (SkPixmapPriv::ShouldSwapWidthHeight(origin)) {
81 info = SkPixmapPriv::SwapWidthHeight(info);
82 }
83
msarett18976312016-03-09 14:20:58 -080084 // FIXME: We have the opportunity to extract color space information here,
85 // though I think it makes sense to wait until we understand how
86 // we want to communicate it to the generator.
87
Leon Scroggins III0cbc10f2017-10-30 09:07:53 -040088 return std::unique_ptr<SkImageGenerator>(new SkImageGeneratorCG(info, autoImageSrc.release(),
89 std::move(data), origin));
msarett18976312016-03-09 14:20:58 -080090}
91
Leon Scroggins III0cbc10f2017-10-30 09:07:53 -040092SkImageGeneratorCG::SkImageGeneratorCG(const SkImageInfo& info, const void* imageSrc,
93 sk_sp<SkData> data, SkEncodedOrigin origin)
msarett18976312016-03-09 14:20:58 -080094 : INHERITED(info)
95 , fImageSrc(imageSrc)
Leon Scroggins III0cbc10f2017-10-30 09:07:53 -040096 , fData(std::move(data))
97 , fOrigin(origin)
msarett18976312016-03-09 14:20:58 -080098{}
99
Brian Osman2feb7962017-04-25 16:41:47 -0400100SkData* SkImageGeneratorCG::onRefEncodedData() {
msarett18976312016-03-09 14:20:58 -0800101 return SkRef(fData.get());
102}
103
104bool SkImageGeneratorCG::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
Matt Sarettebb1b5c2017-05-12 11:41:27 -0400105 const Options&) {
msarett18976312016-03-09 14:20:58 -0800106 if (kN32_SkColorType != info.colorType()) {
107 // FIXME: Support other colorTypes.
108 return false;
109 }
halcanary9d524f22016-03-29 09:03:52 -0700110
msarett18976312016-03-09 14:20:58 -0800111 switch (info.alphaType()) {
112 case kOpaque_SkAlphaType:
113 if (kOpaque_SkAlphaType != this->getInfo().alphaType()) {
114 return false;
115 }
116 break;
117 case kPremul_SkAlphaType:
118 break;
119 default:
120 return false;
121 }
halcanary9d524f22016-03-29 09:03:52 -0700122
msarett18976312016-03-09 14:20:58 -0800123 CGImageRef image = CGImageSourceCreateImageAtIndex((CGImageSourceRef) fImageSrc.get(), 0,
124 nullptr);
125 if (!image) {
126 return false;
127 }
128 SkAutoTCallVProc<CGImage, CGImageRelease> autoImage(image);
129
Leon Scroggins III0cbc10f2017-10-30 09:07:53 -0400130 SkPixmap dst(info, pixels, rowBytes);
131 auto decode = [&image](const SkPixmap& pm) {
132 // FIXME: Using SkCopyPixelsFromCGImage (as opposed to swizzling
133 // ourselves) greatly restricts the color and alpha types that we
134 // support. If we swizzle ourselves, we can add support for:
135 // kUnpremul_SkAlphaType
136 // 16-bit per component RGBA
137 // kGray_8_SkColorType
138 // Additionally, it would be interesting to compare the performance
139 // of SkSwizzler with CG's built in swizzler.
140 return SkCopyPixelsFromCGImage(pm, image);
141 };
142 return SkPixmapPriv::Orient(dst, fOrigin, decode);
msarett18976312016-03-09 14:20:58 -0800143}