121 #include <config_auto.h> 125 #include "allheaders.h" 136 #define Z_DEFAULT_COMPRESSION (-1) 142 static l_int32 var_PNG_STRIP_16_TO_8 = 1;
144 #ifndef NO_CONSOLE_IO 146 #define DEBUG_WRITE 0 190 l_int32 i, j, k, index, ncolors, rval, gval, bval, valid;
191 l_int32 wpl, d, spp, cindex, bitval, bival, quadval, tRNS;
192 l_uint32 png_transforms;
193 l_uint32 *data, *line, *ppixel;
194 int num_palette, num_text, num_trans;
195 png_byte bit_depth, color_type, channels;
196 png_uint_32 w, h, rowbytes, xres, yres;
197 png_bytep rowptr, trans;
198 png_bytep *row_pointers;
200 png_infop info_ptr, end_info;
206 PROCNAME(
"pixReadStreamPng");
209 return (
PIX *)ERROR_PTR(
"fp not defined", procName, NULL);
213 if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
214 (png_voidp)NULL, NULL, NULL)) == NULL)
215 return (
PIX *)ERROR_PTR(
"png_ptr not made", procName, NULL);
217 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
218 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
219 return (
PIX *)ERROR_PTR(
"info_ptr not made", procName, NULL);
222 if ((end_info = png_create_info_struct(png_ptr)) == NULL) {
223 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
224 return (
PIX *)ERROR_PTR(
"end_info not made", procName, NULL);
228 if (setjmp(png_jmpbuf(png_ptr))) {
229 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
230 return (
PIX *)ERROR_PTR(
"internal png error", procName, NULL);
233 png_init_io(png_ptr, fp);
243 if (var_PNG_STRIP_16_TO_8 == 1) {
244 png_transforms = PNG_TRANSFORM_STRIP_16;
246 png_transforms = PNG_TRANSFORM_IDENTITY;
247 L_INFO(
"not stripping 16 --> 8 in png reading\n", procName);
251 png_read_png(png_ptr, info_ptr, png_transforms, NULL);
253 row_pointers = png_get_rows(png_ptr, info_ptr);
254 w = png_get_image_width(png_ptr, info_ptr);
255 h = png_get_image_height(png_ptr, info_ptr);
256 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
257 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
258 color_type = png_get_color_type(png_ptr, info_ptr);
259 channels = png_get_channels(png_ptr, info_ptr);
261 tRNS = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? 1 : 0;
270 if (spp != 1 && bit_depth != 8) {
271 L_ERROR(
"spp = %d and bps = %d != 8\n" 272 "turn on 16 --> 8 stripping\n", procName, spp, bit_depth);
273 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
274 return (
PIX *)ERROR_PTR(
"not implemented for this image",
279 if (color_type == PNG_COLOR_TYPE_PALETTE ||
280 color_type == PNG_COLOR_MASK_PALETTE) {
281 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
283 for (cindex = 0; cindex < num_palette; cindex++) {
284 rval = palette[cindex].red;
285 gval = palette[cindex].green;
286 bval = palette[cindex].blue;
291 if ((pix =
pixCreate(w, h, d)) == NULL) {
293 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
294 return (
PIX *)ERROR_PTR(
"pix not made", procName, NULL);
296 pixSetInputFormat(pix, IFF_PNG);
297 wpl = pixGetWpl(pix);
302 return (
PIX *)ERROR_PTR(
"invalid colormap", procName, NULL);
305 if (spp == 1 && !tRNS) {
306 for (i = 0; i < h; i++) {
307 line = data + i * wpl;
308 rowptr = row_pointers[i];
309 for (j = 0; j < rowbytes; j++) {
313 }
else if (spp == 2) {
314 L_INFO(
"converting (gray + alpha) ==> RGBA\n", procName);
315 for (i = 0; i < h; i++) {
316 ppixel = data + i * wpl;
317 rowptr = row_pointers[i];
318 for (j = k = 0; j < w; j++) {
328 }
else if (spp == 3 || spp == 4) {
329 for (i = 0; i < h; i++) {
330 ppixel = data + i * wpl;
331 rowptr = row_pointers[i];
332 for (j = k = 0; j < w; j++) {
352 if (spp == 1 && tRNS) {
355 L_INFO(
"transparency, 1 spp, no colormap, no transparency array: " 356 "convention is fully transparent image\n", procName);
357 L_INFO(
"converting (fully transparent 1 spp) ==> RGBA\n", procName);
362 L_INFO(
"converting (cmap + alpha) ==> RGBA\n", procName);
365 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
368 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
369 return (
PIX *)ERROR_PTR(
"cmap, tRNS, but no transparency array",
380 wpl = pixGetWpl(pix);
387 for (i = 0; i < ncolors; i++) {
391 rval, gval, bval, trans[i]);
402 L_INFO(
"converting 1 bpp cmap with alpha ==> RGBA\n", procName);
404 L_INFO(
"num_trans = 1; second color opaque by default\n",
406 for (i = 0; i < h; i++) {
407 ppixel = data + i * wpl;
408 rowptr = row_pointers[i];
409 for (j = 0, index = 0; j < rowbytes; j++) {
411 for (k = 0; k < 8 && index < w; k++, index++) {
412 bitval = (
byte >> (7 - k)) & 1;
416 bitval < num_trans ? trans[bitval] : 255);
423 L_INFO(
"converting 2 bpp cmap with alpha ==> RGBA\n", procName);
424 for (i = 0; i < h; i++) {
425 ppixel = data + i * wpl;
426 rowptr = row_pointers[i];
427 for (j = 0, index = 0; j < rowbytes; j++) {
429 for (k = 0; k < 4 && index < w; k++, index++) {
430 bival = (
byte >> 2 * (3 - k)) & 3;
437 bival < num_trans ? trans[bival] : 255);
444 L_INFO(
"converting 4 bpp cmap with alpha ==> RGBA\n", procName);
445 for (i = 0; i < h; i++) {
446 ppixel = data + i * wpl;
447 rowptr = row_pointers[i];
448 for (j = 0, index = 0; j < rowbytes; j++) {
450 for (k = 0; k < 2 && index < w; k++, index++) {
451 quadval = (
byte >> 4 * (1 - k)) & 0xf;
456 quadval < num_trans ? trans[quadval] : 255);
463 L_INFO(
"converting 8 bpp cmap with alpha ==> RGBA\n", procName);
464 for (i = 0; i < h; i++) {
465 ppixel = data + i * wpl;
466 rowptr = row_pointers[i];
467 for (j = 0; j < w; j++) {
473 index < num_trans ? trans[index] : 255);
478 L_ERROR(
"spp == 1, cmap, trans array, invalid depth: %d\n",
487 for (i = 0; i < 16; i++) {
515 if (pixGetDepth(pix) == 1) {
519 L_INFO(
"removing opaque cmap from 1 bpp\n", procName);
526 xres = png_get_x_pixels_per_meter(png_ptr, info_ptr);
527 yres = png_get_y_pixels_per_meter(png_ptr, info_ptr);
528 pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5));
529 pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5));
532 png_get_text(png_ptr, info_ptr, &text_ptr, &num_text);
533 if (num_text && text_ptr)
536 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
539 if ((cmap = pixGetColormap(pix)) != NULL) {
543 return (
PIX *)ERROR_PTR(
"colormap is not valid", procName, NULL);
585 PROCNAME(
"readHeaderPng");
591 if (piscmap) *piscmap = 0;
593 return ERROR_INT(
"filename not defined", procName, 1);
595 return ERROR_INT(
"image file not found", procName, 1);
629 PROCNAME(
"freadHeaderPng");
635 if (piscmap) *piscmap = 0;
637 return ERROR_INT(
"stream not defined", procName, 1);
641 return ERROR_INT(
"file too small to be png", procName, 1);
642 if (fread(data, 1, 40, fp) != 40)
643 return ERROR_INT(
"error reading data", procName, 1);
686 l_int32 colortype, w, h, bps, spp;
689 PROCNAME(
"readHeaderMemPng");
695 if (piscmap) *piscmap = 0;
697 return ERROR_INT(
"data not defined", procName, 1);
699 return ERROR_INT(
"size < 40", procName, 1);
702 if (data[0] != 137 || data[1] != 80 || data[2] != 78 ||
703 data[3] != 71 || data[4] != 13 || data[5] != 10 ||
704 data[6] != 26 || data[7] != 10)
705 return ERROR_INT(
"not a valid png file", procName, 1);
707 pword = (l_uint32 *)data;
708 pshort = (l_uint16 *)data;
709 w = convertOnLittleEnd32(pword[4]);
710 h = convertOnLittleEnd32(pword[5]);
712 return ERROR_INT(
"invalid w or h", procName, 1);
713 twobytes = convertOnLittleEnd16(pshort[12]);
715 colortype = twobytes & 0xff;
723 L_INFO(
"gray + alpha: will extract as RGBA (spp = 4)\n", procName);
725 if (colortype == 2) {
727 }
else if (colortype == 6) {
729 }
else if (colortype == 4) {
735 if (bps < 1 || bps > 16) {
736 L_ERROR(
"invalid bps = %d\n", procName, bps);
741 if (pbps) *pbps = bps;
742 if (pspp) *pspp = spp;
770 fgetPngResolution(FILE *fp,
774 png_uint_32 xres, yres;
778 PROCNAME(
"fgetPngResolution");
780 if (pxres) *pxres = 0;
781 if (pyres) *pyres = 0;
783 return ERROR_INT(
"stream not opened", procName, 1);
784 if (!pxres || !pyres)
785 return ERROR_INT(
"&xres and &yres not both defined", procName, 1);
788 if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
789 (png_voidp)NULL, NULL, NULL)) == NULL)
790 return ERROR_INT(
"png_ptr not made", procName, 1);
791 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
792 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
793 return ERROR_INT(
"info_ptr not made", procName, 1);
798 if (setjmp(png_jmpbuf(png_ptr))) {
799 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
800 return ERROR_INT(
"internal png error", procName, 1);
805 png_init_io(png_ptr, fp);
806 png_read_info(png_ptr, info_ptr);
808 xres = png_get_x_pixels_per_meter(png_ptr, info_ptr);
809 yres = png_get_y_pixels_per_meter(png_ptr, info_ptr);
810 *pxres = (l_int32)((l_float32)xres / 39.37 + 0.5);
811 *pyres = (l_int32)((l_float32)yres / 39.37 + 0.5);
813 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
828 l_int32 *pinterlaced)
833 PROCNAME(
"isPngInterlaced");
836 return ERROR_INT(
"&interlaced not defined", procName, 1);
839 return ERROR_INT(
"filename not defined", procName, 1);
842 return ERROR_INT(
"stream not opened", procName, 1);
843 if (fread(buf, 1, 32, fp) != 32) {
845 return ERROR_INT(
"data not read", procName, 1);
849 *pinterlaced = (buf[28] == 0) ? 0 : 1;
871 fgetPngColormapInfo(FILE *fp,
873 l_int32 *ptransparency)
875 l_int32 i, cindex, rval, gval, bval, num_palette, num_trans;
876 png_byte bit_depth, color_type;
882 PROCNAME(
"fgetPngColormapInfo");
884 if (pcmap) *pcmap = NULL;
885 if (ptransparency) *ptransparency = 0;
886 if (!pcmap && !ptransparency)
887 return ERROR_INT(
"no output defined", procName, 1);
889 return ERROR_INT(
"stream not opened", procName, 1);
892 if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
893 (png_voidp)NULL, NULL, NULL)) == NULL)
894 return ERROR_INT(
"png_ptr not made", procName, 1);
895 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
896 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
897 return ERROR_INT(
"info_ptr not made", procName, 1);
902 if (setjmp(png_jmpbuf(png_ptr))) {
903 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
905 return ERROR_INT(
"internal png error", procName, 1);
910 png_init_io(png_ptr, fp);
911 png_read_info(png_ptr, info_ptr);
912 color_type = png_get_color_type(png_ptr, info_ptr);
913 if (color_type != PNG_COLOR_TYPE_PALETTE &&
914 color_type != PNG_COLOR_MASK_PALETTE) {
915 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
921 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
922 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
924 for (cindex = 0; cindex < num_palette; cindex++) {
925 rval = palette[cindex].red;
926 gval = palette[cindex].green;
927 bval = palette[cindex].blue;
934 if (ptransparency && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
935 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
937 for (i = 0; i < num_trans; i++) {
938 if (trans[i] < 255) {
944 L_ERROR(
"transparency array not returned\n", procName);
948 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
978 PROCNAME(
"pixWritePng");
981 return ERROR_INT(
"pix not defined", procName, 1);
983 return ERROR_INT(
"filename not defined", procName, 1);
986 return ERROR_INT(
"stream not opened", procName, 1);
990 return ERROR_INT(
"pix not written to stream", procName, 1);
1076 char commentstring[] =
"Comment";
1077 l_int32 i, j, k, wpl, d, spp, compval, valid;
1078 l_int32 cmflag, opaque, max_trans, ncolors;
1079 l_int32 *rmap, *gmap, *bmap, *amap;
1080 l_uint32 *data, *ppixel;
1081 png_byte bit_depth, color_type;
1082 png_byte alpha[256];
1084 png_uint_32 xres, yres;
1085 png_bytep *row_pointers;
1086 png_bytep rowbuffer;
1087 png_structp png_ptr;
1094 PROCNAME(
"pixWriteStreamPng");
1097 return ERROR_INT(
"stream not open", procName, 1);
1099 return ERROR_INT(
"pix not defined", procName, 1);
1101 w = pixGetWidth(pix);
1102 h = pixGetHeight(pix);
1103 d = pixGetDepth(pix);
1104 spp = pixGetSpp(pix);
1107 if ((cmap = pixGetColormap(pix))) {
1111 return ERROR_INT(
"colormap is not valid", procName, 1);
1118 if (d == 32 && spp == 4) {
1120 color_type = PNG_COLOR_TYPE_RGBA;
1122 }
else if (d == 24 || d == 32) {
1124 color_type = PNG_COLOR_TYPE_RGB;
1128 color_type = PNG_COLOR_TYPE_GRAY;
1131 color_type = PNG_COLOR_TYPE_PALETTE;
1134 lept_stderr(
"cmflag = %d, bit_depth = %d, color_type = %d\n",
1135 cmflag, bit_depth, color_type);
1139 if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1140 (png_voidp)NULL, NULL, NULL)) == NULL)
1141 return ERROR_INT(
"png_ptr not made", procName, 1);
1142 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
1143 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
1144 return ERROR_INT(
"info_ptr not made", procName, 1);
1149 row_pointers = NULL;
1150 if (setjmp(png_jmpbuf(png_ptr))) {
1151 png_destroy_write_struct(&png_ptr, &info_ptr);
1152 LEPT_FREE(row_pointers);
1154 return ERROR_INT(
"internal png error", procName, 1);
1157 png_init_io(png_ptr, fp);
1164 compval = Z_DEFAULT_COMPRESSION;
1167 png_set_compression_level(png_ptr, compval);
1169 png_set_IHDR(png_ptr, info_ptr, w, h, bit_depth, color_type,
1170 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
1171 PNG_FILTER_TYPE_BASE);
1174 xres = (png_uint_32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
1175 yres = (png_uint_32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
1176 if ((xres == 0) || (yres == 0))
1177 png_set_pHYs(png_ptr, info_ptr, 0, 0, PNG_RESOLUTION_UNKNOWN);
1179 png_set_pHYs(png_ptr, info_ptr, xres, yres, PNG_RESOLUTION_METER);
1184 palette = (png_colorp)LEPT_CALLOC(ncolors,
sizeof(png_color));
1186 for (i = 0; i < ncolors; i++) {
1187 palette[i].red = (png_byte)rmap[i];
1188 palette[i].green = (png_byte)gmap[i];
1189 palette[i].blue = (png_byte)bmap[i];
1190 alpha[i] = (png_byte)amap[i];
1196 png_set_PLTE(png_ptr, info_ptr, palette, (
int)ncolors);
1207 png_set_tRNS(png_ptr, info_ptr, (png_bytep)alpha,
1208 max_trans + 1, NULL);
1216 png_set_gAMA(png_ptr, info_ptr, (l_float64)gamma);
1219 png_text text_chunk;
1220 text_chunk.compression = PNG_TEXT_COMPRESSION_NONE;
1221 text_chunk.key = commentstring;
1222 text_chunk.text = text;
1223 text_chunk.text_length = strlen(text);
1224 #ifdef PNG_ITXT_SUPPORTED 1225 text_chunk.itxt_length = 0;
1226 text_chunk.lang = NULL;
1227 text_chunk.lang_key = NULL;
1229 png_set_text(png_ptr, info_ptr, &text_chunk, 1);
1233 png_write_info(png_ptr, info_ptr);
1235 if ((d != 32) && (d != 24)) {
1242 if (d == 1 && !cmap) {
1249 png_destroy_write_struct(&png_ptr, &info_ptr);
1250 return ERROR_INT(
"pix1 not made", procName, 1);
1254 row_pointers = (png_bytep *)LEPT_CALLOC(h,
sizeof(png_bytep));
1255 wpl = pixGetWpl(pix1);
1257 for (i = 0; i < h; i++)
1258 row_pointers[i] = (png_bytep)(data + i * wpl);
1259 png_set_rows(png_ptr, info_ptr, row_pointers);
1262 png_write_image(png_ptr, row_pointers);
1263 png_write_end(png_ptr, info_ptr);
1264 LEPT_FREE(row_pointers);
1266 png_destroy_write_struct(&png_ptr, &info_ptr);
1272 wpl = pixGetWpl(pix);
1274 for (i = 0; i < h; i++) {
1275 ppixel = data + i * wpl;
1276 png_write_rows(png_ptr, (png_bytepp)&ppixel, 1);
1280 rowbuffer = (png_bytep)LEPT_CALLOC(w, 4);
1281 for (i = 0; i < h; i++) {
1282 ppixel = data + i * wpl;
1283 for (j = k = 0; j < w; j++) {
1292 png_write_rows(png_ptr, &rowbuffer, 1);
1294 LEPT_FREE(rowbuffer);
1297 png_write_end(png_ptr, info_ptr);
1298 png_destroy_write_struct(&png_ptr, &info_ptr);
1328 PROCNAME(
"pixSetZlibCompression");
1331 return ERROR_INT(
"pix not defined", procName, 1);
1332 if (compval < 0 || compval > 9) {
1333 L_ERROR(
"Invalid zlib comp val; using default\n", procName);
1334 compval = Z_DEFAULT_COMPRESSION;
1336 pixSetSpecial(pix, 10 + compval);
1354 var_PNG_STRIP_16_TO_8 = flag;
1383 static void memio_png_flush(
MEMIODATA* pthing);
1384 static void memio_png_read_data(png_structp png_ptr, png_bytep outBytes,
1385 png_size_t byteCountToRead);
1386 static void memio_free(
MEMIODATA* pthing);
1388 static const l_int32 MEMIO_BUFFER_SIZE = 8192;
1409 l_int32 written = 0;
1410 l_int32 remainingSpace, remainingToWrite;
1412 thing = (
struct MemIOData*)png_get_io_ptr(png_ptr);
1415 if (len > MEMIO_BUFFER_SIZE) {
1416 last->
m_Buffer = (
char *)LEPT_MALLOC(len);
1422 last->
m_Buffer = (
char *)LEPT_MALLOC(MEMIO_BUFFER_SIZE);
1423 last->
m_Size = MEMIO_BUFFER_SIZE;
1426 while (written < len) {
1434 last = thing->
m_Last = next;
1436 last->
m_Buffer = (
char *)LEPT_MALLOC(MEMIO_BUFFER_SIZE);
1437 last->
m_Size = MEMIO_BUFFER_SIZE;
1441 remainingToWrite = len - written;
1442 if (remainingSpace < remainingToWrite) {
1445 written += remainingSpace;
1446 last->
m_Count += remainingSpace;
1450 written += remainingToWrite;
1451 last->
m_Count += remainingToWrite;
1477 if (pthing->
m_Next == NULL)
return;
1483 while (buffer != NULL) {
1489 data = (
char *)LEPT_MALLOC(amount);
1499 while (buffer != NULL && copied < amount) {
1532 memio_png_read_data(png_structp png_ptr,
1534 png_size_t byteCountToRead)
1538 thing = (
MEMIODATA *)png_get_io_ptr(png_ptr);
1540 png_error(png_ptr,
"read error in memio_png_read_data");
1543 thing->
m_Count += byteCountToRead;
1568 while (buffer != NULL) {
1599 l_int32 i, j, k, index, ncolors, rval, gval, bval, valid;
1600 l_int32 wpl, d, spp, cindex, bitval, bival, quadval, tRNS;
1601 l_uint32 png_transforms;
1602 l_uint32 *data, *line, *ppixel;
1603 int num_palette, num_text, num_trans;
1604 png_byte bit_depth, color_type, channels;
1605 png_uint_32 w, h, rowbytes, xres, yres;
1606 png_bytep rowptr, trans;
1607 png_bytep *row_pointers;
1608 png_structp png_ptr;
1609 png_infop info_ptr, end_info;
1616 PROCNAME(
"pixReadMemPng");
1619 return (
PIX *)ERROR_PTR(
"filedata not defined", procName, NULL);
1621 return (
PIX *)ERROR_PTR(
"invalid filesize", procName, NULL);
1631 if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
1632 (png_voidp)NULL, NULL, NULL)) == NULL)
1633 return (
PIX *)ERROR_PTR(
"png_ptr not made", procName, NULL);
1635 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
1636 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
1637 return (
PIX *)ERROR_PTR(
"info_ptr not made", procName, NULL);
1640 if ((end_info = png_create_info_struct(png_ptr)) == NULL) {
1641 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
1642 return (
PIX *)ERROR_PTR(
"end_info not made", procName, NULL);
1646 if (setjmp(png_jmpbuf(png_ptr))) {
1647 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1648 return (
PIX *)ERROR_PTR(
"internal png error", procName, NULL);
1651 png_set_read_fn(png_ptr, &state, memio_png_read_data);
1660 if (var_PNG_STRIP_16_TO_8 == 1) {
1661 png_transforms = PNG_TRANSFORM_STRIP_16;
1663 png_transforms = PNG_TRANSFORM_IDENTITY;
1664 L_INFO(
"not stripping 16 --> 8 in png reading\n", procName);
1668 png_read_png(png_ptr, info_ptr, png_transforms, NULL);
1670 row_pointers = png_get_rows(png_ptr, info_ptr);
1671 w = png_get_image_width(png_ptr, info_ptr);
1672 h = png_get_image_height(png_ptr, info_ptr);
1673 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
1674 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
1675 color_type = png_get_color_type(png_ptr, info_ptr);
1676 channels = png_get_channels(png_ptr, info_ptr);
1678 tRNS = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? 1 : 0;
1687 if (spp == 3 && bit_depth != 8) {
1688 lept_stderr(
"Help: spp = 3 and depth = %d != 8\n!!", bit_depth);
1689 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1690 return (
PIX *)ERROR_PTR(
"not implemented for this depth",
1695 if (color_type == PNG_COLOR_TYPE_PALETTE ||
1696 color_type == PNG_COLOR_MASK_PALETTE) {
1697 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
1699 for (cindex = 0; cindex < num_palette; cindex++) {
1700 rval = palette[cindex].red;
1701 gval = palette[cindex].green;
1702 bval = palette[cindex].blue;
1707 if ((pix =
pixCreate(w, h, d)) == NULL) {
1709 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1711 return (
PIX *)ERROR_PTR(
"pix not made", procName, NULL);
1713 pixSetInputFormat(pix, IFF_PNG);
1714 wpl = pixGetWpl(pix);
1716 pixSetSpp(pix, spp);
1719 return (
PIX *)ERROR_PTR(
"invalid colormap", procName, NULL);
1722 if (spp == 1 && !tRNS) {
1723 for (i = 0; i < h; i++) {
1724 line = data + i * wpl;
1725 rowptr = row_pointers[i];
1726 for (j = 0; j < rowbytes; j++) {
1730 }
else if (spp == 2) {
1731 L_INFO(
"converting (gray + alpha) ==> RGBA\n", procName);
1732 for (i = 0; i < h; i++) {
1733 ppixel = data + i * wpl;
1734 rowptr = row_pointers[i];
1735 for (j = k = 0; j < w; j++) {
1745 }
else if (spp == 3 || spp == 4) {
1746 for (i = 0; i < h; i++) {
1747 ppixel = data + i * wpl;
1748 rowptr = row_pointers[i];
1749 for (j = k = 0; j < w; j++) {
1767 if (spp == 1 && tRNS) {
1770 L_INFO(
"transparency, 1 spp, no colormap, no transparency array: " 1771 "convention is fully transparent image\n", procName);
1772 L_INFO(
"converting (fully transparent 1 spp) ==> RGBA\n", procName);
1777 L_INFO(
"converting (cmap + alpha) ==> RGBA\n", procName);
1780 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
1783 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1784 return (
PIX *)ERROR_PTR(
"cmap, tRNS, but no transparency array",
1795 wpl = pixGetWpl(pix);
1801 ncolors, num_trans);
1802 for (i = 0; i < ncolors; i++) {
1804 if (i < num_trans) {
1806 rval, gval, bval, trans[i]);
1817 L_INFO(
"converting 1 bpp cmap with alpha ==> RGBA\n", procName);
1819 L_INFO(
"num_trans = 1; second color opaque by default\n",
1821 for (i = 0; i < h; i++) {
1822 ppixel = data + i * wpl;
1823 rowptr = row_pointers[i];
1824 for (j = 0, index = 0; j < rowbytes; j++) {
1826 for (k = 0; k < 8 && index < w; k++, index++) {
1827 bitval = (
byte >> (7 - k)) & 1;
1831 bitval < num_trans ? trans[bitval] : 255);
1836 }
else if (d == 2) {
1838 L_INFO(
"converting 2 bpp cmap with alpha ==> RGBA\n", procName);
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 < 4 && index < w; k++, index++) {
1845 bival = (
byte >> 2 * (3 - k)) & 3;
1852 bival < num_trans ? trans[bival] : 255);
1857 }
else if (d == 4) {
1859 L_INFO(
"converting 4 bpp cmap with alpha ==> RGBA\n", procName);
1860 for (i = 0; i < h; i++) {
1861 ppixel = data + i * wpl;
1862 rowptr = row_pointers[i];
1863 for (j = 0, index = 0; j < rowbytes; j++) {
1865 for (k = 0; k < 2 && index < w; k++, index++) {
1866 quadval = (
byte >> 4 * (1 - k)) & 0xf;
1871 quadval < num_trans ? trans[quadval] : 255);
1876 }
else if (d == 8) {
1878 L_INFO(
"converting 8 bpp cmap with alpha ==> RGBA\n", procName);
1879 for (i = 0; i < h; i++) {
1880 ppixel = data + i * wpl;
1881 rowptr = row_pointers[i];
1882 for (j = 0; j < w; j++) {
1890 index < num_trans ? trans[index] : 255);
1895 L_ERROR(
"spp == 1, cmap, trans array, invalid depth: %d\n",
1904 for (i = 0; i < 16; i++) {
1932 if (pixGetDepth(pix) == 1) {
1942 xres = png_get_x_pixels_per_meter(png_ptr, info_ptr);
1943 yres = png_get_y_pixels_per_meter(png_ptr, info_ptr);
1944 pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5));
1945 pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5));
1948 png_get_text(png_ptr, info_ptr, &text_ptr, &num_text);
1949 if (num_text && text_ptr)
1952 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1955 if ((cmap = pixGetColormap(pix)) != NULL) {
1959 return (
PIX *)ERROR_PTR(
"colormap is not valid", procName, NULL);
1991 char commentstring[] =
"Comment";
1992 l_int32 i, j, k, wpl, d, spp, cmflag, opaque, ncolors, compval, valid;
1993 l_int32 *rmap, *gmap, *bmap, *amap;
1994 l_uint32 *data, *ppixel;
1995 png_byte bit_depth, color_type;
1996 png_byte alpha[256];
1997 png_uint_32 w, h, xres, yres;
1998 png_bytep rowbuffer;
1999 png_structp png_ptr;
2007 PROCNAME(
"pixWriteMemPng");
2009 if (pfiledata) *pfiledata = NULL;
2010 if (pfilesize) *pfilesize = 0;
2012 return ERROR_INT(
"&filedata not defined", procName, 1);
2014 return ERROR_INT(
"&filesize not defined", procName, 1);
2016 return ERROR_INT(
"pix not defined", procName, 1);
2024 w = pixGetWidth(pix);
2025 h = pixGetHeight(pix);
2026 d = pixGetDepth(pix);
2027 spp = pixGetSpp(pix);
2030 if ((cmap = pixGetColormap(pix))) {
2034 return ERROR_INT(
"colormap is not valid", procName, 1);
2042 if (d == 32 && spp == 4) {
2044 color_type = PNG_COLOR_TYPE_RGBA;
2046 }
else if (d == 24 || d == 32) {
2048 color_type = PNG_COLOR_TYPE_RGB;
2052 color_type = PNG_COLOR_TYPE_GRAY;
2055 color_type = PNG_COLOR_TYPE_PALETTE;
2058 lept_stderr(
"cmflag = %d, bit_depth = %d, color_type = %d\n",
2059 cmflag, bit_depth, color_type);
2063 if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
2064 (png_voidp)NULL, NULL, NULL)) == NULL)
2065 return ERROR_INT(
"png_ptr not made", procName, 1);
2067 if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
2068 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
2069 return ERROR_INT(
"info_ptr not made", procName, 1);
2074 if (setjmp(png_jmpbuf(png_ptr))) {
2075 png_destroy_write_struct(&png_ptr, &info_ptr);
2077 return ERROR_INT(
"internal png error", procName, 1);
2081 (png_flush_ptr)NULL);
2088 compval = Z_DEFAULT_COMPRESSION;
2091 png_set_compression_level(png_ptr, compval);
2093 png_set_IHDR(png_ptr, info_ptr, w, h, bit_depth, color_type,
2094 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
2095 PNG_FILTER_TYPE_BASE);
2098 xres = (png_uint_32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
2099 yres = (png_uint_32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
2100 if ((xres == 0) || (yres == 0))
2101 png_set_pHYs(png_ptr, info_ptr, 0, 0, PNG_RESOLUTION_UNKNOWN);
2103 png_set_pHYs(png_ptr, info_ptr, xres, yres, PNG_RESOLUTION_METER);
2108 palette = (png_colorp)LEPT_CALLOC(ncolors,
sizeof(png_color));
2110 for (i = 0; i < ncolors; i++) {
2111 palette[i].red = (png_byte)rmap[i];
2112 palette[i].green = (png_byte)gmap[i];
2113 palette[i].blue = (png_byte)bmap[i];
2114 alpha[i] = (png_byte)amap[i];
2120 png_set_PLTE(png_ptr, info_ptr, palette, (
int)ncolors);
2125 png_set_tRNS(png_ptr, info_ptr, (png_bytep)alpha,
2126 (
int)ncolors, NULL);
2133 png_set_gAMA(png_ptr, info_ptr, (l_float64)gamma);
2136 png_text text_chunk;
2137 text_chunk.compression = PNG_TEXT_COMPRESSION_NONE;
2138 text_chunk.key = commentstring;
2139 text_chunk.text = text;
2140 text_chunk.text_length = strlen(text);
2141 #ifdef PNG_ITXT_SUPPORTED 2142 text_chunk.itxt_length = 0;
2143 text_chunk.lang = NULL;
2144 text_chunk.lang_key = NULL;
2146 png_set_text(png_ptr, info_ptr, &text_chunk, 1);
2150 png_write_info(png_ptr, info_ptr);
2152 if ((d != 32) && (d != 24)) {
2159 if (d == 1 && !cmap) {
2166 png_destroy_write_struct(&png_ptr, &info_ptr);
2168 return ERROR_INT(
"pix1 not made", procName, 1);
2172 wpl = pixGetWpl(pix1);
2174 for (i = 0; i < h; i++)
2175 png_write_row(png_ptr, (png_bytep)(data + i * wpl));
2176 png_write_end(png_ptr, info_ptr);
2179 png_destroy_write_struct(&png_ptr, &info_ptr);
2180 memio_png_flush(&state);
2181 *pfiledata = (l_uint8 *)state.
m_Buffer;
2190 wpl = pixGetWpl(pix);
2192 for (i = 0; i < h; i++) {
2193 ppixel = data + i * wpl;
2194 png_write_rows(png_ptr, (png_bytepp)&ppixel, 1);
2198 rowbuffer = (png_bytep)LEPT_CALLOC(w, 4);
2199 for (i = 0; i < h; i++) {
2200 ppixel = data + i * wpl;
2201 for (j = k = 0; j < w; j++) {
2210 png_write_rows(png_ptr, &rowbuffer, 1);
2212 LEPT_FREE(rowbuffer);
2214 png_write_end(png_ptr, info_ptr);
2216 png_destroy_write_struct(&png_ptr, &info_ptr);
2217 memio_png_flush(&state);
2218 *pfiledata = (l_uint8 *)state.
m_Buffer;
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
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()
PIX * pixReadStreamPng(FILE *fp)
pixReadStreamPng()
static void memio_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
l_ok freadHeaderPng(FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
freadHeaderPng()
void lept_stderr(const char *fmt,...)
lept_stderr()
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
l_uint32 * pixGetData(PIX *pix)
pixGetData()
void l_pngSetReadStrip16To8(l_int32 flag)
l_pngSetReadStrip16To8()
l_ok pixWriteStreamPng(FILE *fp, PIX *pix, l_float32 gamma)
pixWriteStreamPng()
struct MemIOData * m_Next
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
l_ok pixSetText(PIX *pix, const char *textstring)
pixSetText()
l_ok pixWritePng(const char *filename, PIX *pix, l_float32 gamma)
pixWritePng()
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
l_ok readHeaderPng(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap)
readHeaderPng()
l_ok pixWriteMemPng(l_uint8 **pfiledata, size_t *pfilesize, PIX *pix, l_float32 gamma)
pixWriteMemPng()
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 pixSetZlibCompression(PIX *pix, l_int32 compval)
pixSetZlibCompression()
l_ok pixEndianByteSwap(PIX *pixs)
pixEndianByteSwap()
#define SET_DATA_BYTE(pdata, n, val)
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
size_t fnbytesInFile(FILE *fp)
fnbytesInFile()
#define GET_DATA_BYTE(pdata, n)
l_ok pixcmapIsOpaque(PIXCMAP *cmap, l_int32 *popaque)
pixcmapIsOpaque()
void pixDestroy(PIX **ppix)
pixDestroy()
l_ok pixcmapSetAlpha(PIXCMAP *cmap, l_int32 index, l_int32 aval)
pixcmapSetAlpha()
l_ok pixcmapIsValid(const PIXCMAP *cmap, PIX *pix, l_int32 *pvalid)
pixcmapIsValid()
PIX * pixEndianByteSwapNew(PIX *pixs)
pixEndianByteSwapNew()
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
FILE * fopenReadStream(const char *filename)
fopenReadStream()
l_ok isPngInterlaced(const char *filename, l_int32 *pinterlaced)
isPngInterlaced()
char * pixGetText(PIX *pix)
pixGetText()
PIX * pixReadMemPng(const l_uint8 *filedata, size_t filesize)
pixReadMemPng()
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
PIXCMAP * pixcmapCopy(const PIXCMAP *cmaps)
pixcmapCopy()
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
struct MemIOData * m_Last
l_ok pixcmapToArrays(const PIXCMAP *cmap, l_int32 **prmap, l_int32 **pgmap, l_int32 **pbmap, l_int32 **pamap)
pixcmapToArrays()