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, | |
djsollen
2015/09/29 20:22:17
move this above unimplemented.
scroggo
2015/09/30 13:32:20
Done.
| |
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 * Prepare for a scanline decode with the specified options. | |
242 * | |
243 * After this call, this class will be ready to decode the first scanline. | |
244 * | |
245 * This must be called in order to call getScanlines or skipScanlines. | |
246 * | |
247 * This may require rewinding the stream. | |
248 * | |
249 * Not all SkCodecs support this. | |
250 * | |
251 * @param dstInfo Info of the destination. If the dimensions do not match | |
252 * those of getInfo, this implies a scale. | |
253 * @param options Contains decoding options, including if memory is zero | |
254 * initialized. | |
255 * @param ctable A pointer to a color table. When dstInfo.colorType() is | |
256 * kIndex8, this should be non-NULL and have enough storage for 256 | |
257 * colors. The color table will be populated after decoding the palett e. | |
258 * @param ctableCount A pointer to the size of the color table. When | |
259 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will | |
260 * be modified to the true size of the color table (<= 256) after | |
261 * decoding the palette. | |
262 * @return Enum representing success or reason for failure. | |
263 */ | |
264 Result start(const SkImageInfo& dstInfo, const SkCodec::Options* options, | |
djsollen
2015/09/29 20:22:17
now that this is no longer part of a scanline clas
scroggo
2015/09/30 13:32:20
Matt included the same name in his suggestions. Do
| |
265 SkPMColor ctable[], int* ctableCount); | |
266 | |
267 /** | |
268 * Simplified version of start() that asserts that info is NOT | |
269 * kIndex8_SkColorType and uses the default Options. | |
270 */ | |
271 Result start(const SkImageInfo& dstInfo); | |
272 | |
273 /** | |
274 * Write the next countLines scanlines into dst. | |
275 * | |
276 * Not valid to call before calling start(). | |
277 * | |
278 * @param dst Must be non-null, and large enough to hold countLines | |
279 * scanlines of size rowBytes. | |
280 * @param countLines Number of lines to write. | |
281 * @param rowBytes Number of bytes per row. Must be large enough to hold | |
282 * a scanline based on the SkImageInfo used to create this object. | |
283 */ | |
284 Result getScanlines(void* dst, int countLines, size_t rowBytes) { | |
djsollen
2015/09/29 20:22:17
any reason not to move this to the cpp file since
scroggo
2015/09/30 13:32:20
Done. I also moved skipScanlines into cpp
| |
285 if (fCurrScanline < 0) { | |
286 return kScanlineDecodingNotStarted; | |
287 } | |
288 | |
289 SkASSERT(!fDstInfo.isEmpty()); | |
290 if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0 | |
291 || fCurrScanline + countLines > fDstInfo.height()) { | |
292 return kInvalidParameters; | |
293 } | |
294 const Result result = this->onGetScanlines(dst, countLines, rowBytes); | |
295 fCurrScanline += countLines; | |
296 return result; | |
297 } | |
298 | |
299 /** | |
300 * Skip count scanlines. | |
301 * | |
302 * Not valid to call before calling start(). | |
303 * | |
304 * The default version just calls onGetScanlines and discards the dst. | |
305 * NOTE: If skipped lines are the only lines with alpha, this default | |
306 * will make reallyHasAlpha return true, when it could have returned | |
307 * false. | |
308 */ | |
309 Result skipScanlines(int countLines) { | |
310 if (fCurrScanline < 0) { | |
311 return kScanlineDecodingNotStarted; | |
312 } | |
313 SkASSERT(!fDstInfo.isEmpty()); | |
314 if (fCurrScanline + countLines > fDstInfo.height()) { | |
315 // Arguably, we could just skip the scanlines which are remaining, | |
316 // and return kSuccess. We choose to return invalid so the client | |
317 // can catch their bug. | |
318 return SkCodec::kInvalidParameters; | |
319 } | |
320 const Result result = this->onSkipScanlines(countLines); | |
321 fCurrScanline += countLines; | |
322 return result; | |
323 } | |
324 | |
325 /** | |
326 * The order in which rows are output from the scanline decoder is not the | |
327 * same for all variations of all image types. This explains the possible | |
328 * output row orderings. | |
329 */ | |
330 enum SkScanlineOrder { | |
331 /* | |
332 * By far the most common, this indicates that the image can be decoded | |
333 * reliably using the scanline decoder, and that rows will be output in | |
334 * the logical order. | |
335 */ | |
336 kTopDown_SkScanlineOrder, | |
337 | |
338 /* | |
339 * This indicates that the scanline decoder reliably outputs rows, but | |
340 * they will be returned in reverse order. If the scanline format is | |
341 * kBottomUp, the getY() API can be used to determine the actual | |
342 * y-coordinate of the next output row, but the client is not forced | |
343 * to take advantage of this, given that it's not too tough to keep | |
344 * track independently. | |
345 * | |
346 * For full image decodes, it is safe to get all of the scanlines at | |
347 * once, since the decoder will handle inverting the rows as it | |
348 * decodes. | |
349 * | |
350 * For subset decodes and sampling, it is simplest to get and skip | |
351 * scanlines one at a time, using the getY() API. It is possible to | |
352 * ask for larger chunks at a time, but this should be used with | |
353 * caution. As with full image decodes, the decoder will handle | |
354 * inverting the requested rows, but rows will still be delivered | |
355 * starting from the bottom of the image. | |
356 * | |
357 * Upside down bmps are an example. | |
358 */ | |
359 kBottomUp_SkScanlineOrder, | |
360 | |
361 /* | |
362 * This indicates that the scanline decoder reliably outputs rows, but | |
363 * they will not be in logical order. If the scanline format is | |
364 * kOutOfOrder, the getY() API should be used to determine the actual | |
365 * y-coordinate of the next output row. | |
366 * | |
367 * For this scanline ordering, it is advisable to get and skip | |
368 * scanlines one at a time. | |
369 * | |
370 * Interlaced gifs are an example. | |
371 */ | |
372 kOutOfOrder_SkScanlineOrder, | |
373 | |
374 /* | |
375 * Indicates that the entire image must be decoded in order to output | |
376 * any amount of scanlines. In this case, it is a REALLY BAD IDEA to | |
377 * request scanlines 1-by-1 or in small chunks. The client should | |
378 * determine which scanlines are needed and ask for all of them in | |
379 * a single call to getScanlines(). | |
380 * | |
381 * Interlaced pngs are an example. | |
382 */ | |
383 kNone_SkScanlineOrder, | |
384 }; | |
385 | |
386 /** | |
387 * An enum representing the order in which scanlines will be returned by | |
388 * the scanline decoder. | |
389 */ | |
390 SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder() ; } | |
391 | |
392 /** | |
393 * Returns the y-coordinate of the next row to be returned by the scanline | |
394 * decoder. This will be overridden in the case of | |
395 * kOutOfOrder_SkScanlineOrder and should be unnecessary in the case of | |
396 * kNone_SkScanlineOrder. | |
397 * | |
398 * Results are undefined when not in scanline decoding mode. | |
399 * | |
400 * FIXME: Rename to nextScanline()? | |
djsollen
2015/09/29 20:22:17
I agree that this should be renamed
scroggo
2015/09/30 13:32:20
Renamed to nextScanline().
I also renamed updateY
| |
401 */ | |
402 int getY() const { | |
403 return this->onGetY(); | |
404 } | |
405 | |
228 protected: | 406 protected: |
229 SkCodec(const SkImageInfo&, SkStream*); | 407 SkCodec(const SkImageInfo&, SkStream*); |
230 | 408 |
231 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { | 409 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { |
232 // By default, scaling is not supported. | 410 // By default, scaling is not supported. |
233 return this->getInfo().dimensions(); | 411 return this->getInfo().dimensions(); |
234 } | 412 } |
235 | 413 |
236 virtual SkEncodedFormat onGetEncodedFormat() const = 0; | 414 virtual SkEncodedFormat onGetEncodedFormat() const = 0; |
237 | 415 |
(...skipping 30 matching lines...) Expand all Loading... | |
268 return true; | 446 return true; |
269 } | 447 } |
270 | 448 |
271 /** | 449 /** |
272 * Get method for the input stream | 450 * Get method for the input stream |
273 */ | 451 */ |
274 SkStream* stream() { | 452 SkStream* stream() { |
275 return fStream.get(); | 453 return fStream.get(); |
276 } | 454 } |
277 | 455 |
456 /** | |
457 * The remaining functions revolve around decoding scanlines. | |
458 */ | |
459 | |
460 /** | |
461 * Most images types will be kTopDown and will not need to override this fu nction. | |
462 */ | |
463 virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanl ineOrder; } | |
464 | |
465 /** | |
466 * Most images will be kTopDown and will not need to override this function . | |
467 */ | |
468 virtual int onGetY() const { return fCurrScanline; } | |
469 | |
470 /** | |
471 * Update the next scanline. Used by interlaced png. | |
472 */ | |
473 void updateY(int newY) { fCurrScanline = newY; } | |
474 | |
475 const SkImageInfo& dstInfo() const { return fDstInfo; } | |
476 | |
477 const SkCodec::Options& options() const { return fOptions; } | |
478 | |
278 private: | 479 private: |
279 const SkImageInfo fInfo; | 480 const SkImageInfo fSrcInfo; |
280 SkAutoTDelete<SkStream> fStream; | 481 SkAutoTDelete<SkStream> fStream; |
281 bool fNeedsRewind; | 482 bool fNeedsRewind; |
483 // These fields are only meaningful during scanline decodes. | |
484 SkImageInfo fDstInfo; | |
485 SkCodec::Options fOptions; | |
486 int fCurrScanline; | |
487 | |
488 // Methods for scanline decoding. | |
489 virtual SkCodec::Result onStart(const SkImageInfo& dstInfo, | |
490 const SkCodec::Options& options, | |
491 SkPMColor ctable[], int* ctableCount) { | |
492 return kUnimplemented; | |
493 } | |
494 | |
495 // Naive default version just calls onGetScanlines on temp memory. | |
496 virtual SkCodec::Result onSkipScanlines(int countLines) { | |
497 SkAutoMalloc storage(fDstInfo.minRowBytes()); | |
498 // Note that we pass 0 to rowBytes so we continue to use the same memory . | |
499 // Also note that while getScanlines checks that rowBytes is big enough, | |
500 // onGetScanlines bypasses that check. | |
501 // Calling the virtual method also means we do not double count | |
502 // countLines. | |
503 return this->onGetScanlines(storage.get(), countLines, 0); | |
504 } | |
505 | |
506 virtual SkCodec::Result onGetScanlines(void* dst, int countLines, | |
507 size_t rowBytes) { | |
508 return kUnimplemented; | |
509 } | |
510 | |
282 }; | 511 }; |
283 #endif // SkCodec_DEFINED | 512 #endif // SkCodec_DEFINED |
OLD | NEW |