Leptonica 1.82.0
Image processing and image analysis suite
pnmio.c
Go to the documentation of this file.
1/*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
118#ifdef HAVE_CONFIG_H
119#include <config_auto.h>
120#endif /* HAVE_CONFIG_H */
121
122#include <string.h>
123#include <ctype.h>
124#include "allheaders.h"
125
126/* --------------------------------------------*/
127#if USE_PNMIO /* defined in environ.h */
128/* --------------------------------------------*/
129
130static l_int32 pnmReadNextAsciiValue(FILE *fp, l_int32 *pval);
131static l_int32 pnmReadNextNumber(FILE *fp, l_int32 *pval);
132static l_int32 pnmReadNextString(FILE *fp, char *buff, l_int32 size);
133static l_int32 pnmSkipCommentLines(FILE *fp);
134
135 /* a sanity check on the size read from file */
136static const l_int32 MAX_PNM_WIDTH = 100000;
137static const l_int32 MAX_PNM_HEIGHT = 100000;
138
139
140/*--------------------------------------------------------------------*
141 * Stream interface *
142 *--------------------------------------------------------------------*/
149PIX *
151{
152l_uint8 val8, rval8, gval8, bval8, aval8, mask8;
153l_uint16 val16, rval16, gval16, bval16, aval16;
154l_int32 w, h, d, bps, spp, bpl, wpl, i, j, type;
155l_int32 val, rval, gval, bval;
156l_uint32 rgbval;
157l_uint32 *line, *data;
158PIX *pix;
159
160 PROCNAME("pixReadStreamPnm");
161
162 if (!fp)
163 return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
164
165 if (freadHeaderPnm(fp, &w, &h, &d, &type, &bps, &spp))
166 return (PIX *)ERROR_PTR("header read failed", procName, NULL);
167 if (bps < 1 || bps > 16)
168 return (PIX *)ERROR_PTR("invalid bps", procName, NULL);
169 if (spp < 1 || spp > 4)
170 return (PIX *)ERROR_PTR("invalid spp", procName, NULL);
171 if ((pix = pixCreate(w, h, d)) == NULL)
172 return (PIX *)ERROR_PTR("pix not made", procName, NULL);
173 pixSetInputFormat(pix, IFF_PNM);
174 data = pixGetData(pix);
175 wpl = pixGetWpl(pix);
176
177 /* If type == 6 and bps == 16, we use the code in type 7
178 * to read 6 bytes/pixel from the input file. */
179 if (type == 6 && bps == 16)
180 type = 7;
181
182 switch (type) {
183 case 1:
184 case 2:
185 /* Old "ASCII" binary or gray format */
186 for (i = 0; i < h; i++) {
187 for (j = 0; j < w; j++) {
188 if (pnmReadNextAsciiValue(fp, &val)) {
189 pixDestroy(&pix);
190 return (PIX *)ERROR_PTR("read abend", procName, NULL);
191 }
192 pixSetPixel(pix, j, i, val);
193 }
194 }
195 break;
196
197 case 3:
198 /* Old "ASCII" rgb format */
199 for (i = 0; i < h; i++) {
200 for (j = 0; j < w; j++) {
201 if (pnmReadNextAsciiValue(fp, &rval)) {
202 pixDestroy(&pix);
203 return (PIX *)ERROR_PTR("read abend", procName, NULL);
204 }
205 if (pnmReadNextAsciiValue(fp, &gval)) {
206 pixDestroy(&pix);
207 return (PIX *)ERROR_PTR("read abend", procName, NULL);
208 }
209 if (pnmReadNextAsciiValue(fp, &bval)) {
210 pixDestroy(&pix);
211 return (PIX *)ERROR_PTR("read abend", procName, NULL);
212 }
213 composeRGBPixel(rval, gval, bval, &rgbval);
214 pixSetPixel(pix, j, i, rgbval);
215 }
216 }
217 break;
218
219 case 4:
220 /* "raw" format for 1 bpp */
221 bpl = (d * w + 7) / 8;
222 for (i = 0; i < h; i++) {
223 line = data + i * wpl;
224 for (j = 0; j < bpl; j++) {
225 if (fread(&val8, 1, 1, fp) != 1) {
226 pixDestroy(&pix);
227 return (PIX *)ERROR_PTR("read error in 4", procName, NULL);
228 }
229 SET_DATA_BYTE(line, j, val8);
230 }
231 }
232 break;
233
234 case 5:
235 /* "raw" format for grayscale */
236 for (i = 0; i < h; i++) {
237 line = data + i * wpl;
238 if (d != 16) {
239 for (j = 0; j < w; j++) {
240 if (fread(&val8, 1, 1, fp) != 1) {
241 pixDestroy(&pix);
242 return (PIX *)ERROR_PTR("error in 5", procName, NULL);
243 }
244 if (d == 2)
245 SET_DATA_DIBIT(line, j, val8);
246 else if (d == 4)
247 SET_DATA_QBIT(line, j, val8);
248 else /* d == 8 */
249 SET_DATA_BYTE(line, j, val8);
250 }
251 } else { /* d == 16 */
252 for (j = 0; j < w; j++) {
253 if (fread(&val16, 2, 1, fp) != 1) {
254 pixDestroy(&pix);
255 return (PIX *)ERROR_PTR("16 bpp error", procName, NULL);
256 }
257 SET_DATA_TWO_BYTES(line, j, val16);
258 }
259 }
260 }
261 break;
262
263 case 6:
264 /* "raw" format, type == 6; 8 bps, rgb */
265 for (i = 0; i < h; i++) {
266 line = data + i * wpl;
267 for (j = 0; j < wpl; j++) {
268 if (fread(&rval8, 1, 1, fp) != 1) {
269 pixDestroy(&pix);
270 return (PIX *)ERROR_PTR("read error type 6",
271 procName, NULL);
272 }
273 if (fread(&gval8, 1, 1, fp) != 1) {
274 pixDestroy(&pix);
275 return (PIX *)ERROR_PTR("read error type 6",
276 procName, NULL);
277 }
278 if (fread(&bval8, 1, 1, fp) != 1) {
279 pixDestroy(&pix);
280 return (PIX *)ERROR_PTR("read error type 6",
281 procName, NULL);
282 }
283 composeRGBPixel(rval8, gval8, bval8, &rgbval);
284 line[j] = rgbval;
285 }
286 }
287 break;
288
289 case 7:
290 /* "arbitrary" format; type == 7; */
291 if (bps != 16) {
292 mask8 = (1 << bps) - 1;
293 switch (spp) {
294 case 1: /* 1, 2, 4, 8 bpp grayscale */
295 for (i = 0; i < h; i++) {
296 for (j = 0; j < w; j++) {
297 if (fread(&val8, 1, 1, fp) != 1) {
298 pixDestroy(&pix);
299 return (PIX *)ERROR_PTR("read error type 7",
300 procName, NULL);
301 }
302 val8 = val8 & mask8;
303 if (bps == 1) val8 ^= 1; /* white-is-1 photometry */
304 pixSetPixel(pix, j, i, val8);
305 }
306 }
307 break;
308
309 case 2: /* 1, 2, 4, 8 bpp grayscale + alpha */
310 for (i = 0; i < h; i++) {
311 for (j = 0; j < w; j++) {
312 if (fread(&val8, 1, 1, fp) != 1) {
313 pixDestroy(&pix);
314 return (PIX *)ERROR_PTR("read error type 7",
315 procName, NULL);
316 }
317 if (fread(&aval8, 1, 1, fp) != 1) {
318 pixDestroy(&pix);
319 return (PIX *)ERROR_PTR("read error type 7",
320 procName, NULL);
321 }
322 val8 = val8 & mask8;
323 aval8 = aval8 & mask8;
324 composeRGBAPixel(val8, val8, val8, aval8, &rgbval);
325 pixSetPixel(pix, j, i, rgbval);
326 }
327 }
328 pixSetSpp(pix, 4);
329 break;
330
331 case 3: /* rgb */
332 for (i = 0; i < h; i++) {
333 line = data + i * wpl;
334 for (j = 0; j < wpl; j++) {
335 if (fread(&rval8, 1, 1, fp) != 1) {
336 pixDestroy(&pix);
337 return (PIX *)ERROR_PTR("read error type 7",
338 procName, NULL);
339 }
340 if (fread(&gval8, 1, 1, fp) != 1) {
341 pixDestroy(&pix);
342 return (PIX *)ERROR_PTR("read error type 7",
343 procName, NULL);
344 }
345 if (fread(&bval8, 1, 1, fp) != 1) {
346 pixDestroy(&pix);
347 return (PIX *)ERROR_PTR("read error type 7",
348 procName, NULL);
349 }
350 rval8 = rval8 & mask8;
351 gval8 = gval8 & mask8;
352 bval8 = bval8 & mask8;
353 composeRGBPixel(rval8, gval8, bval8, &rgbval);
354 line[j] = rgbval;
355 }
356 }
357 break;
358
359 case 4: /* rgba */
360 for (i = 0; i < h; i++) {
361 line = data + i * wpl;
362 for (j = 0; j < wpl; j++) {
363 if (fread(&rval8, 1, 1, fp) != 1) {
364 pixDestroy(&pix);
365 return (PIX *)ERROR_PTR("read error type 7",
366 procName, NULL);
367 }
368 if (fread(&gval8, 1, 1, fp) != 1) {
369 pixDestroy(&pix);
370 return (PIX *)ERROR_PTR("read error type 7",
371 procName, NULL);
372 }
373 if (fread(&bval8, 1, 1, fp) != 1) {
374 pixDestroy(&pix);
375 return (PIX *)ERROR_PTR("read error type 7",
376 procName, NULL);
377 }
378 if (fread(&aval8, 1, 1, fp) != 1) {
379 pixDestroy(&pix);
380 return (PIX *)ERROR_PTR("read error type 7",
381 procName, NULL);
382 }
383 rval8 = rval8 & mask8;
384 gval8 = gval8 & mask8;
385 bval8 = bval8 & mask8;
386 aval8 = aval8 & mask8;
387 composeRGBAPixel(rval8, gval8, bval8, aval8, &rgbval);
388 line[j] = rgbval;
389 }
390 }
391 pixSetSpp(pix, 4);
392 break;
393 }
394 } else { /* bps == 16 */
395 /* I have only seen one example that is type 6, 16 bps.
396 * It was 3 spp (rgb), and the 8 bps of real data was stored
397 * in the second byte. In the following, I make the wild
398 * assumption that for all 16 bpp pnm/pam files, we can
399 * take the second byte. */
400 switch (spp) {
401 case 1: /* 16 bps grayscale */
402 for (i = 0; i < h; i++) {
403 for (j = 0; j < w; j++) {
404 if (fread(&val16, 2, 1, fp) != 1) {
405 pixDestroy(&pix);
406 return (PIX *)ERROR_PTR("read error type 7",
407 procName, NULL);
408 }
409 val8 = val16 & 0xff;
410 pixSetPixel(pix, j, i, val8);
411 }
412 }
413 break;
414
415 case 2: /* 16 bps grayscale + alpha */
416 for (i = 0; i < h; i++) {
417 for (j = 0; j < w; j++) {
418 if (fread(&val16, 2, 1, fp) != 1) {
419 pixDestroy(&pix);
420 return (PIX *)ERROR_PTR("read error type 7",
421 procName, NULL);
422 }
423 if (fread(&aval16, 2, 1, fp) != 1) {
424 pixDestroy(&pix);
425 return (PIX *)ERROR_PTR("read error type 7",
426 procName, NULL);
427 }
428 val8 = val16 & 0xff;
429 aval8 = aval16 & 0xff;
430 composeRGBAPixel(val8, val8, val8, aval8, &rgbval);
431 pixSetPixel(pix, j, i, rgbval);
432 }
433 }
434 pixSetSpp(pix, 4);
435 break;
436
437 case 3: /* 16bps rgb */
438 for (i = 0; i < h; i++) {
439 line = data + i * wpl;
440 for (j = 0; j < wpl; j++) {
441 if (fread(&rval16, 2, 1, fp) != 1) {
442 pixDestroy(&pix);
443 return (PIX *)ERROR_PTR("read error type 7",
444 procName, NULL);
445 }
446 if (fread(&gval16, 2, 1, fp) != 1) {
447 pixDestroy(&pix);
448 return (PIX *)ERROR_PTR("read error type 7",
449 procName, NULL);
450 }
451 if (fread(&bval16, 2, 1, fp) != 1) {
452 pixDestroy(&pix);
453 return (PIX *)ERROR_PTR("read error type 7",
454 procName, NULL);
455 }
456 rval8 = rval16 & 0xff;
457 gval8 = gval16 & 0xff;
458 bval8 = bval16 & 0xff;
459 composeRGBPixel(rval8, gval8, bval8, &rgbval);
460 line[j] = rgbval;
461 }
462 }
463 break;
464
465 case 4: /* 16bps rgba */
466 for (i = 0; i < h; i++) {
467 line = data + i * wpl;
468 for (j = 0; j < wpl; j++) {
469 if (fread(&rval16, 2, 1, fp) != 1) {
470 pixDestroy(&pix);
471 return (PIX *)ERROR_PTR("read error type 7",
472 procName, NULL);
473 }
474 if (fread(&gval16, 2, 1, fp) != 1) {
475 pixDestroy(&pix);
476 return (PIX *)ERROR_PTR("read error type 7",
477 procName, NULL);
478 }
479 if (fread(&bval16, 2, 1, fp) != 1) {
480 pixDestroy(&pix);
481 return (PIX *)ERROR_PTR("read error type 7",
482 procName, NULL);
483 }
484 if (fread(&aval16, 2, 1, fp) != 1) {
485 pixDestroy(&pix);
486 return (PIX *)ERROR_PTR("read error type 7",
487 procName, NULL);
488 }
489 rval8 = rval16 & 0xff;
490 gval8 = gval16 & 0xff;
491 bval8 = bval16 & 0xff;
492 aval8 = aval16 & 0xff;
493 composeRGBAPixel(rval8, gval8, bval8, aval8, &rgbval);
494 line[j] = rgbval;
495 }
496 }
497 pixSetSpp(pix, 4);
498 break;
499 }
500 }
501 break;
502 }
503 return pix;
504}
505
506
519l_ok
520readHeaderPnm(const char *filename,
521 l_int32 *pw,
522 l_int32 *ph,
523 l_int32 *pd,
524 l_int32 *ptype,
525 l_int32 *pbps,
526 l_int32 *pspp)
527{
528l_int32 ret;
529FILE *fp;
530
531 PROCNAME("readHeaderPnm");
532
533 if (pw) *pw = 0;
534 if (ph) *ph = 0;
535 if (pd) *pd = 0;
536 if (ptype) *ptype = 0;
537 if (pbps) *pbps = 0;
538 if (pspp) *pspp = 0;
539 if (!filename)
540 return ERROR_INT("filename not defined", procName, 1);
541
542 if ((fp = fopenReadStream(filename)) == NULL)
543 return ERROR_INT("image file not found", procName, 1);
544 ret = freadHeaderPnm(fp, pw, ph, pd, ptype, pbps, pspp);
545 fclose(fp);
546 return ret;
547}
548
549
562l_ok
564 l_int32 *pw,
565 l_int32 *ph,
566 l_int32 *pd,
567 l_int32 *ptype,
568 l_int32 *pbps,
569 l_int32 *pspp)
570{
571char tag[16], tupltype[32];
572l_int32 i, w, h, d, bps, spp, type;
573l_int32 maxval;
574l_int32 ch;
575
576 PROCNAME("freadHeaderPnm");
577
578 if (pw) *pw = 0;
579 if (ph) *ph = 0;
580 if (pd) *pd = 0;
581 if (ptype) *ptype = 0;
582 if (pbps) *pbps = 0;
583 if (pspp) *pspp = 0;
584 if (!fp)
585 return ERROR_INT("fp not defined", procName, 1);
586
587 if (fscanf(fp, "P%d\n", &type) != 1)
588 return ERROR_INT("invalid read for type", procName, 1);
589 if (type < 1 || type > 7)
590 return ERROR_INT("invalid pnm file", procName, 1);
591
592 if (pnmSkipCommentLines(fp))
593 return ERROR_INT("no data in file", procName, 1);
594
595 if (type == 7) {
596 w = h = d = bps = spp = maxval = 0;
597 for (i = 0; i < 10; i++) { /* limit to 10 lines of this header */
598 if (pnmReadNextString(fp, tag, sizeof(tag)))
599 return ERROR_INT("found no next tag", procName, 1);
600 if (!strcmp(tag, "WIDTH")) {
601 if (pnmReadNextNumber(fp, &w))
602 return ERROR_INT("failed reading width", procName, 1);
603 continue;
604 }
605 if (!strcmp(tag, "HEIGHT")) {
606 if (pnmReadNextNumber(fp, &h))
607 return ERROR_INT("failed reading height", procName, 1);
608 continue;
609 }
610 if (!strcmp(tag, "DEPTH")) {
611 if (pnmReadNextNumber(fp, &spp))
612 return ERROR_INT("failed reading depth", procName, 1);
613 continue;
614 }
615 if (!strcmp(tag, "MAXVAL")) {
616 if (pnmReadNextNumber(fp, &maxval))
617 return ERROR_INT("failed reading maxval", procName, 1);
618 continue;
619 }
620 if (!strcmp(tag, "TUPLTYPE")) {
621 if (pnmReadNextString(fp, tupltype, sizeof(tupltype)))
622 return ERROR_INT("failed reading tuple type", procName, 1);
623 continue;
624 }
625 if (!strcmp(tag, "ENDHDR")) {
626 if ('\n' != (ch = fgetc(fp)))
627 return ERROR_INT("missing LF after ENDHDR", procName, 1);
628 break;
629 }
630 }
631 if (w <= 0 || h <= 0 || w > MAX_PNM_WIDTH || h > MAX_PNM_HEIGHT) {
632 L_INFO("invalid size: w = %d, h = %d\n", procName, w, h);
633 return 1;
634 }
635 if (maxval == 1) {
636 d = bps = 1;
637 } else if (maxval == 3) {
638 d = bps = 2;
639 } else if (maxval == 15) {
640 d = bps = 4;
641 } else if (maxval == 255) {
642 d = bps = 8;
643 } else if (maxval == 0xffff) {
644 d = bps = 16;
645 } else {
646 L_INFO("invalid maxval = %d\n", procName, maxval);
647 return 1;
648 }
649 switch (spp) {
650 case 1:
651 /* d and bps are already set */
652 break;
653 case 2:
654 case 3:
655 case 4:
656 /* create a 32 bpp Pix */
657 d = 32;
658 break;
659 default:
660 L_INFO("invalid depth = %d\n", procName, spp);
661 return 1;
662 }
663 } else {
664
665 if (fscanf(fp, "%d %d\n", &w, &h) != 2)
666 return ERROR_INT("invalid read for w,h", procName, 1);
667 if (w <= 0 || h <= 0 || w > MAX_PNM_WIDTH || h > MAX_PNM_HEIGHT) {
668 L_INFO("invalid size: w = %d, h = %d\n", procName, w, h);
669 return 1;
670 }
671
672 /* Get depth of pix. For types 2 and 5, we use the maxval.
673 * Important implementation note:
674 * - You can't use fscanf(), which throws away whitespace,
675 * and will discard binary data if it starts with whitespace(s).
676 * - You can't use fgets(), which stops at newlines, but this
677 * dumb format doesn't require a newline after the maxval
678 * number -- it just requires one whitespace character.
679 * - Which leaves repeated calls to fgetc, including swallowing
680 * the single whitespace character. */
681 if (type == 1 || type == 4) {
682 d = 1;
683 spp = 1;
684 bps = 1;
685 } else if (type == 2 || type == 5) {
686 if (pnmReadNextNumber(fp, &maxval))
687 return ERROR_INT("invalid read for maxval (2,5)", procName, 1);
688 if (maxval == 3) {
689 d = 2;
690 } else if (maxval == 15) {
691 d = 4;
692 } else if (maxval == 255) {
693 d = 8;
694 } else if (maxval == 0xffff) {
695 d = 16;
696 } else {
697 lept_stderr("maxval = %d\n", maxval);
698 return ERROR_INT("invalid maxval", procName, 1);
699 }
700 bps = d;
701 spp = 1;
702 } else { /* type == 3 || type == 6; this is rgb */
703 if (pnmReadNextNumber(fp, &maxval))
704 return ERROR_INT("invalid read for maxval (3,6)", procName, 1);
705 if (maxval != 255 && maxval != 0xffff) {
706 L_ERROR("unexpected maxval = %d\n", procName, maxval);
707 return 1;
708 }
709 bps = (maxval == 255) ? 8 : 16;
710 d = 32;
711 spp = 3;
712 }
713 }
714 if (pw) *pw = w;
715 if (ph) *ph = h;
716 if (pd) *pd = d;
717 if (ptype) *ptype = type;
718 if (pbps) *pbps = bps;
719 if (pspp) *pspp = spp;
720 return 0;
721}
722
723
741l_ok
743 PIX *pix)
744{
745l_uint8 val8;
746l_uint8 pel[4];
747l_uint16 val16;
748l_int32 h, w, d, ds, i, j, wpls, bpl, filebpl, writeerror, maxval;
749l_uint32 *pword, *datas, *lines;
750PIX *pixs;
751
752 PROCNAME("pixWriteStreamPnm");
753
754 if (!fp)
755 return ERROR_INT("fp not defined", procName, 1);
756 if (!pix)
757 return ERROR_INT("pix not defined", procName, 1);
758
759 pixGetDimensions(pix, &w, &h, &d);
760 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
761 return ERROR_INT("d not in {1,2,4,8,16,24,32}", procName, 1);
762 if (d == 32 && pixGetSpp(pix) == 4)
763 return pixWriteStreamPam(fp, pix);
764
765 /* If a colormap exists, remove and convert to grayscale or rgb */
766 if (pixGetColormap(pix) != NULL)
768 else
769 pixs = pixClone(pix);
770 ds = pixGetDepth(pixs);
771 datas = pixGetData(pixs);
772 wpls = pixGetWpl(pixs);
773
774 writeerror = 0;
775
776 if (ds == 1) { /* binary */
777 fprintf(fp, "P4\n# Raw PBM file written by leptonica "
778 "(www.leptonica.com)\n%d %d\n", w, h);
779
780 bpl = (w + 7) / 8;
781 for (i = 0; i < h; i++) {
782 lines = datas + i * wpls;
783 for (j = 0; j < bpl; j++) {
784 val8 = GET_DATA_BYTE(lines, j);
785 fwrite(&val8, 1, 1, fp);
786 }
787 }
788 } else if (ds == 2 || ds == 4 || ds == 8 || ds == 16) { /* grayscale */
789 maxval = (1 << ds) - 1;
790 fprintf(fp, "P5\n# Raw PGM file written by leptonica "
791 "(www.leptonica.com)\n%d %d\n%d\n", w, h, maxval);
792
793 if (ds != 16) {
794 for (i = 0; i < h; i++) {
795 lines = datas + i * wpls;
796 for (j = 0; j < w; j++) {
797 if (ds == 2)
798 val8 = GET_DATA_DIBIT(lines, j);
799 else if (ds == 4)
800 val8 = GET_DATA_QBIT(lines, j);
801 else /* ds == 8 */
802 val8 = GET_DATA_BYTE(lines, j);
803 fwrite(&val8, 1, 1, fp);
804 }
805 }
806 } else { /* ds == 16 */
807 for (i = 0; i < h; i++) {
808 lines = datas + i * wpls;
809 for (j = 0; j < w; j++) {
810 val16 = GET_DATA_TWO_BYTES(lines, j);
811 fwrite(&val16, 2, 1, fp);
812 }
813 }
814 }
815 } else { /* rgb color */
816 fprintf(fp, "P6\n# Raw PPM file written by leptonica "
817 "(www.leptonica.com)\n%d %d\n255\n", w, h);
818
819 if (d == 24) { /* packed, 3 bytes to a pixel */
820 filebpl = 3 * w;
821 for (i = 0; i < h; i++) { /* write out each raster line */
822 lines = datas + i * wpls;
823 if (fwrite(lines, 1, filebpl, fp) != filebpl)
824 writeerror = 1;
825 }
826 } else { /* 32 bpp rgb */
827 for (i = 0; i < h; i++) {
828 lines = datas + i * wpls;
829 for (j = 0; j < wpls; j++) {
830 pword = lines + j;
831 pel[0] = GET_DATA_BYTE(pword, COLOR_RED);
832 pel[1] = GET_DATA_BYTE(pword, COLOR_GREEN);
833 pel[2] = GET_DATA_BYTE(pword, COLOR_BLUE);
834 if (fwrite(pel, 1, 3, fp) != 3)
835 writeerror = 1;
836 }
837 }
838 }
839 }
840
841 pixDestroy(&pixs);
842 if (writeerror)
843 return ERROR_INT("image write fail", procName, 1);
844 return 0;
845}
846
847
860l_ok
862 PIX *pix)
863{
864char buffer[256];
865l_uint8 cval[3];
866l_int32 h, w, d, ds, i, j, k, maxval, count;
867l_uint32 val;
868PIX *pixs;
869
870 PROCNAME("pixWriteStreamAsciiPnm");
871
872 if (!fp)
873 return ERROR_INT("fp not defined", procName, 1);
874 if (!pix)
875 return ERROR_INT("pix not defined", procName, 1);
876
877 pixGetDimensions(pix, &w, &h, &d);
878 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
879 return ERROR_INT("d not in {1,2,4,8,16,32}", procName, 1);
880
881 /* If a colormap exists, remove and convert to grayscale or rgb */
882 if (pixGetColormap(pix) != NULL)
884 else
885 pixs = pixClone(pix);
886 ds = pixGetDepth(pixs);
887
888 if (ds == 1) { /* binary */
889 fprintf(fp, "P1\n# Ascii PBM file written by leptonica "
890 "(www.leptonica.com)\n%d %d\n", w, h);
891
892 count = 0;
893 for (i = 0; i < h; i++) {
894 for (j = 0; j < w; j++) {
895 pixGetPixel(pixs, j, i, &val);
896 if (val == 0)
897 fputc('0', fp);
898 else /* val == 1 */
899 fputc('1', fp);
900 fputc(' ', fp);
901 count += 2;
902 if (count >= 70) {
903 fputc('\n', fp);
904 count = 0;
905 }
906 }
907 }
908 } else if (ds == 2 || ds == 4 || ds == 8 || ds == 16) { /* grayscale */
909 maxval = (1 << ds) - 1;
910 fprintf(fp, "P2\n# Ascii PGM file written by leptonica "
911 "(www.leptonica.com)\n%d %d\n%d\n", w, h, maxval);
912
913 count = 0;
914 for (i = 0; i < h; i++) {
915 for (j = 0; j < w; j++) {
916 pixGetPixel(pixs, j, i, &val);
917 if (ds == 2) {
918 snprintf(buffer, sizeof(buffer), "%1d ", val);
919 fwrite(buffer, 1, 2, fp);
920 count += 2;
921 } else if (ds == 4) {
922 snprintf(buffer, sizeof(buffer), "%2d ", val);
923 fwrite(buffer, 1, 3, fp);
924 count += 3;
925 } else if (ds == 8) {
926 snprintf(buffer, sizeof(buffer), "%3d ", val);
927 fwrite(buffer, 1, 4, fp);
928 count += 4;
929 } else { /* ds == 16 */
930 snprintf(buffer, sizeof(buffer), "%5d ", val);
931 fwrite(buffer, 1, 6, fp);
932 count += 6;
933 }
934 if (count >= 60) {
935 fputc('\n', fp);
936 count = 0;
937 }
938 }
939 }
940 } else { /* rgb color */
941 fprintf(fp, "P3\n# Ascii PPM file written by leptonica "
942 "(www.leptonica.com)\n%d %d\n255\n", w, h);
943 count = 0;
944 for (i = 0; i < h; i++) {
945 for (j = 0; j < w; j++) {
946 pixGetPixel(pixs, j, i, &val);
947 cval[0] = GET_DATA_BYTE(&val, COLOR_RED);
948 cval[1] = GET_DATA_BYTE(&val, COLOR_GREEN);
949 cval[2] = GET_DATA_BYTE(&val, COLOR_BLUE);
950 for (k = 0; k < 3; k++) {
951 snprintf(buffer, sizeof(buffer), "%3d ", cval[k]);
952 fwrite(buffer, 1, 4, fp);
953 count += 4;
954 if (count >= 60) {
955 fputc('\n', fp);
956 count = 0;
957 }
958 }
959 }
960 }
961 }
962
963 pixDestroy(&pixs);
964 return 0;
965}
966
967
982l_ok
984 PIX *pix)
985{
986l_uint8 val8;
987l_uint8 pel[8];
988l_uint16 val16;
989l_int32 h, w, d, ds, i, j;
990l_int32 wpls, spps, filebpl, writeerror, maxval;
991l_uint32 *pword, *datas, *lines;
992PIX *pixs;
993
994 PROCNAME("pixWriteStreamPam");
995
996 if (!fp)
997 return ERROR_INT("fp not defined", procName, 1);
998 if (!pix)
999 return ERROR_INT("pix not defined", procName, 1);
1000
1001 pixGetDimensions(pix, &w, &h, &d);
1002 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
1003 return ERROR_INT("d not in {1,2,4,8,16,24,32}", procName, 1);
1004
1005 /* If a colormap exists, remove and convert to grayscale or rgb */
1006 if (pixGetColormap(pix) != NULL)
1008 else
1009 pixs = pixClone(pix);
1010 ds = pixGetDepth(pixs);
1011 datas = pixGetData(pixs);
1012 wpls = pixGetWpl(pixs);
1013 spps = pixGetSpp(pixs);
1014 if (ds < 24)
1015 maxval = (1 << ds) - 1;
1016 else
1017 maxval = 255;
1018
1019 writeerror = 0;
1020 fprintf(fp, "P7\n# Arbitrary PAM file written by leptonica "
1021 "(www.leptonica.com)\n");
1022 fprintf(fp, "WIDTH %d\n", w);
1023 fprintf(fp, "HEIGHT %d\n", h);
1024 fprintf(fp, "DEPTH %d\n", spps);
1025 fprintf(fp, "MAXVAL %d\n", maxval);
1026 if (spps == 1 && ds == 1)
1027 fprintf(fp, "TUPLTYPE BLACKANDWHITE\n");
1028 else if (spps == 1)
1029 fprintf(fp, "TUPLTYPE GRAYSCALE\n");
1030 else if (spps == 3)
1031 fprintf(fp, "TUPLTYPE RGB\n");
1032 else if (spps == 4)
1033 fprintf(fp, "TUPLTYPE RGB_ALPHA\n");
1034 fprintf(fp, "ENDHDR\n");
1035
1036 switch (d) {
1037 case 1:
1038 for (i = 0; i < h; i++) {
1039 lines = datas + i * wpls;
1040 for (j = 0; j < w; j++) {
1041 val8 = GET_DATA_BIT(lines, j);
1042 val8 ^= 1; /* pam apparently uses white-is-1 photometry */
1043 if (fwrite(&val8, 1, 1, fp) != 1)
1044 writeerror = 1;
1045 }
1046 }
1047 break;
1048
1049 case 2:
1050 for (i = 0; i < h; i++) {
1051 lines = datas + i * wpls;
1052 for (j = 0; j < w; j++) {
1053 val8 = GET_DATA_DIBIT(lines, j);
1054 if (fwrite(&val8, 1, 1, fp) != 1)
1055 writeerror = 1;
1056 }
1057 }
1058 break;
1059
1060 case 4:
1061 for (i = 0; i < h; i++) {
1062 lines = datas + i * wpls;
1063 for (j = 0; j < w; j++) {
1064 val8 = GET_DATA_QBIT(lines, j);
1065 if (fwrite(&val8, 1, 1, fp) != 1)
1066 writeerror = 1;
1067 }
1068 }
1069 break;
1070
1071 case 8:
1072 for (i = 0; i < h; i++) {
1073 lines = datas + i * wpls;
1074 for (j = 0; j < w; j++) {
1075 val8 = GET_DATA_BYTE(lines, j);
1076 if (fwrite(&val8, 1, 1, fp) != 1)
1077 writeerror = 1;
1078 }
1079 }
1080 break;
1081
1082 case 16:
1083 for (i = 0; i < h; i++) {
1084 lines = datas + i * wpls;
1085 for (j = 0; j < w; j++) {
1086 val16 = GET_DATA_TWO_BYTES(lines, j);
1087 if (fwrite(&val16, 2, 1, fp) != 1)
1088 writeerror = 1;
1089 }
1090 }
1091 break;
1092
1093 case 24:
1094 filebpl = 3 * w;
1095 for (i = 0; i < h; i++) {
1096 lines = datas + i * wpls;
1097 if (fwrite(lines, 1, filebpl, fp) != filebpl)
1098 writeerror = 1;
1099 }
1100 break;
1101
1102 case 32:
1103 switch (spps) {
1104 case 3:
1105 for (i = 0; i < h; i++) {
1106 lines = datas + i * wpls;
1107 for (j = 0; j < wpls; j++) {
1108 pword = lines + j;
1109 pel[0] = GET_DATA_BYTE(pword, COLOR_RED);
1110 pel[1] = GET_DATA_BYTE(pword, COLOR_GREEN);
1111 pel[2] = GET_DATA_BYTE(pword, COLOR_BLUE);
1112 if (fwrite(pel, 1, 3, fp) != 3)
1113 writeerror = 1;
1114 }
1115 }
1116 break;
1117 case 4:
1118 for (i = 0; i < h; i++) {
1119 lines = datas + i * wpls;
1120 for (j = 0; j < wpls; j++) {
1121 pword = lines + j;
1122 pel[0] = GET_DATA_BYTE(pword, COLOR_RED);
1123 pel[1] = GET_DATA_BYTE(pword, COLOR_GREEN);
1124 pel[2] = GET_DATA_BYTE(pword, COLOR_BLUE);
1125 pel[3] = GET_DATA_BYTE(pword, L_ALPHA_CHANNEL);
1126 if (fwrite(pel, 1, 4, fp) != 4)
1127 writeerror = 1;
1128 }
1129 }
1130 break;
1131 }
1132 break;
1133 }
1134
1135 pixDestroy(&pixs);
1136 if (writeerror)
1137 return ERROR_INT("image write fail", procName, 1);
1138 return 0;
1139}
1140
1141
1142/*---------------------------------------------------------------------*
1143 * Read/write to memory *
1144 *---------------------------------------------------------------------*/
1145
1158PIX *
1159pixReadMemPnm(const l_uint8 *data,
1160 size_t size)
1161{
1162FILE *fp;
1163PIX *pix;
1164
1165 PROCNAME("pixReadMemPnm");
1166
1167 if (!data)
1168 return (PIX *)ERROR_PTR("data not defined", procName, NULL);
1169 if ((fp = fopenReadFromMemory(data, size)) == NULL)
1170 return (PIX *)ERROR_PTR("stream not opened", procName, NULL);
1171 pix = pixReadStreamPnm(fp);
1172 fclose(fp);
1173 if (!pix) L_ERROR("pix not read\n", procName);
1174 return pix;
1175}
1176
1177
1191l_ok
1192readHeaderMemPnm(const l_uint8 *data,
1193 size_t size,
1194 l_int32 *pw,
1195 l_int32 *ph,
1196 l_int32 *pd,
1197 l_int32 *ptype,
1198 l_int32 *pbps,
1199 l_int32 *pspp)
1200{
1201l_int32 ret;
1202FILE *fp;
1203
1204 PROCNAME("readHeaderMemPnm");
1205
1206 if (!data)
1207 return ERROR_INT("data not defined", procName, 1);
1208
1209 if ((fp = fopenReadFromMemory(data, size)) == NULL)
1210 return ERROR_INT("stream not opened", procName, 1);
1211 ret = freadHeaderPnm(fp, pw, ph, pd, ptype, pbps, pspp);
1212 fclose(fp);
1213 if (ret)
1214 return ERROR_INT("header data read failed", procName, 1);
1215 return 0;
1216}
1217
1218
1233l_ok
1234pixWriteMemPnm(l_uint8 **pdata,
1235 size_t *psize,
1236 PIX *pix)
1237{
1238l_int32 ret;
1239FILE *fp;
1240
1241 PROCNAME("pixWriteMemPnm");
1242
1243 if (pdata) *pdata = NULL;
1244 if (psize) *psize = 0;
1245 if (!pdata)
1246 return ERROR_INT("&data not defined", procName, 1 );
1247 if (!psize)
1248 return ERROR_INT("&size not defined", procName, 1 );
1249 if (!pix)
1250 return ERROR_INT("&pix not defined", procName, 1 );
1251
1252#if HAVE_FMEMOPEN
1253 if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1254 return ERROR_INT("stream not opened", procName, 1);
1255 ret = pixWriteStreamPnm(fp, pix);
1256 fputc('\0', fp);
1257 fclose(fp);
1258 *psize = *psize - 1;
1259#else
1260 L_INFO("work-around: writing to a temp file\n", procName);
1261 #ifdef _WIN32
1262 if ((fp = fopenWriteWinTempfile()) == NULL)
1263 return ERROR_INT("tmpfile stream not opened", procName, 1);
1264 #else
1265 if ((fp = tmpfile()) == NULL)
1266 return ERROR_INT("tmpfile stream not opened", procName, 1);
1267 #endif /* _WIN32 */
1268 ret = pixWriteStreamPnm(fp, pix);
1269 rewind(fp);
1270 *pdata = l_binaryReadStream(fp, psize);
1271 fclose(fp);
1272#endif /* HAVE_FMEMOPEN */
1273 return ret;
1274}
1275
1276
1291l_ok
1292pixWriteMemPam(l_uint8 **pdata,
1293 size_t *psize,
1294 PIX *pix)
1295{
1296l_int32 ret;
1297FILE *fp;
1298
1299 PROCNAME("pixWriteMemPam");
1300
1301 if (pdata) *pdata = NULL;
1302 if (psize) *psize = 0;
1303 if (!pdata)
1304 return ERROR_INT("&data not defined", procName, 1 );
1305 if (!psize)
1306 return ERROR_INT("&size not defined", procName, 1 );
1307 if (!pix)
1308 return ERROR_INT("&pix not defined", procName, 1 );
1309
1310#if HAVE_FMEMOPEN
1311 if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1312 return ERROR_INT("stream not opened", procName, 1);
1313 ret = pixWriteStreamPam(fp, pix);
1314 fputc('\0', fp);
1315 fclose(fp);
1316 *psize = *psize - 1;
1317#else
1318 L_INFO("work-around: writing to a temp file\n", procName);
1319 #ifdef _WIN32
1320 if ((fp = fopenWriteWinTempfile()) == NULL)
1321 return ERROR_INT("tmpfile stream not opened", procName, 1);
1322 #else
1323 if ((fp = tmpfile()) == NULL)
1324 return ERROR_INT("tmpfile stream not opened", procName, 1);
1325 #endif /* _WIN32 */
1326 ret = pixWriteStreamPam(fp, pix);
1327 rewind(fp);
1328 *pdata = l_binaryReadStream(fp, psize);
1329 fclose(fp);
1330#endif /* HAVE_FMEMOPEN */
1331 return ret;
1332}
1333
1334
1335/*--------------------------------------------------------------------*
1336 * Static helpers *
1337 *--------------------------------------------------------------------*/
1346static l_int32
1348 l_int32 *pval)
1349{
1350l_int32 c, ignore;
1351
1352 PROCNAME("pnmReadNextAsciiValue");
1353
1354 if (!pval)
1355 return ERROR_INT("&val not defined", procName, 1);
1356 *pval = 0;
1357 if (!fp)
1358 return ERROR_INT("stream not open", procName, 1);
1359
1360 if (EOF == fscanf(fp, " "))
1361 return 1;
1362 if (1 != fscanf(fp, "%d", pval))
1363 return 1;
1364
1365 return 0;
1366}
1367
1368
1384static l_int32
1386 l_int32 *pval)
1387{
1388char buf[8];
1389l_int32 i, c, foundws;
1390
1391 PROCNAME("pnmReadNextNumber");
1392
1393 if (!pval)
1394 return ERROR_INT("&val not defined", procName, 1);
1395 *pval = 0;
1396 if (!fp)
1397 return ERROR_INT("stream not open", procName, 1);
1398
1399 /* Swallow whitespace */
1400 if (fscanf(fp, " ") == EOF)
1401 return ERROR_INT("end of file reached", procName, 1);
1402
1403 /* The ASCII characters for the number are followed by exactly
1404 * one whitespace character. */
1405 foundws = FALSE;
1406 for (i = 0; i < 8; i++)
1407 buf[i] = '\0';
1408 for (i = 0; i < 8; i++) {
1409 if ((c = fgetc(fp)) == EOF)
1410 return ERROR_INT("end of file reached", procName, 1);
1411 if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
1412 foundws = TRUE;
1413 buf[i] = '\n';
1414 break;
1415 }
1416 if (!isdigit(c))
1417 return ERROR_INT("char read is not a digit", procName, 1);
1418 buf[i] = c;
1419 }
1420 if (!foundws)
1421 return ERROR_INT("no whitespace found", procName, 1);
1422 if (sscanf(buf, "%d", pval) != 1)
1423 return ERROR_INT("invalid read", procName, 1);
1424 return 0;
1425}
1426
1442static l_int32
1444 char *buff,
1445 l_int32 size)
1446{
1447l_int32 i, c;
1448char fmtString[6]; /* must contain "%9999s" [*] */
1449
1450 PROCNAME("pnmReadNextString");
1451
1452 if (!buff)
1453 return ERROR_INT("buff not defined", procName, 1);
1454 *buff = '\0';
1455 if (size > 10000) /* size - 1 has > 4 digits [*] */
1456 return ERROR_INT("size is too big", procName, 1);
1457 if (size <= 0)
1458 return ERROR_INT("size is too small", procName, 1);
1459 if (!fp)
1460 return ERROR_INT("stream not open", procName, 1);
1461
1462 /* Skip whitespace */
1463 if (fscanf(fp, " ") == EOF)
1464 return 1;
1465
1466 /* Comment lines are allowed to appear anywhere in the header lines */
1467 if (pnmSkipCommentLines(fp))
1468 return ERROR_INT("end of file reached", procName, 1);
1469
1470 snprintf(fmtString, 6, "%%%ds", size-1);
1471 if (fscanf(fp, fmtString, buff) == EOF)
1472 return 1;
1473
1474 return 0;
1475}
1476
1477
1489static l_int32
1491{
1492l_int32 i;
1493char c;
1494
1495 PROCNAME("pnmSkipCommentLines");
1496
1497 if (!fp)
1498 return ERROR_INT("stream not open", procName, 1);
1499 while ((i = fscanf(fp, "#%c", &c))) {
1500 if (i == EOF) return 1;
1501 while (c != '\n') {
1502 if (fscanf(fp, "%c", &c) == EOF)
1503 return 1;
1504 }
1505 }
1506 return 0;
1507}
1508
1509
1510/* --------------------------------------------*/
1511#endif /* USE_PNMIO */
1512/* --------------------------------------------*/
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:212
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
pixSetPixel()
Definition: pix2.c:263
l_ok pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:190
l_ok composeRGBAPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel)
composeRGBAPixel()
Definition: pix2.c:2783
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
@ COLOR_BLUE
Definition: pix.h:206
@ COLOR_RED
Definition: pix.h:204
@ L_ALPHA_CHANNEL
Definition: pix.h:207
@ COLOR_GREEN
Definition: pix.h:205
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:260
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
static l_int32 pnmReadNextNumber(FILE *fp, l_int32 *pval)
pnmReadNextNumber()
Definition: pnmio.c:1385
static l_int32 pnmReadNextString(FILE *fp, char *buff, l_int32 size)
pnmReadNextString()
Definition: pnmio.c:1443
l_ok pixWriteMemPam(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemPam()
Definition: pnmio.c:1292
l_ok pixWriteStreamPnm(FILE *fp, PIX *pix)
pixWriteStreamPnm()
Definition: pnmio.c:742
l_ok readHeaderPnm(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pd, l_int32 *ptype, l_int32 *pbps, l_int32 *pspp)
readHeaderPnm()
Definition: pnmio.c:520
PIX * pixReadMemPnm(const l_uint8 *data, size_t size)
pixReadMemPnm()
Definition: pnmio.c:1159
l_ok pixWriteStreamPam(FILE *fp, PIX *pix)
pixWriteStreamPam()
Definition: pnmio.c:983
PIX * pixReadStreamPnm(FILE *fp)
pixReadStreamPnm()
Definition: pnmio.c:150
static l_int32 pnmSkipCommentLines(FILE *fp)
pnmSkipCommentLines()
Definition: pnmio.c:1490
l_ok readHeaderMemPnm(const l_uint8 *data, size_t size, l_int32 *pw, l_int32 *ph, l_int32 *pd, l_int32 *ptype, l_int32 *pbps, l_int32 *pspp)
readHeaderMemPnm()
Definition: pnmio.c:1192
static l_int32 pnmReadNextAsciiValue(FILE *fp, l_int32 *pval)
pnmReadNextAsciiValue()
Definition: pnmio.c:1347
l_ok pixWriteStreamAsciiPnm(FILE *fp, PIX *pix)
pixWriteStreamAsciiPnm()
Definition: pnmio.c:861
l_ok pixWriteMemPnm(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemPnm()
Definition: pnmio.c:1234
l_ok freadHeaderPnm(FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pd, l_int32 *ptype, l_int32 *pbps, l_int32 *pspp)
freadHeaderPnm()
Definition: pnmio.c:563
Definition: pix.h:139
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:2055
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:2009
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1402