1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkBitmap.h" 9 #include "SkColorPriv.h" 10 #include "SkCommandLineFlags.h" 11 #include "SkData.h" 12 #include "SkForceLinking.h" 13 #include "SkGraphics.h" 14 #include "SkImageDecoder.h" 15 #include "SkImageEncoder.h" 16 #include "SkOSFile.h" 17 #include "SkRandom.h" 18 #include "SkStream.h" 19 #include "SkTArray.h" 20 #include "SkTemplates.h" 21 22 __SK_FORCE_IMAGE_DECODER_LINKING; 23 24 DEFINE_string2(readPath, r, "", "Folder(s) and files to decode images. Required."); 25 26 struct Format { 27 SkImageEncoder::Type fType; 28 SkImageDecoder::Format fFormat; 29 const char* fSuffix; 30 }; 31 32 /* 33 static const Format gFormats[] = { 34 { SkImageEncoder::kBMP_Type, SkImageDecoder::kBMP_Format, ".bmp" }, 35 { SkImageEncoder::kGIF_Type, SkImageDecoder::kGIF_Format, ".gif" }, 36 { SkImageEncoder::kICO_Type, SkImageDecoder::kICO_Format, ".ico" }, 37 { SkImageEncoder::kJPEG_Type, SkImageDecoder::kJPEG_Format, ".jpg" }, 38 { SkImageEncoder::kPNG_Type, SkImageDecoder::kPNG_Format, ".png" }, 39 { SkImageEncoder::kWBMP_Type, SkImageDecoder::kWBMP_Format, ".wbmp" }, 40 { SkImageEncoder::kWEBP_Type, SkImageDecoder::kWEBP_Format, ".webp" } 41 }; 42 */ 43 44 static SkISize opaqueSize(const SkBitmap& bm) { 45 int width = 1; 46 int height = 1; 47 for (int y = 0 ; y < bm.height(); y++) { 48 for (int x = 0 ; x < bm.width(); x++) { 49 SkColor color = bm.getColor(x, y); 50 if (SkColorGetA(color) != 0) { 51 height = y + 1; 52 width = width > (x + 1) ? width : x + 1; 53 } 54 } 55 } 56 57 return SkISize::Make(width, height); 58 } 59 60 static void setup_bitmap(SkBitmap* bitmap, int width, int height) { 61 bitmap->allocN32Pixels(width, height); 62 } 63 64 65 static bool write_bitmap(const char outName[], const SkBitmap& bm) { 66 SkISize size = opaqueSize(bm); 67 SkBitmap dst; 68 setup_bitmap(&dst, size.width(), size.height()); 69 70 for (int y = 0 ; y < dst.height(); y++) { 71 for (int x = 0 ; x < dst.width(); x++) { 72 SkColor color = bm.getColor(x, y); 73 if (SkColorGetA(color) != 0xff) { 74 int a = SkColorGetA(color); 75 int r = SkColorGetR(color); 76 int g = SkColorGetG(color); 77 int b = SkColorGetB(color); 78 if (a == 0) { 79 r = g = b = 0; 80 } else { 81 r = (r * a) / 255; 82 g = (g * a) / 255; 83 b = (b * a) / 255; 84 a = 255; 85 } 86 color = SkColorSetARGB((U8CPU)a, (U8CPU)r, (U8CPU)g, (U8CPU)b); 87 } 88 *dst.getAddr32(x, y) = color; 89 } 90 } 91 92 return SkImageEncoder::EncodeFile(outName, dst, SkImageEncoder::kPNG_Type, 100); 93 } 94 95 static void decodeFileAndWrite(const char srcPath[]) { 96 SkBitmap bitmap; 97 SkFILEStream stream(srcPath); 98 if (!stream.isValid()) { 99 return; 100 } 101 102 SkImageDecoder* codec = SkImageDecoder::Factory(&stream); 103 if (NULL == codec) { 104 return; 105 } 106 107 SkAutoTDelete<SkImageDecoder> ad(codec); 108 109 stream.rewind(); 110 111 if (!codec->decode(&stream, &bitmap, kN32_SkColorType, SkImageDecoder::kDecodePixels_Mode)) { 112 return; 113 } 114 115 write_bitmap(srcPath, bitmap); 116 } 117 118 /** 119 * Return true if the filename represents an image. 120 */ 121 static bool is_image_file(const char* filename) { 122 const char* gImageExtensions[] = { 123 ".png", ".PNG", ".jpg", ".JPG", ".jpeg", ".JPEG", ".bmp", ".BMP", 124 ".webp", ".WEBP", ".ico", ".ICO", ".wbmp", ".WBMP", ".gif", ".GIF" 125 }; 126 for (size_t i = 0; i < SK_ARRAY_COUNT(gImageExtensions); ++i) { 127 if (SkStrEndsWith(filename, gImageExtensions[i])) { 128 return true; 129 } 130 } 131 return false; 132 } 133 134 int tool_main(int argc, char** argv); 135 int tool_main(int argc, char** argv) { 136 SkCommandLineFlags::SetUsage("Decode files, and optionally write the results to files."); 137 SkCommandLineFlags::Parse(argc, argv); 138 139 if (FLAGS_readPath.count() < 1) { 140 SkDebugf("Folder(s) or image(s) to decode are required.\n"); 141 return -1; 142 } 143 144 145 SkAutoGraphics ag; 146 147 for (int i = 0; i < FLAGS_readPath.count(); i++) { 148 const char* readPath = FLAGS_readPath[i]; 149 if (strlen(readPath) < 1) { 150 break; 151 } 152 if (sk_isdir(readPath)) { 153 const char* dir = readPath; 154 SkOSFile::Iter iter(dir); 155 SkString filename; 156 while (iter.next(&filename)) { 157 if (!is_image_file(filename.c_str())) { 158 continue; 159 } 160 SkString fullname = SkOSPath::SkPathJoin(dir, filename.c_str()); 161 decodeFileAndWrite(fullname.c_str()); 162 } 163 } else if (sk_exists(readPath) && is_image_file(readPath)) { 164 decodeFileAndWrite(readPath); 165 } 166 } 167 168 return 0; 169 } 170 171 #if !defined SK_BUILD_FOR_IOS 172 int main(int argc, char * const argv[]) { 173 return tool_main(argc, (char**) argv); 174 } 175 #endif 176