| 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 |