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

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

Issue 2247743002: Fix color xform width bug when scaling/subsetting (Closed) Base URL: https://skia.googlesource.com/skia.git@skipstuff
Patch Set: Rebase Created 4 years, 3 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/SkPngCodec.h ('k') | src/codec/SkSwizzler.h » ('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 "SkBitmap.h" 8 #include "SkBitmap.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 case kBGRA_8888_SkColorType: 351 case kBGRA_8888_SkColorType:
352 case kRGBA_F16_SkColorType: 352 case kRGBA_F16_SkColorType:
353 return true; 353 return true;
354 case kRGB_565_SkColorType: 354 case kRGB_565_SkColorType:
355 return kOpaque_SkAlphaType == src.alphaType(); 355 return kOpaque_SkAlphaType == src.alphaType();
356 default: 356 default:
357 return dst.colorType() == src.colorType(); 357 return dst.colorType() == src.colorType();
358 } 358 }
359 } 359 }
360 360
361 void SkPngCodec::allocateStorage(const SkImageInfo& dstInfo) { 361 void SkPngCodec::allocateStorage() {
362 const int width = this->getInfo().width(); 362 size_t colorXformBytes = fColorXform ? fSwizzler->swizzleWidth() * sizeof(ui nt32_t) : 0;
363 size_t colorXformBytes = fColorXform ? width * sizeof(uint32_t) : 0;
364 363
365 fStorage.reset(SkAlign4(fSrcRowBytes) + colorXformBytes); 364 fStorage.reset(SkAlign4(fSrcRowBytes) + colorXformBytes);
366 fSwizzlerSrcRow = fStorage.get(); 365 fSwizzlerSrcRow = fStorage.get();
367 fColorXformSrcRow = 366 fColorXformSrcRow =
368 fColorXform ? SkTAddOffset<uint32_t>(fSwizzlerSrcRow, SkAlign4(fSrcR owBytes)) : 0; 367 fColorXform ? SkTAddOffset<uint32_t>(fSwizzlerSrcRow, SkAlign4(fSrcR owBytes)) : 0;
369 } 368 }
370 369
371 class SkPngNormalCodec : public SkPngCodec { 370 class SkPngNormalCodec : public SkPngCodec {
372 public: 371 public:
373 SkPngNormalCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageI nfo, 372 SkPngNormalCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageI nfo,
374 SkStream* stream, SkPngChunkReader* chunkReader, png_structp png_ptr , 373 SkStream* stream, SkPngChunkReader* chunkReader, png_structp png_ptr ,
375 png_infop info_ptr, int bitDepth) 374 png_infop info_ptr, int bitDepth)
376 : INHERITED(encodedInfo, imageInfo, stream, chunkReader, png_ptr, info_p tr, bitDepth, 1) 375 : INHERITED(encodedInfo, imageInfo, stream, chunkReader, png_ptr, info_p tr, bitDepth, 1)
377 {} 376 {}
378 377
379 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, 378 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons,
380 SkPMColor ctable[], int* ctableCount) override { 379 SkPMColor ctable[], int* ctableCount) override {
381 if (!png_conversion_possible(dstInfo, this->getInfo()) || 380 if (!png_conversion_possible(dstInfo, this->getInfo()) ||
382 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) 381 !this->initializeXforms(dstInfo, options, ctable, ctableCount))
383 { 382 {
384 return kInvalidConversion; 383 return kInvalidConversion;
385 } 384 }
386 385
387 this->allocateStorage(dstInfo); 386 this->allocateStorage();
388 return kSuccess; 387 return kSuccess;
389 } 388 }
390 389
391 int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int cou nt, int startRow) 390 int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int cou nt, int startRow)
392 override { 391 override {
393 SkASSERT(0 == startRow); 392 SkASSERT(0 == startRow);
394 393
395 // Assume that an error in libpng indicates an incomplete input. 394 // Assume that an error in libpng indicates an incomplete input.
396 int y = 0; 395 int y = 0;
397 if (setjmp(png_jmpbuf(fPng_ptr))) { 396 if (setjmp(png_jmpbuf(fPng_ptr))) {
398 SkCodecPrintf("Failed to read row.\n"); 397 SkCodecPrintf("Failed to read row.\n");
399 return y; 398 return y;
400 } 399 }
401 400
402 void* swizzlerDstRow = dst; 401 void* swizzlerDstRow = dst;
403 size_t swizzlerDstRowBytes = rowBytes; 402 size_t swizzlerDstRowBytes = rowBytes;
404 if (fColorXform) { 403 if (fColorXform) {
405 swizzlerDstRow = fColorXformSrcRow; 404 swizzlerDstRow = fColorXformSrcRow;
406 swizzlerDstRowBytes = 0; 405 swizzlerDstRowBytes = 0;
407 } 406 }
408 407
409 SkAlphaType xformAlphaType = (kOpaque_SkAlphaType == this->getInfo().alp haType()) ? 408 SkAlphaType xformAlphaType = (kOpaque_SkAlphaType == this->getInfo().alp haType()) ?
410 kOpaque_SkAlphaType : dstInfo.alphaType(); 409 kOpaque_SkAlphaType : dstInfo.alphaType();
411 for (; y < count; y++) { 410 for (; y < count; y++) {
412 png_read_row(fPng_ptr, fSwizzlerSrcRow, nullptr); 411 png_read_row(fPng_ptr, fSwizzlerSrcRow, nullptr);
413 fSwizzler->swizzle(swizzlerDstRow, fSwizzlerSrcRow); 412 fSwizzler->swizzle(swizzlerDstRow, fSwizzlerSrcRow);
414 413
415 if (fColorXform) { 414 if (fColorXform) {
416 fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, dstInf o.width(), 415 fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, fSwizz ler->swizzleWidth(),
417 dstInfo.colorType(), xformAlphaType); 416 dstInfo.colorType(), xformAlphaType);
418 dst = SkTAddOffset<void>(dst, rowBytes); 417 dst = SkTAddOffset<void>(dst, rowBytes);
419 } 418 }
420 419
421 swizzlerDstRow = SkTAddOffset<void>(swizzlerDstRow, swizzlerDstRowBy tes); 420 swizzlerDstRow = SkTAddOffset<void>(swizzlerDstRow, swizzlerDstRowBy tes);
422 } 421 }
423 422
424 return y; 423 return y;
425 } 424 }
426 425
(...skipping 30 matching lines...) Expand all
457 } 456 }
458 457
459 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, 458 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons,
460 SkPMColor ctable[], int* ctableCount) override { 459 SkPMColor ctable[], int* ctableCount) override {
461 if (!png_conversion_possible(dstInfo, this->getInfo()) || 460 if (!png_conversion_possible(dstInfo, this->getInfo()) ||
462 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) 461 !this->initializeXforms(dstInfo, options, ctable, ctableCount))
463 { 462 {
464 return kInvalidConversion; 463 return kInvalidConversion;
465 } 464 }
466 465
467 this->allocateStorage(dstInfo); 466 this->allocateStorage();
468 fCanSkipRewind = true; 467 fCanSkipRewind = true;
469 return SkCodec::kSuccess; 468 return SkCodec::kSuccess;
470 } 469 }
471 470
472 int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int cou nt, int startRow) 471 int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int cou nt, int startRow)
473 override { 472 override {
474 if (setjmp(png_jmpbuf(fPng_ptr))) { 473 if (setjmp(png_jmpbuf(fPng_ptr))) {
475 SkCodecPrintf("Failed to get scanlines.\n"); 474 SkCodecPrintf("Failed to get scanlines.\n");
476 // FIXME (msarett): Returning 0 is pessimistic. If we can complete a single pass, 475 // FIXME (msarett): Returning 0 is pessimistic. If we can complete a single pass,
477 // we may be able to report that all of the memory has been initiali zed. Even if we 476 // we may be able to report that all of the memory has been initiali zed. Even if we
(...skipping 30 matching lines...) Expand all
508 507
509 SkAlphaType xformAlphaType = (kOpaque_SkAlphaType == this->getInfo().alp haType()) ? 508 SkAlphaType xformAlphaType = (kOpaque_SkAlphaType == this->getInfo().alp haType()) ?
510 kOpaque_SkAlphaType : dstInfo.alphaType(); 509 kOpaque_SkAlphaType : dstInfo.alphaType();
511 srcRow = storage.get(); 510 srcRow = storage.get();
512 for (int y = 0; y < count; y++) { 511 for (int y = 0; y < count; y++) {
513 fSwizzler->swizzle(swizzlerDstRow, srcRow); 512 fSwizzler->swizzle(swizzlerDstRow, srcRow);
514 srcRow = SkTAddOffset<uint8_t>(srcRow, fSrcRowBytes); 513 srcRow = SkTAddOffset<uint8_t>(srcRow, fSrcRowBytes);
515 514
516 if (fColorXform) { 515 if (fColorXform) {
517 if (fColorXform) { 516 if (fColorXform) {
518 fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, ds tInfo.width(), 517 fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow,
519 dstInfo.colorType(), xformAlphaType); 518 fSwizzler->swizzleWidth(), dstInfo.colorT ype(),
519 xformAlphaType);
520 dst = SkTAddOffset<void>(dst, rowBytes); 520 dst = SkTAddOffset<void>(dst, rowBytes);
521 } 521 }
522 } 522 }
523 523
524 swizzlerDstRow = SkTAddOffset<void>(swizzlerDstRow, swizzlerDstRowBy tes); 524 swizzlerDstRow = SkTAddOffset<void>(swizzlerDstRow, swizzlerDstRowBy tes);
525 } 525 }
526 526
527 return count; 527 return count;
528 } 528 }
529 529
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 if (!png_conversion_possible(dstInfo, this->getInfo()) || 858 if (!png_conversion_possible(dstInfo, this->getInfo()) ||
859 !this->initializeXforms(dstInfo, options, ctable, ctableCount)) 859 !this->initializeXforms(dstInfo, options, ctable, ctableCount))
860 { 860 {
861 return kInvalidConversion; 861 return kInvalidConversion;
862 } 862 }
863 863
864 if (options.fSubset) { 864 if (options.fSubset) {
865 return kUnimplemented; 865 return kUnimplemented;
866 } 866 }
867 867
868 this->allocateStorage(dstInfo); 868 this->allocateStorage();
869 int count = this->readRows(dstInfo, dst, rowBytes, dstInfo.height(), 0); 869 int count = this->readRows(dstInfo, dst, rowBytes, dstInfo.height(), 0);
870 if (count > dstInfo.height()) { 870 if (count > dstInfo.height()) {
871 *rowsDecoded = count; 871 *rowsDecoded = count;
872 return kIncompleteInput; 872 return kIncompleteInput;
873 } 873 }
874 874
875 return kSuccess; 875 return kSuccess;
876 } 876 }
877 877
878 uint32_t SkPngCodec::onGetFillValue(SkColorType colorType) const { 878 uint32_t SkPngCodec::onGetFillValue(SkColorType colorType) const {
(...skipping 10 matching lines...) Expand all
889 SkCodec* outCodec; 889 SkCodec* outCodec;
890 if (read_header(stream, chunkReader, &outCodec, nullptr, nullptr)) { 890 if (read_header(stream, chunkReader, &outCodec, nullptr, nullptr)) {
891 // Codec has taken ownership of the stream. 891 // Codec has taken ownership of the stream.
892 SkASSERT(outCodec); 892 SkASSERT(outCodec);
893 streamDeleter.release(); 893 streamDeleter.release();
894 return outCodec; 894 return outCodec;
895 } 895 }
896 896
897 return nullptr; 897 return nullptr;
898 } 898 }
OLDNEW
« no previous file with comments | « src/codec/SkPngCodec.h ('k') | src/codec/SkSwizzler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698