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 
130 static l_int32 pnmReadNextAsciiValue(FILE *fp, l_int32 *pval);
131 static l_int32 pnmReadNextNumber(FILE *fp, l_int32 *pval);
132 static l_int32 pnmReadNextString(FILE *fp, char *buff, l_int32 size);
133 static l_int32 pnmSkipCommentLines(FILE *fp);
134 
135  /* a sanity check on the size read from file */
136 static const l_int32 MAX_PNM_WIDTH = 100000;
137 static const l_int32 MAX_PNM_HEIGHT = 100000;
138 
139 
140 /*--------------------------------------------------------------------*
141  * Stream interface *
142  *--------------------------------------------------------------------*/
149 PIX *
151 {
152 l_uint8 val8, rval8, gval8, bval8, aval8, mask8;
153 l_uint16 val16, rval16, gval16, bval16, aval16;
154 l_int32 w, h, d, bps, spp, bpl, wpl, i, j, type;
155 l_int32 val, rval, gval, bval;
156 l_uint32 rgbval;
157 l_uint32 *line, *data;
158 PIX *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 
519 l_ok
520 readHeaderPnm(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 {
528 l_int32 ret;
529 FILE *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 
562 l_ok
563 freadHeaderPnm(FILE *fp,
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 {
571 char tag[16], tupltype[32];
572 l_int32 i, w, h, d, bps, spp, type;
573 l_int32 maxval;
574 l_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 
741 l_ok
743  PIX *pix)
744 {
745 l_uint8 val8;
746 l_uint8 pel[4];
747 l_uint16 val16;
748 l_int32 h, w, d, ds, i, j, wpls, bpl, filebpl, writeerror, maxval;
749 l_uint32 *pword, *datas, *lines;
750 PIX *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 
860 l_ok
862  PIX *pix)
863 {
864 char buffer[256];
865 l_uint8 cval[3];
866 l_int32 h, w, d, ds, i, j, k, maxval, count;
867 l_uint32 val;
868 PIX *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 
982 l_ok
984  PIX *pix)
985 {
986 l_uint8 val8;
987 l_uint8 pel[8];
988 l_uint16 val16;
989 l_int32 h, w, d, ds, i, j;
990 l_int32 wpls, spps, filebpl, writeerror, maxval;
991 l_uint32 *pword, *datas, *lines;
992 PIX *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 
1158 PIX *
1159 pixReadMemPnm(const l_uint8 *data,
1160  size_t size)
1161 {
1162 FILE *fp;
1163 PIX *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 
1191 l_ok
1192 readHeaderMemPnm(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 {
1201 l_int32 ret;
1202 FILE *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 
1233 l_ok
1234 pixWriteMemPnm(l_uint8 **pdata,
1235  size_t *psize,
1236  PIX *pix)
1237 {
1238 l_int32 ret;
1239 FILE *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 
1291 l_ok
1292 pixWriteMemPam(l_uint8 **pdata,
1293  size_t *psize,
1294  PIX *pix)
1295 {
1296 l_int32 ret;
1297 FILE *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  *--------------------------------------------------------------------*/
1346 static l_int32
1348  l_int32 *pval)
1349 {
1350 l_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 
1384 static l_int32
1386  l_int32 *pval)
1387 {
1388 char buf[8];
1389 l_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 
1442 static l_int32
1444  char *buff,
1445  l_int32 size)
1446 {
1447 l_int32 i, c;
1448 char 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 
1489 static l_int32
1491 {
1492 l_int32 i;
1493 char 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
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
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 * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
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
PIX * pixReadMemPnm(const l_uint8 *data, size_t size)
pixReadMemPnm()
Definition: pnmio.c:1159
static l_int32 pnmReadNextString(FILE *fp, char *buff, l_int32 size)
pnmReadNextString()
Definition: pnmio.c:1443
PIX * pixReadStreamPnm(FILE *fp)
pixReadStreamPnm()
Definition: pnmio.c:150
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
l_ok pixWriteStreamPam(FILE *fp, PIX *pix)
pixWriteStreamPam()
Definition: pnmio.c:983
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
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1402
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:2009
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:2055
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932