1 // Copyright 2010 Google Inc. 2 // 3 // This code is licensed under the same terms as WebM: 4 // Software License Agreement: http://www.webmproject.org/license/software/ 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 6 // ----------------------------------------------------------------------------- 7 // 8 // simple command-line example calling libwebpdecode to 9 // decode a WebP image into a PPM image. 10 // 11 // Compile with: gcc -o dwebp dwebp.c -lwebpdecode 12 // 13 // Author: Skal (pascal.massimino (at) gmail.com) 14 15 #include <assert.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 20 #include "webp/decode.h" 21 22 #if defined(__cplusplus) || defined(c_plusplus) 23 extern "C" { 24 #endif 25 26 //----------------------------------------------------------------------------- 27 28 static void help(const char *s) { 29 printf("Usage: dwebp " 30 "[options] [in_file] [-h] [-raw] [-o ppm_file]\n\n" 31 " -raw: save the raw YUV samples as a grayscale PGM\n" 32 " file with IMC4 layout.\n" 33 ); 34 } 35 36 int main(int argc, char *argv[]) { 37 const char *in_file = NULL; 38 const char *out_file = NULL; 39 int raw_output = 0; 40 41 int width, height, stride, uv_stride; 42 uint8_t* out = NULL, *u = NULL, *v = NULL; 43 44 int c; 45 for (c = 1; c < argc; ++c) { 46 if (!strcmp(argv[c], "-h")) { 47 help(argv[0]); 48 return 0; 49 } else if (!strcmp(argv[c], "-o") && c < argc - 1) { 50 out_file = argv[++c]; 51 } else if (!strcmp(argv[c], "-raw")) { 52 raw_output = 1; 53 } else if (argv[c][0] == '-') { 54 printf("Unknown option '%s'\n", argv[c]); 55 help(argv[0]); 56 return -1; 57 } else { 58 in_file = argv[c]; 59 } 60 } 61 62 if (in_file == NULL) { 63 printf("missing input file!!\n"); 64 help(argv[0]); 65 return -1; 66 } 67 68 { 69 uint32_t data_size = 0; 70 void* data = NULL; 71 FILE* const in = fopen(in_file, "rb"); 72 if (!in) { 73 printf("cannot open input file '%s'\n", in_file); 74 return 1; 75 } 76 fseek(in, 0, SEEK_END); 77 data_size = ftell(in); 78 fseek(in, 0, SEEK_SET); 79 data = malloc(data_size); 80 const int ok = (fread(data, data_size, 1, in) == 1); 81 fclose(in); 82 if (!ok) { 83 free(data); 84 return -1; 85 } 86 87 if (!raw_output) { 88 out = WebPDecodeRGB(data, data_size, &width, &height); 89 } else { 90 out = WebPDecodeYUV(data, data_size, &width, &height, 91 &u, &v, &stride, &uv_stride); 92 } 93 free(data); 94 } 95 96 if (!out) { 97 printf("Decoding of %s failed.\n", in_file); 98 return -1; 99 } 100 101 if (out_file) { 102 FILE* const fout = fopen(out_file, "wb"); 103 if (fout) { 104 int ok = 1; 105 if (!raw_output) { 106 fprintf(fout, "P6\n%d %d\n255\n", width, height); 107 ok &= (fwrite(out, width * height, 3, fout) == 3); 108 } else { 109 // Save a grayscale PGM file using the IMC4 layout 110 // (http://www.fourcc.org/yuv.php#IMC4). This is a very 111 // convenient format for viewing the samples, esp. for 112 // odd dimensions. 113 int y; 114 const int uv_width = (width + 1) / 2; 115 const int uv_height = (height + 1) / 2; 116 const int out_stride = (width + 1) & ~1; 117 fprintf(fout, "P5\n%d %d\n255\n", out_stride, height + uv_height); 118 for (y = 0; ok && y < height; ++y) { 119 ok &= (fwrite(out + y * stride, width, 1, fout) == 1); 120 if (width & 1) fputc(0, fout); // padding byte 121 } 122 for (y = 0; ok && y < uv_height; ++y) { 123 ok &= (fwrite(u + y * uv_stride, uv_width, 1, fout) == 1); 124 ok &= (fwrite(v + y * uv_stride, uv_width, 1, fout) == 1); 125 } 126 } 127 fclose(fout); 128 if (ok) { 129 printf("Saved file %s\n", out_file); 130 } else { 131 printf("Error writing file %s !!\n", out_file); 132 } 133 } else { 134 printf("Error opening output file %s\n", out_file); 135 } 136 } 137 printf("Decoded %s. Dimensions: %d x %d.\n", in_file, width, height); 138 free(out); 139 140 return 0; 141 } 142 143 //----------------------------------------------------------------------------- 144 145 #if defined(__cplusplus) || defined(c_plusplus) 146 } // extern "C" 147 #endif 148