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);
1056char commentstring[] =
"Comment";
1057l_int32 i, j, k, wpl, d, spp, compval, valid;
1058l_int32 cmflag, opaque, max_trans, ncolors;
1059l_int32 *rmap, *gmap, *bmap, *amap;
1060l_uint32 *data, *ppixel;
1061png_byte bit_depth, color_type;
1064png_uint_32 xres, yres;
1065png_bytep *row_pointers;
1075 return ERROR_INT(
"stream not open", __func__, 1);
1077 return ERROR_INT(
"pix not defined", __func__, 1);
1079 w = pixGetWidth(pix);
1080 h = pixGetHeight(pix);
1081 d = pixGetDepth(pix);
1082 spp = pixGetSpp(pix);
1085 if ((cmap = pixGetColormap(pix))) {
1087 pixcmapIsValid(cmap, pix, &valid);
1089 return ERROR_INT(
"colormap is not valid", __func__, 1);
1095 if (d != 24) pixSetPadBits(pix, 0);
1098 if (d == 32 && spp == 4) {
1100 color_type = PNG_COLOR_TYPE_RGBA;
1102 }
else if (d == 24 || d == 32) {
1104 color_type = PNG_COLOR_TYPE_RGB;
1108 color_type = PNG_COLOR_TYPE_GRAY;
1111 color_type = PNG_COLOR_TYPE_PALETTE;
1114 lept_stderr(
"cmflag = %d, bit_depth = %d, color_type = %d\n",
1115 cmflag, bit_depth, color_type);
1119 if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1120 (png_voidp)NULL, NULL, NULL)) == NULL)
1121 return ERROR_INT(
"png_ptr not made", __func__, 1);
1122 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
1123 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
1124 return ERROR_INT(
"info_ptr not made", __func__, 1);
1129 row_pointers = NULL;
1130 if (setjmp(png_jmpbuf(png_ptr))) {
1131 png_destroy_write_struct(&png_ptr, &info_ptr);
1132 LEPT_FREE(row_pointers);
1134 return ERROR_INT(
"internal png error", __func__, 1);
1137 png_init_io(png_ptr, fp);
1144 compval = Z_DEFAULT_COMPRESSION;
1147 png_set_compression_level(png_ptr, compval);
1149 png_set_IHDR(png_ptr, info_ptr, w, h, bit_depth, color_type,
1150 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
1151 PNG_FILTER_TYPE_BASE);
1154 xres = (png_uint_32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
1155 yres = (png_uint_32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
1156 if ((xres == 0) || (yres == 0))
1157 png_set_pHYs(png_ptr, info_ptr, 0, 0, PNG_RESOLUTION_UNKNOWN);
1159 png_set_pHYs(png_ptr, info_ptr, xres, yres, PNG_RESOLUTION_METER);
1163 ncolors = pixcmapGetCount(cmap);
1164 palette = (png_colorp)LEPT_CALLOC(ncolors,
sizeof(png_color));
1165 pixcmapToArrays(cmap, &rmap, &gmap, &bmap, &amap);
1166 for (i = 0; i < ncolors; i++) {
1167 palette[i].red = (png_byte)rmap[i];
1168 palette[i].green = (png_byte)gmap[i];
1169 palette[i].blue = (png_byte)bmap[i];
1170 alpha[i] = (png_byte)amap[i];
1176 png_set_PLTE(png_ptr, info_ptr, palette, (
int)ncolors);
1184 pixcmapIsOpaque(cmap, &opaque);
1186 pixcmapNonOpaqueColorsInfo(cmap, NULL, &max_trans, NULL);
1187 png_set_tRNS(png_ptr, info_ptr, (png_bytep)alpha,
1188 max_trans + 1, NULL);
1196 png_set_gAMA(png_ptr, info_ptr, (l_float64)gamma);
1198 if ((text = pixGetText(pix))) {
1199 png_text text_chunk;
1200 text_chunk.compression = PNG_TEXT_COMPRESSION_NONE;
1201 text_chunk.key = commentstring;
1202 text_chunk.text = text;
1203 text_chunk.text_length = strlen(text);
1204#ifdef PNG_ITXT_SUPPORTED
1205 text_chunk.itxt_length = 0;
1206 text_chunk.lang = NULL;
1207 text_chunk.lang_key = NULL;
1209 png_set_text(png_ptr, info_ptr, &text_chunk, 1);
1213 png_write_info(png_ptr, info_ptr);
1215 if ((d != 32) && (d != 24)) {
1222 if (d == 1 && !cmap) {
1223 pix1 = pixInvert(NULL, pix);
1224 pixEndianByteSwap(pix1);
1226 pix1 = pixEndianByteSwapNew(pix);
1229 png_destroy_write_struct(&png_ptr, &info_ptr);
1230 return ERROR_INT(
"pix1 not made", __func__, 1);
1234 row_pointers = (png_bytep *)LEPT_CALLOC(h,
sizeof(png_bytep));
1235 wpl = pixGetWpl(pix1);
1236 data = pixGetData(pix1);
1237 for (i = 0; i < h; i++)
1238 row_pointers[i] = (png_bytep)(data + i * wpl);
1239 png_set_rows(png_ptr, info_ptr, row_pointers);
1242 png_write_image(png_ptr, row_pointers);
1243 png_write_end(png_ptr, info_ptr);
1244 LEPT_FREE(row_pointers);
1246 png_destroy_write_struct(&png_ptr, &info_ptr);
1251 data = pixGetData(pix);
1252 wpl = pixGetWpl(pix);
1254 for (i = 0; i < h; i++) {
1255 ppixel = data + i * wpl;
1256 png_write_rows(png_ptr, (png_bytepp)&ppixel, 1);
1259 rowbuffer = (png_bytep)LEPT_CALLOC(w, 4);
1260 for (i = 0; i < h; i++) {
1261 ppixel = data + i * wpl;
1262 for (j = k = 0; j < w; j++) {
1271 png_write_rows(png_ptr, &rowbuffer, 1);
1273 LEPT_FREE(rowbuffer);
1276 png_write_end(png_ptr, info_ptr);
1277 png_destroy_write_struct(&png_ptr, &info_ptr);
1576l_int32 i, j, k, index, ncolors, rval, gval, bval, valid;
1577l_int32 wpl, d, spp, cindex, bitval, bival, quadval, tRNS;
1578l_uint32 png_transforms;
1579l_uint32 *data, *line, *ppixel;
1580int num_palette, num_text, num_trans;
1581png_byte bit_depth, color_type, channels;
1582png_uint_32 w, h, rowbytes, xres, yres;
1583png_bytep rowptr, trans;
1584png_bytep *row_pointers;
1586png_infop info_ptr, end_info;
1594 return (
PIX *)ERROR_PTR(
"filedata not defined", __func__, NULL);
1596 return (
PIX *)ERROR_PTR(
"invalid filesize", __func__, NULL);
1606 if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
1607 (png_voidp)NULL, NULL, NULL)) == NULL)
1608 return (
PIX *)ERROR_PTR(
"png_ptr not made", __func__, NULL);
1610 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
1611 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
1612 return (
PIX *)ERROR_PTR(
"info_ptr not made", __func__, NULL);
1615 if ((end_info = png_create_info_struct(png_ptr)) == NULL) {
1616 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
1617 return (
PIX *)ERROR_PTR(
"end_info not made", __func__, NULL);
1621 if (setjmp(png_jmpbuf(png_ptr))) {
1622 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1623 return (
PIX *)ERROR_PTR(
"internal png error", __func__, NULL);
1626 png_set_read_fn(png_ptr, &state, memio_png_read_data);
1635 if (var_PNG_STRIP_16_TO_8 == 1) {
1636 png_transforms = PNG_TRANSFORM_STRIP_16;
1638 png_transforms = PNG_TRANSFORM_IDENTITY;
1639 L_INFO(
"not stripping 16 --> 8 in png reading\n", __func__);
1643 png_read_png(png_ptr, info_ptr, png_transforms, NULL);
1645 row_pointers = png_get_rows(png_ptr, info_ptr);
1646 w = png_get_image_width(png_ptr, info_ptr);
1647 h = png_get_image_height(png_ptr, info_ptr);
1648 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
1649 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
1650 color_type = png_get_color_type(png_ptr, info_ptr);
1651 channels = png_get_channels(png_ptr, info_ptr);
1653 tRNS = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? 1 : 0;
1662 if (spp == 3 && bit_depth != 8) {
1663 lept_stderr(
"Help: spp = 3 and depth = %d != 8\n!!", bit_depth);
1664 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1665 return (
PIX *)ERROR_PTR(
"not implemented for this depth",
1670 if (color_type == PNG_COLOR_TYPE_PALETTE ||
1671 color_type == PNG_COLOR_MASK_PALETTE) {
1672 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
1673 cmap = pixcmapCreate(d);
1674 for (cindex = 0; cindex < num_palette; cindex++) {
1675 rval = palette[cindex].red;
1676 gval = palette[cindex].green;
1677 bval = palette[cindex].blue;
1678 pixcmapAddColor(cmap, rval, gval, bval);
1682 if ((pix = pixCreate(w, h, d)) == NULL) {
1683 pixcmapDestroy(&cmap);
1684 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1685 pixcmapDestroy(&cmap);
1686 return (
PIX *)ERROR_PTR(
"pix not made", __func__, NULL);
1688 pixSetInputFormat(pix, IFF_PNG);
1689 wpl = pixGetWpl(pix);
1690 data = pixGetData(pix);
1691 pixSetSpp(pix, spp);
1692 if (pixSetColormap(pix, cmap)) {
1694 return (
PIX *)ERROR_PTR(
"invalid colormap", __func__, NULL);
1697 if (spp == 1 && !tRNS) {
1698 for (i = 0; i < h; i++) {
1699 line = data + i * wpl;
1700 rowptr = row_pointers[i];
1701 for (j = 0; j < rowbytes; j++) {
1705 }
else if (spp == 2) {
1706 L_INFO(
"converting (gray + alpha) ==> RGBA\n", __func__);
1707 for (i = 0; i < h; i++) {
1708 ppixel = data + i * wpl;
1709 rowptr = row_pointers[i];
1710 for (j = k = 0; j < w; j++) {
1720 }
else if (spp == 3 || spp == 4) {
1721 for (i = 0; i < h; i++) {
1722 ppixel = data + i * wpl;
1723 rowptr = row_pointers[i];
1724 for (j = k = 0; j < w; j++) {
1742 if (spp == 1 && tRNS) {
1745 L_INFO(
"transparency, 1 spp, no colormap, no transparency array: "
1746 "convention is fully transparent image\n", __func__);
1747 L_INFO(
"converting (fully transparent 1 spp) ==> RGBA\n", __func__);
1749 pix = pixCreate(w, h, 32);
1752 L_INFO(
"converting (cmap + alpha) ==> RGBA\n", __func__);
1755 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
1758 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1759 return (
PIX *)ERROR_PTR(
"cmap, tRNS, but no transparency array",
1764 cmap = pixcmapCopy(pixGetColormap(pix));
1765 ncolors = pixcmapGetCount(cmap);
1769 pix = pixCreate(w, h, 32);
1770 wpl = pixGetWpl(pix);
1771 data = pixGetData(pix);
1775 lept_stderr(
"ncolors = %d, num_trans = %d\n",
1776 ncolors, num_trans);
1777 for (i = 0; i < ncolors; i++) {
1778 pixcmapGetColor(cmap, i, &rval, &gval, &bval);
1779 if (i < num_trans) {
1780 lept_stderr(
"(r,g,b,a) = (%d,%d,%d,%d)\n",
1781 rval, gval, bval, trans[i]);
1783 lept_stderr(
"(r,g,b,a) = (%d,%d,%d,<<255>>)\n",
1792 L_INFO(
"converting 1 bpp cmap with alpha ==> RGBA\n", __func__);
1794 L_INFO(
"num_trans = 1; second color opaque by default\n",
1796 for (i = 0; i < h; i++) {
1797 ppixel = data + i * wpl;
1798 rowptr = row_pointers[i];
1799 for (j = 0, index = 0; j < rowbytes; j++) {
1801 for (k = 0; k < 8 && index < w; k++, index++) {
1802 bitval = (
byte >> (7 - k)) & 1;
1803 pixcmapGetColor(cmap, bitval, &rval, &gval, &bval);
1804 composeRGBPixel(rval, gval, bval, ppixel);
1806 bitval < num_trans ? trans[bitval] : 255);
1811 }
else if (d == 2) {
1813 L_INFO(
"converting 2 bpp cmap with alpha ==> RGBA\n", __func__);
1814 for (i = 0; i < h; i++) {
1815 ppixel = data + i * wpl;
1816 rowptr = row_pointers[i];
1817 for (j = 0, index = 0; j < rowbytes; j++) {
1819 for (k = 0; k < 4 && index < w; k++, index++) {
1820 bival = (
byte >> 2 * (3 - k)) & 3;
1821 pixcmapGetColor(cmap, bival, &rval, &gval, &bval);
1822 composeRGBPixel(rval, gval, bval, ppixel);
1827 bival < num_trans ? trans[bival] : 255);
1832 }
else if (d == 4) {
1834 L_INFO(
"converting 4 bpp cmap with alpha ==> RGBA\n", __func__);
1835 for (i = 0; i < h; i++) {
1836 ppixel = data + i * wpl;
1837 rowptr = row_pointers[i];
1838 for (j = 0, index = 0; j < rowbytes; j++) {
1840 for (k = 0; k < 2 && index < w; k++, index++) {
1841 quadval = (
byte >> 4 * (1 - k)) & 0xf;
1842 pixcmapGetColor(cmap, quadval, &rval, &gval, &bval);
1843 composeRGBPixel(rval, gval, bval, ppixel);
1846 quadval < num_trans ? trans[quadval] : 255);
1851 }
else if (d == 8) {
1853 L_INFO(
"converting 8 bpp cmap with alpha ==> RGBA\n", __func__);
1854 for (i = 0; i < h; i++) {
1855 ppixel = data + i * wpl;
1856 rowptr = row_pointers[i];
1857 for (j = 0; j < w; j++) {
1859 pixcmapGetColor(cmap, index, &rval, &gval, &bval);
1860 composeRGBPixel(rval, gval, bval, ppixel);
1865 index < num_trans ? trans[index] : 255);
1870 L_ERROR(
"spp == 1, cmap, trans array, invalid depth: %d\n",
1873 pixcmapDestroy(&cmap);
1879 for (i = 0; i < 16; i++) {
1880 lept_stderr(
"[%d] = %d\n", i, ((l_uint8 *)(cmap->
array))[i]);
1907 if (pixGetDepth(pix) == 1) {
1909 pixInvert(pix, pix);
1917 xres = png_get_x_pixels_per_meter(png_ptr, info_ptr);
1918 yres = png_get_y_pixels_per_meter(png_ptr, info_ptr);
1919 pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5));
1920 pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5));
1923 png_get_text(png_ptr, info_ptr, &text_ptr, &num_text);
1924 if (num_text && text_ptr)
1925 pixSetText(pix, text_ptr->
text);
1927 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1930 if ((cmap = pixGetColormap(pix)) != NULL) {
1931 pixcmapIsValid(cmap, pix, &valid);
1934 return (
PIX *)ERROR_PTR(
"colormap is not valid", __func__, NULL);
1938 pixSetPadBits(pix, 0);
1966char commentstring[] =
"Comment";
1967l_int32 i, j, k, wpl, d, spp, cmflag, opaque, ncolors, compval, valid;
1968l_int32 *rmap, *gmap, *bmap, *amap;
1969l_uint32 *data, *ppixel;
1970png_byte bit_depth, color_type;
1972png_uint_32 w, h, xres, yres;
1982 if (pfiledata) *pfiledata = NULL;
1983 if (pfilesize) *pfilesize = 0;
1985 return ERROR_INT(
"&filedata not defined", __func__, 1);
1987 return ERROR_INT(
"&filesize not defined", __func__, 1);
1989 return ERROR_INT(
"pix not defined", __func__, 1);
1997 w = pixGetWidth(pix);
1998 h = pixGetHeight(pix);
1999 d = pixGetDepth(pix);
2000 spp = pixGetSpp(pix);
2003 if ((cmap = pixGetColormap(pix))) {
2005 pixcmapIsValid(cmap, pix, &valid);
2007 return ERROR_INT(
"colormap is not valid", __func__, 1);
2013 if (d != 24) pixSetPadBits(pix, 0);
2016 if (d == 32 && spp == 4) {
2018 color_type = PNG_COLOR_TYPE_RGBA;
2020 }
else if (d == 24 || d == 32) {
2022 color_type = PNG_COLOR_TYPE_RGB;
2026 color_type = PNG_COLOR_TYPE_GRAY;
2029 color_type = PNG_COLOR_TYPE_PALETTE;
2032 lept_stderr(
"cmflag = %d, bit_depth = %d, color_type = %d\n",
2033 cmflag, bit_depth, color_type);
2037 if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
2038 (png_voidp)NULL, NULL, NULL)) == NULL)
2039 return ERROR_INT(
"png_ptr not made", __func__, 1);
2041 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
2042 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
2043 return ERROR_INT(
"info_ptr not made", __func__, 1);
2048 if (setjmp(png_jmpbuf(png_ptr))) {
2049 png_destroy_write_struct(&png_ptr, &info_ptr);
2051 return ERROR_INT(
"internal png error", __func__, 1);
2055 (png_flush_ptr)NULL);
2062 compval = Z_DEFAULT_COMPRESSION;
2065 png_set_compression_level(png_ptr, compval);
2067 png_set_IHDR(png_ptr, info_ptr, w, h, bit_depth, color_type,
2068 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
2069 PNG_FILTER_TYPE_BASE);
2072 xres = (png_uint_32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
2073 yres = (png_uint_32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
2074 if ((xres == 0) || (yres == 0))
2075 png_set_pHYs(png_ptr, info_ptr, 0, 0, PNG_RESOLUTION_UNKNOWN);
2077 png_set_pHYs(png_ptr, info_ptr, xres, yres, PNG_RESOLUTION_METER);
2081 ncolors = pixcmapGetCount(cmap);
2082 palette = (png_colorp)LEPT_CALLOC(ncolors,
sizeof(png_color));
2083 pixcmapToArrays(cmap, &rmap, &gmap, &bmap, &amap);
2084 for (i = 0; i < ncolors; i++) {
2085 palette[i].red = (png_byte)rmap[i];
2086 palette[i].green = (png_byte)gmap[i];
2087 palette[i].blue = (png_byte)bmap[i];
2088 alpha[i] = (png_byte)amap[i];
2094 png_set_PLTE(png_ptr, info_ptr, palette, (
int)ncolors);
2097 pixcmapIsOpaque(cmap, &opaque);
2099 png_set_tRNS(png_ptr, info_ptr, (png_bytep)alpha,
2100 (
int)ncolors, NULL);
2107 png_set_gAMA(png_ptr, info_ptr, (l_float64)gamma);
2109 if ((text = pixGetText(pix))) {
2110 png_text text_chunk;
2111 text_chunk.compression = PNG_TEXT_COMPRESSION_NONE;
2112 text_chunk.key = commentstring;
2113 text_chunk.text = text;
2114 text_chunk.text_length = strlen(text);
2115#ifdef PNG_ITXT_SUPPORTED
2116 text_chunk.itxt_length = 0;
2117 text_chunk.lang = NULL;
2118 text_chunk.lang_key = NULL;
2120 png_set_text(png_ptr, info_ptr, &text_chunk, 1);
2124 png_write_info(png_ptr, info_ptr);
2126 if ((d != 32) && (d != 24)) {
2133 if (d == 1 && !cmap) {
2134 pix1 = pixInvert(NULL, pix);
2135 pixEndianByteSwap(pix1);
2137 pix1 = pixEndianByteSwapNew(pix);
2140 png_destroy_write_struct(&png_ptr, &info_ptr);
2142 return ERROR_INT(
"pix1 not made", __func__, 1);
2146 wpl = pixGetWpl(pix1);
2147 data = pixGetData(pix1);
2148 for (i = 0; i < h; i++)
2149 png_write_row(png_ptr, (png_bytep)(data + i * wpl));
2150 png_write_end(png_ptr, info_ptr);
2153 png_destroy_write_struct(&png_ptr, &info_ptr);
2154 memio_png_flush(&state);
2155 *pfiledata = (l_uint8 *)state.
m_Buffer;
2163 data = pixGetData(pix);
2164 wpl = pixGetWpl(pix);
2166 for (i = 0; i < h; i++) {
2167 ppixel = data + i * wpl;
2168 png_write_rows(png_ptr, (png_bytepp)&ppixel, 1);
2171 rowbuffer = (png_bytep)LEPT_CALLOC(w, 4);
2172 for (i = 0; i < h; i++) {
2173 ppixel = data + i * wpl;
2174 for (j = k = 0; j < w; j++) {
2183 png_write_rows(png_ptr, &rowbuffer, 1);
2185 LEPT_FREE(rowbuffer);
2187 png_write_end(png_ptr, info_ptr);
2189 png_destroy_write_struct(&png_ptr, &info_ptr);
2190 memio_png_flush(&state);
2191 *pfiledata = (l_uint8 *)state.
m_Buffer;