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 #include "SkCodec.h" | 8 #include "SkCodec.h" |
9 #include "SkJpegCodec.h" | 9 #include "SkJpegCodec.h" |
10 #include "SkJpegDecoderMgr.h" | 10 #include "SkJpegDecoderMgr.h" |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 fDecoderMgr->dinfo()->scale_num = num; | 318 fDecoderMgr->dinfo()->scale_num = num; |
319 fDecoderMgr->dinfo()->scale_denom = denom; | 319 fDecoderMgr->dinfo()->scale_denom = denom; |
320 return true; | 320 return true; |
321 } | 321 } |
322 | 322 |
323 /* | 323 /* |
324 * Performs the jpeg decode | 324 * Performs the jpeg decode |
325 */ | 325 */ |
326 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, | 326 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, |
327 void* dst, size_t dstRowBytes, | 327 void* dst, size_t dstRowBytes, |
328 const Options& options, SkPMColor*, int
*) { | 328 const Options& options, SkPMColor*, int
*, |
| 329 int* rowsDecoded) { |
329 if (options.fSubset) { | 330 if (options.fSubset) { |
330 // Subsets are not supported. | 331 // Subsets are not supported. |
331 return kUnimplemented; | 332 return kUnimplemented; |
332 } | 333 } |
333 | 334 |
334 // Get a pointer to the decompress info since we will use it quite frequentl
y | 335 // Get a pointer to the decompress info since we will use it quite frequentl
y |
335 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); | 336 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); |
336 | 337 |
337 // Set the jump location for libjpeg errors | 338 // Set the jump location for libjpeg errors |
338 if (setjmp(fDecoderMgr->getJmpBuf())) { | 339 if (setjmp(fDecoderMgr->getJmpBuf())) { |
(...skipping 12 matching lines...) Expand all Loading... |
351 | 352 |
352 // The recommended output buffer height should always be 1 in high quality m
odes. | 353 // The recommended output buffer height should always be 1 in high quality m
odes. |
353 // If it's not, we want to know because it means our strategy is not optimal
. | 354 // If it's not, we want to know because it means our strategy is not optimal
. |
354 SkASSERT(1 == dinfo->rec_outbuf_height); | 355 SkASSERT(1 == dinfo->rec_outbuf_height); |
355 | 356 |
356 // Perform the decode a single row at a time | 357 // Perform the decode a single row at a time |
357 uint32_t dstHeight = dstInfo.height(); | 358 uint32_t dstHeight = dstInfo.height(); |
358 JSAMPLE* dstRow = (JSAMPLE*) dst; | 359 JSAMPLE* dstRow = (JSAMPLE*) dst; |
359 for (uint32_t y = 0; y < dstHeight; y++) { | 360 for (uint32_t y = 0; y < dstHeight; y++) { |
360 // Read rows of the image | 361 // Read rows of the image |
361 uint32_t rowsDecoded = jpeg_read_scanlines(dinfo, &dstRow, 1); | 362 uint32_t lines = jpeg_read_scanlines(dinfo, &dstRow, 1); |
362 | 363 |
363 // If we cannot read enough rows, assume the input is incomplete | 364 // If we cannot read enough rows, assume the input is incomplete |
364 if (rowsDecoded != 1) { | 365 if (lines != 1) { |
365 // Fill the remainder of the image with black. This error handling | 366 *rowsDecoded = y; |
366 // behavior is unspecified but SkCodec consistently uses black as | |
367 // the fill color for opaque images. If the destination is kGray, | |
368 // the low 8 bits of SK_ColorBLACK will be used. Conveniently, | |
369 // these are zeros, which is the representation for black in kGray. | |
370 // If the destination is kRGB_565, the low 16 bits of SK_ColorBLACK | |
371 // will be used. Conveniently, these are zeros, which is the | |
372 // representation for black in kRGB_565. | |
373 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, dstHeight - y, | |
374 SK_ColorBLACK, nullptr, options.fZeroInitialized); | |
375 | 367 |
376 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple
teInput); | 368 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple
teInput); |
377 } | 369 } |
378 | 370 |
379 // Convert to RGBA if necessary | 371 // Convert to RGBA if necessary |
380 if (JCS_CMYK == dinfo->out_color_space) { | 372 if (JCS_CMYK == dinfo->out_color_space) { |
381 convert_CMYK_to_RGBA(dstRow, dstInfo.width()); | 373 convert_CMYK_to_RGBA(dstRow, dstInfo.width()); |
382 } | 374 } |
383 | 375 |
384 // Move to the next row | 376 // Move to the next row |
385 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); | 377 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); |
386 } | 378 } |
387 | 379 |
388 return kSuccess; | 380 return kSuccess; |
389 } | 381 } |
390 | 382 |
391 SkSampler* SkJpegCodec::getSampler() { | 383 SkSampler* SkJpegCodec::getSampler(bool createIfNecessary) { |
392 if (fSwizzler) { | 384 if (!createIfNecessary || fSwizzler) { |
393 SkASSERT(fSrcRow && static_cast<uint8_t*>(fStorage.get()) == fSrcRow); | 385 SkASSERT(!fSwizzler || (fSrcRow && static_cast<uint8_t*>(fStorage.get())
== fSrcRow)); |
394 return fSwizzler; | 386 return fSwizzler; |
395 } | 387 } |
396 | 388 |
397 const SkImageInfo& info = this->dstInfo(); | 389 const SkImageInfo& info = this->dstInfo(); |
398 SkSwizzler::SrcConfig srcConfig; | 390 SkSwizzler::SrcConfig srcConfig; |
399 switch (info.colorType()) { | 391 switch (info.colorType()) { |
400 case kGray_8_SkColorType: | 392 case kGray_8_SkColorType: |
401 srcConfig = SkSwizzler::kGray; | 393 srcConfig = SkSwizzler::kGray; |
402 break; | 394 break; |
403 case kRGBA_8888_SkColorType: | 395 case kRGBA_8888_SkColorType: |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 | 437 |
446 // Now, given valid output dimensions, we can start the decompress | 438 // Now, given valid output dimensions, we can start the decompress |
447 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) { | 439 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) { |
448 SkCodecPrintf("start decompress failed\n"); | 440 SkCodecPrintf("start decompress failed\n"); |
449 return kInvalidInput; | 441 return kInvalidInput; |
450 } | 442 } |
451 | 443 |
452 return kSuccess; | 444 return kSuccess; |
453 } | 445 } |
454 | 446 |
455 SkCodec::Result SkJpegCodec::onGetScanlines(void* dst, int count, size_t rowByte
s) { | 447 int SkJpegCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { |
456 // Set the jump location for libjpeg errors | 448 // Set the jump location for libjpeg errors |
457 if (setjmp(fDecoderMgr->getJmpBuf())) { | 449 if (setjmp(fDecoderMgr->getJmpBuf())) { |
458 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); | 450 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); |
459 } | 451 } |
460 // Read rows one at a time | 452 // Read rows one at a time |
461 JSAMPLE* dstRow; | 453 JSAMPLE* dstRow; |
462 if (fSwizzler) { | 454 if (fSwizzler) { |
463 // write data to storage row, then sample using swizzler | 455 // write data to storage row, then sample using swizzler |
464 dstRow = fSrcRow; | 456 dstRow = fSrcRow; |
465 } else { | 457 } else { |
466 // write data directly to dst | 458 // write data directly to dst |
467 dstRow = (JSAMPLE*) dst; | 459 dstRow = (JSAMPLE*) dst; |
468 } | 460 } |
469 | 461 |
470 for (int y = 0; y < count; y++) { | 462 for (int y = 0; y < count; y++) { |
471 // Read row of the image | 463 // Read row of the image |
472 uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow
, 1); | 464 uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow
, 1); |
473 if (rowsDecoded != 1) { | 465 if (rowsDecoded != 1) { |
474 SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes, count - y, | |
475 SK_ColorBLACK, nullptr, this->options().fZeroInitialized
); | |
476 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height(); | 466 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height(); |
477 return kIncompleteInput; | 467 return y; |
478 } | 468 } |
479 | 469 |
480 // Convert to RGBA if necessary | 470 // Convert to RGBA if necessary |
481 if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { | 471 if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { |
482 convert_CMYK_to_RGBA(dstRow, fDecoderMgr->dinfo()->output_width); | 472 convert_CMYK_to_RGBA(dstRow, fDecoderMgr->dinfo()->output_width); |
483 } | 473 } |
484 | 474 |
485 if(fSwizzler) { | 475 if(fSwizzler) { |
486 // use swizzler to sample row | 476 // use swizzler to sample row |
487 fSwizzler->swizzle(dst, dstRow); | 477 fSwizzler->swizzle(dst, dstRow); |
488 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes); | 478 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes); |
489 } else { | 479 } else { |
490 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); | 480 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); |
491 } | 481 } |
492 } | 482 } |
493 return kSuccess; | 483 return count; |
494 } | 484 } |
495 | 485 |
496 #ifndef TURBO_HAS_SKIP | 486 #ifndef TURBO_HAS_SKIP |
497 // TODO (msarett): Make this a member function and avoid reallocating the | 487 // TODO (msarett): Make this a member function and avoid reallocating the |
498 // memory buffer on each call to skip. | 488 // memory buffer on each call to skip. |
499 #define jpeg_skip_scanlines(dinfo, count) \ | 489 #define jpeg_skip_scanlines(dinfo, count) \ |
500 SkAutoMalloc storage(get_row_bytes(dinfo)); \ | 490 SkAutoMalloc storage(get_row_bytes(dinfo)); \ |
501 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \ | 491 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \ |
502 for (int y = 0; y < count; y++) { \ | 492 for (int y = 0; y < count; y++) { \ |
503 jpeg_read_scanlines(dinfo, &storagePtr, 1); \ | 493 jpeg_read_scanlines(dinfo, &storagePtr, 1); \ |
504 } | 494 } |
505 #endif | 495 #endif |
506 | 496 |
507 SkCodec::Result SkJpegCodec::onSkipScanlines(int count) { | 497 bool SkJpegCodec::onSkipScanlines(int count) { |
508 // Set the jump location for libjpeg errors | 498 // Set the jump location for libjpeg errors |
509 if (setjmp(fDecoderMgr->getJmpBuf())) { | 499 if (setjmp(fDecoderMgr->getJmpBuf())) { |
510 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); | 500 return fDecoderMgr->returnFalse("setjmp"); |
511 } | 501 } |
512 | 502 |
513 jpeg_skip_scanlines(fDecoderMgr->dinfo(), count); | 503 return count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count); |
514 | |
515 return kSuccess; | |
516 } | 504 } |
517 | |
OLD | NEW |