1 /* ----------------------------------------------------------------------
2  *
3  * Convert a PAM image to an AVS X image
4  *
5  * By Scott Pakin <scott+pbm@pakin.org>
6  *
7  * ----------------------------------------------------------------------
8  *
9  * Copyright (C) 2010 Scott Pakin <scott+pbm@pakin.org>
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or (at
14  * your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see http://www.gnu.org/licenses/.
23  *
24  * ----------------------------------------------------------------------
25  */
26 
27 #include <stdio.h>
28 #include "pm.h"
29 #include "pam.h"
30 
31 
32 
33 static char
sample2char(sample const s,sample const maxval)34 sample2char(sample const s,
35             sample const maxval) {
36 /* Scale down a sample to a single byte. */
37 
38     return maxval==255 ? s : s * 255 / maxval;
39 }
40 
41 
42 #define THIS_SAMPLE_CHAR(PLANE) \
43   sample2char(tuplerow[col][PLANE], pamP->maxval)
44 
45 static void
produceAvs(struct pam * const pamP,FILE * const avsFileP)46 produceAvs(struct pam * const pamP,
47            FILE *       const avsFileP) {
48 
49     tuple * tuplerow;
50 
51     /* Write the AVS header (image width and height as 4-byte
52        big-endian integers).
53     */
54     pm_writebiglong(avsFileP, pamP->width);
55     pm_writebiglong(avsFileP, pamP->height);
56 
57     /* Write the AVS data (alpha, red, green, blue -- one byte apiece. */
58     tuplerow = pnm_allocpamrow(pamP);
59     switch (pamP->depth) {
60     case 1: {
61         /* Black-and-white or grayscale, no alpha */
62         unsigned int row;
63         for (row = 0; row < pamP->height; ++row) {
64             unsigned int col;
65             pnm_readpamrow(pamP, tuplerow);
66             for (col = 0; col < pamP->width; ++col) {
67                 pm_writechar(avsFileP, (char)255);
68                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(0));
69                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(0));
70                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(0));
71             }
72         }
73     } break;
74 
75     case 2: {
76         /* Black-and-white or grayscale plus alpha */
77         unsigned int row;
78         for (row = 0; row < pamP->height; ++row) {
79             unsigned int col;
80             pnm_readpamrow(pamP, tuplerow);
81             for (col = 0; col < pamP->width; ++col) {
82                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(1));
83                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(0));
84                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(0));
85                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(0));
86             }
87         }
88     } break;
89 
90     case 3: {
91         /* RGB, no alpha */
92         unsigned int row;
93         for (row = 0; row < pamP->height; ++row) {
94             unsigned int col;
95             pnm_readpamrow(pamP, tuplerow);
96             for (col = 0; col < pamP->width; ++col) {
97                 pm_writechar(avsFileP, (char)255);
98                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(0));
99                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(1));
100                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(2));
101             }
102         }
103     } break;
104 
105     case 4: {
106         /* RGB plus alpha */
107         unsigned int row;
108         for (row = 0; row < pamP->height; ++row) {
109             unsigned int col;
110             pnm_readpamrow( pamP, tuplerow );
111             for (col = 0; col < pamP->width; ++col) {
112                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(3));
113                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(0));
114                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(1));
115                 pm_writechar(avsFileP, THIS_SAMPLE_CHAR(2));
116             }
117         }
118     } break;
119 
120     default:
121         pm_error("Unrecognized PAM depth %u.  We understand only "
122                  "1, 2, 3, and 4", pamP->depth);
123         break;
124     }
125     pnm_freepamrow(tuplerow);
126 }
127 
128 
129 
130 int
main(int argc,const char * argv[])131 main(int argc, const char *argv[]) {
132     struct pam   inPam;
133     const char * inputFilename;
134     FILE       * inFileP;
135 
136     pm_proginit(&argc, argv);
137 
138     inputFilename = (argc > 1) ? argv[1] : "-";
139 
140     inFileP = pm_openr(inputFilename);
141 
142     pnm_readpaminit(inFileP, &inPam, PAM_STRUCT_SIZE(tuple_type));
143 
144     produceAvs(&inPam, stdout);
145 
146     pm_closer(inFileP);
147 
148     return 0;
149 }
150 
151