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

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

Issue 1294613002: Revert of SkScaledCodec class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 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
« no previous file with comments | « src/codec/SkJpegCodec.h ('k') | src/codec/SkScaledCodec.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
15 #include "SkScanlineDecoder.h" 14 #include "SkScanlineDecoder.h"
16 #include "SkStream.h" 15 #include "SkStream.h"
17 #include "SkTemplates.h" 16 #include "SkTemplates.h"
18 #include "SkTypes.h" 17 #include "SkTypes.h"
19 18
20 // stdio is needed for libjpeg-turbo 19 // stdio is needed for libjpeg-turbo
21 #include <stdio.h> 20 #include <stdio.h>
22 21
23 extern "C" { 22 extern "C" {
24 #include "jpeglibmangler.h" 23 #include "jpeglibmangler.h"
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 return NULL; 142 return NULL;
144 } 143 }
145 144
146 SkJpegCodec::SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream, 145 SkJpegCodec::SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream,
147 JpegDecoderMgr* decoderMgr) 146 JpegDecoderMgr* decoderMgr)
148 : INHERITED(srcInfo, stream) 147 : INHERITED(srcInfo, stream)
149 , fDecoderMgr(decoderMgr) 148 , fDecoderMgr(decoderMgr)
150 {} 149 {}
151 150
152 /* 151 /*
153 * Return the row bytes of a particular image type and width
154 */
155 static int get_row_bytes(const j_decompress_ptr dinfo) {
156 int colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 : dinfo->out_col or_components;
157 return dinfo->output_width * colorBytes;
158
159 }
160 /*
161 * Return a valid set of output dimensions for this decoder, given an input scal e 152 * Return a valid set of output dimensions for this decoder, given an input scal e
162 */ 153 */
163 SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const { 154 SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
164 // 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 155 // 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
165 // support these as well 156 // support these as well
166 long num; 157 long num;
167 long denom = 8; 158 long denom = 8;
168 if (desiredScale > 0.875f) { 159 if (desiredScale > 0.875f) {
169 num = 8; 160 num = 8;
170 } else if (desiredScale > 0.75f) { 161 } else if (desiredScale > 0.75f) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 // much faster than decoding to color and then converting 251 // much faster than decoding to color and then converting
261 fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE; 252 fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE;
262 } 253 }
263 return true; 254 return true;
264 default: 255 default:
265 return false; 256 return false;
266 } 257 }
267 } 258 }
268 259
269 /* 260 /*
270 * Checks if we can natively scale to the requested dimensions and natively scal es the 261 * Checks if we can scale to the requested dimensions and scales the dimensions
271 * dimensions if possible 262 * if possible
272 */ 263 */
273 bool SkJpegCodec::nativelyScaleToDimensions(uint32_t dstWidth, uint32_t dstHeigh t) { 264 bool SkJpegCodec::scaleToDimensions(uint32_t dstWidth, uint32_t dstHeight) {
274 // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1 265 // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1
275 fDecoderMgr->dinfo()->scale_denom = 8; 266 fDecoderMgr->dinfo()->scale_denom = 8;
276 fDecoderMgr->dinfo()->scale_num = 8; 267 fDecoderMgr->dinfo()->scale_num = 8;
277 chromium_jpeg_calc_output_dimensions(fDecoderMgr->dinfo()); 268 chromium_jpeg_calc_output_dimensions(fDecoderMgr->dinfo());
278 while (fDecoderMgr->dinfo()->output_width != dstWidth || 269 while (fDecoderMgr->dinfo()->output_width != dstWidth ||
279 fDecoderMgr->dinfo()->output_height != dstHeight) { 270 fDecoderMgr->dinfo()->output_height != dstHeight) {
280 271
281 // Return a failure if we have tried all of the possible scales 272 // Return a failure if we have tried all of the possible scales
282 if (1 == fDecoderMgr->dinfo()->scale_num || 273 if (1 == fDecoderMgr->dinfo()->scale_num ||
283 dstWidth > fDecoderMgr->dinfo()->output_width || 274 dstWidth > fDecoderMgr->dinfo()->output_width ||
284 dstHeight > fDecoderMgr->dinfo()->output_height) { 275 dstHeight > fDecoderMgr->dinfo()->output_height) {
285 // reset native scale settings on failure because this may be suppor ted by the swizzler 276 return fDecoderMgr->returnFalse("could not scale to requested dimens ions");
286 this->fDecoderMgr->dinfo()->scale_num = 8;
287 chromium_jpeg_calc_output_dimensions(this->fDecoderMgr->dinfo());
288 return false;
289 } 277 }
290 278
291 // Try the next scale 279 // Try the next scale
292 fDecoderMgr->dinfo()->scale_num -= 1; 280 fDecoderMgr->dinfo()->scale_num -= 1;
293 chromium_jpeg_calc_output_dimensions(fDecoderMgr->dinfo()); 281 chromium_jpeg_calc_output_dimensions(fDecoderMgr->dinfo());
294 } 282 }
295 return true; 283 return true;
296 } 284 }
297 285
298 /* 286 /*
(...skipping 19 matching lines...) Expand all
318 if (setjmp(fDecoderMgr->getJmpBuf())) { 306 if (setjmp(fDecoderMgr->getJmpBuf())) {
319 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); 307 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
320 } 308 }
321 309
322 // Check if we can decode to the requested destination and set the output co lor space 310 // Check if we can decode to the requested destination and set the output co lor space
323 if (!this->setOutputColorSpace(dstInfo)) { 311 if (!this->setOutputColorSpace(dstInfo)) {
324 return fDecoderMgr->returnFailure("conversion_possible", kInvalidConvers ion); 312 return fDecoderMgr->returnFailure("conversion_possible", kInvalidConvers ion);
325 } 313 }
326 314
327 // Perform the necessary scaling 315 // Perform the necessary scaling
328 if (!this->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) { 316 if (!this->scaleToDimensions(dstInfo.width(), dstInfo.height())) {
329 return fDecoderMgr->returnFailure("cannot scale to requested dims", kInv alidScale); 317 return fDecoderMgr->returnFailure("cannot scale to requested dims", kInv alidScale);
330 } 318 }
331 319
332 // Now, given valid output dimensions, we can start the decompress 320 // Now, given valid output dimensions, we can start the decompress
333 if (!chromium_jpeg_start_decompress(dinfo)) { 321 if (!chromium_jpeg_start_decompress(dinfo)) {
334 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput); 322 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
335 } 323 }
336 324
337 // The recommended output buffer height should always be 1 in high quality m odes. 325 // The recommended output buffer height should always be 1 in high quality m odes.
338 // If it's not, we want to know because it means our strategy is not optimal . 326 // If it's not, we want to know because it means our strategy is not optimal .
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 * Enable scanline decoding for jpegs 374 * Enable scanline decoding for jpegs
387 */ 375 */
388 class SkJpegScanlineDecoder : public SkScanlineDecoder { 376 class SkJpegScanlineDecoder : public SkScanlineDecoder {
389 public: 377 public:
390 SkJpegScanlineDecoder(const SkImageInfo& srcInfo, SkJpegCodec* codec) 378 SkJpegScanlineDecoder(const SkImageInfo& srcInfo, SkJpegCodec* codec)
391 : INHERITED(srcInfo) 379 : INHERITED(srcInfo)
392 , fCodec(codec) 380 , fCodec(codec)
393 , fOpts() 381 , fOpts()
394 {} 382 {}
395 383
396 /*
397 * Return a valid set of output dimensions for this decoder, given an input s cale
398 */
399 SkISize onGetScaledDimensions(float desiredScale) override {
400 return fCodec->onGetScaledDimensions(desiredScale);
401 }
402
403 /*
404 * Create the swizzler based on the encoded format.
405 * The swizzler is only used for sampling in the x direction.
406 */
407
408 SkCodec::Result initializeSwizzler(const SkImageInfo& info, const SkCodec::O ptions& options) {
409 SkSwizzler::SrcConfig srcConfig;
410 switch (info.colorType()) {
411 case kGray_8_SkColorType:
412 srcConfig = SkSwizzler::kGray;
413 break;
414 case kRGBA_8888_SkColorType:
415 srcConfig = SkSwizzler::kRGBX;
416 break;
417 case kBGRA_8888_SkColorType:
418 srcConfig = SkSwizzler::kBGRX;
419 break;
420 case kRGB_565_SkColorType:
421 srcConfig = SkSwizzler::kRGB_565;
422 break;
423 default:
424 //would have exited before now if the colorType was supported by jpeg
425 SkASSERT(false);
426 }
427
428 fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, NULL, info, option s.fZeroInitialized,
429 this->getInfo()));
430 if (!fSwizzler) {
431 // FIXME: CreateSwizzler could fail for another reason.
432 return SkCodec::kUnimplemented;
433 }
434 return SkCodec::kSuccess;
435 }
436
437 SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& options, 384 SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& options,
438 SkPMColor ctable[], int* ctableCount) override { 385 SkPMColor ctable[], int* ctableCount) override {
439 386
440 // Rewind the stream if needed 387 // Rewind the stream if needed
441 if (!fCodec->rewindIfNeeded()) { 388 if (!fCodec->rewindIfNeeded()) {
442 return SkCodec::kCouldNotRewind; 389 return SkCodec::kCouldNotRewind;
443 } 390 }
444 391
445 // Set the jump location for libjpeg errors 392 // Set the jump location for libjpeg errors
446 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { 393 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
447 SkCodecPrintf("setjmp: Error from libjpeg\n"); 394 SkCodecPrintf("setjmp: Error from libjpeg\n");
448 return SkCodec::kInvalidInput; 395 return SkCodec::kInvalidInput;
449 } 396 }
450 397
451 // Check if we can decode to the requested destination and set the outpu t color space 398 // Check if we can decode to the requested destination and set the outpu t color space
452 if (!fCodec->setOutputColorSpace(dstInfo)) { 399 if (!fCodec->setOutputColorSpace(dstInfo)) {
453 return SkCodec::kInvalidConversion; 400 return SkCodec::kInvalidConversion;
454 } 401 }
455 402
456 // Perform the necessary scaling 403 // Perform the necessary scaling
457 if (!fCodec->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height() )) { 404 if (!fCodec->scaleToDimensions(dstInfo.width(), dstInfo.height())) {
458 // full native scaling to dstInfo dimensions not supported 405 return SkCodec::kInvalidScale;
459
460 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) {
461 return SkCodec::kInvalidScale;
462 }
463 // create swizzler for sampling
464 SkCodec::Result result = this->initializeSwizzler(dstInfo, options);
465 if (SkCodec::kSuccess != result) {
466 SkCodecPrintf("failed to initialize the swizzler.\n");
467 return result;
468 }
469 fStorage.reset(get_row_bytes(fCodec->fDecoderMgr->dinfo()));
470 fSrcRow = static_cast<uint8_t*>(fStorage.get());
471 } else {
472 fSrcRow = NULL;
473 fSwizzler.reset(NULL);
474 } 406 }
475 407
476 // Now, given valid output dimensions, we can start the decompress 408 // Now, given valid output dimensions, we can start the decompress
477 if (!chromium_jpeg_start_decompress(fCodec->fDecoderMgr->dinfo())) { 409 if (!chromium_jpeg_start_decompress(fCodec->fDecoderMgr->dinfo())) {
478 SkCodecPrintf("start decompress failed\n"); 410 SkCodecPrintf("start decompress failed\n");
479 return SkCodec::kInvalidInput; 411 return SkCodec::kInvalidInput;
480 } 412 }
481 413
482 fOpts = options; 414 fOpts = options;
483 415
(...skipping 10 matching lines...) Expand all
494 // partial decode. 426 // partial decode.
495 fCodec->fDecoderMgr->dinfo()->output_scanline = fCodec->getInfo().height (); 427 fCodec->fDecoderMgr->dinfo()->output_scanline = fCodec->getInfo().height ();
496 chromium_jpeg_finish_decompress(fCodec->fDecoderMgr->dinfo()); 428 chromium_jpeg_finish_decompress(fCodec->fDecoderMgr->dinfo());
497 } 429 }
498 430
499 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de { 431 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de {
500 // Set the jump location for libjpeg errors 432 // Set the jump location for libjpeg errors
501 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { 433 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
502 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput); 434 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput);
503 } 435 }
436
504 // Read rows one at a time 437 // Read rows one at a time
505 JSAMPLE* dstRow; 438 JSAMPLE* dstRow = (JSAMPLE*) dst;
506 if (fSwizzler) {
507 // write data to storage row, then sample using swizzler
508 dstRow = fSrcRow;
509 } else {
510 // write data directly to dst
511 dstRow = (JSAMPLE*) dst;
512 }
513
514 for (int y = 0; y < count; y++) { 439 for (int y = 0; y < count; y++) {
515 // Read row of the image 440 // Read row of the image
516 uint32_t rowsDecoded = 441 uint32_t rowsDecoded =
517 chromium_jpeg_read_scanlines(fCodec->fDecoderMgr->dinfo(), & dstRow, 1); 442 chromium_jpeg_read_scanlines(fCodec->fDecoderMgr->dinfo(), & dstRow, 1);
518 if (rowsDecoded != 1) { 443 if (rowsDecoded != 1) {
519 if (SkCodec::kNo_ZeroInitialized == fOpts.fZeroInitialized || 444 if (SkCodec::kNo_ZeroInitialized == fOpts.fZeroInitialized ||
520 kN32_SkColorType == this->dstInfo().colorType()) { 445 kN32_SkColorType == this->dstInfo().colorType()) {
521 SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes, 446 SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes,
522 count - y, SK_ColorBLACK, NULL); 447 count - y, SK_ColorBLACK, NULL);
523 } 448 }
524 fCodec->fDecoderMgr->dinfo()->output_scanline = this->dstInfo(). height(); 449 fCodec->fDecoderMgr->dinfo()->output_scanline = this->dstInfo(). height();
525 return SkCodec::kIncompleteInput; 450 return SkCodec::kIncompleteInput;
526 } 451 }
527 452
528 // Convert to RGBA if necessary 453 // Convert to RGBA if necessary
529 if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) { 454 if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) {
530 convert_CMYK_to_RGBA(dstRow, fCodec->fDecoderMgr->dinfo()->outpu t_width); 455 convert_CMYK_to_RGBA(dstRow, this->dstInfo().width());
531 } 456 }
532 457
533 if(fSwizzler) { 458 // Move to the next row
534 // use swizzler to sample row 459 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes);
535 fSwizzler->swizzle(dst, dstRow);
536 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes);
537 } else {
538 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes);
539 }
540 } 460 }
461
541 return SkCodec::kSuccess; 462 return SkCodec::kSuccess;
542 } 463 }
543 464
544 #ifndef TURBO_HAS_SKIP 465 #ifndef TURBO_HAS_SKIP
545 // TODO (msarett): Make this a member function and avoid reallocating the 466 // TODO (msarett): Make this a member function and avoid reallocating the
546 // memory buffer on each call to skip. 467 // memory buffer on each call to skip.
547 #define chromium_jpeg_skip_scanlines(dinfo, count) \ 468 #define chromium_jpeg_skip_scanlines(dinfo, count) \
548 SkAutoMalloc storage(get_row_bytes(dinfo)); \ 469 SkAutoMalloc storage(dinfo->output_width * dinfo->out_color_components); \
549 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \ 470 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \
550 for (int y = 0; y < count; y++) { \ 471 for (int y = 0; y < count; y++) { \
551 chromium_jpeg_read_scanlines(dinfo, &storagePtr, 1); \ 472 chromium_jpeg_read_scanlines(dinfo, &storagePtr, 1); \
552 } 473 }
553 #endif 474 #endif
554 475
555 SkCodec::Result onSkipScanlines(int count) override { 476 SkCodec::Result onSkipScanlines(int count) override {
556 // Set the jump location for libjpeg errors 477 // Set the jump location for libjpeg errors
557 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { 478 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
558 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput); 479 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput);
559 } 480 }
560 481
561 chromium_jpeg_skip_scanlines(fCodec->fDecoderMgr->dinfo(), count); 482 chromium_jpeg_skip_scanlines(fCodec->fDecoderMgr->dinfo(), count);
562 483
563 return SkCodec::kSuccess; 484 return SkCodec::kSuccess;
564 } 485 }
565 486
566 SkEncodedFormat onGetEncodedFormat() const override { 487 #ifndef TURBO_HAS_SKIP
567 return kJPEG_SkEncodedFormat; 488 #undef chromium_jpeg_skip_scanlines
568 } 489 #endif
569 490
570 private: 491 private:
571 SkAutoTDelete<SkJpegCodec> fCodec; 492 SkAutoTDelete<SkJpegCodec> fCodec;
572 SkAutoMalloc fStorage; // Only used if sampling is needed
573 uint8_t* fSrcRow; // Only used if sampling is needed
574 SkCodec::Options fOpts; 493 SkCodec::Options fOpts;
575 SkAutoTDelete<SkSwizzler> fSwizzler;
576 494
577 typedef SkScanlineDecoder INHERITED; 495 typedef SkScanlineDecoder INHERITED;
578 }; 496 };
579 497
580 SkScanlineDecoder* SkJpegCodec::NewSDFromStream(SkStream* stream) { 498 SkScanlineDecoder* SkJpegCodec::NewSDFromStream(SkStream* stream) {
581 SkAutoTDelete<SkJpegCodec> codec(static_cast<SkJpegCodec*>(SkJpegCodec::NewF romStream(stream))); 499 SkAutoTDelete<SkJpegCodec> codec(static_cast<SkJpegCodec*>(SkJpegCodec::NewF romStream(stream)));
582 if (!codec) { 500 if (!codec) {
583 return NULL; 501 return NULL;
584 } 502 }
585 503
586 const SkImageInfo& srcInfo = codec->getInfo(); 504 const SkImageInfo& srcInfo = codec->getInfo();
587
588 // Return the new scanline decoder 505 // Return the new scanline decoder
589 return SkNEW_ARGS(SkJpegScanlineDecoder, (srcInfo, codec.detach())); 506 return SkNEW_ARGS(SkJpegScanlineDecoder, (srcInfo, codec.detach()));
590 } 507 }
OLDNEW
« no previous file with comments | « src/codec/SkJpegCodec.h ('k') | src/codec/SkScaledCodec.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698