121 #include <config_auto.h>
125 #include "allheaders.h"
137 #define Z_DEFAULT_COMPRESSION (-1)
143 static l_int32 var_PNG_STRIP_16_TO_8 = 1;
145 #ifndef NO_CONSOLE_IO
147 #define DEBUG_WRITE 0
191 l_int32 i, j, k, index, ncolors, rval, gval, bval, valid;
192 l_int32 wpl, d, spp, cindex, bitval, bival, quadval, tRNS;
193 l_uint32 png_transforms;
194 l_uint32 *data, *line, *ppixel;
195 int num_palette, num_text, num_trans;
196 png_byte bit_depth, color_type, channels;
197 png_uint_32 w, h, rowbytes, xres, yres;
198 png_bytep rowptr, trans;
199 png_bytep *row_pointers;
201 png_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);
282 for (cindex = 0; cindex < num_palette; cindex++) {
283 rval = palette[cindex].red;
284 gval = palette[cindex].green;
285 bval = palette[cindex].blue;
290 if ((pix =
pixCreate(w, h, d)) == NULL) {
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);
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__);
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",
379 wpl = pixGetWpl(pix);
386 for (i = 0; i < ncolors; i++) {
390 rval, gval, bval, trans[i]);
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;
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;
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;
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++) {
472 index < num_trans ? trans[index] : 255);
477 L_ERROR(
"spp == 1, cmap, trans array, invalid depth: %d\n",
486 for (i = 0; i < 16; 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)
535 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
538 if ((cmap = pixGetColormap(pix)) != NULL) {
542 return (
PIX *)ERROR_PTR(
"colormap is not valid", __func__, NULL);
588 if (piscmap) *piscmap = 0;
590 return ERROR_INT(
"filename not defined", __func__, 1);
592 return ERROR_INT(
"image file not found", __func__, 1);
630 if (piscmap) *piscmap = 0;
632 return ERROR_INT(
"stream not defined", __func__, 1);
636 return ERROR_INT(
"file too small to be png", __func__, 1);
637 if (fread(data, 1, 40, fp) != 40)
638 return ERROR_INT(
"error reading data", __func__, 1);
681 l_int32 colortype, w, h, bps, spp;
688 if (piscmap) *piscmap = 0;
690 return ERROR_INT(
"data not defined", __func__, 1);
692 return ERROR_INT(
"size < 40", __func__, 1);
695 if (data[0] != 137 || data[1] != 80 || data[2] != 78 ||
696 data[3] != 71 || data[4] != 13 || data[5] != 10 ||
697 data[6] != 26 || data[7] != 10)
698 return ERROR_INT(
"not a valid png file", __func__, 1);
700 pword = (l_uint32 *)data;
701 pshort = (l_uint16 *)data;
702 w = convertOnLittleEnd32(pword[4]);
703 h = convertOnLittleEnd32(pword[5]);
705 return ERROR_INT(
"invalid w or h", __func__, 1);
706 twobytes = convertOnLittleEnd16(pshort[12]);
708 colortype = twobytes & 0xff;
716 L_INFO(
"gray + alpha: will extract as RGBA (spp = 4)\n", __func__);
718 if (colortype == 2) {
720 }
else if (colortype == 6) {
722 }
else if (colortype == 4) {
728 if (bps < 1 || bps > 16) {
729 L_ERROR(
"invalid bps = %d\n", __func__, bps);
734 if (pbps) *pbps = bps;
735 if (pspp) *pspp = spp;
763 fgetPngResolution(FILE *fp,
767 png_uint_32 xres, yres;
771 if (pxres) *pxres = 0;
772 if (pyres) *pyres = 0;
774 return ERROR_INT(
"stream not opened", __func__, 1);
775 if (!pxres || !pyres)
776 return ERROR_INT(
"&xres and &yres not both defined", __func__, 1);
779 if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
780 (png_voidp)NULL, NULL, NULL)) == NULL)
781 return ERROR_INT(
"png_ptr not made", __func__, 1);
782 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
783 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
784 return ERROR_INT(
"info_ptr not made", __func__, 1);
789 if (setjmp(png_jmpbuf(png_ptr))) {
790 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
791 return ERROR_INT(
"internal png error", __func__, 1);
796 png_init_io(png_ptr, fp);
797 png_read_info(png_ptr, info_ptr);
799 xres = png_get_x_pixels_per_meter(png_ptr, info_ptr);
800 yres = png_get_y_pixels_per_meter(png_ptr, info_ptr);
801 *pxres = (l_int32)((l_float32)xres / 39.37 + 0.5);
802 *pyres = (l_int32)((l_float32)yres / 39.37 + 0.5);
804 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
819 l_int32 *pinterlaced)
825 return ERROR_INT(
"&interlaced not defined", __func__, 1);
828 return ERROR_INT(
"filename not defined", __func__, 1);
831 return ERROR_INT(
"stream not opened", __func__, 1);
832 if (fread(buf, 1, 32, fp) != 32) {
834 return ERROR_INT(
"data not read", __func__, 1);
838 *pinterlaced = (buf[28] == 0) ? 0 : 1;
860 fgetPngColormapInfo(FILE *fp,
862 l_int32 *ptransparency)
864 l_int32 i, cindex, rval, gval, bval, num_palette, num_trans;
865 png_byte bit_depth, color_type;
871 if (pcmap) *pcmap = NULL;
872 if (ptransparency) *ptransparency = 0;
873 if (!pcmap && !ptransparency)
874 return ERROR_INT(
"no output defined", __func__, 1);
876 return ERROR_INT(
"stream not opened", __func__, 1);
879 if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
880 (png_voidp)NULL, NULL, NULL)) == NULL)
881 return ERROR_INT(
"png_ptr not made", __func__, 1);
882 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
883 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
884 return ERROR_INT(
"info_ptr not made", __func__, 1);
889 if (setjmp(png_jmpbuf(png_ptr))) {
890 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
892 return ERROR_INT(
"internal png error", __func__, 1);
897 png_init_io(png_ptr, fp);
898 png_read_info(png_ptr, info_ptr);
899 color_type = png_get_color_type(png_ptr, info_ptr);
900 if (color_type != PNG_COLOR_TYPE_PALETTE &&
901 color_type != PNG_COLOR_MASK_PALETTE) {
902 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
908 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
909 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
911 for (cindex = 0; cindex < num_palette; cindex++) {
912 rval = palette[cindex].red;
913 gval = palette[cindex].green;
914 bval = palette[cindex].blue;
921 if (ptransparency && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
922 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
924 for (i = 0; i < num_trans; i++) {
925 if (trans[i] < 255) {
931 L_ERROR(
"transparency array not returned\n", __func__);
935 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
966 return ERROR_INT(
"pix not defined", __func__, 1);
968 return ERROR_INT(
"filename not defined", __func__, 1);
971 return ERROR_INT(
"stream not opened", __func__, 1);
975 return ERROR_INT(
"pix not written to stream", __func__, 1);
1061 char commentstring[] =
"Comment";
1062 l_int32 i, j, k, wpl, d, spp, compval, valid;
1063 l_int32 cmflag, opaque, max_trans, ncolors;
1064 l_int32 *rmap, *gmap, *bmap, *amap;
1065 l_uint32 *data, *ppixel;
1066 png_byte bit_depth, color_type;
1067 png_byte alpha[256];
1069 png_uint_32 xres, yres;
1070 png_bytep *row_pointers;
1071 png_bytep rowbuffer;
1072 png_structp png_ptr;
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))) {
1094 return ERROR_INT(
"colormap is not valid", __func__, 1);
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);
1167 palette = (png_colorp)LEPT_CALLOC(ncolors,
sizeof(png_color));
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);
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);
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) {
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);
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);
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);
1312 return ERROR_INT(
"pix not defined", __func__, 1);
1313 if (compval < 0 || compval > 9) {
1314 L_ERROR(
"Invalid zlib comp val; using default\n", __func__);
1315 compval = Z_DEFAULT_COMPRESSION;
1317 pixSetSpecial(pix, 10 + compval);
1335 var_PNG_STRIP_16_TO_8 = flag;
1364 static void memio_png_flush(
MEMIODATA* pthing);
1365 static void memio_png_read_data(png_structp png_ptr, png_bytep outBytes,
1366 png_size_t byteCountToRead);
1367 static void memio_free(
MEMIODATA* pthing);
1369 static const l_int32 MEMIO_BUFFER_SIZE = 8192;
1390 l_int32 written = 0;
1391 l_int32 remainingSpace, remainingToWrite;
1393 thing = (
struct MemIOData*)png_get_io_ptr(png_ptr);
1396 if (len > MEMIO_BUFFER_SIZE) {
1397 last->
m_Buffer = (
char *)LEPT_MALLOC(len);
1403 last->
m_Buffer = (
char *)LEPT_MALLOC(MEMIO_BUFFER_SIZE);
1404 last->
m_Size = MEMIO_BUFFER_SIZE;
1407 while (written < len) {
1415 last = thing->
m_Last = next;
1417 last->
m_Buffer = (
char *)LEPT_MALLOC(MEMIO_BUFFER_SIZE);
1418 last->
m_Size = MEMIO_BUFFER_SIZE;
1422 remainingToWrite = len - written;
1423 if (remainingSpace < remainingToWrite) {
1426 written += remainingSpace;
1427 last->
m_Count += remainingSpace;
1431 written += remainingToWrite;
1432 last->
m_Count += remainingToWrite;
1458 if (pthing->
m_Next == NULL)
return;
1464 while (buffer != NULL) {
1470 data = (
char *)LEPT_MALLOC(amount);
1480 while (buffer != NULL && copied < amount) {
1513 memio_png_read_data(png_structp png_ptr,
1515 png_size_t byteCountToRead)
1519 thing = (
MEMIODATA *)png_get_io_ptr(png_ptr);
1521 png_error(png_ptr,
"read error in memio_png_read_data");
1524 thing->
m_Count += byteCountToRead;
1549 while (buffer != NULL) {
1580 l_int32 i, j, k, index, ncolors, rval, gval, bval, valid;
1581 l_int32 wpl, d, spp, cindex, bitval, bival, quadval, tRNS;
1582 l_uint32 png_transforms;
1583 l_uint32 *data, *line, *ppixel;
1584 int num_palette, num_text, num_trans;
1585 png_byte bit_depth, color_type, channels;
1586 png_uint_32 w, h, rowbytes, xres, yres;
1587 png_bytep rowptr, trans;
1588 png_bytep *row_pointers;
1589 png_structp png_ptr;
1590 png_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);
1678 for (cindex = 0; cindex < num_palette; cindex++) {
1679 rval = palette[cindex].red;
1680 gval = palette[cindex].green;
1681 bval = palette[cindex].blue;
1686 if ((pix =
pixCreate(w, h, d)) == NULL) {
1688 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1690 return (
PIX *)ERROR_PTR(
"pix not made", __func__, NULL);
1692 pixSetInputFormat(pix, IFF_PNG);
1693 wpl = pixGetWpl(pix);
1695 pixSetSpp(pix, spp);
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__);
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",
1774 wpl = pixGetWpl(pix);
1780 ncolors, num_trans);
1781 for (i = 0; i < ncolors; i++) {
1783 if (i < num_trans) {
1785 rval, gval, bval, trans[i]);
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;
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;
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;
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++) {
1869 index < num_trans ? trans[index] : 255);
1874 L_ERROR(
"spp == 1, cmap, trans array, invalid depth: %d\n",
1883 for (i = 0; i < 16; i++) {
1911 if (pixGetDepth(pix) == 1) {
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)
1931 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1934 if ((cmap = pixGetColormap(pix)) != NULL) {
1938 return (
PIX *)ERROR_PTR(
"colormap is not valid", __func__, NULL);
1970 char commentstring[] =
"Comment";
1971 l_int32 i, j, k, wpl, d, spp, cmflag, opaque, ncolors, compval, valid;
1972 l_int32 *rmap, *gmap, *bmap, *amap;
1973 l_uint32 *data, *ppixel;
1974 png_byte bit_depth, color_type;
1975 png_byte alpha[256];
1976 png_uint_32 w, h, xres, yres;
1977 png_bytep rowbuffer;
1978 png_structp png_ptr;
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))) {
2011 return ERROR_INT(
"colormap is not valid", __func__, 1);
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);
2085 palette = (png_colorp)LEPT_CALLOC(ncolors,
sizeof(png_color));
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);
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);
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) {
2143 png_destroy_write_struct(&png_ptr, &info_ptr);
2145 return ERROR_INT(
"pix1 not made", __func__, 1);
2149 wpl = pixGetWpl(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;
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;
#define GET_DATA_BYTE(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
l_ok pixcmapSetAlpha(PIXCMAP *cmap, l_int32 index, l_int32 aval)
pixcmapSetAlpha()
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()
l_ok pixcmapIsValid(const PIXCMAP *cmap, PIX *pix, l_int32 *pvalid)
pixcmapIsValid()
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
l_ok pixcmapNonOpaqueColorsInfo(PIXCMAP *cmap, l_int32 *pntrans, l_int32 *pmax_trans, l_int32 *pmin_opaque)
pixcmapNonOpaqueColorsInfo()
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
l_ok pixcmapIsOpaque(PIXCMAP *cmap, l_int32 *popaque)
pixcmapIsOpaque()
l_ok pixcmapToArrays(const PIXCMAP *cmap, l_int32 **prmap, l_int32 **pgmap, l_int32 **pbmap, l_int32 **pamap)
pixcmapToArrays()
PIXCMAP * pixcmapCopy(const PIXCMAP *cmaps)
pixcmapCopy()
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
l_uint32 * pixGetData(PIX *pix)
pixGetData()
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
void pixDestroy(PIX **ppix)
pixDestroy()
char * pixGetText(PIX *pix)
pixGetText()
l_ok pixSetText(PIX *pix, const char *textstring)
pixSetText()
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
PIX * pixEndianByteSwapNew(PIX *pixs)
pixEndianByteSwapNew()
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
l_ok pixEndianByteSwap(PIX *pixs)
pixEndianByteSwap()
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
@ REMOVE_CMAP_BASED_ON_SRC
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
l_ok readHeaderPng(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
readHeaderPng()
PIX * pixReadMemPng(const l_uint8 *filedata, size_t filesize)
pixReadMemPng()
l_ok isPngInterlaced(const char *filename, l_int32 *pinterlaced)
isPngInterlaced()
l_ok readHeaderMemPng(const l_uint8 *data, size_t size, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
readHeaderMemPng()
l_ok pixSetZlibCompression(PIX *pix, l_int32 compval)
pixSetZlibCompression()
static void memio_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
l_ok pixWriteStreamPng(FILE *fp, PIX *pix, l_float32 gamma)
pixWriteStreamPng()
l_ok freadHeaderPng(FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
freadHeaderPng()
void l_pngSetReadStrip16To8(l_int32 flag)
l_pngSetReadStrip16To8()
PIX * pixReadStreamPng(FILE *fp)
pixReadStreamPng()
l_ok pixWriteMemPng(l_uint8 **pfiledata, size_t *pfilesize, PIX *pix, l_float32 gamma)
pixWriteMemPng()
l_ok pixWritePng(const char *filename, PIX *pix, l_float32 gamma)
pixWritePng()
struct MemIOData * m_Next
struct MemIOData * m_Last
void lept_stderr(const char *fmt,...)
lept_stderr()
size_t fnbytesInFile(FILE *fp)
fnbytesInFile()
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
FILE * fopenReadStream(const char *filename)
fopenReadStream()