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