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