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