Leptonica  1.77.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 
113 #ifdef HAVE_CONFIG_H
114 #include "config_auto.h"
115 #endif /* HAVE_CONFIG_H */
116 
117 #include <string.h>
118 #include <ctype.h>
119 #include "allheaders.h"
120 
121 /* --------------------------------------------*/
122 #if USE_PNMIO /* defined in environ.h */
123 /* --------------------------------------------*/
124 
125 static l_int32 pnmReadNextAsciiValue(FILE *fp, l_int32 *pval);
126 static l_int32 pnmReadNextNumber(FILE *fp, l_int32 *pval);
127 static l_int32 pnmReadNextString(FILE *fp, char *buff, l_int32 size);
128 static l_int32 pnmSkipCommentLines(FILE *fp);
129 
130  /* a sanity check on the size read from file */
131 static const l_int32 MAX_PNM_WIDTH = 100000;
132 static const l_int32 MAX_PNM_HEIGHT = 100000;
133 
134 
135 /*--------------------------------------------------------------------*
136  * Stream interface *
137  *--------------------------------------------------------------------*/
144 PIX *
146 {
147 l_uint8 val8, rval8, gval8, bval8, aval8, mask8;
148 l_uint16 val16, rval16, gval16, bval16, aval16, mask16;
149 l_int32 w, h, d, bps, spp, bpl, wpl, i, j, type;
150 l_int32 val, rval, gval, bval;
151 l_uint32 rgbval;
152 l_uint32 *line, *data;
153 PIX *pix;
154 
155  PROCNAME("pixReadStreamPnm");
156 
157  if (!fp)
158  return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
159 
160  if (freadHeaderPnm(fp, &w, &h, &d, &type, &bps, &spp))
161  return (PIX *)ERROR_PTR( "header read failed", procName, NULL);
162  if (bps < 1 || bps > 16)
163  return (PIX *)ERROR_PTR( "invalid bps", procName, NULL);
164  if (spp < 1 || spp > 4)
165  return (PIX *)ERROR_PTR( "invalid spp", procName, NULL);
166  if ((pix = pixCreate(w, h, d)) == NULL)
167  return (PIX *)ERROR_PTR( "pix not made", procName, NULL);
168  pixSetInputFormat(pix, IFF_PNM);
169  data = pixGetData(pix);
170  wpl = pixGetWpl(pix);
171 
172  switch (type) {
173  case 1:
174  case 2:
175  /* Old "ASCII" binary or gray format */
176  for (i = 0; i < h; i++) {
177  for (j = 0; j < w; j++) {
178  if (pnmReadNextAsciiValue(fp, &val))
179  return (PIX *)ERROR_PTR( "read abend", procName, pix);
180  pixSetPixel(pix, j, i, val);
181  }
182  }
183  break;
184 
185  case 3:
186  /* Old "ASCII" rgb format */
187  for (i = 0; i < h; i++) {
188  for (j = 0; j < w; j++) {
189  if (pnmReadNextAsciiValue(fp, &rval))
190  return (PIX *)ERROR_PTR("read abend", procName, pix);
191  if (pnmReadNextAsciiValue(fp, &gval))
192  return (PIX *)ERROR_PTR("read abend", procName, pix);
193  if (pnmReadNextAsciiValue(fp, &bval))
194  return (PIX *)ERROR_PTR("read abend", procName, pix);
195  composeRGBPixel(rval, gval, bval, &rgbval);
196  pixSetPixel(pix, j, i, rgbval);
197  }
198  }
199  break;
200 
201  case 4:
202  /* "raw" format for 1 bpp */
203  bpl = (d * w + 7) / 8;
204  for (i = 0; i < h; i++) {
205  line = data + i * wpl;
206  for (j = 0; j < bpl; j++) {
207  if (fread(&val8, 1, 1, fp) != 1)
208  return (PIX *)ERROR_PTR("read error in 4", procName, pix);
209  SET_DATA_BYTE(line, j, val8);
210  }
211  }
212  break;
213 
214  case 5:
215  /* "raw" format for grayscale */
216  for (i = 0; i < h; i++) {
217  line = data + i * wpl;
218  if (d != 16) {
219  for (j = 0; j < w; j++) {
220  if (fread(&val8, 1, 1, fp) != 1)
221  return (PIX *)ERROR_PTR("error in 5", procName, pix);
222  if (d == 2)
223  SET_DATA_DIBIT(line, j, val8);
224  else if (d == 4)
225  SET_DATA_QBIT(line, j, val8);
226  else /* d == 8 */
227  SET_DATA_BYTE(line, j, val8);
228  }
229  } else { /* d == 16 */
230  for (j = 0; j < w; j++) {
231  if (fread(&val16, 2, 1, fp) != 1)
232  return (PIX *)ERROR_PTR("16 bpp error", procName, pix);
233  SET_DATA_TWO_BYTES(line, j, val16);
234  }
235  }
236  }
237  break;
238 
239  case 6:
240  /* "raw" format, type == 6; rgb */
241  for (i = 0; i < h; i++) {
242  line = data + i * wpl;
243  for (j = 0; j < wpl; j++) {
244  if (fread(&rval8, 1, 1, fp) != 1)
245  return (PIX *)ERROR_PTR("read error type 6",
246  procName, pix);
247  if (fread(&gval8, 1, 1, fp) != 1)
248  return (PIX *)ERROR_PTR("read error type 6",
249  procName, pix);
250  if (fread(&bval8, 1, 1, fp) != 1)
251  return (PIX *)ERROR_PTR("read error type 6",
252  procName, pix);
253  composeRGBPixel(rval8, gval8, bval8, &rgbval);
254  line[j] = rgbval;
255  }
256  }
257  pixSetSpp(pix, 4);
258  break;
259 
260  case 7:
261  /* "arbitrary" format; type == 7; */
262  if (bps != 16) {
263  mask8 = (1 << bps) - 1;
264  switch (spp) {
265  case 1: /* 1, 2, 4, 8 bpp grayscale */
266  for (i = 0; i < h; i++) {
267  for (j = 0; j < w; j++) {
268  if (fread(&val8, 1, 1, fp) != 1)
269  return (PIX *)ERROR_PTR("read error type 7",
270  procName, pix);
271  val8 = val8 & mask8;
272  if (bps == 1) val8 ^= 1; /* white-is-1 photometry */
273  pixSetPixel(pix, j, i, val8);
274  }
275  }
276  break;
277 
278  case 2: /* 1, 2, 4, 8 bpp grayscale + alpha */
279  for (i = 0; i < h; i++) {
280  for (j = 0; j < w; j++) {
281  if (fread(&val8, 1, 1, fp) != 1)
282  return (PIX *)ERROR_PTR("read error type 7",
283  procName, pix);
284  if (fread(&aval8, 1, 1, fp) != 1)
285  return (PIX *)ERROR_PTR("read error type 7",
286  procName, pix);
287  val8 = val8 & mask8;
288  aval8 = aval8 & mask8;
289  composeRGBAPixel(val8, val8, val8, aval8, &rgbval);
290  pixSetPixel(pix, j, i, rgbval);
291  }
292  }
293  pixSetSpp(pix, 4);
294  break;
295 
296  case 3: /* rgb */
297  for (i = 0; i < h; i++) {
298  line = data + i * wpl;
299  for (j = 0; j < wpl; j++) {
300  if (fread(&rval8, 1, 1, fp) != 1)
301  return (PIX *)ERROR_PTR("read error type 7",
302  procName, pix);
303  if (fread(&gval8, 1, 1, fp) != 1)
304  return (PIX *)ERROR_PTR("read error type 7",
305  procName, pix);
306  if (fread(&bval8, 1, 1, fp) != 1)
307  return (PIX *)ERROR_PTR("read error type 7",
308  procName, pix);
309  rval8 = rval8 & mask8;
310  gval8 = gval8 & mask8;
311  bval8 = bval8 & mask8;
312  composeRGBPixel(rval8, gval8, bval8, &rgbval);
313  line[j] = rgbval;
314  }
315  }
316  break;
317 
318  case 4: /* rgba */
319  for (i = 0; i < h; i++) {
320  line = data + i * wpl;
321  for (j = 0; j < wpl; j++) {
322  if (fread(&rval8, 1, 1, fp) != 1)
323  return (PIX *)ERROR_PTR("read error type 7",
324  procName, pix);
325  if (fread(&gval8, 1, 1, fp) != 1)
326  return (PIX *)ERROR_PTR("read error type 7",
327  procName, pix);
328  if (fread(&bval8, 1, 1, fp) != 1)
329  return (PIX *)ERROR_PTR("read error type 7",
330  procName, pix);
331  if (fread(&aval8, 1, 1, fp) != 1)
332  return (PIX *)ERROR_PTR("read error type 7",
333  procName, pix);
334  rval8 = rval8 & mask8;
335  gval8 = gval8 & mask8;
336  bval8 = bval8 & mask8;
337  aval8 = aval8 & mask8;
338  composeRGBAPixel(rval8, gval8, bval8, aval8, &rgbval);
339  line[j] = rgbval;
340  }
341  }
342  pixSetSpp(pix, 4);
343  break;
344  }
345  } else { /* bps == 16 */
346  mask16 = (1 << 16) - 1;
347  switch (spp) {
348  case 1: /* 16 bpp grayscale */
349  for (i = 0; i < h; i++) {
350  for (j = 0; j < w; j++) {
351  if (fread(&val16, 2, 1, fp) != 1)
352  return (PIX *)ERROR_PTR("read error type 7",
353  procName, pix);
354  val8 = (val16 & mask16) >> 8;
355  pixSetPixel(pix, j, i, val8);
356  }
357  }
358  break;
359 
360  case 2: /* 16 bpp grayscale + alpha */
361  for (i = 0; i < h; i++) {
362  for (j = 0; j < w; j++) {
363  if (fread(&val16, 2, 1, fp) != 1)
364  return (PIX *)ERROR_PTR("read error type 7",
365  procName, pix);
366  if (fread(&aval16, 2, 1, fp) != 1)
367  return (PIX *)ERROR_PTR("read error type 7",
368  procName, pix);
369  val8 = (val16 & mask16) >> 8;
370  aval8 = (aval16 & mask16) >> 8;
371  composeRGBAPixel(val8, val8, val8, aval8, &rgbval);
372  pixSetPixel(pix, j, i, rgbval);
373  }
374  }
375  pixSetSpp(pix, 4);
376  break;
377 
378  case 3: /* 16bpp rgb */
379  for (i = 0; i < h; i++) {
380  line = data + i * wpl;
381  for (j = 0; j < wpl; j++) {
382  if (fread(&rval16, 2, 1, fp) != 1)
383  return (PIX *)ERROR_PTR("read error type 7",
384  procName, pix);
385  if (fread(&gval16, 2, 1, fp) != 1)
386  return (PIX *)ERROR_PTR("read error type 7",
387  procName, pix);
388  if (fread(&bval16, 2, 1, fp) != 1)
389  return (PIX *)ERROR_PTR("read error type 7",
390  procName, pix);
391  rval8 = (rval16 & mask16) >> 8;
392  gval8 = (gval16 & mask16) >> 8;
393  bval8 = (bval16 & mask16) >> 8;
394  composeRGBPixel(rval8, gval8, bval8, &rgbval);
395  line[j] = rgbval;
396  }
397  }
398  break;
399 
400  case 4: /* 16bpp rgba */
401  for (i = 0; i < h; i++) {
402  line = data + i * wpl;
403  for (j = 0; j < wpl; j++) {
404  if (fread(&rval16, 2, 1, fp) != 1)
405  return (PIX *)ERROR_PTR("read error type 7",
406  procName, pix);
407  if (fread(&gval16, 2, 1, fp) != 1)
408  return (PIX *)ERROR_PTR("read error type 7",
409  procName, pix);
410  if (fread(&bval16, 2, 1, fp) != 1)
411  return (PIX *)ERROR_PTR("read error type 7",
412  procName, pix);
413  if (fread(&aval16, 2, 1, fp) != 1)
414  return (PIX *)ERROR_PTR("read error type 7",
415  procName, pix);
416  rval8 = (rval16 & mask16) >> 8;
417  gval8 = (gval16 & mask16) >> 8;
418  bval8 = (bval16 & mask16) >> 8;
419  aval8 = (aval16 & mask16) >> 8;
420  composeRGBAPixel(rval8, gval8, bval8, aval8, &rgbval);
421  line[j] = rgbval;
422  }
423  }
424  pixSetSpp(pix, 4);
425  break;
426  }
427  }
428  break;
429  }
430  return pix;
431 }
432 
433 
446 l_ok
447 readHeaderPnm(const char *filename,
448  l_int32 *pw,
449  l_int32 *ph,
450  l_int32 *pd,
451  l_int32 *ptype,
452  l_int32 *pbps,
453  l_int32 *pspp)
454 {
455 l_int32 ret;
456 FILE *fp;
457 
458  PROCNAME("readHeaderPnm");
459 
460  if (pw) *pw = 0;
461  if (ph) *ph = 0;
462  if (pd) *pd = 0;
463  if (ptype) *ptype = 0;
464  if (pbps) *pbps = 0;
465  if (pspp) *pspp = 0;
466  if (!filename)
467  return ERROR_INT("filename not defined", procName, 1);
468 
469  if ((fp = fopenReadStream(filename)) == NULL)
470  return ERROR_INT("image file not found", procName, 1);
471  ret = freadHeaderPnm(fp, pw, ph, pd, ptype, pbps, pspp);
472  fclose(fp);
473  return ret;
474 }
475 
476 
489 l_ok
490 freadHeaderPnm(FILE *fp,
491  l_int32 *pw,
492  l_int32 *ph,
493  l_int32 *pd,
494  l_int32 *ptype,
495  l_int32 *pbps,
496  l_int32 *pspp)
497 {
498 char tag[16], tupltype[32];
499 l_int32 i, w, h, d, bps, spp, type;
500 l_int32 maxval;
501 l_int32 ch;
502 
503  PROCNAME("freadHeaderPnm");
504 
505  if (pw) *pw = 0;
506  if (ph) *ph = 0;
507  if (pd) *pd = 0;
508  if (ptype) *ptype = 0;
509  if (pbps) *pbps = 0;
510  if (pspp) *pspp = 0;
511  if (!fp)
512  return ERROR_INT("fp not defined", procName, 1);
513 
514  if (fscanf(fp, "P%d\n", &type) != 1)
515  return ERROR_INT("invalid read for type", procName, 1);
516  if (type < 1 || type > 7)
517  return ERROR_INT("invalid pnm file", procName, 1);
518 
519  if (pnmSkipCommentLines(fp))
520  return ERROR_INT("no data in file", procName, 1);
521 
522  if (type == 7) {
523  w = h = d = bps = spp = maxval = 0;
524  for (i = 0; i < 10; i++) { /* limit to 10 lines of this header */
525  if (pnmReadNextString(fp, tag, sizeof(tag)))
526  return ERROR_INT("found no next tag", procName, 1);
527  if (!strcmp(tag, "WIDTH")) {
528  if (pnmReadNextNumber(fp, &w))
529  return ERROR_INT("failed reading width", procName, 1);
530  continue;
531  }
532  if (!strcmp(tag, "HEIGHT")) {
533  if (pnmReadNextNumber(fp, &h))
534  return ERROR_INT("failed reading height", procName, 1);
535  continue;
536  }
537  if (!strcmp(tag, "DEPTH")) {
538  if (pnmReadNextNumber(fp, &spp))
539  return ERROR_INT("failed reading depth", procName, 1);
540  continue;
541  }
542  if (!strcmp(tag, "MAXVAL")) {
543  if (pnmReadNextNumber(fp, &maxval))
544  return ERROR_INT("failed reading maxval", procName, 1);
545  continue;
546  }
547  if (!strcmp(tag, "TUPLTYPE")) {
548  if (pnmReadNextString(fp, tupltype, sizeof(tupltype)))
549  return ERROR_INT("failed reading tuple type", procName, 1);
550  continue;
551  }
552  if (!strcmp(tag, "ENDHDR")) {
553  if ('\n' != (ch = fgetc(fp)))
554  return ERROR_INT("missing LF after ENDHDR", procName, 1);
555  break;
556  }
557  }
558  if (w <= 0 || h <= 0 || w > MAX_PNM_WIDTH || h > MAX_PNM_HEIGHT) {
559  L_INFO("invalid size: w = %d, h = %d\n", procName, w, h);
560  return 1;
561  }
562  if (maxval == 1) {
563  d = bps = 1;
564  } else if (maxval == 3) {
565  d = bps = 2;
566  } else if (maxval == 15) {
567  d = bps = 4;
568  } else if (maxval == 255) {
569  d = bps = 8;
570  } else if (maxval == 0xffff) {
571  d = bps = 16;
572  } else {
573  L_INFO("invalid maxval = %d\n", procName, maxval);
574  return 1;
575  }
576  switch (spp) {
577  case 1:
578  /* d and bps are already set */
579  break;
580  case 2:
581  case 3:
582  case 4:
583  /* create a 32 bpp Pix */
584  d = 32;
585  break;
586  default:
587  L_INFO("invalid depth = %d\n", procName, spp);
588  return 1;
589  }
590  } else {
591 
592  if (fscanf(fp, "%d %d\n", &w, &h) != 2)
593  return ERROR_INT("invalid read for w,h", procName, 1);
594  if (w <= 0 || h <= 0 || w > MAX_PNM_WIDTH || h > MAX_PNM_HEIGHT) {
595  L_INFO("invalid size: w = %d, h = %d\n", procName, w, h);
596  return 1;
597  }
598 
599  /* Get depth of pix. For types 2 and 5, we use the maxval.
600  * Important implementation note:
601  * - You can't use fscanf(), which throws away whitespace,
602  * and will discard binary data if it starts with whitespace(s).
603  * - You can't use fgets(), which stops at newlines, but this
604  * dumb format doesn't require a newline after the maxval
605  * number -- it just requires one whitespace character.
606  * - Which leaves repeated calls to fgetc, including swallowing
607  * the single whitespace character. */
608  if (type == 1 || type == 4) {
609  d = 1;
610  spp = 1;
611  bps = 1;
612  } else if (type == 2 || type == 5) {
613  if (pnmReadNextNumber(fp, &maxval))
614  return ERROR_INT("invalid read for maxval (2,5)", procName, 1);
615  if (maxval == 3) {
616  d = 2;
617  } else if (maxval == 15) {
618  d = 4;
619  } else if (maxval == 255) {
620  d = 8;
621  } else if (maxval == 0xffff) {
622  d = 16;
623  } else {
624  fprintf(stderr, "maxval = %d\n", maxval);
625  return ERROR_INT("invalid maxval", procName, 1);
626  }
627  bps = d;
628  spp = 1;
629  } else { /* type == 3 || type == 6; this is rgb */
630  if (pnmReadNextNumber(fp, &maxval))
631  return ERROR_INT("invalid read for maxval (3,6)", procName, 1);
632  if (maxval != 255)
633  L_WARNING("unexpected maxval = %d\n", procName, maxval);
634  d = 32;
635  spp = 3;
636  bps = 8;
637  }
638  }
639  if (pw) *pw = w;
640  if (ph) *ph = h;
641  if (pd) *pd = d;
642  if (ptype) *ptype = type;
643  if (pbps) *pbps = bps;
644  if (pspp) *pspp = spp;
645  return 0;
646 }
647 
648 
666 l_ok
668  PIX *pix)
669 {
670 l_uint8 val8;
671 l_uint8 pel[4];
672 l_uint16 val16;
673 l_int32 h, w, d, ds, i, j, wpls, bpl, filebpl, writeerror, maxval;
674 l_uint32 *pword, *datas, *lines;
675 PIX *pixs;
676 
677  PROCNAME("pixWriteStreamPnm");
678 
679  if (!fp)
680  return ERROR_INT("fp not defined", procName, 1);
681  if (!pix)
682  return ERROR_INT("pix not defined", procName, 1);
683 
684  pixGetDimensions(pix, &w, &h, &d);
685  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
686  return ERROR_INT("d not in {1,2,4,8,16,24,32}", procName, 1);
687  if (d == 32 && pixGetSpp(pix) == 4)
688  return pixWriteStreamPam(fp, pix);
689 
690  /* If a colormap exists, remove and convert to grayscale or rgb */
691  if (pixGetColormap(pix) != NULL)
693  else
694  pixs = pixClone(pix);
695  ds = pixGetDepth(pixs);
696  datas = pixGetData(pixs);
697  wpls = pixGetWpl(pixs);
698 
699  writeerror = 0;
700 
701  if (ds == 1) { /* binary */
702  fprintf(fp, "P4\n# Raw PBM file written by leptonica "
703  "(www.leptonica.com)\n%d %d\n", w, h);
704 
705  bpl = (w + 7) / 8;
706  for (i = 0; i < h; i++) {
707  lines = datas + i * wpls;
708  for (j = 0; j < bpl; j++) {
709  val8 = GET_DATA_BYTE(lines, j);
710  fwrite(&val8, 1, 1, fp);
711  }
712  }
713  } else if (ds == 2 || ds == 4 || ds == 8 || ds == 16) { /* grayscale */
714  maxval = (1 << ds) - 1;
715  fprintf(fp, "P5\n# Raw PGM file written by leptonica "
716  "(www.leptonica.com)\n%d %d\n%d\n", w, h, maxval);
717 
718  if (ds != 16) {
719  for (i = 0; i < h; i++) {
720  lines = datas + i * wpls;
721  for (j = 0; j < w; j++) {
722  if (ds == 2)
723  val8 = GET_DATA_DIBIT(lines, j);
724  else if (ds == 4)
725  val8 = GET_DATA_QBIT(lines, j);
726  else /* ds == 8 */
727  val8 = GET_DATA_BYTE(lines, j);
728  fwrite(&val8, 1, 1, fp);
729  }
730  }
731  } else { /* ds == 16 */
732  for (i = 0; i < h; i++) {
733  lines = datas + i * wpls;
734  for (j = 0; j < w; j++) {
735  val16 = GET_DATA_TWO_BYTES(lines, j);
736  fwrite(&val16, 2, 1, fp);
737  }
738  }
739  }
740  } else { /* rgb color */
741  fprintf(fp, "P6\n# Raw PPM file written by leptonica "
742  "(www.leptonica.com)\n%d %d\n255\n", w, h);
743 
744  if (d == 24) { /* packed, 3 bytes to a pixel */
745  filebpl = 3 * w;
746  for (i = 0; i < h; i++) { /* write out each raster line */
747  lines = datas + i * wpls;
748  if (fwrite(lines, 1, filebpl, fp) != filebpl)
749  writeerror = 1;
750  }
751  } else { /* 32 bpp rgb */
752  for (i = 0; i < h; i++) {
753  lines = datas + i * wpls;
754  for (j = 0; j < wpls; j++) {
755  pword = lines + j;
756  pel[0] = GET_DATA_BYTE(pword, COLOR_RED);
757  pel[1] = GET_DATA_BYTE(pword, COLOR_GREEN);
758  pel[2] = GET_DATA_BYTE(pword, COLOR_BLUE);
759  if (fwrite(pel, 1, 3, fp) != 3)
760  writeerror = 1;
761  }
762  }
763  }
764  }
765 
766  pixDestroy(&pixs);
767  if (writeerror)
768  return ERROR_INT("image write fail", procName, 1);
769  return 0;
770 }
771 
772 
785 l_ok
787  PIX *pix)
788 {
789 char buffer[256];
790 l_uint8 cval[3];
791 l_int32 h, w, d, ds, i, j, k, maxval, count;
792 l_uint32 val;
793 PIX *pixs;
794 
795  PROCNAME("pixWriteStreamAsciiPnm");
796 
797  if (!fp)
798  return ERROR_INT("fp not defined", procName, 1);
799  if (!pix)
800  return ERROR_INT("pix not defined", procName, 1);
801 
802  pixGetDimensions(pix, &w, &h, &d);
803  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
804  return ERROR_INT("d not in {1,2,4,8,16,32}", procName, 1);
805 
806  /* If a colormap exists, remove and convert to grayscale or rgb */
807  if (pixGetColormap(pix) != NULL)
809  else
810  pixs = pixClone(pix);
811  ds = pixGetDepth(pixs);
812 
813  if (ds == 1) { /* binary */
814  fprintf(fp, "P1\n# Ascii PBM file written by leptonica "
815  "(www.leptonica.com)\n%d %d\n", w, h);
816 
817  count = 0;
818  for (i = 0; i < h; i++) {
819  for (j = 0; j < w; j++) {
820  pixGetPixel(pixs, j, i, &val);
821  if (val == 0)
822  fputc('0', fp);
823  else /* val == 1 */
824  fputc('1', fp);
825  fputc(' ', fp);
826  count += 2;
827  if (count >= 70) {
828  fputc('\n', fp);
829  count = 0;
830  }
831  }
832  }
833  } else if (ds == 2 || ds == 4 || ds == 8 || ds == 16) { /* grayscale */
834  maxval = (1 << ds) - 1;
835  fprintf(fp, "P2\n# Ascii PGM file written by leptonica "
836  "(www.leptonica.com)\n%d %d\n%d\n", w, h, maxval);
837 
838  count = 0;
839  for (i = 0; i < h; i++) {
840  for (j = 0; j < w; j++) {
841  pixGetPixel(pixs, j, i, &val);
842  if (ds == 2) {
843  snprintf(buffer, sizeof(buffer), "%1d ", val);
844  fwrite(buffer, 1, 2, fp);
845  count += 2;
846  } else if (ds == 4) {
847  snprintf(buffer, sizeof(buffer), "%2d ", val);
848  fwrite(buffer, 1, 3, fp);
849  count += 3;
850  } else if (ds == 8) {
851  snprintf(buffer, sizeof(buffer), "%3d ", val);
852  fwrite(buffer, 1, 4, fp);
853  count += 4;
854  } else { /* ds == 16 */
855  snprintf(buffer, sizeof(buffer), "%5d ", val);
856  fwrite(buffer, 1, 6, fp);
857  count += 6;
858  }
859  if (count >= 60) {
860  fputc('\n', fp);
861  count = 0;
862  }
863  }
864  }
865  } else { /* rgb color */
866  fprintf(fp, "P3\n# Ascii PPM file written by leptonica "
867  "(www.leptonica.com)\n%d %d\n255\n", w, h);
868  count = 0;
869  for (i = 0; i < h; i++) {
870  for (j = 0; j < w; j++) {
871  pixGetPixel(pixs, j, i, &val);
872  cval[0] = GET_DATA_BYTE(&val, COLOR_RED);
873  cval[1] = GET_DATA_BYTE(&val, COLOR_GREEN);
874  cval[2] = GET_DATA_BYTE(&val, COLOR_BLUE);
875  for (k = 0; k < 3; k++) {
876  snprintf(buffer, sizeof(buffer), "%3d ", cval[k]);
877  fwrite(buffer, 1, 4, fp);
878  count += 4;
879  if (count >= 60) {
880  fputc('\n', fp);
881  count = 0;
882  }
883  }
884  }
885  }
886  }
887 
888  pixDestroy(&pixs);
889  return 0;
890 }
891 
892 
907 l_ok
909  PIX *pix)
910 {
911 l_uint8 val8;
912 l_uint8 pel[8];
913 l_uint16 val16;
914 l_int32 h, w, d, ds, i, j;
915 l_int32 wpls, spps, filebpl, writeerror, maxval;
916 l_uint32 *pword, *datas, *lines;
917 PIX *pixs;
918 
919  PROCNAME("pixWriteStreamPam");
920 
921  if (!fp)
922  return ERROR_INT("fp not defined", procName, 1);
923  if (!pix)
924  return ERROR_INT("pix not defined", procName, 1);
925 
926  pixGetDimensions(pix, &w, &h, &d);
927  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
928  return ERROR_INT("d not in {1,2,4,8,16,24,32}", procName, 1);
929 
930  /* If a colormap exists, remove and convert to grayscale or rgb */
931  if (pixGetColormap(pix) != NULL)
933  else
934  pixs = pixClone(pix);
935  ds = pixGetDepth(pixs);
936  datas = pixGetData(pixs);
937  wpls = pixGetWpl(pixs);
938  spps = pixGetSpp(pixs);
939  if (ds < 24)
940  maxval = (1 << ds) - 1;
941  else
942  maxval = 255;
943 
944  writeerror = 0;
945  fprintf(fp, "P7\n# Arbitrary PAM file written by leptonica "
946  "(www.leptonica.com)\n");
947  fprintf(fp, "WIDTH %d\n", w);
948  fprintf(fp, "HEIGHT %d\n", h);
949  fprintf(fp, "DEPTH %d\n", spps);
950  fprintf(fp, "MAXVAL %d\n", maxval);
951  if (spps == 1 && ds == 1)
952  fprintf(fp, "TUPLTYPE BLACKANDWHITE\n");
953  else if (spps == 1)
954  fprintf(fp, "TUPLTYPE GRAYSCALE\n");
955  else if (spps == 3)
956  fprintf(fp, "TUPLTYPE RGB\n");
957  else if (spps == 4)
958  fprintf(fp, "TUPLTYPE RGB_ALPHA\n");
959  fprintf(fp, "ENDHDR\n");
960 
961  switch (d) {
962  case 1:
963  for (i = 0; i < h; i++) {
964  lines = datas + i * wpls;
965  for (j = 0; j < w; j++) {
966  val8 = GET_DATA_BIT(lines, j);
967  val8 ^= 1; /* pam apparently uses white-is-1 photometry */
968  if (fwrite(&val8, 1, 1, fp) != 1)
969  writeerror = 1;
970  }
971  }
972  break;
973 
974  case 2:
975  for (i = 0; i < h; i++) {
976  lines = datas + i * wpls;
977  for (j = 0; j < w; j++) {
978  val8 = GET_DATA_DIBIT(lines, j);
979  if (fwrite(&val8, 1, 1, fp) != 1)
980  writeerror = 1;
981  }
982  }
983  break;
984 
985  case 4:
986  for (i = 0; i < h; i++) {
987  lines = datas + i * wpls;
988  for (j = 0; j < w; j++) {
989  val8 = GET_DATA_QBIT(lines, j);
990  if (fwrite(&val8, 1, 1, fp) != 1)
991  writeerror = 1;
992  }
993  }
994  break;
995 
996  case 8:
997  for (i = 0; i < h; i++) {
998  lines = datas + i * wpls;
999  for (j = 0; j < w; j++) {
1000  val8 = GET_DATA_BYTE(lines, j);
1001  if (fwrite(&val8, 1, 1, fp) != 1)
1002  writeerror = 1;
1003  }
1004  }
1005  break;
1006 
1007  case 16:
1008  for (i = 0; i < h; i++) {
1009  lines = datas + i * wpls;
1010  for (j = 0; j < w; j++) {
1011  val16 = GET_DATA_TWO_BYTES(lines, j);
1012  if (fwrite(&val16, 2, 1, fp) != 1)
1013  writeerror = 1;
1014  }
1015  }
1016  break;
1017 
1018  case 24:
1019  filebpl = 3 * w;
1020  for (i = 0; i < h; i++) {
1021  lines = datas + i * wpls;
1022  if (fwrite(lines, 1, filebpl, fp) != filebpl)
1023  writeerror = 1;
1024  }
1025  break;
1026 
1027  case 32:
1028  switch (spps) {
1029  case 3:
1030  for (i = 0; i < h; i++) {
1031  lines = datas + i * wpls;
1032  for (j = 0; j < wpls; j++) {
1033  pword = lines + j;
1034  pel[0] = GET_DATA_BYTE(pword, COLOR_RED);
1035  pel[1] = GET_DATA_BYTE(pword, COLOR_GREEN);
1036  pel[2] = GET_DATA_BYTE(pword, COLOR_BLUE);
1037  if (fwrite(pel, 1, 3, fp) != 3)
1038  writeerror = 1;
1039  }
1040  }
1041  break;
1042  case 4:
1043  for (i = 0; i < h; i++) {
1044  lines = datas + i * wpls;
1045  for (j = 0; j < wpls; j++) {
1046  pword = lines + j;
1047  pel[0] = GET_DATA_BYTE(pword, COLOR_RED);
1048  pel[1] = GET_DATA_BYTE(pword, COLOR_GREEN);
1049  pel[2] = GET_DATA_BYTE(pword, COLOR_BLUE);
1050  pel[3] = GET_DATA_BYTE(pword, L_ALPHA_CHANNEL);
1051  if (fwrite(pel, 1, 4, fp) != 4)
1052  writeerror = 1;
1053  }
1054  }
1055  break;
1056  }
1057  break;
1058  }
1059 
1060  pixDestroy(&pixs);
1061  if (writeerror)
1062  return ERROR_INT("image write fail", procName, 1);
1063  return 0;
1064 }
1065 
1066 
1067 /*---------------------------------------------------------------------*
1068  * Read/write to memory *
1069  *---------------------------------------------------------------------*/
1070 
1083 PIX *
1084 pixReadMemPnm(const l_uint8 *data,
1085  size_t size)
1086 {
1087 FILE *fp;
1088 PIX *pix;
1089 
1090  PROCNAME("pixReadMemPnm");
1091 
1092  if (!data)
1093  return (PIX *)ERROR_PTR("data not defined", procName, NULL);
1094  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1095  return (PIX *)ERROR_PTR("stream not opened", procName, NULL);
1096  pix = pixReadStreamPnm(fp);
1097  fclose(fp);
1098  if (!pix) L_ERROR("pix not read\n", procName);
1099  return pix;
1100 }
1101 
1102 
1116 l_ok
1117 readHeaderMemPnm(const l_uint8 *data,
1118  size_t size,
1119  l_int32 *pw,
1120  l_int32 *ph,
1121  l_int32 *pd,
1122  l_int32 *ptype,
1123  l_int32 *pbps,
1124  l_int32 *pspp)
1125 {
1126 l_int32 ret;
1127 FILE *fp;
1128 
1129  PROCNAME("readHeaderMemPnm");
1130 
1131  if (!data)
1132  return ERROR_INT("data not defined", procName, 1);
1133 
1134  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1135  return ERROR_INT("stream not opened", procName, 1);
1136  ret = freadHeaderPnm(fp, pw, ph, pd, ptype, pbps, pspp);
1137  fclose(fp);
1138  if (ret)
1139  return ERROR_INT("header data read failed", procName, 1);
1140  return 0;
1141 }
1142 
1143 
1158 l_ok
1159 pixWriteMemPnm(l_uint8 **pdata,
1160  size_t *psize,
1161  PIX *pix)
1162 {
1163 l_int32 ret;
1164 FILE *fp;
1165 
1166  PROCNAME("pixWriteMemPnm");
1167 
1168  if (pdata) *pdata = NULL;
1169  if (psize) *psize = 0;
1170  if (!pdata)
1171  return ERROR_INT("&data not defined", procName, 1 );
1172  if (!psize)
1173  return ERROR_INT("&size not defined", procName, 1 );
1174  if (!pix)
1175  return ERROR_INT("&pix not defined", procName, 1 );
1176 
1177 #if HAVE_FMEMOPEN
1178  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1179  return ERROR_INT("stream not opened", procName, 1);
1180  ret = pixWriteStreamPnm(fp, pix);
1181 #else
1182  L_INFO("work-around: writing to a temp file\n", procName);
1183  #ifdef _WIN32
1184  if ((fp = fopenWriteWinTempfile()) == NULL)
1185  return ERROR_INT("tmpfile stream not opened", procName, 1);
1186  #else
1187  if ((fp = tmpfile()) == NULL)
1188  return ERROR_INT("tmpfile stream not opened", procName, 1);
1189  #endif /* _WIN32 */
1190  ret = pixWriteStreamPnm(fp, pix);
1191  rewind(fp);
1192  *pdata = l_binaryReadStream(fp, psize);
1193 #endif /* HAVE_FMEMOPEN */
1194  fclose(fp);
1195  return ret;
1196 }
1197 
1198 
1213 l_ok
1214 pixWriteMemPam(l_uint8 **pdata,
1215  size_t *psize,
1216  PIX *pix)
1217 {
1218 l_int32 ret;
1219 FILE *fp;
1220 
1221  PROCNAME("pixWriteMemPam");
1222 
1223  if (pdata) *pdata = NULL;
1224  if (psize) *psize = 0;
1225  if (!pdata)
1226  return ERROR_INT("&data not defined", procName, 1 );
1227  if (!psize)
1228  return ERROR_INT("&size not defined", procName, 1 );
1229  if (!pix)
1230  return ERROR_INT("&pix not defined", procName, 1 );
1231 
1232 #if HAVE_FMEMOPEN
1233  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1234  return ERROR_INT("stream not opened", procName, 1);
1235  ret = pixWriteStreamPam(fp, pix);
1236 #else
1237  L_INFO("work-around: writing to a temp file\n", procName);
1238  #ifdef _WIN32
1239  if ((fp = fopenWriteWinTempfile()) == NULL)
1240  return ERROR_INT("tmpfile stream not opened", procName, 1);
1241  #else
1242  if ((fp = tmpfile()) == NULL)
1243  return ERROR_INT("tmpfile stream not opened", procName, 1);
1244  #endif /* _WIN32 */
1245  ret = pixWriteStreamPam(fp, pix);
1246  rewind(fp);
1247  *pdata = l_binaryReadStream(fp, psize);
1248 #endif /* HAVE_FMEMOPEN */
1249  fclose(fp);
1250  return ret;
1251 }
1252 
1253 
1254 
1255 /*--------------------------------------------------------------------*
1256  * Static helpers *
1257  *--------------------------------------------------------------------*/
1266 static l_int32
1268  l_int32 *pval)
1269 {
1270 l_int32 c, ignore;
1271 
1272  PROCNAME("pnmReadNextAsciiValue");
1273 
1274  if (!pval)
1275  return ERROR_INT("&val not defined", procName, 1);
1276  *pval = 0;
1277  if (!fp)
1278  return ERROR_INT("stream not open", procName, 1);
1279  do { /* skip whitespace */
1280  if ((c = fgetc(fp)) == EOF)
1281  return 1;
1282  } while (c == ' ' || c == '\t' || c == '\n' || c == '\r');
1283 
1284  fseek(fp, -1L, SEEK_CUR); /* back up one byte */
1285  ignore = fscanf(fp, "%d", pval);
1286  return 0;
1287 }
1288 
1289 
1305 static l_int32
1307  l_int32 *pval)
1308 {
1309 char buf[8];
1310 l_int32 i, c, foundws;
1311 
1312  PROCNAME("pnmReadNextNumber");
1313 
1314  if (!pval)
1315  return ERROR_INT("&val not defined", procName, 1);
1316  *pval = 0;
1317  if (!fp)
1318  return ERROR_INT("stream not open", procName, 1);
1319 
1320  /* The ASCII characters for the number are followed by exactly
1321  * one whitespace character. */
1322  foundws = FALSE;
1323  for (i = 0; i < 8; i++)
1324  buf[i] = '\0';
1325  for (i = 0; i < 8; i++) {
1326  if ((c = fgetc(fp)) == EOF)
1327  return ERROR_INT("end of file reached", procName, 1);
1328  if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
1329  foundws = TRUE;
1330  buf[i] = '\n';
1331  break;
1332  }
1333  if (!isdigit(c))
1334  return ERROR_INT("char read is not a digit", procName, 1);
1335  buf[i] = c;
1336  }
1337  if (!foundws)
1338  return ERROR_INT("no whitespace found", procName, 1);
1339  if (sscanf(buf, "%d", pval) != 1)
1340  return ERROR_INT("invalid read", procName, 1);
1341  return 0;
1342 }
1343 
1361 static l_int32
1363  char *buff,
1364  l_int32 size)
1365 {
1366 l_int32 i, c;
1367 
1368  PROCNAME("pnmReadNextString");
1369 
1370  if (!buff)
1371  return ERROR_INT("buff not defined", procName, 1);
1372  *buff = '\0';
1373  if (!fp)
1374  return ERROR_INT("stream not open", procName, 1);
1375  if (size <= 0)
1376  return ERROR_INT("size is too small", procName, 1);
1377 
1378  do { /* skip whitespace */
1379  if ((c = fgetc(fp)) == EOF)
1380  return ERROR_INT("end of file reached", procName, 1);
1381  } while (c == ' ' || c == '\t' || c == '\n' || c == '\r');
1382 
1383  /* Comment lines are allowed to appear
1384  * anywhere in the header lines */
1385  if (c == '#') {
1386  do { /* each line starting with '#' */
1387  do { /* this entire line */
1388  if ((c = fgetc(fp)) == EOF)
1389  return ERROR_INT("end of file reached", procName, 1);
1390  } while (c != '\n');
1391  if ((c = fgetc(fp)) == EOF)
1392  return ERROR_INT("end of file reached", procName, 1);
1393  } while (c == '#');
1394  }
1395 
1396  /* The next string ends when there is
1397  * a whitespace character following. */
1398  for (i = 0; i < size - 1; i++) {
1399  if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
1400  break;
1401  buff[i] = c;
1402  if ((c = fgetc(fp)) == EOF)
1403  return ERROR_INT("end of file reached", procName, 1);
1404  }
1405  buff[i] = '\0';
1406 
1407  /* Back up one byte */
1408  fseek(fp, -1L, SEEK_CUR);
1409  if (i >= size - 1)
1410  return ERROR_INT("buff size too small", procName, 1);
1411 
1412  /* Skip over trailing spaces and tabs */
1413  for (;;) {
1414  if ((c = fgetc(fp)) == EOF)
1415  return ERROR_INT("end of file reached", procName, 1);
1416  if (c != ' ' && c != '\t')
1417  break;
1418  }
1419 
1420  /* Back up one byte */
1421  fseek(fp, -1L, SEEK_CUR);
1422  return 0;
1423 }
1424 
1425 
1435 static l_int32
1437 {
1438 l_int32 c;
1439 
1440  PROCNAME("pnmSkipCommentLines");
1441 
1442  if (!fp)
1443  return ERROR_INT("stream not open", procName, 1);
1444  if ((c = fgetc(fp)) == EOF)
1445  return 1;
1446  if (c == '#') {
1447  do { /* each line starting with '#' */
1448  do { /* this entire line */
1449  if ((c = fgetc(fp)) == EOF)
1450  return 1;
1451  } while (c != '\n');
1452  if ((c = fgetc(fp)) == EOF)
1453  return 1;
1454  } while (c == '#');
1455  }
1456 
1457  /* Back up one byte */
1458  fseek(fp, -1L, SEEK_CUR);
1459  return 0;
1460 }
1461 
1462 /* --------------------------------------------*/
1463 #endif /* USE_PNMIO */
1464 /* --------------------------------------------*/
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:322
l_ok pixWriteMemPam(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemPam()
Definition: pnmio.c:1214
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:447
static l_int32 pnmSkipCommentLines(FILE *fp)
pnmSkipCommentLines()
Definition: pnmio.c:1436
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:1734
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
PIX * pixReadMemPnm(const l_uint8 *data, size_t size)
pixReadMemPnm()
Definition: pnmio.c:1084
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
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:1117
static l_int32 pnmReadNextString(FILE *fp, char *buff, l_int32 size)
pnmReadNextString()
Definition: pnmio.c:1362
PIX * pixReadStreamPnm(FILE *fp)
pixReadStreamPnm()
Definition: pnmio.c:145
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
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:490
l_ok pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
pixSetPixel()
Definition: pix2.c:253
l_ok composeRGBAPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel)
composeRGBAPixel()
Definition: pix2.c:2702
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
FILE * fopenWriteWinTempfile()
fopenWriteWinTempfile()
Definition: utils2.c:1780
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
l_ok pixWriteStreamPnm(FILE *fp, PIX *pix)
pixWriteStreamPnm()
Definition: pnmio.c:667
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
static l_int32 pnmReadNextNumber(FILE *fp, l_int32 *pval)
pnmReadNextNumber()
Definition: pnmio.c:1306
l_ok pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:180
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1657
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1262
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:212
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
static l_int32 pnmReadNextAsciiValue(FILE *fp, l_int32 *pval)
pnmReadNextAsciiValue()
Definition: pnmio.c:1267
Definition: pix.h:134
l_ok pixWriteStreamPam(FILE *fp, PIX *pix)
pixWriteStreamPam()
Definition: pnmio.c:908
Definition: pix.h:201
l_ok pixWriteStreamAsciiPnm(FILE *fp, PIX *pix)
pixWriteStreamAsciiPnm()
Definition: pnmio.c:786
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2671
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
l_ok pixWriteMemPnm(l_uint8 **pdata, size_t *psize, PIX *pix)
pixWriteMemPnm()
Definition: pnmio.c:1159