| Index: tools/skimage_main.cpp
|
| diff --git a/tools/skimage_main.cpp b/tools/skimage_main.cpp
|
| index 7906386cdce2fb7f25999863f0c215826a7349ac..688d3a22753eb943d89245827eb78898dd541569 100644
|
| --- a/tools/skimage_main.cpp
|
| +++ b/tools/skimage_main.cpp
|
| @@ -13,6 +13,7 @@
|
| #include "SkImageDecoder.h"
|
| #include "SkImageEncoder.h"
|
| #include "SkOSFile.h"
|
| +#include "SkRandom.h"
|
| #include "SkStream.h"
|
| #include "SkTArray.h"
|
| #include "SkTemplates.h"
|
| @@ -20,6 +21,7 @@
|
| DEFINE_string2(readPath, r, "", "Folder(s) and files to decode images. Required.");
|
| DEFINE_string2(writePath, w, "", "Write rendered images into this directory.");
|
| DEFINE_bool(reencode, true, "Reencode the images to test encoding.");
|
| +DEFINE_bool(testSubsetDecoding, true, "Test decoding subsets of images.");
|
|
|
| struct Format {
|
| SkImageEncoder::Type fType;
|
| @@ -92,6 +94,8 @@ static SkTArray<SkString, false> gMissingCodecs;
|
| static SkTArray<SkString, false> gDecodeFailures;
|
| static SkTArray<SkString, false> gEncodeFailures;
|
| static SkTArray<SkString, false> gSuccessfulDecodes;
|
| +static SkTArray<SkString, false> gSuccessfulSubsetDecodes;
|
| +static SkTArray<SkString, false> gFailedSubsetDecodes;
|
|
|
| static bool write_bitmap(const char outName[], SkBitmap* bm) {
|
| SkBitmap bitmap8888;
|
| @@ -112,6 +116,47 @@ static bool write_bitmap(const char outName[], SkBitmap* bm) {
|
| return SkImageEncoder::EncodeFile(outName, *bm, SkImageEncoder::kPNG_Type, 100);
|
| }
|
|
|
| +/**
|
| + * Return a random SkIRect inside the range specified.
|
| + * @param rand Random number generator.
|
| + * @param maxX Exclusive maximum x-coordinate. SkIRect's fLeft and fRight will be
|
| + * in the range [0, maxX)
|
| + * @param maxY Exclusive maximum y-coordinate. SkIRect's fTop and fBottom will be
|
| + * in the range [0, maxY)
|
| + * @return SkIRect Non-empty, non-degenerate rectangle.
|
| + */
|
| +static SkIRect generate_random_rect(SkRandom* rand, int32_t maxX, int32_t maxY) {
|
| + SkASSERT(maxX > 1 && maxY > 1);
|
| + int32_t left = rand->nextULessThan(maxX);
|
| + int32_t right = rand->nextULessThan(maxX);
|
| + int32_t top = rand->nextULessThan(maxY);
|
| + int32_t bottom = rand->nextULessThan(maxY);
|
| + SkIRect rect = SkIRect::MakeLTRB(left, top, right, bottom);
|
| + rect.sort();
|
| + // Make sure rect is not empty.
|
| + if (rect.fLeft == rect.fRight) {
|
| + if (rect.fLeft > 0) {
|
| + rect.fLeft--;
|
| + } else {
|
| + rect.fRight++;
|
| + // This branch is only taken if 0 == rect.fRight, and
|
| + // maxX must be at least 2, so it must still be in
|
| + // range.
|
| + SkASSERT(rect.fRight < maxX);
|
| + }
|
| + }
|
| + if (rect.fTop == rect.fBottom) {
|
| + if (rect.fTop > 0) {
|
| + rect.fTop--;
|
| + } else {
|
| + rect.fBottom++;
|
| + // Again, this must be in range.
|
| + SkASSERT(rect.fBottom < maxY);
|
| + }
|
| + }
|
| + return rect;
|
| +}
|
| +
|
| static void decodeFileAndWrite(const char srcPath[], const SkString* writePath) {
|
| SkBitmap bitmap;
|
| SkFILEStream stream(srcPath);
|
| @@ -137,6 +182,49 @@ static void decodeFileAndWrite(const char srcPath[], const SkString* writePath)
|
|
|
| gSuccessfulDecodes.push_back().printf("%s [%d %d]", srcPath, bitmap.width(), bitmap.height());
|
|
|
| + if (FLAGS_testSubsetDecoding) {
|
| + bool couldRewind = stream.rewind();
|
| + SkASSERT(couldRewind);
|
| + int width, height;
|
| + // Build the tile index for decoding subsets. If the image is 1x1, skip subset
|
| + // decoding since there are no smaller subsets.
|
| + if (codec->buildTileIndex(&stream, &width, &height) && width > 1 && height > 1) {
|
| + SkASSERT(bitmap.width() == width && bitmap.height() == height);
|
| + // Call decodeSubset multiple times:
|
| + SkRandom rand(0);
|
| + for (int i = 0; i < 5; i++) {
|
| + SkBitmap bitmapFromDecodeSubset;
|
| + // FIXME: Come up with a more representative set of rectangles.
|
| + SkIRect rect = generate_random_rect(&rand, width, height);
|
| + SkString subsetDim = SkStringPrintf("[%d,%d,%d,%d]", rect.fLeft, rect.fTop,
|
| + rect.fRight, rect.fBottom);
|
| + if (codec->decodeSubset(&bitmapFromDecodeSubset, rect, SkBitmap::kNo_Config)) {
|
| + gSuccessfulSubsetDecodes.push_back().printf("Decoded subset %s from %s",
|
| + subsetDim.c_str(), srcPath);
|
| + if (writePath != NULL) {
|
| + // Write the region to a file whose name includes the dimensions.
|
| + SkString suffix = SkStringPrintf("_%s.png", subsetDim.c_str());
|
| + SkString outPath;
|
| + make_outname(&outPath, writePath->c_str(), srcPath, suffix.c_str());
|
| + bool success = write_bitmap(outPath.c_str(), &bitmapFromDecodeSubset);
|
| + SkASSERT(success);
|
| + gSuccessfulSubsetDecodes.push_back().printf("\twrote %s", outPath.c_str());
|
| + // Also use extractSubset from the original for visual comparison.
|
| + SkBitmap extractedSubset;
|
| + if (bitmap.extractSubset(&extractedSubset, rect)) {
|
| + suffix.printf("_%s_extracted.png", subsetDim.c_str());
|
| + make_outname(&outPath, writePath->c_str(), srcPath, suffix.c_str());
|
| + success = write_bitmap(outPath.c_str(), &extractedSubset);
|
| + SkASSERT(success);
|
| + }
|
| + }
|
| + } else {
|
| + gFailedSubsetDecodes.push_back().printf("Failed to decode region %s from %s\n",
|
| + subsetDim.c_str(), srcPath);
|
| + }
|
| + }
|
| + }
|
| + }
|
| if (FLAGS_reencode) {
|
| // Encode to the format the file was originally in, or PNG if the encoder for the same
|
| // format is unavailable.
|
| @@ -289,6 +377,11 @@ int tool_main(int argc, char** argv) {
|
| failed |= print_strings("Failed to encode", gEncodeFailures);
|
| print_strings("Decoded", gSuccessfulDecodes);
|
|
|
| + if (FLAGS_testSubsetDecoding) {
|
| + failed |= print_strings("Failed subset decodes", gFailedSubsetDecodes);
|
| + print_strings("Decoded subsets", gSuccessfulSubsetDecodes);
|
| + }
|
| +
|
| return failed ? -1 : 0;
|
| }
|
|
|
|
|