Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: src/ports/SkImageDecoder_CG.cpp

Issue 1828433004: Revert of Delete SkImageDecoder (Closed) Base URL: https://skia.googlesource.com/skia.git@fix-animator
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/images/bmpdecoderhelper.cpp ('k') | src/ports/SkImageDecoder_WIC.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2008 The Android Open Source Project 2 * Copyright 2008 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkTypes.h" 8 #include "SkTypes.h"
9 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) 9 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
10 10
11 #include "SkCGUtils.h" 11 #include "SkCGUtils.h"
12 #include "SkColorPriv.h" 12 #include "SkColorPriv.h"
13 #include "SkData.h" 13 #include "SkData.h"
14 #include "SkImageDecoder.h"
14 #include "SkImageEncoder.h" 15 #include "SkImageEncoder.h"
15 #include "SkMovie.h" 16 #include "SkMovie.h"
16 #include "SkStream.h" 17 #include "SkStream.h"
17 #include "SkStreamPriv.h" 18 #include "SkStreamPriv.h"
18 #include "SkTemplates.h" 19 #include "SkTemplates.h"
19 #include "SkUnPreMultiply.h" 20 #include "SkUnPreMultiply.h"
20 21
21 #ifdef SK_BUILD_FOR_MAC 22 #ifdef SK_BUILD_FOR_MAC
22 #include <ApplicationServices/ApplicationServices.h> 23 #include <ApplicationServices/ApplicationServices.h>
23 #endif 24 #endif
24 25
25 #ifdef SK_BUILD_FOR_IOS 26 #ifdef SK_BUILD_FOR_IOS
26 #include <CoreGraphics/CoreGraphics.h> 27 #include <CoreGraphics/CoreGraphics.h>
27 #include <ImageIO/ImageIO.h> 28 #include <ImageIO/ImageIO.h>
28 #include <MobileCoreServices/MobileCoreServices.h> 29 #include <MobileCoreServices/MobileCoreServices.h>
29 #endif 30 #endif
30 31
32 static void data_unref_proc(void* skdata, const void*, size_t) {
33 SkASSERT(skdata);
34 static_cast<SkData*>(skdata)->unref();
35 }
36
37 static CGDataProviderRef SkStreamToDataProvider(SkStream* stream) {
38 // TODO: use callbacks, so we don't have to load all the data into RAM
39 SkData* skdata = SkCopyStreamToData(stream).release();
40 if (!skdata) {
41 return nullptr;
42 }
43
44 return CGDataProviderCreateWithData(skdata, skdata->data(), skdata->size(), data_unref_proc);
45 }
46
47 static CGImageSourceRef SkStreamToCGImageSource(SkStream* stream) {
48 CGDataProviderRef data = SkStreamToDataProvider(stream);
49 if (!data) {
50 return nullptr;
51 }
52 CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(data, 0);
53 CGDataProviderRelease(data);
54 return imageSrc;
55 }
56
57 class SkImageDecoder_CG : public SkImageDecoder {
58 protected:
59 virtual Result onDecode(SkStream* stream, SkBitmap* bm, Mode);
60 };
61
62 static void argb_4444_force_opaque(void* row, int count) {
63 uint16_t* row16 = (uint16_t*)row;
64 for (int i = 0; i < count; ++i) {
65 row16[i] |= 0xF000;
66 }
67 }
68
69 static void argb_8888_force_opaque(void* row, int count) {
70 // can use RGBA or BGRA, they have the same shift for alpha
71 const uint32_t alphaMask = 0xFF << SK_RGBA_A32_SHIFT;
72 uint32_t* row32 = (uint32_t*)row;
73 for (int i = 0; i < count; ++i) {
74 row32[i] |= alphaMask;
75 }
76 }
77
78 static void alpha_8_force_opaque(void* row, int count) {
79 memset(row, 0xFF, count);
80 }
81
82 static void force_opaque(SkBitmap* bm) {
83 SkAutoLockPixels alp(*bm);
84 if (!bm->getPixels()) {
85 return;
86 }
87
88 void (*proc)(void*, int);
89 switch (bm->colorType()) {
90 case kARGB_4444_SkColorType:
91 proc = argb_4444_force_opaque;
92 break;
93 case kRGBA_8888_SkColorType:
94 case kBGRA_8888_SkColorType:
95 proc = argb_8888_force_opaque;
96 break;
97 case kAlpha_8_SkColorType:
98 proc = alpha_8_force_opaque;
99 break;
100 default:
101 return;
102 }
103
104 char* row = (char*)bm->getPixels();
105 for (int y = 0; y < bm->height(); ++y) {
106 proc(row, bm->width());
107 row += bm->rowBytes();
108 }
109 bm->setAlphaType(kOpaque_SkAlphaType);
110 }
111
112 #define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast)
113
114 class AutoCFDataRelease {
115 CFDataRef fDR;
116 public:
117 AutoCFDataRelease(CFDataRef dr) : fDR(dr) {}
118 ~AutoCFDataRelease() { if (fDR) { CFRelease(fDR); } }
119
120 operator CFDataRef () { return fDR; }
121 };
122
123 static bool colorspace_is_sRGB(CGColorSpaceRef cs) {
124 #ifdef SK_BUILD_FOR_IOS
125 return true; // iOS seems to define itself to always return sRGB <reed>
126 #else
127 AutoCFDataRelease data(CGColorSpaceCopyICCProfile(cs));
128 if (data) {
129 // found by inspection -- need a cleaner way to sniff a profile
130 const CFIndex ICC_PROFILE_OFFSET_TO_SRGB_TAG = 52;
131
132 if (CFDataGetLength(data) >= ICC_PROFILE_OFFSET_TO_SRGB_TAG + 4) {
133 return !memcmp(CFDataGetBytePtr(data) + ICC_PROFILE_OFFSET_TO_SRGB_T AG, "sRGB", 4);
134 }
135 }
136 return false;
137 #endif
138 }
139
140 SkImageDecoder::Result SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* b m, Mode mode) {
141 CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);
142
143 if (nullptr == imageSrc) {
144 return kFailure;
145 }
146 SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);
147
148 CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, nullptr);
149 if (nullptr == image) {
150 return kFailure;
151 }
152 SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image);
153
154 const int width = SkToInt(CGImageGetWidth(image));
155 const int height = SkToInt(CGImageGetHeight(image));
156 SkColorProfileType cpType = kLinear_SkColorProfileType;
157
158 CGColorSpaceRef cs = CGImageGetColorSpace(image);
159 if (cs) {
160 CGColorSpaceModel m = CGColorSpaceGetModel(cs);
161 if (kCGColorSpaceModelRGB == m && colorspace_is_sRGB(cs)) {
162 cpType = kSRGB_SkColorProfileType;
163 }
164 }
165
166 SkAlphaType at = kPremul_SkAlphaType;
167 switch (CGImageGetAlphaInfo(image)) {
168 case kCGImageAlphaNone:
169 case kCGImageAlphaNoneSkipLast:
170 case kCGImageAlphaNoneSkipFirst:
171 at = kOpaque_SkAlphaType;
172 break;
173 default:
174 break;
175 }
176
177 bm->setInfo(SkImageInfo::Make(width, height, kN32_SkColorType, at, cpType));
178 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
179 return kSuccess;
180 }
181
182 if (!this->allocPixelRef(bm, nullptr)) {
183 return kFailure;
184 }
185
186 SkAutoLockPixels alp(*bm);
187
188 if (!SkCopyPixelsFromCGImage(bm->info(), bm->rowBytes(), bm->getPixels(), im age)) {
189 return kFailure;
190 }
191
192 CGImageAlphaInfo info = CGImageGetAlphaInfo(image);
193 switch (info) {
194 case kCGImageAlphaNone:
195 case kCGImageAlphaNoneSkipLast:
196 case kCGImageAlphaNoneSkipFirst:
197 // We're opaque, but we can't rely on the data always having 0xFF
198 // in the alpha slot (which Skia wants), so we have to ram it in
199 // ourselves.
200 force_opaque(bm);
201 break;
202 default:
203 // we don't know if we're opaque or not, so compute it.
204 if (SkBitmap::ComputeIsOpaque(*bm)) {
205 bm->setAlphaType(kOpaque_SkAlphaType);
206 }
207 }
208 if (!bm->isOpaque() && this->getRequireUnpremultipliedColors()) {
209 // CGBitmapContext does not support unpremultiplied, so the image has be en premultiplied.
210 // Convert to unpremultiplied.
211 for (int i = 0; i < width; ++i) {
212 for (int j = 0; j < height; ++j) {
213 uint32_t* addr = bm->getAddr32(i, j);
214 *addr = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*addr) ;
215 }
216 }
217 bm->setAlphaType(kUnpremul_SkAlphaType);
218 }
219 return kSuccess;
220 }
221
222 ///////////////////////////////////////////////////////////////////////////////
223
224 extern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*);
225
226 SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) {
227 SkImageDecoder* decoder = image_decoder_from_stream(stream);
228 if (nullptr == decoder) {
229 // If no image decoder specific to the stream exists, use SkImageDecoder _CG.
230 return new SkImageDecoder_CG;
231 } else {
232 return decoder;
233 }
234 }
235
31 ///////////////////////////////////////////////////////////////////////// 236 /////////////////////////////////////////////////////////////////////////
32 237
33 SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { 238 SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) {
34 return nullptr; 239 return nullptr;
35 } 240 }
36 241
37 ///////////////////////////////////////////////////////////////////////// 242 /////////////////////////////////////////////////////////////////////////
38 243
39 static size_t consumer_put(void* info, const void* buffer, size_t count) { 244 static size_t consumer_put(void* info, const void* buffer, size_t count) {
40 SkWStream* stream = reinterpret_cast<SkWStream*>(info); 245 SkWStream* stream = reinterpret_cast<SkWStream*>(info);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 case SkImageEncoder::kPNG_Type: 348 case SkImageEncoder::kPNG_Type:
144 break; 349 break;
145 default: 350 default:
146 return nullptr; 351 return nullptr;
147 } 352 }
148 return new SkImageEncoder_CG(t); 353 return new SkImageEncoder_CG(t);
149 } 354 }
150 355
151 static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_cg_factory); 356 static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_cg_factory);
152 357
153 class SkPNGImageEncoder_CG : public SkImageEncoder_CG { 358 #ifdef SK_BUILD_FOR_IOS
359 class SkPNGImageEncoder_IOS : public SkImageEncoder_CG {
154 public: 360 public:
155 SkPNGImageEncoder_CG() 361 SkPNGImageEncoder_IOS()
156 : SkImageEncoder_CG(kPNG_Type) { 362 : SkImageEncoder_CG(kPNG_Type) {
157 } 363 }
158 }; 364 };
159 365
160 DEFINE_ENCODER_CREATOR(PNGImageEncoder_CG); 366 DEFINE_ENCODER_CREATOR(PNGImageEncoder_IOS);
367 #endif
368
369 struct FormatConversion {
370 CFStringRef fUTType;
371 SkImageDecoder::Format fFormat;
372 };
373
374 // Array of the types supported by the decoder.
375 static const FormatConversion gFormatConversions[] = {
376 { kUTTypeBMP, SkImageDecoder::kBMP_Format },
377 { kUTTypeGIF, SkImageDecoder::kGIF_Format },
378 { kUTTypeICO, SkImageDecoder::kICO_Format },
379 { kUTTypeJPEG, SkImageDecoder::kJPEG_Format },
380 // Also include JPEG2000
381 { kUTTypeJPEG2000, SkImageDecoder::kJPEG_Format },
382 { kUTTypePNG, SkImageDecoder::kPNG_Format },
383 };
384
385 static SkImageDecoder::Format UTType_to_Format(const CFStringRef uttype) {
386 for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) {
387 if (CFStringCompare(uttype, gFormatConversions[i].fUTType, 0) == kCFComp areEqualTo) {
388 return gFormatConversions[i].fFormat;
389 }
390 }
391 return SkImageDecoder::kUnknown_Format;
392 }
393
394 static SkImageDecoder::Format get_format_cg(SkStreamRewindable* stream) {
395 CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);
396
397 if (nullptr == imageSrc) {
398 return SkImageDecoder::kUnknown_Format;
399 }
400
401 SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);
402 const CFStringRef name = CGImageSourceGetType(imageSrc);
403 if (nullptr == name) {
404 return SkImageDecoder::kUnknown_Format;
405 }
406 return UTType_to_Format(name);
407 }
408
409 static SkImageDecoder_FormatReg gFormatReg(get_format_cg);
161 410
162 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) 411 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
OLDNEW
« no previous file with comments | « src/images/bmpdecoderhelper.cpp ('k') | src/ports/SkImageDecoder_WIC.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698