DM testing for skipping and scaling
authormsarett <msarett@google.com>
Thu, 11 Jun 2015 21:27:27 +0000 (14:27 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 11 Jun 2015 21:27:28 +0000 (14:27 -0700)
BUG=skia:

Review URL: https://codereview.chromium.org/1175993005

dm/DM.cpp
dm/DMSrcSink.cpp
dm/DMSrcSink.h

index 0174b73..684ae80 100644 (file)
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -205,38 +205,54 @@ static void push_codec_srcs(Path path) {
         return;
     }
 
-    // Build additional test cases for images that decode natively to non-canvas types
-    switch(codec->getInfo().colorType()) {
-        case kGray_8_SkColorType:
-            push_src("image", "codec_kGray8", new CodecSrc(path, CodecSrc::kNormal_Mode,
-                    CodecSrc::kGrayscale_Always_DstColorType));
-            push_src("image", "scanline_kGray8", new CodecSrc(path, CodecSrc::kScanline_Mode,
-                    CodecSrc::kGrayscale_Always_DstColorType));
-            push_src("image", "scanline_subset_kGray8", new CodecSrc(path,
-                    CodecSrc::kScanline_Subset_Mode, CodecSrc::kGrayscale_Always_DstColorType));
-            // Intentional fall through
-            // FIXME: Is this a long term solution for testing wbmps decodes to kIndex8?
-            // Further discussion on this topic is at skbug.com/3683
-        case kIndex_8_SkColorType:
-            push_src("image", "codec_kIndex8", new CodecSrc(path, CodecSrc::kNormal_Mode,
-                    CodecSrc::kIndex8_Always_DstColorType));
-            push_src("image", "scanline_kIndex8", new CodecSrc(path, CodecSrc::kScanline_Mode,
-                    CodecSrc::kIndex8_Always_DstColorType));
-            push_src("image", "scanline_subset_kIndex8", new CodecSrc(path,
-                    CodecSrc::kScanline_Subset_Mode, CodecSrc::kIndex8_Always_DstColorType));
-            break;
-        default:
-            // Do nothing
-            break;
-    }
-
-    // Decode all images to the canvas color type
-    push_src("image", "codec", new CodecSrc(path, CodecSrc::kNormal_Mode,
-            CodecSrc::kGetFromCanvas_DstColorType));
-    push_src("image", "scanline", new CodecSrc(path, CodecSrc::kScanline_Mode,
-            CodecSrc::kGetFromCanvas_DstColorType));
-    push_src("image", "scanline_subset", new CodecSrc(path, CodecSrc::kScanline_Subset_Mode,
-            CodecSrc::kGetFromCanvas_DstColorType));
+    // Choose scales for scaling tests.
+    // TODO (msarett): Add more scaling tests as we implement more flexible scaling.
+    // TODO (msarett): Implement scaling tests for SkImageDecoder in order to compare with these
+    //                 tests.  SkImageDecoder supports downscales by integer factors.
+    const float scales[] = { 0.125f, 0.25f, 0.5f, 1.0f };
+
+    for (float scale : scales) {
+        // Build additional test cases for images that decode natively to non-canvas types
+        switch(codec->getInfo().colorType()) {
+            case kGray_8_SkColorType:
+                push_src("image", "codec_kGray8", new CodecSrc(path, CodecSrc::kNormal_Mode,
+                        CodecSrc::kGrayscale_Always_DstColorType, scale));
+                push_src("image", "scanline_kGray8", new CodecSrc(path, CodecSrc::kScanline_Mode,
+                        CodecSrc::kGrayscale_Always_DstColorType, scale));
+                push_src("image", "scanline_subset_kGray8", new CodecSrc(path,
+                        CodecSrc::kScanline_Subset_Mode, CodecSrc::kGrayscale_Always_DstColorType,
+                        scale));
+                push_src("image", "stripe_kGray8", new CodecSrc(path, CodecSrc::kStripe_Mode,
+                        CodecSrc::kGrayscale_Always_DstColorType, scale));
+                // Intentional fall through
+                // FIXME: Is this a long term solution for testing wbmps decodes to kIndex8?
+                // Further discussion on this topic is at skbug.com/3683
+            case kIndex_8_SkColorType:
+                push_src("image", "codec_kIndex8", new CodecSrc(path, CodecSrc::kNormal_Mode,
+                        CodecSrc::kIndex8_Always_DstColorType, scale));
+                push_src("image", "scanline_kIndex8", new CodecSrc(path, CodecSrc::kScanline_Mode,
+                        CodecSrc::kIndex8_Always_DstColorType, scale));
+                push_src("image", "scanline_subset_kIndex8", new CodecSrc(path,
+                        CodecSrc::kScanline_Subset_Mode, CodecSrc::kIndex8_Always_DstColorType,
+                        scale));
+                push_src("image", "stripe_kIndex8", new CodecSrc(path, CodecSrc::kStripe_Mode,
+                        CodecSrc::kIndex8_Always_DstColorType, scale));
+                break;
+            default:
+                // Do nothing
+                break;
+        }
+
+        // Decode all images to the canvas color type
+        push_src("image", "codec", new CodecSrc(path, CodecSrc::kNormal_Mode,
+                CodecSrc::kGetFromCanvas_DstColorType, scale));
+        push_src("image", "scanline", new CodecSrc(path, CodecSrc::kScanline_Mode,
+                CodecSrc::kGetFromCanvas_DstColorType, scale));
+        push_src("image", "scanline_subset", new CodecSrc(path, CodecSrc::kScanline_Subset_Mode,
+                CodecSrc::kGetFromCanvas_DstColorType, scale));
+        push_src("image", "stripe", new CodecSrc(path, CodecSrc::kStripe_Mode,
+                CodecSrc::kGetFromCanvas_DstColorType, scale));
+    }
 }
 
 static bool codec_supported(const char* ext) {
index 0a90e03..c89ffd1 100644 (file)
@@ -64,10 +64,11 @@ void GMSrc::modifyGrContextOptions(GrContextOptions* options) const {
 
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
-CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType)
+CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, float scale)
     : fPath(path)
     , fMode(mode)
     , fDstColorType(dstColorType)
