Mon, 03 Aug 2009 14:21:23 +0100
added keepme for ptdecode obj directory
1 /****************************************************************************
2 * ptdecode: P-touch PT-2450DX output decoder
3 ****************************************************************************/
5 #include <cstdio>
6 #include <exception>
7 #include "CImg.h"
9 using namespace std;
10 using namespace cimg_library;
12 // maximum size of a Ptouch printer head in dots
13 const unsigned int PT_HEAD_WIDTH = 1024;
15 // If defined, makes "blank row" blocks visible
16 //#define MAKE_BLANK_ROWS_VISIBLE
18 // custom exception class for file read errors
19 class EReadError : public exception {
20 public:
21 virtual const char* what() const throw()
22 {
23 return "Read error";
24 }
25 };
27 FILE *fp;
29 // get next character from file
30 unsigned char getNext() {
31 unsigned char ch;
32 int i;
34 i = fread(&ch, 1, 1, fp);
35 if (i != 1) {
36 throw EReadError();
37 } else {
38 return ch;
39 }
40 }
42 // Handler for graphics transfer mode 1
43 void runGraphicsXferMode1()
44 {
45 bool exit = false;
46 unsigned int cm = -1;
47 unsigned long xpos = 0;
48 unsigned long ypos = 0;
49 unsigned long ydim = 128;
50 CImg<unsigned char> img(0, 0, 0, 0, (unsigned char)0);
52 while (!exit) {
53 unsigned char ch = getNext();
54 unsigned int len = 0;
55 unsigned int rowpos = 0;
56 unsigned char row[PT_HEAD_WIDTH / 8]; // stores uncompressed row data
58 switch (ch) {
59 case 'M': // Set compression mode
60 ch = getNext();
61 cm = ch;
62 printf("Set compression mode: 0x%02X", ch);
63 switch (cm) {
64 case 0x02:
65 printf(" (TIFF/Packbits)\n");
66 break;
67 default:
68 printf(" *** Unknown, assuming uncompressed ***\n");
69 cm = 1;
70 break;
71 }
72 break;
74 case 'Z': // Blank raster line
75 // Increment x-position and resize the image
76 img.resize(xpos+1, ydim, 1, 1, 0, 0);
78 // Blank the new row
79 if (img.dimy() > 0) {
80 // printf("Clear row: x=%lu\n", xpos);
81 for (int i=0; i<img.dimy(); i++) {
82 #ifdef MAKE_BLANK_ROWS_VISIBLE
83 img(xpos, i) = 128;
84 #else
85 img(xpos, i) = 255;
86 #endif
87 }
88 }
90 xpos++;
91 break;
93 case 'G': // Graphics data row
94 // decode the length
95 ch = getNext();
96 len = (((int)getNext()) << 8) + ch;
98 // Dump the gfx data
99 rowpos = 0;
100 while (len > 0) {
101 // get the prefix byte
102 ch = getNext(); len--;
104 // Is this a "run" (a single byte replicated) or a "copy"?
105 int runlen;
106 if (ch & 0x80) {
107 // MSB set, it's a run
108 runlen = 257 - ((int)ch);
110 // Get the byte to replicate, and replicate it into the o/p buffer
111 ch = getNext(); len--;
112 while (runlen-- > 0) {
113 row[rowpos++] = ch;
114 }
115 } else {
116 // MSB clear, it's a copy
117 runlen = ((int)ch) + 1;
119 // Copy N bytes from the input stream to the output
120 while (runlen-- > 0) {
121 row[rowpos++] = getNext();
122 len--;
123 }
124 }
125 }
127 // Row decode complete. row contains the image data, and rowpos
128 // contains its length in bytes. Now shuffle it into CImg...
130 // If image height is less than size of image row, then make the
131 // image taller.
132 if (((unsigned int)img.dimy()) < (rowpos * 8)) {
133 ydim = rowpos * 8;
134 } else {
135 ydim = img.dimy();
136 }
138 // Perform the Y resize if necessary, but also make Xdim=Xdim+1
139 img.resize(xpos+1, ydim, 1, 1, 0, 0);
141 img(xpos, ydim/2) = 128;
143 // Now copy the image data...
144 ypos = 0;
145 for (unsigned int byte=0; byte<rowpos; byte++) {
146 for (unsigned int bit=0; bit<8; bit++) {
147 if (row[byte] & (0x80>>bit)) {
148 img(xpos, ypos) = 0;
149 } else {
150 img(xpos, ypos) = 255;
151 }
153 // Increment y-position
154 ypos++;
155 }
156 }
158 // An entire row has been decoded. Increment x-position.
159 xpos++;
160 break;
162 case 0x0c: // FF
163 printf("Formfeed: Print without label feed (job completed, more labels follow)\n");
164 exit = true;
165 break;
167 case 0x1a: // Ctrl-Z
168 printf("Ctrl-Z: Print with label feed (job completed, no further labels)\n");
169 exit = true;
170 break;
172 default: // Something else
173 printf("** Unrecognised command prefix in gfx mode: 0x%02x\n", ch);
174 break;
175 }
176 }
178 // Display the contents of the image
179 img.display();
180 }
182 // Parse an ESC i command
183 void parse_esc_i()
184 {
185 unsigned char ch = getNext();
186 unsigned int tmpI;
188 switch (ch) {
189 case 'B': // ESC i B: Specify baud rate
190 tmpI = getNext();
191 ch = getNext();
192 tmpI += ((int)ch)*256;
193 printf("Set baud rate:\t%d00", tmpI);
194 if ((tmpI != 96) && (tmpI != 576) && (tmpI != 1152)) {
195 printf(" [ILLEGAL SETTING]\n");
196 } else {
197 printf("\n");
198 }
199 break;
201 case 'S': // ESC i S: Status request
202 printf("Printer status request\n");
203 break;
205 case 'M': // ESC i M: Set mode
206 ch = getNext();
207 printf("Set mode 0x%02X:\tAutoCut %s, Mirror %s\n", ch,
208 (ch & 0x40) ? "on" : "off",
209 (ch & 0x80) ? "on" : "off");
210 break;
212 case 'd': // ESC i d: Set margin amount (feed amount)
213 tmpI = getNext();
214 ch = getNext();
215 tmpI += ((int)ch)*256;
216 printf("Set margin:\t%d dots", tmpI);
217 break;
219 case 'K': // ESC i K: Set expanded mode
220 ch = getNext();
221 printf("Set expanded mode 0x%02X:\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n", ch,
222 (ch & 0x04) ? "Half-cut on" : "Half-cut off",
223 (ch & 0x08) ? "Chain-print off: last label will be fed and cut" : "Chain-print on: last label will NOT be fed or cut",
224 (ch & 0x20) ? "Label end cut: when printing multiple copies, end of last label is cut" : "Label end cut off",
225 (ch & 0x40) ? "High-resolution (360x720dpi)" : "Normal resolution (360x360dpi)",
226 (ch & 0x80) ? "Copy-printing on (expansion buffer not cleared on form-feed)" : "Copy-printing off"
227 );
228 break;
230 case 'R': // ESC i R: Set graphics transfer mode
231 ch = getNext();
232 printf("Set graphics transfer mode 0x%02X: ", ch);
233 if (ch == 1) {
234 printf("Raster graphics mode\n");
235 runGraphicsXferMode1();
236 } else {
237 printf("\n\tUnrecognised graphics transfer mode: remainder of data may be garbage.\n");
238 }
239 break;
241 default:
242 printf("Unrecognised cmnd: ESC i 0x%02X\n", ch);
243 break;
244 }
245 }
247 // Parse an ESC command
248 void parse_esc()
249 {
250 unsigned char ch = getNext();
252 switch(ch) {
253 case 'i': // ESC i: Brother-specific extensions
254 parse_esc_i();
255 break;
257 case '@': // ESC @: Initialize
258 printf("Initialize: clear buffer and reset print origin\n");
259 break;
261 default:
262 printf("Unrecognised cmnd: ESC 0x%02X\n", ch);
263 break;
264 }
265 }
267 int main(int argc, char **argv)
268 {
269 // check params
270 if (argc != 2) {
271 // wrong!
272 printf("Usage: %s filename\n", argv[0]);
273 return -1;
274 }
276 // open binary dump file
277 fp = fopen(argv[1], "rb");
278 if (!fp) {
279 printf("Error opening source file\n");
280 return -1;
281 }
283 try {
284 while (true) {
285 unsigned char ch;
287 ch = getNext();
289 switch (ch) {
290 case 0x00: // NULL
291 printf("Null\n");
292 break;
293 case 0x0c: // FF
294 printf("Formfeed: Print without feed\n");
295 break;
296 case 0x1a: // Ctrl-Z
297 printf("Ctrl-Z: Print with label feed\n");
298 break;
299 case 0x1b: // ESC
300 parse_esc();
301 break;
302 default:
303 printf("Unrecognised cmnd: 0x%02X\n", ch);
304 break;
305 }
306 }
307 } catch (EReadError &e) {
308 if (feof(fp)) {
309 printf("EOF reached.\n");
310 } else {
311 printf("Uncaught EReadException: %s\n", e.what());
312 }
313 } catch (exception &e) {
314 printf("Uncaught exception: %s\n", e.what());
315 } catch (...) {
316 printf("Uncaught and unrecognised exception. Something went *really* wrong here...\n");
317 }
319 // close the file
320 fclose(fp);
322 return 0;
323 }