Fix some typos (found by codespell)
[openjpeg.git] / src / bin / jp2 / convertpng.c
1 /*
2  * The copyright in this software is being made available under the 2-clauses
3  * BSD License, included below. This software may be subject to other third
4  * party and contributor rights, including patent rights, and no such rights
5  * are granted under this license.
6  *
7  * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
8  * Copyright (c) 2002-2014, Professor Benoit Macq
9  * Copyright (c) 2001-2003, David Janssens
10  * Copyright (c) 2002-2003, Yannick Verschueren
11  * Copyright (c) 2003-2007, Francois-Olivier Devaux
12  * Copyright (c) 2003-2014, Antonin Descampe
13  * Copyright (c) 2005, Herve Drolon, FreeImage Team
14  * Copyright (c) 2006-2007, Parvatha Elangovan
15  * Copyright (c) 2015, Matthieu Darbois
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions
20  * are met:
21  * 1. Redistributions of source code must retain the above copyright
22  *    notice, this list of conditions and the following disclaimer.
23  * 2. Redistributions in binary form must reproduce the above copyright
24  *    notice, this list of conditions and the following disclaimer in the
25  *    documentation and/or other materials provided with the distribution.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 #include "opj_apps_config.h"
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <ctype.h>
45
46 #include <zlib.h>
47 #include <png.h>
48
49 #include "openjpeg.h"
50 #include "convert.h"
51
52 #define PNG_MAGIC "\x89PNG\x0d\x0a\x1a\x0a"
53 #define MAGIC_SIZE 8
54 /* PNG allows bits per sample: 1, 2, 4, 8, 16 */
55
56
57 static void convert_16u32s_C1R(const OPJ_BYTE* pSrc, OPJ_INT32* pDst,
58                                OPJ_SIZE_T length)
59 {
60     OPJ_SIZE_T i;
61     for (i = 0; i < length; i++) {
62         OPJ_INT32 val0 = *pSrc++;
63         OPJ_INT32 val1 = *pSrc++;
64         pDst[i] = val0 << 8 | val1;
65     }
66 }
67
68 static opj_image_t * pngtoimage_internal(opj_cparameters_t * params,
69         FILE *reader,
70         png_structp  png,
71         png_infop    info,
72         png_uint_32* pheight,
73         OPJ_BYTE*** prows,
74         OPJ_INT32** prow32s)
75 {
76     *pheight = 0;
77     *prows = NULL;
78     *prow32s = NULL;
79
80     if (setjmp(png_jmpbuf(png))) {
81         return NULL;
82     }
83
84     {
85         opj_image_t *image = NULL;
86         opj_image_cmptparm_t cmptparm[4];
87         OPJ_UINT32 nr_comp;
88         convert_XXx32s_C1R cvtXXTo32s = NULL;
89         convert_32s_CXPX cvtCxToPx = NULL;
90         OPJ_INT32* planes[4];
91         double gamma;
92         int bit_depth, interlace_type, compression_type, filter_type;
93         OPJ_UINT32 i;
94         png_uint_32  width, height = 0U;
95         int color_type;
96         OPJ_BYTE** rows = NULL;
97         OPJ_INT32* row32s = NULL;
98
99         png_init_io(png, reader);
100         png_set_sig_bytes(png, MAGIC_SIZE);
101
102         png_read_info(png, info);
103
104         if (png_get_IHDR(png, info, &width, &height,
105                          &bit_depth, &color_type, &interlace_type,
106                          &compression_type, &filter_type) == 0) {
107             return image;
108         }
109         *pheight = height;
110
111         /* png_set_expand():
112          * expand paletted images to RGB, expand grayscale images of
113          * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
114          * to alpha channels.
115          */
116         if (color_type == PNG_COLOR_TYPE_PALETTE) {
117             png_set_expand(png);
118         }
119
120         if (png_get_valid(png, info, PNG_INFO_tRNS)) {
121             png_set_expand(png);
122         }
123         /* We might want to expand background */
124         /*
125         if(png_get_valid(png, info, PNG_INFO_bKGD)) {
126             png_color_16p bgnd;
127             png_get_bKGD(png, info, &bgnd);
128             png_set_background(png, bgnd, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
129         }
130         */
131
132         if (!png_get_gAMA(png, info, &gamma)) {
133             gamma = 1.0;
134         }
135
136         /* we're not displaying but converting, screen gamma == 1.0 */
137         png_set_gamma(png, 1.0, gamma);
138
139         png_read_update_info(png, info);
140
141         color_type = png_get_color_type(png, info);
142
143         switch (color_type) {
144         case PNG_COLOR_TYPE_GRAY:
145             nr_comp = 1;
146             break;
147         case PNG_COLOR_TYPE_GRAY_ALPHA:
148             nr_comp = 2;
149             break;
150         case PNG_COLOR_TYPE_RGB:
151             nr_comp = 3;
152             break;
153         case PNG_COLOR_TYPE_RGB_ALPHA:
154             nr_comp = 4;
155             break;
156         default:
157             fprintf(stderr, "pngtoimage: colortype %d is not supported\n", color_type);
158             return image;
159         }
160         cvtCxToPx = convert_32s_CXPX_LUT[nr_comp];
161         bit_depth = png_get_bit_depth(png, info);
162
163         switch (bit_depth) {
164         case 1:
165         case 2:
166         case 4:
167         case 8:
168             cvtXXTo32s = convert_XXu32s_C1R_LUT[bit_depth];
169             break;
170         case 16: /* 16 bpp is specific to PNG */
171             cvtXXTo32s = convert_16u32s_C1R;
172             break;
173         default:
174             fprintf(stderr, "pngtoimage: bit depth %d is not supported\n", bit_depth);
175             return image;
176         }
177
178         rows = (OPJ_BYTE**)calloc(height + 1, sizeof(OPJ_BYTE*));
179         if (rows == NULL) {
180             fprintf(stderr, "pngtoimage: memory out\n");
181             return image;
182         }
183         *prows = rows;
184         for (i = 0; i < height; ++i) {
185             rows[i] = (OPJ_BYTE*)malloc(png_get_rowbytes(png, info));
186             if (rows[i] == NULL) {
187                 fprintf(stderr, "pngtoimage: memory out\n");
188                 return image;
189             }
190         }
191         png_read_image(png, rows);
192
193         /* Create image */
194         memset(cmptparm, 0, sizeof(cmptparm));
195         for (i = 0; i < nr_comp; ++i) {
196             /* bits_per_pixel: 8 or 16 */
197             cmptparm[i].prec = (OPJ_UINT32)bit_depth;
198             cmptparm[i].sgnd = 0;
199             cmptparm[i].dx = (OPJ_UINT32)params->subsampling_dx;
200             cmptparm[i].dy = (OPJ_UINT32)params->subsampling_dy;
201             cmptparm[i].w = (OPJ_UINT32)width;
202             cmptparm[i].h = (OPJ_UINT32)height;
203         }
204
205         image = opj_image_create(nr_comp, &cmptparm[0],
206                                  (nr_comp > 2U) ? OPJ_CLRSPC_SRGB : OPJ_CLRSPC_GRAY);
207         if (image == NULL) {
208             return image;
209         }
210         image->x0 = (OPJ_UINT32)params->image_offset_x0;
211         image->y0 = (OPJ_UINT32)params->image_offset_y0;
212         image->x1 = (OPJ_UINT32)(image->x0 + (width  - 1) * (OPJ_UINT32)
213                                  params->subsampling_dx + 1);
214         image->y1 = (OPJ_UINT32)(image->y0 + (height - 1) * (OPJ_UINT32)
215                                  params->subsampling_dy + 1);
216
217         row32s = (OPJ_INT32 *)malloc((size_t)width * nr_comp * sizeof(OPJ_INT32));
218         if (row32s == NULL) {
219             return image;
220         }
221         *prow32s = row32s;
222
223         /* Set alpha channel */
224         image->comps[nr_comp - 1U].alpha = 1U - (nr_comp & 1U);
225
226         for (i = 0; i < nr_comp; i++) {
227             planes[i] = image->comps[i].data;
228         }
229
230         for (i = 0; i < height; ++i) {
231             cvtXXTo32s(rows[i], row32s, (OPJ_SIZE_T)width * nr_comp);
232             cvtCxToPx(row32s, planes, width);
233             planes[0] += width;
234             planes[1] += width;
235             planes[2] += width;
236             planes[3] += width;
237         }
238
239         return image;
240     }
241 }
242
243 opj_image_t *pngtoimage(const char *read_idf, opj_cparameters_t * params)
244 {
245     png_structp  png = NULL;
246     png_infop    info = NULL;
247     OPJ_UINT32 i;
248     png_uint_32  height = 0U;
249     FILE *reader = NULL;
250     OPJ_BYTE** rows = NULL;
251     OPJ_INT32* row32s = NULL;
252     OPJ_BYTE sigbuf[8];
253     opj_image_t *image = NULL;
254
255     if ((reader = fopen(read_idf, "rb")) == NULL) {
256         fprintf(stderr, "pngtoimage: can not open %s\n", read_idf);
257         return NULL;
258     }
259
260     if (fread(sigbuf, 1, MAGIC_SIZE, reader) != MAGIC_SIZE
261             || memcmp(sigbuf, PNG_MAGIC, MAGIC_SIZE) != 0) {
262         fprintf(stderr, "pngtoimage: %s is no valid PNG file\n", read_idf);
263         goto fin;
264     }
265
266     if ((png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
267                                       NULL, NULL, NULL)) == NULL) {
268         goto fin;
269     }
270     if ((info = png_create_info_struct(png)) == NULL) {
271         goto fin;
272     }
273
274     image = pngtoimage_internal(params, reader, png, info, &height, &rows, &row32s);
275 fin:
276     if (rows) {
277         for (i = 0; i < height; ++i)
278             if (rows[i]) {
279                 free(rows[i]);
280             }
281         free(rows);
282     }
283     if (row32s) {
284         free(row32s);
285     }
286     if (png) {
287         png_destroy_read_struct(&png, &info, NULL);
288     }
289
290     fclose(reader);
291
292     return image;
293
294 }/* pngtoimage() */
295
296
297 static void convert_32s16u_C1R(const OPJ_INT32* pSrc, OPJ_BYTE* pDst,
298                                OPJ_SIZE_T length)
299 {
300     OPJ_SIZE_T i;
301     for (i = 0; i < length; i++) {
302         OPJ_UINT32 val = (OPJ_UINT32)pSrc[i];
303         *pDst++ = (OPJ_BYTE)(val >> 8);
304         *pDst++ = (OPJ_BYTE)val;
305     }
306 }
307 int imagetopng(opj_image_t * image, const char *write_idf)
308 {
309     FILE * volatile writer = NULL;
310     png_structp png = NULL;
311     png_infop info = NULL;
312     png_bytep volatile row_buf = NULL;
313     int nr_comp, color_type;
314     volatile int prec;
315     png_color_8 sig_bit;
316     OPJ_INT32 const* planes[4];
317     int i;
318     OPJ_INT32* volatile buffer32s = NULL;
319
320     volatile int fails = 1;
321
322     memset(&sig_bit, 0, sizeof(sig_bit));
323     prec = (int)image->comps[0].prec;
324     planes[0] = image->comps[0].data;
325     if (planes[0] == NULL) {
326         fprintf(stderr,
327                 "imagetopng: planes[%d] == NULL.\n", 0);
328         fprintf(stderr, "\tAborting\n");
329         return 1;
330     }
331     nr_comp = (int)image->numcomps;
332
333     if (nr_comp > 4) {
334         nr_comp = 4;
335     }
336     for (i = 1; i < nr_comp; ++i) {
337         if (image->comps[0].dx != image->comps[i].dx) {
338             break;
339         }
340         if (image->comps[0].dy != image->comps[i].dy) {
341             break;
342         }
343         if (image->comps[0].prec != image->comps[i].prec) {
344             break;
345         }
346         if (image->comps[0].sgnd != image->comps[i].sgnd) {
347             break;
348         }
349         planes[i] = image->comps[i].data;
350         if (planes[i] == NULL) {
351             fprintf(stderr,
352                     "imagetopng: planes[%d] == NULL.\n", i);
353             fprintf(stderr, "\tAborting\n");
354             return 1;
355         }
356     }
357     if (i != nr_comp) {
358         fprintf(stderr,
359                 "imagetopng: All components shall have the same subsampling, same bit depth, same sign.\n");
360         fprintf(stderr, "\tAborting\n");
361         return 1;
362     }
363     for (i = 0; i < nr_comp; ++i) {
364         clip_component(&(image->comps[i]), image->comps[0].prec);
365     }
366     if (prec > 8 && prec < 16) {
367         for (i = 0; i < nr_comp; ++i) {
368             scale_component(&(image->comps[i]), 16);
369         }
370         prec = 16;
371     } else if (prec < 8 && nr_comp > 1) { /* GRAY_ALPHA, RGB, RGB_ALPHA */
372         for (i = 0; i < nr_comp; ++i) {
373             scale_component(&(image->comps[i]), 8);
374         }
375         prec = 8;
376     } else if ((prec > 1) && (prec < 8) && ((prec == 6) ||
377                                             ((prec & 1) == 1))) { /* GRAY with non native precision */
378         if ((prec == 5) || (prec == 6)) {
379             prec = 8;
380         } else {
381             prec++;
382         }
383         for (i = 0; i < nr_comp; ++i) {
384             scale_component(&(image->comps[i]), (OPJ_UINT32)prec);
385         }
386     }
387
388     if (prec != 1 && prec != 2 && prec != 4 && prec != 8 && prec != 16) {
389         fprintf(stderr, "imagetopng: can not create %s\n\twrong bit_depth %d\n",
390                 write_idf, prec);
391         return fails;
392     }
393
394     writer = fopen(write_idf, "wb");
395
396     if (writer == NULL) {
397         return fails;
398     }
399
400     /* Create and initialize the png_struct with the desired error handler
401      * functions.  If you want to use the default stderr and longjump method,
402      * you can supply NULL for the last three parameters.  We also check that
403      * the library version is compatible with the one used at compile time,
404      * in case we are using dynamically linked libraries.  REQUIRED.
405      */
406     png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
407                                   NULL, NULL, NULL);
408     /*png_voidp user_error_ptr, user_error_fn, user_warning_fn); */
409
410     if (png == NULL) {
411         goto fin;
412     }
413
414     /* Allocate/initialize the image information data.  REQUIRED
415      */
416     info = png_create_info_struct(png);
417
418     if (info == NULL) {
419         goto fin;
420     }
421
422     /* Set error handling.  REQUIRED if you are not supplying your own
423      * error handling functions in the png_create_write_struct() call.
424      */
425     if (setjmp(png_jmpbuf(png))) {
426         goto fin;
427     }
428
429     /* I/O initialization functions is REQUIRED
430      */
431     png_init_io(png, writer);
432
433     /* Set the image information here.  Width and height are up to 2^31,
434      * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
435      * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
436      * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
437      * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
438      * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
439      * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE.
440      * REQUIRED
441      *
442      * ERRORS:
443      *
444      * color_type == PNG_COLOR_TYPE_PALETTE && bit_depth > 8
445      * color_type == PNG_COLOR_TYPE_RGB && bit_depth < 8
446      * color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth < 8
447      * color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8
448      *
449      */
450     png_set_compression_level(png, Z_BEST_COMPRESSION);
451
452     if (nr_comp >= 3) { /* RGB(A) */
453         color_type = PNG_COLOR_TYPE_RGB;
454         sig_bit.red = sig_bit.green = sig_bit.blue = (png_byte)prec;
455     } else { /* GRAY(A) */
456         color_type = PNG_COLOR_TYPE_GRAY;
457         sig_bit.gray = (png_byte)prec;
458     }
459     if ((nr_comp & 1) == 0) { /* ALPHA */
460         color_type |= PNG_COLOR_MASK_ALPHA;
461         sig_bit.alpha = (png_byte)prec;
462     }
463
464     png_set_IHDR(png, info, image->comps[0].w, image->comps[0].h, prec, color_type,
465                  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,  PNG_FILTER_TYPE_BASE);
466
467     png_set_sBIT(png, info, &sig_bit);
468     /* png_set_gamma(png, 2.2, 1./2.2); */
469     /* png_set_sRGB(png, info, PNG_sRGB_INTENT_PERCEPTUAL); */
470     png_write_info(png, info);
471
472     /* setup conversion */
473     {
474         OPJ_SIZE_T rowStride;
475         png_size_t png_row_size;
476
477         png_row_size = png_get_rowbytes(png, info);
478         rowStride = ((OPJ_SIZE_T)image->comps[0].w * (OPJ_SIZE_T)nr_comp *
479                      (OPJ_SIZE_T)prec + 7U) / 8U;
480         if (rowStride != (OPJ_SIZE_T)png_row_size) {
481             fprintf(stderr, "Invalid PNG row size\n");
482             goto fin;
483         }
484         row_buf = (png_bytep)malloc(png_row_size);
485         if (row_buf == NULL) {
486             fprintf(stderr, "Can't allocate memory for PNG row\n");
487             goto fin;
488         }
489         buffer32s = (OPJ_INT32*)malloc((OPJ_SIZE_T)image->comps[0].w *
490                                        (OPJ_SIZE_T)nr_comp * sizeof(OPJ_INT32));
491         if (buffer32s == NULL) {
492             fprintf(stderr, "Can't allocate memory for interleaved 32s row\n");
493             goto fin;
494         }
495     }
496
497     /* convert */
498     {
499         OPJ_SIZE_T width = image->comps[0].w;
500         OPJ_UINT32 y;
501         convert_32s_PXCX cvtPxToCx = convert_32s_PXCX_LUT[nr_comp];
502         convert_32sXXx_C1R cvt32sToPack = NULL;
503         OPJ_INT32 adjust = image->comps[0].sgnd ? 1 << (prec - 1) : 0;
504         png_bytep row_buf_cpy = row_buf;
505         OPJ_INT32* buffer32s_cpy = buffer32s;
506
507         switch (prec) {
508         case 1:
509         case 2:
510         case 4:
511         case 8:
512             cvt32sToPack = convert_32sXXu_C1R_LUT[prec];
513             break;
514         case 16:
515             cvt32sToPack = convert_32s16u_C1R;
516             break;
517         default:
518             /* never here */
519             break;
520         }
521
522         for (y = 0; y < image->comps[0].h; ++y) {
523             cvtPxToCx(planes, buffer32s_cpy, width, adjust);
524             cvt32sToPack(buffer32s_cpy, row_buf_cpy, width * (OPJ_SIZE_T)nr_comp);
525             png_write_row(png, row_buf_cpy);
526             planes[0] += width;
527             planes[1] += width;
528             planes[2] += width;
529             planes[3] += width;
530         }
531     }
532
533     png_write_end(png, info);
534
535     fails = 0;
536
537 fin:
538     if (png) {
539         png_destroy_write_struct(&png, &info);
540     }
541     if (row_buf) {
542         free(row_buf);
543     }
544     if (buffer32s) {
545         free(buffer32s);
546     }
547     fclose(writer);
548
549     if (fails) {
550         (void)remove(write_idf);    /* ignore return value */
551     }
552
553     return fails;
554 }/* imagetopng() */