OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 #ifndef SkCodec_DEFINED | 8 #ifndef SkCodec_DEFINED |
9 #define SkCodec_DEFINED | 9 #define SkCodec_DEFINED |
10 | 10 |
(...skipping 27 matching lines...) Expand all Loading... | |
38 * | 38 * |
39 * Will take a ref if it returns a codec, else will not affect the data. | 39 * Will take a ref if it returns a codec, else will not affect the data. |
40 */ | 40 */ |
41 static SkCodec* NewFromData(SkData*); | 41 static SkCodec* NewFromData(SkData*); |
42 | 42 |
43 virtual ~SkCodec(); | 43 virtual ~SkCodec(); |
44 | 44 |
45 /** | 45 /** |
46 * Return the ImageInfo associated with this codec. | 46 * Return the ImageInfo associated with this codec. |
47 */ | 47 */ |
48 const SkImageInfo& getInfo() const { return fInfo; } | 48 const SkImageInfo& getInfo() const { return fSrcInfo; } |
49 | 49 |
50 /** | 50 /** |
51 * Return a size that approximately supports the desired scale factor. | 51 * Return a size that approximately supports the desired scale factor. |
52 * The codec may not be able to scale efficiently to the exact scale | 52 * The codec may not be able to scale efficiently to the exact scale |
53 * factor requested, so return a size that approximates that scale. | 53 * factor requested, so return a size that approximates that scale. |
54 * The returned value is the codec's suggestion for the closest valid | 54 * The returned value is the codec's suggestion for the closest valid |
55 * scale that it can natively support | 55 * scale that it can natively support |
56 */ | 56 */ |
57 SkISize getScaledDimensions(float desiredScale) const { | 57 SkISize getScaledDimensions(float desiredScale) const { |
58 // Negative and zero scales are errors. | 58 // Negative and zero scales are errors. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
124 /** | 124 /** |
125 * The input did not contain a valid image. | 125 * The input did not contain a valid image. |
126 */ | 126 */ |
127 kInvalidInput, | 127 kInvalidInput, |
128 /** | 128 /** |
129 * Fulfilling this request requires rewinding the input, which is not | 129 * Fulfilling this request requires rewinding the input, which is not |
130 * supported for this input. | 130 * supported for this input. |
131 */ | 131 */ |
132 kCouldNotRewind, | 132 kCouldNotRewind, |
133 /** | 133 /** |
134 * This method is not implemented by this generator. | 134 * This method is not implemented by this codec. |
135 * FIXME: Perhaps this should be kUnsupported? | |
135 */ | 136 */ |
136 kUnimplemented, | 137 kUnimplemented, |
138 /** | |
139 * start() was not called before calling getScanlines. | |
140 */ | |
141 kScanlineDecodingNotStarted, | |
137 }; | 142 }; |
138 | 143 |
139 /** | 144 /** |
140 * Whether or not the memory passed to getPixels is zero initialized. | 145 * Whether or not the memory passed to getPixels is zero initialized. |
141 */ | 146 */ |
142 enum ZeroInitialized { | 147 enum ZeroInitialized { |
143 /** | 148 /** |
144 * The memory passed to getPixels is zero initialized. The SkCodec | 149 * The memory passed to getPixels is zero initialized. The SkCodec |
145 * may take advantage of this by skipping writing zeroes. | 150 * may take advantage of this by skipping writing zeroes. |
146 */ | 151 */ |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
195 * to scale. If the generator cannot perform this scale, | 200 * to scale. If the generator cannot perform this scale, |
196 * it will return kInvalidScale. | 201 * it will return kInvalidScale. |
197 * | 202 * |
198 * If info is kIndex8_SkColorType, then the caller must provide storage for up to 256 | 203 * If info is kIndex8_SkColorType, then the caller must provide storage for up to 256 |
199 * SkPMColor values in ctable. On success the generator must copy N colors into that storage, | 204 * SkPMColor values in ctable. On success the generator must copy N colors into that storage, |
200 * (where N is the logical number of table entries) and set ctableCount to N. | 205 * (where N is the logical number of table entries) and set ctableCount to N. |
201 * | 206 * |
202 * If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount | 207 * If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount |
203 * is not null, it will be set to 0. | 208 * is not null, it will be set to 0. |
204 * | 209 * |
210 * If a scanline decode is in progress, scanline mode will end, requiring t he client to call | |
211 * start() in order to return to decoding scanlines. | |
212 * | |
205 * @return Result kSuccess, or another value explaining the type of failure . | 213 * @return Result kSuccess, or another value explaining the type of failure . |
206 */ | 214 */ |
207 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, con st Options*, | 215 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, con st Options*, |
208 SkPMColor ctable[], int* ctableCount); | 216 SkPMColor ctable[], int* ctableCount); |
209 | 217 |
210 /** | 218 /** |
211 * Simplified version of getPixels() that asserts that info is NOT kIndex8_ SkColorType and | 219 * Simplified version of getPixels() that asserts that info is NOT kIndex8_ SkColorType and |
212 * uses the default Options. | 220 * uses the default Options. |
213 */ | 221 */ |
214 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes); | 222 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes); |
215 | 223 |
216 /** | 224 /** |
217 * Some images may initially report that they have alpha due to the format | 225 * Some images may initially report that they have alpha due to the format |
218 * of the encoded data, but then never use any colors which have alpha | 226 * of the encoded data, but then never use any colors which have alpha |
219 * less than 100%. This function can be called *after* decoding to | 227 * less than 100%. This function can be called *after* decoding to |
220 * determine if such an image truly had alpha. Calling it before decoding | 228 * determine if such an image truly had alpha. Calling it before decoding |
221 * is undefined. | 229 * is undefined. |
222 * FIXME: see skbug.com/3582. | 230 * FIXME: see skbug.com/3582. |
223 */ | 231 */ |
224 bool reallyHasAlpha() const { | 232 bool reallyHasAlpha() const { |
225 return this->onReallyHasAlpha(); | 233 return this->onReallyHasAlpha(); |
226 } | 234 } |
227 | 235 |
236 /** | |
237 * The remaining functions revolve around decoding scanlines. | |
238 */ | |
239 | |
240 /** | |
241 * Initialize on the first scanline, with the specified options. | |
msarett
2015/09/28 14:48:50
"Initialize on the first scanline" is a little unc
scroggo
2015/09/28 16:01:52
Sgtm. I think it made a little more sense back whe
| |
242 * | |
243 * This must be called in order to call getScanlines or skipScanlines. | |
244 * | |
245 * This may require rewinding the stream. | |
246 * | |
247 * Not all SkCodecs support this. | |
248 * | |
249 * @param dstInfo Info of the destination. If the dimensions do not match | |
250 * those of getInfo, this implies a scale. | |
251 * @param options Contains decoding options, including if memory is zero | |
252 * initialized. | |
253 * @param ctable A pointer to a color table. When dstInfo.colorType() is | |
254 * kIndex8, this should be non-NULL and have enough storage for 256 | |
255 * colors. The color table will be populated after decoding the palett e. | |
256 * @param ctableCount A pointer to the size of the color table. When | |
257 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will | |
258 * be modified to the true size of the color table (<= 256) after | |
259 * decoding the palette. | |
260 * @return Enum representing success or reason for failure. | |
261 */ | |
262 Result start(const SkImageInfo& dstInfo, const SkCodec::Options* options, | |
scroggo
2015/09/25 16:07:49
I left the name "start" to make the changeover sim
msarett
2015/09/28 14:48:50
I like a shorter name but that's because I know wh
scroggo
2015/09/28 16:01:52
These sound fine with me. I'll wait for API review
| |
263 SkPMColor ctable[], int* ctableCount); | |
264 | |
265 /** | |
266 * Simplified version of start() that asserts that info is NOT | |
267 * kIndex8_SkColorType and uses the default Options. | |
268 */ | |
269 Result start(const SkImageInfo& dstInfo); | |
270 | |
271 /** | |
272 * Write the next countLines scanlines into dst. | |
273 * | |
274 * Not valid to call before calling start(). | |
275 * | |
276 * @param dst Must be non-null, and large enough to hold countLines | |
277 * scanlines of size rowBytes. | |
278 * @param countLines Number of lines to write. | |
279 * @param rowBytes Number of bytes per row. Must be large enough to hold | |
280 * a scanline based on the SkImageInfo used to create this object. | |
281 */ | |
282 Result getScanlines(void* dst, int countLines, size_t rowBytes) { | |
283 if (fCurrScanline < 0) { | |
scroggo
2015/09/25 16:07:49
Alternatively, I could have checked fDstInfo, whic
msarett
2015/09/28 14:48:50
I like what you've chosen to do.
| |
284 return kScanlineDecodingNotStarted; | |
scroggo
2015/09/25 16:07:49
I know (msarett@) you have a CL out for review whi
msarett
2015/09/28 14:48:50
Yeah I think that's ok. Maybe we can provide more
scroggo
2015/09/28 16:01:52
I think returning kScanlineDecodingNoStarted is pr
| |
285 } | |
286 | |
287 SkASSERT(!fDstInfo.isEmpty()); | |
288 if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0 | |
289 || fCurrScanline + countLines > fDstInfo.height()) { | |
290 return kInvalidParameters; | |
291 } | |
292 const Result result = this->onGetScanlines(dst, countLines, rowBytes); | |
293 fCurrScanline += countLines; | |
294 return result; | |
295 } | |
296 | |
297 /** | |
298 * Skip count scanlines. | |
299 * | |
300 * Not valid to call before calling start(). | |
301 * | |
302 * The default version just calls onGetScanlines and discards the dst. | |
303 * NOTE: If skipped lines are the only lines with alpha, this default | |
304 * will make reallyHasAlpha return true, when it could have returned | |
305 * false. | |
306 */ | |
307 Result skipScanlines(int countLines) { | |
308 if (fCurrScanline < 0) { | |
309 return kScanlineDecodingNotStarted; | |
310 } | |
311 SkASSERT(!fDstInfo.isEmpty()); | |
312 if (fCurrScanline + countLines > fDstInfo.height()) { | |
313 // Arguably, we could just skip the scanlines which are remaining, | |
314 // and return kSuccess. We choose to return invalid so the client | |
315 // can catch their bug. | |
316 return SkCodec::kInvalidParameters; | |
317 } | |
318 const Result result = this->onSkipScanlines(countLines); | |
319 fCurrScanline += countLines; | |
320 return result; | |
321 } | |
322 | |
323 /** | |
324 * The order in which rows are output from the scanline decoder is not the | |
325 * same for all variations of all image types. This explains the possible | |
326 * output row orderings. | |
327 */ | |
328 enum SkScanlineOrder { | |
329 /* | |
330 * By far the most common, this indicates that the image can be decoded | |
331 * reliably using the scanline decoder, and that rows will be output in | |
332 * the logical order. | |
333 */ | |
334 kTopDown_SkScanlineOrder, | |
335 | |
336 /* | |
337 * This indicates that the scanline decoder reliably outputs rows, but | |
338 * they will be returned in reverse order. If the scanline format is | |
339 * kBottomUp, the getY() API can be used to determine the actual | |
340 * y-coordinate of the next output row, but the client is not forced | |
341 * to take advantage of this, given that it's not too tough to keep | |
342 * track independently. | |
343 * | |
344 * For full image decodes, it is safe to get all of the scanlines at | |
345 * once, since the decoder will handle inverting the rows as it | |
346 * decodes. | |
347 * | |
348 * For subset decodes and sampling, it is simplest to get and skip | |
349 * scanlines one at a time, using the getY() API. It is possible to | |
350 * ask for larger chunks at a time, but this should be used with | |
351 * caution. As with full image decodes, the decoder will handle | |
352 * inverting the requested rows, but rows will still be delivered | |
353 * starting from the bottom of the image. | |
354 * | |
355 * Upside down bmps are an example. | |
356 */ | |
357 kBottomUp_SkScanlineOrder, | |
358 | |
359 /* | |
360 * This indicates that the scanline decoder reliably outputs rows, but | |
361 * they will not be in logical order. If the scanline format is | |
362 * kOutOfOrder, the getY() API should be used to determine the actual | |
363 * y-coordinate of the next output row. | |
364 * | |
365 * For this scanline ordering, it is advisable to get and skip | |
366 * scanlines one at a time. | |
367 * | |
368 * Interlaced gifs are an example. | |
369 */ | |
370 kOutOfOrder_SkScanlineOrder, | |
371 | |
372 /* | |
373 * Indicates that the entire image must be decoded in order to output | |
374 * any amount of scanlines. In this case, it is a REALLY BAD IDEA to | |
375 * request scanlines 1-by-1 or in small chunks. The client should | |
376 * determine which scanlines are needed and ask for all of them in | |
377 * a single call to getScanlines(). | |
378 * | |
379 * Interlaced pngs are an example. | |
380 */ | |
381 kNone_SkScanlineOrder, | |
382 }; | |
383 | |
384 /** | |
385 * An enum representing the order in which scanlines will be returned by | |
386 * the scanline decoder. | |
387 */ | |
388 SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder() ; } | |
389 | |
390 /** | |
391 * Returns the y-coordinate of the next row to be returned by the scanline | |
392 * decoder. This will be overridden in the case of | |
393 * kOutOfOrder_SkScanlineOrder and should be unnecessary in the case of | |
394 * kNone_SkScanlineOrder. | |
395 * | |
396 * Results are undefined when not in scanline decoding mode. | |
397 */ | |
398 int getY() const { | |
399 SkASSERT(kNone_SkScanlineOrder != this->getScanlineOrder()); | |
msarett
2015/09/28 14:48:50
Given that the interlaced png scanline decoder now
scroggo
2015/09/28 16:01:52
I've removed the assert. FWIW, interlaced png call
| |
400 return this->onGetY(); | |
401 } | |
402 | |
228 protected: | 403 protected: |
229 SkCodec(const SkImageInfo&, SkStream*); | 404 SkCodec(const SkImageInfo&, SkStream*); |
230 | 405 |
231 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { | 406 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { |
232 // By default, scaling is not supported. | 407 // By default, scaling is not supported. |
233 return this->getInfo().dimensions(); | 408 return this->getInfo().dimensions(); |
234 } | 409 } |
235 | 410 |
236 virtual SkEncodedFormat onGetEncodedFormat() const = 0; | 411 virtual SkEncodedFormat onGetEncodedFormat() const = 0; |
237 | 412 |
(...skipping 30 matching lines...) Expand all Loading... | |
268 return true; | 443 return true; |
269 } | 444 } |
270 | 445 |
271 /** | 446 /** |
272 * Get method for the input stream | 447 * Get method for the input stream |
273 */ | 448 */ |
274 SkStream* stream() { | 449 SkStream* stream() { |
275 return fStream.get(); | 450 return fStream.get(); |
276 } | 451 } |
277 | 452 |
453 /** | |
454 * The remaining functions revolve around decoding scanlines. | |
455 */ | |
456 | |
457 /** | |
458 * Most images types will be kTopDown and will not need to override this fu nction. | |
459 */ | |
460 virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanl ineOrder; } | |
461 | |
462 /** | |
463 * Most images will be kTopDown and will not need to override this function . | |
464 */ | |
465 virtual int onGetY() const { return fCurrScanline; } | |
466 | |
467 /** | |
468 * Update the next scanline. Used by interlaced png. | |
469 */ | |
470 void updateY(int newY) { fCurrScanline = newY; } | |
scroggo
2015/09/25 16:07:49
I named this updateY to mirror getY, but I might p
msarett
2015/09/28 14:48:50
I'm in favor of renaming these.
I think my origin
scroggo
2015/09/28 16:01:52
I'll add a FIXME to discuss for API review. I woul
| |
471 | |
472 const SkImageInfo& dstInfo() const { return fDstInfo; } | |
473 | |
474 const SkCodec::Options& options() const { return fOptions; } | |
475 | |
278 private: | 476 private: |
279 const SkImageInfo fInfo; | 477 const SkImageInfo fSrcInfo; |
280 SkAutoTDelete<SkStream> fStream; | 478 SkAutoTDelete<SkStream> fStream; |
281 bool fNeedsRewind; | 479 bool fNeedsRewind; |
480 // These fields are only meaningful during scanline decodes. | |
481 SkImageInfo fDstInfo; | |
482 SkCodec::Options fOptions; | |
483 int fCurrScanline; | |
484 | |
485 // Methods for scanline decoding. | |
486 virtual SkCodec::Result onStart(const SkImageInfo& dstInfo, | |
487 const SkCodec::Options& options, | |
488 SkPMColor ctable[], int* ctableCount) { | |
489 return kUnimplemented; | |
490 } | |
491 | |
492 // Naive default version just calls onGetScanlines on temp memory. | |
493 virtual SkCodec::Result onSkipScanlines(int countLines) { | |
494 SkAutoMalloc storage(fDstInfo.minRowBytes()); | |
495 // Note that we pass 0 to rowBytes so we continue to use the same memory . | |
496 // Also note that while getScanlines checks that rowBytes is big enough, | |
497 // onGetScanlines bypasses that check. | |
498 // Calling the virtual method also means we do not double count | |
499 // countLines. | |
500 return this->onGetScanlines(storage.get(), countLines, 0); | |
501 } | |
502 | |
503 virtual SkCodec::Result onGetScanlines(void* dst, int countLines, | |
504 size_t rowBytes) { | |
505 return kUnimplemented; | |
506 } | |
507 | |
282 }; | 508 }; |
283 #endif // SkCodec_DEFINED | 509 #endif // SkCodec_DEFINED |
OLD | NEW |