Chromium Code Reviews| 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 |