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, | |
| 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 * Initialize on the first scanline, with the specified options. | |
|
msarett
2015/09/28 14:48:50
"Initialize on the first scanline" is a little unc
scroggo
2015/09/28 16:01:52
Sgtm. I think it made a little more sense back whe
| |
| 242 * | |
| 243 * This must be called in order to call getScanlines or skipScanlines. | |
| 244 * | |
| 245 * This may require rewinding the stream. | |
| 246 * | |
| 247 * Not all SkCodecs support this. | |
| 248 * | |
| 249 * @param dstInfo Info of the destination. If the dimensions do not match | |
| 250 * those of getInfo, this implies a scale. | |
| 251 * @param options Contains decoding options, including if memory is zero | |
| 252 * initialized. | |
| 253 * @param ctable A pointer to a color table. When dstInfo.colorType() is | |
| 254 * kIndex8, this should be non-NULL and have enough storage for 256 | |
| 255 * colors. The color table will be populated after decoding the palett e. | |
| 256 * @param ctableCount A pointer to the size of the color table. When | |
| 257 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will | |
| 258 * be modified to the true size of the color table (<= 256) after | |
| 259 * decoding the palette. | |
| 260 * @return Enum representing success or reason for failure. | |
| 261 */ | |
| 262 Result start(const SkImageInfo& dstInfo, const SkCodec::Options* options, | |
|
scroggo
2015/09/25 16:07:49
I left the name "start" to make the changeover sim
msarett
2015/09/28 14:48:50
I like a shorter name but that's because I know wh
scroggo
2015/09/28 16:01:52
These sound fine with me. I'll wait for API review
| |
| 263 SkPMColor ctable[], int* ctableCount); | |
| 264 | |
| 265 /** | |
| 266 * Simplified version of start() that asserts that info is NOT | |
| 267 * kIndex8_SkColorType and uses the default Options. | |
| 268 */ | |
| 269 Result start(const SkImageInfo& dstInfo); | |
| 270 | |
| 271 /** | |
| 272 * Write the next countLines scanlines into dst. | |
| 273 * | |
| 274 * Not valid to call before calling start(). | |
| 275 * | |
| 276 * @param dst Must be non-null, and large enough to hold countLines | |
| 277 * scanlines of size rowBytes. | |
| 278 * @param countLines Number of lines to write. | |
| 279 * @param rowBytes Number of bytes per row. Must be large enough to hold | |
| 280 * a scanline based on the SkImageInfo used to create this object. | |
| 281 */ | |
| 282 Result getScanlines(void* dst, int countLines, size_t rowBytes) { | |
| 283 if (fCurrScanline < 0) { | |
|
scroggo
2015/09/25 16:07:49
Alternatively, I could have checked fDstInfo, whic
msarett
2015/09/28 14:48:50
I like what you've chosen to do.
| |
| 284 return kScanlineDecodingNotStarted; | |
|
scroggo
2015/09/25 16:07:49
I know (msarett@) you have a CL out for review whi
msarett
2015/09/28 14:48:50
Yeah I think that's ok. Maybe we can provide more
scroggo
2015/09/28 16:01:52
I think returning kScanlineDecodingNoStarted is pr
| |
| 285 } | |
| 286 | |
| 287 SkASSERT(!fDstInfo.isEmpty()); | |
| 288 if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0 | |
| 289 || fCurrScanline + countLines > fDstInfo.height()) { | |
| 290 return kInvalidParameters; | |
| 291 } | |
| 292 const Result result = this->onGetScanlines(dst, countLines, rowBytes); | |
| 293 fCurrScanline += countLines; | |
| 294 return result; | |
| 295 } | |
| 296 | |
| 297 /** | |
| 298 * Skip count scanlines. | |
| 299 * | |
| 300 * Not valid to call before calling start(). | |
| 301 * | |
| 302 * The default version just calls onGetScanlines and discards the dst. | |
| 303 * NOTE: If skipped lines are the only lines with alpha, this default | |
| 304 * will make reallyHasAlpha return true, when it could have returned | |
| 305 * false. | |
| 306 */ | |
| 307 Result skipScanlines(int countLines) { | |
| 308 if (fCurrScanline < 0) { | |
| 309 return kScanlineDecodingNotStarted; | |
| 310 } | |
| 311 SkASSERT(!fDstInfo.isEmpty()); | |
| 312 if (fCurrScanline + countLines > fDstInfo.height()) { | |
| 313 // Arguably, we could just skip the scanlines which are remaining, | |
| 314 // and return kSuccess. We choose to return invalid so the client | |
| 315 // can catch their bug. | |
| 316 return SkCodec::kInvalidParameters; | |
| 317 } | |
| 318 const Result result = this->onSkipScanlines(countLines); | |
| 319 fCurrScanline += countLines; | |
| 320 return result; | |
| 321 } | |
| 322 | |
| 323 /** | |
| 324 * The order in which rows are output from the scanline decoder is not the | |
| 325 * same for all variations of all image types. This explains the possible | |
| 326 * output row orderings. | |
| 327 */ | |
| 328 enum SkScanlineOrder { | |
| 329 /* | |
| 330 * By far the most common, this indicates that the image can be decoded | |
| 331 * reliably using the scanline decoder, and that rows will be output in | |
| 332 * the logical order. | |
| 333 */ | |
| 334 kTopDown_SkScanlineOrder, | |
| 335 | |
| 336 /* | |
| 337 * This indicates that the scanline decoder reliably outputs rows, but | |
| 338 * they will be returned in reverse order. If the scanline format is | |
| 339 * kBottomUp, the getY() API can be used to determine the actual | |
| 340 * y-coordinate of the next output row, but the client is not forced | |
| 341 * to take advantage of this, given that it's not too tough to keep | |
| 342 * track independently. | |
| 343 * | |
| 344 * For full image decodes, it is safe to get all of the scanlines at | |
| 345 * once, since the decoder will handle inverting the rows as it | |
| 346 * decodes. | |
| 347 * | |
| 348 * For subset decodes and sampling, it is simplest to get and skip | |
| 349 * scanlines one at a time, using the getY() API. It is possible to | |
| 350 * ask for larger chunks at a time, but this should be used with | |
| 351 * caution. As with full image decodes, the decoder will handle | |
| 352 * inverting the requested rows, but rows will still be delivered | |
| 353 * starting from the bottom of the image. | |
| 354 * | |
| 355 * Upside down bmps are an example. | |
| 356 */ | |
| 357 kBottomUp_SkScanlineOrder, | |
| 358 | |
| 359 /* | |
| 360 * This indicates that the scanline decoder reliably outputs rows, but | |
| 361 * they will not be in logical order. If the scanline format is | |
| 362 * kOutOfOrder, the getY() API should be used to determine the actual | |
| 363 * y-coordinate of the next output row. | |
| 364 * | |
| 365 * For this scanline ordering, it is advisable to get and skip | |
| 366 * scanlines one at a time. | |
| 367 * | |
| 368 * Interlaced gifs are an example. | |
| 369 */ | |
| 370 kOutOfOrder_SkScanlineOrder, | |
| 371 | |
| 372 /* | |
| 373 * Indicates that the entire image must be decoded in order to output | |
| 374 * any amount of scanlines. In this case, it is a REALLY BAD IDEA to | |
| 375 * request scanlines 1-by-1 or in small chunks. The client should | |
| 376 * determine which scanlines are needed and ask for all of them in | |
| 377 * a single call to getScanlines(). | |
| 378 * | |
| 379 * Interlaced pngs are an example. | |
| 380 */ | |
| 381 kNone_SkScanlineOrder, | |
| 382 }; | |
| 383 | |
| 384 /** | |
| 385 * An enum representing the order in which scanlines will be returned by | |
| 386 * the scanline decoder. | |
| 387 */ | |
| 388 SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder() ; } | |
| 389 | |
| 390 /** | |
| 391 * Returns the y-coordinate of the next row to be returned by the scanline | |
| 392 * decoder. This will be overridden in the case of | |
| 393 * kOutOfOrder_SkScanlineOrder and should be unnecessary in the case of | |
| 394 * kNone_SkScanlineOrder. | |
| 395 * | |
| 396 * Results are undefined when not in scanline decoding mode. | |
| 397 */ | |
| 398 int getY() const { | |
| 399 SkASSERT(kNone_SkScanlineOrder != this->getScanlineOrder()); | |
|
msarett
2015/09/28 14:48:50
Given that the interlaced png scanline decoder now
scroggo
2015/09/28 16:01:52
I've removed the assert. FWIW, interlaced png call
| |
| 400 return this->onGetY(); | |
| 401 } | |
| 402 | |
| 228 protected: | 403 protected: |
| 229 SkCodec(const SkImageInfo&, SkStream*); | 404 SkCodec(const SkImageInfo&, SkStream*); |
| 230 | 405 |
| 231 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { | 406 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { |
| 232 // By default, scaling is not supported. | 407 // By default, scaling is not supported. |
| 233 return this->getInfo().dimensions(); | 408 return this->getInfo().dimensions(); |
| 234 } | 409 } |
| 235 | 410 |
| 236 virtual SkEncodedFormat onGetEncodedFormat() const = 0; | 411 virtual SkEncodedFormat onGetEncodedFormat() const = 0; |
| 237 | 412 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 268 return true; | 443 return true; |
| 269 } | 444 } |
| 270 | 445 |
| 271 /** | 446 /** |
| 272 * Get method for the input stream | 447 * Get method for the input stream |
| 273 */ | 448 */ |
| 274 SkStream* stream() { | 449 SkStream* stream() { |
| 275 return fStream.get(); | 450 return fStream.get(); |
| 276 } | 451 } |
| 277 | 452 |
| 453 /** | |
| 454 * The remaining functions revolve around decoding scanlines. | |
| 455 */ | |
| 456 | |
| 457 /** | |
| 458 * Most images types will be kTopDown and will not need to override this fu nction. | |
| 459 */ | |
| 460 virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanl ineOrder; } | |
| 461 | |
| 462 /** | |
| 463 * Most images will be kTopDown and will not need to override this function . | |
| 464 */ | |
| 465 virtual int onGetY() const { return fCurrScanline; } | |
| 466 | |
| 467 /** | |
| 468 * Update the next scanline. Used by interlaced png. | |
| 469 */ | |
| 470 void updateY(int newY) { fCurrScanline = newY; } | |
|
scroggo
2015/09/25 16:07:49
I named this updateY to mirror getY, but I might p
msarett
2015/09/28 14:48:50
I'm in favor of renaming these.
I think my origin
scroggo
2015/09/28 16:01:52
I'll add a FIXME to discuss for API review. I woul
| |
| 471 | |
| 472 const SkImageInfo& dstInfo() const { return fDstInfo; } | |
| 473 | |
| 474 const SkCodec::Options& options() const { return fOptions; } | |
| 475 | |
| 278 private: | 476 private: |
| 279 const SkImageInfo fInfo; | 477 const SkImageInfo fSrcInfo; |
| 280 SkAutoTDelete<SkStream> fStream; | 478 SkAutoTDelete<SkStream> fStream; |
| 281 bool fNeedsRewind; | 479 bool fNeedsRewind; |
| 480 // These fields are only meaningful during scanline decodes. | |
| 481 SkImageInfo fDstInfo; | |
| 482 SkCodec::Options fOptions; | |
| 483 int fCurrScanline; | |
| 484 | |
| 485 // Methods for scanline decoding. | |
| 486 virtual SkCodec::Result onStart(const SkImageInfo& dstInfo, | |
| 487 const SkCodec::Options& options, | |
| 488 SkPMColor ctable[], int* ctableCount) { | |
| 489 return kUnimplemented; | |
| 490 } | |
| 491 | |
| 492 // Naive default version just calls onGetScanlines on temp memory. | |
| 493 virtual SkCodec::Result onSkipScanlines(int countLines) { | |
| 494 SkAutoMalloc storage(fDstInfo.minRowBytes()); | |
| 495 // Note that we pass 0 to rowBytes so we continue to use the same memory . | |
| 496 // Also note that while getScanlines checks that rowBytes is big enough, | |
| 497 // onGetScanlines bypasses that check. | |
| 498 // Calling the virtual method also means we do not double count | |
| 499 // countLines. | |
| 500 return this->onGetScanlines(storage.get(), countLines, 0); | |
| 501 } | |
| 502 | |
| 503 virtual SkCodec::Result onGetScanlines(void* dst, int countLines, | |
| 504 size_t rowBytes) { | |
| 505 return kUnimplemented; | |
| 506 } | |
| 507 | |
| 282 }; | 508 }; |
| 283 #endif // SkCodec_DEFINED | 509 #endif // SkCodec_DEFINED |
| OLD | NEW |