Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: src/codec/SkJpegCodec.cpp

Issue 1260673002: SkScaledCodec class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix sample function for 565 images Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "SkJpegUtility_codec.h" 11 #include "SkJpegUtility_codec.h"
12 #include "SkCodecPriv.h" 12 #include "SkCodecPriv.h"
13 #include "SkColorPriv.h" 13 #include "SkColorPriv.h"
14 #include "SkScaledCodec.h"
14 #include "SkScanlineDecoder.h" 15 #include "SkScanlineDecoder.h"
15 #include "SkStream.h" 16 #include "SkStream.h"
16 #include "SkTemplates.h" 17 #include "SkTemplates.h"
17 #include "SkTypes.h" 18 #include "SkTypes.h"
18 19
19 // stdio is needed for libjpeg-turbo 20 // stdio is needed for libjpeg-turbo
20 #include <stdio.h> 21 #include <stdio.h>
21 22
22 extern "C" { 23 extern "C" {
23 #include "jpeglibmangler.h" 24 #include "jpeglibmangler.h"
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 dinfo.global_state = DSTATE_READY; 183 dinfo.global_state = DSTATE_READY;
183 dinfo.num_components = 0; 184 dinfo.num_components = 0;
184 dinfo.scale_num = num; 185 dinfo.scale_num = num;
185 dinfo.scale_denom = denom; 186 dinfo.scale_denom = denom;
186 turbo_jpeg_calc_output_dimensions(&dinfo); 187 turbo_jpeg_calc_output_dimensions(&dinfo);
187 188
188 // Return the calculated output dimensions for the given scale 189 // Return the calculated output dimensions for the given scale
189 return SkISize::Make(dinfo.output_width, dinfo.output_height); 190 return SkISize::Make(dinfo.output_width, dinfo.output_height);
190 } 191 }
191 192
193 SkCodec::Result SkJpegCodec::initializeSwizzler(const SkImageInfo& requestedInfo ,
scroggo 2015/07/31 19:31:58 It looks like the swizzler is never used in getPix
emmaleer 2015/07/31 20:43:10 Acknowledged.
194 void* dst, size_t rowBytes,
195 const Options& options,
196 SkPMColor ctable[],
197 int* ctableCount) {
198
199 const SkColorType srcColorType = requestedInfo.colorType();
200 SkSwizzler::SrcConfig srcConfig;
201 switch (srcColorType) {
202 case kGray_8_SkColorType:
203 srcConfig = SkSwizzler::kGray;
204 break;
205 case kRGBA_8888_SkColorType:
206 srcConfig = SkSwizzler::kRGBX;
207 break;
208 case kBGRA_8888_SkColorType:
209 srcConfig = SkSwizzler::kBGRX;
210 break;
211 case kRGB_565_SkColorType:
212 srcConfig = SkSwizzler::kRGB_565;
213 break;
214 default:
215 //would have exited before now if the colorType was supported by jpe g
216 SkASSERT(false);
217 }
218
219 fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, NULL, requestedInfo,
220 options.fZeroInitialized, this->g etInfo().width()));
221 if (!fSwizzler) {
222 // FIXME: CreateSwizzler could fail for another reason.
223 return kUnimplemented;
224 }
225 return kSuccess;
226 }
227
192 /* 228 /*
193 * Handles rewinding the input stream if it is necessary 229 * Handles rewinding the input stream if it is necessary
194 */ 230 */
195 bool SkJpegCodec::handleRewind() { 231 bool SkJpegCodec::handleRewind() {
196 switch(this->rewindIfNeeded()) { 232 switch(this->rewindIfNeeded()) {
197 case kCouldNotRewind_RewindState: 233 case kCouldNotRewind_RewindState:
198 return fDecoderMgr->returnFalse("could not rewind"); 234 return fDecoderMgr->returnFalse("could not rewind");
199 case kRewound_RewindState: { 235 case kRewound_RewindState: {
200 JpegDecoderMgr* decoderMgr = NULL; 236 JpegDecoderMgr* decoderMgr = NULL;
201 if (!ReadHeader(this->stream(), NULL, &decoderMgr)) { 237 if (!ReadHeader(this->stream(), NULL, &decoderMgr)) {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 fDecoderMgr->dinfo()->scale_denom = 8; 316 fDecoderMgr->dinfo()->scale_denom = 8;
281 fDecoderMgr->dinfo()->scale_num = 8; 317 fDecoderMgr->dinfo()->scale_num = 8;
282 turbo_jpeg_calc_output_dimensions(fDecoderMgr->dinfo()); 318 turbo_jpeg_calc_output_dimensions(fDecoderMgr->dinfo());
283 while (fDecoderMgr->dinfo()->output_width != dstWidth || 319 while (fDecoderMgr->dinfo()->output_width != dstWidth ||
284 fDecoderMgr->dinfo()->output_height != dstHeight) { 320 fDecoderMgr->dinfo()->output_height != dstHeight) {
285 321
286 // Return a failure if we have tried all of the possible scales 322 // Return a failure if we have tried all of the possible scales
287 if (1 == fDecoderMgr->dinfo()->scale_num || 323 if (1 == fDecoderMgr->dinfo()->scale_num ||
288 dstWidth > fDecoderMgr->dinfo()->output_width || 324 dstWidth > fDecoderMgr->dinfo()->output_width ||
289 dstHeight > fDecoderMgr->dinfo()->output_height) { 325 dstHeight > fDecoderMgr->dinfo()->output_height) {
326 // reset scale settings on failure
scroggo 2015/07/31 19:31:58 Can you explain why? "because this may be supporte
emmaleer 2015/07/31 20:43:10 Acknowledged.
327 this->fDecoderMgr->dinfo()->scale_num = 8;
328 turbo_jpeg_calc_output_dimensions(this->fDecoderMgr->dinfo());
290 return fDecoderMgr->returnFalse("could not scale to requested dimens ions"); 329 return fDecoderMgr->returnFalse("could not scale to requested dimens ions");
scroggo 2015/07/31 19:31:58 I wonder if this error message is necessary now th
emmaleer 2015/07/31 20:43:09 I removed the error. I think it's okay for the fun
scroggo 2015/07/31 21:11:57 Agreed for your case, although we should perhaps m
emmaleer 2015/08/03 14:29:41 If the function fails onGetPixels already returns:
scroggo 2015/08/03 17:02:55 Ok, great, so this is fine to remove.
291 } 330 }
292 331
293 // Try the next scale 332 // Try the next scale
294 fDecoderMgr->dinfo()->scale_num -= 1; 333 fDecoderMgr->dinfo()->scale_num -= 1;
295 turbo_jpeg_calc_output_dimensions(fDecoderMgr->dinfo()); 334 turbo_jpeg_calc_output_dimensions(fDecoderMgr->dinfo());
296 } 335 }
297 return true; 336 return true;
298 } 337 }
299 338
300 /* 339 /*
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 /* 426 /*
388 * Enable scanline decoding for jpegs 427 * Enable scanline decoding for jpegs
389 */ 428 */
390 class SkJpegScanlineDecoder : public SkScanlineDecoder { 429 class SkJpegScanlineDecoder : public SkScanlineDecoder {
391 public: 430 public:
392 SkJpegScanlineDecoder(const SkImageInfo& dstInfo, SkJpegCodec* codec, 431 SkJpegScanlineDecoder(const SkImageInfo& dstInfo, SkJpegCodec* codec,
393 const SkCodec::Options& opts) 432 const SkCodec::Options& opts)
394 : INHERITED(dstInfo) 433 : INHERITED(dstInfo)
395 , fCodec(codec) 434 , fCodec(codec)
396 , fOpts(opts) 435 , fOpts(opts)
397 {} 436 {
437 if(fCodec->fSwizzler) {
438 fStorage.reset(fCodec->getInfo().width() * dstInfo.minRowBytes());
439 fSrcRow = static_cast<uint8_t*>(fStorage.get());
440 }
441 }
398 442
399 virtual ~SkJpegScanlineDecoder() { 443 virtual ~SkJpegScanlineDecoder() {
400 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { 444 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
401 SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n"); 445 SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n");
402 return; 446 return;
403 } 447 }
404 448
405 // We may not have decoded the entire image. Prevent libjpeg-turbo from failing on a 449 // We may not have decoded the entire image. Prevent libjpeg-turbo from failing on a
406 // partial decode. 450 // partial decode.
407 fCodec->fDecoderMgr->dinfo()->output_scanline = fCodec->getInfo().height (); 451 fCodec->fDecoderMgr->dinfo()->output_scanline = fCodec->getInfo().height ();
408 turbo_jpeg_finish_decompress(fCodec->fDecoderMgr->dinfo()); 452 turbo_jpeg_finish_decompress(fCodec->fDecoderMgr->dinfo());
409 } 453 }
410 454
411 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de { 455 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de {
412 // Set the jump location for libjpeg errors 456 // Set the jump location for libjpeg errors
413 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { 457 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
414 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput); 458 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput);
415 } 459 }
460 // Read rows one at a time
461 JSAMPLE* dstRow;
462 if (fCodec->fSwizzler) {
463 // write data to storage row, then sample using swizzler
464 dstRow = fSrcRow;
465 } else {
466 // write data directly to dst
467 dstRow = (JSAMPLE*) dst;
468 }
416 469
417 // Read rows one at a time
418 JSAMPLE* dstRow = (JSAMPLE*) dst;
419 for (int y = 0; y < count; y++) { 470 for (int y = 0; y < count; y++) {
420 // Read row of the image 471 // Read row of the image
421 uint32_t rowsDecoded = 472 uint32_t rowsDecoded =
422 turbo_jpeg_read_scanlines(fCodec->fDecoderMgr->dinfo(), &dst Row, 1); 473 turbo_jpeg_read_scanlines(fCodec->fDecoderMgr->dinfo(), &dst Row, 1);
423 if (rowsDecoded != 1) { 474 if (rowsDecoded != 1) {
424 if (SkCodec::kNo_ZeroInitialized == fOpts.fZeroInitialized || 475 if (SkCodec::kNo_ZeroInitialized == fOpts.fZeroInitialized ||
425 kN32_SkColorType == this->dstInfo().colorType()) { 476 kN32_SkColorType == this->dstInfo().colorType()) {
426 SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes, 477 SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes,
427 count - y, SK_ColorBLACK, NULL); 478 count - y, SK_ColorBLACK, NULL);
428 } 479 }
429 fCodec->fDecoderMgr->dinfo()->output_scanline = this->dstInfo(). height(); 480 fCodec->fDecoderMgr->dinfo()->output_scanline = this->dstInfo(). height();
430 return SkCodec::kIncompleteInput; 481 return SkCodec::kIncompleteInput;
431 } 482 }
432 483
433 // Convert to RGBA if necessary 484 // Convert to RGBA if necessary
434 if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) { 485 if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) {
435 convert_CMYK_to_RGBA(dstRow, this->dstInfo().width()); 486 convert_CMYK_to_RGBA(dstRow, this->dstInfo().width());
436 } 487 }
437 488
438 // Move to the next row 489 if(fCodec->fSwizzler) {
439 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); 490 // use swizzler to sample row
491 fCodec->fSwizzler->swizzle(dst, dstRow);
492 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes);
493 } else {
494 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes);
495 }
440 } 496 }
441
442 return SkCodec::kSuccess; 497 return SkCodec::kSuccess;
443 } 498 }
444 499
445 #ifndef TURBO_HAS_SKIP 500 #ifndef TURBO_HAS_SKIP
446 #define turbo_jpeg_skip_scanlines(dinfo, count) \ 501 #define turbo_jpeg_skip_scanlines(dinfo, count) \
447 SkAutoMalloc storage(dinfo->output_width * dinfo->out_color_components); \ 502 SkAutoMalloc storage(dinfo->output_width * dinfo->out_color_components); \
448 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \ 503 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \
449 for (int y = 0; y < count; y++) { \ 504 for (int y = 0; y < count; y++) { \
450 turbo_jpeg_read_scanlines(dinfo, &storagePtr, 1); \ 505 turbo_jpeg_read_scanlines(dinfo, &storagePtr, 1); \
451 } 506 }
452 #endif 507 #endif
453 508
454 SkCodec::Result onSkipScanlines(int count) override { 509 SkCodec::Result onSkipScanlines(int count) override {
455 // Set the jump location for libjpeg errors 510 // Set the jump location for libjpeg errors
456 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { 511 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
457 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput); 512 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput);
458 } 513 }
459 514
460 turbo_jpeg_skip_scanlines(fCodec->fDecoderMgr->dinfo(), count); 515 turbo_jpeg_skip_scanlines(fCodec->fDecoderMgr->dinfo(), count);
461 516
462 return SkCodec::kSuccess; 517 return SkCodec::kSuccess;
463 } 518 }
464 519
465 private: 520 private:
466 SkAutoTDelete<SkJpegCodec> fCodec; 521 SkAutoTDelete<SkJpegCodec> fCodec;
522 SkAutoMalloc fStorage; // Only used if sampling is needed
523 uint8_t* fSrcRow; // Only used if sampling is needed
467 const SkCodec::Options& fOpts; 524 const SkCodec::Options& fOpts;
468 525
469 typedef SkScanlineDecoder INHERITED; 526 typedef SkScanlineDecoder INHERITED;
470 }; 527 };
471 528
472 SkScanlineDecoder* SkJpegCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, 529 SkScanlineDecoder* SkJpegCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo,
473 const Options& options, SkPMColor ctable[], int* ctableCount) { 530 const Options& options, SkPMColor ctable[], int* ctableCount) {
474 531
475 // Rewind the stream if needed 532 // Rewind the stream if needed
476 if (!this->handleRewind()) { 533 if (!this->handleRewind()) {
(...skipping 17 matching lines...) Expand all
494 } 551 }
495 552
496 // Check if we can decode to the requested destination and set the output co lor space 553 // Check if we can decode to the requested destination and set the output co lor space
497 if (!codec->setOutputColorSpace(dstInfo)) { 554 if (!codec->setOutputColorSpace(dstInfo)) {
498 SkCodecPrintf("Cannot convert to output type\n"); 555 SkCodecPrintf("Cannot convert to output type\n");
499 return NULL; 556 return NULL;
500 } 557 }
501 558
502 // Perform the necessary scaling 559 // Perform the necessary scaling
503 if (!codec->scaleToDimensions(dstInfo.width(), dstInfo.height())) { 560 if (!codec->scaleToDimensions(dstInfo.width(), dstInfo.height())) {
504 SkCodecPrintf("Cannot scale to output dimensions\n"); 561 // native scaling to dstInfo dimensions not supported
505 return NULL; 562
563 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstI nfo)) {
564 return NULL;
565 }
566 // create swizzler for sampling
567 if (codec->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), opti ons, ctable,
568 ctableCount) != kSuccess) {
569 SkCodecPrintf("failed to initialize the swizzler.\n");
570 return NULL;
571 }
506 } 572 }
507 573
508 // Now, given valid output dimensions, we can start the decompress 574 // Now, given valid output dimensions, we can start the decompress
509 if (!turbo_jpeg_start_decompress(codec->fDecoderMgr->dinfo())) { 575 if (!turbo_jpeg_start_decompress(codec->fDecoderMgr->dinfo())) {
510 SkCodecPrintf("start decompress failed\n"); 576 SkCodecPrintf("start decompress failed\n");
511 return NULL; 577 return NULL;
512 } 578 }
513 579
514 // Return the new scanline decoder 580 // Return the new scanline decoder
515 return SkNEW_ARGS(SkJpegScanlineDecoder, (dstInfo, codec.detach(), options)) ; 581 return SkNEW_ARGS(SkJpegScanlineDecoder, (dstInfo, codec.detach(), options)) ;
516 } 582 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698