diff --git a/gyp/tools.gyp b/gyp/tools.gyp index 4a4a1da3f7..7f79dc4114 100644 --- a/gyp/tools.gyp +++ b/gyp/tools.gyp @@ -82,6 +82,7 @@ 'skia_base_libs.gyp:skia_base_libs', 'effects.gyp:effects', 'images.gyp:images', + 'flags.gyp:flags', ], }, { diff --git a/tools/skimage_main.cpp b/tools/skimage_main.cpp index 53cc6b3d0f..dc5bdd4260 100644 --- a/tools/skimage_main.cpp +++ b/tools/skimage_main.cpp @@ -1,27 +1,41 @@ - /* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ + #include "SkBitmap.h" +#include "SkCommandLineFlags.h" #include "SkGraphics.h" #include "SkImageDecoder.h" #include "SkImageEncoder.h" +#include "SkOSFile.h" #include "SkStream.h" +#include "SkTArray.h" #include "SkTemplates.h" + +DEFINE_string2(readPath, r, "", "Folder(s) and files to decode images. Required."); +DEFINE_string2(writePath, w, "", "Write rendered images into this directory."); + +// Store the names of the filenames to report later which ones failed, succeeded, and were +// invalid. +static SkTArray invalids; +static SkTArray nocodecs; +static SkTArray failures; +static SkTArray successes; + static bool decodeFile(SkBitmap* bitmap, const char srcPath[]) { SkFILEStream stream(srcPath); if (!stream.isValid()) { - SkDebugf("ERROR: bad filename <%s>\n", srcPath); + invalids.push_back().set(srcPath); return false; } SkImageDecoder* codec = SkImageDecoder::Factory(&stream); if (NULL == codec) { - SkDebugf("ERROR: no codec found for <%s>\n", srcPath); + nocodecs.push_back().set(srcPath); return false; } @@ -30,18 +44,16 @@ static bool decodeFile(SkBitmap* bitmap, const char srcPath[]) { stream.rewind(); if (!codec->decode(&stream, bitmap, SkBitmap::kARGB_8888_Config, SkImageDecoder::kDecodePixels_Mode)) { - SkDebugf("ERROR: codec failed for <%s>\n", srcPath); + failures.push_back().set(srcPath); return false; } + + successes.push_back().printf("%s [%d %d]", srcPath, bitmap->width(), bitmap->height()); return true; } /////////////////////////////////////////////////////////////////////////////// -static void show_help() { - SkDebugf("usage: skiamge [-o out-dir] inputfiles...\n"); -} - static void make_outname(SkString* dst, const char outDir[], const char src[]) { dst->set(outDir); const char* start = strrchr(src, '/'); @@ -51,58 +63,106 @@ static void make_outname(SkString* dst, const char outDir[], const char src[]) { start = src; } dst->append(start); - dst->append(".png"); + if (!dst->endsWith(".png")) { + const char* cstyleDst = dst->c_str(); + const char* dot = strrchr(cstyleDst, '.'); + if (dot != NULL) { + int32_t index = SkToS32(dot - cstyleDst); + dst->remove(index, dst->size() - index); + } + dst->append(".png"); + } +} + +// If strings is not empty, print title, followed by each string on its own line starting +// with a tab. +static void print_strings(const char* title, const SkTArray& strings) { + if (strings.count() > 0) { + SkDebugf("%s:\n", title); + for (int i = 0; i < strings.count(); i++) { + SkDebugf("\t%s\n", strings[i].c_str()); + } + SkDebugf("\n"); + } +} + +static void decodeFileAndWrite(const char filePath[], const SkString* writePath) { + SkBitmap bitmap; + if (decodeFile(&bitmap, filePath)) { + if (writePath != NULL) { + SkString outPath; + make_outname(&outPath, writePath->c_str(), filePath); + successes.push_back().appendf("\twrote %s", outPath.c_str()); + SkImageEncoder::EncodeFile(outPath.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); + } + } } int tool_main(int argc, char** argv); int tool_main(int argc, char** argv) { + SkCommandLineFlags::SetUsage("Decode files, and optionally write the results to files."); + SkCommandLineFlags::Parse(argc, argv); + + if (FLAGS_readPath.count() < 1) { + SkDebugf("Folder(s) or image(s) to decode are required.\n"); + return -1; + } + + SkAutoGraphics ag; - int i, outDirIndex = 0; + SkString outDir; + SkString* outDirPtr; - for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "-help")) { - show_help(); - return 0; + if (FLAGS_writePath.count() == 1) { + outDir.set(FLAGS_writePath[0]); + if (outDir.c_str()[outDir.size() - 1] != '/') { + outDir.append("/"); } - if (!strcmp(argv[i], "-o")) { - if (i == argc-1) { - SkDebugf("ERROR: -o needs a following filename\n"); - return -1; + outDirPtr = &outDir; + } else { + outDirPtr = NULL; + } + + for (int i = 0; i < FLAGS_readPath.count(); i++) { + if (strlen(FLAGS_readPath[i]) < 1) { + break; + } + SkOSFile::Iter iter(FLAGS_readPath[i]); + SkString filename; + if (iter.next(&filename)) { + SkString directory(FLAGS_readPath[i]); + if (directory[directory.size() - 1] != '/') { + directory.append("/"); } - outDirIndex = i; - outDir.set(argv[i+1]); - if (outDir.c_str()[outDir.size() - 1] != '/') { - outDir.append("/"); - } - i += 1; // skip the out dir name + do { + SkString fullname(directory); + fullname.append(filename); + decodeFileAndWrite(fullname.c_str(), outDirPtr); + } while (iter.next(&filename)); + } else { + decodeFileAndWrite(FLAGS_readPath[i], outDirPtr); } } - for (i = 1; i < argc; i++) { - if (i == outDirIndex) { - i += 1; // skip this and the next entry - continue; - } + // Add some space, since codecs may print warnings without newline. + SkDebugf("\n\n"); - SkBitmap bitmap; - if (decodeFile(&bitmap, argv[i])) { - if (outDirIndex) { - SkString outPath; - make_outname(&outPath, outDir.c_str(), argv[i]); - SkDebugf(" writing %s\n", outPath.c_str()); - SkImageEncoder::EncodeFile(outPath.c_str(), bitmap, - SkImageEncoder::kPNG_Type, 100); - } else { - SkDebugf(" decoded %s [%d %d]\n", argv[i], bitmap.width(), - bitmap.height()); - } - } - } + print_strings("Invalid files", invalids); + print_strings("Missing codec", nocodecs); + print_strings("Failed to decode", failures); + print_strings("Decoded", successes); return 0; } +void forceLinking(); + +void forceLinking() { + SkDEBUGCODE(SkImageDecoder *creator = ) CreateJPEGImageDecoder(); + SkASSERT(creator); +} + #if !defined SK_BUILD_FOR_IOS int main(int argc, char * const argv[]) { return tool_main(argc, (char**) argv);