/* PNG allows bits per sample: 1, 2, 4, 8, 16 */
-static void convert_16u32s_C1R(const OPJ_BYTE* pSrc, OPJ_INT32* pDst, OPJ_SIZE_T length)
+static void convert_16u32s_C1R(const OPJ_BYTE* pSrc, OPJ_INT32* pDst,
+ OPJ_SIZE_T length)
{
- OPJ_SIZE_T i;
- for (i = 0; i < length; i++) {
- OPJ_INT32 val0 = *pSrc++;
- OPJ_INT32 val1 = *pSrc++;
- pDst[i] = val0 << 8 | val1;
- }
+ OPJ_SIZE_T i;
+ for (i = 0; i < length; i++) {
+ OPJ_INT32 val0 = *pSrc++;
+ OPJ_INT32 val1 = *pSrc++;
+ pDst[i] = val0 << 8 | val1;
+ }
}
opj_image_t *pngtoimage(const char *read_idf, opj_cparameters_t * params)
{
- png_structp png = NULL;
- png_infop info = NULL;
- double gamma;
- int bit_depth, interlace_type,compression_type, filter_type;
- OPJ_UINT32 i;
- png_uint_32 width, height = 0U;
- int color_type;
- FILE *reader = NULL;
- OPJ_BYTE** rows = NULL;
- OPJ_INT32* row32s = NULL;
- /* j2k: */
- opj_image_t *image = NULL;
- opj_image_cmptparm_t cmptparm[4];
- OPJ_UINT32 nr_comp;
- OPJ_BYTE sigbuf[8];
- convert_XXx32s_C1R cvtXXTo32s = NULL;
- convert_32s_CXPX cvtCxToPx = NULL;
- OPJ_INT32* planes[4];
-
- if((reader = fopen(read_idf, "rb")) == NULL)
- {
- fprintf(stderr,"pngtoimage: can not open %s\n",read_idf);
- return NULL;
- }
-
- if(fread(sigbuf, 1, MAGIC_SIZE, reader) != MAGIC_SIZE
- || memcmp(sigbuf, PNG_MAGIC, MAGIC_SIZE) != 0)
- {
- fprintf(stderr,"pngtoimage: %s is no valid PNG file\n",read_idf);
- goto fin;
- }
-
- if((png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
- NULL, NULL, NULL)) == NULL)
- goto fin;
- if((info = png_create_info_struct(png)) == NULL)
- goto fin;
-
- if(setjmp(png_jmpbuf(png)))
- goto fin;
-
- png_init_io(png, reader);
- png_set_sig_bytes(png, MAGIC_SIZE);
-
- png_read_info(png, info);
-
- if(png_get_IHDR(png, info, &width, &height,
- &bit_depth, &color_type, &interlace_type,
- &compression_type, &filter_type) == 0)
- goto fin;
-
- /* png_set_expand():
- * expand paletted images to RGB, expand grayscale images of
- * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
- * to alpha channels.
- */
- if(color_type == PNG_COLOR_TYPE_PALETTE) {
- png_set_expand(png);
- }
-
- if(png_get_valid(png, info, PNG_INFO_tRNS)) {
- png_set_expand(png);
- }
- /* We might wan't to expand background */
- /*
- if(png_get_valid(png, info, PNG_INFO_bKGD)) {
- png_color_16p bgnd;
- png_get_bKGD(png, info, &bgnd);
- png_set_background(png, bgnd, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
- }
- */
-
- if( !png_get_gAMA(png, info, &gamma))
- gamma = 1.0;
-
- /* we're not displaying but converting, screen gamma == 1.0 */
- png_set_gamma(png, 1.0, gamma);
-
- png_read_update_info(png, info);
-
- color_type = png_get_color_type(png, info);
-
- switch (color_type) {
- case PNG_COLOR_TYPE_GRAY:
- nr_comp = 1;
- break;
- case PNG_COLOR_TYPE_GRAY_ALPHA:
- nr_comp = 2;
- break;
- case PNG_COLOR_TYPE_RGB:
- nr_comp = 3;
- break;
- case PNG_COLOR_TYPE_RGB_ALPHA:
- nr_comp = 4;
- break;
- default:
- fprintf(stderr,"pngtoimage: colortype %d is not supported\n", color_type);
- goto fin;
- }
- cvtCxToPx = convert_32s_CXPX_LUT[nr_comp];
- bit_depth = png_get_bit_depth(png, info);
-
- switch (bit_depth) {
- case 1:
- case 2:
- case 4:
- case 8:
- cvtXXTo32s = convert_XXu32s_C1R_LUT[bit_depth];
- break;
- case 16: /* 16 bpp is specific to PNG */
- cvtXXTo32s = convert_16u32s_C1R;
- break;
- default:
- fprintf(stderr,"pngtoimage: bit depth %d is not supported\n", bit_depth);
- goto fin;
- }
-
-
- rows = (OPJ_BYTE**)calloc(height+1, sizeof(OPJ_BYTE*));
- for(i = 0; i < height; ++i)
- rows[i] = (OPJ_BYTE*)malloc(png_get_rowbytes(png,info));
-
- png_read_image(png, rows);
-
- /* Create image */
- memset(cmptparm, 0, sizeof(cmptparm));
- for(i = 0; i < nr_comp; ++i)
- {
- cmptparm[i].prec = (OPJ_UINT32)bit_depth;
- /* bits_per_pixel: 8 or 16 */
- cmptparm[i].bpp = (OPJ_UINT32)bit_depth;
- cmptparm[i].sgnd = 0;
- cmptparm[i].dx = (OPJ_UINT32)params->subsampling_dx;
- cmptparm[i].dy = (OPJ_UINT32)params->subsampling_dy;
- cmptparm[i].w = (OPJ_UINT32)width;
- cmptparm[i].h = (OPJ_UINT32)height;
- }
-
- image = opj_image_create(nr_comp, &cmptparm[0], (nr_comp > 2U) ? OPJ_CLRSPC_SRGB : OPJ_CLRSPC_GRAY);
- if(image == NULL) goto fin;
- image->x0 = (OPJ_UINT32)params->image_offset_x0;
- image->y0 = (OPJ_UINT32)params->image_offset_y0;
- image->x1 = (OPJ_UINT32)(image->x0 + (width - 1) * (OPJ_UINT32)params->subsampling_dx + 1 + image->x0);
- image->y1 = (OPJ_UINT32)(image->y0 + (height - 1) * (OPJ_UINT32)params->subsampling_dy + 1 + image->y0);
-
- row32s = malloc((size_t)width * nr_comp * sizeof(OPJ_INT32));
- if(row32s == NULL) goto fin;
-
- /* Set alpha channel */
- image->comps[nr_comp-1U].alpha = 1U - (nr_comp & 1U);
-
- for(i = 0; i < nr_comp; i++)
- {
- planes[i] = image->comps[i].data;
- }
-
- for(i = 0; i < height; ++i)
- {
- cvtXXTo32s(rows[i], row32s, (OPJ_SIZE_T)width * nr_comp);
- cvtCxToPx(row32s, planes, width);
- planes[0] += width;
- planes[1] += width;
- planes[2] += width;
- planes[3] += width;
- }
+ png_structp png = NULL;
+ png_infop info = NULL;
+ double gamma;
+ int bit_depth, interlace_type, compression_type, filter_type;
+ OPJ_UINT32 i;
+ png_uint_32 width, height = 0U;
+ int color_type;
+ FILE *reader = NULL;
+ OPJ_BYTE** rows = NULL;
+ OPJ_INT32* row32s = NULL;
+ /* j2k: */
+ opj_image_t *image = NULL;
+ opj_image_cmptparm_t cmptparm[4];
+ OPJ_UINT32 nr_comp;
+ OPJ_BYTE sigbuf[8];
+ convert_XXx32s_C1R cvtXXTo32s = NULL;
+ convert_32s_CXPX cvtCxToPx = NULL;
+ OPJ_INT32* planes[4];
+
+ if ((reader = fopen(read_idf, "rb")) == NULL) {
+ fprintf(stderr, "pngtoimage: can not open %s\n", read_idf);
+ return NULL;
+ }
+
+ if (fread(sigbuf, 1, MAGIC_SIZE, reader) != MAGIC_SIZE
+ || memcmp(sigbuf, PNG_MAGIC, MAGIC_SIZE) != 0) {
+ fprintf(stderr, "pngtoimage: %s is no valid PNG file\n", read_idf);
+ goto fin;
+ }
+
+ if ((png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL)) == NULL) {
+ goto fin;
+ }
+ if ((info = png_create_info_struct(png)) == NULL) {
+ goto fin;
+ }
+
+ if (setjmp(png_jmpbuf(png))) {
+ goto fin;
+ }
+
+ png_init_io(png, reader);
+ png_set_sig_bytes(png, MAGIC_SIZE);
+
+ png_read_info(png, info);
+
+ if (png_get_IHDR(png, info, &width, &height,
+ &bit_depth, &color_type, &interlace_type,
+ &compression_type, &filter_type) == 0) {
+ goto fin;
+ }
+
+ /* png_set_expand():
+ * expand paletted images to RGB, expand grayscale images of
+ * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
+ * to alpha channels.
+ */
+ if (color_type == PNG_COLOR_TYPE_PALETTE) {
+ png_set_expand(png);
+ }
+
+ if (png_get_valid(png, info, PNG_INFO_tRNS)) {
+ png_set_expand(png);
+ }
+ /* We might wan't to expand background */
+ /*
+ if(png_get_valid(png, info, PNG_INFO_bKGD)) {
+ png_color_16p bgnd;
+ png_get_bKGD(png, info, &bgnd);
+ png_set_background(png, bgnd, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+ }
+ */
+
+ if (!png_get_gAMA(png, info, &gamma)) {
+ gamma = 1.0;
+ }
+
+ /* we're not displaying but converting, screen gamma == 1.0 */
+ png_set_gamma(png, 1.0, gamma);
+
+ png_read_update_info(png, info);
+
+ color_type = png_get_color_type(png, info);
+
+ switch (color_type) {
+ case PNG_COLOR_TYPE_GRAY:
+ nr_comp = 1;
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ nr_comp = 2;
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ nr_comp = 3;
+ break;
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ nr_comp = 4;
+ break;
+ default:
+ fprintf(stderr, "pngtoimage: colortype %d is not supported\n", color_type);
+ goto fin;
+ }
+ cvtCxToPx = convert_32s_CXPX_LUT[nr_comp];
+ bit_depth = png_get_bit_depth(png, info);
+
+ switch (bit_depth) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ cvtXXTo32s = convert_XXu32s_C1R_LUT[bit_depth];
+ break;
+ case 16: /* 16 bpp is specific to PNG */
+ cvtXXTo32s = convert_16u32s_C1R;
+ break;
+ default:
+ fprintf(stderr, "pngtoimage: bit depth %d is not supported\n", bit_depth);
+ goto fin;
+ }
+
+
+ rows = (OPJ_BYTE**)calloc(height + 1, sizeof(OPJ_BYTE*));
+ if (rows == NULL) {
+ fprintf(stderr, "pngtoimage: memory out\n");
+ goto fin;
+ }
+ for (i = 0; i < height; ++i) {
+ rows[i] = (OPJ_BYTE*)malloc(png_get_rowbytes(png, info));
+ if (rows[i] == NULL) {
+ fprintf(stderr, "pngtoimage: memory out\n");
+ goto fin;
+ }
+ }
+ png_read_image(png, rows);
+
+ /* Create image */
+ memset(cmptparm, 0, sizeof(cmptparm));
+ for (i = 0; i < nr_comp; ++i) {
+ cmptparm[i].prec = (OPJ_UINT32)bit_depth;
+ /* bits_per_pixel: 8 or 16 */
+ cmptparm[i].bpp = (OPJ_UINT32)bit_depth;
+ cmptparm[i].sgnd = 0;
+ cmptparm[i].dx = (OPJ_UINT32)params->subsampling_dx;
+ cmptparm[i].dy = (OPJ_UINT32)params->subsampling_dy;
+ cmptparm[i].w = (OPJ_UINT32)width;
+ cmptparm[i].h = (OPJ_UINT32)height;
+ }
+
+ image = opj_image_create(nr_comp, &cmptparm[0],
+ (nr_comp > 2U) ? OPJ_CLRSPC_SRGB : OPJ_CLRSPC_GRAY);
+ if (image == NULL) {
+ goto fin;
+ }
+ image->x0 = (OPJ_UINT32)params->image_offset_x0;
+ image->y0 = (OPJ_UINT32)params->image_offset_y0;
+ image->x1 = (OPJ_UINT32)(image->x0 + (width - 1) * (OPJ_UINT32)
+ params->subsampling_dx + 1 + image->x0);
+ image->y1 = (OPJ_UINT32)(image->y0 + (height - 1) * (OPJ_UINT32)
+ params->subsampling_dy + 1 + image->y0);
+
+ row32s = (OPJ_INT32 *)malloc((size_t)width * nr_comp * sizeof(OPJ_INT32));
+ if (row32s == NULL) {
+ goto fin;
+ }
+
+ /* Set alpha channel */
+ image->comps[nr_comp - 1U].alpha = 1U - (nr_comp & 1U);
+
+ for (i = 0; i < nr_comp; i++) {
+ planes[i] = image->comps[i].data;
+ }
+
+ for (i = 0; i < height; ++i) {
+ cvtXXTo32s(rows[i], row32s, (OPJ_SIZE_T)width * nr_comp);
+ cvtCxToPx(row32s, planes, width);
+ planes[0] += width;
+ planes[1] += width;
+ planes[2] += width;
+ planes[3] += width;
+ }
fin:
- if(rows)
- {
- for(i = 0; i < height; ++i)
- free(rows[i]);
- free(rows);
- }
- if (row32s) {
- free(row32s);
- }
- if(png)
- png_destroy_read_struct(&png, &info, NULL);
-
- fclose(reader);
-
- return image;
-
+ if (rows) {
+ for (i = 0; i < height; ++i)
+ if (rows[i]) {
+ free(rows[i]);
+ }
+ free(rows);
+ }
+ if (row32s) {
+ free(row32s);
+ }
+ if (png) {
+ png_destroy_read_struct(&png, &info, NULL);
+ }
+
+ fclose(reader);
+
+ return image;
+
}/* pngtoimage() */
-static void convert_32s16u_C1R(const OPJ_INT32* pSrc, OPJ_BYTE* pDst, OPJ_SIZE_T length)
+static void convert_32s16u_C1R(const OPJ_INT32* pSrc, OPJ_BYTE* pDst,
+ OPJ_SIZE_T length)
{
- OPJ_SIZE_T i;
- for (i = 0; i < length; i++) {
- OPJ_UINT32 val = (OPJ_UINT32)pSrc[i];
- *pDst++ = (OPJ_BYTE)(val >> 8);
- *pDst++ = (OPJ_BYTE)val;
- }
+ OPJ_SIZE_T i;
+ for (i = 0; i < length; i++) {
+ OPJ_UINT32 val = (OPJ_UINT32)pSrc[i];
+ *pDst++ = (OPJ_BYTE)(val >> 8);
+ *pDst++ = (OPJ_BYTE)val;
+ }
}
int imagetopng(opj_image_t * image, const char *write_idf)
{
- FILE * volatile writer = NULL;
- png_structp png = NULL;
- png_infop info = NULL;
- png_bytep volatile row_buf = NULL;
- int nr_comp, color_type;
- volatile int prec;
- png_color_8 sig_bit;
- OPJ_INT32 const* planes[4];
- int i;
- OPJ_INT32* volatile buffer32s = NULL;
-
- volatile int fails = 1;
-
- memset(&sig_bit, 0, sizeof(sig_bit));
- prec = (int)image->comps[0].prec;
- planes[0] = image->comps[0].data;
- nr_comp = (int)image->numcomps;
-
- if (nr_comp > 4) {
- nr_comp = 4;
- }
- for (i = 1; i < nr_comp; ++i) {
- if (image->comps[0].dx != image->comps[i].dx) {
- break;
- }
- if (image->comps[0].dy != image->comps[i].dy) {
- break;
- }
- if (image->comps[0].prec != image->comps[i].prec) {
- break;
- }
- if (image->comps[0].sgnd != image->comps[i].sgnd) {
- break;
- }
- planes[i] = image->comps[i].data;
- }
- if (i != nr_comp) {
- fprintf(stderr,"imagetopng: All components shall have the same subsampling, same bit depth, same sign.\n");
- fprintf(stderr,"\tAborting\n");
- return 1;
- }
- for (i = 0; i < nr_comp; ++i) {
- clip_component(&(image->comps[i]), image->comps[0].prec);
- }
- if(prec > 8 && prec < 16)
- {
- for (i = 0; i < nr_comp; ++i) {
- scale_component(&(image->comps[i]), 16);
- }
- prec = 16;
- }
- else if(prec < 8 && nr_comp > 1)/* GRAY_ALPHA, RGB, RGB_ALPHA */
- {
- for (i = 0; i < nr_comp; ++i) {
- scale_component(&(image->comps[i]), 8);
- }
- prec = 8;
- } else if((prec > 1) && (prec < 8) && ((prec == 6) || ((prec & 1)==1))) { /* GRAY with non native precision */
- if ((prec == 5) || (prec == 6)) {
- prec = 8;
- } else {
- prec++;
- }
- for (i = 0; i < nr_comp; ++i) {
- scale_component(&(image->comps[i]), (OPJ_UINT32)prec);
- }
- }
-
- if(prec != 1 && prec != 2 && prec != 4 && prec != 8 && prec != 16)
- {
- fprintf(stderr,"imagetopng: can not create %s\n\twrong bit_depth %d\n", write_idf, prec);
- return fails;
- }
-
- writer = fopen(write_idf, "wb");
-
- if(writer == NULL) return fails;
-
- /* Create and initialize the png_struct with the desired error handler
- * functions. If you want to use the default stderr and longjump method,
- * you can supply NULL for the last three parameters. We also check that
- * the library version is compatible with the one used at compile time,
- * in case we are using dynamically linked libraries. REQUIRED.
- */
- png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
- NULL, NULL, NULL);
- /*png_voidp user_error_ptr, user_error_fn, user_warning_fn); */
-
- if(png == NULL) goto fin;
-
- /* Allocate/initialize the image information data. REQUIRED
- */
- info = png_create_info_struct(png);
-
- if(info == NULL) goto fin;
-
- /* Set error handling. REQUIRED if you are not supplying your own
- * error handling functions in the png_create_write_struct() call.
- */
- if(setjmp(png_jmpbuf(png))) goto fin;
-
- /* I/O initialization functions is REQUIRED
- */
- png_init_io(png, writer);
-
- /* Set the image information here. Width and height are up to 2^31,
- * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
- * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
- * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
- * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
- * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
- * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE.
- * REQUIRED
- *
- * ERRORS:
- *
- * color_type == PNG_COLOR_TYPE_PALETTE && bit_depth > 8
- * color_type == PNG_COLOR_TYPE_RGB && bit_depth < 8
- * color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth < 8
- * color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8
- *
- */
- png_set_compression_level(png, Z_BEST_COMPRESSION);
-
- if(nr_comp >= 3) /* RGB(A) */
- {
- color_type = PNG_COLOR_TYPE_RGB;
- sig_bit.red = sig_bit.green = sig_bit.blue = (png_byte)prec;
- }
- else /* GRAY(A) */
- {
- color_type = PNG_COLOR_TYPE_GRAY;
- sig_bit.gray = (png_byte)prec;
- }
- if((nr_comp & 1) == 0) /* ALPHA */
- {
- color_type |= PNG_COLOR_MASK_ALPHA;
- sig_bit.alpha = (png_byte)prec;
- }
-
- png_set_IHDR(png, info, image->comps[0].w, image->comps[0].h, prec, color_type,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
- png_set_sBIT(png, info, &sig_bit);
- /* png_set_gamma(png, 2.2, 1./2.2); */
- /* png_set_sRGB(png, info, PNG_sRGB_INTENT_PERCEPTUAL); */
- png_write_info(png, info);
-
- /* setup conversion */
- {
- OPJ_SIZE_T rowStride;
- png_size_t png_row_size;
-
- png_row_size = png_get_rowbytes(png, info);
- rowStride = ((OPJ_SIZE_T)image->comps[0].w * (OPJ_SIZE_T)nr_comp * (OPJ_SIZE_T)prec + 7U) / 8U;
- if (rowStride != (OPJ_SIZE_T)png_row_size) {
- fprintf(stderr, "Invalid PNG row size\n");
- goto fin;
- }
- row_buf = (png_bytep)malloc(png_row_size);
- if (row_buf == NULL) {
- fprintf(stderr, "Can't allocate memory for PNG row\n");
- goto fin;
- }
- buffer32s = (OPJ_INT32*)malloc((OPJ_SIZE_T)image->comps[0].w * (OPJ_SIZE_T)nr_comp * sizeof(OPJ_INT32));
- if (buffer32s == NULL) {
- fprintf(stderr, "Can't allocate memory for interleaved 32s row\n");
- goto fin;
- }
- }
-
- /* convert */
- {
- OPJ_SIZE_T width= image->comps[0].w;
- OPJ_UINT32 y;
- convert_32s_PXCX cvtPxToCx = convert_32s_PXCX_LUT[nr_comp];
- convert_32sXXx_C1R cvt32sToPack = NULL;
- OPJ_INT32 adjust = image->comps[0].sgnd ? 1 << (prec - 1) : 0;
- png_bytep row_buf_cpy = row_buf;
- OPJ_INT32* buffer32s_cpy = buffer32s;
-
- switch (prec) {
- case 1:
- case 2:
- case 4:
- case 8:
- cvt32sToPack = convert_32sXXu_C1R_LUT[prec];
- break;
- case 16:
- cvt32sToPack = convert_32s16u_C1R;
- break;
- default:
- /* never here */
- break;
- }
-
- for(y = 0; y < image->comps[0].h; ++y)
- {
- cvtPxToCx(planes, buffer32s_cpy, width, adjust);
- cvt32sToPack(buffer32s_cpy, row_buf_cpy, width * (OPJ_SIZE_T)nr_comp);
- png_write_row(png, row_buf_cpy);
- planes[0] += width;
- planes[1] += width;
- planes[2] += width;
- planes[3] += width;
- }
- }
-
- png_write_end(png, info);
-
- fails = 0;
-
+ FILE * volatile writer = NULL;
+ png_structp png = NULL;
+ png_infop info = NULL;
+ png_bytep volatile row_buf = NULL;
+ int nr_comp, color_type;
+ volatile int prec;
+ png_color_8 sig_bit;
+ OPJ_INT32 const* planes[4];
+ int i;
+ OPJ_INT32* volatile buffer32s = NULL;
+
+ volatile int fails = 1;
+
+ memset(&sig_bit, 0, sizeof(sig_bit));
+ prec = (int)image->comps[0].prec;
+ planes[0] = image->comps[0].data;
+ nr_comp = (int)image->numcomps;
+
+ if (nr_comp > 4) {
+ nr_comp = 4;
+ }
+ for (i = 1; i < nr_comp; ++i) {
+ if (image->comps[0].dx != image->comps[i].dx) {
+ break;
+ }
+ if (image->comps[0].dy != image->comps[i].dy) {
+ break;
+ }
+ if (image->comps[0].prec != image->comps[i].prec) {
+ break;
+ }
+ if (image->comps[0].sgnd != image->comps[i].sgnd) {
+ break;
+ }
+ planes[i] = image->comps[i].data;
+ }
+ if (i != nr_comp) {
+ fprintf(stderr,
+ "imagetopng: All components shall have the same subsampling, same bit depth, same sign.\n");
+ fprintf(stderr, "\tAborting\n");
+ return 1;
+ }
+ for (i = 0; i < nr_comp; ++i) {
+ clip_component(&(image->comps[i]), image->comps[0].prec);
+ }
+ if (prec > 8 && prec < 16) {
+ for (i = 0; i < nr_comp; ++i) {
+ scale_component(&(image->comps[i]), 16);
+ }
+ prec = 16;
+ } else if (prec < 8 && nr_comp > 1) { /* GRAY_ALPHA, RGB, RGB_ALPHA */
+ for (i = 0; i < nr_comp; ++i) {
+ scale_component(&(image->comps[i]), 8);
+ }
+ prec = 8;
+ } else if ((prec > 1) && (prec < 8) && ((prec == 6) ||
+ ((prec & 1) == 1))) { /* GRAY with non native precision */
+ if ((prec == 5) || (prec == 6)) {
+ prec = 8;
+ } else {
+ prec++;
+ }
+ for (i = 0; i < nr_comp; ++i) {
+ scale_component(&(image->comps[i]), (OPJ_UINT32)prec);
+ }
+ }
+
+ if (prec != 1 && prec != 2 && prec != 4 && prec != 8 && prec != 16) {
+ fprintf(stderr, "imagetopng: can not create %s\n\twrong bit_depth %d\n",
+ write_idf, prec);
+ return fails;
+ }
+
+ writer = fopen(write_idf, "wb");
+
+ if (writer == NULL) {
+ return fails;
+ }
+
+ /* Create and initialize the png_struct with the desired error handler
+ * functions. If you want to use the default stderr and longjump method,
+ * you can supply NULL for the last three parameters. We also check that
+ * the library version is compatible with the one used at compile time,
+ * in case we are using dynamically linked libraries. REQUIRED.
+ */
+ png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL);
+ /*png_voidp user_error_ptr, user_error_fn, user_warning_fn); */
+
+ if (png == NULL) {
+ goto fin;
+ }
+
+ /* Allocate/initialize the image information data. REQUIRED
+ */
+ info = png_create_info_struct(png);
+
+ if (info == NULL) {
+ goto fin;
+ }
+
+ /* Set error handling. REQUIRED if you are not supplying your own
+ * error handling functions in the png_create_write_struct() call.
+ */
+ if (setjmp(png_jmpbuf(png))) {
+ goto fin;
+ }
+
+ /* I/O initialization functions is REQUIRED
+ */
+ png_init_io(png, writer);
+
+ /* Set the image information here. Width and height are up to 2^31,
+ * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
+ * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
+ * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
+ * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
+ * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
+ * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE.
+ * REQUIRED
+ *
+ * ERRORS:
+ *
+ * color_type == PNG_COLOR_TYPE_PALETTE && bit_depth > 8
+ * color_type == PNG_COLOR_TYPE_RGB && bit_depth < 8
+ * color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth < 8
+ * color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8
+ *
+ */
+ png_set_compression_level(png, Z_BEST_COMPRESSION);
+
+ if (nr_comp >= 3) { /* RGB(A) */
+ color_type = PNG_COLOR_TYPE_RGB;
+ sig_bit.red = sig_bit.green = sig_bit.blue = (png_byte)prec;
+ } else { /* GRAY(A) */
+ color_type = PNG_COLOR_TYPE_GRAY;
+ sig_bit.gray = (png_byte)prec;
+ }
+ if ((nr_comp & 1) == 0) { /* ALPHA */
+ color_type |= PNG_COLOR_MASK_ALPHA;
+ sig_bit.alpha = (png_byte)prec;
+ }
+
+ png_set_IHDR(png, info, image->comps[0].w, image->comps[0].h, prec, color_type,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ png_set_sBIT(png, info, &sig_bit);
+ /* png_set_gamma(png, 2.2, 1./2.2); */
+ /* png_set_sRGB(png, info, PNG_sRGB_INTENT_PERCEPTUAL); */
+ png_write_info(png, info);
+
+ /* setup conversion */
+ {
+ OPJ_SIZE_T rowStride;
+ png_size_t png_row_size;
+
+ png_row_size = png_get_rowbytes(png, info);
+ rowStride = ((OPJ_SIZE_T)image->comps[0].w * (OPJ_SIZE_T)nr_comp *
+ (OPJ_SIZE_T)prec + 7U) / 8U;
+ if (rowStride != (OPJ_SIZE_T)png_row_size) {
+ fprintf(stderr, "Invalid PNG row size\n");
+ goto fin;
+ }
+ row_buf = (png_bytep)malloc(png_row_size);
+ if (row_buf == NULL) {
+ fprintf(stderr, "Can't allocate memory for PNG row\n");
+ goto fin;
+ }
+ buffer32s = (OPJ_INT32*)malloc((OPJ_SIZE_T)image->comps[0].w *
+ (OPJ_SIZE_T)nr_comp * sizeof(OPJ_INT32));
+ if (buffer32s == NULL) {
+ fprintf(stderr, "Can't allocate memory for interleaved 32s row\n");
+ goto fin;
+ }
+ }
+
+ /* convert */
+ {
+ OPJ_SIZE_T width = image->comps[0].w;
+ OPJ_UINT32 y;
+ convert_32s_PXCX cvtPxToCx = convert_32s_PXCX_LUT[nr_comp];
+ convert_32sXXx_C1R cvt32sToPack = NULL;
+ OPJ_INT32 adjust = image->comps[0].sgnd ? 1 << (prec - 1) : 0;
+ png_bytep row_buf_cpy = row_buf;
+ OPJ_INT32* buffer32s_cpy = buffer32s;
+
+ switch (prec) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ cvt32sToPack = convert_32sXXu_C1R_LUT[prec];
+ break;
+ case 16:
+ cvt32sToPack = convert_32s16u_C1R;
+ break;
+ default:
+ /* never here */
+ break;
+ }
+
+ for (y = 0; y < image->comps[0].h; ++y) {
+ cvtPxToCx(planes, buffer32s_cpy, width, adjust);
+ cvt32sToPack(buffer32s_cpy, row_buf_cpy, width * (OPJ_SIZE_T)nr_comp);
+ png_write_row(png, row_buf_cpy);
+ planes[0] += width;
+ planes[1] += width;
+ planes[2] += width;
+ planes[3] += width;
+ }
+ }
+
+ png_write_end(png, info);
+
+ fails = 0;
+
fin:
- if(png) {
- png_destroy_write_struct(&png, &info);
- }
- if(row_buf) {
- free(row_buf);
- }
- if(buffer32s) {
- free(buffer32s);
- }
- fclose(writer);
-
- if(fails) (void)remove(write_idf); /* ignore return value */
-
- return fails;
+ if (png) {
+ png_destroy_write_struct(&png, &info);
+ }
+ if (row_buf) {
+ free(row_buf);
+ }
+ if (buffer32s) {
+ free(buffer32s);
+ }
+ fclose(writer);
+
+ if (fails) {
+ (void)remove(write_idf); /* ignore return value */
+ }
+
+ return fails;
}/* imagetopng() */