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

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

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

Powered by Google App Engine
This is Rietveld 408576698