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.
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.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
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.
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.
39 #include "opj_apps_config.h"
52 #define PNG_MAGIC "\x89PNG\x0d\x0a\x1a\x0a"
54 /* PNG allows bits per sample: 1, 2, 4, 8, 16 */
57 static void convert_16u32s_C1R(const OPJ_BYTE* pSrc, OPJ_INT32* pDst,
61 for (i = 0; i < length; i++) {
62 OPJ_INT32 val0 = *pSrc++;
63 OPJ_INT32 val1 = *pSrc++;
64 pDst[i] = val0 << 8 | val1;
68 static opj_image_t * pngtoimage_internal(opj_cparameters_t * params,
80 if (setjmp(png_jmpbuf(png))) {
85 opj_image_t *image = NULL;
86 opj_image_cmptparm_t cmptparm[4];
88 convert_XXx32s_C1R cvtXXTo32s = NULL;
89 convert_32s_CXPX cvtCxToPx = NULL;
92 int bit_depth, interlace_type, compression_type, filter_type;
94 png_uint_32 width, height = 0U;
96 OPJ_BYTE** rows = NULL;
97 OPJ_INT32* row32s = NULL;
99 png_init_io(png, reader);
100 png_set_sig_bytes(png, MAGIC_SIZE);
102 png_read_info(png, info);
104 if (png_get_IHDR(png, info, &width, &height,
105 &bit_depth, &color_type, &interlace_type,
106 &compression_type, &filter_type) == 0) {
112 * expand paletted images to RGB, expand grayscale images of
113 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
116 if (color_type == PNG_COLOR_TYPE_PALETTE) {
120 if (png_get_valid(png, info, PNG_INFO_tRNS)) {
123 /* We might want to expand background */
125 if(png_get_valid(png, info, PNG_INFO_bKGD)) {
127 png_get_bKGD(png, info, &bgnd);
128 png_set_background(png, bgnd, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
132 if (!png_get_gAMA(png, info, &gamma)) {
136 /* we're not displaying but converting, screen gamma == 1.0 */
137 png_set_gamma(png, 1.0, gamma);
139 png_read_update_info(png, info);
141 color_type = png_get_color_type(png, info);
143 switch (color_type) {
144 case PNG_COLOR_TYPE_GRAY:
147 case PNG_COLOR_TYPE_GRAY_ALPHA:
150 case PNG_COLOR_TYPE_RGB:
153 case PNG_COLOR_TYPE_RGB_ALPHA:
157 fprintf(stderr, "pngtoimage: colortype %d is not supported\n", color_type);
160 cvtCxToPx = convert_32s_CXPX_LUT[nr_comp];
161 bit_depth = png_get_bit_depth(png, info);
168 cvtXXTo32s = convert_XXu32s_C1R_LUT[bit_depth];
170 case 16: /* 16 bpp is specific to PNG */
171 cvtXXTo32s = convert_16u32s_C1R;
174 fprintf(stderr, "pngtoimage: bit depth %d is not supported\n", bit_depth);
178 rows = (OPJ_BYTE**)calloc(height + 1, sizeof(OPJ_BYTE*));
180 fprintf(stderr, "pngtoimage: memory out\n");
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");
191 png_read_image(png, rows);
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;
205 image = opj_image_create(nr_comp, &cmptparm[0],
206 (nr_comp > 2U) ? OPJ_CLRSPC_SRGB : OPJ_CLRSPC_GRAY);
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);
217 row32s = (OPJ_INT32 *)malloc((size_t)width * nr_comp * sizeof(OPJ_INT32));
218 if (row32s == NULL) {
223 /* Set alpha channel */
224 image->comps[nr_comp - 1U].alpha = 1U - (nr_comp & 1U);
226 for (i = 0; i < nr_comp; i++) {
227 planes[i] = image->comps[i].data;
230 for (i = 0; i < height; ++i) {
231 cvtXXTo32s(rows[i], row32s, (OPJ_SIZE_T)width * nr_comp);
232 cvtCxToPx(row32s, planes, width);
243 opj_image_t *pngtoimage(const char *read_idf, opj_cparameters_t * params)
245 png_structp png = NULL;
246 png_infop info = NULL;
248 png_uint_32 height = 0U;
250 OPJ_BYTE** rows = NULL;
251 OPJ_INT32* row32s = NULL;
253 opj_image_t *image = NULL;
255 if ((reader = fopen(read_idf, "rb")) == NULL) {
256 fprintf(stderr, "pngtoimage: can not open %s\n", read_idf);
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);
266 if ((png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
267 NULL, NULL, NULL)) == NULL) {
270 if ((info = png_create_info_struct(png)) == NULL) {
274 image = pngtoimage_internal(params, reader, png, info, &height, &rows, &row32s);
277 for (i = 0; i < height; ++i)
287 png_destroy_read_struct(&png, &info, NULL);
297 static void convert_32s16u_C1R(const OPJ_INT32* pSrc, OPJ_BYTE* pDst,
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;
307 int imagetopng(opj_image_t * image, const char *write_idf)
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;
316 OPJ_INT32 const* planes[4];
318 OPJ_INT32* volatile buffer32s = NULL;
320 volatile int fails = 1;
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) {
327 "imagetopng: planes[%d] == NULL.\n", 0);
328 fprintf(stderr, "\tAborting\n");
331 nr_comp = (int)image->numcomps;
336 for (i = 1; i < nr_comp; ++i) {
337 if (image->comps[0].dx != image->comps[i].dx) {
340 if (image->comps[0].dy != image->comps[i].dy) {
343 if (image->comps[0].prec != image->comps[i].prec) {
346 if (image->comps[0].sgnd != image->comps[i].sgnd) {
349 planes[i] = image->comps[i].data;
350 if (planes[i] == NULL) {
352 "imagetopng: planes[%d] == NULL.\n", i);
353 fprintf(stderr, "\tAborting\n");
359 "imagetopng: All components shall have the same subsampling, same bit depth, same sign.\n");
360 fprintf(stderr, "\tAborting\n");
363 for (i = 0; i < nr_comp; ++i) {
364 clip_component(&(image->comps[i]), image->comps[0].prec);
366 if (prec > 8 && prec < 16) {
367 for (i = 0; i < nr_comp; ++i) {
368 scale_component(&(image->comps[i]), 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);
376 } else if ((prec > 1) && (prec < 8) && ((prec == 6) ||
377 ((prec & 1) == 1))) { /* GRAY with non native precision */
378 if ((prec == 5) || (prec == 6)) {
383 for (i = 0; i < nr_comp; ++i) {
384 scale_component(&(image->comps[i]), (OPJ_UINT32)prec);
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",
394 writer = fopen(write_idf, "wb");
396 if (writer == NULL) {
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.
406 png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
408 /*png_voidp user_error_ptr, user_error_fn, user_warning_fn); */
414 /* Allocate/initialize the image information data. REQUIRED
416 info = png_create_info_struct(png);
422 /* Set error handling. REQUIRED if you are not supplying your own
423 * error handling functions in the png_create_write_struct() call.
425 if (setjmp(png_jmpbuf(png))) {
429 /* I/O initialization functions is REQUIRED
431 png_init_io(png, writer);
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.
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
450 png_set_compression_level(png, Z_BEST_COMPRESSION);
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;
459 if ((nr_comp & 1) == 0) { /* ALPHA */
460 color_type |= PNG_COLOR_MASK_ALPHA;
461 sig_bit.alpha = (png_byte)prec;
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);
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);
472 /* setup conversion */
474 OPJ_SIZE_T rowStride;
475 png_size_t png_row_size;
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");
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");
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");
499 OPJ_SIZE_T width = image->comps[0].w;
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;
512 cvt32sToPack = convert_32sXXu_C1R_LUT[prec];
515 cvt32sToPack = convert_32s16u_C1R;
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);
533 png_write_end(png, info);
539 png_destroy_write_struct(&png, &info);
550 (void)remove(write_idf); /* ignore return value */