1 /* leaftoppm.c - read an ileaf img file and write a PPM
2  *
3  * Copyright (C) 1994 by Bill O'Donnell.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation for any purpose and without fee is hereby granted, provided
7  * that the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation.  This software is provided "as is" without express or
10  * implied warranty.
11  *
12  * known problems: doesn't do compressed ileaf images.
13  *
14  */
15 
16 #include <stdio.h>
17 #include "ppm.h"
18 
19 #define MAXCOLORS 256
20 #define LEAF_MAXVAL 255
21 
22 static void
leaf_init(FILE * const fp,int * const colsP,int * const rowsP,int * const depthP,int * const ncolorsP,pixel * const colors)23 leaf_init(FILE *  const fp,
24           int *   const colsP,
25           int *   const rowsP,
26           int *   const depthP,
27           int *   const ncolorsP,
28           pixel * const colors) {
29 
30     unsigned char buf[256];
31     unsigned char compressed;
32     short version;
33     short cols;
34     short rows;
35     short depth;
36     long magic;
37 
38     pm_readbiglong(fp, &magic);
39     if ((uint32_t)magic != 0x894f5053)
40         pm_error("Bad magic number.  First 4 bytes should be "
41                  "0x894f5053 but are instead 0x%08x", (unsigned)magic);
42 
43     /* version =   2 bytes
44        hres =      2
45        vres =      2
46        unique id = 4
47        offset x =  2
48        offset y =  2
49        TOTAL    =  14 bytes
50     */
51 
52     pm_readbigshort(fp, &version);
53 
54     if (fread(buf, 1, 12, fp) != 12)
55         pm_error("bad header, short file?");
56 
57     pm_readbigshort(fp, &cols);
58     *colsP = cols;
59     pm_readbigshort(fp, &rows);
60     *rowsP = rows;
61     pm_readbigshort(fp, &depth);
62     *depthP = depth;
63 
64     if ((compressed = fgetc(fp)) != 0)
65         pm_error("Can't do compressed images.");
66 
67     if ((*depthP == 1) && (version < 4)) {
68         fgetc(fp);
69         *ncolorsP = 0;
70     } else if ((*depthP == 8) && (version < 4)) {
71         fgetc(fp);
72         *ncolorsP = 0;
73     } else {
74         long format;
75         pm_readbiglong(fp, &format);
76         if (format == 0x29000000) {
77             /* color image */
78             short ncolors;
79             pm_readbigshort(fp, &ncolors);
80 
81             if (ncolors > 0) {
82                 /* 8-bit image */
83                 unsigned int i;
84 
85                 if (ncolors > 256)
86                     pm_error("Can't have > 256 colors in colormap.");
87                 /* read colormap */
88                 for (i=0; i < 256; ++i)
89                     PPM_PUTR(colors[i], fgetc(fp));
90                 for (i=0; i < 256; ++i)
91                     PPM_PUTG(colors[i], fgetc(fp));
92                 for (i=0; i < 256; ++i)
93                     PPM_PUTB(colors[i], fgetc(fp));
94                 *ncolorsP = ncolors;
95             } else {
96                 /* 24-bit image */
97                 *ncolorsP = 0;
98             }
99         } else if (*depthP ==1) {
100             /* mono image */
101             short dummy;
102             pm_readbigshort(fp, &dummy);  /* must toss cmap size */
103             *ncolorsP = 0;
104         } else {
105             /* gray image */
106             short dummy;
107             pm_readbigshort(fp, &dummy);  /* must toss cmap size */
108             *ncolorsP = 0;
109         }
110     }
111 }
112 
113 
114 
115 int
main(int argc,char * argv[])116 main(int argc, char * argv[]) {
117 
118     pixval const maxval = LEAF_MAXVAL;
119 
120     FILE *ifd;
121     pixel colormap[MAXCOLORS];
122     int rows, cols, row, col, depth, ncolors;
123 
124 
125     ppm_init(&argc, argv);
126 
127     if (argc-1 > 1)
128         pm_error("Too many arguments.  Only argument is ileaf file name");
129 
130     if (argc-1 == 1)
131         ifd = pm_openr(argv[1]);
132     else
133         ifd = stdin;
134 
135     leaf_init(ifd, &cols, &rows, &depth, &ncolors, colormap);
136 
137     if ((depth == 8) && (ncolors == 0)) {
138         /* gray image */
139         gray * grayrow;
140         unsigned int row;
141         pgm_writepgminit( stdout, cols, rows, maxval, 0 );
142         grayrow = pgm_allocrow(cols);
143         for (row = 0; row < rows; ++row) {
144             unsigned int col;
145             for ( col = 0; col < cols; ++col)
146                 grayrow[col] = (gray)fgetc(ifd);
147             if (cols % 2)
148                 fgetc (ifd); /* padding */
149             pgm_writepgmrow(stdout, grayrow, cols, maxval, 0);
150         }
151         pgm_freerow(grayrow);
152     } else if (depth == 24) {
153         pixel * pixrow;
154         unsigned int row;
155         ppm_writeppminit(stdout, cols, rows, maxval, 0);
156         pixrow = ppm_allocrow(cols);
157         /* true color */
158         for (row = 0; row < rows; ++row) {
159             for (col = 0; col < cols; ++col)
160                 PPM_PUTR(pixrow[col], fgetc(ifd));
161             if (cols % 2)
162                 fgetc (ifd); /* padding */
163             for (col = 0; col < cols; ++col)
164                 PPM_PUTG(pixrow[col], fgetc(ifd));
165             if (cols % 2)
166                 fgetc (ifd); /* padding */
167             for (col = 0; col < cols; ++col)
168                 PPM_PUTB(pixrow[col], fgetc(ifd));
169             if (cols % 2)
170                 fgetc (ifd); /* padding */
171             ppm_writeppmrow(stdout, pixrow, cols, maxval, 0);
172         }
173         ppm_freerow(pixrow);
174     } else if (depth == 8) {
175         /* 8-bit (color mapped) image */
176         pixel * pixrow;
177 
178         ppm_writeppminit(stdout, cols, rows, (pixval) maxval, 0);
179         pixrow = ppm_allocrow( cols );
180 
181         for (row = 0; row < rows; ++row) {
182             for (col = 0; col < cols; ++col)
183                 pixrow[col] = colormap[fgetc(ifd)];
184             if (cols %2)
185                 fgetc(ifd); /* padding */
186             ppm_writeppmrow(stdout, pixrow, cols, maxval, 0);
187         }
188         ppm_freerow(pixrow);
189     } else if (depth == 1) {
190         /* mono image */
191         bit *bitrow;
192         unsigned int row;
193 
194         pbm_writepbminit(stdout, cols, rows, 0);
195         bitrow = pbm_allocrow(cols);
196 
197         for (row = 0; row < rows; ++row) {
198             unsigned char bits;
199             bits = 0x00;  /* initial value */
200             for (col = 0; col < cols; ++col) {
201                 int const shift = col % 8;
202                 if (shift == 0)
203                     bits = (unsigned char) fgetc(ifd);
204                 bitrow[col] = (bits & (unsigned char)(0x01 << (7 - shift))) ?
205                     PBM_WHITE : PBM_BLACK;
206             }
207             if ((cols % 16) && (cols % 16) <= 8)
208                 fgetc(ifd);  /* 16 bit pad */
209             pbm_writepbmrow(stdout, bitrow, cols, 0);
210         }
211         pbm_freerow(bitrow);
212     }
213     pm_close(ifd);
214 
215     return 0;
216 }
217