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@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
help(const char * s)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
main(int argc,char * argv[])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