19aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Copyright 2010 Google Inc. 29aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 39aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// This code is licensed under the same terms as WebM: 49aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Software License Agreement: http://www.webmproject.org/license/software/ 59aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 69aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// ----------------------------------------------------------------------------- 79aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 89aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// simple command-line example calling libwebpdecode to 99aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// decode a WebP image into a PPM image. 109aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 119aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Compile with: gcc -o dwebp dwebp.c -lwebpdecode 129aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 139aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Author: Skal (pascal.massimino@gmail.com) 149aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 159aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include <assert.h> 169aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include <stdio.h> 179aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include <stdlib.h> 189aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include <string.h> 199aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 209aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include "webp/decode.h" 219aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 229aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#if defined(__cplusplus) || defined(c_plusplus) 239aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldextern "C" { 249aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#endif 259aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 269aea642eefa7a641ab8b89d953251939221d2719Eric Hassold//----------------------------------------------------------------------------- 279aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 289aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldstatic void help(const char *s) { 299aea642eefa7a641ab8b89d953251939221d2719Eric Hassold printf("Usage: dwebp " 309aea642eefa7a641ab8b89d953251939221d2719Eric Hassold "[options] [in_file] [-h] [-raw] [-o ppm_file]\n\n" 319aea642eefa7a641ab8b89d953251939221d2719Eric Hassold " -raw: save the raw YUV samples as a grayscale PGM\n" 329aea642eefa7a641ab8b89d953251939221d2719Eric Hassold " file with IMC4 layout.\n" 339aea642eefa7a641ab8b89d953251939221d2719Eric Hassold ); 349aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 359aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 369aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldint main(int argc, char *argv[]) { 379aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const char *in_file = NULL; 389aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const char *out_file = NULL; 399aea642eefa7a641ab8b89d953251939221d2719Eric Hassold int raw_output = 0; 409aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 419aea642eefa7a641ab8b89d953251939221d2719Eric Hassold int width, height, stride, uv_stride; 429aea642eefa7a641ab8b89d953251939221d2719Eric Hassold uint8_t* out = NULL, *u = NULL, *v = NULL; 439aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 449aea642eefa7a641ab8b89d953251939221d2719Eric Hassold int c; 459aea642eefa7a641ab8b89d953251939221d2719Eric Hassold for (c = 1; c < argc; ++c) { 469aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (!strcmp(argv[c], "-h")) { 479aea642eefa7a641ab8b89d953251939221d2719Eric Hassold help(argv[0]); 489aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return 0; 499aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else if (!strcmp(argv[c], "-o") && c < argc - 1) { 509aea642eefa7a641ab8b89d953251939221d2719Eric Hassold out_file = argv[++c]; 519aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else if (!strcmp(argv[c], "-raw")) { 529aea642eefa7a641ab8b89d953251939221d2719Eric Hassold raw_output = 1; 539aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else if (argv[c][0] == '-') { 549aea642eefa7a641ab8b89d953251939221d2719Eric Hassold printf("Unknown option '%s'\n", argv[c]); 559aea642eefa7a641ab8b89d953251939221d2719Eric Hassold help(argv[0]); 569aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return -1; 579aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else { 589aea642eefa7a641ab8b89d953251939221d2719Eric Hassold in_file = argv[c]; 599aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 609aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 619aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 629aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (in_file == NULL) { 639aea642eefa7a641ab8b89d953251939221d2719Eric Hassold printf("missing input file!!\n"); 649aea642eefa7a641ab8b89d953251939221d2719Eric Hassold help(argv[0]); 659aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return -1; 669aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 679aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 689aea642eefa7a641ab8b89d953251939221d2719Eric Hassold { 699aea642eefa7a641ab8b89d953251939221d2719Eric Hassold uint32_t data_size = 0; 709aea642eefa7a641ab8b89d953251939221d2719Eric Hassold void* data = NULL; 719aea642eefa7a641ab8b89d953251939221d2719Eric Hassold FILE* const in = fopen(in_file, "rb"); 729aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (!in) { 739aea642eefa7a641ab8b89d953251939221d2719Eric Hassold printf("cannot open input file '%s'\n", in_file); 749aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return 1; 759aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 769aea642eefa7a641ab8b89d953251939221d2719Eric Hassold fseek(in, 0, SEEK_END); 779aea642eefa7a641ab8b89d953251939221d2719Eric Hassold data_size = ftell(in); 789aea642eefa7a641ab8b89d953251939221d2719Eric Hassold fseek(in, 0, SEEK_SET); 799aea642eefa7a641ab8b89d953251939221d2719Eric Hassold data = malloc(data_size); 809aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const int ok = (fread(data, data_size, 1, in) == 1); 819aea642eefa7a641ab8b89d953251939221d2719Eric Hassold fclose(in); 829aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (!ok) { 839aea642eefa7a641ab8b89d953251939221d2719Eric Hassold free(data); 849aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return -1; 859aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 869aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 879aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (!raw_output) { 889aea642eefa7a641ab8b89d953251939221d2719Eric Hassold out = WebPDecodeRGB(data, data_size, &width, &height); 899aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else { 909aea642eefa7a641ab8b89d953251939221d2719Eric Hassold out = WebPDecodeYUV(data, data_size, &width, &height, 919aea642eefa7a641ab8b89d953251939221d2719Eric Hassold &u, &v, &stride, &uv_stride); 929aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 939aea642eefa7a641ab8b89d953251939221d2719Eric Hassold free(data); 949aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 959aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 969aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (!out) { 979aea642eefa7a641ab8b89d953251939221d2719Eric Hassold printf("Decoding of %s failed.\n", in_file); 989aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return -1; 999aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 1009aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 1019aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (out_file) { 1029aea642eefa7a641ab8b89d953251939221d2719Eric Hassold FILE* const fout = fopen(out_file, "wb"); 1039aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (fout) { 1049aea642eefa7a641ab8b89d953251939221d2719Eric Hassold int ok = 1; 1059aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (!raw_output) { 1069aea642eefa7a641ab8b89d953251939221d2719Eric Hassold fprintf(fout, "P6\n%d %d\n255\n", width, height); 1079aea642eefa7a641ab8b89d953251939221d2719Eric Hassold ok &= (fwrite(out, width * height, 3, fout) == 3); 1089aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else { 1099aea642eefa7a641ab8b89d953251939221d2719Eric Hassold // Save a grayscale PGM file using the IMC4 layout 1109aea642eefa7a641ab8b89d953251939221d2719Eric Hassold // (http://www.fourcc.org/yuv.php#IMC4). This is a very 1119aea642eefa7a641ab8b89d953251939221d2719Eric Hassold // convenient format for viewing the samples, esp. for 1129aea642eefa7a641ab8b89d953251939221d2719Eric Hassold // odd dimensions. 1139aea642eefa7a641ab8b89d953251939221d2719Eric Hassold int y; 1149aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const int uv_width = (width + 1) / 2; 1159aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const int uv_height = (height + 1) / 2; 1169aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const int out_stride = (width + 1) & ~1; 1179aea642eefa7a641ab8b89d953251939221d2719Eric Hassold fprintf(fout, "P5\n%d %d\n255\n", out_stride, height + uv_height); 1189aea642eefa7a641ab8b89d953251939221d2719Eric Hassold for (y = 0; ok && y < height; ++y) { 1199aea642eefa7a641ab8b89d953251939221d2719Eric Hassold ok &= (fwrite(out + y * stride, width, 1, fout) == 1); 1209aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (width & 1) fputc(0, fout); // padding byte 1219aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 1229aea642eefa7a641ab8b89d953251939221d2719Eric Hassold for (y = 0; ok && y < uv_height; ++y) { 1239aea642eefa7a641ab8b89d953251939221d2719Eric Hassold ok &= (fwrite(u + y * uv_stride, uv_width, 1, fout) == 1); 1249aea642eefa7a641ab8b89d953251939221d2719Eric Hassold ok &= (fwrite(v + y * uv_stride, uv_width, 1, fout) == 1); 1259aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 1269aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 1279aea642eefa7a641ab8b89d953251939221d2719Eric Hassold fclose(fout); 1289aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (ok) { 1299aea642eefa7a641ab8b89d953251939221d2719Eric Hassold printf("Saved file %s\n", out_file); 1309aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else { 1319aea642eefa7a641ab8b89d953251939221d2719Eric Hassold printf("Error writing file %s !!\n", out_file); 1329aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 1339aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else { 1349aea642eefa7a641ab8b89d953251939221d2719Eric Hassold printf("Error opening output file %s\n", out_file); 1359aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 1369aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 1379aea642eefa7a641ab8b89d953251939221d2719Eric Hassold printf("Decoded %s. Dimensions: %d x %d.\n", in_file, width, height); 1389aea642eefa7a641ab8b89d953251939221d2719Eric Hassold free(out); 1399aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 1409aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return 0; 1419aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 1429aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 1439aea642eefa7a641ab8b89d953251939221d2719Eric Hassold//----------------------------------------------------------------------------- 1449aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 1459aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#if defined(__cplusplus) || defined(c_plusplus) 1469aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} // extern "C" 1479aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#endif 148