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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 */ | 47 */ |
48 const SkImageInfo& getInfo() const { return fSrcInfo; } | 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. | |
59 SkASSERT(desiredScale > 0.0f); | |
60 if (desiredScale <= 0.0f) { | |
61 return SkISize::Make(0, 0); | |
62 } | |
63 | |
64 // Upscaling is not supported. Return the original size if the client | |
65 // requests an upscale. | |
66 if (desiredScale >= 1.0f) { | |
67 return this->getInfo().dimensions(); | |
68 } | |
69 return this->onGetScaledDimensions(desiredScale); | |
70 } | |
71 | 58 |
72 /** | 59 /** |
73 * Return (via desiredSubset) a subset which can decoded from this codec, | 60 * Return (via desiredSubset) a subset which can decoded from this codec, |
74 * or false if this codec cannot decode subsets or anything similar to | 61 * or false if this codec cannot decode subsets or anything similar to |
75 * desiredSubset. | 62 * desiredSubset. |
76 * | 63 * |
77 * @param desiredSubset In/out parameter. As input, a desired subset of | 64 * @param desiredSubset In/out parameter. As input, a desired subset of |
78 * the original bounds (as specified by getInfo). If true is returned, | 65 * the original bounds (as specified by getInfo). If true is returned, |
79 * desiredSubset may have been modified to a subset which is | 66 * desiredSubset may have been modified to a subset which is |
80 * supported. Although a particular change may have been made to | 67 * supported. Although a particular change may have been made to |
81 * desiredSubset to create something supported, it is possible other | 68 * desiredSubset to create something supported, it is possible other |
82 * changes could result in a valid subset. | 69 * changes could result in a valid subset. |
83 * If false is returned, desiredSubset's value is undefined. | 70 * If false is returned, desiredSubset's value is undefined. |
84 * @return true if this codec supports decoding desiredSubset (as | 71 * @return true if this codec supports decoding desiredSubset (as |
85 * returned, potentially modified) | 72 * returned, potentially modified) |
86 */ | 73 */ |
87 bool getValidSubset(SkIRect* desiredSubset) const { | 74 bool getValidSubset(SkIRect* desiredSubset) const; |
88 return this->onGetValidSubset(desiredSubset); | |
89 } | |
90 | 75 |
91 /** | 76 /** |
92 * Format of the encoded data. | 77 * Format of the encoded data. |
93 */ | 78 */ |
94 SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat() ; } | 79 SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat() ; } |
95 | 80 |
96 /** | 81 /** |
97 * Used to describe the result of a call to getPixels(). | 82 * Used to describe the result of a call to getPixels(). |
98 * | 83 * |
99 * Result is the union of possible results from subclasses. | 84 * Result is the union of possible results from subclasses. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
155 kNo_ZeroInitialized, | 140 kNo_ZeroInitialized, |
156 }; | 141 }; |
157 | 142 |
158 /** | 143 /** |
159 * Additional options to pass to getPixels. | 144 * Additional options to pass to getPixels. |
160 */ | 145 */ |
161 struct Options { | 146 struct Options { |
162 Options() | 147 Options() |
163 : fZeroInitialized(kNo_ZeroInitialized) | 148 : fZeroInitialized(kNo_ZeroInitialized) |
164 , fSubset(NULL) | 149 , fSubset(NULL) |
150 , fScaledDimensions(SkISize::Make(0, 0)) | |
151 , fScaledSubset(SkIRect::MakeEmpty()) | |
165 {} | 152 {} |
166 | 153 |
167 ZeroInitialized fZeroInitialized; | 154 ZeroInitialized fZeroInitialized; |
155 | |
168 /** | 156 /** |
169 * If not NULL, represents a subset of the original image to decode. | 157 * fSubset represents a subset of the original image to decode. |
158 * It must be within the bounds returned by getInfo(). | |
159 * If the EncodedFormat is kWEBP_SkEncodedFormat, the top and left | |
160 * values must be even. | |
161 * If fSubset is NULL, we are not performing a subset decode. | |
170 * | 162 * |
171 * Must be within the bounds returned by getInfo(). | 163 * fScaledDimensions and fScaledSubset are used together to help |
164 * specify a scaled subset decode. Both should be specified for a | |
165 * scaled subset decode, and both should be zeroed otherwise. | |
172 * | 166 * |
173 * If the EncodedFormat is kWEBP_SkEncodedFormat (the only one which | 167 * If fScaledDimensions and fScaledSubset are zeroed, we are not |
174 * currently supports subsets), the top and left values must be even. | 168 * performing a scaled subset decode: |
169 * (1) If fSubset is non-NULL, we are performing an unscaled | |
170 * subset decode, and the subset dimensions must match the | |
171 * dstInfo dimensions. | |
172 * (2) If fSubset is NULL and the dstInfo dimensions do not | |
173 * match the original dimensions, we are performing a | |
174 * scaled decode. | |
175 * (3) If fSubset is NULL and the dstInfo dimensions match the | |
176 * original dimensions, we are performing an unscaled, full | |
177 * image decode. | |
178 * | |
179 * If both are non-NULL we are performing a scaled subset decode: | |
180 * fSubset must be non-NULL. | |
181 * fScaledSubset must be within the bounds of fScaledDimensions. | |
182 * The dimensions of fScaledSubset must match the dimensions | |
183 * specified by dstInfo. | |
184 * | |
185 * Usage: | |
186 * Call getScaledSubsetDimensions() with the desired fSubset of | |
187 * the original image and the desired scale. The function will | |
188 * populate the options object with valid values of | |
189 * fScaledDimensions and fScaledSubset that can be decoded | |
190 * efficiently. | |
175 */ | 191 */ |
176 SkIRect* fSubset; | 192 SkIRect* fSubset; |
193 SkISize fScaledDimensions; | |
scroggo
2015/10/02 18:27:03
For fSubset, we decided to make it an unowned poin
msarett
2015/10/06 23:01:27
I'll change to be consistent.
My concern is that
scroggo
2015/10/07 17:49:39
I don't think it's so bad. In this case it will ju
| |
194 SkIRect fScaledSubset; | |
177 }; | 195 }; |
178 | 196 |
179 /** | 197 /** |
198 * @param desiredScale The requested scale factor. | |
199 * @param options In/out parameter. | |
200 * options->fSubset (in/out) specifies the | |
201 * requested subset in terms of the original image | |
202 * dimensions. This may be modified to a subset | |
scroggo
2015/10/02 18:27:03
So if I understand correctly, this is analogous to
msarett
2015/10/06 23:01:27
I'm in favor of combining. I had considered that
| |
203 * that can be decoded more efficiently. | |
204 * options->fScaledDimensions is an output and | |
205 * specifies the best scaled (full image) output | |
206 * dimensions that can be achieved for the | |
207 * desiredScale. | |
208 * options->fScaledSubset is an output and specifies | |
209 * the fSubset in terms of fScaledDimensions. | |
210 * | |
211 * The codec may not be able to scale and subset efficiently to the exact | |
212 * scale and subset requested, so fScaledDimensions and fScaledSubset may | |
213 * be approximate. These output values are the codec's suggestion for | |
214 * the closest valid scaled subset that it can support. | |
215 * | |
216 * @return true if fScaledDimensions and fScaledSubset have been | |
217 * successfully set to values that the codec supports. | |
218 * false otherwise. | |
219 */ | |
220 bool getScaledSubsetDimensions(float desiredScale, Options* options) const; | |
221 | |
222 /** | |
180 * Decode into the given pixels, a block of memory of size at | 223 * Decode into the given pixels, a block of memory of size at |
181 * least (info.fHeight - 1) * rowBytes + (info.fWidth * | 224 * least (info.fHeight - 1) * rowBytes + (info.fWidth * |
182 * bytesPerPixel) | 225 * bytesPerPixel) |
183 * | 226 * |
184 * Repeated calls to this function should give the same results, | 227 * Repeated calls to this function should give the same results, |
185 * allowing the PixelRef to be immutable. | 228 * allowing the PixelRef to be immutable. |
186 * | 229 * |
187 * @param info A description of the format (config, size) | 230 * @param info A description of the format (config, size) |
188 * expected by the caller. This can simply be identical | 231 * expected by the caller. This can simply be identical |
189 * to the info returned by getInfo(). | 232 * to the info returned by getInfo(). |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
248 * those of getInfo, this implies a scale. | 291 * those of getInfo, this implies a scale. |
249 * @param options Contains decoding options, including if memory is zero | 292 * @param options Contains decoding options, including if memory is zero |
250 * initialized. | 293 * initialized. |
251 * @param ctable A pointer to a color table. When dstInfo.colorType() is | 294 * @param ctable A pointer to a color table. When dstInfo.colorType() is |
252 * kIndex8, this should be non-NULL and have enough storage for 256 | 295 * kIndex8, this should be non-NULL and have enough storage for 256 |
253 * colors. The color table will be populated after decoding the palett e. | 296 * colors. The color table will be populated after decoding the palett e. |
254 * @param ctableCount A pointer to the size of the color table. When | 297 * @param ctableCount A pointer to the size of the color table. When |
255 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will | 298 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will |
256 * be modified to the true size of the color table (<= 256) after | 299 * be modified to the true size of the color table (<= 256) after |
257 * decoding the palette. | 300 * decoding the palette. |
301 * @param subsetLeft The left offset at which to begin decoding each | |
302 * scanline. This enables partial scanline decodes. | |
303 * @param subsetWidth The number of pixels to decode in each scanline row. | |
scroggo
2015/10/02 18:27:03
My first thought was that this could be represente
msarett
2015/10/06 23:01:27
I'm in favor of putting all of this on the Options
| |
258 * @return Enum representing success or reason for failure. | 304 * @return Enum representing success or reason for failure. |
259 */ | 305 */ |
260 Result startScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Option s* options, | 306 Result startScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Option s* options, |
261 SkPMColor ctable[], int* ctableCount); | 307 SkPMColor ctable[], int* ctableCount, int subsetLeft, int subse tWidth); |
308 | |
309 /** | |
310 * Simplified version of startScanlineDecode() that does not enable partial | |
311 * scanline decoding. | |
312 */ | |
313 Result startScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Option s* options, | |
314 SkPMColor ctable[], int* ctableCount); | |
262 | 315 |
263 /** | 316 /** |
264 * Simplified version of startScanlineDecode() that asserts that info is NO T | 317 * Simplified version of startScanlineDecode() that asserts that info is NO T |
265 * kIndex8_SkColorType and uses the default Options. | 318 * kIndex8_SkColorType, uses the default Options, and does not enable |
319 * partial scanline decoding. | |
266 */ | 320 */ |
267 Result startScanlineDecode(const SkImageInfo& dstInfo); | 321 Result startScanlineDecode(const SkImageInfo& dstInfo); |
268 | 322 |
269 /** | 323 /** |
270 * Write the next countLines scanlines into dst. | 324 * Write the next countLines scanlines into dst. |
271 * | 325 * |
272 * Not valid to call before calling startScanlineDecode(). | 326 * Not valid to call before calling startScanlineDecode(). |
273 * | 327 * |
274 * @param dst Must be non-null, and large enough to hold countLines | 328 * @param dst Must be non-null, and large enough to hold countLines |
275 * scanlines of size rowBytes. | 329 * scanlines of size rowBytes. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
390 int outputScanline(int inputScanline) const; | 444 int outputScanline(int inputScanline) const; |
391 | 445 |
392 protected: | 446 protected: |
393 SkCodec(const SkImageInfo&, SkStream*); | 447 SkCodec(const SkImageInfo&, SkStream*); |
394 | 448 |
395 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { | 449 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { |
396 // By default, scaling is not supported. | 450 // By default, scaling is not supported. |
397 return this->getInfo().dimensions(); | 451 return this->getInfo().dimensions(); |
398 } | 452 } |
399 | 453 |
454 virtual bool onGetValidSubset(SkIRect* /* desiredSubset */) const { | |
455 // By default, subsets are not supported. | |
456 return false; | |
457 } | |
458 | |
459 virtual bool onGetScaledSubsetDimensions(float desiredScale, Options* option s) const { | |
460 // By default, scaled subsetting is not supported. | |
461 return false; | |
462 } | |
463 | |
400 virtual SkEncodedFormat onGetEncodedFormat() const = 0; | 464 virtual SkEncodedFormat onGetEncodedFormat() const = 0; |
401 | 465 |
402 /** | 466 /** |
403 * @param rowsDecoded When the encoded image stream is incomplete, this func tion | 467 * @param rowsDecoded When the encoded image stream is incomplete, this func tion |
404 * will return kIncompleteInput and rowsDecoded will be s et to | 468 * will return kIncompleteInput and rowsDecoded will be s et to |
405 * the number of scanlines that were successfully decoded . | 469 * the number of scanlines that were successfully decoded . |
406 * This will allow getPixels() to fill the uninitialized memory. | 470 * This will allow getPixels() to fill the uninitialized memory. |
407 */ | 471 */ |
408 virtual Result onGetPixels(const SkImageInfo& info, | 472 virtual Result onGetPixels(const SkImageInfo& info, |
409 void* pixels, size_t rowBytes, const Options&, | 473 void* pixels, size_t rowBytes, const Options&, |
410 SkPMColor ctable[], int* ctableCount, | 474 SkPMColor ctable[], int* ctableCount, |
411 int* rowsDecoded) = 0; | 475 int* rowsDecoded) = 0; |
412 | 476 |
413 virtual bool onGetValidSubset(SkIRect* /* desiredSubset */) const { | |
414 // By default, subsets are not supported. | |
415 return false; | |
416 } | |
417 | |
418 virtual bool onReallyHasAlpha() const { return false; } | 477 virtual bool onReallyHasAlpha() const { return false; } |
419 | 478 |
420 /** | 479 /** |
421 * If the stream was previously read, attempt to rewind. | 480 * If the stream was previously read, attempt to rewind. |
422 * | 481 * |
423 * If the stream needed to be rewound, call onRewind. | 482 * If the stream needed to be rewound, call onRewind. |
424 * @returns true if the codec is at the right position and can be used. | 483 * @returns true if the codec is at the right position and can be used. |
425 * false if there was a failure to rewind. | 484 * false if there was a failure to rewind. |
426 * | 485 * |
427 * This is called by getPixels() and start(). Subclasses may call if they | 486 * This is called by getPixels() and start(). Subclasses may call if they |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 | 545 |
487 /** | 546 /** |
488 * Update the next scanline. Used by interlaced png. | 547 * Update the next scanline. Used by interlaced png. |
489 */ | 548 */ |
490 void updateNextScanline(int newY) { fCurrScanline = newY; } | 549 void updateNextScanline(int newY) { fCurrScanline = newY; } |
491 | 550 |
492 const SkImageInfo& dstInfo() const { return fDstInfo; } | 551 const SkImageInfo& dstInfo() const { return fDstInfo; } |
493 | 552 |
494 const SkCodec::Options& options() const { return fOptions; } | 553 const SkCodec::Options& options() const { return fOptions; } |
495 | 554 |
555 int subsetWidth() const { return fSubsetWidth; } | |
556 | |
496 private: | 557 private: |
497 const SkImageInfo fSrcInfo; | 558 const SkImageInfo fSrcInfo; |
498 SkAutoTDelete<SkStream> fStream; | 559 SkAutoTDelete<SkStream> fStream; |
499 bool fNeedsRewind; | 560 bool fNeedsRewind; |
500 // These fields are only meaningful during scanline decodes. | 561 // These fields are only meaningful during scanline decodes. |
501 SkImageInfo fDstInfo; | 562 SkImageInfo fDstInfo; |
502 SkCodec::Options fOptions; | 563 SkCodec::Options fOptions; |
503 int fCurrScanline; | 564 int fCurrScanline; |
565 int fSubsetWidth; | |
504 | 566 |
505 // Methods for scanline decoding. | 567 // Methods for scanline decoding. |
506 virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& dstInfo, | 568 virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& dstInfo, |
507 const SkCodec::Options& options, SkPMColor ctable[], int* ctableCoun t) { | 569 const SkCodec::Options& options, SkPMColor ctable[], int* ctableCoun t, int subsetLeft, |
570 int subsetWidth) { | |
508 return kUnimplemented; | 571 return kUnimplemented; |
509 } | 572 } |
510 | 573 |
511 // Naive default version just calls onGetScanlines on temp memory. | 574 // Naive default version just calls onGetScanlines on temp memory. |
512 virtual bool onSkipScanlines(int countLines) { | 575 virtual bool onSkipScanlines(int countLines) { |
513 // FIXME (msarett): Make this a pure virtual and always override this. | 576 // FIXME (msarett): Make this a pure virtual and always override this. |
514 SkAutoMalloc storage(fDstInfo.minRowBytes()); | 577 SkAutoMalloc storage(fDstInfo.minRowBytes()); |
515 | 578 |
516 // Note that we pass 0 to rowBytes so we continue to use the same memory . | 579 // Note that we pass 0 to rowBytes so we continue to use the same memory . |
517 // Also note that while getScanlines checks that rowBytes is big enough, | 580 // Also note that while getScanlines checks that rowBytes is big enough, |
(...skipping 16 matching lines...) Expand all Loading... | |
534 * @param linesRequested Number of lines that the client requested | 597 * @param linesRequested Number of lines that the client requested |
535 * @param linesDecoded Number of lines that were successfully decoded | 598 * @param linesDecoded Number of lines that were successfully decoded |
536 */ | 599 */ |
537 void fillIncompleteImage(const SkImageInfo& info, void* dst, size_t rowBytes , | 600 void fillIncompleteImage(const SkImageInfo& info, void* dst, size_t rowBytes , |
538 ZeroInitialized zeroInit, int linesRequested, int linesDecoded); | 601 ZeroInitialized zeroInit, int linesRequested, int linesDecoded); |
539 | 602 |
540 // Needed to call getFillColor() | 603 // Needed to call getFillColor() |
541 friend class SkScaledCodec; | 604 friend class SkScaledCodec; |
542 }; | 605 }; |
543 #endif // SkCodec_DEFINED | 606 #endif // SkCodec_DEFINED |
OLD | NEW |