15149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com/*
25149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com * Copyright 2013 Google Inc.
35149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com *
45149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com * Use of this source code is governed by a BSD-style license that can be
55149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com * found in the LICENSE file.
65149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com */
75149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
85149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkBitmap.h"
95149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkColorPriv.h"
105149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkCommandLineFlags.h"
115149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkData.h"
125149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkForceLinking.h"
135149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkGraphics.h"
145149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkImageDecoder.h"
155149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkImageEncoder.h"
165149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkOSFile.h"
175149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkRandom.h"
185149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkStream.h"
195149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkTArray.h"
205149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#include "SkTemplates.h"
215149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
225149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com__SK_FORCE_IMAGE_DECODER_LINKING;
235149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
245149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.comDEFINE_string2(readPath, r, "", "Folder(s) and files to decode images. Required.");
255149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
265149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.comstruct Format {
275149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    SkImageEncoder::Type    fType;
285149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    SkImageDecoder::Format  fFormat;
295149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    const char*             fSuffix;
305149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com};
315149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
320724e1fc2d3227bded0fe9bf07f467f2ba80fa30mtklein@google.com/*
335149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.comstatic const Format gFormats[] = {
345149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    { SkImageEncoder::kBMP_Type, SkImageDecoder::kBMP_Format, ".bmp" },
355149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    { SkImageEncoder::kGIF_Type, SkImageDecoder::kGIF_Format, ".gif" },
365149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    { SkImageEncoder::kICO_Type, SkImageDecoder::kICO_Format, ".ico" },
375149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    { SkImageEncoder::kJPEG_Type, SkImageDecoder::kJPEG_Format, ".jpg" },
385149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    { SkImageEncoder::kPNG_Type, SkImageDecoder::kPNG_Format, ".png" },
395149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    { SkImageEncoder::kWBMP_Type, SkImageDecoder::kWBMP_Format, ".wbmp" },
405149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    { SkImageEncoder::kWEBP_Type, SkImageDecoder::kWEBP_Format, ".webp" }
415149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com};
420724e1fc2d3227bded0fe9bf07f467f2ba80fa30mtklein@google.com*/
435149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
4433f11b6fcdb7dfce27f953803be40fbacedc7450edisonn@google.comstatic SkISize opaqueSize(const SkBitmap& bm) {
455149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    int width = 1;
465149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    int height = 1;
475149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    for (int y = 0 ; y < bm.height(); y++) {
4845be4eb90426e17bde8f36478cc02f076fdc87d9edisonn@google.com        for (int x = 0 ; x < bm.width(); x++) {
495149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            SkColor color = bm.getColor(x, y);
505149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            if (SkColorGetA(color) != 0) {
515149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                height = y + 1;
525149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                width = width > (x + 1) ? width : x + 1;
535149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            }
545149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        }
555149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    }
565149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
575149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    return SkISize::Make(width, height);
585149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com}
595149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
605149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.comstatic void setup_bitmap(SkBitmap* bitmap, int width, int height) {
616c22573edb234ad14df947278cfed010669a39a7reed    bitmap->allocN32Pixels(width, height);
625149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com}
635149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
645149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
655149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.comstatic bool write_bitmap(const char outName[], const SkBitmap& bm) {
665149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    SkISize size = opaqueSize(bm);
675149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    SkBitmap dst;
685149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    setup_bitmap(&dst, size.width(), size.height());
695149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
705149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    for (int y = 0 ; y < dst.height(); y++) {
715149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        for (int x = 0 ; x < dst.width(); x++) {
725149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            SkColor color = bm.getColor(x, y);
735149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            if (SkColorGetA(color) != 0xff) {
745149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                int a = SkColorGetA(color);
755149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                int r = SkColorGetR(color);
765149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                int g = SkColorGetG(color);
775149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                int b = SkColorGetB(color);
785149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                if (a == 0) {
795149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                    r = g = b = 0;
805149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                } else {
815149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                    r = (r * a) / 255;
825149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                    g = (g * a) / 255;
835149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                    b = (b * a) / 255;
845149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                    a = 255;
855149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                }
865149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                color = SkColorSetARGB((U8CPU)a, (U8CPU)r, (U8CPU)g, (U8CPU)b);
875149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            }
885149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            *dst.getAddr32(x, y) = color;
895149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        }
905149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    }
915149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
925149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    return SkImageEncoder::EncodeFile(outName, dst, SkImageEncoder::kPNG_Type, 100);
935149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com}
945149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
955149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.comstatic void decodeFileAndWrite(const char srcPath[]) {
965149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    SkBitmap bitmap;
975149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    SkFILEStream stream(srcPath);
985149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    if (!stream.isValid()) {
995149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        return;
1005149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    }
1015149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1025149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
1035149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    if (NULL == codec) {
1045149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        return;
1055149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    }
1065149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1075149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    SkAutoTDelete<SkImageDecoder> ad(codec);
1085149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1095149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    stream.rewind();
1105149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
111bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed    if (!codec->decode(&stream, &bitmap, kN32_SkColorType, SkImageDecoder::kDecodePixels_Mode)) {
1125149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        return;
1135149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    }
1145149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1155149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    write_bitmap(srcPath, bitmap);
1165149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com}
1175149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1185149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com/**
1195149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com *  Return true if the filename represents an image.
1205149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com */
1215149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.comstatic bool is_image_file(const char* filename) {
1225149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    const char* gImageExtensions[] = {
1235149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        ".png", ".PNG", ".jpg", ".JPG", ".jpeg", ".JPEG", ".bmp", ".BMP",
1245149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        ".webp", ".WEBP", ".ico", ".ICO", ".wbmp", ".WBMP", ".gif", ".GIF"
1255149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    };
1265149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gImageExtensions); ++i) {
1275149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        if (SkStrEndsWith(filename, gImageExtensions[i])) {
1285149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            return true;
1295149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        }
1305149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    }
1315149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    return false;
1325149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com}
1335149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1345149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.comint tool_main(int argc, char** argv);
1355149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.comint tool_main(int argc, char** argv) {
1365149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    SkCommandLineFlags::SetUsage("Decode files, and optionally write the results to files.");
1375149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    SkCommandLineFlags::Parse(argc, argv);
1385149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1395149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    if (FLAGS_readPath.count() < 1) {
1405149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        SkDebugf("Folder(s) or image(s) to decode are required.\n");
1415149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        return -1;
1425149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    }
1435149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1445149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1455149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    SkAutoGraphics ag;
1465149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1475149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    for (int i = 0; i < FLAGS_readPath.count(); i++) {
1485149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        const char* readPath = FLAGS_readPath[i];
1495149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        if (strlen(readPath) < 1) {
1505149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            break;
1515149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        }
1525149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        if (sk_isdir(readPath)) {
1535149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            const char* dir = readPath;
1545149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            SkOSFile::Iter iter(dir);
1555149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            SkString filename;
1565149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            while (iter.next(&filename)) {
1575149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                if (!is_image_file(filename.c_str())) {
1585149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                    continue;
1595149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                }
160a8e2e1504b9af6ba791637f228debaa23953064atfarina                SkString fullname = SkOSPath::Join(dir, filename.c_str());
1615149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com                decodeFileAndWrite(fullname.c_str());
1625149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            }
1635149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        } else if (sk_exists(readPath) && is_image_file(readPath)) {
1645149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com            decodeFileAndWrite(readPath);
1655149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com        }
1665149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    }
1675149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1685149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    return 0;
1695149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com}
1705149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com
1715149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#if !defined SK_BUILD_FOR_IOS
1725149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.comint main(int argc, char * const argv[]) {
1735149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com    return tool_main(argc, (char**) argv);
1745149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com}
1755149bd954b301abb3cb1e6332c5c84a8d3b99681edisonn@google.com#endif
176