Mercurial > hg > forks > libbpg
annotate bpgdec.c @ 34:5d51fff843eb default tip
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sun, 08 Mar 2020 19:18:48 +0200 |
parents | 33594243ce31 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 * BPG decoder command line utility | |
3 * | |
4 * Copyright (c) 2014 Fabrice Bellard | |
5 * | |
6 * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 * of this software and associated documentation files (the "Software"), to deal | |
8 * in the Software without restriction, including without limitation the rights | |
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 * copies of the Software, and to permit persons to whom the Software is | |
11 * furnished to do so, subject to the following conditions: | |
12 * | |
13 * The above copyright notice and this permission notice shall be included in | |
14 * all copies or substantial portions of the Software. | |
15 * | |
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 * THE SOFTWARE. | |
23 */ | |
24 | |
25 #include <stdlib.h> | |
26 #include <stdio.h> | |
27 #include <math.h> | |
28 #include <getopt.h> | |
29 #include <inttypes.h> | |
20 | 30 #include <string.h> |
31 | |
0 | 32 |
33 /* define it to include PNG output */ | |
34 #define USE_PNG | |
35 | |
36 #ifdef USE_PNG | |
37 #include <png.h> | |
38 #endif | |
39 | |
34
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
40 #ifdef HAVE_LIBEXIF |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
41 #include <exif-data.h> |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
42 #endif |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
43 |
0 | 44 #include "libbpg.h" |
45 | |
46 static void ppm_save(BPGDecoderContext *img, const char *filename) | |
47 { | |
48 BPGImageInfo img_info_s, *img_info = &img_info_s; | |
49 FILE *f; | |
50 int w, h, y; | |
51 uint8_t *rgb_line; | |
52 | |
53 bpg_decoder_get_info(img, img_info); | |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
54 |
0 | 55 w = img_info->width; |
56 h = img_info->height; | |
57 | |
58 rgb_line = malloc(3 * w); | |
59 | |
60 f = fopen(filename,"wb"); | |
61 if (!f) { | |
62 fprintf(stderr, "%s: I/O error\n", filename); | |
63 exit(1); | |
64 } | |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
65 |
0 | 66 fprintf(f, "P6\n%d %d\n%d\n", w, h, 255); |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
67 |
0 | 68 bpg_decoder_start(img, BPG_OUTPUT_FORMAT_RGB24); |
69 for (y = 0; y < h; y++) { | |
70 bpg_decoder_get_line(img, rgb_line); | |
71 fwrite(rgb_line, 1, w * 3, f); | |
72 } | |
73 fclose(f); | |
74 | |
75 free(rgb_line); | |
76 } | |
77 | |
78 #ifdef USE_PNG | |
79 static void png_write_data (png_structp png_ptr, png_bytep data, | |
80 png_size_t length) | |
81 { | |
23
d0ec05fbab88
Cleanups and warnings fixes.
Matti Hamalainen <ccr@tnsp.org>
parents:
21
diff
changeset
|
82 FILE *f = png_get_io_ptr(png_ptr); |
d0ec05fbab88
Cleanups and warnings fixes.
Matti Hamalainen <ccr@tnsp.org>
parents:
21
diff
changeset
|
83 png_size_t ret; |
0 | 84 ret = fwrite(data, 1, length, f); |
85 if (ret != length) | |
86 png_error(png_ptr, "PNG Write Error"); | |
87 } | |
88 | |
89 static void png_save(BPGDecoderContext *img, const char *filename, int bit_depth) | |
90 { | |
91 BPGImageInfo img_info_s, *img_info = &img_info_s; | |
92 FILE *f; | |
93 png_structp png_ptr; | |
94 png_infop info_ptr; | |
95 png_bytep row_pointer; | |
96 int y, color_type, bpp; | |
97 BPGDecoderOutputFormat out_fmt; | |
98 | |
99 if (bit_depth != 8 && bit_depth != 16) { | |
100 fprintf(stderr, "Only bit_depth = 8 or 16 are supported for PNG output\n"); | |
101 exit(1); | |
102 } | |
103 | |
104 bpg_decoder_get_info(img, img_info); | |
105 | |
106 f = fopen(filename, "wb"); | |
107 if (!f) { | |
108 fprintf(stderr, "%s: I/O error\n", filename); | |
109 exit(1); | |
110 } | |
111 | |
112 png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, | |
113 NULL, | |
114 NULL, /* error */ | |
115 NULL, /* warning */ | |
116 NULL, | |
117 NULL, | |
118 NULL); | |
119 info_ptr = png_create_info_struct(png_ptr); | |
120 png_set_write_fn(png_ptr, (png_voidp)f, &png_write_data, NULL); | |
121 | |
122 if (setjmp(png_jmpbuf(png_ptr)) != 0) { | |
123 fprintf(stderr, "PNG write error\n"); | |
124 exit(1); | |
125 } | |
126 | |
127 if (img_info->has_alpha) | |
128 color_type = PNG_COLOR_TYPE_RGB_ALPHA; | |
129 else | |
130 color_type = PNG_COLOR_TYPE_RGB; | |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
131 |
0 | 132 png_set_IHDR(png_ptr, info_ptr, img_info->width, img_info->height, |
133 bit_depth, color_type, PNG_INTERLACE_NONE, | |
134 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); | |
135 | |
136 png_write_info(png_ptr, info_ptr); | |
137 | |
138 #if __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ | |
139 if (bit_depth == 16) { | |
140 png_set_swap(png_ptr); | |
141 } | |
142 #endif | |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
143 |
0 | 144 if (bit_depth == 16) { |
145 if (img_info->has_alpha) | |
146 out_fmt = BPG_OUTPUT_FORMAT_RGBA64; | |
147 else | |
148 out_fmt = BPG_OUTPUT_FORMAT_RGB48; | |
149 } else { | |
150 if (img_info->has_alpha) | |
151 out_fmt = BPG_OUTPUT_FORMAT_RGBA32; | |
152 else | |
153 out_fmt = BPG_OUTPUT_FORMAT_RGB24; | |
154 } | |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
155 |
0 | 156 bpg_decoder_start(img, out_fmt); |
157 | |
158 bpp = (3 + img_info->has_alpha) * (bit_depth / 8); | |
159 row_pointer = (png_bytep)png_malloc(png_ptr, img_info->width * bpp); | |
160 for (y = 0; y < img_info->height; y++) { | |
161 bpg_decoder_get_line(img, row_pointer); | |
162 png_write_row(png_ptr, row_pointer); | |
163 } | |
164 png_free(png_ptr, row_pointer); | |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
165 |
0 | 166 png_write_end(png_ptr, NULL); |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
167 |
0 | 168 png_destroy_write_struct(&png_ptr, &info_ptr); |
169 | |
170 fclose(f); | |
171 } | |
172 #endif /* USE_PNG */ | |
173 | |
33 | 174 |
0 | 175 static void bpg_show_info(const char *filename, int show_extensions) |
176 { | |
177 uint8_t *buf; | |
178 int buf_len, ret, buf_len_max; | |
179 FILE *f; | |
180 BPGImageInfo p_s, *p = &p_s; | |
181 BPGExtensionData *first_md, *md; | |
182 static const char *format_str[6] = { | |
183 "Gray", | |
184 "4:2:0", | |
185 "4:2:2", | |
186 "4:4:4", | |
187 "4:2:0_video", | |
188 "4:2:2_video", | |
189 }; | |
190 static const char *color_space_str[BPG_CS_COUNT] = { | |
191 "YCbCr", | |
192 "RGB", | |
193 "YCgCo", | |
194 "YCbCr_BT709", | |
195 "YCbCr_BT2020", | |
196 }; | |
197 static const char *extension_tag_str[] = { | |
198 "Unknown", | |
199 "EXIF", | |
200 "ICC profile", | |
201 "XMP", | |
202 "Thumbnail", | |
203 "Animation control", | |
204 }; | |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
205 |
0 | 206 f = fopen(filename, "rb"); |
207 if (!f) { | |
208 fprintf(stderr, "Could not open %s\n", filename); | |
209 exit(1); | |
210 } | |
211 | |
212 if (show_extensions) { | |
213 fseek(f, 0, SEEK_END); | |
214 buf_len_max = ftell(f); | |
215 fseek(f, 0, SEEK_SET); | |
216 } else { | |
217 /* if no extension are shown, just need the header */ | |
218 buf_len_max = BPG_DECODER_INFO_BUF_SIZE; | |
219 } | |
220 buf = malloc(buf_len_max); | |
221 buf_len = fread(buf, 1, buf_len_max, f); | |
222 | |
223 ret = bpg_decoder_get_info_from_buf(p, show_extensions ? &first_md : NULL, | |
224 buf, buf_len); | |
225 free(buf); | |
226 fclose(f); | |
227 if (ret < 0) { | |
228 fprintf(stderr, "Not a BPG image\n"); | |
229 exit(1); | |
230 } | |
231 printf("size=%dx%d color_space=%s", | |
232 p->width, p->height, | |
233 p->format == BPG_FORMAT_GRAY ? "Gray" : color_space_str[p->color_space]); | |
234 if (p->has_w_plane) { | |
235 printf(" w_plane=%d", p->has_w_plane); | |
236 } | |
237 if (p->has_alpha) { | |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
238 printf(" alpha=%d premul=%d", |
0 | 239 p->has_alpha, p->premultiplied_alpha); |
240 } | |
241 printf(" format=%s limited_range=%d bit_depth=%d animation=%d\n", | |
242 format_str[p->format], | |
243 p->limited_range, | |
244 p->bit_depth, | |
245 p->has_animation); | |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
246 |
0 | 247 if (first_md) { |
248 const char *tag_name; | |
249 printf("Extension data:\n"); | |
250 for(md = first_md; md != NULL; md = md->next) { | |
23
d0ec05fbab88
Cleanups and warnings fixes.
Matti Hamalainen <ccr@tnsp.org>
parents:
21
diff
changeset
|
251 tag_name = (md->tag < sizeof(extension_tag_str) / sizeof(extension_tag_str[0])) ? |
d0ec05fbab88
Cleanups and warnings fixes.
Matti Hamalainen <ccr@tnsp.org>
parents:
21
diff
changeset
|
252 extension_tag_str[md->tag] : extension_tag_str[0]; |
d0ec05fbab88
Cleanups and warnings fixes.
Matti Hamalainen <ccr@tnsp.org>
parents:
21
diff
changeset
|
253 |
0 | 254 printf(" tag=%d (%s) length=%d\n", |
255 md->tag, tag_name, md->buf_len); | |
34
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
256 |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
257 switch (md->tag) |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
258 { |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
259 case BPG_EXTENSION_TAG_XMP: |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
260 // fwrite(md->buf, md->buf_len, 1, stderr); |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
261 break; |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
262 |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
263 #ifdef HAVE_LIBEXIF |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
264 case BPG_EXTENSION_TAG_EXIF: |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
265 { |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
266 ExifMem *exif_mem = exif_mem_new_default(); |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
267 if (exif_mem != NULL) |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
268 { |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
269 ExifData *exif = exif_data_new_mem(exif_mem); |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
270 if (exif != NULL) |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
271 { |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
272 exif_data_load_data(exif, md->buf, md->buf_len); |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
273 exif_data_fix(exif); |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
274 exif_data_dump(exif); |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
275 exif_data_free(exif); |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
276 } |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
277 } |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
278 } |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
279 break; |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
280 #endif |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
281 |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
282 default: |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
283 break; |
5d51fff843eb
A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
33
diff
changeset
|
284 } |
0 | 285 } |
286 bpg_decoder_free_extension_data(first_md); | |
287 } | |
288 } | |
289 | |
290 static void help(void) | |
291 { | |
292 printf("BPG Image Decoder version " CONFIG_BPG_VERSION "\n" | |
293 "usage: bpgdec [options] infile\n" | |
294 "Options:\n" | |
295 "-o outfile.[ppm|png] set the output filename (default = out.png)\n" | |
296 "-b bit_depth PNG output only: use bit_depth per component (8 or 16, default = 8)\n" | |
297 "-i display information about the image\n"); | |
298 exit(1); | |
299 } | |
300 | |
301 int main(int argc, char **argv) | |
302 { | |
303 FILE *f; | |
304 BPGDecoderContext *img; | |
305 uint8_t *buf; | |
23
d0ec05fbab88
Cleanups and warnings fixes.
Matti Hamalainen <ccr@tnsp.org>
parents:
21
diff
changeset
|
306 png_size_t buf_len; |
d0ec05fbab88
Cleanups and warnings fixes.
Matti Hamalainen <ccr@tnsp.org>
parents:
21
diff
changeset
|
307 int bit_depth, c, show_info; |
0 | 308 const char *outfilename, *filename, *p; |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
309 |
0 | 310 outfilename = "out.png"; |
311 bit_depth = 8; | |
312 show_info = 0; | |
313 for(;;) { | |
314 c = getopt(argc, argv, "ho:b:i"); | |
315 if (c == -1) | |
316 break; | |
317 switch(c) { | |
318 case 'h': | |
319 show_help: | |
320 help(); | |
321 break; | |
322 case 'o': | |
323 outfilename = optarg; | |
324 break; | |
325 case 'b': | |
326 bit_depth = atoi(optarg); | |
327 break; | |
328 case 'i': | |
329 show_info = 1; | |
330 break; | |
331 default: | |
332 exit(1); | |
333 } | |
334 } | |
335 | |
336 if (optind >= argc) | |
337 goto show_help; | |
338 | |
339 filename = argv[optind++]; | |
340 | |
341 if (show_info) { | |
342 bpg_show_info(filename, 1); | |
343 return 0; | |
344 } | |
345 | |
346 f = fopen(filename, "rb"); | |
347 if (!f) { | |
348 fprintf(stderr, "Could not open %s\n", filename); | |
349 exit(1); | |
350 } | |
351 | |
352 fseek(f, 0, SEEK_END); | |
353 buf_len = ftell(f); | |
354 fseek(f, 0, SEEK_SET); | |
355 | |
356 buf = malloc(buf_len); | |
21 | 357 if (!buf) { |
358 fprintf(stderr, "Could not allocate memory for buffer.\n"); | |
359 exit(1); | |
360 } | |
361 | |
0 | 362 if (fread(buf, 1, buf_len, f) != buf_len) { |
363 fprintf(stderr, "Error while reading file\n"); | |
364 exit(1); | |
365 } | |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
366 |
0 | 367 fclose(f); |
368 | |
369 img = bpg_decoder_open(); | |
370 | |
371 if (bpg_decoder_decode(img, buf, buf_len) < 0) { | |
372 fprintf(stderr, "Could not decode image\n"); | |
373 exit(1); | |
374 } | |
375 free(buf); | |
376 | |
377 #ifdef USE_PNG | |
378 p = strrchr(outfilename, '.'); | |
21 | 379 if (p && strcasecmp(p + 1, "ppm") != 0) { |
0 | 380 png_save(img, outfilename, bit_depth); |
5
524eae707ba4
Cosmetics: Remove trailing whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
381 } else |
0 | 382 #endif |
383 { | |
384 ppm_save(img, outfilename); | |
385 } | |
386 | |
387 bpg_decoder_close(img); | |
388 | |
389 return 0; | |
390 } |