w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

pnmio.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  - This software is distributed in the hope that it will be
4  - useful, but with NO WARRANTY OF ANY KIND.
5  - No author or distributor accepts responsibility to anyone for the
6  - consequences of using this software, or for whether it serves any
7  - particular purpose or works at all, unless he or she says so in
8  - writing. Everyone is granted permission to copy, modify and
9  - redistribute this source code, for commercial or non-commercial
10  - purposes, with the following restrictions: (1) the origin of this
11  - source code must not be misrepresented; (2) modified versions must
12  - be plainly marked as such; and (3) this notice may not be removed
13  - or altered from any source or modified source distribution.
14  *====================================================================*/
15 
16 /*
17  * pnmio.c
18  *
19  * Stream interface
20  * PIX *pixReadStreamPnm()
21  * l_int32 pixWriteStreamPnm()
22  * l_int32 pixWriteStreamAsciiPnm()
23  *
24  * Local helpers
25  * static l_int32 pnmReadNextAsciiValue();
26  * static l_int32 pnmSkipCommentLines();
27  *
28  * These are here by popular demand, with the help of Mattias
29  * Kregert (mattias@kregert.se), who provided the first implementation.
30  *
31  * The pnm formats are exceedingly simple, because they have
32  * no compression and no colormaps. They support images that
33  * are 1 bpp; 2, 4 and 8 bpp grayscale; and rgb.
34  *
35  * The original pnm formats ("ascii") are included for completeness,
36  * but their use is deprecated for all but tiny iconic images.
37  * They are extremely wasteful of memory; for example, the P1 binary
38  * ascii format is 16 times as big as the packed uncompressed
39  * format, because 2 characters are used to represent every bit
40  * (pixel) in the image. Reading is slow because we check for extra
41  * white space and EOL at every sample value.
42  *
43  * The packed pnm formats ("raw") give file sizes similar to
44  * bmp files, which are uncompressed packed. However, bmp
45  * are more flexible, because they can support colormaps.
46  *
47  * We don't differentiate between the different types ("pbm",
48  * "pgm", "ppm") at the interface level, because this is really a
49  * "distinction without a difference." You read a file, you get
50  * the appropriate Pix. You write a file from a Pix, you get the
51  * appropriate type of file. If there is a colormap on the Pix,
52  * and the Pix is more than 1 bpp, you get either an 8 bpp pgm
53  * or a 24 bpp RGB pnm, depending on whether the colormap colors
54  * are gray or rgb, respectively.
55  *
56  * This follows the general policy that the I/O routines don't
57  * make decisions about the content of the image -- you do that
58  * with image processing before you write it out to file.
59  * The I/O routines just try to make the closest connection
60  * possible between the file and the Pix in memory.
61  */
62 
63 #include <stdio.h>
64 #include <string.h>
65 #include <stdlib.h>
66 
67 #include "allheaders.h"
68 
69 
72 
73  /* a sanity check on the size read from file */
74 static const l_int32 MAX_PNM_WIDTH = 100000;
75 static const l_int32 MAX_PNM_HEIGHT = 100000;
76 
77 
78 /*--------------------------------------------------------------------*
79  * Stream interface *
80  *--------------------------------------------------------------------*/
81 /*!
82  * pixReadStreamPnm()
83  *
84  * Input: stream opened for read
85  * Return: pix, or null on error
86  */
87 PIX *
89 {
90 l_uint8 val8, rval8, gval8, bval8;
91 l_int32 w, h, d, bpl, wpl, i, j, type;
92 l_int32 maxval, val, rval, gval, bval;
93 l_uint32 rgbval;
94 l_uint32 *line, *data;
95 PIX *pix;
96 
97  PROCNAME("pixReadStreamPnm");
98 
99  if (!fp)
100  return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
101 
102  fscanf(fp, "P%d\n", &type);
103  if (type < 1 || type > 6)
104  return (PIX *)ERROR_PTR("invalid pnm file", procName, NULL);
105 
106  if (pnmSkipCommentLines(fp))
107  return (PIX *)ERROR_PTR("no data in file", procName, NULL);
108 
109  fscanf(fp, "%d %d\n", &w, &h);
110  if (w <= 0 || h <= 0 || w > MAX_PNM_WIDTH || h > MAX_PNM_HEIGHT)
111  return (PIX *)ERROR_PTR("invalid sizes", procName, NULL);
112 
113  /* get depth of pix */
114  if (type == 1 || type == 4)
115  d = 1;
116  else if (type == 2 || type == 5) {
117  fscanf(fp, "%d\n", &maxval);
118  if (maxval == 3)
119  d = 2;
120  else if (maxval == 15)
121  d = 4;
122  else if (maxval == 255)
123  d = 8;
124  else {
125  fprintf(stderr, "maxval = %d\n", maxval);
126  return (PIX *)ERROR_PTR("invalid maxval", procName, NULL);
127  }
128  }
129  else { /* type == 3 || type == 6; this is rgb */
130  fscanf(fp, "%d\n", &maxval);
131  if (maxval != 255)
132  L_WARNING_INT("unexpected maxval = %d", procName, maxval);
133  d = 32;
134  }
135 
136  if ((pix = pixCreate(w, h, d)) == NULL)
137  return (PIX *)ERROR_PTR( "pix not made", procName, NULL);
138  data = pixGetData(pix);
139  wpl = pixGetWpl(pix);
140 
141  /* old "ascii" format */
142  if (type <= 3) {
143  for (i = 0; i < h; i++) {
144  for (j = 0; j < w; j++) {
145  if (type == 1 || type == 2) {
147  return (PIX *)ERROR_PTR( "read abend", procName, pix);
148  pixSetPixel(pix, j, i, val);
149  }
150  else { /* type == 3 */
151  if (pnmReadNextAsciiValue(fp, &rval))
152  return (PIX *)ERROR_PTR( "read abend", procName, pix);
154  return (PIX *)ERROR_PTR( "read abend", procName, pix);
155  if (pnmReadNextAsciiValue(fp, &bval))
156  return (PIX *)ERROR_PTR( "read abend", procName, pix);
157  composeRGBPixel(rval, gval, bval, &rgbval);
158  pixSetPixel(pix, j, i, rgbval);
159  }
160  }
161  }
162  return pix;
163  }
164 
165  /* "raw" format; binary and grayscale */
166  if (type == 4 || type == 5) {
167  bpl = (d * w + 7) / 8;
168  for (i = 0; i < h; i++) {
169  line = data + i * wpl;
170  for (j = 0; j < bpl; j++) {
171  fread(&val8, 1, 1, fp);
172  SET_DATA_BYTE(line, j, val8);
173  }
174  }
175  return pix;
176  }
177 
178  /* "raw" format, type == 6; rgb */
179  for (i = 0; i < h; i++) {
180  line = data + i * wpl;
181  for (j = 0; j < wpl; j++) {
182  fread(&rval8, 1, 1, fp);
183  fread(&gval8, 1, 1, fp);
184  fread(&bval8, 1, 1, fp);
185  composeRGBPixel(rval8, gval8, bval8, &rgbval);
186  line[j] = rgbval;
187  }
188  }
189  return pix;
190 }
191 
192 
193 /*!
194  * pixWriteStreamPnm()
195  *
196  * Input: stream opened for write
197  * pix
198  * Return: 0 if OK; 1 on error
199  *
200  * Writes "raw" packed format only:
201  * 1 bpp --> pbm (P4)
202  * 2, 4, 8 bpp, no colormap or grayscale colormap --> pgm (P5)
203  * 2, 4, 8 bpp with color-valued colormap, or rgb --> rgb ppm (P6)
204  */
205 l_int32
207  PIX *pix)
208 {
209 l_uint8 byteval, rval, gval, bval;
210 l_int32 h, w, d, ds, i, j, wpls, bpl, maxval;
211 l_uint32 *datas, *lines;
212 PIX *pixs;
213 
214  PROCNAME("pixWriteStreamPnm");
215 
216  if (!fp)
217  return ERROR_INT("fp not defined", procName, 1);
218  if (!pix)
219  return ERROR_INT("pix not defined", procName, 1);
220 
221  w = pixGetWidth(pix);
222  h = pixGetHeight(pix);
223  d = pixGetDepth(pix);
224  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 32)
225  return ERROR_INT("d not in {1,2,4,8,32}", procName, 1);
226 
227  /* if a colormap exists, remove and convert to grayscale or rgb */
228  if (pixGetColormap(pix) != NULL)
230  else
231  pixs = pixClone(pix);
232  ds = pixGetDepth(pixs);
233  datas = pixGetData(pixs);
234  wpls = pixGetWpl(pixs);
235 
236  if (ds == 1) { /* binary */
237  fprintf(fp, "P4\n# Raw PBM file written by leptonlib (www.leptonica.com)\n%d %d\n", w, h);
238 
239  bpl = (w + 7) / 8;
240  for (i = 0; i < h; i++) {
241  lines = datas + i * wpls;
242  for (j = 0; j < bpl; j++) {
243  byteval = GET_DATA_BYTE(lines, j);
244  fwrite(&byteval, 1, 1, fp);
245  }
246  }
247  }
248  else if (ds == 2 || ds == 4 || ds == 8) { /* grayscale */
249  maxval = (1 << ds) - 1;
250  fprintf(fp, "P5\n# Raw PGM file written by leptonlib (www.leptonica.com)\n%d %d\n%d\n", w, h, maxval);
251 
252  bpl = (ds * w + 7) / 8;
253  for (i = 0; i < h; i++) {
254  lines = datas + i * wpls;
255  for (j = 0; j < bpl; j++) {
256  byteval = GET_DATA_BYTE(lines, j);
257  fwrite(&byteval, 1, 1, fp);
258  }
259  }
260  }
261  else { /* rgb color */
262  fprintf(fp, "P6\n# Raw PPM file written by leptonlib (www.leptonica.com)\n%d %d\n255\n", w, h);
263 
264  for (i = 0; i < h; i++) {
265  lines = datas + i * wpls;
266  for (j = 0; j < wpls; j++) {
267  rval = GET_DATA_BYTE(lines + j, COLOR_RED);
269  bval = GET_DATA_BYTE(lines + j, COLOR_BLUE);
270  fwrite(&rval, 1, 1, fp);
271  fwrite(&gval, 1, 1, fp);
272  fwrite(&bval, 1, 1, fp);
273  }
274  }
275  }
276 
277  pixDestroy(&pixs);
278  return 0;
279 }
280 
281 
282 /*!
283  * pixWriteStreamAsciiPnm()
284  *
285  * Input: stream opened for write
286  * pix
287  * Return: 0 if OK; 1 on error
288  *
289  * Writes "ascii" format only:
290  * 1 bpp --> pbm (P1)
291  * 2, 4, 8 bpp, no colormap or grayscale colormap --> pgm (P2)
292  * 2, 4, 8 bpp with color-valued colormap, or rgb --> rgb ppm (P3)
293  */
294 l_int32
296  PIX *pix)
297 {
298 char buffer[256];
299 l_uint8 cval[3];
300 l_int32 h, w, d, ds, i, j, k, maxval, count;
301 l_uint32 val;
302 PIX *pixs;
303 
304  PROCNAME("pixWriteStreamAsciiPnm");
305 
306  if (!fp)
307  return ERROR_INT("fp not defined", procName, 1);
308  if (!pix)
309  return ERROR_INT("pix not defined", procName, 1);
310 
311  w = pixGetWidth(pix);
312  h = pixGetHeight(pix);
313  d = pixGetDepth(pix);
314  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 32)
315  return ERROR_INT("d not in {1,2,4,8,32}", procName, 1);
316 
317  /* if a colormap exists, remove and convert to grayscale or rgb */
318  if (pixGetColormap(pix) != NULL)
320  else
321  pixs = pixClone(pix);
322  ds = pixGetDepth(pixs);
323 
324  if (ds == 1) { /* binary */
325  fprintf(fp, "P1\n# Ascii PBM file written by leptonlib (www.leptonica.com)\n%d %d\n", w, h);
326 
327  count = 0;
328  for (i = 0; i < h; i++) {
329  for (j = 0; j < w; j++) {
330  pixGetPixel(pixs, j, i, &val);
331  if (val == 0)
332  fputc('0', fp);
333  else /* val == 1 */
334  fputc('1', fp);
335  fputc(' ', fp);
336  count += 2;
337  if (count >= 70)
338  fputc('\n', fp);
339  }
340  }
341  }
342  else if (ds == 2 || ds == 4 || ds == 8) { /* grayscale */
343  maxval = (1 << ds) - 1;
344  fprintf(fp, "P2\n# Ascii PGM file written by leptonlib (www.leptonica.com)\n%d %d\n%d\n", w, h, maxval);
345 
346  count = 0;
347  for (i = 0; i < h; i++) {
348  for (j = 0; j < w; j++) {
349  pixGetPixel(pixs, j, i, &val);
350  if (ds == 2) {
351  sprintf(buffer, "%1d ", val);
352  fwrite(buffer, 1, 2, fp);
353  count += 2;
354  }
355  else if (ds == 4) {
356  sprintf(buffer, "%2d ", val);
357  fwrite(buffer, 1, 3, fp);
358  count += 3;
359  }
360  else { /* ds == 8 */
361  sprintf(buffer, "%3d ", val);
362  fwrite(buffer, 1, 4, fp);
363  count += 4;
364  }
365  if (count >= 60) {
366  fputc('\n', fp);
367  count = 0;
368  }
369  }
370  }
371  }
372  else { /* rgb color */
373  fprintf(fp, "P3\n# Ascii PPM file written by leptonlib (www.leptonica.com)\n%d %d\n255\n", w, h);
374 
375  count = 0;
376  for (i = 0; i < h; i++) {
377  for (j = 0; j < w; j++) {
378  pixGetPixel(pixs, j, i, &val);
379  cval[0] = GET_DATA_BYTE(&val, COLOR_RED);
380  cval[1] = GET_DATA_BYTE(&val, COLOR_GREEN);
381  cval[2] = GET_DATA_BYTE(&val, COLOR_BLUE);
382  for (k = 0; k < 3; k++) {
383  sprintf(buffer, "%3d ", cval[k]);
384  fwrite(buffer, 1, 4, fp);
385  count += 4;
386  if (count >= 60) {
387  fputc('\n', fp);
388  count = 0;
389  }
390  }
391  }
392  }
393  }
394 
395  pixDestroy(&pixs);
396  return 0;
397 }
398 
399 
400 /*--------------------------------------------------------------------*
401  * Static helpers *
402  *--------------------------------------------------------------------*/
403 /*!
404  * pnmReadNextAsciiValue()
405  *
406  * Return: 0 if OK, 1 on error or EOF.
407  *
408  * Read the next sample value in ascii from the the file.
409  */
410 static l_int32
412  l_int32 *pval)
413 {
414 l_int32 c;
415 
416  PROCNAME("pnmReadNextAsciiValue");
417 
418  if (!fp)
419  return ERROR_INT("stream not open", procName, 1);
420  if (!pval)
421  return ERROR_INT("&val not defined", procName, 1);
422  *pval = 0;
423  do { /* skip whitespace */
424  if ((c = fgetc(fp)) == EOF)
425  return 1;
426  } while (c == ' ' || c == '\t' || c == '\n' || c == '\r');
427 
428  fseek(fp, -1L, SEEK_CUR); /* back up one byte */
429  fscanf(fp, "%d", pval);
430  return 0;
431 }
432 
433 
434 /*!
435  * pnmSkipCommentLines()
436  *
437  * Return: 0 if OK, 1 on error or EOF
438  *
439  * Comment lines begin with '#'
440  * Usage: caller should check return value for EOF
441  */
442 static l_int32
444 {
445 l_int32 c;
446 
447  PROCNAME("pnmSkipCommentLines");
448 
449  if (!fp)
450  return ERROR_INT("stream not open", procName, 1);
451  if ((c = fgetc(fp)) == EOF)
452  return 1;
453  if (c == '#') {
454  do { /* each line starting with '#' */
455  do { /* this entire line */
456  if ((c = fgetc(fp)) == EOF)
457  return 1;
458  } while (c != '\n');
459  if ((c = fgetc(fp)) == EOF)
460  return 1;
461  } while (c == '#');
462  }
463 
464  /* back up one byte */
465  fseek(fp, -1L, SEEK_CUR);
466  return 0;
467 }
468 
469 
#define type(a)
Definition: aptex-macros.h:171
#define count(a)
Definition: aptex-macros.h:781
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:98
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:106
static gray maxval
Definition: asciitopgm.c:38
int w
Definition: dviconv.c:26
int h
Definition: dviconv.c:9
#define fread
Definition: xxstdio.h:25
#define fseek
Definition: xxstdio.h:30
#define fgetc
Definition: xxstdio.h:26
struct rect data
Definition: dvipdfm.c:64
#define PROCNAME(name)
Definition: environ.h:131
#define ERROR_PTR(a, b, c)
Definition: environ.h:132
unsigned int l_uint32
Definition: environ.h:33
unsigned char l_uint8
Definition: environ.h:29
#define ERROR_INT(a, b, c)
Definition: environ.h:133
int l_int32
Definition: environ.h:32
#define L_WARNING_INT(a, b, c)
Definition: environ.h:137
#define c(n)
Definition: gpos-common.c:150
#define d(n)
Definition: gpos-common.c:151
pix
Definition: in_pcx.cpp:383
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
#define SEEK_CUR
Definition: ftzconf.h:250
#define EOF
Definition: afmparse.c:59
int lines
Definition: var.h:5
#define fprintf
Definition: mendex.h:64
Code related to b fwrite(a, sizeof(char), b, stdout) @d C_printf(c
#define sprintf
Definition: snprintf.c:44
l_uint32 * pixGetData(PIX *pix)
Definition: pix1.c:793
void pixDestroy(PIX **ppix)
Definition: pix1.c:225
l_int32 pixGetWpl(PIX *pix)
Definition: pix1.c:477
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
Definition: pixconv.c:198
l_int32 pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
Definition: pix2.c:197
l_int32 pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
Definition: pix2.c:128
l_int32 pixGetDepth(PIX *pix)
Definition: pix1.c:449
PIXCMAP * pixGetColormap(PIX *pix)
Definition: pix1.c:766
l_int32 composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
Definition: pix2.c:2230
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
Definition: pix1.c:90
PIX * pixClone(PIX *pixs)
Definition: pix1.c:197
l_int32 pixGetHeight(PIX *pix)
Definition: pix1.c:419
l_int32 pixGetWidth(PIX *pix)
Definition: pix1.c:389
int k
Definition: otp-parser.c:70
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:113
@ COLOR_BLUE
Definition: pix.h:102
@ COLOR_RED
Definition: pix.h:100
@ COLOR_GREEN
Definition: pix.h:101
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF base if bpp PF set rept prefetch_distance PF set OFFSET endr endif endm macro preload_leading_step2 base if bpp ifc DST PF PF else if bpp lsl PF PF lsl PF PF lsl PF PF bpl
#define fp
l_int32 pixWriteStreamAsciiPnm(FILE *fp, PIX *pix)
Definition: pnmio.c:295
PIX * pixReadStreamPnm(FILE *fp)
Definition: pnmio.c:88
static const l_int32 MAX_PNM_WIDTH
Definition: pnmio.c:74
l_int32 pixWriteStreamPnm(FILE *fp, PIX *pix)
Definition: pnmio.c:206
static l_int32 pnmSkipCommentLines(FILE *fp)
Definition: pnmio.c:443
static l_int32 pnmReadNextAsciiValue(FILE *fp, l_int32 *pval)
Definition: pnmio.c:411
static const l_int32 MAX_PNM_HEIGHT
Definition: pnmio.c:75
char line[1024]
Definition: process_score.c:29
#define gval(n)
Definition: ltable.h:14
Definition: pix.h:51
Definition: utils.c:300
Definition: bdf.c:133
Definition: strexpr.c:21
#define FILE
Definition: t1stdio.h:34
int j
Definition: t4ht.c:1589
val
Definition: tex4ht.c:3227