SkCodec.h revision 97ff7f56620a50e83e433b158a86ff082935ed47
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 "SkEncodedFormat.h" 14#include "SkImageInfo.h" 15#include "SkSize.h" 16#include "SkStream.h" 17#include "SkTypes.h" 18 19class SkData; 20class SkPngChunkReader; 21class SkSampler; 22 23/** 24 * Abstraction layer directly on top of an image codec. 25 */ 26class SkCodec : SkNoncopyable { 27public: 28 /** 29 * If this stream represents an encoded image that we know how to decode, 30 * return an SkCodec that can decode it. Otherwise return NULL. 31 * 32 * If the SkPngChunkReader is not NULL then: 33 * If the image is not a PNG, the SkPngChunkReader will be ignored. 34 * If the image is a PNG, the SkPngChunkReader will be reffed. 35 * If the PNG has unknown chunks, the SkPngChunkReader will be used 36 * to handle these chunks. SkPngChunkReader will be called to read 37 * any unknown chunk at any point during the creation of the codec 38 * or the decode. Note that if SkPngChunkReader fails to read a 39 * chunk, this could result in a failure to create the codec or a 40 * failure to decode the image. 41 * If the PNG does not contain unknown chunks, the SkPngChunkReader 42 * will not be used or modified. 43 * 44 * If NULL is returned, the stream is deleted immediately. Otherwise, the 45 * SkCodec takes ownership of it, and will delete it when done with it. 46 */ 47 static SkCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL); 48 49 /** 50 * If this data represents an encoded image that we know how to decode, 51 * return an SkCodec that can decode it. Otherwise return NULL. 52 * 53 * If the SkPngChunkReader is not NULL then: 54 * If the image is not a PNG, the SkPngChunkReader will be ignored. 55 * If the image is a PNG, the SkPngChunkReader will be reffed. 56 * If the PNG has unknown chunks, the SkPngChunkReader will be used 57 * to handle these chunks. SkPngChunkReader will be called to read 58 * any unknown chunk at any point during the creation of the codec 59 * or the decode. Note that if SkPngChunkReader fails to read a 60 * chunk, this could result in a failure to create the codec or a 61 * failure to decode the image. 62 * If the PNG does not contain unknown chunks, the SkPngChunkReader 63 * will not be used or modified. 64 * 65 * Will take a ref if it returns a codec, else will not affect the data. 66 */ 67 static SkCodec* NewFromData(SkData*, SkPngChunkReader* = NULL); 68 69 virtual ~SkCodec(); 70 71 /** 72 * Return the ImageInfo associated with this codec. 73 */ 74 const SkImageInfo& getInfo() const { return fSrcInfo; } 75 76 /** 77 * Return a size that approximately supports the desired scale factor. 78 * The codec may not be able to scale efficiently to the exact scale 79 * factor requested, so return a size that approximates that scale. 80 * The returned value is the codec's suggestion for the closest valid 81 * scale that it can natively support 82 */ 83 SkISize getScaledDimensions(float desiredScale) const { 84 // Negative and zero scales are errors. 85 SkASSERT(desiredScale > 0.0f); 86 if (desiredScale <= 0.0f) { 87 return SkISize::Make(0, 0); 88 } 89 90 // Upscaling is not supported. Return the original size if the client 91 // requests an upscale. 92 if (desiredScale >= 1.0f) { 93 return this->getInfo().dimensions(); 94 } 95 return this->onGetScaledDimensions(desiredScale); 96 } 97 98 /** 99 * Return (via desiredSubset) a subset which can decoded from this codec, 100 * or false if this codec cannot decode subsets or anything similar to 101 * desiredSubset. 102 * 103 * @param desiredSubset In/out parameter. As input, a desired subset of 104 * the original bounds (as specified by getInfo). If true is returned, 105 * desiredSubset may have been modified to a subset which is 106 * supported. Although a particular change may have been made to 107 * desiredSubset to create something supported, it is possible other 108 * changes could result in a valid subset. 109 * If false is returned, desiredSubset's value is undefined. 110 * @return true if this codec supports decoding desiredSubset (as 111 * returned, potentially modified) 112 */ 113 bool getValidSubset(SkIRect* desiredSubset) const { 114 return this->onGetValidSubset(desiredSubset); 115 } 116 117 /** 118 * Format of the encoded data. 119 */ 120 SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); } 121 122 /** 123 * Used to describe the result of a call to getPixels(). 124 * 125 * Result is the union of possible results from subclasses. 126 */ 127 enum Result { 128 /** 129 * General return value for success. 130 */ 131 kSuccess, 132 /** 133 * The input is incomplete. A partial image was generated. 134 */ 135 kIncompleteInput, 136 /** 137 * The generator cannot convert to match the request, ignoring 138 * dimensions. 139 */ 140 kInvalidConversion, 141 /** 142 * The generator cannot scale to requested size. 143 */ 144 kInvalidScale, 145 /** 146 * Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes 147 * too small, etc. 148 */ 149 kInvalidParameters, 150 /** 151 * The input did not contain a valid image. 152 */ 153 kInvalidInput, 154 /** 155 * Fulfilling this request requires rewinding the input, which is not 156 * supported for this input. 157 */ 158 kCouldNotRewind, 159 /** 160 * This method is not implemented by this codec. 161 * FIXME: Perhaps this should be kUnsupported? 162 */ 163 kUnimplemented, 164 }; 165 166 /** 167 * Whether or not the memory passed to getPixels is zero initialized. 168 */ 169 enum ZeroInitialized { 170 /** 171 * The memory passed to getPixels is zero initialized. The SkCodec 172 * may take advantage of this by skipping writing zeroes. 173 */ 174 kYes_ZeroInitialized, 175 /** 176 * The memory passed to getPixels has not been initialized to zero, 177 * so the SkCodec must write all zeroes to memory. 178 * 179 * This is the default. It will be used if no Options struct is used. 180 */ 181 kNo_ZeroInitialized, 182 }; 183 184 /** 185 * Additional options to pass to getPixels. 186 */ 187 struct Options { 188 Options() 189 : fZeroInitialized(kNo_ZeroInitialized) 190 , fSubset(NULL) 191 {} 192 193 ZeroInitialized fZeroInitialized; 194 /** 195 * If not NULL, represents a subset of the original image to decode. 196 * Must be within the bounds returned by getInfo(). 197 * If the EncodedFormat is kWEBP_SkEncodedFormat (the only one which 198 * currently supports subsets), the top and left values must be even. 199 * 200 * In getPixels, we will attempt to decode the exact rectangular 201 * subset specified by fSubset. 202 * 203 * In a scanline decode, it does not make sense to specify a subset 204 * top or subset height, since the client already controls which rows 205 * to get and which rows to skip. During scanline decodes, we will 206 * require that the subset top be zero and the subset height be equal 207 * to the full height. We will, however, use the values of 208 * subset left and subset width to decode partial scanlines on calls 209 * to getScanlines(). 210 */ 211 SkIRect* fSubset; 212 }; 213 214 /** 215 * Decode into the given pixels, a block of memory of size at 216 * least (info.fHeight - 1) * rowBytes + (info.fWidth * 217 * bytesPerPixel) 218 * 219 * Repeated calls to this function should give the same results, 220 * allowing the PixelRef to be immutable. 221 * 222 * @param info A description of the format (config, size) 223 * expected by the caller. This can simply be identical 224 * to the info returned by getInfo(). 225 * 226 * This contract also allows the caller to specify 227 * different output-configs, which the implementation can 228 * decide to support or not. 229 * 230 * A size that does not match getInfo() implies a request 231 * to scale. If the generator cannot perform this scale, 232 * it will return kInvalidScale. 233 * 234 * If info is kIndex8_SkColorType, then the caller must provide storage for up to 256 235 * SkPMColor values in ctable. On success the generator must copy N colors into that storage, 236 * (where N is the logical number of table entries) and set ctableCount to N. 237 * 238 * If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount 239 * is not null, it will be set to 0. 240 * 241 * If a scanline decode is in progress, scanline mode will end, requiring the client to call 242 * startScanlineDecode() in order to return to decoding scanlines. 243 * 244 * @return Result kSuccess, or another value explaining the type of failure. 245 */ 246 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*, 247 SkPMColor ctable[], int* ctableCount); 248 249 /** 250 * Simplified version of getPixels() that asserts that info is NOT kIndex8_SkColorType and 251 * uses the default Options. 252 */ 253 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes); 254 255 /** 256 * Some images may initially report that they have alpha due to the format 257 * of the encoded data, but then never use any colors which have alpha 258 * less than 100%. This function can be called *after* decoding to 259 * determine if such an image truly had alpha. Calling it before decoding 260 * is undefined. 261 * FIXME: see skbug.com/3582. 262 */ 263 bool reallyHasAlpha() const { 264 return this->onReallyHasAlpha(); 265 } 266 267 /** 268 * The remaining functions revolve around decoding scanlines. 269 */ 270 271 /** 272 * Prepare for a scanline decode with the specified options. 273 * 274 * After this call, this class will be ready to decode the first scanline. 275 * 276 * This must be called in order to call getScanlines or skipScanlines. 277 * 278 * This may require rewinding the stream. 279 * 280 * Not all SkCodecs support this. 281 * 282 * @param dstInfo Info of the destination. If the dimensions do not match 283 * those of getInfo, this implies a scale. 284 * @param options Contains decoding options, including if memory is zero 285 * initialized. 286 * @param ctable A pointer to a color table. When dstInfo.colorType() is 287 * kIndex8, this should be non-NULL and have enough storage for 256 288 * colors. The color table will be populated after decoding the palette. 289 * @param ctableCount A pointer to the size of the color table. When 290 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will 291 * be modified to the true size of the color table (<= 256) after 292 * decoding the palette. 293 * @return Enum representing success or reason for failure. 294 */ 295 Result startScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options* options, 296 SkPMColor ctable[], int* ctableCount); 297 298 /** 299 * Simplified version of startScanlineDecode() that asserts that info is NOT 300 * kIndex8_SkColorType and uses the default Options. 301 */ 302 Result startScanlineDecode(const SkImageInfo& dstInfo); 303 304 /** 305 * Write the next countLines scanlines into dst. 306 * 307 * Not valid to call before calling startScanlineDecode(). 308 * 309 * @param dst Must be non-null, and large enough to hold countLines 310 * scanlines of size rowBytes. 311 * @param countLines Number of lines to write. 312 * @param rowBytes Number of bytes per row. Must be large enough to hold 313 * a scanline based on the SkImageInfo used to create this object. 314 * @return the number of lines successfully decoded. If this value is 315 * less than countLines, this will fill the remaining lines with a 316 * default value. 317 */ 318 int getScanlines(void* dst, int countLines, size_t rowBytes); 319 320 /** 321 * Skip count scanlines. 322 * 323 * Not valid to call before calling startScanlineDecode(). 324 * 325 * The default version just calls onGetScanlines and discards the dst. 326 * NOTE: If skipped lines are the only lines with alpha, this default 327 * will make reallyHasAlpha return true, when it could have returned 328 * false. 329 * 330 * @return true if the scanlines were successfully skipped 331 * false on failure, possible reasons for failure include: 332 * An incomplete input image stream. 333 * Calling this function before calling startScanlineDecode(). 334 * If countLines is less than zero or so large that it moves 335 * the current scanline past the end of the image. 336 */ 337 bool skipScanlines(int countLines); 338 339 /** 340 * The order in which rows are output from the scanline decoder is not the 341 * same for all variations of all image types. This explains the possible 342 * output row orderings. 343 */ 344 enum SkScanlineOrder { 345 /* 346 * By far the most common, this indicates that the image can be decoded 347 * reliably using the scanline decoder, and that rows will be output in 348 * the logical order. 349 */ 350 kTopDown_SkScanlineOrder, 351 352 /* 353 * This indicates that the scanline decoder reliably outputs rows, but 354 * they will be returned in reverse order. If the scanline format is 355 * kBottomUp, the nextScanline() API can be used to determine the actual 356 * y-coordinate of the next output row, but the client is not forced 357 * to take advantage of this, given that it's not too tough to keep 358 * track independently. 359 * 360 * For full image decodes, it is safe to get all of the scanlines at 361 * once, since the decoder will handle inverting the rows as it 362 * decodes. 363 * 364 * For subset decodes and sampling, it is simplest to get and skip 365 * scanlines one at a time, using the nextScanline() API. It is 366 * possible to ask for larger chunks at a time, but this should be used 367 * with caution. As with full image decodes, the decoder will handle 368 * inverting the requested rows, but rows will still be delivered 369 * starting from the bottom of the image. 370 * 371 * Upside down bmps are an example. 372 */ 373 kBottomUp_SkScanlineOrder, 374 375 /* 376 * This indicates that the scanline decoder reliably outputs rows, but 377 * they will not be in logical order. If the scanline format is 378 * kOutOfOrder, the nextScanline() API should be used to determine the 379 * actual y-coordinate of the next output row. 380 * 381 * For this scanline ordering, it is advisable to get and skip 382 * scanlines one at a time. 383 * 384 * Interlaced gifs are an example. 385 */ 386 kOutOfOrder_SkScanlineOrder, 387 388 /* 389 * Indicates that the entire image must be decoded in order to output 390 * any amount of scanlines. In this case, it is a REALLY BAD IDEA to 391 * request scanlines 1-by-1 or in small chunks. The client should 392 * determine which scanlines are needed and ask for all of them in 393 * a single call to getScanlines(). 394 * 395 * Interlaced pngs are an example. 396 */ 397 kNone_SkScanlineOrder, 398 }; 399 400 /** 401 * An enum representing the order in which scanlines will be returned by 402 * the scanline decoder. 403 */ 404 SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); } 405 406 /** 407 * Returns the y-coordinate of the next row to be returned by the scanline 408 * decoder. 409 * 410 * This will equal fCurrScanline, except in the case of strangely 411 * encoded image types (bottom-up bmps, interlaced gifs). 412 * 413 * Results are undefined when not in scanline decoding mode. 414 */ 415 int nextScanline() const { return this->outputScanline(fCurrScanline); } 416 417 /** 418 * Returns the output y-coordinate of the row that corresponds to an input 419 * y-coordinate. The input y-coordinate represents where the scanline 420 * is located in the encoded data. 421 * 422 * This will equal inputScanline, except in the case of strangely 423 * encoded image types (bottom-up bmps, interlaced gifs). 424 */ 425 int outputScanline(int inputScanline) const; 426 427protected: 428 SkCodec(const SkImageInfo&, SkStream*); 429 430 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { 431 // By default, scaling is not supported. 432 return this->getInfo().dimensions(); 433 } 434 435 // FIXME: What to do about subsets?? 436 /** 437 * Subclasses should override if they support dimensions other than the 438 * srcInfo's. 439 */ 440 virtual bool onDimensionsSupported(const SkISize&) { 441 return false; 442 } 443 444 virtual SkEncodedFormat onGetEncodedFormat() const = 0; 445 446 /** 447 * @param rowsDecoded When the encoded image stream is incomplete, this function 448 * will return kIncompleteInput and rowsDecoded will be set to 449 * the number of scanlines that were successfully decoded. 450 * This will allow getPixels() to fill the uninitialized memory. 451 */ 452 virtual Result onGetPixels(const SkImageInfo& info, 453 void* pixels, size_t rowBytes, const Options&, 454 SkPMColor ctable[], int* ctableCount, 455 int* rowsDecoded) = 0; 456 457 virtual bool onGetValidSubset(SkIRect* /* desiredSubset */) const { 458 // By default, subsets are not supported. 459 return false; 460 } 461 462 virtual bool onReallyHasAlpha() const { return false; } 463 464 /** 465 * If the stream was previously read, attempt to rewind. 466 * 467 * If the stream needed to be rewound, call onRewind. 468 * @returns true if the codec is at the right position and can be used. 469 * false if there was a failure to rewind. 470 * 471 * This is called by getPixels() and start(). Subclasses may call if they 472 * need to rewind at another time. 473 */ 474 bool SK_WARN_UNUSED_RESULT rewindIfNeeded(); 475 476 /** 477 * Called by rewindIfNeeded, if the stream needed to be rewound. 478 * 479 * Subclasses should do any set up needed after a rewind. 480 */ 481 virtual bool onRewind() { 482 return true; 483 } 484 485 /** 486 * On an incomplete input, getPixels() and getScanlines() will fill any uninitialized 487 * scanlines. This allows the subclass to indicate what value to fill with. 488 * 489 * @param colorType Destination color type. 490 * @param alphaType Destination alpha type. 491 * @return The value with which to fill uninitialized pixels. 492 * 493 * Note that we can interpret the return value as an SkPMColor, a 16-bit 565 color, 494 * an 8-bit gray color, or an 8-bit index into a color table, depending on the color 495 * type. 496 */ 497 uint32_t getFillValue(SkColorType colorType, SkAlphaType alphaType) const { 498 return this->onGetFillValue(colorType, alphaType); 499 } 500 501 /** 502 * Some subclasses will override this function, but this is a useful default for the color 503 * types that we support. Note that for color types that do not use the full 32-bits, 504 * we will simply take the low bits of the fill value. 505 * 506 * kN32_SkColorType: Transparent or Black 507 * kRGB_565_SkColorType: Black 508 * kGray_8_SkColorType: Black 509 * kIndex_8_SkColorType: First color in color table 510 */ 511 virtual uint32_t onGetFillValue(SkColorType /*colorType*/, SkAlphaType alphaType) const { 512 return kOpaque_SkAlphaType == alphaType ? SK_ColorBLACK : SK_ColorTRANSPARENT; 513 } 514 515 /** 516 * Get method for the input stream 517 */ 518 SkStream* stream() { 519 return fStream.get(); 520 } 521 522 /** 523 * The remaining functions revolve around decoding scanlines. 524 */ 525 526 /** 527 * Most images types will be kTopDown and will not need to override this function. 528 */ 529 virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; } 530 531 /** 532 * Update the current scanline. Used by interlaced png. 533 */ 534 void updateCurrScanline(int newY) { fCurrScanline = newY; } 535 536 const SkImageInfo& dstInfo() const { return fDstInfo; } 537 538 const SkCodec::Options& options() const { return fOptions; } 539 540 /** 541 * Returns the number of scanlines that have been decoded so far. 542 * This is unaffected by the SkScanlineOrder. 543 * 544 * Returns -1 if we have not started a scanline decode. 545 */ 546 int currScanline() const { return fCurrScanline; } 547 548 virtual int onOutputScanline(int inputScanline) const; 549 550private: 551 const SkImageInfo fSrcInfo; 552 SkAutoTDelete<SkStream> fStream; 553 bool fNeedsRewind; 554 // These fields are only meaningful during scanline decodes. 555 SkImageInfo fDstInfo; 556 SkCodec::Options fOptions; 557 int fCurrScanline; 558 559 /** 560 * Return whether these dimensions are supported as a scale. 561 * 562 * The codec may choose to cache the information about scale and subset. 563 * Either way, the same information will be passed to onGetPixels/onStart 564 * on success. 565 * 566 * This must return true for a size returned from getScaledDimensions. 567 */ 568 bool dimensionsSupported(const SkISize& dim) { 569 return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim); 570 } 571 572 // Methods for scanline decoding. 573 virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/, 574 const SkCodec::Options& /*options*/, SkPMColor* /*ctable*/, int* /*ctableCount*/) { 575 return kUnimplemented; 576 } 577 578 // Naive default version just calls onGetScanlines on temp memory. 579 virtual bool onSkipScanlines(int countLines) { 580 // FIXME (msarett): Make this a pure virtual and always override this. 581 SkAutoMalloc storage(fDstInfo.minRowBytes()); 582 583 // Note that we pass 0 to rowBytes so we continue to use the same memory. 584 // Also note that while getScanlines checks that rowBytes is big enough, 585 // onGetScanlines bypasses that check. 586 // Calling the virtual method also means we do not double count 587 // countLines. 588 return countLines == this->onGetScanlines(storage.get(), countLines, 0); 589 } 590 591 virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; } 592 593 /** 594 * On an incomplete decode, getPixels() and getScanlines() will call this function 595 * to fill any uinitialized memory. 596 * 597 * @param dstInfo Contains the destination color type 598 * Contains the destination alpha type 599 * Contains the destination width 600 * The height stored in this info is unused 601 * @param dst Pointer to the start of destination pixel memory 602 * @param rowBytes Stride length in destination pixel memory 603 * @param zeroInit Indicates if memory is zero initialized 604 * @param linesRequested Number of lines that the client requested 605 * @param linesDecoded Number of lines that were successfully decoded 606 */ 607 void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, 608 ZeroInitialized zeroInit, int linesRequested, int linesDecoded); 609 610 /** 611 * Return an object which will allow forcing scanline decodes to sample in X. 612 * 613 * May create a sampler, if one is not currently being used. Otherwise, does 614 * not affect ownership. 615 * 616 * Only valid during scanline decoding. 617 */ 618 virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; } 619 620 friend class SkSampledCodec; 621}; 622#endif // SkCodec_DEFINED 623