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

Side by Side Diff: src/images/SkDecodingImageGenerator.cpp

Issue 93703004: Change SkDecodingImageGenerator API (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years 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 | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
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 "SkDecodingImageGenerator.h" 8 #include "SkDecodingImageGenerator.h"
9 #include "SkData.h" 9 #include "SkData.h"
10 #include "SkImageDecoder.h" 10 #include "SkImageDecoder.h"
11 #include "SkImageGenerator.h" 11 #include "SkImageGenerator.h"
12 #include "SkImagePriv.h" 12 #include "SkImagePriv.h"
13 #include "SkStream.h" 13 #include "SkStream.h"
14 14 #include "SkUtils.h"
15 15
16 namespace { 16 namespace {
17 /** 17 /**
18 * Special allocator used by getPixels(). Uses preallocated memory 18 * Special allocator used by getPixels(). Uses preallocated memory
19 * provided. 19 * provided.
20 */ 20 */
21 class TargetAllocator : public SkBitmap::Allocator { 21 class TargetAllocator : public SkBitmap::Allocator {
22 public: 22 public:
23 TargetAllocator(void* target, size_t rowBytes, const SkImageInfo& info) 23 TargetAllocator(void* target,
24 size_t rowBytes,
25 int width,
26 int height,
27 SkBitmap::Config config)
scroggo 2013/12/12 22:33:46 Comments would be nice here, explaining the parame
hal.canary 2013/12/13 15:48:48 Done.
24 : fTarget(target) 28 : fTarget(target)
25 , fRowBytes(rowBytes) 29 , fRowBytes(rowBytes)
26 , fInfo(info) { } 30 , fWidth(width)
31 , fHeight(height)
32 , fConfig(config) { }
33
34 bool isReady() { return (fTarget != NULL); }
27 35
28 virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE { 36 virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE {
29 if ((SkImageInfoToBitmapConfig(fInfo) != bm->config()) 37 if ((NULL == fTarget)
scroggo 2013/12/12 22:33:46 When will fTarget be NULL and called?
hal.canary 2013/12/13 15:48:48 probably shouldn't happen. but a weird decoder co
scroggo 2013/12/13 17:23:03 What should we do in that situation? I think the c
30 || (bm->width() != fInfo.fWidth) 38 || (fConfig != bm->config())
31 || (bm->height() != fInfo.fHeight)) { 39 || (fWidth != bm->width())
scroggo 2013/12/12 22:33:46 It seems you're mixing uses of this if statement.
hal.canary 2013/12/13 15:48:48 I just want to assert that everyone agrees on what
scroggo 2013/12/13 17:23:03 You don't assert anything - you allocate new pixel
32 return false; 40 || (fHeight != bm->height())
41 || (ct != NULL)) {
42 return bm->allocPixels(NULL, ct);
33 } 43 }
34 bm->setConfig(bm->config(), bm->width(), bm->height(), 44 bm->setConfig(fConfig, fWidth, fHeight, fRowBytes, bm->alphaType());
35 fRowBytes, bm->alphaType()); 45 // TODO(halcanary): verify that all callers of this function
36 bm->setPixels(fTarget, ct); 46 // will respect new RowBytes. Will be moot once rowbytes belongs
47 // to PixelRef.
48 bm->setPixels(fTarget, NULL);
49 fTarget = NULL;
37 return true; 50 return true;
38 } 51 }
39 52
40 private: 53 private:
41 void* fTarget; 54 void* fTarget;
42 size_t fRowBytes; 55 size_t fRowBytes;
43 SkImageInfo fInfo; 56 int fWidth;
57 int fHeight;
58 SkBitmap::Config fConfig;
44 typedef SkBitmap::Allocator INHERITED; 59 typedef SkBitmap::Allocator INHERITED;
45 }; 60 };
46 } // namespace 61 } // namespace
47 //////////////////////////////////////////////////////////////////////////////// 62 ////////////////////////////////////////////////////////////////////////////////
48 63
49 SkDecodingImageGenerator::SkDecodingImageGenerator(SkData* data) 64 SkDecodingImageGenerator::SkDecodingImageGenerator(SkData* data,
65 const Options* opts)
50 : fData(data) 66 : fData(data)
51 , fHasInfo(false) 67 , fHasInfo(false)
52 , fDoCopyTo(false) { 68 , fDoCopyTo(false)
69 , fOpts() {
53 SkASSERT(fData != NULL); 70 SkASSERT(fData != NULL);
54 fStream = SkNEW_ARGS(SkMemoryStream, (fData)); 71 fStream = SkNEW_ARGS(SkMemoryStream, (fData));
55 SkASSERT(fStream != NULL); 72 SkASSERT(fStream != NULL);
56 SkASSERT(fStream->unique()); 73 SkASSERT(fStream->unique());
57 fData->ref(); 74 fData->ref();
75 if (opts != NULL) {
76 fOpts = *opts;
77 SkASSERT(fOpts.fRequestedConfig != SkBitmap::kIndex8_Config);
78 }
58 } 79 }
59 80
60 SkDecodingImageGenerator::SkDecodingImageGenerator(SkStreamRewindable* stream) 81 SkDecodingImageGenerator::SkDecodingImageGenerator(SkStreamRewindable* stream,
82 const Options* opts)
61 : fData(NULL) 83 : fData(NULL)
62 , fStream(stream) 84 , fStream(stream)
63 , fHasInfo(false) 85 , fHasInfo(false)
64 , fDoCopyTo(false) { 86 , fDoCopyTo(false)
87 , fOpts() {
65 SkASSERT(fStream != NULL); 88 SkASSERT(fStream != NULL);
66 SkASSERT(fStream->unique()); 89 SkASSERT(fStream->unique());
90 if (opts != NULL) {
91 fOpts = *opts;
92 SkASSERT(fOpts.fRequestedConfig != SkBitmap::kIndex8_Config);
93 }
67 } 94 }
68 95
69 SkDecodingImageGenerator::~SkDecodingImageGenerator() { 96 SkDecodingImageGenerator::~SkDecodingImageGenerator() {
70 SkSafeUnref(fData); 97 SkSafeUnref(fData);
71 fStream->unref(); 98 fStream->unref();
72 } 99 }
73 100
74 // TODO(halcanary): Give this macro a better name and move it into SkTypes.h 101 // TODO(halcanary): Give this macro a better name and move it into SkTypes.h
75 #ifdef SK_DEBUG 102 #ifdef SK_DEBUG
76 #define SkCheckResult(expr, value) SkASSERT((value) == (expr)) 103 #define SkCheckResult(expr, value) SkASSERT((value) == (expr))
77 #else 104 #else
78 #define SkCheckResult(expr, value) (void)(expr) 105 #define SkCheckResult(expr, value) (void)(expr)
79 #endif 106 #endif
80 107
81 SkData* SkDecodingImageGenerator::refEncodedData() { 108 SkData* SkDecodingImageGenerator::refEncodedData() {
82 // This functionality is used in `gm --serialize` 109 // This functionality is used in `gm --serialize`
110 // Does not encode options.
83 if (fData != NULL) { 111 if (fData != NULL) {
84 return SkSafeRef(fData); 112 return SkSafeRef(fData);
85 } 113 }
86 // TODO(halcanary): SkStreamRewindable needs a refData() function 114 // TODO(halcanary): SkStreamRewindable needs a refData() function
87 // which returns a cheap copy of the underlying data. 115 // which returns a cheap copy of the underlying data.
88 if (!fStream->rewind()) { 116 if (!fStream->rewind()) {
89 return NULL; 117 return NULL;
90 } 118 }
91 size_t length = fStream->getLength(); 119 size_t length = fStream->getLength();
92 if (0 == length) { 120 if (0 == length) {
93 return NULL; 121 return NULL;
94 } 122 }
95 void* buffer = sk_malloc_flags(length, 0); 123 void* buffer = sk_malloc_flags(length, 0);
96 SkCheckResult(fStream->read(buffer, length), length); 124 SkCheckResult(fStream->read(buffer, length), length);
97 fData = SkData::NewFromMalloc(buffer, length); 125 fData = SkData::NewFromMalloc(buffer, length);
98 return SkSafeRef(fData); 126 return SkSafeRef(fData);
99 } 127 }
100 128
129 // TODO(halcanary) move this function into a standard header.
130 static bool config_to_colorType(SkBitmap::Config config, SkColorType* ctOut) {
131 SkColorType ct;
132 switch (config) {
133 case SkBitmap::kA8_Config:
134 ct = kAlpha_8_SkColorType;
135 break;
136 case SkBitmap::kIndex8_Config:
137 ct = kIndex_8_SkColorType;
138 break;
139 case SkBitmap::kRGB_565_Config:
140 ct = kRGB_565_SkColorType;
141 break;
142 case SkBitmap::kARGB_4444_Config:
143 ct = kARGB_4444_SkColorType;
144 break;
145 case SkBitmap::kARGB_8888_Config:
146 ct = kPMColor_SkColorType;
147 break;
148 case SkBitmap::kNo_Config:
149 default:
150 return false;
151 }
152 if (ctOut) {
153 *ctOut = ct;
154 }
155 return true;
156 }
157
158
101 bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) { 159 bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
160 if (SkBitmap::kIndex8_Config == fOpts.fRequestedConfig) {
161 // We do not support indexed color with SkImageGenerators,
162 SkDEBUGFAIL("SkBitmap::kIndex8_Config == fOpts.fRequestedConfig");
163 return false;
164 }
165
102 // info can be NULL. If so, will update fInfo, fDoCopyTo, and fHasInfo. 166 // info can be NULL. If so, will update fInfo, fDoCopyTo, and fHasInfo.
103 if (fHasInfo) { 167 if (fHasInfo) {
104 if (info != NULL) { 168 if (info != NULL) {
105 *info = fInfo; 169 *info = fInfo;
106 } 170 }
107 return true; 171 return true;
108 } 172 }
109 SkAssertResult(fStream->rewind()); 173 SkAssertResult(fStream->rewind());
110 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream)); 174 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
111 if (NULL == decoder.get()) { 175 if (NULL == decoder.get()) {
112 return false; 176 return false;
113 } 177 }
178
114 SkBitmap bitmap; 179 SkBitmap bitmap;
180 decoder->setSampleSize(fOpts.fSampleSize);
115 if (!decoder->decode(fStream, &bitmap, 181 if (!decoder->decode(fStream, &bitmap,
116 SkImageDecoder::kDecodeBounds_Mode)) { 182 SkImageDecoder::kDecodeBounds_Mode)) {
117 return false; 183 return false;
118 } 184 }
119 if (bitmap.config() == SkBitmap::kNo_Config) { 185 if (bitmap.config() == SkBitmap::kNo_Config) {
120 return false; 186 return false;
121 } 187 }
122 if (!bitmap.asImageInfo(&fInfo)) { 188
123 // We can't use bitmap.config() as is. 189 if (fOpts.fRequestedConfig == SkBitmap::kNo_Config) {
124 if (!bitmap.canCopyTo(SkBitmap::kARGB_8888_Config)) { 190 // Use default config.
125 SkDEBUGFAIL("!bitmap->canCopyTo(SkBitmap::kARGB_8888_Config)"); 191 if (SkBitmap::kIndex8_Config == bitmap.config()) {
192 // We don't support kIndex8 because we don't support
193 // colortables in this workflow.
194 fOpts.fRequestedConfig = SkBitmap::kARGB_8888_Config;
195 fInfo.fWidth = bitmap.width();
196 fInfo.fHeight = bitmap.height();
197 fInfo.fColorType = kPMColor_SkColorType;
198 fInfo.fAlphaType = bitmap.alphaType();
199 } else {
200 fOpts.fRequestedConfig = bitmap.config(); // Save for later!
201 if (!bitmap.asImageInfo(&fInfo)) {
202 SkDEBUGFAIL("!bitmap.asImageInfo() && !kNoConfig");
scroggo 2013/12/12 22:33:46 Can you make this message more informative?
hal.canary 2013/12/13 15:48:48 Done.
203 return false;
204 }
205 }
206 } else {
207 if (!bitmap.canCopyTo(fOpts.fRequestedConfig)) {
208 SkASSERT(SkBitmap::kARGB_4444_Config == fOpts.fRequestedConfig);
209 SkASSERT(bitmap.config() != fOpts.fRequestedConfig);
210 return false; // Can not translate to needed config.
211 }
212 fInfo.fWidth = bitmap.width();
213 fInfo.fHeight = bitmap.height();
214 if (!config_to_colorType(fOpts.fRequestedConfig,
215 &(fInfo.fColorType))) {
216 SkDEBUGFAIL("SkBitmapConfigToColorType fails.");
126 return false; 217 return false;
127 } 218 }
128 fDoCopyTo = true;
129 fInfo.fWidth = bitmap.width();
130 fInfo.fHeight = bitmap.height();
131 fInfo.fColorType = kPMColor_SkColorType;
132 fInfo.fAlphaType = bitmap.alphaType(); 219 fInfo.fAlphaType = bitmap.alphaType();
133 } 220 }
134 if (info != NULL) { 221 if (info != NULL) {
135 *info = fInfo; 222 *info = fInfo;
136 } 223 }
137 fHasInfo = true; 224 fHasInfo = true;
138 return true; 225 return true;
139 } 226 }
140 227
228 static inline bool check_alpha(SkAlphaType reported, SkAlphaType actual) {
229 return ((reported == actual)
230 || ((reported == kPremul_SkAlphaType)
231 && (actual == kOpaque_SkAlphaType)));
232 }
233
141 bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info, 234 bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info,
142 void* pixels, 235 void* pixels,
143 size_t rowBytes) { 236 size_t rowBytes) {
144 if (NULL == pixels) { 237 if (NULL == pixels) {
145 return false; 238 return false;
146 } 239 }
147 if (!this->getInfo(NULL)) { 240 if (!this->getInfo(NULL)) { // Verify that fInfo populated.
148 return false; 241 return false;
149 } 242 }
150 if (SkImageInfoToBitmapConfig(info) == SkBitmap::kNo_Config) { 243 if (SkImageInfoToBitmapConfig(info) == SkBitmap::kNo_Config) {
151 return false; // Unsupported SkColorType. 244 return false; // Unsupported SkColorType.
152 } 245 }
246 if (fInfo != info) {
247 // The caller has specified a different info. This is an
248 // error for this kind of SkImageGenerator. Use the Options
249 // to change the settings.
250 return false;
251 }
252 int bpp = SkBitmap::ComputeBytesPerPixel(fOpts.fRequestedConfig);
253 if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
254 // The caller has specified a bad rowBytes.
255 return false;
256 }
257
153 SkAssertResult(fStream->rewind()); 258 SkAssertResult(fStream->rewind());
154 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream)); 259 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
155 if (NULL == decoder.get()) { 260 if (NULL == decoder.get()) {
156 return false; 261 return false;
157 } 262 }
158 if (fInfo != info) { 263 decoder->setDitherImage(fOpts.fDitherImage);
159 // The caller has specified a different info. For now, this 264 decoder->setPreferQualityOverSpeed(fOpts.fPreferQualityOverSpeed);
160 // is an error. In the future, we will check to see if we can 265 decoder->setSampleSize(fOpts.fSampleSize);
161 // convert. 266
162 return false;
163 }
164 int bpp = SkBitmap::ComputeBytesPerPixel(SkImageInfoToBitmapConfig(info));
165 if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
166 return false;
167 }
168 SkBitmap bitmap; 267 SkBitmap bitmap;
169 if (!bitmap.setConfig(info, rowBytes)) { 268 TargetAllocator allocator(pixels, rowBytes, info.fWidth,
170 return false; 269 info.fHeight, fOpts.fRequestedConfig);
171 } 270 decoder->setAllocator(&allocator);
172 271 bool success = decoder->decode(fStream, &bitmap, fOpts.fRequestedConfig,
173 TargetAllocator allocator(pixels, rowBytes, info);
174 if (!fDoCopyTo) {
175 decoder->setAllocator(&allocator);
176 }
177 bool success = decoder->decode(fStream, &bitmap,
178 SkImageDecoder::kDecodePixels_Mode); 272 SkImageDecoder::kDecodePixels_Mode);
179 decoder->setAllocator(NULL); 273 decoder->setAllocator(NULL);
180 if (!success) { 274 if (!success) {
181 return false; 275 return false;
182 } 276 }
183 if (fDoCopyTo) { 277 if (allocator.isReady()) { // Did not use pixels!
184 SkBitmap bm8888; 278 SkBitmap bm;
185 bitmap.copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator); 279 SkASSERT(bitmap.canCopyTo(fOpts.fRequestedConfig));
280 bitmap.copyTo(&bm, fOpts.fRequestedConfig, &allocator);
281 if (allocator.isReady()) {
282 SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
283 return false;
284 }
285 SkASSERT(check_alpha(fInfo.fAlphaType, bm.alphaType()));
286 } else {
287 SkASSERT(check_alpha(fInfo.fAlphaType, bitmap.alphaType()));
186 } 288 }
187 return true; 289 return true;
188 } 290 }
291
189 bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst, 292 bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst,
293 const Options* opts,
190 SkDiscardableMemory::Factory* factory) { 294 SkDiscardableMemory::Factory* factory) {
191 SkASSERT(data != NULL); 295 SkASSERT(data != NULL);
192 SkASSERT(dst != NULL); 296 SkASSERT(dst != NULL);
193 SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data))); 297 SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data, opts)));
194 return SkInstallDiscardablePixelRef(gen, dst, factory); 298 return SkInstallDiscardablePixelRef(gen, dst, factory);
195 } 299 }
196 300
197 bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream, 301 bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream,
198 SkBitmap* dst, 302 SkBitmap* dst,
303 const Options* opts,
199 SkDiscardableMemory::Factory* factory) { 304 SkDiscardableMemory::Factory* factory) {
200 SkASSERT(stream != NULL); 305 SkASSERT(stream != NULL);
201 SkASSERT(dst != NULL); 306 SkASSERT(dst != NULL);
202 if ((stream == NULL) || !stream->unique()) { 307 if ((stream == NULL) || !stream->unique()) {
203 SkSafeUnref(stream); 308 SkSafeUnref(stream);
204 return false; 309 return false;
205 } 310 }
206 SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream))); 311 SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream, opts)));
207 return SkInstallDiscardablePixelRef(gen, dst, factory); 312 return SkInstallDiscardablePixelRef(gen, dst, factory);
208 } 313 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698