Leptonica  1.83.1
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  if (!fp)
161  return (PIX *)ERROR_PTR("fp not defined", __func__, NULL);
162 
163  if (freadHeaderPnm(fp, &w, &h, &d, &type, &bps, &spp))
164  return (PIX *)ERROR_PTR("header read failed", __func__, NULL);
165  if (bps < 1 || bps > 16)
166  return (PIX *)ERROR_PTR("invalid bps", __func__, NULL);
167  if (spp < 1 || spp > 4)
168  return (PIX *)ERROR_PTR("invalid spp", __func__, NULL);
169  if ((pix = pixCreate(w, h, d)) == NULL)
170  return (PIX *)ERROR_PTR("pix not made", __func__, NULL);
171  pixSetInputFormat(pix, IFF_PNM);
172  data = pixGetData(pix);
173  wpl = pixGetWpl(pix);
174 
175  /* If type == 6 and bps == 16, we use the code in type 7
176  * to read 6 bytes/pixel from the input file. */
177  if (type == 6 && bps == 16)
178  type = 7;
179 
180  switch (type) {
181  case 1:
182  case 2:
183  /* Old "ASCII" binary or gray format */
184  for (i = 0; i < h; i++) {
185  for (j = 0; j < w; j++) {
186  if (pnmReadNextAsciiValue(fp, &val)) {
187  pixDestroy(&pix);
188  return (PIX *)ERROR_PTR("read abend", __func__, NULL);
189  }
190  pixSetPixel(pix, j, i, val);
191  }
192  }
193  break;
194 
195  case 3:
196  /* Old "ASCII" rgb format */
197  for (i = 0; i < h; i++) {
198  for (j = 0; j < w; j++) {
199  if (pnmReadNextAsciiValue(fp, &rval)) {
200  pixDestroy(&pix);
201  return (PIX *)ERROR_PTR("read abend", __func__, NULL);
202  }
203  if (pnmReadNextAsciiValue(fp, &gval)) {
204  pixDestroy(&pix);
205  return (PIX *)ERROR_PTR("read abend", __func__, NULL);
206  }
207  if (pnmReadNextAsciiValue(fp, &bval)) {
208  pixDestroy(&pix);
209  return (PIX *)ERROR_PTR("read abend", __func__, NULL);
210  }
211  composeRGBPixel(rval, gval, bval, &rgbval);
212  pixSetPixel(pix, j, i, rgbval);
213  }
214  }
215  break;
216 
217  case 4:
218  /* "raw" format for 1 bpp */
219  bpl = (d * w + 7) / 8;
220  for (i = 0; i < h; i++) {
221  line = data + i * wpl;
222  for (j = 0; j < bpl; j++) {
223  if (fread(&val8, 1, 1, fp) != 1) {
224  pixDestroy(&pix);
225  return (PIX *)ERROR_PTR("read error in 4", __func__, NULL);
226  }
227  SET_DATA_BYTE(line, j, val8);
228  }
229  }
230  break;
231 
232  case 5:
233  /* "raw" format for grayscale */
234  for (i = 0; i < h; i++) {
235  line = data + i * wpl;
236  if (d != 16) {
237  for (j = 0; j < w; j++) {
238  if (fread(&val8, 1, 1, fp) != 1) {
239  pixDestroy(&pix);
240  return (PIX *)ERROR_PTR("error in 5", __func__, NULL);
241  }
242  if (d == 2)
243  SET_DATA_DIBIT(line, j, val8);
244  else if (d == 4)
245  SET_DATA_QBIT(line, j, val8);
246  else /* d == 8 */
247  SET_DATA_BYTE(line, j, val8);
248  }
249  } else { /* d == 16 */
250  for (j = 0; j < w; j++) {
251  if (fread(&val16, 2, 1, fp) != 1) {
252  pixDestroy(&pix);
253  return (PIX *)ERROR_PTR("16 bpp error", __func__, NULL);
254  }
255  SET_DATA_TWO_BYTES(line, j, val16);
256  }
257  }
258  }
259  break;
260 
261  case 6:
262  /* "raw" format, type == 6; 8 bps, rgb */
263  for (i = 0; i < h; i++) {
264  line = data + i * wpl;
265  for (j = 0; j < wpl; j++) {
266  if (fread(&rval8, 1, 1, fp) != 1) {
267  pixDestroy(&pix);
268  return (PIX *)ERROR_PTR("read error type 6",
269  __func__, NULL);
270  }
271  if (fread(&gval8, 1, 1, fp) != 1) {
272  pixDestroy(&pix);
273  return (PIX *)ERROR_PTR("read error type 6",
274  __func__, NULL);
275  }
276  if (fread(&bval8, 1, 1, fp) != 1) {
277  pixDestroy(&pix);
278  return (PIX *)ERROR_PTR("read error type 6",
279  __func__, NULL);
280  }
281  composeRGBPixel(rval8, gval8, bval8, &rgbval);
282  line[j] = rgbval;
283  }
284  }
285  break;
286 
287  case 7:
288  /* "arbitrary" format; type == 7; */
289  if (bps != 16) {
290  mask8 = (1 << bps) - 1;
291  switch (spp) {
292  case 1: /* 1, 2, 4, 8 bpp grayscale */
293  for (i = 0; i < h; i++) {
294  for (j = 0; j < w; j++) {
295  if (fread(&val8, 1, 1, fp) != 1) {
296  pixDestroy(&pix);
297  return (PIX *)ERROR_PTR("read error type 7",
298  __func__, NULL);
299  }
300  val8 = val8 & mask8;
301  if (bps == 1) val8 ^= 1; /* white-is-1 photometry */
302  pixSetPixel(pix, j, i, val8);
303  }
304  }
305  break;
306 
307  case 2: /* 1, 2, 4, 8 bpp grayscale + alpha */
308  for (i = 0; i < h; i++) {
309  for (j = 0; j < w; j++) {
310  if (fread(&val8, 1, 1, fp) != 1) {
311  pixDestroy(&pix);
312  return (PIX *)ERROR_PTR("read error type 7",
313  __func__, NULL);
314  }
315  if (fread(&aval8, 1, 1, fp) != 1) {
316  pixDestroy(&pix);
317  return (PIX *)ERROR_PTR("read error type 7",
318  __func__, NULL);
319  }
320  val8 = val8 & mask8;
321  aval8 = aval8 & mask8;
322  composeRGBAPixel(val8, val8, val8, aval8, &rgbval);
323  pixSetPixel(pix, j, i, rgbval);
324  }
325  }
326  pixSetSpp(pix, 4);
327  break;
328 
329  case 3: /* rgb */
330  for (i = 0; i < h; i++) {
331  line = data + i * wpl;
332  for (j = 0; j < wpl; j++) {
333  if (fread(&rval8, 1, 1, fp) != 1) {
334  pixDestroy(&pix);
335  return (PIX *)ERROR_PTR("read error type 7",
336  __func__, NULL);
337  }
338  if (fread(&gval8, 1, 1, fp) != 1) {
339  pixDestroy(&pix);
340  return (PIX *)ERROR_PTR("read error type 7",
341  __func__, NULL);
342  }
343  if (fread(&bval8, 1, 1, fp) != 1) {
344  pixDestroy(&pix);
345  return (PIX *)ERROR_PTR("read error type 7",
346  __func__, NULL);
347  }
348  rval8 = rval8 & mask8;
349  gval8 = gval8 & mask8;
350  bval8 = bval8 & mask8;
351  composeRGBPixel(rval8, gval8, bval8, &rgbval);
352  line[j] = rgbval;
353  }
354  }
355  break;
356 
357  case 4: /* rgba */
358  for (i = 0; i < h; i++) {
359  line = data + i * wpl;
360  for (j = 0; j < wpl; j++) {
361  if (fread(&rval8, 1, 1, fp) != 1) {
362  pixDestroy(&pix);
363  return (PIX *)ERROR_PTR("read error type 7",
364  __func__, NULL);
365  }
366  if (fread(&gval8, 1, 1, fp) != 1) {
367  pixDestroy(&pix);
368  return (PIX *)ERROR_PTR("read error type 7",
369  __func__, NULL);
370  }
371  if (fread(&bval8, 1, 1, fp) != 1) {
372  pixDestroy(&pix);
373  return (PIX *)ERROR_PTR("read error type 7",
374  __func__, NULL);
375  }
376  if (fread(&aval8, 1, 1, fp) != 1) {
377  pixDestroy(&pix);
378  return (PIX *)ERROR_PTR("read error type 7",
379  __func__, NULL);
380  }
381  rval8 = rval8 & mask8;
382  gval8 = gval8 & mask8;
383  bval8 = bval8 & mask8;
384  aval8 = aval8 & mask8;
385  composeRGBAPixel(rval8, gval8, bval8, aval8, &rgbval);
386  line[j] = rgbval;
387  }
388  }
389  pixSetSpp(pix, 4);
390  break;
391  }
392  } else { /* bps == 16 */
393  /* I have only seen one example that is type 6, 16 bps.
394  * It was 3 spp (rgb), and the 8 bps of real data was stored
395  * in the second byte. In the following, I make the wild
396  * assumption that for all 16 bpp pnm/pam files, we can
397  * take the second byte. */
398  switch (spp) {
399  case 1: /* 16 bps grayscale */
400  for (i = 0; i < h; i++) {
401  for (j = 0; j < w; j++) {
402  if (fread(&val16, 2, 1, fp) != 1) {
403  pixDestroy(&pix);
404  return (PIX *)ERROR_PTR("read error type 7",
405  __func__, NULL);
406  }
407  val8 = val16 & 0xff;
408  pixSetPixel(pix, j, i, val8);
409  }
410  }
411  break;
412 
413  case 2: /* 16 bps grayscale + alpha */
414  for (i = 0; i < h; i++) {
415  for (j = 0; j < w; j++) {
416  if (fread(&val16, 2, 1, fp) != 1) {
417  pixDestroy(&pix);
418  return (PIX *)ERROR_PTR("read error type 7",
419  __func__, NULL);
420  }
421  if (fread(&aval16, 2, 1, fp) != 1) {
422  pixDestroy(&pix);
423  return (PIX *)ERROR_PTR("read error type 7",
424  __func__, NULL);
425  }
426  val8 = val16 & 0xff;
427  aval8 = aval16 & 0xff;
428  composeRGBAPixel(val8, val8, val8, aval8, &rgbval);
429  pixSetPixel(pix, j, i, rgbval);
430  }
431  }
432  pixSetSpp(pix, 4);
433  break;
434 
435  case 3: /* 16bps rgb */
436  for (i = 0; i < h; i++) {
437  line = data + i * wpl;
438  for (j = 0; j < wpl; j++) {
439  if (fread(&rval16, 2, 1, fp) != 1) {
440  pixDestroy(&pix);
441  return (PIX *)ERROR_PTR("read error type 7",
442  __func__, NULL);
443  }
444  if (fread(&gval16, 2, 1, fp) != 1) {
445  pixDestroy(&pix);
446  return (PIX *)ERROR_PTR("read error type 7",
447  __func__, NULL);
448  }
449  if (fread(&bval16, 2, 1, fp) != 1) {
450  pixDestroy(&pix);
451  return (PIX *)ERROR_PTR("read error type 7",
452  __func__, NULL);
453  }
454  rval8 = rval16 & 0xff;
455  gval8 = gval16 & 0xff;
456  bval8 = bval16 & 0xff;
457  composeRGBPixel(rval8, gval8, bval8, &rgbval);
458  line[j] = rgbval;
459  }
460  }
461  break;
462 
463  case 4: /* 16bps rgba */
464  for (i = 0; i < h; i++) {
465  line = data + i * wpl;
466  for (j = 0; j < wpl; j++) {
467  if (fread(&rval16, 2, 1, fp) != 1) {
468  pixDestroy(&pix);
469  return (PIX *)ERROR_PTR("read error type 7",
470  __func__, NULL);
471  }
472  if (fread(&gval16, 2, 1, fp) != 1) {
473  pixDestroy(&pix);
474  return (PIX *)ERROR_PTR("read error type 7",
475  __func__, NULL);
476  }
477  if (fread(&bval16, 2, 1, fp) != 1) {
478  pixDestroy(&pix);
479  return (PIX *)ERROR_PTR("read error type 7",
480  __func__, NULL);
481  }
482  if (fread(&aval16, 2, 1, fp) != 1) {
483  pixDestroy(&pix);
484  return (PIX *)ERROR_PTR("read error type 7",
485  __func__, NULL);
486  }
487  rval8 = rval16 & 0xff;
488  gval8 = gval16 & 0xff;
489  bval8 = bval16 & 0xff;
490  aval8 = aval16 & 0xff;
491  composeRGBAPixel(rval8, gval8, bval8, aval8, &rgbval);
492  line[j] = rgbval;
493  }
494  }
495  pixSetSpp(pix, 4);
496  break;
497  }
498  }
499  break;
500  }
501  return pix;
502 }
503 
504 
517 l_ok
518 readHeaderPnm(const char *filename,
519  l_int32 *pw,
520  l_int32 *ph,
521  l_int32 *pd,
522  l_int32 *ptype,
523  l_int32 *pbps,
524  l_int32 *pspp)
525 {
526 l_int32 ret;
527 FILE *fp;
528 
529  if (pw) *pw = 0;
530  if (ph) *ph = 0;
531  if (pd) *pd = 0;
532  if (ptype) *ptype = 0;
533  if (pbps) *pbps = 0;
534  if (pspp) *pspp = 0;
535  if (!filename)
536  return ERROR_INT("filename not defined", __func__, 1);
537 
538  if ((fp = fopenReadStream(filename)) == NULL)
539  return ERROR_INT("image file not found", __func__, 1);
540  ret = freadHeaderPnm(fp, pw, ph, pd, ptype, pbps, pspp);
541  fclose(fp);
542  return ret;
543 }
544 
545 
558 l_ok
559 freadHeaderPnm(FILE *fp,
560  l_int32 *pw,
561  l_int32 *ph,
562  l_int32 *pd,
563  l_int32 *ptype,
564  l_int32 *pbps,
565  l_int32 *pspp)
566 {
567 char tag[16], tupltype[32];
568 l_int32 i, w, h, d, bps, spp, type;
569 l_int32 maxval;
570 l_int32 ch;
571 
572  if (pw) *pw = 0;
573  if (ph) *ph = 0;
574  if (pd) *pd = 0;
575  if (ptype) *ptype = 0;
576  if (pbps) *pbps = 0;
577  if (pspp) *pspp = 0;
578  if (!fp)
579  return ERROR_INT("fp not defined", __func__, 1);
580 
581  if (fscanf(fp, "P%d\n", &type) != 1)
582  return ERROR_INT("invalid read for type", __func__, 1);
583  if (type < 1 || type > 7)
584  return ERROR_INT("invalid pnm file", __func__, 1);
585 
586  if (pnmSkipCommentLines(fp))
587  return ERROR_INT("no data in file", __func__, 1);
588 
589  if (type == 7) {
590  w = h = d = bps = spp = maxval = 0;
591  for (i = 0; i < 10; i++) { /* limit to 10 lines of this header */
592  if (pnmReadNextString(fp, tag, sizeof(tag)))
593  return ERROR_INT("found no next tag", __func__, 1);
594  if (!strcmp(tag, "WIDTH")) {
595  if (pnmReadNextNumber(fp, &w))
596  return ERROR_INT("failed reading width", __func__, 1);
597  continue;
598  }
599  if (!strcmp(tag, "HEIGHT")) {
600  if (pnmReadNextNumber(fp, &h))
601  return ERROR_INT("failed reading height", __func__, 1);
602  continue;
603  }
604  if (!strcmp(tag, "DEPTH")) {
605  if (pnmReadNextNumber(fp, &spp))
606  return ERROR_INT("failed reading depth", __func__, 1);
607  continue;
608  }
609  if (!strcmp(tag, "MAXVAL")) {
610  if (pnmReadNextNumber(fp, &maxval))
611  return ERROR_INT("failed reading maxval", __func__, 1);
612  continue;
613  }
614  if (!strcmp(tag, "TUPLTYPE")) {
615  if (pnmReadNextString(fp, tupltype, sizeof(tupltype)))
616  return ERROR_INT("failed reading tuple type", __func__, 1);
617  continue;
618  }
619  if (!strcmp(tag, "ENDHDR")) {
620  if ('\n' != (ch = fgetc(fp)))
621  return ERROR_INT("missing LF after ENDHDR", __func__, 1);
622  break;
623  }
624  }
625  if (w <= 0 || h <= 0 || w > MAX_PNM_WIDTH || h > MAX_PNM_HEIGHT) {
626  L_INFO("invalid size: w = %d, h = %d\n", __func__, w, h);
627  return 1;
628  }
629  if (maxval == 1) {
630  d = bps = 1;
631  } else if (maxval == 3) {
632  d = bps = 2;
633  } else if (maxval == 15) {
634  d = bps = 4;
635  } else if (maxval == 255) {
636  d = bps = 8;
637  } else if (maxval == 0xffff) {
638  d = bps = 16;
639  } else {
640  L_INFO("invalid maxval = %d\n", __func__, maxval);
641  return 1;
642  }
643  switch (spp) {
644  case 1:
645  /* d and bps are already set */
646  break;
647  case 2:
648  case 3:
649  case 4:
650  /* create a 32 bpp Pix */
651  d = 32;
652  break;
653  default:
654  L_INFO("invalid depth = %d\n", __func__, spp);
655  return 1;
656  }
657  } else {
658 
659  if (fscanf(fp, "%d %d\n", &w, &h) != 2)
660  return ERROR_INT("invalid read for w,h", __func__, 1);
661  if (w <= 0 || h <= 0 || w > MAX_PNM_WIDTH || h > MAX_PNM_HEIGHT) {
662  L_INFO("invalid size: w = %d, h = %d\n", __func__, w, h);
663  return 1;
664  }
665 
666  /* Get depth of pix. For types 2 and 5, we use the maxval.
667  * Important implementation note:
668  * - You can't use fscanf(), which throws away whitespace,
669  * and will discard binary data if it starts with whitespace(s).
670  * - You can't use fgets(), which stops at newlines, but this
671  * dumb format doesn't require a newline after the maxval
672  * number -- it just requires one whitespace character.
673  * - Which leaves repeated calls to fgetc, including swallowing
674  * the single whitespace character. */
675  if (type == 1 || type == 4) {
676  d = 1;
677  spp = 1;
678  bps = 1;
679  } else if (type == 2 || type == 5) {
680  if (pnmReadNextNumber(fp, &maxval))
681  return ERROR_INT("invalid read for maxval (2,5)", __func__, 1);
682  if (maxval == 3) {
683  d = 2;
684  } else if (maxval == 15) {
685  d = 4;
686  } else if (maxval == 255) {
687  d = 8;
688  } else if (maxval == 0xffff) {
689  d = 16;
690  } else {
691  lept_stderr("maxval = %d\n", maxval);
692  return ERROR_INT("invalid maxval", __func__, 1);
693  }
694  bps = d;
695  spp = 1;
696  } else { /* type == 3 || type == 6; this is rgb */
697  if (pnmReadNextNumber(fp, &maxval))
698  return ERROR_INT("invalid read for maxval (3,6)", __func__, 1);
699  if (maxval != 255 && maxval != 0xffff) {
700  L_ERROR("unexpected maxval = %d\n", __func__, maxval);
701  return 1;
702  }
703  bps = (maxval == 255) ? 8 : 16;
704  d = 32;
705  spp = 3;
706  }
707  }
708  if (pw) *pw = w;
709  if (ph) *ph = h;
710  if (pd) *pd = d;
711  if (ptype) *ptype = type;
712  if (pbps) *pbps = bps;
713  if (pspp) *pspp = spp;
714  return 0;
715 }
716 
717 
735 l_ok
737  PIX *pix)
738 {
739 l_uint8 val8;
740 l_uint8 pel[4];
741 l_uint16 val16;
742 l_int32 h, w, d, ds, i, j, wpls, bpl, filebpl, writeerror, maxval;
743 l_uint32 *pword, *datas, *lines;
744 PIX *pixs;
745 
746  if (!fp)
747  return ERROR_INT("fp not defined", __func__, 1);
748  if (!pix)
749  return ERROR_INT("pix not defined", __func__, 1);
750 
751  pixGetDimensions(pix, &w, &h, &d);
752  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
753  return ERROR_INT("d not in {1,2,4,8,16,24,32}", __func__, 1);
754  if (d == 32 && pixGetSpp(pix) == 4)
755  return pixWriteStreamPam(fp, pix);
756 
757  /* If a colormap exists, remove and convert to grayscale or rgb */
758  if (pixGetColormap(pix) != NULL)
760  else
761  pixs = pixClone(pix);
762  ds = pixGetDepth(pixs);
763  datas = pixGetData(pixs);
764  wpls = pixGetWpl(pixs);
765 
766  writeerror = 0;
767 
768  if (ds == 1) { /* binary */
769  fprintf(fp, "P4\n# Raw PBM file written by leptonica "
770  "(www.leptonica.com)\n%d %d\n", w, h);
771 
772  bpl = (w + 7) / 8;
773  for (i = 0; i < h; i++) {
774  lines = datas + i * wpls;
775  for (j = 0; j < bpl; j++) {
776  val8 = GET_DATA_BYTE(lines, j);
777  fwrite(&val8, 1, 1, fp);
778  }
779  }
780  } else if (ds == 2 || ds == 4 || ds == 8 || ds == 16) { /* grayscale */
781  maxval = (1 << ds) - 1;
782  fprintf(fp, "P5\n# Raw PGM file written by leptonica "
783  "(www.leptonica.com)\n%d %d\n%d\n", w, h, maxval);
784 
785  if (ds != 16) {
786  for (i = 0; i < h; i++) {
787  lines = datas + i * wpls;
788  for (j = 0; j < w; j++) {
789  if (ds == 2)
790  val8 = GET_DATA_DIBIT(lines, j);
791  else if (ds == 4)
792  val8 = GET_DATA_QBIT(lines, j);
793  else /* ds == 8 */
794  val8 = GET_DATA_BYTE(lines, j);
795  fwrite(&val8, 1, 1, fp);
796  }
797  }
798  } else { /* ds == 16 */
799  for (i = 0; i < h; i++) {
800  lines = datas + i * wpls;
801  for (j = 0; j < w; j++) {
802  val16 = GET_DATA_TWO_BYTES(lines, j);
803  fwrite(&val16, 2, 1, fp);
804  }
805  }
806  }
807  } else { /* rgb color */
808  fprintf(fp, "P6\n# Raw PPM file written by leptonica "
809  "(www.leptonica.com)\n%d %d\n255\n", w, h);
810 
811  if (d == 24) { /* packed, 3 bytes to a pixel */
812  filebpl = 3 * w;
813  for (i = 0; i < h; i++) { /* write out each raster line */
814  lines = datas + i * wpls;
815  if (fwrite(lines, 1, filebpl, fp) != filebpl)
816  writeerror = 1;
817  }
818  } else { /* 32 bpp rgb */
819  for (i = 0; i < h; i++) {
820  lines = datas + i * wpls;
821  for (j = 0; j < wpls; j++) {
822  pword = lines + j;
823  pel[0] = GET_DATA_BYTE(pword, COLOR_RED);
824  pel[1] = GET_DATA_BYTE(pword, COLOR_GREEN);
825  pel[2] = GET_DATA_BYTE(pword, COLOR_BLUE);
826  if (fwrite(pel, 1, 3, fp) != 3)
827  writeerror = 1;
828  }
829  }
830  }
831  }
832 
833  pixDestroy(&pixs);
834  if (writeerror)
835  return ERROR_INT("image write fail", __func__, 1);
836  return 0;
837 }
838 
839 
852 l_ok
854  PIX *pix)
855 {
856 char buffer[256];
857 l_uint8 cval[3];
858 l_int32 h, w, d, ds, i, j, k, maxval, count;
859 l_uint32 val;
860 PIX *pixs;
861 
862  if (!fp)
863  return ERROR_INT("fp not defined", __func__, 1);
864  if (!pix)
865  return ERROR_INT("pix not defined", __func__, 1);
866 
867  pixGetDimensions(pix, &w, &h, &d);
868  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
869  return ERROR_INT("d not in {1,2,4,8,16,32}", __func__, 1);
870 
871  /* If a colormap exists, remove and convert to grayscale or rgb */
872  if (pixGetColormap(pix) != NULL)
874  else
875  pixs = pixClone(pix);
876  ds = pixGetDepth(pixs);
877 
878  if (ds == 1) { /* binary */
879  fprintf(fp, "P1\n# Ascii PBM file written by leptonica "
880  "(www.leptonica.com)\n%d %d\n", w, h);
881 
882  count = 0;
883  for (i = 0; i < h; i++) {
884  for (j = 0; j < w; j++) {
885  pixGetPixel(pixs, j, i, &val);
886  if (val == 0)
887  fputc('0', fp);
888  else /* val == 1 */
889  fputc('1', fp);
890  fputc(' ', fp);
891  count += 2;
892  if (count >= 70) {
893  fputc('\n', fp);
894  count = 0;
895  }
896  }
897  }
898  } else if (ds == 2 || ds == 4 || ds == 8 || ds == 16) { /* grayscale */
899  maxval = (1 << ds) - 1;
900  fprintf(fp, "P2\n# Ascii PGM file written by leptonica "
901  "(www.leptonica.com)\n%d %d\n%d\n", w, h, maxval);
902 
903  count = 0;
904  for (i = 0; i < h; i++) {
905  for (j = 0; j < w; j++) {
906  pixGetPixel(pixs, j, i, &val);
907  if (ds == 2) {
908  snprintf(buffer, sizeof(buffer), "%1d ", val);
909  fwrite(buffer, 1, 2, fp);
910  count += 2;
911  } else if (ds == 4) {
912  snprintf(buffer, sizeof(buffer), "%2d ", val);
913  fwrite(buffer, 1, 3, fp);
914  count += 3;
915  } else if (ds == 8) {
916  snprintf(buffer, sizeof(buffer), "%3d ", val);
917  fwrite(buffer, 1, 4, fp);
918  count += 4;
919  } else { /* ds == 16 */
920  snprintf(buffer, sizeof(buffer), "%5d ", val);
921  fwrite(buffer, 1, 6, fp);
922  count += 6;
923  }
924  if (count >= 60) {
925  fputc('\n', fp);
926  count = 0;
927  }
928  }
929  }
930  } else { /* rgb color */
931  fprintf(fp, "P3\n# Ascii PPM file written by leptonica "
932  "(www.leptonica.com)\n%d %d\n255\n", w, h);
933  count = 0;
934  for (i = 0; i < h; i++) {
935  for (j = 0; j < w; j++) {
936  pixGetPixel(pixs, j, i, &val);
937  cval[0] = GET_DATA_BYTE(&val, COLOR_RED);
938  cval[1] = GET_DATA_BYTE(&val, COLOR_GREEN);
939  cval[2] = GET_DATA_BYTE(&val, COLOR_BLUE);
940  for (k = 0; k < 3; k++) {
941  snprintf(buffer, sizeof(buffer), "%3d ", cval[k]);
942  fwrite(buffer, 1, 4, fp);
943  count += 4;
944  if (count >= 60) {
945  fputc('\n', fp);
946  count = 0;
947  }
948  }
949  }
950  }
951  }
952 
953  pixDestroy(&pixs);
954  return 0;
955 }
956 
957 
972 l_ok
974  PIX *pix)
975 {
976 l_uint8 val8;
977 l_uint8 pel[8];
978 l_uint16 val16;
979 l_int32 h, w, d, ds, i, j;
980 l_int32 wpls, spps, filebpl, writeerror, maxval;
981 l_uint32 *pword, *datas, *lines;
982 PIX *pixs;
983 
984  if (!fp)
985  return ERROR_INT("fp not defined", __func__, 1);
986  if (!pix)
987  return ERROR_INT("pix not defined", __func__, 1);
988 
989  pixGetDimensions(pix, &w, &h, &d);
990  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
991  return ERROR_INT("d not in {1,2,4,8,16,24,32}", __func__, 1);
992 
993  /* If a colormap exists, remove and convert to grayscale or rgb */
994  if (pixGetColormap(pix) != NULL)
996  else
997  pixs = pixClone(pix);
998  ds = pixGetDepth(pixs);
999  datas = pixGetData(pixs);
1000  wpls = pixGetWpl(pixs);
1001  spps = pixGetSpp(pixs);
1002  if (ds < 24)
1003  maxval = (1 << ds) - 1;
1004  else
1005  maxval = 255;
1006 
1007  writeerror = 0;
1008  fprintf(fp, "P7\n# Arbitrary PAM file written by leptonica "
1009  "(www.leptonica.com)\n");
1010  fprintf(fp, "WIDTH %d\n", w);
1011  fprintf(fp, "HEIGHT %d\n", h);
1012  fprintf(fp, "DEPTH %d\n", spps);
1013  fprintf(fp, "MAXVAL %d\n", maxval);
1014  if (spps == 1 && ds == 1)
1015  fprintf(fp, "TUPLTYPE BLACKANDWHITE\n");
1016  else if (spps == 1)
1017  fprintf(fp, "TUPLTYPE GRAYSCALE\n");
1018  else if (spps == 3)
1019  fprintf(fp, "TUPLTYPE RGB\n");
1020  else if (spps == 4)
1021  fprintf(fp, "TUPLTYPE RGB_ALPHA\n");
1022  fprintf(fp, "ENDHDR\n");
1023 
1024  switch (d) {
1025  case 1:
1026  for (i = 0; i < h; i++) {
1027  lines = datas + i * wpls;
1028  for (j = 0; j < w; j++) {
1029  val8 = GET_DATA_BIT(lines, j);
1030  val8 ^= 1; /* pam apparently uses white-is-1 photometry */
1031  if (fwrite(&val8, 1, 1, fp) != 1)
1032  writeerror = 1;
1033  }
1034  }
1035  break;
1036 
1037  case 2:
1038  for (i = 0; i < h; i++) {
1039  lines = datas + i * wpls;
1040  for (j = 0; j < w; j++) {
1041  val8 = GET_DATA_DIBIT(lines, j);
1042  if (fwrite(&val8, 1, 1, fp) != 1)
1043  writeerror = 1;
1044  }
1045  }
1046  break;
1047 
1048  case 4:
1049  for (i = 0; i < h; i++) {
1050  lines = datas + i * wpls;
1051  for (j = 0; j < w; j++) {
1052  val8 = GET_DATA_QBIT(lines, j);
1053  if (fwrite(&val8, 1, 1, fp) != 1)
1054  writeerror = 1;
1055  }
1056  }
1057  break;
1058 
1059  case 8:
1060  for (i = 0; i < h; i++) {
1061  lines = datas + i * wpls;
1062  for (j = 0; j < w; j++) {
1063  val8 = GET_DATA_BYTE(lines, j);
1064  if (fwrite(&val8, 1, 1, fp) != 1)
1065  writeerror = 1;
1066  }
1067  }
1068  break;
1069 
1070  case 16:
1071  for (i = 0; i < h; i++) {
1072  lines = datas + i * wpls;
1073  for (j = 0; j < w; j++) {
1074  val16 = GET_DATA_TWO_BYTES(lines, j);
1075  if (fwrite(&val16, 2, 1, fp) != 1)
1076  writeerror = 1;
1077  }
1078  }
1079  break;
1080 
1081  case 24:
1082  filebpl = 3 * w;
1083  for (i = 0; i < h; i++) {
1084  lines = datas + i * wpls;
1085  if (fwrite(lines, 1, filebpl, fp) != filebpl)
1086  writeerror = 1;
1087  }
1088  break;
1089 
1090  case 32:
1091  switch (spps) {
1092  case 3:
1093  for (i = 0; i < h; i++) {
1094  lines = datas + i * wpls;
1095  for (j = 0; j < wpls; j++) {
1096  pword = lines + j;
1097  pel[0] = GET_DATA_BYTE(pword, COLOR_RED);
1098  pel[1] = GET_DATA_BYTE(pword, COLOR_GREEN);
1099  pel[2] = GET_DATA_BYTE(pword, COLOR_BLUE);
1100  if (fwrite(pel, 1, 3, fp) != 3)
1101  writeerror = 1;
1102  }
1103  }
1104  break;
1105  case 4:
1106  for (i = 0; i < h; i++) {
1107  lines = datas + i * wpls;
1108  for (j = 0; j < wpls; j++) {
1109  pword = lines + j;
1110  pel[0] = GET_DATA_BYTE(pword, COLOR_RED);
1111  pel[1] = GET_DATA_BYTE(pword, COLOR_GREEN);
1112  pel[2] = GET_DATA_BYTE(pword, COLOR_BLUE);
1113  pel[3] = GET_DATA_BYTE(pword, L_ALPHA_CHANNEL);
1114  if (fwrite(pel, 1, 4, fp) != 4)
1115  writeerror = 1;
1116  }
1117  }
1118  break;
1119  }
1120  break;
1121  }
1122 
1123  pixDestroy(&pixs);
1124  if (writeerror)
1125  return ERROR_INT("image write fail", __func__, 1);
1126  return 0;
1127 }
1128 
1129 
1130 /*---------------------------------------------------------------------*
1131  * Read/write to memory *
1132  *---------------------------------------------------------------------*/
1133 
1146 PIX *
1147 pixReadMemPnm(const l_uint8 *data,
1148  size_t size)
1149 {
1150 FILE *fp;
1151 PIX *pix;
1152 
1153  if (!data)
1154  return (PIX *)ERROR_PTR("data not defined", __func__, NULL);
1155  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1156  return (PIX *)ERROR_PTR("stream not opened", __func__, NULL);
1157  pix = pixReadStreamPnm(fp);
1158  fclose(fp);
1159  if (!pix) L_ERROR("pix not read\n", __func__);
1160  return pix;
1161 }
1162 
1163 
1177 l_ok
1178 readHeaderMemPnm(const l_uint8 *data,
1179  size_t size,
1180  l_int32 *pw,
1181  l_int32 *ph,
1182  l_int32 *pd,
1183  l_int32 *ptype,
1184  l_int32 *pbps,
1185  l_int32 *pspp)
1186 {
1187 l_int32 ret;
1188 FILE *fp;
1189 
1190  if (!data)
1191  return ERROR_INT("data not defined", __func__, 1);
1192 
1193  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1194  return ERROR_INT("stream not opened", __func__, 1);
1195  ret = freadHeaderPnm(fp, pw, ph, pd, ptype, pbps, pspp);
1196  fclose(fp);
1197  if (ret)
1198  return ERROR_INT("header data read failed", __func__, 1);
1199  return 0;
1200 }
1201 
1202 
1217 l_ok
1218 pixWriteMemPnm(l_uint8 **pdata,
1219  size_t *psize,
1220  PIX *pix)
1221 {
1222 l_int32 ret;
1223 FILE *fp;
1224 
1225  if (pdata) *pdata = NULL;
1226  if (psize) *psize = 0;
1227  if (!pdata)
1228  return ERROR_INT("&data not defined", __func__, 1 );
1229  if (!psize)
1230  return ERROR_INT("&size not defined", __func__, 1 );
1231  if (!pix)
1232  return ERROR_INT("&pix not defined", __func__, 1 );
1233 
1234 #if HAVE_FMEMOPEN
1235  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1236  return ERROR_INT("stream not opened", __func__, 1);
1237  ret = pixWriteStreamPnm(fp, pix);
1238  fputc('\0', fp);
1239  fclose(fp);
1240  *psize = *psize - 1;
1241 #else
1242  L_INFO("work-around: writing to a temp file\n", __func__);
1243  #ifdef _WIN32
1244  if ((fp = fopenWriteWinTempfile()) == NULL)
1245  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1246  #else
1247  if ((fp = tmpfile()) == NULL)
1248  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1249  #endif /* _WIN32 */
1250  ret = pixWriteStreamPnm(fp, pix);
1251  rewind(fp);
1252  *pdata = l_binaryReadStream(fp, psize);
1253  fclose(fp);
1254 #endif /* HAVE_FMEMOPEN */
1255  return ret;
1256 }
1257 
1258 
1273 l_ok
1274 pixWriteMemPam(l_uint8 **pdata,
1275  size_t *psize,
1276  PIX *pix)
1277 {
1278 l_int32 ret;
1279 FILE *fp;
1280 
1281  if (pdata) *pdata = NULL;
1282  if (psize) *psize = 0;
1283  if (!pdata)
1284  return ERROR_INT("&data not defined", __func__, 1 );
1285  if (!psize)
1286  return ERROR_INT("&size not defined", __func__, 1 );
1287  if (!pix)
1288  return ERROR_INT("&pix not defined", __func__, 1 );
1289 
1290 #if HAVE_FMEMOPEN
1291  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1292  return ERROR_INT("stream not opened", __func__, 1);
1293  ret = pixWriteStreamPam(fp, pix);
1294  fputc('\0', fp);
1295  fclose(fp);
1296  *psize = *psize - 1;
1297 #else
1298  L_INFO("work-around: writing to a temp file\n", __func__);
1299  #ifdef _WIN32
1300  if ((fp = fopenWriteWinTempfile()) == NULL)
1301  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1302  #else
1303  if ((fp = tmpfile()) == NULL)
1304  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1305  #endif /* _WIN32 */
1306  ret = pixWriteStreamPam(fp, pix);
1307  rewind(fp);
1308  *pdata = l_binaryReadStream(fp, psize);
1309  fclose(fp);
1310 #endif /* HAVE_FMEMOPEN */
1311  return ret;
1312 }
1313 
1314 
1315 /*--------------------------------------------------------------------*
1316  * Static helpers *
1317  *--------------------------------------------------------------------*/
1326 static l_int32
1328  l_int32 *pval)
1329 {
1330 l_int32 ignore;
1331 
1332  if (!pval)
1333  return ERROR_INT("&val not defined", __func__, 1);
1334  *pval = 0;
1335  if (!fp)
1336  return ERROR_INT("stream not open", __func__, 1);
1337 
1338  if (EOF == fscanf(fp, " "))
1339  return 1;
1340  if (1 != fscanf(fp, "%d", pval))
1341  return 1;
1342 
1343  return 0;
1344 }
1345 
1346 
1362 static l_int32
1364  l_int32 *pval)
1365 {
1366 char buf[8];
1367 l_int32 i, c, foundws;
1368 
1369  if (!pval)
1370  return ERROR_INT("&val not defined", __func__, 1);
1371  *pval = 0;
1372  if (!fp)
1373  return ERROR_INT("stream not open", __func__, 1);
1374 
1375  /* Swallow whitespace */
1376  if (fscanf(fp, " ") == EOF)
1377  return ERROR_INT("end of file reached", __func__, 1);
1378 
1379  /* The ASCII characters for the number are followed by exactly
1380  * one whitespace character. */
1381  foundws = FALSE;
1382  for (i = 0; i < 8; i++)
1383  buf[i] = '\0';
1384  for (i = 0; i < 8; i++) {
1385  if ((c = fgetc(fp)) == EOF)
1386  return ERROR_INT("end of file reached", __func__, 1);
1387  if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
1388  foundws = TRUE;
1389  buf[i] = '\n';
1390  break;
1391  }
1392  if (!isdigit(c))
1393  return ERROR_INT("char read is not a digit", __func__, 1);
1394  buf[i] = c;
1395  }
1396  if (!foundws)
1397  return ERROR_INT("no whitespace found", __func__, 1);
1398  if (sscanf(buf, "%d", pval) != 1)
1399  return ERROR_INT("invalid read", __func__, 1);
1400  return 0;
1401 }
1402 
1418 static l_int32
1420  char *buff,
1421  l_int32 size)
1422 {
1423 char fmtString[7]; /* must contain "%9999s" [*] */
1424 
1425  if (!buff)
1426  return ERROR_INT("buff not defined", __func__, 1);
1427  *buff = '\0';
1428  if (size > 10000) /* size - 1 has > 4 digits [*] */
1429  return ERROR_INT("size is too big", __func__, 1);
1430  if (size <= 0)
1431  return ERROR_INT("size is too small", __func__, 1);
1432  if (!fp)
1433  return ERROR_INT("stream not open", __func__, 1);
1434 
1435  /* Skip whitespace */
1436  if (fscanf(fp, " ") == EOF)
1437  return 1;
1438 
1439  /* Comment lines are allowed to appear anywhere in the header lines */
1440  if (pnmSkipCommentLines(fp))
1441  return ERROR_INT("end of file reached", __func__, 1);
1442 
1443  snprintf(fmtString, 7, "%%%ds", size - 1);
1444  if (fscanf(fp, fmtString, buff) == EOF)
1445  return 1;
1446 
1447  return 0;
1448 }
1449 
1450 
1462 static l_int32
1464 {
1465 l_int32 i;
1466 char c;
1467 
1468  if (!fp)
1469  return ERROR_INT("stream not open", __func__, 1);
1470  while ((i = fscanf(fp, "#%c", &c))) {
1471  if (i == EOF) return 1;
1472  while (c != '\n') {
1473  if (fscanf(fp, "%c", &c) == EOF)
1474  return 1;
1475  }
1476  }
1477  return 0;
1478 }
1479 
1480 
1481 /* --------------------------------------------*/
1482 #endif /* USE_PNMIO */
1483 /* --------------------------------------------*/
#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:1642
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
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:192
l_ok composeRGBAPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel)
composeRGBAPixel()
Definition: pix2.c:2758
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2728
@ COLOR_BLUE
Definition: pix.h:330
@ COLOR_RED
Definition: pix.h:328
@ L_ALPHA_CHANNEL
Definition: pix.h:331
@ COLOR_GREEN
Definition: pix.h:329
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:384
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:324
static l_int32 pnmReadNextNumber(FILE *fp, l_int32 *pval)
pnmReadNextNumber()
Definition: pnmio.c:1363
PIX * pixReadMemPnm(const l_uint8 *data, size_t size)
pixReadMemPnm()
Definition: pnmio.c:1147
static l_int32 pnmReadNextString(FILE *fp, char *buff, l_int32 size)
pnmReadNextString()
Definition: pnmio.c:1419
PIX * pixReadStreamPnm(FILE *fp)
pixReadStreamPnm()
Definition: pnmio.c:150
l_ok pixWriteMemPam(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemPam()
Definition: pnmio.c:1274
l_ok pixWriteStreamPnm(FILE *fp, PIX *pix)
pixWriteStreamPnm()
Definition: pnmio.c:736
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:518
l_ok pixWriteStreamPam(FILE *fp, PIX *pix)
pixWriteStreamPam()
Definition: pnmio.c:973
static l_int32 pnmSkipCommentLines(FILE *fp)
pnmSkipCommentLines()
Definition: pnmio.c:1463
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:1178
static l_int32 pnmReadNextAsciiValue(FILE *fp, l_int32 *pval)
pnmReadNextAsciiValue()
Definition: pnmio.c:1327
l_ok pixWriteStreamAsciiPnm(FILE *fp, PIX *pix)
pixWriteStreamAsciiPnm()
Definition: pnmio.c:853
l_ok pixWriteMemPnm(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemPnm()
Definition: pnmio.c:1218
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:559
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:1358
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:1937
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:1981
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1864