SkCodec.h revision 7f97f49a840c92e26058034c631e8d76a54897bd
1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#ifndef SkCodec_DEFINED 9#define SkCodec_DEFINED 10 11#include "../private/SkTemplates.h" 12#include "SkCodecAnimation.h" 13#include "SkColor.h" 14#include "SkColorSpaceXform.h" 15#include "SkEncodedImageFormat.h" 16#include "SkEncodedInfo.h" 17#include "SkImageInfo.h" 18#include "SkSize.h" 19#include "SkStream.h" 20#include "SkTypes.h" 21#include "SkYUVSizeInfo.h" 22 23#include <vector> 24 25class SkColorSpace; 26class SkData; 27class SkFrameHolder; 28class SkPngChunkReader; 29class SkSampler; 30 31namespace DM { 32class CodecSrc; 33class ColorCodecSrc; 34} 35class ColorCodecBench; 36 37/** 38 * Abstraction layer directly on top of an image codec. 39 */ 40class SK_API SkCodec : SkNoncopyable { 41public: 42 /** 43 * Minimum number of bytes that must be buffered in SkStream input. 44 * 45 * An SkStream passed to NewFromStream must be able to use this many 46 * bytes to determine the image type. Then the same SkStream must be 47 * passed to the correct decoder to read from the beginning. 48 * 49 * This can be accomplished by implementing peek() to support peeking 50 * this many bytes, or by implementing rewind() to be able to rewind() 51 * after reading this many bytes. 52 */ 53 static size_t MinBufferedBytesNeeded(); 54 55 /** 56 * Error codes for various SkCodec methods. 57 */ 58 enum Result { 59 /** 60 * General return value for success. 61 */ 62 kSuccess, 63 /** 64 * The input is incomplete. A partial image was generated. 65 */ 66 kIncompleteInput, 67 /** 68 * Like kIncompleteInput, except the input had an error. 69 * 70 * If returned from an incremental decode, decoding cannot continue, 71 * even with more data. 72 */ 73 kErrorInInput, 74 /** 75 * The generator cannot convert to match the request, ignoring 76 * dimensions. 77 */ 78 kInvalidConversion, 79 /** 80 * The generator cannot scale to requested size. 81 */ 82 kInvalidScale, 83 /** 84 * Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes 85 * too small, etc. 86 */ 87 kInvalidParameters, 88 /** 89 * The input did not contain a valid image. 90 */ 91 kInvalidInput, 92 /** 93 * Fulfilling this request requires rewinding the input, which is not 94 * supported for this input. 95 */ 96 kCouldNotRewind, 97 /** 98 * An internal error, such as OOM. 99 */ 100 kInternalError, 101 /** 102 * This method is not implemented by this codec. 103 * FIXME: Perhaps this should be kUnsupported? 104 */ 105 kUnimplemented, 106 }; 107 108 /** 109 * If this stream represents an encoded image that we know how to decode, 110 * return an SkCodec that can decode it. Otherwise return NULL. 111 * 112 * As stated above, this call must be able to peek or read 113 * MinBufferedBytesNeeded to determine the correct format, and then start 114 * reading from the beginning. First it will attempt to peek, and it 115 * assumes that if less than MinBufferedBytesNeeded bytes (but more than 116 * zero) are returned, this is because the stream is shorter than this, 117 * so falling back to reading would not provide more data. If peek() 118 * returns zero bytes, this call will instead attempt to read(). This 119 * will require that the stream can be rewind()ed. 120 * 121 * If Result is not NULL, it will be set to either kSuccess if an SkCodec 122 * is returned or a reason for the failure if NULL is returned. 123 * 124 * If SkPngChunkReader is not NULL, take a ref and pass it to libpng if 125 * the image is a png. 126 * 127 * If the SkPngChunkReader is not NULL then: 128 * If the image is not a PNG, the SkPngChunkReader will be ignored. 129 * If the image is a PNG, the SkPngChunkReader will be reffed. 130 * If the PNG has unknown chunks, the SkPngChunkReader will be used 131 * to handle these chunks. SkPngChunkReader will be called to read 132 * any unknown chunk at any point during the creation of the codec 133 * or the decode. Note that if SkPngChunkReader fails to read a 134 * chunk, this could result in a failure to create the codec or a 135 * failure to decode the image. 136 * If the PNG does not contain unknown chunks, the SkPngChunkReader 137 * will not be used or modified. 138 * 139 * If NULL is returned, the stream is deleted immediately. Otherwise, the 140 * SkCodec takes ownership of it, and will delete it when done with it. 141 */ 142 static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result* = nullptr, 143 SkPngChunkReader* = nullptr); 144 145 /** 146 * If this data represents an encoded image that we know how to decode, 147 * return an SkCodec that can decode it. Otherwise return NULL. 148 * 149 * If the SkPngChunkReader is not NULL then: 150 * If the image is not a PNG, the SkPngChunkReader will be ignored. 151 * If the image is a PNG, the SkPngChunkReader will be reffed. 152 * If the PNG has unknown chunks, the SkPngChunkReader will be used 153 * to handle these chunks. SkPngChunkReader will be called to read 154 * any unknown chunk at any point during the creation of the codec 155 * or the decode. Note that if SkPngChunkReader fails to read a 156 * chunk, this could result in a failure to create the codec or a 157 * failure to decode the image. 158 * If the PNG does not contain unknown chunks, the SkPngChunkReader 159 * will not be used or modified. 160 */ 161 static std::unique_ptr<SkCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr); 162 163 virtual ~SkCodec(); 164 165 /** 166 * Return the ImageInfo associated with this codec. 167 */ 168 const SkImageInfo& getInfo() const { return fSrcInfo; } 169 170 const SkEncodedInfo& getEncodedInfo() const { return fEncodedInfo; } 171 172 enum Origin { 173 kTopLeft_Origin = 1, // Default 174 kTopRight_Origin = 2, // Reflected across y-axis 175 kBottomRight_Origin = 3, // Rotated 180 176 kBottomLeft_Origin = 4, // Reflected across x-axis 177 kLeftTop_Origin = 5, // Reflected across x-axis, Rotated 90 CCW 178 kRightTop_Origin = 6, // Rotated 90 CW 179 kRightBottom_Origin = 7, // Reflected across x-axis, Rotated 90 CW 180 kLeftBottom_Origin = 8, // Rotated 90 CCW 181 kDefault_Origin = kTopLeft_Origin, 182 kLast_Origin = kLeftBottom_Origin, 183 }; 184 185 /** 186 * Returns the image orientation stored in the EXIF data. 187 * If there is no EXIF data, or if we cannot read the EXIF data, returns kTopLeft. 188 */ 189 Origin getOrigin() const { return fOrigin; } 190 191 /** 192 * Return a size that approximately supports the desired scale factor. 193 * The codec may not be able to scale efficiently to the exact scale 194 * factor requested, so return a size that approximates that scale. 195 * The returned value is the codec's suggestion for the closest valid 196 * scale that it can natively support 197 */ 198 SkISize getScaledDimensions(float desiredScale) const { 199 // Negative and zero scales are errors. 200 SkASSERT(desiredScale > 0.0f); 201 if (desiredScale <= 0.0f) { 202 return SkISize::Make(0, 0); 203 } 204 205 // Upscaling is not supported. Return the original size if the client 206 // requests an upscale. 207 if (desiredScale >= 1.0f) { 208 return this->getInfo().dimensions(); 209 } 210 return this->onGetScaledDimensions(desiredScale); 211 } 212 213 /** 214 * Return (via desiredSubset) a subset which can decoded from this codec, 215 * or false if this codec cannot decode subsets or anything similar to 216 * desiredSubset. 217 * 218 * @param desiredSubset In/out parameter. As input, a desired subset of 219 * the original bounds (as specified by getInfo). If true is returned, 220 * desiredSubset may have been modified to a subset which is 221 * supported. Although a particular change may have been made to 222 * desiredSubset to create something supported, it is possible other 223 * changes could result in a valid subset. 224 * If false is returned, desiredSubset's value is undefined. 225 * @return true if this codec supports decoding desiredSubset (as 226 * returned, potentially modified) 227 */ 228 bool getValidSubset(SkIRect* desiredSubset) const { 229 return this->onGetValidSubset(desiredSubset); 230 } 231 232 /** 233 * Format of the encoded data. 234 */ 235 SkEncodedImageFormat getEncodedFormat() const { return this->onGetEncodedFormat(); } 236 237 /** 238 * Whether or not the memory passed to getPixels is zero initialized. 239 */ 240 enum ZeroInitialized { 241 /** 242 * The memory passed to getPixels is zero initialized. The SkCodec 243 * may take advantage of this by skipping writing zeroes. 244 */ 245 kYes_ZeroInitialized, 246 /** 247 * The memory passed to getPixels has not been initialized to zero, 248 * so the SkCodec must write all zeroes to memory. 249 * 250 * This is the default. It will be used if no Options struct is used. 251 */ 252 kNo_ZeroInitialized, 253 }; 254 255 /** 256 * Additional options to pass to getPixels. 257 */ 258 struct Options { 259 Options() 260 : fZeroInitialized(kNo_ZeroInitialized) 261 , fSubset(nullptr) 262 , fFrameIndex(0) 263 , fPriorFrame(kNone) 264 , fPremulBehavior(SkTransferFunctionBehavior::kRespect) 265 {} 266 267 ZeroInitialized fZeroInitialized; 268 /** 269 * If not NULL, represents a subset of the original image to decode. 270 * Must be within the bounds returned by getInfo(). 271 * If the EncodedFormat is SkEncodedImageFormat::kWEBP (the only one which 272 * currently supports subsets), the top and left values must be even. 273 * 274 * In getPixels and incremental decode, we will attempt to decode the 275 * exact rectangular subset specified by fSubset. 276 * 277 * In a scanline decode, it does not make sense to specify a subset 278 * top or subset height, since the client already controls which rows 279 * to get and which rows to skip. During scanline decodes, we will 280 * require that the subset top be zero and the subset height be equal 281 * to the full height. We will, however, use the values of 282 * subset left and subset width to decode partial scanlines on calls 283 * to getScanlines(). 284 */ 285 const SkIRect* fSubset; 286 287 /** 288 * The frame to decode. 289 * 290 * Only meaningful for multi-frame images. 291 */ 292 int fFrameIndex; 293 294 /** 295 * If not kNone, the dst already contains the prior frame at this index. 296 * 297 * Only meaningful for multi-frame images. 298 * 299 * If fFrameIndex needs to be blended with a prior frame (as reported by 300 * getFrameInfo[fFrameIndex].fRequiredFrame), the client can set this to 301 * any non-kRestorePrevious frame in [fRequiredFrame, fFrameIndex) to 302 * indicate that that frame is already in the dst. Options.fZeroInitialized 303 * is ignored in this case. 304 * 305 * If set to kNone, the codec will decode any necessary required frame(s) first. 306 */ 307 int fPriorFrame; 308 309 /** 310 * Indicates whether we should do a linear premultiply or a legacy premultiply. 311 * 312 * In the case where the dst SkColorSpace is nullptr, this flag is ignored and 313 * we will always do a legacy premultiply. 314 */ 315 SkTransferFunctionBehavior fPremulBehavior; 316 }; 317 318 /** 319 * Decode into the given pixels, a block of memory of size at 320 * least (info.fHeight - 1) * rowBytes + (info.fWidth * 321 * bytesPerPixel) 322 * 323 * Repeated calls to this function should give the same results, 324 * allowing the PixelRef to be immutable. 325 * 326 * @param info A description of the format (config, size) 327 * expected by the caller. This can simply be identical 328 * to the info returned by getInfo(). 329 * 330 * This contract also allows the caller to specify 331 * different output-configs, which the implementation can 332 * decide to support or not. 333 * 334 * A size that does not match getInfo() implies a request 335 * to scale. If the generator cannot perform this scale, 336 * it will return kInvalidScale. 337 * 338 * If the info contains a non-null SkColorSpace, the codec 339 * will perform the appropriate color space transformation. 340 * If the caller passes in the same color space that was 341 * reported by the codec, the color space transformation is 342 * a no-op. 343 * 344 * If a scanline decode is in progress, scanline mode will end, requiring the client to call 345 * startScanlineDecode() in order to return to decoding scanlines. 346 * 347 * @return Result kSuccess, or another value explaining the type of failure. 348 */ 349 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*); 350 351 /** 352 * Simplified version of getPixels() that uses the default Options. 353 */ 354 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { 355 return this->getPixels(info, pixels, rowBytes, nullptr); 356 } 357 358 /** 359 * If decoding to YUV is supported, this returns true. Otherwise, this 360 * returns false and does not modify any of the parameters. 361 * 362 * @param sizeInfo Output parameter indicating the sizes and required 363 * allocation widths of the Y, U, and V planes. 364 * @param colorSpace Output parameter. If non-NULL this is set to kJPEG, 365 * otherwise this is ignored. 366 */ 367 bool queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const { 368 if (nullptr == sizeInfo) { 369 return false; 370 } 371 372 return this->onQueryYUV8(sizeInfo, colorSpace); 373 } 374 375 /** 376 * Returns kSuccess, or another value explaining the type of failure. 377 * This always attempts to perform a full decode. If the client only 378 * wants size, it should call queryYUV8(). 379 * 380 * @param sizeInfo Needs to exactly match the values returned by the 381 * query, except the WidthBytes may be larger than the 382 * recommendation (but not smaller). 383 * @param planes Memory for each of the Y, U, and V planes. 384 */ 385 Result getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) { 386 if (nullptr == planes || nullptr == planes[0] || nullptr == planes[1] || 387 nullptr == planes[2]) { 388 return kInvalidInput; 389 } 390 391 if (!this->rewindIfNeeded()) { 392 return kCouldNotRewind; 393 } 394 395 return this->onGetYUV8Planes(sizeInfo, planes); 396 } 397 398 /** 399 * Prepare for an incremental decode with the specified options. 400 * 401 * This may require a rewind. 402 * 403 * @param dstInfo Info of the destination. If the dimensions do not match 404 * those of getInfo, this implies a scale. 405 * @param dst Memory to write to. Needs to be large enough to hold the subset, 406 * if present, or the full image as described in dstInfo. 407 * @param options Contains decoding options, including if memory is zero 408 * initialized and whether to decode a subset. 409 * @return Enum representing success or reason for failure. 410 */ 411 Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, 412 const Options*); 413 414 Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) { 415 return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr); 416 } 417 418 /** 419 * Start/continue the incremental decode. 420 * 421 * Not valid to call before calling startIncrementalDecode(). 422 * 423 * After the first call, should only be called again if more data has been 424 * provided to the source SkStream. 425 * 426 * Unlike getPixels and getScanlines, this does not do any filling. This is 427 * left up to the caller, since they may be skipping lines or continuing the 428 * decode later. In the latter case, they may choose to initialize all lines 429 * first, or only initialize the remaining lines after the first call. 430 * 431 * @param rowsDecoded Optional output variable returning the total number of 432 * lines initialized. Only meaningful if this method returns kIncompleteInput. 433 * Otherwise the implementation may not set it. 434 * Note that some implementations may have initialized this many rows, but 435 * not necessarily finished those rows (e.g. interlaced PNG). This may be 436 * useful for determining what rows the client needs to initialize. 437 * @return kSuccess if all lines requested in startIncrementalDecode have 438 * been completely decoded. kIncompleteInput otherwise. 439 */ 440 Result incrementalDecode(int* rowsDecoded = nullptr) { 441 if (!fStartedIncrementalDecode) { 442 return kInvalidParameters; 443 } 444 return this->onIncrementalDecode(rowsDecoded); 445 } 446 447 /** 448 * The remaining functions revolve around decoding scanlines. 449 */ 450 451 /** 452 * Prepare for a scanline decode with the specified options. 453 * 454 * After this call, this class will be ready to decode the first scanline. 455 * 456 * This must be called in order to call getScanlines or skipScanlines. 457 * 458 * This may require rewinding the stream. 459 * 460 * Not all SkCodecs support this. 461 * 462 * @param dstInfo Info of the destination. If the dimensions do not match 463 * those of getInfo, this implies a scale. 464 * @param options Contains decoding options, including if memory is zero 465 * initialized. 466 * @return Enum representing success or reason for failure. 467 */ 468 Result startScanlineDecode(const SkImageInfo& dstInfo, const Options* options); 469 470 /** 471 * Simplified version of startScanlineDecode() that uses the default Options. 472 */ 473 Result startScanlineDecode(const SkImageInfo& dstInfo) { 474 return this->startScanlineDecode(dstInfo, nullptr); 475 } 476 477 /** 478 * Write the next countLines scanlines into dst. 479 * 480 * Not valid to call before calling startScanlineDecode(). 481 * 482 * @param dst Must be non-null, and large enough to hold countLines 483 * scanlines of size rowBytes. 484 * @param countLines Number of lines to write. 485 * @param rowBytes Number of bytes per row. Must be large enough to hold 486 * a scanline based on the SkImageInfo used to create this object. 487 * @return the number of lines successfully decoded. If this value is 488 * less than countLines, this will fill the remaining lines with a 489 * default value. 490 */ 491 int getScanlines(void* dst, int countLines, size_t rowBytes); 492 493 /** 494 * Skip count scanlines. 495 * 496 * Not valid to call before calling startScanlineDecode(). 497 * 498 * The default version just calls onGetScanlines and discards the dst. 499 * NOTE: If skipped lines are the only lines with alpha, this default 500 * will make reallyHasAlpha return true, when it could have returned 501 * false. 502 * 503 * @return true if the scanlines were successfully skipped 504 * false on failure, possible reasons for failure include: 505 * An incomplete input image stream. 506 * Calling this function before calling startScanlineDecode(). 507 * If countLines is less than zero or so large that it moves 508 * the current scanline past the end of the image. 509 */ 510 bool skipScanlines(int countLines); 511 512 /** 513 * The order in which rows are output from the scanline decoder is not the 514 * same for all variations of all image types. This explains the possible 515 * output row orderings. 516 */ 517 enum SkScanlineOrder { 518 /* 519 * By far the most common, this indicates that the image can be decoded 520 * reliably using the scanline decoder, and that rows will be output in 521 * the logical order. 522 */ 523 kTopDown_SkScanlineOrder, 524 525 /* 526 * This indicates that the scanline decoder reliably outputs rows, but 527 * they will be returned in reverse order. If the scanline format is 528 * kBottomUp, the nextScanline() API can be used to determine the actual 529 * y-coordinate of the next output row, but the client is not forced 530 * to take advantage of this, given that it's not too tough to keep 531 * track independently. 532 * 533 * For full image decodes, it is safe to get all of the scanlines at 534 * once, since the decoder will handle inverting the rows as it 535 * decodes. 536 * 537 * For subset decodes and sampling, it is simplest to get and skip 538 * scanlines one at a time, using the nextScanline() API. It is 539 * possible to ask for larger chunks at a time, but this should be used 540 * with caution. As with full image decodes, the decoder will handle 541 * inverting the requested rows, but rows will still be delivered 542 * starting from the bottom of the image. 543 * 544 * Upside down bmps are an example. 545 */ 546 kBottomUp_SkScanlineOrder, 547 }; 548 549 /** 550 * An enum representing the order in which scanlines will be returned by 551 * the scanline decoder. 552 * 553 * This is undefined before startScanlineDecode() is called. 554 */ 555 SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); } 556 557 /** 558 * Returns the y-coordinate of the next row to be returned by the scanline 559 * decoder. 560 * 561 * This will equal fCurrScanline, except in the case of strangely 562 * encoded image types (bottom-up bmps). 563 * 564 * Results are undefined when not in scanline decoding mode. 565 */ 566 int nextScanline() const { return this->outputScanline(fCurrScanline); } 567 568 /** 569 * Returns the output y-coordinate of the row that corresponds to an input 570 * y-coordinate. The input y-coordinate represents where the scanline 571 * is located in the encoded data. 572 * 573 * This will equal inputScanline, except in the case of strangely 574 * encoded image types (bottom-up bmps, interlaced gifs). 575 */ 576 int outputScanline(int inputScanline) const; 577 578 /** 579 * Return the number of frames in the image. 580 * 581 * May require reading through the stream. 582 */ 583 int getFrameCount() { 584 return this->onGetFrameCount(); 585 } 586 587 // The required frame for an independent frame is marked as 588 // kNone. 589 static constexpr int kNone = -1; 590 591 /** 592 * Information about individual frames in a multi-framed image. 593 */ 594 struct FrameInfo { 595 /** 596 * The frame that this frame needs to be blended with, or 597 * kNone if this frame is independent. 598 * 599 * Note that this is the *earliest* frame that can be used 600 * for blending. Any frame from [fRequiredFrame, i) can be 601 * used, unless its fDisposalMethod is kRestorePrevious. 602 */ 603 int fRequiredFrame; 604 605 /** 606 * Number of milliseconds to show this frame. 607 */ 608 int fDuration; 609 610 /** 611 * Whether the end marker for this frame is contained in the stream. 612 * 613 * Note: this does not guarantee that an attempt to decode will be complete. 614 * There could be an error in the stream. 615 */ 616 bool fFullyReceived; 617 618 /** 619 * This is conservative; it will still return non-opaque if e.g. a 620 * color index-based frame has a color with alpha but does not use it. 621 */ 622 SkAlphaType fAlphaType; 623 624 /** 625 * How this frame should be modified before decoding the next one. 626 */ 627 SkCodecAnimation::DisposalMethod fDisposalMethod; 628 }; 629 630 /** 631 * Return info about a single frame. 632 * 633 * Only supported by multi-frame images. Does not read through the stream, 634 * so it should be called after getFrameCount() to parse any frames that 635 * have not already been parsed. 636 */ 637 bool getFrameInfo(int index, FrameInfo* info) const { 638 if (index < 0) { 639 return false; 640 } 641 return this->onGetFrameInfo(index, info); 642 } 643 644 /** 645 * Return info about all the frames in the image. 646 * 647 * May require reading through the stream to determine info about the 648 * frames (including the count). 649 * 650 * As such, future decoding calls may require a rewind. 651 * 652 * For single-frame images, this will return an empty vector. 653 */ 654 std::vector<FrameInfo> getFrameInfo(); 655 656 static constexpr int kRepetitionCountInfinite = -1; 657 658 /** 659 * Return the number of times to repeat, if this image is animated. 660 * 661 * May require reading the stream to find the repetition count. 662 * 663 * As such, future decoding calls may require a rewind. 664 * 665 * For single-frame images, this will return 0. 666 */ 667 int getRepetitionCount() { 668 return this->onGetRepetitionCount(); 669 } 670 671protected: 672 using XformFormat = SkColorSpaceXform::ColorFormat; 673 674 SkCodec(int width, 675 int height, 676 const SkEncodedInfo&, 677 XformFormat srcFormat, 678 std::unique_ptr<SkStream>, 679 sk_sp<SkColorSpace>, 680 Origin = kTopLeft_Origin); 681 682 /** 683 * Allows the subclass to set the recommended SkImageInfo 684 */ 685 SkCodec(const SkEncodedInfo&, 686 const SkImageInfo&, 687 XformFormat srcFormat, 688 std::unique_ptr<SkStream>, 689 Origin = kTopLeft_Origin); 690 691 virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const { 692 // By default, scaling is not supported. 693 return this->getInfo().dimensions(); 694 } 695 696 // FIXME: What to do about subsets?? 697 /** 698 * Subclasses should override if they support dimensions other than the 699 * srcInfo's. 700 */ 701 virtual bool onDimensionsSupported(const SkISize&) { 702 return false; 703 } 704 705 virtual SkEncodedImageFormat onGetEncodedFormat() const = 0; 706 707 /** 708 * @param rowsDecoded When the encoded image stream is incomplete, this function 709 * will return kIncompleteInput and rowsDecoded will be set to 710 * the number of scanlines that were successfully decoded. 711 * This will allow getPixels() to fill the uninitialized memory. 712 */ 713 virtual Result onGetPixels(const SkImageInfo& info, 714 void* pixels, size_t rowBytes, const Options&, 715 int* rowsDecoded) = 0; 716 717 virtual bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const { 718 return false; 719 } 720 721 virtual Result onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) { 722 return kUnimplemented; 723 } 724 725 virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const { 726 // By default, subsets are not supported. 727 return false; 728 } 729 730 /** 731 * If the stream was previously read, attempt to rewind. 732 * 733 * If the stream needed to be rewound, call onRewind. 734 * @returns true if the codec is at the right position and can be used. 735 * false if there was a failure to rewind. 736 * 737 * This is called by getPixels() and start(). Subclasses may call if they 738 * need to rewind at another time. 739 */ 740 bool SK_WARN_UNUSED_RESULT rewindIfNeeded(); 741 742 /** 743 * Called by rewindIfNeeded, if the stream needed to be rewound. 744 * 745 * Subclasses should do any set up needed after a rewind. 746 */ 747 virtual bool onRewind() { 748 return true; 749 } 750 751 /** 752 * On an incomplete input, getPixels() and getScanlines() will fill any uninitialized 753 * scanlines. This allows the subclass to indicate what value to fill with. 754 * 755 * @param dstInfo Describes the destination. 756 * @return The value with which to fill uninitialized pixels. 757 * 758 * Note that we can interpret the return value as a 64-bit Float16 color, a SkPMColor, 759 * a 16-bit 565 color, an 8-bit gray color, or an 8-bit index into a color table, 760 * depending on the color type. 761 */ 762 uint64_t getFillValue(const SkImageInfo& dstInfo) const { 763 return this->onGetFillValue(dstInfo); 764 } 765 766 /** 767 * Some subclasses will override this function, but this is a useful default for the color 768 * types that we support. Note that for color types that do not use the full 64-bits, 769 * we will simply take the low bits of the fill value. 770 * 771 * The defaults are: 772 * kRGBA_F16_SkColorType: Transparent or Black, depending on the src alpha type 773 * kN32_SkColorType: Transparent or Black, depending on the src alpha type 774 * kRGB_565_SkColorType: Black 775 * kGray_8_SkColorType: Black 776 */ 777 virtual uint64_t onGetFillValue(const SkImageInfo& dstInfo) const; 778 779 /** 780 * Get method for the input stream 781 */ 782 SkStream* stream() { 783 return fStream.get(); 784 } 785 786 /** 787 * The remaining functions revolve around decoding scanlines. 788 */ 789 790 /** 791 * Most images types will be kTopDown and will not need to override this function. 792 */ 793 virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; } 794 795 const SkImageInfo& dstInfo() const { return fDstInfo; } 796 797 const Options& options() const { return fOptions; } 798 799 /** 800 * Returns the number of scanlines that have been decoded so far. 801 * This is unaffected by the SkScanlineOrder. 802 * 803 * Returns -1 if we have not started a scanline decode. 804 */ 805 int currScanline() const { return fCurrScanline; } 806 807 virtual int onOutputScanline(int inputScanline) const; 808 809 bool initializeColorXform(const SkImageInfo& dstInfo, 810 SkTransferFunctionBehavior premulBehavior); 811 void applyColorXform(void* dst, const void* src, int count, SkAlphaType) const; 812 void applyColorXform(void* dst, const void* src, int count) const; 813 814 SkColorSpaceXform* colorXform() const { return fColorXform.get(); } 815 bool xformOnDecode() const { return fXformOnDecode; } 816 817 virtual int onGetFrameCount() { 818 return 1; 819 } 820 821 virtual bool onGetFrameInfo(int, FrameInfo*) const { 822 return false; 823 } 824 825 virtual int onGetRepetitionCount() { 826 return 0; 827 } 828 829private: 830 const SkEncodedInfo fEncodedInfo; 831 const SkImageInfo fSrcInfo; 832 const XformFormat fSrcXformFormat; 833 std::unique_ptr<SkStream> fStream; 834 bool fNeedsRewind; 835 const Origin fOrigin; 836 837 SkImageInfo fDstInfo; 838 Options fOptions; 839 XformFormat fDstXformFormat; // Based on fDstInfo. 840 std::unique_ptr<SkColorSpaceXform> fColorXform; 841 bool fXformOnDecode; 842 843 // Only meaningful during scanline decodes. 844 int fCurrScanline; 845 846 bool fStartedIncrementalDecode; 847 848 /** 849 * Return whether these dimensions are supported as a scale. 850 * 851 * The codec may choose to cache the information about scale and subset. 852 * Either way, the same information will be passed to onGetPixels/onStart 853 * on success. 854 * 855 * This must return true for a size returned from getScaledDimensions. 856 */ 857 bool dimensionsSupported(const SkISize& dim) { 858 return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim); 859 } 860 861 /** 862 * For multi-framed images, return the object with information about the frames. 863 */ 864 virtual const SkFrameHolder* getFrameHolder() const { 865 return nullptr; 866 } 867 868 /** 869 * Check for a valid Options.fFrameIndex, and decode prior frames if necessary. 870 */ 871 Result handleFrameIndex(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&); 872 873 // Methods for scanline decoding. 874 virtual Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/, 875 const Options& /*options*/) { 876 return kUnimplemented; 877 } 878 879 virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t, 880 const Options&) { 881 return kUnimplemented; 882 } 883 884 virtual Result onIncrementalDecode(int*) { 885 return kUnimplemented; 886 } 887 888 889 virtual bool onSkipScanlines(int /*countLines*/) { return false; } 890 891 virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; } 892 893 /** 894 * On an incomplete decode, getPixels() and getScanlines() will call this function 895 * to fill any uinitialized memory. 896 * 897 * @param dstInfo Contains the destination color type 898 * Contains the destination alpha type 899 * Contains the destination width 900 * The height stored in this info is unused 901 * @param dst Pointer to the start of destination pixel memory 902 * @param rowBytes Stride length in destination pixel memory 903 * @param zeroInit Indicates if memory is zero initialized 904 * @param linesRequested Number of lines that the client requested 905 * @param linesDecoded Number of lines that were successfully decoded 906 */ 907 void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, 908 ZeroInitialized zeroInit, int linesRequested, int linesDecoded); 909 910 /** 911 * Return an object which will allow forcing scanline decodes to sample in X. 912 * 913 * May create a sampler, if one is not currently being used. Otherwise, does 914 * not affect ownership. 915 * 916 * Only valid during scanline decoding or incremental decoding. 917 */ 918 virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; } 919 920 friend class DM::CodecSrc; // for fillIncompleteImage 921 friend class SkSampledCodec; 922 friend class SkIcoCodec; 923}; 924#endif // SkCodec_DEFINED 925