 Chromium Code Reviews
 Chromium Code Reviews Issue 1287423002:
  Scanline decoding for bmp  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@master
    
  
    Issue 1287423002:
  Scanline decoding for bmp  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@master| Index: src/codec/SkScaledCodec.cpp | 
| diff --git a/src/codec/SkScaledCodec.cpp b/src/codec/SkScaledCodec.cpp | 
| index 7ff279c21742d6d2e7f05b0a3c1175c6bab8c5fe..a90db78ad1afc87a885333be014b9430a5b15554 100644 | 
| --- a/src/codec/SkScaledCodec.cpp | 
| +++ b/src/codec/SkScaledCodec.cpp | 
| @@ -139,6 +139,28 @@ static bool scaling_supported(const SkImageInfo& dstInfo, const SkImageInfo& src | 
| return true; | 
| } | 
| +inline int SkScaledCodec::GetStartCoord(int sampleFactor) { | 
| + return sampleFactor / 2; | 
| +} | 
| + | 
| +inline int SkScaledCodec::GetDstCoord(int srcCoord, int sampleFactor) { | 
| + return srcCoord / sampleFactor; | 
| +} | 
| + | 
| +bool SkScaledCodec::IsCoordNecessary(int srcCoord, int sampleFactor, int scaledDim) { | 
| + // Get the first coordinate that we want to keep | 
| + int startCoord = GetStartCoord(sampleFactor); | 
| + | 
| + // Return false on edge cases | 
| + if (srcCoord < startCoord || | 
| + SkScaledCodec::GetDstCoord(srcCoord, sampleFactor) >= scaledDim) { | 
| + return false; | 
| + } | 
| + | 
| + // Every sampleFactor rows are necessary | 
| + return ((srcCoord - startCoord) % sampleFactor) == 0; | 
| +} | 
| + | 
| // calculates sampleSize in x and y direction | 
| void SkScaledCodec::ComputeSampleSize(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo, | 
| int* sampleXPtr, int* sampleYPtr) { | 
| @@ -198,7 +220,6 @@ SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi | 
| if (kSuccess == result) { | 
| // native decode supported | 
| return fScanlineDecoder->getScanlines(dst, requestedInfo.height(), rowBytes); | 
| - | 
| } | 
| if (kInvalidScale != result) { | 
| @@ -213,7 +234,7 @@ SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi | 
| return kInvalidScale; | 
| } | 
| // set first sample pixel in y direction | 
| - int Y0 = sampleY >> 1; | 
| + int Y0 = SkScaledCodec::GetStartCoord(sampleY); | 
| int dstHeight = requestedInfo.height(); | 
| int srcHeight = fScanlineDecoder->getInfo().height(); | 
| @@ -227,41 +248,65 @@ SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi | 
| if (kSuccess != result) { | 
| return result; | 
| } | 
| - | 
| - const bool requiresPostYSampling = fScanlineDecoder->requiresPostYSampling(); | 
| - | 
| - if (requiresPostYSampling) { | 
| - SkAutoMalloc storage(srcHeight * rowBytes); | 
| - uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); | 
| - result = fScanlineDecoder->getScanlines(storagePtr, srcHeight, rowBytes); | 
| - if (kSuccess != result) { | 
| - return result; | 
| - } | 
| - storagePtr += Y0 * rowBytes; | 
| - for (int y = 0; y < dstHeight; y++) { | 
| - memcpy(dst, storagePtr, rowBytes); | 
| - storagePtr += sampleY * rowBytes; | 
| - dst = SkTAddOffset<void>(dst, rowBytes); | 
| + | 
| + switch(fScanlineDecoder->getScanlineOrder()) { | 
| + case SkScanlineDecoder::kTopDown_SkScanlineOrder: { | 
| + result = fScanlineDecoder->skipScanlines(Y0); | 
| + if (kSuccess != result && kIncompleteInput != result) { | 
| + return result; | 
| + } | 
| + for (int y = 0; y < dstHeight; y++) { | 
| + result = fScanlineDecoder->getScanlines(dst, 1, rowBytes); | 
| + if (kSuccess != result && kIncompleteInput != result) { | 
| + return result; | 
| + } | 
| + if (y < dstHeight - 1) { | 
| + result = fScanlineDecoder->skipScanlines(sampleY - 1); | 
| + if (kSuccess != result && kIncompleteInput != result) { | 
| + return result; | 
| + } | 
| + } | 
| + dst = SkTAddOffset<void>(dst, rowBytes); | 
| + } | 
| + return kSuccess; | 
| } | 
| - } else { | 
| - // does not require post y sampling | 
| - result = fScanlineDecoder->skipScanlines(Y0); | 
| - if (kSuccess != result) { | 
| - return result; | 
| + case SkScanlineDecoder::kBottomUp_SkScanlineOrder: | 
| 
scroggo
2015/08/28 13:28:47
Is this the bug fix listed in the patch set descri
 
msarett
2015/08/28 14:05:57
Yes, sorry this was unclear.
 | 
| + case SkScanlineDecoder::kOutOfOrder_SkScanlineOrder: { | 
| + for (int y = 0; y < srcHeight; y++) { | 
| + int srcY = fScanlineDecoder->getY(); | 
| + if (SkScaledCodec::IsCoordNecessary(srcY, sampleY, dstHeight)) { | 
| + void* dstPtr = SkTAddOffset<void>(dst, | 
| + rowBytes * SkScaledCodec::GetDstCoord(srcY, sampleY)); | 
| + result = fScanlineDecoder->getScanlines(dstPtr, 1, rowBytes); | 
| + if (kSuccess != result && kIncompleteInput != result) { | 
| + return result; | 
| + } | 
| + } else { | 
| + result = fScanlineDecoder->skipScanlines(1); | 
| + if (kSuccess != result && kIncompleteInput != result) { | 
| + return result; | 
| + } | 
| + } | 
| + } | 
| + return kSuccess; | 
| } | 
| - for (int y = 0; y < dstHeight; y++) { | 
| - result = fScanlineDecoder->getScanlines(dst, 1, rowBytes); | 
| + case SkScanlineDecoder::kNone_SkScanlineOrder: { | 
| + SkAutoMalloc storage(srcHeight * rowBytes); | 
| + uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); | 
| + result = fScanlineDecoder->getScanlines(storagePtr, srcHeight, rowBytes); | 
| if (kSuccess != result) { | 
| return result; | 
| } | 
| - if (y < dstHeight - 1) { | 
| - result = fScanlineDecoder->skipScanlines(sampleY - 1); | 
| - if (kSuccess != result) { | 
| - return result; | 
| - } | 
| + storagePtr += Y0 * rowBytes; | 
| + for (int y = 0; y < dstHeight; y++) { | 
| + memcpy(dst, storagePtr, rowBytes); | 
| + storagePtr += sampleY * rowBytes; | 
| + dst = SkTAddOffset<void>(dst, rowBytes); | 
| } | 
| - dst = SkTAddOffset<void>(dst, rowBytes); | 
| + return kSuccess; | 
| } | 
| + default: | 
| + SkASSERT(false); | 
| + return kUnimplemented; | 
| } | 
| - return kSuccess; | 
| } |