1 // ppmzip.cpp
2
3 #include "stdafx.h"
4
5 #define COMP 1
6 #define DECOMP 2
7
8 #define TRY_ROT(a) (rot?a^0xff:a)
9
10 /* PPMDi getc/putc bridge */
PPMDI(FILE * f)11 PPMDI::PPMDI(FILE *f)
12 {
13 file = f;
14 count = 0;
15 }
16
_putc(char c)17 void PPMDI::_putc(char c)
18 {
19 putc (c,file);
20 count++;
21 }
22
_getc()23 int PPMDI::_getc()
24 {
25 count++;
26 #ifdef _DEBUG
27 int a = count;
28 a = getc(file);
29 return a;
30 #else
31 return getc(file);
32 #endif
33 }
34
getCount()35 int PPMDI::getCount()
36 {
37 return count;
38 }
39
40 /* copy-paste from xmilldata.cpp etc */
41 typedef struct {
42 int size;
43 int order;
44 } level_settings;
45
46 #define XMILL_PPMDI_IDXS 19
47
48 level_settings ppmsettings[XMILL_PPMDI_IDXS] = {
49 {1,6},
50 {1,7},
51 {1,8},
52 {1,9},
53 {4,9},
54 {1,10},
55 {2,10},
56 {5,10},
57 {6,10},
58 {8,10},
59 {10,10},
60 {20,10},
61 {1,12},
62 {2,12},
63 {1,16},
64 {2,16},
65 {3,16},
66 {4,16},
67 {8,16}
68 };
69
70 /* main program, contains all PPMDi (de)compress API calls */
71 #ifdef WIN32
main(int argc,char ** argv)72 int _cdecl main(int argc,char **argv)
73 #else
74 int main(int argc,char **argv)
75 #endif
76 {
77 int action = COMP;
78 FILE* outfile = stdout;
79 FILE* infile = stdin;
80 int c, stat = 0, size = 10, order = 6, i = 0, c1;
81 PPM_ENCODER* enc = NULL;
82 PPM_DECODER* dec = NULL;
83 PPMDIData *data = NULL;
84 PPMDI *f = NULL;
85 bool rot = false, skip4 = false;
86
87 /* check arguments */
88 if (argc > 1) {
89 if (toupper(argv[1][0]) == 'D') {
90 action = DECOMP;
91 } else if (toupper(argv[1][0]) == 'C') {
92 action = COMP;
93 }
94 }
95
96 if (argc > 2) {
97 infile = fopen(argv[2], "r");
98 }
99
100 if (argc > 3) {
101 outfile = fopen(argv[3], "wb");
102 }
103
104 if (argc > 5) {
105 size = atoi(argv[4]);
106 order = atoi(argv[5]);
107 }
108
109 if (argc > 6) {
110 skip4 = (toupper(argv[6][0]) == 'T');
111 rot = argv[6][1];
112 }
113
114 #ifdef WIN32
115 _setmode(_fileno(infile), _O_BINARY);
116 _setmode(_fileno(outfile), _O_BINARY);
117 #else
118 /* how do I implement this on Unix?? */
119 #endif
120
121 switch (action) {
122 case COMP:
123 /* compress the file */
124 f = new PPMDI(outfile);
125 data = new PPMDIData(f);
126 data->getAlloc(size);
127 enc = new PPM_ENCODER (size,order,data);
128 data->ariInitEncoder();
129 while ((c = getc(infile)) != EOF) {
130 enc->EncodeChar(TRY_ROT(c));
131 i++;
132 }
133 enc->EncodeChar(EOF);
134 data->ariFlushEncoder();
135 break;
136
137 case DECOMP:
138 /* decompress the file */
139 if (skip4) {
140 /* skip first four Bytes & read size/order from the last one */
141 for (int j=0; j<4; j++) {
142 c1 = getc(infile);
143 }
144 size = ppmsettings[c1].size;
145 order = ppmsettings[c1].order;
146 }
147 f = new PPMDI(infile);
148 data = new PPMDIData(f);
149 data->getAlloc(size);
150 dec = new PPM_DECODER (size,order,data);
151 data->ariInitDecoder();
152 while (TRUE) {
153 if ((c1 = dec->DecodeChar()) == EOF) {
154 goto cleanup;
155 }
156 i++;
157 putc(TRY_ROT(c1), outfile);
158 }
159
160 break;
161
162 default:
163 stat = 1;
164 goto cleanup;
165 }
166
167 cleanup:
168 if (stat == 0 && outfile != stdout && f) {
169 printf ("(de)compressed %ld Bytes to %ld Bytes\n", f->getCount(), i);
170 }
171
172 if (f) delete f;
173 if (data) delete data;
174 if (enc) delete enc;
175 if (dec) delete dec;
176 if (infile) fclose(infile);
177 if (outfile) fclose(outfile);
178
179 return stat;
180 }
181