1*b2055c35SXin Li // Copyright 2017 Google Inc. All Rights Reserved.
2*b2055c35SXin Li //
3*b2055c35SXin Li // Use of this source code is governed by a BSD-style license
4*b2055c35SXin Li // that can be found in the COPYING file in the root of the source
5*b2055c35SXin Li // tree. An additional intellectual property rights grant can be found
6*b2055c35SXin Li // in the file PATENTS. All contributing project authors may
7*b2055c35SXin Li // be found in the AUTHORS file in the root of the source tree.
8*b2055c35SXin Li // -----------------------------------------------------------------------------
9*b2055c35SXin Li //
10*b2055c35SXin Li // Decodes an animated WebP file and dumps the decoded frames as PNG or TIFF.
11*b2055c35SXin Li //
12*b2055c35SXin Li // Author: Skal ([email protected])
13*b2055c35SXin Li
14*b2055c35SXin Li #include <stdio.h>
15*b2055c35SXin Li #include <string.h> // for 'strcmp'.
16*b2055c35SXin Li
17*b2055c35SXin Li #include "./anim_util.h"
18*b2055c35SXin Li #include "webp/decode.h"
19*b2055c35SXin Li #include "../imageio/image_enc.h"
20*b2055c35SXin Li #include "./unicode.h"
21*b2055c35SXin Li
22*b2055c35SXin Li #if defined(_MSC_VER) && _MSC_VER < 1900
23*b2055c35SXin Li #define snprintf _snprintf
24*b2055c35SXin Li #endif
25*b2055c35SXin Li
Help(void)26*b2055c35SXin Li static void Help(void) {
27*b2055c35SXin Li printf("Usage: anim_dump [options] files...\n");
28*b2055c35SXin Li printf("\nOptions:\n");
29*b2055c35SXin Li printf(" -folder <string> .... dump folder (default: '.')\n");
30*b2055c35SXin Li printf(" -prefix <string> .... prefix for dumped frames "
31*b2055c35SXin Li "(default: 'dump_')\n");
32*b2055c35SXin Li printf(" -tiff ............... save frames as TIFF\n");
33*b2055c35SXin Li printf(" -pam ................ save frames as PAM\n");
34*b2055c35SXin Li printf(" -h .................. this help\n");
35*b2055c35SXin Li printf(" -version ............ print version number and exit\n");
36*b2055c35SXin Li }
37*b2055c35SXin Li
main(int argc,const char * argv[])38*b2055c35SXin Li int main(int argc, const char* argv[]) {
39*b2055c35SXin Li int error = 0;
40*b2055c35SXin Li const W_CHAR* dump_folder = TO_W_CHAR(".");
41*b2055c35SXin Li const W_CHAR* prefix = TO_W_CHAR("dump_");
42*b2055c35SXin Li const W_CHAR* suffix = TO_W_CHAR("png");
43*b2055c35SXin Li WebPOutputFileFormat format = PNG;
44*b2055c35SXin Li int c;
45*b2055c35SXin Li
46*b2055c35SXin Li INIT_WARGV(argc, argv);
47*b2055c35SXin Li
48*b2055c35SXin Li if (argc < 2) {
49*b2055c35SXin Li Help();
50*b2055c35SXin Li FREE_WARGV_AND_RETURN(-1);
51*b2055c35SXin Li }
52*b2055c35SXin Li
53*b2055c35SXin Li for (c = 1; !error && c < argc; ++c) {
54*b2055c35SXin Li if (!strcmp(argv[c], "-folder")) {
55*b2055c35SXin Li if (c + 1 == argc) {
56*b2055c35SXin Li fprintf(stderr, "missing argument after option '%s'\n", argv[c]);
57*b2055c35SXin Li error = 1;
58*b2055c35SXin Li break;
59*b2055c35SXin Li }
60*b2055c35SXin Li dump_folder = GET_WARGV(argv, ++c);
61*b2055c35SXin Li } else if (!strcmp(argv[c], "-prefix")) {
62*b2055c35SXin Li if (c + 1 == argc) {
63*b2055c35SXin Li fprintf(stderr, "missing argument after option '%s'\n", argv[c]);
64*b2055c35SXin Li error = 1;
65*b2055c35SXin Li break;
66*b2055c35SXin Li }
67*b2055c35SXin Li prefix = GET_WARGV(argv, ++c);
68*b2055c35SXin Li } else if (!strcmp(argv[c], "-tiff")) {
69*b2055c35SXin Li format = TIFF;
70*b2055c35SXin Li suffix = TO_W_CHAR("tiff");
71*b2055c35SXin Li } else if (!strcmp(argv[c], "-pam")) {
72*b2055c35SXin Li format = PAM;
73*b2055c35SXin Li suffix = TO_W_CHAR("pam");
74*b2055c35SXin Li } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
75*b2055c35SXin Li Help();
76*b2055c35SXin Li FREE_WARGV_AND_RETURN(0);
77*b2055c35SXin Li } else if (!strcmp(argv[c], "-version")) {
78*b2055c35SXin Li int dec_version, demux_version;
79*b2055c35SXin Li GetAnimatedImageVersions(&dec_version, &demux_version);
80*b2055c35SXin Li printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
81*b2055c35SXin Li (dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
82*b2055c35SXin Li (dec_version >> 0) & 0xff,
83*b2055c35SXin Li (demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
84*b2055c35SXin Li (demux_version >> 0) & 0xff);
85*b2055c35SXin Li FREE_WARGV_AND_RETURN(0);
86*b2055c35SXin Li } else {
87*b2055c35SXin Li uint32_t i;
88*b2055c35SXin Li AnimatedImage image;
89*b2055c35SXin Li const W_CHAR* const file = GET_WARGV(argv, c);
90*b2055c35SXin Li memset(&image, 0, sizeof(image));
91*b2055c35SXin Li WPRINTF("Decoding file: %s as %s/%sxxxx.%s\n",
92*b2055c35SXin Li file, dump_folder, prefix, suffix);
93*b2055c35SXin Li if (!ReadAnimatedImage((const char*)file, &image, 0, NULL)) {
94*b2055c35SXin Li WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", file);
95*b2055c35SXin Li error = 1;
96*b2055c35SXin Li break;
97*b2055c35SXin Li }
98*b2055c35SXin Li for (i = 0; !error && i < image.num_frames; ++i) {
99*b2055c35SXin Li W_CHAR out_file[1024];
100*b2055c35SXin Li WebPDecBuffer buffer;
101*b2055c35SXin Li if (!WebPInitDecBuffer(&buffer)) {
102*b2055c35SXin Li fprintf(stderr, "Cannot init dec buffer\n");
103*b2055c35SXin Li error = 1;
104*b2055c35SXin Li continue;
105*b2055c35SXin Li }
106*b2055c35SXin Li buffer.colorspace = MODE_RGBA;
107*b2055c35SXin Li buffer.is_external_memory = 1;
108*b2055c35SXin Li buffer.width = image.canvas_width;
109*b2055c35SXin Li buffer.height = image.canvas_height;
110*b2055c35SXin Li buffer.u.RGBA.rgba = image.frames[i].rgba;
111*b2055c35SXin Li buffer.u.RGBA.stride = buffer.width * sizeof(uint32_t);
112*b2055c35SXin Li buffer.u.RGBA.size = buffer.u.RGBA.stride * buffer.height;
113*b2055c35SXin Li WSNPRINTF(out_file, sizeof(out_file), "%s/%s%.4d.%s",
114*b2055c35SXin Li dump_folder, prefix, i, suffix);
115*b2055c35SXin Li if (!WebPSaveImage(&buffer, format, (const char*)out_file)) {
116*b2055c35SXin Li WFPRINTF(stderr, "Error while saving image '%s'\n", out_file);
117*b2055c35SXin Li error = 1;
118*b2055c35SXin Li }
119*b2055c35SXin Li WebPFreeDecBuffer(&buffer);
120*b2055c35SXin Li }
121*b2055c35SXin Li ClearAnimatedImage(&image);
122*b2055c35SXin Li }
123*b2055c35SXin Li }
124*b2055c35SXin Li FREE_WARGV_AND_RETURN(error ? 1 : 0);
125*b2055c35SXin Li }
126