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