5635c7d0d8897c6446addc4674e7ec5cbc6caba9
[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, OPJ_SIZE_T length)
58 {
59         OPJ_SIZE_T i;
60         for (i = 0; i < length; i++) {
61                 OPJ_INT32 val0 = *pSrc++;
62                 OPJ_INT32 val1 = *pSrc++;
63                 pDst[i] = val0 << 8 | val1;
64         }
65 }
66
67 opj_image_t *pngtoimage(const char *read_idf, opj_cparameters_t * params)
68 {
69         png_structp  png = NULL;
70         png_infop    info = NULL;
71         double gamma;
72         int bit_depth, interlace_type,compression_type, filter_type;
73         OPJ_UINT32 i;
74         png_uint_32  width, height = 0U;
75         int color_type;
76         FILE *reader = NULL;
77         OPJ_BYTE** rows = NULL;
78         OPJ_INT32* row32s = NULL;
79         /* j2k: */
80         opj_image_t *image = NULL;
81         opj_image_cmptparm_t cmptparm[4];
82         OPJ_UINT32 nr_comp;
83         OPJ_BYTE sigbuf[8];
84         convert_XXx32s_C1R cvtXXTo32s = NULL;
85         convert_32s_CXPX cvtCxToPx = NULL;
86         OPJ_INT32* planes[4];
87         
88         if((reader = fopen(read_idf, "rb")) == NULL)
89         {
90                 fprintf(stderr,"pngtoimage: can not open %s\n",read_idf);
91                 return NULL;
92         }
93         
94         if(fread(sigbuf, 1, MAGIC_SIZE, reader) != MAGIC_SIZE
95                  || memcmp(sigbuf, PNG_MAGIC, MAGIC_SIZE) != 0)
96         {
97                 fprintf(stderr,"pngtoimage: %s is no valid PNG file\n",read_idf);
98                 goto fin;
99         }
100         
101         if((png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
102                                                                                                                                          NULL, NULL, NULL)) == NULL)
103                 goto fin;
104         if((info = png_create_info_struct(png)) == NULL)
105                 goto fin;
106         
107         if(setjmp(png_jmpbuf(png)))
108                 goto fin;
109         
110         png_init_io(png, reader);
111         png_set_sig_bytes(png, MAGIC_SIZE);
112         
113         png_read_info(png, info);
114         
115         if(png_get_IHDR(png, info, &width, &height,
116                                                                         &bit_depth, &color_type, &interlace_type,
117                                                                         &compression_type, &filter_type) == 0)
118                 goto fin;
119         
120         /* png_set_expand():
121          * expand paletted images to RGB, expand grayscale images of
122          * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
123          * to alpha channels.
124          */
125         if(color_type == PNG_COLOR_TYPE_PALETTE) {
126                 png_set_expand(png);
127         }
128         
129         if(png_get_valid(png, info, PNG_INFO_tRNS)) {
130                 png_set_expand(png);
131         }
132         /* We might wan't to expand background */
133         /*
134         if(png_get_valid(png, info, PNG_INFO_bKGD)) {
135                 png_color_16p bgnd;
136                 png_get_bKGD(png, info, &bgnd);
137                 png_set_background(png, bgnd, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
138         }
139         */
140         
141         if( !png_get_gAMA(png, info, &gamma))
142                 gamma = 1.0;
143         
144         /* we're not displaying but converting, screen gamma == 1.0 */
145         png_set_gamma(png, 1.0, gamma);
146         
147         png_read_update_info(png, info);
148         
149         color_type = png_get_color_type(png, info);
150         
151         switch (color_type) {
152                 case PNG_COLOR_TYPE_GRAY:
153                         nr_comp = 1;
154                         break;
155                 case PNG_COLOR_TYPE_GRAY_ALPHA:
156                         nr_comp = 2;
157                         break;
158                 case PNG_COLOR_TYPE_RGB:
159                         nr_comp = 3;
160                         break;
161                 case PNG_COLOR_TYPE_RGB_ALPHA:
162                         nr_comp = 4;
163                         break;
164                 default:
165                         fprintf(stderr,"pngtoimage: colortype %d is not supported\n", color_type);
166                         goto fin;
167         }
168         cvtCxToPx = convert_32s_CXPX_LUT[nr_comp];
169         bit_depth = png_get_bit_depth(png, info);
170         
171         switch (bit_depth) {
172                 case 1:
173                 case 2:
174                 case 4:
175                 case 8:
176                         cvtXXTo32s = convert_XXu32s_C1R_LUT[bit_depth];
177                         break;
178                 case 16: /* 16 bpp is specific to PNG */
179                         cvtXXTo32s = convert_16u32s_C1R;
180                         break;
181                 default:
182                         fprintf(stderr,"pngtoimage: bit depth %d is not supported\n", bit_depth);
183                         goto fin;
184         }
185
186         
187         rows = (OPJ_BYTE**)calloc(height+1, sizeof(OPJ_BYTE*));
188         if(rows == NULL){
189                 fprintf(stderr, "pngtoimage: memory out\n");
190                 goto fin;
191         }
192         for(i = 0; i < height; ++i){
193                 rows[i] = (OPJ_BYTE*)malloc(png_get_rowbytes(png,info));
194                 if(rows[i] == NULL){
195                         fprintf(stderr,"pngtoimage: memory out\n");
196                         goto fin;
197                 }
198         }       
199         png_read_image(png, rows);
200         
201         /* Create image */
202         memset(cmptparm, 0, sizeof(cmptparm));
203         for(i = 0; i < nr_comp; ++i)
204         {
205                 cmptparm[i].prec = (OPJ_UINT32)bit_depth;
206                 /* bits_per_pixel: 8 or 16 */
207                 cmptparm[i].bpp = (OPJ_UINT32)bit_depth;
208                 cmptparm[i].sgnd = 0;
209                 cmptparm[i].dx = (OPJ_UINT32)params->subsampling_dx;
210                 cmptparm[i].dy = (OPJ_UINT32)params->subsampling_dy;
211                 cmptparm[i].w = (OPJ_UINT32)width;
212                 cmptparm[i].h = (OPJ_UINT32)height;
213         }
214         
215         image = opj_image_create(nr_comp, &cmptparm[0], (nr_comp > 2U) ? OPJ_CLRSPC_SRGB : OPJ_CLRSPC_GRAY);
216         if(image == NULL) goto fin;
217         image->x0 = (OPJ_UINT32)params->image_offset_x0;
218         image->y0 = (OPJ_UINT32)params->image_offset_y0;
219         image->x1 = (OPJ_UINT32)(image->x0 + (width  - 1) * (OPJ_UINT32)params->subsampling_dx + 1 + image->x0);
220         image->y1 = (OPJ_UINT32)(image->y0 + (height - 1) * (OPJ_UINT32)params->subsampling_dy + 1 + image->y0);
221         
222         row32s = (OPJ_INT32 *)malloc((size_t)width * nr_comp * sizeof(OPJ_INT32));
223         if(row32s == NULL) goto fin;
224         
225         /* Set alpha channel */
226         image->comps[nr_comp-1U].alpha = 1U - (nr_comp & 1U);
227         
228         for(i = 0; i < nr_comp; i++)
229         {
230                 planes[i] = image->comps[i].data;
231         }
232         
233         for(i = 0; i < height; ++i)
234         {
235                 cvtXXTo32s(rows[i], row32s, (OPJ_SIZE_T)width * nr_comp);
236                 cvtCxToPx(row32s, planes, width);
237                 planes[0] += width;
238                 planes[1] += width;
239                 planes[2] += width;
240                 planes[3] += width;
241         }
242 fin:
243         if(rows)
244         {
245                 for(i = 0; i < height; ++i)
246                         if(rows[i]) free(rows[i]);
247                 free(rows);
248         }
249         if (row32s) {
250                 free(row32s);
251         }
252         if(png)
253                 png_destroy_read_struct(&png, &info, NULL);
254         
255         fclose(reader);
256         
257         return image;
258         
259 }/* pngtoimage() */
260
261
262 static void convert_32s16u_C1R(const OPJ_INT32* pSrc, OPJ_BYTE* pDst, OPJ_SIZE_T length)
263 {
264         OPJ_SIZE_T i;
265         for (i = 0; i < length; i++) {
266                 OPJ_UINT32 val = (OPJ_UINT32)pSrc[i];
267                 *pDst++ = (OPJ_BYTE)(val >> 8);
268                 *pDst++ = (OPJ_BYTE)val;
269         }
270 }
271 int imagetopng(opj_image_t * image, const char *write_idf)
272 {
273         FILE * volatile writer = NULL;
274         png_structp png = NULL;
275         png_infop info = NULL;
276         png_bytep volatile row_buf = NULL;
277         int nr_comp, color_type;
278         volatile int prec;
279         png_color_8 sig_bit;
280         OPJ_INT32 const* planes[4];
281         int i;
282         OPJ_INT32* volatile buffer32s = NULL;
283         
284         volatile int fails = 1;
285         
286         memset(&sig_bit, 0, sizeof(sig_bit));
287         prec = (int)image->comps[0].prec;
288         planes[0] = image->comps[0].data;
289         nr_comp = (int)image->numcomps;
290         
291         if (nr_comp > 4) {
292                 nr_comp = 4;
293         }
294         for (i = 1; i < nr_comp; ++i) {
295                 if (image->comps[0].dx != image->comps[i].dx) {
296                         break;
297                 }
298                 if (image->comps[0].dy != image->comps[i].dy) {
299                         break;
300                 }
301                 if (image->comps[0].prec != image->comps[i].prec) {
302                         break;
303                 }
304                 if (image->comps[0].sgnd != image->comps[i].sgnd) {
305                         break;
306                 }
307                 planes[i] = image->comps[i].data;
308         }
309         if (i != nr_comp) {
310                 fprintf(stderr,"imagetopng: All components shall have the same subsampling, same bit depth, same sign.\n");
311                 fprintf(stderr,"\tAborting\n");
312                 return 1;
313         }
314         for (i = 0; i < nr_comp; ++i) {
315                 clip_component(&(image->comps[i]), image->comps[0].prec);
316         }
317         if(prec > 8 && prec < 16)
318         {
319                 for (i = 0; i < nr_comp; ++i) {
320                         scale_component(&(image->comps[i]), 16);
321                 }
322                 prec = 16;
323         }
324         else if(prec < 8 && nr_comp > 1)/* GRAY_ALPHA, RGB, RGB_ALPHA */
325         {
326                 for (i = 0; i < nr_comp; ++i) {
327                         scale_component(&(image->comps[i]), 8);
328                 }
329                 prec = 8;
330         } else if((prec > 1) && (prec < 8) && ((prec == 6) || ((prec & 1)==1))) { /* GRAY with non native precision */
331                 if ((prec == 5) || (prec == 6)) {
332                         prec = 8;
333                 } else {
334                         prec++;
335                 }
336                 for (i = 0; i < nr_comp; ++i) {
337                         scale_component(&(image->comps[i]), (OPJ_UINT32)prec);
338                 }
339         }
340         
341         if(prec != 1 && prec != 2 && prec != 4 && prec != 8 && prec != 16)
342         {
343                 fprintf(stderr,"imagetopng: can not create %s\n\twrong bit_depth %d\n", write_idf, prec);
344                 return fails;
345         }
346         
347         writer = fopen(write_idf, "wb");
348         
349         if(writer == NULL) return fails;
350         
351         /* Create and initialize the png_struct with the desired error handler
352          * functions.  If you want to use the default stderr and longjump method,
353          * you can supply NULL for the last three parameters.  We also check that
354          * the library version is compatible with the one used at compile time,
355          * in case we are using dynamically linked libraries.  REQUIRED.
356          */
357         png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
358                                                                                                                                 NULL, NULL, NULL);
359         /*png_voidp user_error_ptr, user_error_fn, user_warning_fn); */
360         
361         if(png == NULL) goto fin;
362         
363         /* Allocate/initialize the image information data.  REQUIRED
364          */
365         info = png_create_info_struct(png);
366         
367         if(info == NULL) goto fin;
368         
369         /* Set error handling.  REQUIRED if you are not supplying your own
370          * error handling functions in the png_create_write_struct() call.
371          */
372         if(setjmp(png_jmpbuf(png))) goto fin;
373         
374         /* I/O initialization functions is REQUIRED
375          */
376         png_init_io(png, writer);
377         
378         /* Set the image information here.  Width and height are up to 2^31,
379          * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
380          * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
381          * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
382          * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
383          * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
384          * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE.
385          * REQUIRED
386          *
387          * ERRORS:
388          *
389          * color_type == PNG_COLOR_TYPE_PALETTE && bit_depth > 8
390          * color_type == PNG_COLOR_TYPE_RGB && bit_depth < 8
391          * color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth < 8
392          * color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8
393          *
394          */
395         png_set_compression_level(png, Z_BEST_COMPRESSION);
396         
397         if(nr_comp >= 3) /* RGB(A) */
398         {
399                 color_type = PNG_COLOR_TYPE_RGB;
400                 sig_bit.red = sig_bit.green = sig_bit.blue = (png_byte)prec;
401         }
402         else /* GRAY(A) */
403         {
404                 color_type = PNG_COLOR_TYPE_GRAY;
405                 sig_bit.gray = (png_byte)prec;
406         }
407         if((nr_comp & 1) == 0) /* ALPHA */
408         {
409                 color_type |= PNG_COLOR_MASK_ALPHA;
410                 sig_bit.alpha = (png_byte)prec;
411         }
412         
413         png_set_IHDR(png, info, image->comps[0].w, image->comps[0].h, prec, color_type,
414                                                          PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,  PNG_FILTER_TYPE_BASE);
415         
416         png_set_sBIT(png, info, &sig_bit);
417         /* png_set_gamma(png, 2.2, 1./2.2); */
418         /* png_set_sRGB(png, info, PNG_sRGB_INTENT_PERCEPTUAL); */
419         png_write_info(png, info);
420         
421         /* setup conversion */
422         {
423                 OPJ_SIZE_T rowStride;
424                 png_size_t png_row_size;
425                 
426                 png_row_size = png_get_rowbytes(png, info);
427                 rowStride = ((OPJ_SIZE_T)image->comps[0].w * (OPJ_SIZE_T)nr_comp * (OPJ_SIZE_T)prec + 7U) / 8U;
428                 if (rowStride != (OPJ_SIZE_T)png_row_size) {
429                         fprintf(stderr, "Invalid PNG row size\n");
430                         goto fin;
431                 }
432                 row_buf = (png_bytep)malloc(png_row_size);
433                 if (row_buf == NULL) {
434                         fprintf(stderr, "Can't allocate memory for PNG row\n");
435                         goto fin;
436                 }
437                 buffer32s = (OPJ_INT32*)malloc((OPJ_SIZE_T)image->comps[0].w * (OPJ_SIZE_T)nr_comp * sizeof(OPJ_INT32));
438                 if (buffer32s == NULL) {
439                         fprintf(stderr, "Can't allocate memory for interleaved 32s row\n");
440                         goto fin;
441                 }
442         }
443         
444         /* convert */
445         {
446                 OPJ_SIZE_T width= image->comps[0].w;
447                 OPJ_UINT32 y;
448                 convert_32s_PXCX cvtPxToCx = convert_32s_PXCX_LUT[nr_comp];
449                 convert_32sXXx_C1R cvt32sToPack = NULL;
450                 OPJ_INT32 adjust = image->comps[0].sgnd ? 1 << (prec - 1) : 0;
451                 png_bytep row_buf_cpy = row_buf;
452                 OPJ_INT32* buffer32s_cpy = buffer32s;
453
454                 switch (prec) {
455                         case 1:
456                         case 2:
457                         case 4:
458                         case 8:
459                                 cvt32sToPack = convert_32sXXu_C1R_LUT[prec];
460                                 break;
461                         case 16:
462                                 cvt32sToPack = convert_32s16u_C1R;
463                                 break;
464                         default:
465                                 /* never here */
466                                 break;
467                 }
468         
469                 for(y = 0; y < image->comps[0].h; ++y)
470                 {
471                         cvtPxToCx(planes, buffer32s_cpy, width, adjust);
472                         cvt32sToPack(buffer32s_cpy, row_buf_cpy, width * (OPJ_SIZE_T)nr_comp);
473                         png_write_row(png, row_buf_cpy);
474                         planes[0] += width;
475                         planes[1] += width;
476                         planes[2] += width;
477                         planes[3] += width;
478                 }
479         }
480
481         png_write_end(png, info);
482         
483         fails = 0;
484         
485 fin:
486         if(png) {
487                 png_destroy_write_struct(&png, &info);
488         }
489         if(row_buf) {
490                 free(row_buf);
491         }
492         if(buffer32s) {
493                 free(buffer32s);
494         }
495         fclose(writer);
496         
497         if(fails) (void)remove(write_idf); /* ignore return value */
498         
499         return fails;
500 }/* imagetopng() */