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