Preparations for running skimage tool on bots.

skimage_main:
Specify the full name of the expectations file to write on the command line,
rather than the folder to write 'results.json'. This is consistent with
writeJsonSummaryPath in GM, as well as the format for reading the file.
Further, it allows more flexibility to name the file.
Do not force opaque when writing bitmaps. skimage does its comparison on
the raw bitmaps. The images are written for visual comparison, and mostly
transparent bitmaps (like resources/plane.png) aren't meaningful when
forced opaque.
Provide an option to to write only mismatches to a directory. Handled
similar to the writePath.
Report a failure if there is no expectations file. This allows writing
to the mismatchPath so we can create an initial baseline.
Pass SkBitmap by const&.

skimage_self_test:
Include the name of the json file in the parameter passed to
createExpectationsPath. The name has been changed to be more specific.

.gitignore:
Ignore the new name of the file created by skimage_self_test.

run.sh:
Run skimage_self_tests.py

BUG=http://code.google.com/p/skia/issues/detail?id=1241
R=epoger@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@9474 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
scroggo@google.com 2013-06-07 12:43:15 +00:00
parent e762dad67c
commit cf5eb6ab25
3 changed files with 43 additions and 50 deletions

View File

@ -23,11 +23,12 @@
__SK_FORCE_IMAGE_DECODER_LINKING;
DEFINE_string(createExpectationsPath, "", "Path to write JSON expectations.");
DEFINE_string(mismatchPath, "", "Folder to write mismatched images to.");
DEFINE_string2(readPath, r, "", "Folder(s) and files to decode images. Required.");
DEFINE_string(readExpectationsPath, "", "Path to read JSON expectations from.");
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.");
DEFINE_string2(writePath, w, "", "Write rendered images into this directory.");
struct Format {
SkImageEncoder::Type fType;
@ -101,23 +102,8 @@ static SkTArray<SkString, false> gFailedSubsetDecodes;
// previously written using createExpectationsPath.
SkAutoTUnref<skiagm::JsonExpectationsSource> gJsonExpectations;
static bool write_bitmap(const char outName[], SkBitmap* bm) {
SkBitmap bitmap8888;
if (SkBitmap::kARGB_8888_Config != bm->config()) {
if (!bm->copyTo(&bitmap8888, SkBitmap::kARGB_8888_Config)) {
return false;
}
bm = &bitmap8888;
}
// FIXME: This forces all pixels to be opaque, like the many implementations
// of force_all_opaque. These should be unified if they cannot be eliminated.
SkAutoLockPixels lock(*bm);
for (int y = 0; y < bm->height(); y++) {
for (int x = 0; x < bm->width(); x++) {
*bm->getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
}
}
return SkImageEncoder::EncodeFile(outName, *bm, SkImageEncoder::kPNG_Type, 100);
static bool write_bitmap(const char outName[], const SkBitmap& bm) {
return SkImageEncoder::EncodeFile(outName, bm, SkImageEncoder::kPNG_Type, 100);
}
/**
@ -183,16 +169,25 @@ static void write_expectations(const SkBitmap& bitmap, const char* filename) {
* @param filename String used to find the expected value.
* @return bool True in any of these cases:
* - the bitmap matches the expectation.
* - there is no expectations file.
* False in any of these cases:
* - there is no expectations file.
* - there is an expectations file, but no expectation for this bitmap.
* - there is an expectation for this bitmap, but it did not match.
* - expectation could not be computed from the bitmap.
*/
static bool compare_to_expectations_if_necessary(const SkBitmap& bitmap, const char* filename,
SkTArray<SkString, false>* failureArray) {
skiagm::GmResultDigest resultDigest(bitmap);
if (!resultDigest.isValid()) {
if (failureArray != NULL) {
failureArray->push_back().printf("decoded %s, but could not create a GmResultDigest.",
filename);
}
return false;
}
if (NULL == gJsonExpectations.get()) {
return true;
return false;
}
skiagm::Expectations jsExpectation = gJsonExpectations->get(filename);
@ -204,15 +199,6 @@ static bool compare_to_expectations_if_necessary(const SkBitmap& bitmap, const c
return false;
}
skiagm::GmResultDigest resultDigest(bitmap);
if (!resultDigest.isValid()) {
if (failureArray != NULL) {
failureArray->push_back().printf("decoded %s, but could not create a GmResultDigest.",
filename);
}
return false;
}
if (jsExpectation.match(resultDigest)) {
return true;
}
@ -270,7 +256,7 @@ static bool write_subset(const char* writePath, const char* filename, const char
SkString suffix = SkStringPrintf("_%s.png", subsetDim);
SkString outPath;
make_outname(&outPath, dir.c_str(), filename, suffix.c_str());
SkAssertResult(write_bitmap(outPath.c_str(), bitmapFromDecodeSubset));
SkAssertResult(write_bitmap(outPath.c_str(), *bitmapFromDecodeSubset));
gSuccessfulSubsetDecodes.push_back().printf("\twrote %s", outPath.c_str());
// Also use extractSubset from the original for visual comparison.
@ -292,7 +278,7 @@ static bool write_subset(const char* writePath, const char* filename, const char
}
make_outname(&outPath, dirExtracted.c_str(), filename, suffix.c_str());
SkAssertResult(write_bitmap(outPath.c_str(), &extractedSubset));
SkAssertResult(write_bitmap(outPath.c_str(), extractedSubset));
return true;
}
@ -326,6 +312,24 @@ static void decodeFileAndWrite(const char srcPath[], const SkString* writePath)
if (compare_to_expectations_if_necessary(bitmap, filename, &gDecodeFailures)) {
gSuccessfulDecodes.push_back().printf("%s [%d %d]", srcPath, bitmap.width(),
bitmap.height());
} else if (!FLAGS_mismatchPath.isEmpty()) {
SkString outPath;
make_outname(&outPath, FLAGS_mismatchPath[0], srcPath, ".png");
if (write_bitmap(outPath.c_str(), bitmap)) {
gSuccessfulDecodes.push_back().appendf("\twrote %s", outPath.c_str());
} else {
gEncodeFailures.push_back().set(outPath);
}
}
if (writePath != NULL) {
SkString outPath;
make_outname(&outPath, writePath->c_str(), srcPath, ".png");
if (write_bitmap(outPath.c_str(), bitmap)) {
gSuccessfulDecodes.push_back().appendf("\twrote %s", outPath.c_str());
} else {
gEncodeFailures.push_back().set(outPath);
}
}
write_expectations(bitmap, filename);
@ -353,6 +357,9 @@ static void decodeFileAndWrite(const char srcPath[], const SkString* writePath)
&gFailedSubsetDecodes)) {
gSuccessfulSubsetDecodes.push_back().printf("Decoded subset %s from %s",
subsetDim.c_str(), srcPath);
} else if (!FLAGS_mismatchPath.isEmpty()) {
write_subset(FLAGS_mismatchPath[0], filename, subsetDim.c_str(),
&bitmapFromDecodeSubset, rect, bitmap);
}
write_expectations(bitmapFromDecodeSubset, subsetName.c_str());
@ -411,8 +418,7 @@ static void decodeFileAndWrite(const char srcPath[], const SkString* writePath)
SkAutoTUnref<SkData> data(wStream.copyToData());
if (writePath != NULL && type != SkImageEncoder::kPNG_Type) {
// Write the encoded data to a file. Do not write to PNG, which will be written later,
// regardless of the input format.
// Write the encoded data to a file. Do not write to PNG, which was already written.
SkString outPath;
make_outname(&outPath, writePath->c_str(), srcPath, suffix_for_type(type));
SkFILEWStream file(outPath.c_str());
@ -435,16 +441,6 @@ static void decodeFileAndWrite(const char srcPath[], const SkString* writePath)
srcPath, suffix_for_type(type));
}
}
if (writePath != NULL) {
SkString outPath;
make_outname(&outPath, writePath->c_str(), srcPath, ".png");
if (write_bitmap(outPath.c_str(), &bitmap)) {
gSuccessfulDecodes.push_back().appendf("\twrote %s", outPath.c_str());
} else {
gEncodeFailures.push_back().set(outPath);
}
}
}
///////////////////////////////////////////////////////////////////////////////
@ -530,9 +526,7 @@ int tool_main(int argc, char** argv) {
Json::Value root = skiagm::CreateJsonTree(gExpectationsToWrite, nullValue, nullValue,
nullValue, nullValue);
std::string jsonStdString = root.toStyledString();
SkString path = SkStringPrintf("%s%cresults.json", FLAGS_createExpectationsPath[0],
SkPATH_SEPARATOR);
SkFILEWStream stream(path.c_str());
SkFILEWStream stream(FLAGS_createExpectationsPath[0]);
stream.write(jsonStdString.c_str(), jsonStdString.length());
}
// Add some space, since codecs may print warnings without newline.

View File

@ -1 +1 @@
results.json
self_test_results.json

View File

@ -49,13 +49,12 @@ def main():
cmd_line.extend(["-r", resources_dir])
# Create the expectations file
results_dir = os.path.join(file_dir, "skimage")
results_file = os.path.join(file_dir, "skimage", "self_test_results.json")
create_expectations_cmd = cmd_line + ["--createExpectationsPath",
results_dir]
results_file]
subprocess.check_call(create_expectations_cmd)
# Now read from the expectations file
results_file = os.path.join(results_dir, "results.json")
check_expectations_cmd = cmd_line + ["--readExpectationsPath",
results_file]
subprocess.check_call(check_expectations_cmd)