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