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