191l_int32 i, j, k, index, ncolors, rval, gval, bval, valid;
192l_int32 wpl, d, spp, cindex, bitval, bival, quadval, tRNS;
193l_uint32 png_transforms;
194l_uint32 *data, *line, *ppixel;
195int num_palette, num_text, num_trans;
196png_byte bit_depth, color_type, channels;
197png_uint_32 w, h, rowbytes, xres, yres;
198png_bytep rowptr, trans;
199png_bytep *row_pointers;
201png_infop info_ptr, end_info;
208 return (
PIX *)ERROR_PTR(
"fp not defined", __func__, NULL);
212 if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
213 (png_voidp)NULL, NULL, NULL)) == NULL)
214 return (
PIX *)ERROR_PTR(
"png_ptr not made", __func__, NULL);
216 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
217 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
218 return (
PIX *)ERROR_PTR(
"info_ptr not made", __func__, NULL);
221 if ((end_info = png_create_info_struct(png_ptr)) == NULL) {
222 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
223 return (
PIX *)ERROR_PTR(
"end_info not made", __func__, NULL);
227 if (setjmp(png_jmpbuf(png_ptr))) {
228 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
229 return (
PIX *)ERROR_PTR(
"internal png error", __func__, NULL);
232 png_init_io(png_ptr, fp);
242 if (var_PNG_STRIP_16_TO_8 == 1) {
243 png_transforms = PNG_TRANSFORM_STRIP_16;
245 png_transforms = PNG_TRANSFORM_IDENTITY;
246 L_INFO(
"not stripping 16 --> 8 in png reading\n", __func__);
250 png_read_png(png_ptr, info_ptr, png_transforms, NULL);
252 row_pointers = png_get_rows(png_ptr, info_ptr);
253 w = png_get_image_width(png_ptr, info_ptr);
254 h = png_get_image_height(png_ptr, info_ptr);
255 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
256 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
257 color_type = png_get_color_type(png_ptr, info_ptr);
258 channels = png_get_channels(png_ptr, info_ptr);
260 tRNS = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? 1 : 0;
269 if (spp != 1 && bit_depth != 8) {
270 L_ERROR(
"spp = %d and bps = %d != 8\n"
271 "turn on 16 --> 8 stripping\n", __func__, spp, bit_depth);
272 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
273 return (
PIX *)ERROR_PTR(
"not implemented for this image",
278 if (color_type == PNG_COLOR_TYPE_PALETTE ||
279 color_type == PNG_COLOR_MASK_PALETTE) {
280 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
281 cmap = pixcmapCreate(d);
282 for (cindex = 0; cindex < num_palette; cindex++) {
283 rval = palette[cindex].red;
284 gval = palette[cindex].green;
285 bval = palette[cindex].blue;
286 pixcmapAddColor(cmap, rval, gval, bval);
290 if ((pix = pixCreate(w, h, d)) == NULL) {
291 pixcmapDestroy(&cmap);
292 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
293 return (
PIX *)ERROR_PTR(
"pix not made", __func__, NULL);
295 pixSetInputFormat(pix, IFF_PNG);
296 wpl = pixGetWpl(pix);
297 data = pixGetData(pix);
299 if (pixSetColormap(pix, cmap)) {
301 return (
PIX *)ERROR_PTR(
"invalid colormap", __func__, NULL);
304 if (spp == 1 && !tRNS) {
305 for (i = 0; i < h; i++) {
306 line = data + i * wpl;
307 rowptr = row_pointers[i];
308 for (j = 0; j < rowbytes; j++) {
312 }
else if (spp == 2) {
313 L_INFO(
"converting (gray + alpha) ==> RGBA\n", __func__);
314 for (i = 0; i < h; i++) {
315 ppixel = data + i * wpl;
316 rowptr = row_pointers[i];
317 for (j = k = 0; j < w; j++) {
327 }
else if (spp == 3 || spp == 4) {
328 for (i = 0; i < h; i++) {
329 ppixel = data + i * wpl;
330 rowptr = row_pointers[i];
331 for (j = k = 0; j < w; j++) {
351 if (spp == 1 && tRNS) {
354 L_INFO(
"transparency, 1 spp, no colormap, no transparency array: "
355 "convention is fully transparent image\n", __func__);
356 L_INFO(
"converting (fully transparent 1 spp) ==> RGBA\n", __func__);
358 pix = pixCreate(w, h, 32);
361 L_INFO(
"converting (cmap + alpha) ==> RGBA\n", __func__);
364 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
367 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
368 return (
PIX *)ERROR_PTR(
"cmap, tRNS, but no transparency array",
373 cmap = pixcmapCopy(pixGetColormap(pix));
374 ncolors = pixcmapGetCount(cmap);
378 pix = pixCreate(w, h, 32);
379 wpl = pixGetWpl(pix);
380 data = pixGetData(pix);
384 lept_stderr(
"ncolors = %d, num_trans = %d\n",
386 for (i = 0; i < ncolors; i++) {
387 pixcmapGetColor(cmap, i, &rval, &gval, &bval);
389 lept_stderr(
"(r,g,b,a) = (%d,%d,%d,%d)\n",
390 rval, gval, bval, trans[i]);
392 lept_stderr(
"(r,g,b,a) = (%d,%d,%d,<<255>>)\n",
401 L_INFO(
"converting 1 bpp cmap with alpha ==> RGBA\n", __func__);
403 L_INFO(
"num_trans = 1; second color opaque by default\n",
405 for (i = 0; i < h; i++) {
406 ppixel = data + i * wpl;
407 rowptr = row_pointers[i];
408 for (j = 0, index = 0; j < rowbytes; j++) {
410 for (k = 0; k < 8 && index < w; k++, index++) {
411 bitval = (
byte >> (7 - k)) & 1;
412 pixcmapGetColor(cmap, bitval, &rval, &gval, &bval);
413 composeRGBPixel(rval, gval, bval, ppixel);
415 bitval < num_trans ? trans[bitval] : 255);
422 L_INFO(
"converting 2 bpp cmap with alpha ==> RGBA\n", __func__);
423 for (i = 0; i < h; i++) {
424 ppixel = data + i * wpl;
425 rowptr = row_pointers[i];
426 for (j = 0, index = 0; j < rowbytes; j++) {
428 for (k = 0; k < 4 && index < w; k++, index++) {
429 bival = (
byte >> 2 * (3 - k)) & 3;
430 pixcmapGetColor(cmap, bival, &rval, &gval, &bval);
431 composeRGBPixel(rval, gval, bval, ppixel);
436 bival < num_trans ? trans[bival] : 255);
443 L_INFO(
"converting 4 bpp cmap with alpha ==> RGBA\n", __func__);
444 for (i = 0; i < h; i++) {
445 ppixel = data + i * wpl;
446 rowptr = row_pointers[i];
447 for (j = 0, index = 0; j < rowbytes; j++) {
449 for (k = 0; k < 2 && index < w; k++, index++) {
450 quadval = (
byte >> 4 * (1 - k)) & 0xf;
451 pixcmapGetColor(cmap, quadval, &rval, &gval, &bval);
452 composeRGBPixel(rval, gval, bval, ppixel);
455 quadval < num_trans ? trans[quadval] : 255);
462 L_INFO(
"converting 8 bpp cmap with alpha ==> RGBA\n", __func__);
463 for (i = 0; i < h; i++) {
464 ppixel = data + i * wpl;
465 rowptr = row_pointers[i];
466 for (j = 0; j < w; j++) {
468 pixcmapGetColor(cmap, index, &rval, &gval, &bval);
469 composeRGBPixel(rval, gval, bval, ppixel);
472 index < num_trans ? trans[index] : 255);
477 L_ERROR(
"spp == 1, cmap, trans array, invalid depth: %d\n",
480 pixcmapDestroy(&cmap);
486 for (i = 0; i < 16; i++) {
487 lept_stderr(
"[%d] = %d\n", i, ((l_uint8 *)(cmap->
array))[i]);
514 if (pixGetDepth(pix) == 1) {
518 L_INFO(
"removing opaque cmap from 1 bpp\n", __func__);
525 xres = png_get_x_pixels_per_meter(png_ptr, info_ptr);
526 yres = png_get_y_pixels_per_meter(png_ptr, info_ptr);
527 pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5));
528 pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5));
531 png_get_text(png_ptr, info_ptr, &text_ptr, &num_text);
532 if (num_text && text_ptr)
533 pixSetText(pix, text_ptr->
text);
535 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
538 if ((cmap = pixGetColormap(pix)) != NULL) {
539 pixcmapIsValid(cmap, pix, &valid);
542 return (
PIX *)ERROR_PTR(
"colormap is not valid", __func__, NULL);
546 pixSetPadBits(pix, 0);
1061char commentstring[] =
"Comment";
1062l_int32 i, j, k, wpl, d, spp, compval, valid;
1063l_int32 cmflag, opaque, max_trans, ncolors;
1064l_int32 *rmap, *gmap, *bmap, *amap;
1065l_uint32 *data, *ppixel;
1066png_byte bit_depth, color_type;
1069png_uint_32 xres, yres;
1070png_bytep *row_pointers;
1080 return ERROR_INT(
"stream not open", __func__, 1);
1082 return ERROR_INT(
"pix not defined", __func__, 1);
1084 w = pixGetWidth(pix);
1085 h = pixGetHeight(pix);
1086 d = pixGetDepth(pix);
1087 spp = pixGetSpp(pix);
1090 if ((cmap = pixGetColormap(pix))) {
1092 pixcmapIsValid(cmap, pix, &valid);
1094 return ERROR_INT(
"colormap is not valid", __func__, 1);
1098 pixSetPadBits(pix, 0);
1101 if (d == 32 && spp == 4) {
1103 color_type = PNG_COLOR_TYPE_RGBA;
1105 }
else if (d == 24 || d == 32) {
1107 color_type = PNG_COLOR_TYPE_RGB;
1111 color_type = PNG_COLOR_TYPE_GRAY;
1114 color_type = PNG_COLOR_TYPE_PALETTE;
1117 lept_stderr(
"cmflag = %d, bit_depth = %d, color_type = %d\n",
1118 cmflag, bit_depth, color_type);
1122 if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1123 (png_voidp)NULL, NULL, NULL)) == NULL)
1124 return ERROR_INT(
"png_ptr not made", __func__, 1);
1125 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
1126 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
1127 return ERROR_INT(
"info_ptr not made", __func__, 1);
1132 row_pointers = NULL;
1133 if (setjmp(png_jmpbuf(png_ptr))) {
1134 png_destroy_write_struct(&png_ptr, &info_ptr);
1135 LEPT_FREE(row_pointers);
1137 return ERROR_INT(
"internal png error", __func__, 1);
1140 png_init_io(png_ptr, fp);
1147 compval = Z_DEFAULT_COMPRESSION;
1150 png_set_compression_level(png_ptr, compval);
1152 png_set_IHDR(png_ptr, info_ptr, w, h, bit_depth, color_type,
1153 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
1154 PNG_FILTER_TYPE_BASE);
1157 xres = (png_uint_32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
1158 yres = (png_uint_32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
1159 if ((xres == 0) || (yres == 0))
1160 png_set_pHYs(png_ptr, info_ptr, 0, 0, PNG_RESOLUTION_UNKNOWN);
1162 png_set_pHYs(png_ptr, info_ptr, xres, yres, PNG_RESOLUTION_METER);
1166 ncolors = pixcmapGetCount(cmap);
1167 palette = (png_colorp)LEPT_CALLOC(ncolors,
sizeof(png_color));
1168 pixcmapToArrays(cmap, &rmap, &gmap, &bmap, &amap);
1169 for (i = 0; i < ncolors; i++) {
1170 palette[i].red = (png_byte)rmap[i];
1171 palette[i].green = (png_byte)gmap[i];
1172 palette[i].blue = (png_byte)bmap[i];
1173 alpha[i] = (png_byte)amap[i];
1179 png_set_PLTE(png_ptr, info_ptr, palette, (
int)ncolors);
1187 pixcmapIsOpaque(cmap, &opaque);
1189 pixcmapNonOpaqueColorsInfo(cmap, NULL, &max_trans, NULL);
1190 png_set_tRNS(png_ptr, info_ptr, (png_bytep)alpha,
1191 max_trans + 1, NULL);
1199 png_set_gAMA(png_ptr, info_ptr, (l_float64)gamma);
1201 if ((text = pixGetText(pix))) {
1202 png_text text_chunk;
1203 text_chunk.compression = PNG_TEXT_COMPRESSION_NONE;
1204 text_chunk.key = commentstring;
1205 text_chunk.text = text;
1206 text_chunk.text_length = strlen(text);
1207#ifdef PNG_ITXT_SUPPORTED
1208 text_chunk.itxt_length = 0;
1209 text_chunk.lang = NULL;
1210 text_chunk.lang_key = NULL;
1212 png_set_text(png_ptr, info_ptr, &text_chunk, 1);
1216 png_write_info(png_ptr, info_ptr);
1218 if ((d != 32) && (d != 24)) {
1225 if (d == 1 && !cmap) {
1226 pix1 = pixInvert(NULL, pix);
1227 pixEndianByteSwap(pix1);
1229 pix1 = pixEndianByteSwapNew(pix);
1232 png_destroy_write_struct(&png_ptr, &info_ptr);
1233 return ERROR_INT(
"pix1 not made", __func__, 1);
1237 row_pointers = (png_bytep *)LEPT_CALLOC(h,
sizeof(png_bytep));
1238 wpl = pixGetWpl(pix1);
1239 data = pixGetData(pix1);
1240 for (i = 0; i < h; i++)
1241 row_pointers[i] = (png_bytep)(data + i * wpl);
1242 png_set_rows(png_ptr, info_ptr, row_pointers);
1245 png_write_image(png_ptr, row_pointers);
1246 png_write_end(png_ptr, info_ptr);
1247 LEPT_FREE(row_pointers);
1249 png_destroy_write_struct(&png_ptr, &info_ptr);
1254 data = pixGetData(pix);
1255 wpl = pixGetWpl(pix);
1257 for (i = 0; i < h; i++) {
1258 ppixel = data + i * wpl;
1259 png_write_rows(png_ptr, (png_bytepp)&ppixel, 1);
1263 rowbuffer = (png_bytep)LEPT_CALLOC(w, 4);
1264 for (i = 0; i < h; i++) {
1265 ppixel = data + i * wpl;
1266 for (j = k = 0; j < w; j++) {
1275 png_write_rows(png_ptr, &rowbuffer, 1);
1277 LEPT_FREE(rowbuffer);
1280 png_write_end(png_ptr, info_ptr);
1281 png_destroy_write_struct(&png_ptr, &info_ptr);
1580l_int32 i, j, k, index, ncolors, rval, gval, bval, valid;
1581l_int32 wpl, d, spp, cindex, bitval, bival, quadval, tRNS;
1582l_uint32 png_transforms;
1583l_uint32 *data, *line, *ppixel;
1584int num_palette, num_text, num_trans;
1585png_byte bit_depth, color_type, channels;
1586png_uint_32 w, h, rowbytes, xres, yres;
1587png_bytep rowptr, trans;
1588png_bytep *row_pointers;
1590png_infop info_ptr, end_info;
1598 return (
PIX *)ERROR_PTR(
"filedata not defined", __func__, NULL);
1600 return (
PIX *)ERROR_PTR(
"invalid filesize", __func__, NULL);
1610 if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
1611 (png_voidp)NULL, NULL, NULL)) == NULL)
1612 return (
PIX *)ERROR_PTR(
"png_ptr not made", __func__, NULL);
1614 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
1615 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
1616 return (
PIX *)ERROR_PTR(
"info_ptr not made", __func__, NULL);
1619 if ((end_info = png_create_info_struct(png_ptr)) == NULL) {
1620 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
1621 return (
PIX *)ERROR_PTR(
"end_info not made", __func__, NULL);
1625 if (setjmp(png_jmpbuf(png_ptr))) {
1626 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1627 return (
PIX *)ERROR_PTR(
"internal png error", __func__, NULL);
1630 png_set_read_fn(png_ptr, &state, memio_png_read_data);
1639 if (var_PNG_STRIP_16_TO_8 == 1) {
1640 png_transforms = PNG_TRANSFORM_STRIP_16;
1642 png_transforms = PNG_TRANSFORM_IDENTITY;
1643 L_INFO(
"not stripping 16 --> 8 in png reading\n", __func__);
1647 png_read_png(png_ptr, info_ptr, png_transforms, NULL);
1649 row_pointers = png_get_rows(png_ptr, info_ptr);
1650 w = png_get_image_width(png_ptr, info_ptr);
1651 h = png_get_image_height(png_ptr, info_ptr);
1652 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
1653 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
1654 color_type = png_get_color_type(png_ptr, info_ptr);
1655 channels = png_get_channels(png_ptr, info_ptr);
1657 tRNS = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? 1 : 0;
1666 if (spp == 3 && bit_depth != 8) {
1667 lept_stderr(
"Help: spp = 3 and depth = %d != 8\n!!", bit_depth);
1668 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1669 return (
PIX *)ERROR_PTR(
"not implemented for this depth",
1674 if (color_type == PNG_COLOR_TYPE_PALETTE ||
1675 color_type == PNG_COLOR_MASK_PALETTE) {
1676 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
1677 cmap = pixcmapCreate(d);
1678 for (cindex = 0; cindex < num_palette; cindex++) {
1679 rval = palette[cindex].red;
1680 gval = palette[cindex].green;
1681 bval = palette[cindex].blue;
1682 pixcmapAddColor(cmap, rval, gval, bval);
1686 if ((pix = pixCreate(w, h, d)) == NULL) {
1687 pixcmapDestroy(&cmap);
1688 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1689 pixcmapDestroy(&cmap);
1690 return (
PIX *)ERROR_PTR(
"pix not made", __func__, NULL);
1692 pixSetInputFormat(pix, IFF_PNG);
1693 wpl = pixGetWpl(pix);
1694 data = pixGetData(pix);
1695 pixSetSpp(pix, spp);
1696 if (pixSetColormap(pix, cmap)) {
1698 return (
PIX *)ERROR_PTR(
"invalid colormap", __func__, NULL);
1701 if (spp == 1 && !tRNS) {
1702 for (i = 0; i < h; i++) {
1703 line = data + i * wpl;
1704 rowptr = row_pointers[i];
1705 for (j = 0; j < rowbytes; j++) {
1709 }
else if (spp == 2) {
1710 L_INFO(
"converting (gray + alpha) ==> RGBA\n", __func__);
1711 for (i = 0; i < h; i++) {
1712 ppixel = data + i * wpl;
1713 rowptr = row_pointers[i];
1714 for (j = k = 0; j < w; j++) {
1724 }
else if (spp == 3 || spp == 4) {
1725 for (i = 0; i < h; i++) {
1726 ppixel = data + i * wpl;
1727 rowptr = row_pointers[i];
1728 for (j = k = 0; j < w; j++) {
1746 if (spp == 1 && tRNS) {
1749 L_INFO(
"transparency, 1 spp, no colormap, no transparency array: "
1750 "convention is fully transparent image\n", __func__);
1751 L_INFO(
"converting (fully transparent 1 spp) ==> RGBA\n", __func__);
1753 pix = pixCreate(w, h, 32);
1756 L_INFO(
"converting (cmap + alpha) ==> RGBA\n", __func__);
1759 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
1762 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1763 return (
PIX *)ERROR_PTR(
"cmap, tRNS, but no transparency array",
1768 cmap = pixcmapCopy(pixGetColormap(pix));
1769 ncolors = pixcmapGetCount(cmap);
1773 pix = pixCreate(w, h, 32);
1774 wpl = pixGetWpl(pix);
1775 data = pixGetData(pix);
1779 lept_stderr(
"ncolors = %d, num_trans = %d\n",
1780 ncolors, num_trans);
1781 for (i = 0; i < ncolors; i++) {
1782 pixcmapGetColor(cmap, i, &rval, &gval, &bval);
1783 if (i < num_trans) {
1784 lept_stderr(
"(r,g,b,a) = (%d,%d,%d,%d)\n",
1785 rval, gval, bval, trans[i]);
1787 lept_stderr(
"(r,g,b,a) = (%d,%d,%d,<<255>>)\n",
1796 L_INFO(
"converting 1 bpp cmap with alpha ==> RGBA\n", __func__);
1798 L_INFO(
"num_trans = 1; second color opaque by default\n",
1800 for (i = 0; i < h; i++) {
1801 ppixel = data + i * wpl;
1802 rowptr = row_pointers[i];
1803 for (j = 0, index = 0; j < rowbytes; j++) {
1805 for (k = 0; k < 8 && index < w; k++, index++) {
1806 bitval = (
byte >> (7 - k)) & 1;
1807 pixcmapGetColor(cmap, bitval, &rval, &gval, &bval);
1808 composeRGBPixel(rval, gval, bval, ppixel);
1810 bitval < num_trans ? trans[bitval] : 255);
1815 }
else if (d == 2) {
1817 L_INFO(
"converting 2 bpp cmap with alpha ==> RGBA\n", __func__);
1818 for (i = 0; i < h; i++) {
1819 ppixel = data + i * wpl;
1820 rowptr = row_pointers[i];
1821 for (j = 0, index = 0; j < rowbytes; j++) {
1823 for (k = 0; k < 4 && index < w; k++, index++) {
1824 bival = (
byte >> 2 * (3 - k)) & 3;
1825 pixcmapGetColor(cmap, bival, &rval, &gval, &bval);
1826 composeRGBPixel(rval, gval, bval, ppixel);
1831 bival < num_trans ? trans[bival] : 255);
1836 }
else if (d == 4) {
1838 L_INFO(
"converting 4 bpp cmap with alpha ==> RGBA\n", __func__);
1839 for (i = 0; i < h; i++) {
1840 ppixel = data + i * wpl;
1841 rowptr = row_pointers[i];
1842 for (j = 0, index = 0; j < rowbytes; j++) {
1844 for (k = 0; k < 2 && index < w; k++, index++) {
1845 quadval = (
byte >> 4 * (1 - k)) & 0xf;
1846 pixcmapGetColor(cmap, quadval, &rval, &gval, &bval);
1847 composeRGBPixel(rval, gval, bval, ppixel);
1850 quadval < num_trans ? trans[quadval] : 255);
1855 }
else if (d == 8) {
1857 L_INFO(
"converting 8 bpp cmap with alpha ==> RGBA\n", __func__);
1858 for (i = 0; i < h; i++) {
1859 ppixel = data + i * wpl;
1860 rowptr = row_pointers[i];
1861 for (j = 0; j < w; j++) {
1863 pixcmapGetColor(cmap, index, &rval, &gval, &bval);
1864 composeRGBPixel(rval, gval, bval, ppixel);
1869 index < num_trans ? trans[index] : 255);
1874 L_ERROR(
"spp == 1, cmap, trans array, invalid depth: %d\n",
1877 pixcmapDestroy(&cmap);
1883 for (i = 0; i < 16; i++) {
1884 lept_stderr(
"[%d] = %d\n", i, ((l_uint8 *)(cmap->
array))[i]);
1911 if (pixGetDepth(pix) == 1) {
1913 pixInvert(pix, pix);
1921 xres = png_get_x_pixels_per_meter(png_ptr, info_ptr);
1922 yres = png_get_y_pixels_per_meter(png_ptr, info_ptr);
1923 pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5));
1924 pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5));
1927 png_get_text(png_ptr, info_ptr, &text_ptr, &num_text);
1928 if (num_text && text_ptr)
1929 pixSetText(pix, text_ptr->
text);
1931 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1934 if ((cmap = pixGetColormap(pix)) != NULL) {
1935 pixcmapIsValid(cmap, pix, &valid);
1938 return (
PIX *)ERROR_PTR(
"colormap is not valid", __func__, NULL);
1942 pixSetPadBits(pix, 0);
1970char commentstring[] =
"Comment";
1971l_int32 i, j, k, wpl, d, spp, cmflag, opaque, ncolors, compval, valid;
1972l_int32 *rmap, *gmap, *bmap, *amap;
1973l_uint32 *data, *ppixel;
1974png_byte bit_depth, color_type;
1976png_uint_32 w, h, xres, yres;
1986 if (pfiledata) *pfiledata = NULL;
1987 if (pfilesize) *pfilesize = 0;
1989 return ERROR_INT(
"&filedata not defined", __func__, 1);
1991 return ERROR_INT(
"&filesize not defined", __func__, 1);
1993 return ERROR_INT(
"pix not defined", __func__, 1);
2001 w = pixGetWidth(pix);
2002 h = pixGetHeight(pix);
2003 d = pixGetDepth(pix);
2004 spp = pixGetSpp(pix);
2007 if ((cmap = pixGetColormap(pix))) {
2009 pixcmapIsValid(cmap, pix, &valid);
2011 return ERROR_INT(
"colormap is not valid", __func__, 1);
2016 pixSetPadBits(pix, 0);
2019 if (d == 32 && spp == 4) {
2021 color_type = PNG_COLOR_TYPE_RGBA;
2023 }
else if (d == 24 || d == 32) {
2025 color_type = PNG_COLOR_TYPE_RGB;
2029 color_type = PNG_COLOR_TYPE_GRAY;
2032 color_type = PNG_COLOR_TYPE_PALETTE;
2035 lept_stderr(
"cmflag = %d, bit_depth = %d, color_type = %d\n",
2036 cmflag, bit_depth, color_type);
2040 if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
2041 (png_voidp)NULL, NULL, NULL)) == NULL)
2042 return ERROR_INT(
"png_ptr not made", __func__, 1);
2044 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
2045 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
2046 return ERROR_INT(
"info_ptr not made", __func__, 1);
2051 if (setjmp(png_jmpbuf(png_ptr))) {
2052 png_destroy_write_struct(&png_ptr, &info_ptr);
2054 return ERROR_INT(
"internal png error", __func__, 1);
2058 (png_flush_ptr)NULL);
2065 compval = Z_DEFAULT_COMPRESSION;
2068 png_set_compression_level(png_ptr, compval);
2070 png_set_IHDR(png_ptr, info_ptr, w, h, bit_depth, color_type,
2071 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
2072 PNG_FILTER_TYPE_BASE);
2075 xres = (png_uint_32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
2076 yres = (png_uint_32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
2077 if ((xres == 0) || (yres == 0))
2078 png_set_pHYs(png_ptr, info_ptr, 0, 0, PNG_RESOLUTION_UNKNOWN);
2080 png_set_pHYs(png_ptr, info_ptr, xres, yres, PNG_RESOLUTION_METER);
2084 ncolors = pixcmapGetCount(cmap);
2085 palette = (png_colorp)LEPT_CALLOC(ncolors,
sizeof(png_color));
2086 pixcmapToArrays(cmap, &rmap, &gmap, &bmap, &amap);
2087 for (i = 0; i < ncolors; i++) {
2088 palette[i].red = (png_byte)rmap[i];
2089 palette[i].green = (png_byte)gmap[i];
2090 palette[i].blue = (png_byte)bmap[i];
2091 alpha[i] = (png_byte)amap[i];
2097 png_set_PLTE(png_ptr, info_ptr, palette, (
int)ncolors);
2100 pixcmapIsOpaque(cmap, &opaque);
2102 png_set_tRNS(png_ptr, info_ptr, (png_bytep)alpha,
2103 (
int)ncolors, NULL);
2110 png_set_gAMA(png_ptr, info_ptr, (l_float64)gamma);
2112 if ((text = pixGetText(pix))) {
2113 png_text text_chunk;
2114 text_chunk.compression = PNG_TEXT_COMPRESSION_NONE;
2115 text_chunk.key = commentstring;
2116 text_chunk.text = text;
2117 text_chunk.text_length = strlen(text);
2118#ifdef PNG_ITXT_SUPPORTED
2119 text_chunk.itxt_length = 0;
2120 text_chunk.lang = NULL;
2121 text_chunk.lang_key = NULL;
2123 png_set_text(png_ptr, info_ptr, &text_chunk, 1);
2127 png_write_info(png_ptr, info_ptr);
2129 if ((d != 32) && (d != 24)) {
2136 if (d == 1 && !cmap) {
2137 pix1 = pixInvert(NULL, pix);
2138 pixEndianByteSwap(pix1);
2140 pix1 = pixEndianByteSwapNew(pix);
2143 png_destroy_write_struct(&png_ptr, &info_ptr);
2145 return ERROR_INT(
"pix1 not made", __func__, 1);
2149 wpl = pixGetWpl(pix1);
2150 data = pixGetData(pix1);
2151 for (i = 0; i < h; i++)
2152 png_write_row(png_ptr, (png_bytep)(data + i * wpl));
2153 png_write_end(png_ptr, info_ptr);
2156 png_destroy_write_struct(&png_ptr, &info_ptr);
2157 memio_png_flush(&state);
2158 *pfiledata = (l_uint8 *)state.
m_Buffer;
2166 data = pixGetData(pix);
2167 wpl = pixGetWpl(pix);
2169 for (i = 0; i < h; i++) {
2170 ppixel = data + i * wpl;
2171 png_write_rows(png_ptr, (png_bytepp)&ppixel, 1);
2175 rowbuffer = (png_bytep)LEPT_CALLOC(w, 4);
2176 for (i = 0; i < h; i++) {
2177 ppixel = data + i * wpl;
2178 for (j = k = 0; j < w; j++) {
2187 png_write_rows(png_ptr, &rowbuffer, 1);
2189 LEPT_FREE(rowbuffer);
2191 png_write_end(png_ptr, info_ptr);
2193 png_destroy_write_struct(&png_ptr, &info_ptr);
2194 memio_png_flush(&state);
2195 *pfiledata = (l_uint8 *)state.
m_Buffer;