Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef SkCodec_DEFINED | 8 #ifndef SkCodec_DEFINED |
| 9 #define SkCodec_DEFINED | 9 #define SkCodec_DEFINED |
| 10 | 10 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 38 * | 38 * |
| 39 * Will take a ref if it returns a codec, else will not affect the data. | 39 * Will take a ref if it returns a codec, else will not affect the data. |
| 40 */ | 40 */ |
| 41 static SkCodec* NewFromData(SkData*); | 41 static SkCodec* NewFromData(SkData*); |
| 42 | 42 |
| 43 virtual ~SkCodec(); | 43 virtual ~SkCodec(); |
| 44 | 44 |
| 45 /** | 45 /** |
| 46 * Return the ImageInfo associated with this codec. | 46 * Return the ImageInfo associated with this codec. |
| 47 */ | 47 */ |
| 48 const SkImageInfo& getInfo() const { return fInfo; } | 48 const SkImageInfo& getInfo() const { return fSrcInfo; } |
| 49 | 49 |
| 50 /** | 50 /** |
| 51 * Return a size that approximately supports the desired scale factor. | 51 * Return a size that approximately supports the desired scale factor. |
| 52 * The codec may not be able to scale efficiently to the exact scale | 52 * The codec may not be able to scale efficiently to the exact scale |
| 53 * factor requested, so return a size that approximates that scale. | 53 * factor requested, so return a size that approximates that scale. |
| 54 * The returned value is the codec's suggestion for the closest valid | 54 * The returned value is the codec's suggestion for the closest valid |
| 55 * scale that it can natively support | 55 * scale that it can natively support |
| 56 */ | 56 */ |
| 57 SkISize getScaledDimensions(float desiredScale) const { | 57 SkISize getScaledDimensions(float desiredScale) const { |
| 58 // Negative and zero scales are errors. | 58 // Negative and zero scales are errors. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 /** | 124 /** |
| 125 * The input did not contain a valid image. | 125 * The input did not contain a valid image. |
| 126 */ | 126 */ |
| 127 kInvalidInput, | 127 kInvalidInput, |
| 128 /** | 128 /** |
| 129 * Fulfilling this request requires rewinding the input, which is not | 129 * Fulfilling this request requires rewinding the input, which is not |
| 130 * supported for this input. | 130 * supported for this input. |
| 131 */ | 131 */ |
| 132 kCouldNotRewind, | 132 kCouldNotRewind, |
| 133 /** | 133 /** |
| 134 * This method is not implemented by this generator. | 134 * This method is not implemented by this codec. |
| 135 * FIXME: Perhaps this should be kUnsupported? | |
| 135 */ | 136 */ |
| 136 kUnimplemented, | 137 kUnimplemented, |
| 138 /** | |
| 139 * start() was not called before calling getScanlines. | |
| 140 */ | |
| 141 kScanlineDecodingNotStarted, | |
|
djsollen
2015/09/29 20:22:17
move this above unimplemented.
scroggo
2015/09/30 13:32:20
Done.
| |
| 137 }; | 142 }; |
| 138 | 143 |
| 139 /** | 144 /** |
| 140 * Whether or not the memory passed to getPixels is zero initialized. | 145 * Whether or not the memory passed to getPixels is zero initialized. |
| 141 */ | 146 */ |
| 142 enum ZeroInitialized { | 147 enum ZeroInitialized { |
| 143 /** | 148 /** |
| 144 * The memory passed to getPixels is zero initialized. The SkCodec | 149 * The memory passed to getPixels is zero initialized. The SkCodec |
| 145 * may take advantage of this by skipping writing zeroes. | 150 * may take advantage of this by skipping writing zeroes. |
| 146 */ | 151 */ |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 195 * to scale. If the generator cannot perform this scale, | 200 * to scale. If the generator cannot perform this scale, |
| 196 * it will return kInvalidScale. | 201 * it will return kInvalidScale. |
| 197 * | 202 * |
| 198 * If info is kIndex8_SkColorType, then the caller must provide storage for up to 256 | 203 * If info is kIndex8_SkColorType, then the caller must provide storage for up to 256 |
| 199 * SkPMColor values in ctable. On success the generator must copy N colors into that storage, | 204 * SkPMColor values in ctable. On success the generator must copy N colors into that storage, |
| 200 * (where N is the logical number of table entries) and set ctableCount to N. | 205 * (where N is the logical number of table entries) and set ctableCount to N. |
| 201 * | 206 * |
| 202 * If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount | 207 * If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount |
| 203 * is not null, it will be set to 0. | 208 * is not null, it will be set to 0. |
| 204 * | 209 * |
| 210 * If a scanline decode is in progress, scanline mode will end, requiring t he client to call | |
| 211 * start() in order to return to decoding scanlines. | |
| 212 * | |
| 205 * @return Result kSuccess, or another value explaining the type of failure . | 213 * @return Result kSuccess, or another value explaining the type of failure . |
| 206 */ | 214 */ |
| 207 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, con st Options*, | 215 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, con st Options*, |
| 208 SkPMColor ctable[], int* ctableCount); | 216 SkPMColor ctable[], int* ctableCount); |
| 209 | 217 |
| 210 /** | 218 /** |
| 211 * Simplified version of getPixels() that asserts that info is NOT kIndex8_ SkColorType and | 219 * Simplified version of getPixels() that asserts that info is NOT kIndex8_ SkColorType and |
| 212 * uses the default Options. | 220 * uses the default Options. |
| 213 */ | 221 */ |
| 214 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes); | 222 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes); |
| 215 | 223 |
| 216 /** | 224 /** |
| 217 * Some images may initially report that they have alpha due to the format | 225 * Some images may initially report that they have alpha due to the format |
| 218 * of the encoded data, but then never use any colors which have alpha | 226 * of the encoded data, but then never use any colors which have alpha |
| 219 * less than 100%. This function can be called *after* decoding to | 227 * less than 100%. This function can be called *after* decoding to |
| 220 * determine if such an image truly had alpha. Calling it before decoding | 228 * determine if such an image truly had alpha. Calling it before decoding |
| 221 * is undefined. | 229 * is undefined. |
| 222 * FIXME: see skbug.com/3582. | 230 * FIXME: see skbug.com/3582. |
| 223 */ | 231 */ |
| 224 bool reallyHasAlpha() const { | 232 bool reallyHasAlpha() const { |
| 225 return this->onReallyHasAlpha(); | 233 return this->onReallyHasAlpha(); |
| 226 } | 234 } |
| 227 | 235 |
| 236 /** | |
| 237 * The remaining functions revolve around decoding scanlines. | |
| 238 */ | |
| 239 | |
| 240 /** | |
| 241 * Prepare for a scanline decode with the specified options. | |
| 242 * | |
| 243 * After this call, this class will be ready to decode the first scanline. | |
| 244 * | |
| 245 * This must be called in order to call getScanlines or skipScanlines. | |
| 246 * | |
| 247 * This may require rewinding the stream. | |
| 248 * | |
| 249 * Not all SkCodecs support this. | |
| 250 * | |
| 251 * @param dstInfo Info of the destination. If the dimensions do not match | |
| 252 * those of getInfo, this implies a scale. | |
| 253 * @param options Contains decoding options, including if memory is zero | |
| 254 * initialized. | |
| 255 * @param ctable A pointer to a color table. When dstInfo.colorType() is | |
| 256 * kIndex8, this should be non-NULL and have enough storage for 256 | |
| 257 * colors. The color table will be populated after decoding the palett e. | |
| 258 * @param ctableCount A pointer to the size of the color table. When | |
| 259 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will | |
| 260 * be modified to the true size of the color table (<= 256) after | |
| 261 * decoding the palette. | |
| 262 * @return Enum representing success or reason for failure. | |
| 263 */ | |
| 264 Result start(const SkImageInfo& dstInfo, const SkCodec::Options* options, | |
|
djsollen
2015/09/29 20:22:17
now that this is no longer part of a scanline clas
scroggo
2015/09/30 13:32:20
Matt included the same name in his suggestions. Do
| |
| 265 SkPMColor ctable[], int* ctableCount); | |
| 266 | |
| 267 /** | |
| 268 * Simplified version of start() that asserts that info is NOT | |
| 269 * kIndex8_SkColorType and uses the default Options. | |
| 270 */ | |
| 271 Result start(const SkImageInfo& dstInfo); | |
| 272 | |
| 273 /** | |
| 274 * Write the next countLines scanlines into dst. | |
| 275 * | |
| 276 * Not valid to call before calling start(). | |
| 277 * | |
| 278 * @param dst Must be non-null, and large enough to hold countLines | |
| 279 * scanlines of size rowBytes. | |
| 280 * @param countLines Number of lines to write. | |
| 281 * @param rowBytes Number of bytes per row. Must be large enough to hold | |
| 282 * a scanline based on the SkImageInfo used to create this object. | |
| 283 */ | |
| 284 Result getScanlines(void* dst, int countLines, size_t rowBytes) { | |
|
djsollen
2015/09/29 20:22:17
any reason not to move this to the cpp file since
scroggo
2015/09/30 13:32:20
Done. I also moved skipScanlines into cpp
| |
| 285 if (fCurrScanline < 0) { | |
| 286 return kScanlineDecodingNotStarted; | |
| 287 } | |
| 288 | |
| 289 SkASSERT(!fDstInfo.isEmpty()); | |
| 290 if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0 | |
| 291 || fCurrScanline + countLines > fDstInfo.height()) { | |
| 292 return kInvalidParameters; | |
| 293 } | |
| 294 const Result result = this->onGetScanlines(dst, countLines, rowBytes); | |
| 295 fCurrScanline += countLines; | |
| 296 return result; | |
| 297 } | |
| 298 | |
| 299 /** | |
| 300 * Skip count scanlines. | |
| 301 * | |
| 302 * Not valid to call before calling start(). | |
| 303 * | |
| 304 * The default version just calls onGetScanlines and discards the dst. | |
| 305 * NOTE: If skipped lines are the only lines with alpha, this default | |
| 306 * will make reallyHasAlpha return true, when it could have returned | |
| 307 * false. | |
| 308 */ | |
| 309 Result skipScanlines(int countLines) { | |
| 310 if (fCurrScanline < 0) { | |
| 311 return kScanlineDecodingNotStarted; | |
| 312 } | |
| 313 SkASSERT(!fDstInfo.isEmpty()); | |
| 314 if (fCurrScanline + countLines > fDstInfo.height()) { | |
| 315 // Arguably, we could just skip the scanlines which are remaining, | |
| 316 // and return kSuccess. We choose to return invalid so the client | |
| 317 // can catch their bug. | |
| 318 return SkCodec::kInvalidParameters; | |
| 319 } | |
| 320 const Result result = this->onSkipScanlines(countLines); | |
| 321 fCurrScanline += countLines; | |
| 322 return result; | |
| 323 } | |
| 324 | |
| 325 /** | |
| 326 * The order in which rows are output from the scanline decoder is not the | |
| 327 * same for all variations of all image types. This explains the possible | |
| 328 * output row orderings. | |
| 329 */ | |
| 330 enum SkScanlineOrder { | |
| 331 /* | |
| 332 * By far the most common, this indicates that the image can be decoded | |
| 333 * reliably using the scanline decoder, and that rows will be output in | |
| 334 * the logical order. | |
| 335 */ | |
| 336 kTopDown_SkScanlineOrder, | |
| 337 | |
| 338 /* | |
| 339 * This indicates that the scanline decoder reliably outputs rows, but | |
| 340 * they will be returned in reverse order. If the scanline format is | |
| 341 * kBottomUp, the getY() API can be used to determine the actual | |
| 342 * y-coordinate of the next output row, but the client is not forced | |
| 343 * to take advantage of this, given that it's not too tough to keep | |
| 344 * track independently. | |
| 345 * | |
| 346 * For full image decodes, it is safe to get all of the scanlines at | |
| 347 * once, since the decoder will handle inverting the rows as it | |
| 348 * decodes. | |
| 349 * | |
| 350 * For subset decodes and sampling, it is simplest to get and skip | |
| 351 * scanlines one at a time, using the getY() API. It is possible to | |
| 352 * ask for larger chunks at a time, but this should be used with | |
| 353 * caution. As with full image decodes, the decoder will handle | |
| 354 * inverting the requested rows, but rows will still be delivered | |
| 355 * starting from the bottom of the image. | |
| 356 * | |
| 357 * Upside down bmps are an example. | |
| 358 */ | |
| 359 kBottomUp_SkScanlineOrder, | |
| 360 | |
| 361 /* | |
| 362 * This indicates that the scanline decoder reliably outputs rows, but | |
| 363 * they will not be in logical order. If the scanline format is | |
| 364 * kOutOfOrder, the getY() API should be used to determine the actual | |
| 365 * y-coordinate of the next output row. | |
| 366 * | |
| 367 * For this scanline ordering, it is advisable to get and skip | |
| 368 * scanlines one at a time. | |
| 369 * | |
| 370 * Interlaced gifs are an example. | |
| 371 */ | |
| 372 kOutOfOrder_SkScanlineOrder, | |
| 373 | |
| 374 /* | |
| 375 * Indicates that the entire image must be decoded in order to output | |
| 376 * any amount of scanlines. In this case, it is a REALLY BAD IDEA to | |
| 377 * request scanlines 1-by-1 or in small chunks. The client should | |
| 378 * determine which scanlines are needed and ask for all of them in | |
| 379 * a single call to getScanlines(). | |
| 380 * | |
| 381 * Interlaced pngs are an example. | |
| 382 */ | |
| 383 kNone_SkScanlineOrder, | |
| 384 }; | |
| 385 | |
| 386 /** | |
| 387 * An enum representing the order in which scanlines will be returned by | |
| 388 * the scanline decoder. | |
| 389 */ | |
| 390 SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder() ; } | |
| 391 | |
| 392 /** | |
| 393 * Returns the y-coordinate of the next row to be returned by the scanline | |
| 394 * decoder. This will be overridden in the case of | |
| 395 * kOutOfOrder_SkScanlineOrder and should be unnecessary in the case of | |
| 396 * kNone_SkScanlineOrder. | |
| 397 * | |
| 398 * Results are undefined when not in scanline decoding mode. | |
| 399 * | |
| 400 * FIXME: Rename to nextScanline()? | |
|
djsollen
2015/09/29 20:22:17
I agree that this should be renamed
scroggo
2015/09/30 13:32:20
Renamed to nextScanline().
I also renamed updateY
| |
| 401 */ | |
| 402 int getY() const { | |
| 403 return this->onGetY(); | |
| 404 } | |
| 405 | |
| 228 protected: | 406 protected: |
| 229 SkCodec(const SkImageInfo&, SkStream*); | 407 SkCodec(const SkImageInfo&, SkStream*); |
| 230 | 408 |
| 231 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { | 409 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { |
| 232 // By default, scaling is not supported. | 410 // By default, scaling is not supported. |
| 233 return this->getInfo().dimensions(); | 411 return this->getInfo().dimensions(); |
| 234 } | 412 } |
| 235 | 413 |
| 236 virtual SkEncodedFormat onGetEncodedFormat() const = 0; | 414 virtual SkEncodedFormat onGetEncodedFormat() const = 0; |
| 237 | 415 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 268 return true; | 446 return true; |
| 269 } | 447 } |
| 270 | 448 |
| 271 /** | 449 /** |
| 272 * Get method for the input stream | 450 * Get method for the input stream |
| 273 */ | 451 */ |
| 274 SkStream* stream() { | 452 SkStream* stream() { |
| 275 return fStream.get(); | 453 return fStream.get(); |
| 276 } | 454 } |
| 277 | 455 |
| 456 /** | |
| 457 * The remaining functions revolve around decoding scanlines. | |
| 458 */ | |
| 459 | |
| 460 /** | |
| 461 * Most images types will be kTopDown and will not need to override this fu nction. | |
| 462 */ | |
| 463 virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanl ineOrder; } | |
| 464 | |
| 465 /** | |
| 466 * Most images will be kTopDown and will not need to override this function . | |
| 467 */ | |
| 468 virtual int onGetY() const { return fCurrScanline; } | |
| 469 | |
| 470 /** | |
| 471 * Update the next scanline. Used by interlaced png. | |
| 472 */ | |
| 473 void updateY(int newY) { fCurrScanline = newY; } | |
| 474 | |
| 475 const SkImageInfo& dstInfo() const { return fDstInfo; } | |
| 476 | |
| 477 const SkCodec::Options& options() const { return fOptions; } | |
| 478 | |
| 278 private: | 479 private: |
| 279 const SkImageInfo fInfo; | 480 const SkImageInfo fSrcInfo; |
| 280 SkAutoTDelete<SkStream> fStream; | 481 SkAutoTDelete<SkStream> fStream; |
| 281 bool fNeedsRewind; | 482 bool fNeedsRewind; |
| 483 // These fields are only meaningful during scanline decodes. | |
| 484 SkImageInfo fDstInfo; | |
| 485 SkCodec::Options fOptions; | |
| 486 int fCurrScanline; | |
| 487 | |
| 488 // Methods for scanline decoding. | |
| 489 virtual SkCodec::Result onStart(const SkImageInfo& dstInfo, | |
| 490 const SkCodec::Options& options, | |
| 491 SkPMColor ctable[], int* ctableCount) { | |
| 492 return kUnimplemented; | |
| 493 } | |
| 494 | |
| 495 // Naive default version just calls onGetScanlines on temp memory. | |
| 496 virtual SkCodec::Result onSkipScanlines(int countLines) { | |
| 497 SkAutoMalloc storage(fDstInfo.minRowBytes()); | |
| 498 // Note that we pass 0 to rowBytes so we continue to use the same memory . | |
| 499 // Also note that while getScanlines checks that rowBytes is big enough, | |
| 500 // onGetScanlines bypasses that check. | |
| 501 // Calling the virtual method also means we do not double count | |
| 502 // countLines. | |
| 503 return this->onGetScanlines(storage.get(), countLines, 0); | |
| 504 } | |
| 505 | |
| 506 virtual SkCodec::Result onGetScanlines(void* dst, int countLines, | |
| 507 size_t rowBytes) { | |
| 508 return kUnimplemented; | |
| 509 } | |
| 510 | |
| 282 }; | 511 }; |
| 283 #endif // SkCodec_DEFINED | 512 #endif // SkCodec_DEFINED |
| OLD | NEW |