+    , fScale(scale)
 {}
 
 Error CodecSrc::draw(SkCanvas* canvas) const {
@@ -108,6 +109,13 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
             break;
     }
 
+    // Try to scale the image if it is desired
+    SkISize size = codec->getScaledDimensions(fScale);
+    if (size == decodeInfo.dimensions() && 1.0f != fScale) {
+        return Error::Nonfatal("Test without scaling is uninteresting.");
+    }
+    decodeInfo = decodeInfo.makeWH(size.width(), size.height());
+
     // Construct a color table for the decode if necessary
     SkAutoTUnref<SkColorTable> colorTable(NULL);
     SkPMColor* colorPtr = NULL;
@@ -195,7 +203,7 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
             * subsetBm's size is determined based on the current subset and may be larger for end
             * subsets.
             */
-            SkImageInfo largestSubsetDecodeInfo = 
+            SkImageInfo largestSubsetDecodeInfo =
                     decodeInfo.makeWH(subsetWidth + extraX, subsetHeight + extraY);
             SkBitmap largestSubsetBm;
             if (!largestSubsetBm.tryAllocPixels(largestSubsetDecodeInfo, NULL, colorTable.get())) {
@@ -226,7 +234,7 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
                         }
                     }
                     //skip to first line of subset
-                    const SkImageGenerator::Result skipResult = 
+                    const SkImageGenerator::Result skipResult =
                             subsetScanlineDecoder->skipScanlines(y);
                     switch (skipResult) {
                         case SkImageGenerator::kSuccess:
@@ -262,6 +270,80 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
             }
             break;
         }
