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 #include "SkCodec.h" | 8 #include "SkCodec.h" |
| 9 #include "SkJpegCodec.h" | 9 #include "SkJpegCodec.h" |
| 10 #include "SkJpegDecoderMgr.h" | 10 #include "SkJpegDecoderMgr.h" |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 | 156 |
| 157 } | 157 } |
| 158 /* | 158 /* |
| 159 * Return a valid set of output dimensions for this decoder, given an input scal e | 159 * Return a valid set of output dimensions for this decoder, given an input scal e |
| 160 */ | 160 */ |
| 161 SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const { | 161 SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const { |
| 162 // libjpeg-turbo supports scaling by 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1, so we will | 162 // libjpeg-turbo supports scaling by 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1, so we will |
| 163 // support these as well | 163 // support these as well |
| 164 long num; | 164 long num; |
| 165 long denom = 8; | 165 long denom = 8; |
| 166 if (desiredScale > 0.875f) { | 166 if (desiredScale >= 0.9375) { |
|
scroggo
2015/10/02 18:27:03
why did this change?
msarett
2015/10/06 23:01:27
IMO, it used to make sense to always round up, sin
| |
| 167 num = 8; | 167 num = 8; |
| 168 } else if (desiredScale > 0.75f) { | 168 } else if (desiredScale >= 0.8125) { |
| 169 num = 7; | 169 num = 7; |
| 170 } else if (desiredScale > 0.625f) { | 170 } else if (desiredScale >= 0.6875f) { |
| 171 num = 6; | 171 num = 6; |
| 172 } else if (desiredScale > 0.5f) { | 172 } else if (desiredScale >= 0.5625f) { |
| 173 num = 5; | 173 num = 5; |
| 174 } else if (desiredScale > 0.375f) { | 174 } else if (desiredScale >= 0.4375f) { |
| 175 num = 4; | 175 num = 4; |
| 176 } else if (desiredScale > 0.25f) { | 176 } else if (desiredScale >= 0.3125f) { |
| 177 num = 3; | 177 num = 3; |
| 178 } else if (desiredScale > 0.125f) { | 178 } else if (desiredScale >= 0.1875f) { |
| 179 num = 2; | 179 num = 2; |
| 180 } else { | 180 } else { |
| 181 num = 1; | 181 num = 1; |
| 182 } | 182 } |
| 183 | 183 |
| 184 // Set up a fake decompress struct in order to use libjpeg to calculate outp ut dimensions | 184 // Set up a fake decompress struct in order to use libjpeg to calculate outp ut dimensions |
| 185 jpeg_decompress_struct dinfo; | 185 jpeg_decompress_struct dinfo; |
| 186 sk_bzero(&dinfo, sizeof(dinfo)); | 186 sk_bzero(&dinfo, sizeof(dinfo)); |
| 187 dinfo.image_width = this->getInfo().width(); | 187 dinfo.image_width = this->getInfo().width(); |
| 188 dinfo.image_height = this->getInfo().height(); | 188 dinfo.image_height = this->getInfo().height(); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 } | 361 } |
| 362 | 362 |
| 363 // Move to the next row | 363 // Move to the next row |
| 364 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); | 364 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); |
| 365 } | 365 } |
| 366 jpeg_finish_decompress(dinfo); | 366 jpeg_finish_decompress(dinfo); |
| 367 | 367 |
| 368 return kSuccess; | 368 return kSuccess; |
| 369 } | 369 } |
| 370 | 370 |
| 371 SkCodec::Result SkJpegCodec::initializeSwizzler(const SkImageInfo& info, const O ptions& options) { | 371 SkCodec::Result SkJpegCodec::initializeSwizzler(const SkImageInfo& info, const O ptions& options, |
| 372 int subsetLeft, int subsetWidth) { | |
| 372 SkSwizzler::SrcConfig srcConfig; | 373 SkSwizzler::SrcConfig srcConfig; |
| 373 switch (info.colorType()) { | 374 switch (info.colorType()) { |
| 374 case kGray_8_SkColorType: | 375 case kGray_8_SkColorType: |
| 375 srcConfig = SkSwizzler::kGray; | 376 srcConfig = SkSwizzler::kGray; |
| 376 break; | 377 break; |
| 377 case kRGBA_8888_SkColorType: | 378 case kRGBA_8888_SkColorType: |
| 378 srcConfig = SkSwizzler::kRGBX; | 379 srcConfig = SkSwizzler::kRGBX; |
| 379 break; | 380 break; |
| 380 case kBGRA_8888_SkColorType: | 381 case kBGRA_8888_SkColorType: |
| 381 srcConfig = SkSwizzler::kBGRX; | 382 srcConfig = SkSwizzler::kBGRX; |
| 382 break; | 383 break; |
| 383 case kRGB_565_SkColorType: | 384 case kRGB_565_SkColorType: |
| 384 srcConfig = SkSwizzler::kRGB_565; | 385 srcConfig = SkSwizzler::kRGB_565; |
| 385 break; | 386 break; |
| 386 default: | 387 default: |
| 387 // This function should only be called if the colorType is supported by jpeg | 388 // This function should only be called if the colorType is supported by jpeg |
| 388 SkASSERT(false); | 389 SkASSERT(false); |
| 389 } | 390 } |
| 390 | 391 |
| 391 fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, info, options .fZeroInitialized, | 392 fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, info, options .fZeroInitialized, |
| 392 this->getInfo())); | 393 this->getInfo(), subsetLeft, subs etWidth)); |
| 393 if (!fSwizzler) { | 394 if (!fSwizzler) { |
| 394 return SkCodec::kUnimplemented; | 395 return SkCodec::kUnimplemented; |
| 395 } | 396 } |
| 396 | 397 |
| 397 return kSuccess; | 398 return kSuccess; |
| 398 } | 399 } |
| 399 | 400 |
| 400 SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, | 401 SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, |
| 401 const Options& options, SkPMColor ctable[], int* ctableCount) { | 402 const Options& options, SkPMColor ctable[], int* ctableCount, int subset Left, |
| 403 int subsetWidth) { | |
| 402 // Set the jump location for libjpeg errors | 404 // Set the jump location for libjpeg errors |
| 403 if (setjmp(fDecoderMgr->getJmpBuf())) { | 405 if (setjmp(fDecoderMgr->getJmpBuf())) { |
| 404 SkCodecPrintf("setjmp: Error from libjpeg\n"); | 406 SkCodecPrintf("setjmp: Error from libjpeg\n"); |
| 405 return kInvalidInput; | 407 return kInvalidInput; |
| 406 } | 408 } |
| 407 | 409 |
| 408 // Check if we can decode to the requested destination and set the output co lor space | 410 // Check if we can decode to the requested destination and set the output co lor space |
| 409 if (!this->setOutputColorSpace(dstInfo)) { | 411 if (!this->setOutputColorSpace(dstInfo)) { |
| 410 return kInvalidConversion; | 412 return kInvalidConversion; |
| 411 } | 413 } |
| 412 | 414 |
| 413 // Perform the necessary scaling | 415 // Perform the necessary scaling |
| 414 if (!this->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) { | 416 if (!this->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) { |
| 415 // full native scaling to dstInfo dimensions not supported | 417 // full native scaling to dstInfo dimensions not supported |
| 416 | 418 |
| 417 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstI nfo)) { | 419 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstI nfo)) { |
| 418 return kInvalidScale; | 420 return kInvalidScale; |
| 419 } | 421 } |
| 422 | |
| 420 // create swizzler for sampling | 423 // create swizzler for sampling |
| 421 Result result = this->initializeSwizzler(dstInfo, options); | 424 SkCodec::Result result = this->initializeSwizzler(dstInfo, options, subs etLeft, |
| 422 if (kSuccess != result) { | 425 subsetWidth); |
| 426 if (SkCodec::kSuccess != result) { | |
| 423 SkCodecPrintf("failed to initialize the swizzler.\n"); | 427 SkCodecPrintf("failed to initialize the swizzler.\n"); |
| 424 return result; | 428 return result; |
| 425 } | 429 } |
| 426 fStorage.reset(get_row_bytes(fDecoderMgr->dinfo())); | 430 fStorage.reset(get_row_bytes(this->fDecoderMgr->dinfo())); |
| 431 fSrcRow = static_cast<uint8_t*>(fStorage.get()); | |
| 432 } else if (0 != subsetLeft || dstInfo.width() != subsetWidth) { | |
| 433 // TODO (msarett): If we implement a read partial scanlines API in libjp eg-turbo, we | |
| 434 // won't need to use the swizzler here. | |
| 435 // Create swizzler for subsetting. We pass in the original info because scaling is | |
| 436 // handlded natively. | |
| 437 SkCodec::Result result = this->initializeSwizzler( | |
| 438 dstInfo.makeWH(this->getInfo().width(), this->getInfo().height() ), options, | |
| 439 subsetLeft, subsetWidth); | |
| 440 if (SkCodec::kSuccess != result) { | |
| 441 SkCodecPrintf("failed to initialize the swizzler.\n"); | |
| 442 return result; | |
| 443 } | |
| 444 fStorage.reset(get_row_bytes(this->fDecoderMgr->dinfo())); | |
| 427 fSrcRow = static_cast<uint8_t*>(fStorage.get()); | 445 fSrcRow = static_cast<uint8_t*>(fStorage.get()); |
| 428 } else { | 446 } else { |
| 429 fSrcRow = nullptr; | 447 fSrcRow = nullptr; |
| 430 fSwizzler.reset(nullptr); | 448 fSwizzler.reset(nullptr); |
| 431 } | 449 } |
| 432 | 450 |
| 433 // Now, given valid output dimensions, we can start the decompress | 451 // Now, given valid output dimensions, we can start the decompress |
| 434 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) { | 452 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) { |
| 435 SkCodecPrintf("start decompress failed\n"); | 453 SkCodecPrintf("start decompress failed\n"); |
| 436 return kInvalidInput; | 454 return kInvalidInput; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 #endif | 522 #endif |
| 505 | 523 |
| 506 bool SkJpegCodec::onSkipScanlines(int count) { | 524 bool SkJpegCodec::onSkipScanlines(int count) { |
| 507 // Set the jump location for libjpeg errors | 525 // Set the jump location for libjpeg errors |
| 508 if (setjmp(fDecoderMgr->getJmpBuf())) { | 526 if (setjmp(fDecoderMgr->getJmpBuf())) { |
| 509 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); | 527 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); |
| 510 } | 528 } |
| 511 | 529 |
| 512 return count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count); | 530 return count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count); |
| 513 } | 531 } |
| OLD | NEW |