// Copyright 2017 Google Inc. All Rights Reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the COPYING file in the root of the source // tree. An additional intellectual property rights grant can be found // in the file PATENTS. All contributing project authors may // be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Decodes an animated WebP file and dumps the decoded frames as PNG or TIFF. // // Author: Skal (pascal.massimino@gmail.com) #include #include #include // for 'strcmp'. #include "./anim_util.h" #include "webp/decode.h" #include "../imageio/image_enc.h" #include "./unicode.h" #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif static void Help(void) { printf("Usage: anim_dump [options] files...\n"); printf("\nOptions:\n"); printf(" -folder .... dump folder (default: '.')\n"); printf(" -prefix .... prefix for dumped frames " "(default: 'dump_')\n"); printf(" -tiff ............... save frames as TIFF\n"); printf(" -pam ................ save frames as PAM\n"); printf(" -h .................. this help\n"); printf(" -version ............ print version number and exit\n"); } // Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure. int main(int argc, const char* argv[]) { int error = 0; const W_CHAR* dump_folder = TO_W_CHAR("."); const W_CHAR* prefix = TO_W_CHAR("dump_"); const W_CHAR* suffix = TO_W_CHAR("png"); WebPOutputFileFormat format = PNG; int c; INIT_WARGV(argc, argv); if (argc < 2) { Help(); FREE_WARGV_AND_RETURN(EXIT_FAILURE); } for (c = 1; !error && c < argc; ++c) { if (!strcmp(argv[c], "-folder")) { if (c + 1 == argc) { fprintf(stderr, "missing argument after option '%s'\n", argv[c]); error = 1; break; } dump_folder = GET_WARGV(argv, ++c); } else if (!strcmp(argv[c], "-prefix")) { if (c + 1 == argc) { fprintf(stderr, "missing argument after option '%s'\n", argv[c]); error = 1; break; } prefix = GET_WARGV(argv, ++c); } else if (!strcmp(argv[c], "-tiff")) { format = TIFF; suffix = TO_W_CHAR("tiff"); } else if (!strcmp(argv[c], "-pam")) { format = PAM; suffix = TO_W_CHAR("pam"); } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { Help(); FREE_WARGV_AND_RETURN(EXIT_SUCCESS); } else if (!strcmp(argv[c], "-version")) { int dec_version, demux_version; GetAnimatedImageVersions(&dec_version, &demux_version); printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n", (dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff, (dec_version >> 0) & 0xff, (demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff, (demux_version >> 0) & 0xff); FREE_WARGV_AND_RETURN(EXIT_SUCCESS); } else { uint32_t i; AnimatedImage image; const W_CHAR* const file = GET_WARGV(argv, c); memset(&image, 0, sizeof(image)); WPRINTF("Decoding file: %s as %s/%sxxxx.%s\n", file, dump_folder, prefix, suffix); if (!ReadAnimatedImage((const char*)file, &image, 0, NULL)) { WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", file); error = 1; break; } for (i = 0; !error && i < image.num_frames; ++i) { W_CHAR out_file[1024]; WebPDecBuffer buffer; if (!WebPInitDecBuffer(&buffer)) { fprintf(stderr, "Cannot init dec buffer\n"); error = 1; continue; } buffer.colorspace = MODE_RGBA; buffer.is_external_memory = 1; buffer.width = image.canvas_width; buffer.height = image.canvas_height; buffer.u.RGBA.rgba = image.frames[i].rgba; buffer.u.RGBA.stride = buffer.width * sizeof(uint32_t); buffer.u.RGBA.size = buffer.u.RGBA.stride * buffer.height; WSNPRINTF(out_file, sizeof(out_file), "%s/%s%.4d.%s", dump_folder, prefix, i, suffix); if (!WebPSaveImage(&buffer, format, (const char*)out_file)) { WFPRINTF(stderr, "Error while saving image '%s'\n", out_file); error = 1; } WebPFreeDecBuffer(&buffer); } ClearAnimatedImage(&image); } } FREE_WARGV_AND_RETURN(error ? EXIT_FAILURE : EXIT_SUCCESS); }