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