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

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

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

Powered by Google App Engine
This is Rietveld 408576698