SkCodec.h (46284B)
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 "include/codec/SkEncodedOrigin.h" 12 #include "include/core/SkImageInfo.h" 13 #include "include/core/SkPixmap.h" 14 #include "include/core/SkRect.h" 15 #include "include/core/SkRefCnt.h" 16 #include "include/core/SkSize.h" 17 #include "include/core/SkSpan.h" 18 #include "include/core/SkTypes.h" 19 #include "include/core/SkYUVAPixmaps.h" 20 #include "include/private/SkEncodedInfo.h" 21 #include "include/private/SkHdrMetadata.h" 22 #include "include/private/base/SkNoncopyable.h" 23 #include "modules/skcms/skcms.h" 24 25 #include <cstddef> 26 #include <functional> 27 #include <memory> 28 #include <optional> 29 #include <string_view> 30 #include <tuple> 31 #include <vector> 32 33 class SkData; 34 class SkFrameHolder; 35 class SkImage; 36 class SkPngChunkReader; 37 class SkSampler; 38 class SkStream; 39 struct SkGainmapInfo; 40 enum SkAlphaType : int; 41 enum class SkEncodedImageFormat; 42 43 namespace SkCodecAnimation { 44 enum class Blend; 45 enum class DisposalMethod; 46 } 47 48 namespace DM { 49 class CodecSrc; 50 } // namespace DM 51 52 namespace SkCodecs { 53 struct Decoder; 54 } 55 56 /** 57 * Abstraction layer directly on top of an image codec. 58 */ 59 class SK_API SkCodec : SkNoncopyable { 60 public: 61 /** 62 * Minimum number of bytes that must be buffered in SkStream input. 63 * 64 * An SkStream passed to NewFromStream must be able to use this many 65 * bytes to determine the image type. Then the same SkStream must be 66 * passed to the correct decoder to read from the beginning. 67 * 68 * This can be accomplished by implementing peek() to support peeking 69 * this many bytes, or by implementing rewind() to be able to rewind() 70 * after reading this many bytes. 71 */ 72 static constexpr size_t MinBufferedBytesNeeded() { return 32; } 73 74 /** 75 * Error codes for various SkCodec methods. 76 */ 77 enum Result { 78 /** 79 * General return value for success. 80 */ 81 kSuccess, 82 /** 83 * The input is incomplete. A partial image was generated. 84 */ 85 kIncompleteInput, 86 /** 87 * Like kIncompleteInput, except the input had an error. 88 * 89 * If returned from an incremental decode, decoding cannot continue, 90 * even with more data. 91 */ 92 kErrorInInput, 93 /** 94 * The generator cannot convert to match the request, ignoring 95 * dimensions. 96 */ 97 kInvalidConversion, 98 /** 99 * The generator cannot scale to requested size. 100 */ 101 kInvalidScale, 102 /** 103 * Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes 104 * too small, etc. 105 */ 106 kInvalidParameters, 107 /** 108 * The input did not contain a valid image. 109 */ 110 kInvalidInput, 111 /** 112 * Fulfilling this request requires rewinding the input, which is not 113 * supported for this input. 114 */ 115 kCouldNotRewind, 116 /** 117 * An internal error, such as OOM. 118 */ 119 kInternalError, 120 /** 121 * This method is not implemented by this codec. 122 * FIXME: Perhaps this should be kUnsupported? 123 */ 124 kUnimplemented, 125 }; 126 127 /** 128 * Readable string representing the error code. 129 */ 130 static const char* ResultToString(Result); 131 132 /** 133 * For container formats that contain both still images and image sequences, 134 * instruct the decoder how the output should be selected. (Refer to comments 135 * for each value for more details.) 136 */ 137 enum class SelectionPolicy { 138 /** 139 * If the container format contains both still images and image sequences, 140 * SkCodec should choose one of the still images. This is the default. 141 * Note that kPreferStillImage may prevent use of the animation features 142 * if the input is not rewindable. 143 */ 144 kPreferStillImage, 145 /** 146 * If the container format contains both still images and image sequences, 147 * SkCodec should choose one of the image sequences for animation. 148 */ 149 kPreferAnimation, 150 }; 151 152 /** 153 * If this stream represents an encoded image that we know how to decode, 154 * return an SkCodec that can decode it. Otherwise return NULL. 155 * 156 * As stated above, this call must be able to peek or read 157 * MinBufferedBytesNeeded to determine the correct format, and then start 158 * reading from the beginning. First it will attempt to peek, and it 159 * assumes that if less than MinBufferedBytesNeeded bytes (but more than 160 * zero) are returned, this is because the stream is shorter than this, 161 * so falling back to reading would not provide more data. If peek() 162 * returns zero bytes, this call will instead attempt to read(). This 163 * will require that the stream can be rewind()ed. 164 * 165 * If Result is not NULL, it will be set to either kSuccess if an SkCodec 166 * is returned or a reason for the failure if NULL is returned. 167 * 168 * If SkPngChunkReader is not NULL, take a ref and pass it to libpng if 169 * the image is a png. 170 * 171 * If the SkPngChunkReader is not NULL then: 172 * If the image is not a PNG, the SkPngChunkReader will be ignored. 173 * If the image is a PNG, the SkPngChunkReader will be reffed. 174 * If the PNG has unknown chunks, the SkPngChunkReader will be used 175 * to handle these chunks. SkPngChunkReader will be called to read 176 * any unknown chunk at any point during the creation of the codec 177 * or the decode. Note that if SkPngChunkReader fails to read a 178 * chunk, this could result in a failure to create the codec or a 179 * failure to decode the image. 180 * If the PNG does not contain unknown chunks, the SkPngChunkReader 181 * will not be used or modified. 182 * 183 * If NULL is returned, the stream is deleted immediately. Otherwise, the 184 * SkCodec takes ownership of it, and will delete it when done with it. 185 */ 186 static std::unique_ptr<SkCodec> MakeFromStream( 187 std::unique_ptr<SkStream>, 188 SkSpan<const SkCodecs::Decoder> decoders, 189 Result* = nullptr, 190 SkPngChunkReader* = nullptr, 191 SelectionPolicy selectionPolicy = SelectionPolicy::kPreferStillImage); 192 // deprecated 193 static std::unique_ptr<SkCodec> MakeFromStream( 194 std::unique_ptr<SkStream>, 195 Result* = nullptr, 196 SkPngChunkReader* = nullptr, 197 SelectionPolicy selectionPolicy = SelectionPolicy::kPreferStillImage); 198 199 /** 200 * If this data represents an encoded image that we know how to decode, 201 * return an SkCodec that can decode it. Otherwise return NULL. 202 * 203 * If the SkPngChunkReader is not NULL then: 204 * If the image is not a PNG, the SkPngChunkReader will be ignored. 205 * If the image is a PNG, the SkPngChunkReader will be reffed. 206 * If the PNG has unknown chunks, the SkPngChunkReader will be used 207 * to handle these chunks. SkPngChunkReader will be called to read 208 * any unknown chunk at any point during the creation of the codec 209 * or the decode. Note that if SkPngChunkReader fails to read a 210 * chunk, this could result in a failure to create the codec or a 211 * failure to decode the image. 212 * If the PNG does not contain unknown chunks, the SkPngChunkReader 213 * will not be used or modified. 214 */ 215 static std::unique_ptr<SkCodec> MakeFromData(sk_sp<SkData>, 216 SkSpan<const SkCodecs::Decoder> decoders, 217 SkPngChunkReader* = nullptr); 218 // deprecated 219 static std::unique_ptr<SkCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr); 220 221 virtual ~SkCodec(); 222 223 /** 224 * Return a reasonable SkImageInfo to decode into. 225 * 226 * If the image has an ICC profile that does not map to an SkColorSpace, 227 * the returned SkImageInfo will use SRGB. 228 */ 229 SkImageInfo getInfo() const { return fEncodedInfo.makeImageInfo(); } 230 231 SkISize dimensions() const { return {fEncodedInfo.width(), fEncodedInfo.height()}; } 232 SkIRect bounds() const { 233 return SkIRect::MakeWH(fEncodedInfo.width(), fEncodedInfo.height()); 234 } 235 236 /** 237 * Return the ICC profile of the encoded data. 238 */ 239 const skcms_ICCProfile* getICCProfile() const { 240 return this->getEncodedInfo().profile(); 241 } 242 243 /** 244 * Return the HDR metadata associated with this image. Note that even SDR images can include 245 * HDR metadata (e.g, indicating how to inverse tone map when displayed on an HDR display). 246 */ 247 const skhdr::Metadata& getHdrMetadata() const { return fEncodedInfo.getHdrMetadata(); } 248 249 /** 250 * Whether the encoded input uses 16 or more bits per component. 251 */ 252 bool hasHighBitDepthEncodedData() const { 253 // API design note: We don't return `bitsPerComponent` because it may be 254 // misleading in some cases - see https://crbug.com/359350061#comment4 255 // for more details. 256 return this->getEncodedInfo().bitsPerComponent() >= 16; 257 } 258 259 /** 260 * Returns the image orientation stored in the EXIF data. 261 * If there is no EXIF data, or if we cannot read the EXIF data, returns kTopLeft. 262 */ 263 SkEncodedOrigin getOrigin() const { return fOrigin; } 264 265 /** 266 * Return a size that approximately supports the desired scale factor. 267 * The codec may not be able to scale efficiently to the exact scale 268 * factor requested, so return a size that approximates that scale. 269 * The returned value is the codec's suggestion for the closest valid 270 * scale that it can natively support 271 */ 272 SkISize getScaledDimensions(float desiredScale) const { 273 // Negative and zero scales are errors. 274 SkASSERT(desiredScale > 0.0f); 275 if (desiredScale <= 0.0f) { 276 return SkISize::Make(0, 0); 277 } 278 279 // Upscaling is not supported. Return the original size if the client 280 // requests an upscale. 281 if (desiredScale >= 1.0f) { 282 return this->dimensions(); 283 } 284 return this->onGetScaledDimensions(desiredScale); 285 } 286 287 /** 288 * Return (via desiredSubset) a subset which can decoded from this codec, 289 * or false if this codec cannot decode subsets or anything similar to 290 * desiredSubset. 291 * 292 * @param desiredSubset In/out parameter. As input, a desired subset of 293 * the original bounds (as specified by getInfo). If true is returned, 294 * desiredSubset may have been modified to a subset which is 295 * supported. Although a particular change may have been made to 296 * desiredSubset to create something supported, it is possible other 297 * changes could result in a valid subset. 298 * If false is returned, desiredSubset's value is undefined. 299 * @return true if this codec supports decoding desiredSubset (as 300 * returned, potentially modified) 301 */ 302 bool getValidSubset(SkIRect* desiredSubset) const { 303 return this->onGetValidSubset(desiredSubset); 304 } 305 306 /** 307 * Format of the encoded data. 308 */ 309 SkEncodedImageFormat getEncodedFormat() const { return this->onGetEncodedFormat(); } 310 311 /** 312 * Return the underlying encoded data stream. This may be nullptr if the original 313 * stream could not be duplicated. 314 */ 315 virtual std::unique_ptr<SkStream> getEncodedData() const; 316 317 /** 318 * Whether or not the memory passed to getPixels is zero initialized. 319 */ 320 enum ZeroInitialized { 321 /** 322 * The memory passed to getPixels is zero initialized. The SkCodec 323 * may take advantage of this by skipping writing zeroes. 324 */ 325 kYes_ZeroInitialized, 326 /** 327 * The memory passed to getPixels has not been initialized to zero, 328 * so the SkCodec must write all zeroes to memory. 329 * 330 * This is the default. It will be used if no Options struct is used. 331 */ 332 kNo_ZeroInitialized, 333 }; 334 335 /** 336 * Additional options to pass to getPixels. 337 */ 338 struct Options { 339 Options() 340 : fZeroInitialized(kNo_ZeroInitialized) 341 , fSubset(nullptr) 342 , fFrameIndex(0) 343 , fPriorFrame(kNoFrame) 344 {} 345 346 ZeroInitialized fZeroInitialized; 347 /** 348 * If not NULL, represents a subset of the original image to decode. 349 * Must be within the bounds returned by getInfo(). 350 * If the EncodedFormat is SkEncodedImageFormat::kWEBP (the only one which 351 * currently supports subsets), the top and left values must be even. 352 * 353 * In getPixels and incremental decode, we will attempt to decode the 354 * exact rectangular subset specified by fSubset. 355 * 356 * In a scanline decode, it does not make sense to specify a subset 357 * top or subset height, since the client already controls which rows 358 * to get and which rows to skip. During scanline decodes, we will 359 * require that the subset top be zero and the subset height be equal 360 * to the full height. We will, however, use the values of 361 * subset left and subset width to decode partial scanlines on calls 362 * to getScanlines(). 363 */ 364 const SkIRect* fSubset; 365 366 /** 367 * The frame to decode. 368 * 369 * Only meaningful for multi-frame images. 370 */ 371 int fFrameIndex; 372 373 /** 374 * If not kNoFrame, the dst already contains the prior frame at this index. 375 * 376 * Only meaningful for multi-frame images. 377 * 378 * If fFrameIndex needs to be blended with a prior frame (as reported by 379 * getFrameInfo[fFrameIndex].fRequiredFrame), the client can set this to 380 * any non-kRestorePrevious frame in [fRequiredFrame, fFrameIndex) to 381 * indicate that that frame is already in the dst. Options.fZeroInitialized 382 * is ignored in this case. 383 * 384 * If set to kNoFrame, the codec will decode any necessary required frame(s) first. 385 */ 386 int fPriorFrame; 387 }; 388 389 /** 390 * Decode into the given pixels, a block of memory of size at 391 * least (info.fHeight - 1) * rowBytes + (info.fWidth * 392 * bytesPerPixel) 393 * 394 * Repeated calls to this function should give the same results, 395 * allowing the PixelRef to be immutable. 396 * 397 * @param info A description of the format (config, size) 398 * expected by the caller. This can simply be identical 399 * to the info returned by getInfo(). 400 * 401 * This contract also allows the caller to specify 402 * different output-configs, which the implementation can 403 * decide to support or not. 404 * 405 * A size that does not match getInfo() implies a request 406 * to scale. If the generator cannot perform this scale, 407 * it will return kInvalidScale. 408 * 409 * If the info contains a non-null SkColorSpace, the codec 410 * will perform the appropriate color space transformation. 411 * 412 * If the caller passes in the SkColorSpace that maps to the 413 * ICC profile reported by getICCProfile(), the color space 414 * transformation is a no-op. 415 * 416 * If the caller passes a null SkColorSpace, no color space 417 * transformation will be done. 418 * 419 * If a scanline decode is in progress, scanline mode will end, requiring the client to call 420 * startScanlineDecode() in order to return to decoding scanlines. 421 * 422 * For certain codecs, reading into a smaller bitmap than the original dimensions may not 423 * produce correct results (e.g. animated webp). 424 * 425 * @return Result kSuccess, or another value explaining the type of failure. 426 */ 427 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*); 428 429 /** 430 * Simplified version of getPixels() that uses the default Options. 431 */ 432 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { 433 return this->getPixels(info, pixels, rowBytes, nullptr); 434 } 435 436 Result getPixels(const SkPixmap& pm, const Options* opts = nullptr) { 437 return this->getPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), opts); 438 } 439 440 /** 441 * Return an image containing the pixels. If the codec's origin is not "upper left", 442 * This will rotate the output image accordingly. 443 */ 444 std::tuple<sk_sp<SkImage>, SkCodec::Result> getImage(const SkImageInfo& info, 445 const Options* opts = nullptr); 446 std::tuple<sk_sp<SkImage>, SkCodec::Result> getImage(); 447 448 /** 449 * If decoding to YUV is supported, this returns true. Otherwise, this 450 * returns false and the caller will ignore output parameter yuvaPixmapInfo. 451 * 452 * @param supportedDataTypes Indicates the data type/planar config combinations that are 453 * supported by the caller. If the generator supports decoding to 454 * YUV(A), but not as a type in supportedDataTypes, this method 455 * returns false. 456 * @param yuvaPixmapInfo Output parameter that specifies the planar configuration, subsampling, 457 * orientation, chroma siting, plane color types, and row bytes. 458 */ 459 bool queryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes, 460 SkYUVAPixmapInfo* yuvaPixmapInfo) const; 461 462 /** 463 * Returns kSuccess, or another value explaining the type of failure. 464 * This always attempts to perform a full decode. To get the planar 465 * configuration without decoding use queryYUVAInfo(). 466 * 467 * @param yuvaPixmaps Contains preallocated pixmaps configured according to a successful call 468 * to queryYUVAInfo(). 469 */ 470 Result getYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps); 471 472 /** 473 * Prepare for an incremental decode with the specified options. 474 * 475 * This may require a rewind. 476 * 477 * If kIncompleteInput is returned, may be called again after more data has 478 * been provided to the source SkStream. 479 * 480 * @param dstInfo Info of the destination. If the dimensions do not match 481 * those of getInfo, this implies a scale. 482 * @param dst Memory to write to. Needs to be large enough to hold the subset, 483 * if present, or the full image as described in dstInfo. 484 * @param options Contains decoding options, including if memory is zero 485 * initialized and whether to decode a subset. 486 * @return Enum representing success or reason for failure. 487 */ 488 Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, 489 const Options*); 490 491 Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) { 492 return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr); 493 } 494 495 /** 496 * Start/continue the incremental decode. 497 * 498 * Not valid to call before a call to startIncrementalDecode() returns 499 * kSuccess. 500 * 501 * If kIncompleteInput is returned, may be called again after more data has 502 * been provided to the source SkStream. 503 * 504 * Unlike getPixels and getScanlines, this does not do any filling. This is 505 * left up to the caller, since they may be skipping lines or continuing the 506 * decode later. In the latter case, they may choose to initialize all lines 507 * first, or only initialize the remaining lines after the first call. 508 * 509 * @param rowsDecoded Optional output variable returning the total number of 510 * lines initialized. Only meaningful if this method returns kIncompleteInput. 511 * Otherwise the implementation may not set it. 512 * Note that some implementations may have initialized this many rows, but 513 * not necessarily finished those rows (e.g. interlaced PNG). This may be 514 * useful for determining what rows the client needs to initialize. 515 * @return kSuccess if all lines requested in startIncrementalDecode have 516 * been completely decoded. kIncompleteInput otherwise. 517 */ 518 Result incrementalDecode(int* rowsDecoded = nullptr) { 519 if (!fStartedIncrementalDecode) { 520 return kInvalidParameters; 521 } 522 return this->onIncrementalDecode(rowsDecoded); 523 } 524 525 /** 526 * The remaining functions revolve around decoding scanlines. 527 */ 528 529 /** 530 * Prepare for a scanline decode with the specified options. 531 * 532 * After this call, this class will be ready to decode the first scanline. 533 * 534 * This must be called in order to call getScanlines or skipScanlines. 535 * 536 * This may require rewinding the stream. 537 * 538 * Not all SkCodecs support this. 539 * 540 * @param dstInfo Info of the destination. If the dimensions do not match 541 * those of getInfo, this implies a scale. 542 * @param options Contains decoding options, including if memory is zero 543 * initialized. 544 * @return Enum representing success or reason for failure. 545 */ 546 Result startScanlineDecode(const SkImageInfo& dstInfo, const Options* options); 547 548 /** 549 * Simplified version of startScanlineDecode() that uses the default Options. 550 */ 551 Result startScanlineDecode(const SkImageInfo& dstInfo) { 552 return this->startScanlineDecode(dstInfo, nullptr); 553 } 554 555 /** 556 * Write the next countLines scanlines into dst. 557 * 558 * Not valid to call before calling startScanlineDecode(). 559 * 560 * @param dst Must be non-null, and large enough to hold countLines 561 * scanlines of size rowBytes. 562 * @param countLines Number of lines to write. 563 * @param rowBytes Number of bytes per row. Must be large enough to hold 564 * a scanline based on the SkImageInfo used to create this object. 565 * @return the number of lines successfully decoded. If this value is 566 * less than countLines, this will fill the remaining lines with a 567 * default value. 568 */ 569 int getScanlines(void* dst, int countLines, size_t rowBytes); 570 571 /** 572 * Skip count scanlines. 573 * 574 * Not valid to call before calling startScanlineDecode(). 575 * 576 * The default version just calls onGetScanlines and discards the dst. 577 * NOTE: If skipped lines are the only lines with alpha, this default 578 * will make reallyHasAlpha return true, when it could have returned 579 * false. 580 * 581 * @return true if the scanlines were successfully skipped 582 * false on failure, possible reasons for failure include: 583 * An incomplete input image stream. 584 * Calling this function before calling startScanlineDecode(). 585 * If countLines is less than zero or so large that it moves 586 * the current scanline past the end of the image. 587 */ 588 bool skipScanlines(int countLines); 589 590 /** 591 * The order in which rows are output from the scanline decoder is not the 592 * same for all variations of all image types. This explains the possible 593 * output row orderings. 594 */ 595 enum SkScanlineOrder { 596 /* 597 * By far the most common, this indicates that the image can be decoded 598 * reliably using the scanline decoder, and that rows will be output in 599 * the logical order. 600 */ 601 kTopDown_SkScanlineOrder, 602 603 /* 604 * This indicates that the scanline decoder reliably outputs rows, but 605 * they will be returned in reverse order. If the scanline format is 606 * kBottomUp, the nextScanline() API can be used to determine the actual 607 * y-coordinate of the next output row, but the client is not forced 608 * to take advantage of this, given that it's not too tough to keep 609 * track independently. 610 * 611 * For full image decodes, it is safe to get all of the scanlines at 612 * once, since the decoder will handle inverting the rows as it 613 * decodes. 614 * 615 * For subset decodes and sampling, it is simplest to get and skip 616 * scanlines one at a time, using the nextScanline() API. It is 617 * possible to ask for larger chunks at a time, but this should be used 618 * with caution. As with full image decodes, the decoder will handle 619 * inverting the requested rows, but rows will still be delivered 620 * starting from the bottom of the image. 621 * 622 * Upside down bmps are an example. 623 */ 624 kBottomUp_SkScanlineOrder, 625 }; 626 627 /** 628 * An enum representing the order in which scanlines will be returned by 629 * the scanline decoder. 630 * 631 * This is undefined before startScanlineDecode() is called. 632 */ 633 SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); } 634 635 /** 636 * Returns the y-coordinate of the next row to be returned by the scanline 637 * decoder. 638 * 639 * This will equal fCurrScanline, except in the case of strangely 640 * encoded image types (bottom-up bmps). 641 * 642 * Results are undefined when not in scanline decoding mode. 643 */ 644 int nextScanline() const { return this->outputScanline(fCurrScanline); } 645 646 /** 647 * Returns the output y-coordinate of the row that corresponds to an input 648 * y-coordinate. The input y-coordinate represents where the scanline 649 * is located in the encoded data. 650 * 651 * This will equal inputScanline, except in the case of strangely 652 * encoded image types (bottom-up bmps, interlaced gifs). 653 */ 654 int outputScanline(int inputScanline) const; 655 656 /** 657 * Return the number of frames in the image. 658 * 659 * May require reading through the stream. 660 * 661 * Note that some codecs may be unable to gather `FrameInfo` for all frames 662 * in case of `kIncompleteInput`. For such codecs `getFrameCount` may 663 * initially report a low frame count. After the underlying `SkStream` 664 * provides additional data, then calling `getFrameCount` again may return 665 * an updated, increased frame count. 666 */ 667 int getFrameCount() { 668 return this->onGetFrameCount(); 669 } 670 671 // Sentinel value used when a frame index implies "no frame": 672 // - FrameInfo::fRequiredFrame set to this value means the frame 673 // is independent. 674 // - Options::fPriorFrame set to this value means no (relevant) prior frame 675 // is residing in dst's memory. 676 static constexpr int kNoFrame = -1; 677 678 /** 679 * Information about individual frames in a multi-framed image. 680 */ 681 struct FrameInfo { 682 /** 683 * The frame that this frame needs to be blended with, or 684 * kNoFrame if this frame is independent (so it can be 685 * drawn over an uninitialized buffer). 686 * 687 * Note that this is the *earliest* frame that can be used 688 * for blending. Any frame from [fRequiredFrame, i) can be 689 * used, unless its fDisposalMethod is kRestorePrevious. 690 */ 691 int fRequiredFrame; 692 693 /** 694 * Number of milliseconds to show this frame. 695 */ 696 int fDuration; 697 698 /** 699 * Whether the end marker for this frame is contained in the stream. 700 * 701 * Note: this does not guarantee that an attempt to decode will be complete. 702 * There could be an error in the stream. 703 */ 704 bool fFullyReceived; 705 706 /** 707 * This is conservative; it will still return non-opaque if e.g. a 708 * color index-based frame has a color with alpha but does not use it. 709 */ 710 SkAlphaType fAlphaType; 711 712 /** 713 * Whether the updated rectangle contains alpha. 714 * 715 * This is conservative; it will still be set to true if e.g. a color 716 * index-based frame has a color with alpha but does not use it. In 717 * addition, it may be set to true, even if the final frame, after 718 * blending, is opaque. 719 */ 720 bool fHasAlphaWithinBounds; 721 722 /** 723 * How this frame should be modified before decoding the next one. 724 */ 725 SkCodecAnimation::DisposalMethod fDisposalMethod; 726 727 /** 728 * How this frame should blend with the prior frame. 729 */ 730 SkCodecAnimation::Blend fBlend; 731 732 /** 733 * The rectangle updated by this frame. 734 * 735 * It may be empty, if the frame does not change the image. It will 736 * always be contained by SkCodec::dimensions(). 737 */ 738 SkIRect fFrameRect; 739 }; 740 741 /** 742 * Return info about a single frame. 743 * 744 * Does not read through the stream, so it should be called after 745 * getFrameCount() to parse any frames that have not already been parsed. 746 * 747 * Only supported by animated (multi-frame) codecs. Note that this is a 748 * property of the codec (the SkCodec subclass), not the image. 749 * 750 * To elaborate, some codecs support animation (e.g. GIF). Others do not 751 * (e.g. BMP). Animated codecs can still represent single frame images. 752 * Calling getFrameInfo(0, etc) will return true for a single frame GIF 753 * even if the overall image is not animated (in that the pixels on screen 754 * do not change over time). When incrementally decoding a GIF image, we 755 * might only know that there's a single frame *so far*. 756 * 757 * For non-animated SkCodec subclasses, it's sufficient but not necessary 758 * for this method to always return false. 759 */ 760 bool getFrameInfo(int index, FrameInfo* info) const { 761 if (index < 0) { 762 return false; 763 } 764 return this->onGetFrameInfo(index, info); 765 } 766 767 /** 768 * Return info about all the frames in the image. 769 * 770 * May require reading through the stream to determine info about the 771 * frames (including the count). 772 * 773 * As such, future decoding calls may require a rewind. 774 * 775 * This may return an empty vector for non-animated codecs. See the 776 * getFrameInfo(int, FrameInfo*) comment. 777 */ 778 std::vector<FrameInfo> getFrameInfo(); 779 780 static constexpr int kRepetitionCountInfinite = -1; 781 782 /** 783 * Return the number of times to repeat, if this image is animated. This number does not 784 * include the first play through of each frame. For example, a repetition count of 4 means 785 * that each frame is played 5 times and then the animation stops. 786 * 787 * It can return kRepetitionCountInfinite, a negative number, meaning that the animation 788 * should loop forever. 789 * 790 * May require reading the stream to find the repetition count. 791 * 792 * As such, future decoding calls may require a rewind. 793 * 794 * `getRepetitionCount` will return `0` in two cases: 795 * 1. Still (non-animated) images. 796 * 2. Animated images that only play the animation once (i.e. that don't 797 * repeat the animation) 798 * `isAnimated` can be used to disambiguate between these two cases. 799 */ 800 int getRepetitionCount() { 801 return this->onGetRepetitionCount(); 802 } 803 804 /** 805 * `isAnimated` returns whether the full input is expected to contain an 806 * animated image (i.e. more than 1 image frame). This can be used to 807 * disambiguate the meaning of `getRepetitionCount` returning `0` (see 808 * `getRepetitionCount`'s doc comment for more details). 809 * 810 * Note that in some codecs `getFrameCount()` only returns the number of 811 * frames for which all the metadata has been already successfully decoded. 812 * Therefore for a partial input `isAnimated()` may return "yes", even 813 * though `getFrameCount()` may temporarily return `1` until more of the 814 * input is available. 815 * 816 * When handling partial input, some codecs may not know until later (e.g. 817 * until encountering additional image frames) whether the given image has 818 * more than one frame. Such codecs may initially return 819 * `IsAnimated::kUnknown` and only later give a definitive "yes" or "no" 820 * answer. GIF format is one example where this may happen. 821 * 822 * Other codecs may be able to decode the information from the metadata 823 * present before the first image frame. Such codecs should be able to give 824 * a definitive "yes" or "no" answer as soon as they are constructed. PNG 825 * format is one example where this happens. 826 */ 827 enum class IsAnimated { 828 kYes, 829 kNo, 830 kUnknown, 831 }; 832 IsAnimated isAnimated() { return this->onIsAnimated(); } 833 834 // Register a decoder at runtime by passing two function pointers: 835 // - peek() to return true if the span of bytes appears to be your encoded format; 836 // - make() to attempt to create an SkCodec from the given stream. 837 // Not thread safe. 838 static void Register( 839 bool (*peek)(const void*, size_t), 840 std::unique_ptr<SkCodec> (*make)(std::unique_ptr<SkStream>, SkCodec::Result*)); 841 842 protected: 843 const SkEncodedInfo& getEncodedInfo() const { return fEncodedInfo; } 844 845 using XformFormat = skcms_PixelFormat; 846 847 SkCodec(SkEncodedInfo&&, 848 XformFormat srcFormat, 849 std::unique_ptr<SkStream>, 850 SkEncodedOrigin = kTopLeft_SkEncodedOrigin); 851 852 void setSrcXformFormat(XformFormat pixelFormat); 853 854 XformFormat getSrcXformFormat() const { 855 return fSrcXformFormat; 856 } 857 858 virtual bool onGetGainmapCodec(SkGainmapInfo*, std::unique_ptr<SkCodec>*) { return false; } 859 virtual bool onGetGainmapInfo(SkGainmapInfo*) { return false; } 860 861 // TODO(issues.skia.org/363544350): This API only works for JPEG images. Remove this API once 862 // it is no longer used. 863 virtual bool onGetGainmapInfo(SkGainmapInfo*, std::unique_ptr<SkStream>*) { return false; } 864 865 virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const { 866 // By default, scaling is not supported. 867 return this->dimensions(); 868 } 869 870 // FIXME: What to do about subsets?? 871 /** 872 * Subclasses should override if they support dimensions other than the 873 * srcInfo's. 874 */ 875 virtual bool onDimensionsSupported(const SkISize&) { 876 return false; 877 } 878 879 virtual SkEncodedImageFormat onGetEncodedFormat() const = 0; 880 881 /** 882 * @param rowsDecoded When the encoded image stream is incomplete, this function 883 * will return kIncompleteInput and rowsDecoded will be set to 884 * the number of scanlines that were successfully decoded. 885 * This will allow getPixels() to fill the uninitialized memory. 886 */ 887 virtual Result onGetPixels(const SkImageInfo& info, 888 void* pixels, size_t rowBytes, const Options&, 889 int* rowsDecoded) = 0; 890 891 virtual bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes&, 892 SkYUVAPixmapInfo*) const { return false; } 893 894 virtual Result onGetYUVAPlanes(const SkYUVAPixmaps&) { return kUnimplemented; } 895 896 virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const { 897 // By default, subsets are not supported. 898 return false; 899 } 900 901 /** 902 * If the stream was previously read, attempt to rewind. 903 * 904 * If the stream needed to be rewound, call onRewind. 905 * @returns true if the codec is at the right position and can be used. 906 * false if there was a failure to rewind. 907 * 908 * This is called by getPixels(), getYUV8Planes(), startIncrementalDecode() and 909 * startScanlineDecode(). Subclasses may call if they need to rewind at another time. 910 */ 911 [[nodiscard]] bool rewindIfNeeded(); 912 913 /** 914 * Called by onRewind(), attempts to rewind fStream. 915 */ 916 bool rewindStream(); 917 918 /** 919 * Called by rewindIfNeeded, if the stream needed to be rewound. 920 * 921 * Subclasses should call rewindStream() if they own one, and then 922 * do any set up needed after. 923 */ 924 virtual bool onRewind() { 925 if (!this->rewindStream()) { 926 return false; 927 } 928 return true; 929 } 930 931 /** 932 * Get method for the input stream 933 */ 934 SkStream* stream() { 935 return fStream.get(); 936 } 937 938 /** 939 * The remaining functions revolve around decoding scanlines. 940 */ 941 942 /** 943 * Most images types will be kTopDown and will not need to override this function. 944 */ 945 virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; } 946 947 const SkImageInfo& dstInfo() const { return fDstInfo; } 948 949 const Options& options() const { return fOptions; } 950 951 /** 952 * Returns the number of scanlines that have been decoded so far. 953 * This is unaffected by the SkScanlineOrder. 954 * 955 * Returns -1 if we have not started a scanline decode. 956 */ 957 int currScanline() const { return fCurrScanline; } 958 959 virtual int onOutputScanline(int inputScanline) const; 960 961 /** 962 * Return whether we can convert to dst. 963 * 964 * Will be called for the appropriate frame, prior to initializing the colorXform. 965 */ 966 virtual bool conversionSupported(const SkImageInfo& dst, bool srcIsOpaque, 967 bool needsColorXform); 968 969 // Some classes never need a colorXform e.g. 970 // - ICO uses its embedded codec's colorXform 971 // - WBMP is just Black/White 972 virtual bool usesColorXform() const { return true; } 973 void applyColorXform(void* dst, const void* src, int count) const; 974 975 bool colorXform() const { return fXformTime != kNo_XformTime; } 976 bool xformOnDecode() const { return fXformTime == kDecodeRow_XformTime; } 977 978 virtual int onGetFrameCount() { 979 return 1; 980 } 981 982 virtual bool onGetFrameInfo(int, FrameInfo*) const { 983 return false; 984 } 985 986 virtual int onGetRepetitionCount() { 987 return 0; 988 } 989 990 virtual IsAnimated onIsAnimated() { 991 return IsAnimated::kNo; 992 } 993 994 private: 995 const SkEncodedInfo fEncodedInfo; 996 XformFormat fSrcXformFormat; 997 std::unique_ptr<SkStream> fStream; 998 bool fNeedsRewind = false; 999 const SkEncodedOrigin fOrigin; 1000 1001 SkImageInfo fDstInfo; 1002 Options fOptions; 1003 1004 enum XformTime { 1005 kNo_XformTime, 1006 kPalette_XformTime, 1007 kDecodeRow_XformTime, 1008 }; 1009 XformTime fXformTime; 1010 XformFormat fDstXformFormat; // Based on fDstInfo. 1011 skcms_ICCProfile fDstProfileStorage; 1012 // This tracks either fDstProfileStorage or the ICC profile in fEncodedInfo. 1013 // For the latter case it is important to not make a profile copy because skcms_Transform 1014 // only performs a shallow pointer comparison to decide whether it can skip the color space 1015 // transformation. 1016 const skcms_ICCProfile* fDstProfile = &fDstProfileStorage; 1017 skcms_AlphaFormat fDstXformAlphaFormat; 1018 1019 // Only meaningful during scanline decodes. 1020 int fCurrScanline = -1; 1021 1022 bool fStartedIncrementalDecode = false; 1023 1024 // Allows SkAndroidCodec to call handleFrameIndex (potentially decoding a prior frame and 1025 // clearing to transparent) without SkCodec itself calling it, too. 1026 bool fUsingCallbackForHandleFrameIndex = false; 1027 1028 bool initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha, bool srcIsOpaque); 1029 1030 /** 1031 * Return whether these dimensions are supported as a scale. 1032 * 1033 * The codec may choose to cache the information about scale and subset. 1034 * Either way, the same information will be passed to onGetPixels/onStart 1035 * on success. 1036 * 1037 * This must return true for a size returned from getScaledDimensions. 1038 */ 1039 bool dimensionsSupported(const SkISize& dim) { 1040 return dim == this->dimensions() || this->onDimensionsSupported(dim); 1041 } 1042 1043 /** 1044 * For multi-framed images, return the object with information about the frames. 1045 */ 1046 virtual const SkFrameHolder* getFrameHolder() const { 1047 return nullptr; 1048 } 1049 1050 // Callback for decoding a prior frame. The `Options::fFrameIndex` is ignored, 1051 // being replaced by frameIndex. This allows opts to actually be a subclass of 1052 // SkCodec::Options which SkCodec itself does not know how to copy or modify, 1053 // but just passes through to the caller (where it can be reinterpret_cast'd). 1054 using GetPixelsCallback = std::function<Result(const SkImageInfo&, void* pixels, 1055 size_t rowBytes, const Options& opts, 1056 int frameIndex)>; 1057 1058 /** 1059 * Check for a valid Options.fFrameIndex, and decode prior frames if necessary. 1060 * 1061 * If GetPixelsCallback is not null, it will be used to decode a prior frame instead 1062 * of using this SkCodec directly. It may also be used recursively, if that in turn 1063 * depends on a prior frame. This is used by SkAndroidCodec. 1064 */ 1065 Result handleFrameIndex(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&, 1066 GetPixelsCallback = nullptr); 1067 1068 // Methods for scanline decoding. 1069 virtual Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/, 1070 const Options& /*options*/) { 1071 return kUnimplemented; 1072 } 1073 1074 virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t, 1075 const Options&) { 1076 return kUnimplemented; 1077 } 1078 1079 virtual Result onIncrementalDecode(int*) { 1080 return kUnimplemented; 1081 } 1082 1083 1084 virtual bool onSkipScanlines(int /*countLines*/) { return false; } 1085 1086 virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; } 1087 1088 /** 1089 * On an incomplete decode, getPixels() and getScanlines() will call this function 1090 * to fill any uinitialized memory. 1091 * 1092 * @param dstInfo Contains the destination color type 1093 * Contains the destination alpha type 1094 * Contains the destination width 1095 * The height stored in this info is unused 1096 * @param dst Pointer to the start of destination pixel memory 1097 * @param rowBytes Stride length in destination pixel memory 1098 * @param zeroInit Indicates if memory is zero initialized 1099 * @param linesRequested Number of lines that the client requested 1100 * @param linesDecoded Number of lines that were successfully decoded 1101 */ 1102 void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, 1103 ZeroInitialized zeroInit, int linesRequested, int linesDecoded); 1104 1105 /** 1106 * Return an object which will allow forcing scanline decodes to sample in X. 1107 * 1108 * May create a sampler, if one is not currently being used. Otherwise, does 1109 * not affect ownership. 1110 * 1111 * Only valid during scanline decoding or incremental decoding. 1112 */ 1113 virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; } 1114 1115 friend class DM::CodecSrc; // for fillIncompleteImage 1116 friend class PNGCodecGM; // for fillIncompleteImage 1117 friend class SkSampledCodec; 1118 friend class SkIcoCodec; 1119 friend class SkPngCodec; // for onGetGainmapCodec 1120 friend class SkAndroidCodec; // for handleFrameIndex 1121 friend class SkCodecPriv; // for fEncodedInfo 1122 }; 1123 1124 namespace SkCodecs { 1125 1126 using DecodeContext = void*; 1127 using IsFormatCallback = bool (*)(const void* data, size_t len); 1128 using MakeFromStreamCallback = std::unique_ptr<SkCodec> (*)(std::unique_ptr<SkStream>, 1129 SkCodec::Result*, 1130 DecodeContext); 1131 1132 struct SK_API Decoder { 1133 // By convention, we use all lowercase letters and go with the primary filename extension. 1134 // For example "png", "jpg", "ico", "webp", etc 1135 std::string_view id; 1136 IsFormatCallback isFormat; 1137 MakeFromStreamCallback makeFromStream; 1138 }; 1139 1140 // Add the decoder to the end of a linked list of decoders, which will be used to identify calls to 1141 // SkCodec::MakeFromStream. If a decoder with the same id already exists, this new decoder 1142 // will replace the existing one (in the same position). This is not thread-safe, so make sure all 1143 // initialization is done before the first call. 1144 void SK_API Register(Decoder d); 1145 1146 /** 1147 * Return a SkImage produced by the codec, but attempts to defer image allocation until the 1148 * image is actually used/drawn. This deferral allows the system to cache the result, either on the 1149 * CPU or on the GPU, depending on where the image is drawn. If memory is low, the cache may 1150 * be purged, causing the next draw of the image to have to re-decode. 1151 * 1152 * If alphaType is nullopt, the image's alpha type will be chosen automatically based on the 1153 * image format. Transparent images will default to kPremul_SkAlphaType. If alphaType contains 1154 * kPremul_SkAlphaType or kUnpremul_SkAlphaType, that alpha type will be used. Forcing opaque 1155 * (passing kOpaque_SkAlphaType) is not allowed, and will return nullptr. 1156 * 1157 * @param codec A non-null codec (e.g. from SkPngDecoder::Decode) 1158 * @return created SkImage, or nullptr 1159 */ 1160 SK_API sk_sp<SkImage> DeferredImage(std::unique_ptr<SkCodec> codec, 1161 std::optional<SkAlphaType> alphaType = std::nullopt); 1162 } 1163 1164 #endif // SkCodec_DEFINED