blob: 7dbf3fcb1494c1453092970cc12b71246777abb4 [file] [log] [blame]
edisonn@google.com5149bd92013-08-05 17:26:11 +00001/*
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
24DEFINE_string2(readPath, r, "", "Folder(s) and files to decode images. Required.");
25
26struct Format {
27 SkImageEncoder::Type fType;
28 SkImageDecoder::Format fFormat;
29 const char* fSuffix;
30};
31
mtklein@google.com0724e1f2013-11-20 18:02:00 +000032/*
edisonn@google.com5149bd92013-08-05 17:26:11 +000033static 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};
mtklein@google.com0724e1f2013-11-20 18:02:00 +000042*/
edisonn@google.com5149bd92013-08-05 17:26:11 +000043
edisonn@google.com33f11b62013-08-14 21:35:27 +000044static SkISize opaqueSize(const SkBitmap& bm) {
edisonn@google.com5149bd92013-08-05 17:26:11 +000045 int width = 1;
46 int height = 1;
47 for (int y = 0 ; y < bm.height(); y++) {
edisonn@google.com45be4eb2013-08-05 17:59:11 +000048 for (int x = 0 ; x < bm.width(); x++) {
edisonn@google.com5149bd92013-08-05 17:26:11 +000049 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
60static void setup_bitmap(SkBitmap* bitmap, int width, int height) {
61 bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
62
63 bitmap->allocPixels();
64}
65
66
67static bool write_bitmap(const char outName[], const SkBitmap& bm) {
68 SkISize size = opaqueSize(bm);
69 SkBitmap dst;
70 setup_bitmap(&dst, size.width(), size.height());
71
72 for (int y = 0 ; y < dst.height(); y++) {
73 for (int x = 0 ; x < dst.width(); x++) {
74 SkColor color = bm.getColor(x, y);
75 if (SkColorGetA(color) != 0xff) {
76 int a = SkColorGetA(color);
77 int r = SkColorGetR(color);
78 int g = SkColorGetG(color);
79 int b = SkColorGetB(color);
80 if (a == 0) {
81 r = g = b = 0;
82 } else {
83 r = (r * a) / 255;
84 g = (g * a) / 255;
85 b = (b * a) / 255;
86 a = 255;
87 }
88 color = SkColorSetARGB((U8CPU)a, (U8CPU)r, (U8CPU)g, (U8CPU)b);
89 }
90 *dst.getAddr32(x, y) = color;
91 }
92 }
93
94 return SkImageEncoder::EncodeFile(outName, dst, SkImageEncoder::kPNG_Type, 100);
95}
96
97static void decodeFileAndWrite(const char srcPath[]) {
98 SkBitmap bitmap;
99 SkFILEStream stream(srcPath);
100 if (!stream.isValid()) {
101 return;
102 }
103
104 SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
105 if (NULL == codec) {
106 return;
107 }
108
109 SkAutoTDelete<SkImageDecoder> ad(codec);
110
111 stream.rewind();
112
113 if (!codec->decode(&stream, &bitmap, SkBitmap::kARGB_8888_Config,
114 SkImageDecoder::kDecodePixels_Mode)) {
115 return;
116 }
117
118 write_bitmap(srcPath, bitmap);
119}
120
121/**
122 * Return true if the filename represents an image.
123 */
124static bool is_image_file(const char* filename) {
125 const char* gImageExtensions[] = {
126 ".png", ".PNG", ".jpg", ".JPG", ".jpeg", ".JPEG", ".bmp", ".BMP",
127 ".webp", ".WEBP", ".ico", ".ICO", ".wbmp", ".WBMP", ".gif", ".GIF"
128 };
129 for (size_t i = 0; i < SK_ARRAY_COUNT(gImageExtensions); ++i) {
130 if (SkStrEndsWith(filename, gImageExtensions[i])) {
131 return true;
132 }
133 }
134 return false;
135}
136
137int tool_main(int argc, char** argv);
138int tool_main(int argc, char** argv) {
139 SkCommandLineFlags::SetUsage("Decode files, and optionally write the results to files.");
140 SkCommandLineFlags::Parse(argc, argv);
141
142 if (FLAGS_readPath.count() < 1) {
143 SkDebugf("Folder(s) or image(s) to decode are required.\n");
144 return -1;
145 }
146
147
148 SkAutoGraphics ag;
149
150 for (int i = 0; i < FLAGS_readPath.count(); i++) {
151 const char* readPath = FLAGS_readPath[i];
152 if (strlen(readPath) < 1) {
153 break;
154 }
155 if (sk_isdir(readPath)) {
156 const char* dir = readPath;
157 SkOSFile::Iter iter(dir);
158 SkString filename;
159 while (iter.next(&filename)) {
160 if (!is_image_file(filename.c_str())) {
161 continue;
162 }
163 SkString fullname = SkOSPath::SkPathJoin(dir, filename.c_str());
164 decodeFileAndWrite(fullname.c_str());
165 }
166 } else if (sk_exists(readPath) && is_image_file(readPath)) {
167 decodeFileAndWrite(readPath);
168 }
169 }
170
171 return 0;
172}
173
174#if !defined SK_BUILD_FOR_IOS
175int main(int argc, char * const argv[]) {
176 return tool_main(argc, (char**) argv);
177}
178#endif