| /* |
| * Copyright 2013 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 "SkColorPriv.h" |
| #include "SkCommandLineFlags.h" |
| #include "SkData.h" |
| #include "SkForceLinking.h" |
| #include "SkGraphics.h" |
| #include "SkImageDecoder.h" |
| #include "SkImageEncoder.h" |
| #include "SkOSFile.h" |
| #include "SkRandom.h" |
| #include "SkStream.h" |
| #include "SkTArray.h" |
| #include "SkTemplates.h" |
| |
| __SK_FORCE_IMAGE_DECODER_LINKING; |
| |
| DEFINE_string2(readPath, r, "", "Folder(s) and files to decode images. Required."); |
| |
| struct Format { |
| SkImageEncoder::Type fType; |
| SkImageDecoder::Format fFormat; |
| const char* fSuffix; |
| }; |
| |
| /* |
| static const Format gFormats[] = { |
| { SkImageEncoder::kBMP_Type, SkImageDecoder::kBMP_Format, ".bmp" }, |
| { SkImageEncoder::kGIF_Type, SkImageDecoder::kGIF_Format, ".gif" }, |
| { SkImageEncoder::kICO_Type, SkImageDecoder::kICO_Format, ".ico" }, |
| { SkImageEncoder::kJPEG_Type, SkImageDecoder::kJPEG_Format, ".jpg" }, |
| { SkImageEncoder::kPNG_Type, SkImageDecoder::kPNG_Format, ".png" }, |
| { SkImageEncoder::kWBMP_Type, SkImageDecoder::kWBMP_Format, ".wbmp" }, |
| { SkImageEncoder::kWEBP_Type, SkImageDecoder::kWEBP_Format, ".webp" } |
| }; |
| */ |
| |
| static SkISize opaqueSize(const SkBitmap& bm) { |
| int width = 1; |
| int height = 1; |
| for (int y = 0 ; y < bm.height(); y++) { |
| for (int x = 0 ; x < bm.width(); x++) { |
| SkColor color = bm.getColor(x, y); |
| if (SkColorGetA(color) != 0) { |
| height = y + 1; |
| width = width > (x + 1) ? width : x + 1; |
| } |
| } |
| } |
| |
| return SkISize::Make(width, height); |
| } |
| |
| static void setup_bitmap(SkBitmap* bitmap, int width, int height) { |
| bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height); |
| |
| bitmap->allocPixels(); |
| } |
| |
| |
| static bool write_bitmap(const char outName[], const SkBitmap& bm) { |
| SkISize size = opaqueSize(bm); |
| SkBitmap dst; |
| setup_bitmap(&dst, size.width(), size.height()); |
| |
| for (int y = 0 ; y < dst.height(); y++) { |
| for (int x = 0 ; x < dst.width(); x++) { |
| SkColor color = bm.getColor(x, y); |
| if (SkColorGetA(color) != 0xff) { |
| int a = SkColorGetA(color); |
| int r = SkColorGetR(color); |
| int g = SkColorGetG(color); |
| int b = SkColorGetB(color); |
| if (a == 0) { |
| r = g = b = 0; |
| } else { |
| r = (r * a) / 255; |
| g = (g * a) / 255; |
| b = (b * a) / 255; |
| a = 255; |
| } |
| color = SkColorSetARGB((U8CPU)a, (U8CPU)r, (U8CPU)g, (U8CPU)b); |
| } |
| *dst.getAddr32(x, y) = color; |
| } |
| } |
| |
| return SkImageEncoder::EncodeFile(outName, dst, SkImageEncoder::kPNG_Type, 100); |
| } |
| |
| static void decodeFileAndWrite(const char srcPath[]) { |
| SkBitmap bitmap; |
| SkFILEStream stream(srcPath); |
| if (!stream.isValid()) { |
| return; |
| } |
| |
| SkImageDecoder* codec = SkImageDecoder::Factory(&stream); |
| if (NULL == codec) { |
| return; |
| } |
| |
| SkAutoTDelete<SkImageDecoder> ad(codec); |
| |
| stream.rewind(); |
| |
| if (!codec->decode(&stream, &bitmap, SkBitmap::kARGB_8888_Config, |
| SkImageDecoder::kDecodePixels_Mode)) { |
| return; |
| } |
| |
| write_bitmap(srcPath, bitmap); |
| } |
| |
| /** |
| * Return true if the filename represents an image. |
| */ |
| static bool is_image_file(const char* filename) { |
| const char* gImageExtensions[] = { |
| ".png", ".PNG", ".jpg", ".JPG", ".jpeg", ".JPEG", ".bmp", ".BMP", |
| ".webp", ".WEBP", ".ico", ".ICO", ".wbmp", ".WBMP", ".gif", ".GIF" |
| }; |
| for (size_t i = 0; i < SK_ARRAY_COUNT(gImageExtensions); ++i) { |
| if (SkStrEndsWith(filename, gImageExtensions[i])) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| 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; |
| |
| for (int i = 0; i < FLAGS_readPath.count(); i++) { |
| const char* readPath = FLAGS_readPath[i]; |
| if (strlen(readPath) < 1) { |
| break; |
| } |
| if (sk_isdir(readPath)) { |
| const char* dir = readPath; |
| SkOSFile::Iter iter(dir); |
| SkString filename; |
| while (iter.next(&filename)) { |
| if (!is_image_file(filename.c_str())) { |
| continue; |
| } |
| SkString fullname = SkOSPath::SkPathJoin(dir, filename.c_str()); |
| decodeFileAndWrite(fullname.c_str()); |
| } |
| } else if (sk_exists(readPath) && is_image_file(readPath)) { |
| decodeFileAndWrite(readPath); |
| } |
| } |
| |
| return 0; |
| } |
| |
| #if !defined SK_BUILD_FOR_IOS |
| int main(int argc, char * const argv[]) { |
| return tool_main(argc, (char**) argv); |
| } |
| #endif |