| 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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 /** | 125 /** |
| 126 * The input did not contain a valid image. | 126 * The input did not contain a valid image. |
| 127 */ | 127 */ |
| 128 kInvalidInput, | 128 kInvalidInput, |
| 129 /** | 129 /** |
| 130 * Fulfilling this request requires rewinding the input, which is not | 130 * Fulfilling this request requires rewinding the input, which is not |
| 131 * supported for this input. | 131 * supported for this input. |
| 132 */ | 132 */ |
| 133 kCouldNotRewind, | 133 kCouldNotRewind, |
| 134 /** | 134 /** |
| 135 * startScanlineDecode() was not called before calling getScanlines. | |
| 136 */ | |
| 137 kScanlineDecodingNotStarted, | |
| 138 /** | |
| 139 * This method is not implemented by this codec. | 135 * This method is not implemented by this codec. |
| 140 * FIXME: Perhaps this should be kUnsupported? | 136 * FIXME: Perhaps this should be kUnsupported? |
| 141 */ | 137 */ |
| 142 kUnimplemented, | 138 kUnimplemented, |
| 143 }; | 139 }; |
| 144 | 140 |
| 145 /** | 141 /** |
| 146 * Whether or not the memory passed to getPixels is zero initialized. | 142 * Whether or not the memory passed to getPixels is zero initialized. |
| 147 */ | 143 */ |
| 148 enum ZeroInitialized { | 144 enum ZeroInitialized { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 /** | 270 /** |
| 275 * Write the next countLines scanlines into dst. | 271 * Write the next countLines scanlines into dst. |
| 276 * | 272 * |
| 277 * Not valid to call before calling startScanlineDecode(). | 273 * Not valid to call before calling startScanlineDecode(). |
| 278 * | 274 * |
| 279 * @param dst Must be non-null, and large enough to hold countLines | 275 * @param dst Must be non-null, and large enough to hold countLines |
| 280 * scanlines of size rowBytes. | 276 * scanlines of size rowBytes. |
| 281 * @param countLines Number of lines to write. | 277 * @param countLines Number of lines to write. |
| 282 * @param rowBytes Number of bytes per row. Must be large enough to hold | 278 * @param rowBytes Number of bytes per row. Must be large enough to hold |
| 283 * a scanline based on the SkImageInfo used to create this object. | 279 * a scanline based on the SkImageInfo used to create this object. |
| 280 * @return the number of lines successfully decoded. If this value is |
| 281 * less than countLines, this will fill the remaining lines with a |
| 282 * default value. |
| 284 */ | 283 */ |
| 285 Result getScanlines(void* dst, int countLines, size_t rowBytes); | 284 int getScanlines(void* dst, int countLines, size_t rowBytes); |
| 286 | 285 |
| 287 /** | 286 /** |
| 288 * Skip count scanlines. | 287 * Skip count scanlines. |
| 289 * | 288 * |
| 290 * Not valid to call before calling startScanlineDecode(). | 289 * Not valid to call before calling startScanlineDecode(). |
| 291 * | 290 * |
| 292 * The default version just calls onGetScanlines and discards the dst. | 291 * The default version just calls onGetScanlines and discards the dst. |
| 293 * NOTE: If skipped lines are the only lines with alpha, this default | 292 * NOTE: If skipped lines are the only lines with alpha, this default |
| 294 * will make reallyHasAlpha return true, when it could have returned | 293 * will make reallyHasAlpha return true, when it could have returned |
| 295 * false. | 294 * false. |
| 295 * |
| 296 * @return true if the scanlines were successfully skipped |
| 297 * false on failure, possible reasons for failure include: |
| 298 * An incomplete input image stream. |
| 299 * Calling this function before calling startScanlineDecode(). |
| 300 * If countLines is less than zero or so large that it moves |
| 301 * the current scanline past the end of the image. |
| 296 */ | 302 */ |
| 297 Result skipScanlines(int countLines); | 303 bool skipScanlines(int countLines); |
| 298 | 304 |
| 299 /** | 305 /** |
| 300 * The order in which rows are output from the scanline decoder is not the | 306 * The order in which rows are output from the scanline decoder is not the |
| 301 * same for all variations of all image types. This explains the possible | 307 * same for all variations of all image types. This explains the possible |
| 302 * output row orderings. | 308 * output row orderings. |
| 303 */ | 309 */ |
| 304 enum SkScanlineOrder { | 310 enum SkScanlineOrder { |
| 305 /* | 311 /* |
| 306 * By far the most common, this indicates that the image can be decoded | 312 * By far the most common, this indicates that the image can be decoded |
| 307 * reliably using the scanline decoder, and that rows will be output in | 313 * reliably using the scanline decoder, and that rows will be output in |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 }; | 364 }; |
| 359 | 365 |
| 360 /** | 366 /** |
| 361 * An enum representing the order in which scanlines will be returned by | 367 * An enum representing the order in which scanlines will be returned by |
| 362 * the scanline decoder. | 368 * the scanline decoder. |
| 363 */ | 369 */ |
| 364 SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder()
; } | 370 SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder()
; } |
| 365 | 371 |
| 366 /** | 372 /** |
| 367 * Returns the y-coordinate of the next row to be returned by the scanline | 373 * Returns the y-coordinate of the next row to be returned by the scanline |
| 368 * decoder. This will be overridden in the case of | 374 * decoder. |
| 369 * kOutOfOrder_SkScanlineOrder and should be unnecessary in the case of | 375 * |
| 370 * kNone_SkScanlineOrder. | 376 * This will equal fCurrScanline, except in the case of strangely |
| 377 * encoded image types (bottom-up bmps, interlaced gifs). |
| 371 * | 378 * |
| 372 * Results are undefined when not in scanline decoding mode. | 379 * Results are undefined when not in scanline decoding mode. |
| 373 */ | 380 */ |
| 374 int nextScanline() const { | 381 int nextScanline() const { return this->outputScanline(fCurrScanline); } |
| 375 return this->onNextScanline(); | 382 |
| 376 } | 383 /** |
| 384 * Returns the output y-coordinate of the row that corresponds to an input |
| 385 * y-coordinate. The input y-coordinate represents where the scanline |
| 386 * is located in the encoded data. |
| 387 * |
| 388 * This will equal inputScanline, except in the case of strangely |
| 389 * encoded image types (bottom-up bmps, interlaced gifs). |
| 390 */ |
| 391 int outputScanline(int inputScanline) const; |
| 377 | 392 |
| 378 protected: | 393 protected: |
| 379 SkCodec(const SkImageInfo&, SkStream*); | 394 SkCodec(const SkImageInfo&, SkStream*); |
| 380 | 395 |
| 381 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { | 396 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { |
| 382 // By default, scaling is not supported. | 397 // By default, scaling is not supported. |
| 383 return this->getInfo().dimensions(); | 398 return this->getInfo().dimensions(); |
| 384 } | 399 } |
| 385 | 400 |
| 386 // FIXME: What to do about subsets?? | 401 // FIXME: What to do about subsets?? |
| 387 /** | 402 /** |
| 388 * Subclasses should override if they support dimensions other than the | 403 * Subclasses should override if they support dimensions other than the |
| 389 * srcInfo's. | 404 * srcInfo's. |
| 390 */ | 405 */ |
| 391 virtual bool onDimensionsSupported(const SkISize&) { | 406 virtual bool onDimensionsSupported(const SkISize&) { |
| 392 return false; | 407 return false; |
| 393 } | 408 } |
| 394 | 409 |
| 395 virtual SkEncodedFormat onGetEncodedFormat() const = 0; | 410 virtual SkEncodedFormat onGetEncodedFormat() const = 0; |
| 396 | 411 |
| 412 /** |
| 413 * @param rowsDecoded When the encoded image stream is incomplete, this func
tion |
| 414 * will return kIncompleteInput and rowsDecoded will be s
et to |
| 415 * the number of scanlines that were successfully decoded
. |
| 416 * This will allow getPixels() to fill the uninitialized
memory. |
| 417 */ |
| 397 virtual Result onGetPixels(const SkImageInfo& info, | 418 virtual Result onGetPixels(const SkImageInfo& info, |
| 398 void* pixels, size_t rowBytes, const Options&, | 419 void* pixels, size_t rowBytes, const Options&, |
| 399 SkPMColor ctable[], int* ctableCount) = 0; | 420 SkPMColor ctable[], int* ctableCount, |
| 421 int* rowsDecoded) = 0; |
| 400 | 422 |
| 401 virtual bool onGetValidSubset(SkIRect* /* desiredSubset */) const { | 423 virtual bool onGetValidSubset(SkIRect* /* desiredSubset */) const { |
| 402 // By default, subsets are not supported. | 424 // By default, subsets are not supported. |
| 403 return false; | 425 return false; |
| 404 } | 426 } |
| 405 | 427 |
| 406 virtual bool onReallyHasAlpha() const { return false; } | 428 virtual bool onReallyHasAlpha() const { return false; } |
| 407 | 429 |
| 408 /** | 430 /** |
| 409 * If the stream was previously read, attempt to rewind. | 431 * If the stream was previously read, attempt to rewind. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 420 /** | 442 /** |
| 421 * Called by rewindIfNeeded, if the stream needed to be rewound. | 443 * Called by rewindIfNeeded, if the stream needed to be rewound. |
| 422 * | 444 * |
| 423 * Subclasses should do any set up needed after a rewind. | 445 * Subclasses should do any set up needed after a rewind. |
| 424 */ | 446 */ |
| 425 virtual bool onRewind() { | 447 virtual bool onRewind() { |
| 426 return true; | 448 return true; |
| 427 } | 449 } |
| 428 | 450 |
| 429 /** | 451 /** |
| 452 * On an incomplete input, getPixels() and getScanlines() will fill any unin
itialized |
| 453 * scanlines. This allows the subclass to indicate what value to fill with. |
| 454 * |
| 455 * @param colorType Destination color type. |
| 456 * @param alphaType Destination alpha type. |
| 457 * @return The value with which to fill uninitialized pixels. |
| 458 * |
| 459 * Note that we can interpret the return value as an SkPMColor, a 16-bit 565
color, |
| 460 * an 8-bit gray color, or an 8-bit index into a color table, depending on t
he color |
| 461 * type. |
| 462 */ |
| 463 uint32_t getFillValue(SkColorType colorType, SkAlphaType alphaType) const { |
| 464 return this->onGetFillValue(colorType, alphaType); |
| 465 } |
| 466 |
| 467 /** |
| 468 * Some subclasses will override this function, but this is a useful default
for the color |
| 469 * types that we support. Note that for color types that do not use the ful
l 32-bits, |
| 470 * we will simply take the low bits of the fill value. |
| 471 * |
| 472 * kN32_SkColorType: Transparent or Black |
| 473 * kRGB_565_SkColorType: Black |
| 474 * kGray_8_SkColorType: Black |
| 475 * kIndex_8_SkColorType: First color in color table |
| 476 */ |
| 477 virtual uint32_t onGetFillValue(SkColorType colorType, SkAlphaType alphaType
) const { |
| 478 return kOpaque_SkAlphaType == alphaType ? SK_ColorBLACK : SK_ColorTRANSP
ARENT; |
| 479 } |
| 480 |
| 481 /** |
| 430 * Get method for the input stream | 482 * Get method for the input stream |
| 431 */ | 483 */ |
| 432 SkStream* stream() { | 484 SkStream* stream() { |
| 433 return fStream.get(); | 485 return fStream.get(); |
| 434 } | 486 } |
| 435 | 487 |
| 436 /** | 488 /** |
| 437 * The remaining functions revolve around decoding scanlines. | 489 * The remaining functions revolve around decoding scanlines. |
| 438 */ | 490 */ |
| 439 | 491 |
| 440 /** | 492 /** |
| 441 * Most images types will be kTopDown and will not need to override this fu
nction. | 493 * Most images types will be kTopDown and will not need to override this fu
nction. |
| 442 */ | 494 */ |
| 443 virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanl
ineOrder; } | 495 virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanl
ineOrder; } |
| 444 | 496 |
| 445 /** | 497 /** |
| 446 * Most images will be kTopDown and will not need to override this function
. | |
| 447 */ | |
| 448 virtual int onNextScanline() const { return fCurrScanline; } | |
| 449 | |
| 450 /** | |
| 451 * Update the next scanline. Used by interlaced png. | 498 * Update the next scanline. Used by interlaced png. |
| 452 */ | 499 */ |
| 453 void updateNextScanline(int newY) { fCurrScanline = newY; } | 500 void updateNextScanline(int newY) { fCurrScanline = newY; } |
| 454 | 501 |
| 455 const SkImageInfo& dstInfo() const { return fDstInfo; } | 502 const SkImageInfo& dstInfo() const { return fDstInfo; } |
| 456 | 503 |
| 457 const SkCodec::Options& options() const { return fOptions; } | 504 const SkCodec::Options& options() const { return fOptions; } |
| 458 | 505 |
| 506 virtual int onOutputScanline(int inputScanline) const; |
| 507 |
| 459 private: | 508 private: |
| 460 const SkImageInfo fSrcInfo; | 509 const SkImageInfo fSrcInfo; |
| 461 SkAutoTDelete<SkStream> fStream; | 510 SkAutoTDelete<SkStream> fStream; |
| 462 bool fNeedsRewind; | 511 bool fNeedsRewind; |
| 463 // These fields are only meaningful during scanline decodes. | 512 // These fields are only meaningful during scanline decodes. |
| 464 SkImageInfo fDstInfo; | 513 SkImageInfo fDstInfo; |
| 465 SkCodec::Options fOptions; | 514 SkCodec::Options fOptions; |
| 466 int fCurrScanline; | 515 int fCurrScanline; |
| 467 | 516 |
| 468 /** | 517 /** |
| 469 * Return whether these dimensions are supported as a scale. | 518 * Return whether these dimensions are supported as a scale. |
| 470 * | 519 * |
| 471 * The codec may choose to cache the information about scale and subset. | 520 * The codec may choose to cache the information about scale and subset. |
| 472 * Either way, the same information will be passed to onGetPixels/onStart | 521 * Either way, the same information will be passed to onGetPixels/onStart |
| 473 * on success. | 522 * on success. |
| 474 * | 523 * |
| 475 * This must return true for a size returned from getScaledDimensions. | 524 * This must return true for a size returned from getScaledDimensions. |
| 476 */ | 525 */ |
| 477 bool dimensionsSupported(const SkISize& dim) { | 526 bool dimensionsSupported(const SkISize& dim) { |
| 478 return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim); | 527 return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim); |
| 479 } | 528 } |
| 480 | 529 |
| 481 // Methods for scanline decoding. | 530 // Methods for scanline decoding. |
| 482 virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& dstInfo, | 531 virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& dstInfo, |
| 483 const SkCodec::Options& options, SkPMColor ctable[], int* ctableCoun
t) { | 532 const SkCodec::Options& options, SkPMColor ctable[], int* ctableCoun
t) { |
| 484 return kUnimplemented; | 533 return kUnimplemented; |
| 485 } | 534 } |
| 486 | 535 |
| 487 // Naive default version just calls onGetScanlines on temp memory. | 536 // Naive default version just calls onGetScanlines on temp memory. |
| 488 virtual SkCodec::Result onSkipScanlines(int countLines) { | 537 virtual bool onSkipScanlines(int countLines) { |
| 538 // FIXME (msarett): Make this a pure virtual and always override this. |
| 489 SkAutoMalloc storage(fDstInfo.minRowBytes()); | 539 SkAutoMalloc storage(fDstInfo.minRowBytes()); |
| 540 |
| 490 // Note that we pass 0 to rowBytes so we continue to use the same memory
. | 541 // Note that we pass 0 to rowBytes so we continue to use the same memory
. |
| 491 // Also note that while getScanlines checks that rowBytes is big enough, | 542 // Also note that while getScanlines checks that rowBytes is big enough, |
| 492 // onGetScanlines bypasses that check. | 543 // onGetScanlines bypasses that check. |
| 493 // Calling the virtual method also means we do not double count | 544 // Calling the virtual method also means we do not double count |
| 494 // countLines. | 545 // countLines. |
| 495 return this->onGetScanlines(storage.get(), countLines, 0); | 546 return countLines == this->onGetScanlines(storage.get(), countLines, 0); |
| 496 } | 547 } |
| 497 | 548 |
| 498 virtual SkCodec::Result onGetScanlines(void* dst, int countLines, | 549 virtual int onGetScanlines(void* dst, int countLines, size_t rowBytes) { ret
urn 0; } |
| 499 size_t rowBytes) { | 550 |
| 500 return kUnimplemented; | 551 /** |
| 501 } | 552 * On an incomplete decode, getPixels() and getScanlines() will call this fu
nction |
| 553 * to fill any uinitialized memory. |
| 554 * |
| 555 * @param dstInfo Contains the destination color type |
| 556 * Contains the destination alpha type |
| 557 * Contains the destination width |
| 558 * The height stored in this info is unused |
| 559 * @param dst Pointer to the start of destination pixel memory |
| 560 * @param rowBytes Stride length in destination pixel memory |
| 561 * @param zeroInit Indicates if memory is zero initialized |
| 562 * @param linesRequested Number of lines that the client requested |
| 563 * @param linesDecoded Number of lines that were successfully decoded |
| 564 */ |
| 565 void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBy
tes, |
| 566 ZeroInitialized zeroInit, int linesRequested, int linesDecoded); |
| 502 | 567 |
| 503 /** | 568 /** |
| 504 * Return an object which will allow forcing scanline decodes to sample in
X. | 569 * Return an object which will allow forcing scanline decodes to sample in
X. |
| 505 * | 570 * |
| 506 * May create a sampler, if one is not currently being used. Otherwise, doe
s | 571 * May create a sampler, if one is not currently being used. Otherwise, doe
s |
| 507 * not affect ownership. | 572 * not affect ownership. |
| 508 * | 573 * |
| 509 * Only valid during scanline decoding. | 574 * Only valid during scanline decoding. |
| 510 */ | 575 */ |
| 511 virtual SkSampler* getSampler() { return nullptr; } | 576 virtual SkSampler* getSampler(bool createIfNecessary) { return nullptr; } |
| 512 | 577 |
| 513 // Needed to call getSampler and dimensionsSupported. | |
| 514 friend class SkScaledCodec; | 578 friend class SkScaledCodec; |
| 515 }; | 579 }; |
| 516 #endif // SkCodec_DEFINED | 580 #endif // SkCodec_DEFINED |
| OLD | NEW |