+        case kStripe_Mode: {
+            const int height = decodeInfo.height();
+            // This value is chosen arbitrarily.  We exercise more cases by choosing a value that
+            // does not align with image blocks.
+            const int stripeHeight = 37;
+            const int numStripes = (height + stripeHeight - 1) / stripeHeight;
+
+            // Decode odd stripes
+            SkScanlineDecoder* decoder = codec->getScanlineDecoder(decodeInfo, NULL, colorPtr,
+                    colorCountPtr);
+            if (NULL == decoder) {
+                return Error::Nonfatal("Cannot use scanline decoder for all images");
+            }
+            for (int i = 0; i < numStripes; i += 2) {
+                // Skip a stripe
+                const int linesToSkip = SkTMin(stripeHeight, height - i * stripeHeight);
+                SkImageGenerator::Result result = decoder->skipScanlines(linesToSkip);
+                switch (result) {
+                    case SkImageGenerator::kSuccess:
+                    case SkImageGenerator::kIncompleteInput:
+                        break;
+                    default:
+                        return SkStringPrintf("Cannot skip scanlines for %s.", fPath.c_str());
+                }
+
+                // Read a stripe
+                const int startY = (i + 1) * stripeHeight;
+                const int linesToRead = SkTMin(stripeHeight, height - startY);
+                if (linesToRead > 0) {
+                    result = decoder->getScanlines(bitmap.getAddr(0, startY),
+                            linesToRead, bitmap.rowBytes());
+                    switch (result) {
+                        case SkImageGenerator::kSuccess:
+                        case SkImageGenerator::kIncompleteInput:
+                            break;
+                        default:
+                            return SkStringPrintf("Cannot get scanlines for %s.", fPath.c_str());
+                    }
+                }
+            }
+
+            // Decode even stripes
+            decoder = codec->getScanlineDecoder(decodeInfo, NULL, colorPtr, colorCountPtr);
+            if (NULL == decoder) {
+                return "Failed to create second scanline decoder.";
+            }
+            for (int i = 0; i < numStripes; i += 2) {
+                // Read a stripe
+                const int startY = i * stripeHeight;
+                const int linesToRead = SkTMin(stripeHeight, height - startY);
+                SkImageGenerator::Result result = decoder->getScanlines(bitmap.getAddr(0, startY),
+                        linesToRead, bitmap.rowBytes());
+                switch (result) {
+                    case SkImageGenerator::kSuccess:
+                    case SkImageGenerator::kIncompleteInput:
+                        break;
+                    default:
+                        return SkStringPrintf("Cannot get scanlines for %s.", fPath.c_str());
+                }
+
+                // Skip a stripe
+                const int linesToSkip = SkTMax(0, SkTMin(stripeHeight,
+                        height - (i + 1) * stripeHeight));
+                result = decoder->skipScanlines(linesToSkip);
+                switch (result) {
+                    case SkImageGenerator::kSuccess:
+                    case SkImageGenerator::kIncompleteInput:
+                        break;
+                    default:
+                        return SkStringPrintf("Cannot skip scanlines for %s.", fPath.c_str());
+                }
+            }
+            canvas->drawBitmap(bitmap, 0, 0);
+        }
     }
     return "";
 }
@@ -270,14 +352,19 @@ SkISize CodecSrc::size() const {
     SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
     SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
     if (NULL != codec) {
-        return codec->getInfo().dimensions();
+        SkISize size = codec->getScaledDimensions(fScale);
+        return size;
     } else {
         return SkISize::Make(0, 0);
     }
 }
 
 Name CodecSrc::name() const {
-    return SkOSPath::Basename(fPath.c_str());
+    if (1.0f == fScale) {
+        return SkOSPath::Basename(fPath.c_str());
+    } else {
+        return SkStringPrintf("%s_%.3f", SkOSPath::Basename(fPath.c_str()).c_str(), fScale);
+    }
 }
 
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
index bd8c41e..b7c28ed 100644 (file)
@@ -98,13 +98,14 @@ public:
         kNormal_Mode,
         kScanline_Mode,
         kScanline_Subset_Mode,
+        kStripe_Mode, // Tests the skipping of scanlines
     };
     enum DstColorType {
         kGetFromCanvas_DstColorType,
         kIndex8_Always_DstColorType,
         kGrayscale_Always_DstColorType,
     };
-    CodecSrc(Path, Mode, DstColorType);
+    CodecSrc(Path, Mode, DstColorType, float);
 
     Error draw(SkCanvas*) const override;
     SkISize size() const override;
@@ -113,6 +114,7 @@ private:
     Path                   fPath;
     Mode                   fMode;
     DstColorType           fDstColorType;
+    float                  fScale;
 };