1.1 diff -r 5edfbd3e7a46 -r 1204ebf9340d PTdecode/src/main.cpp 1.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 +++ b/PTdecode/src/main.cpp Mon Aug 03 14:09:20 2009 +0100 1.4 @@ -0,0 +1,323 @@ 1.5 +/**************************************************************************** 1.6 + * ptdecode: P-touch PT-2450DX output decoder 1.7 + ****************************************************************************/ 1.8 + 1.9 +#include <cstdio> 1.10 +#include <exception> 1.11 +#include "CImg.h" 1.12 + 1.13 +using namespace std; 1.14 +using namespace cimg_library; 1.15 + 1.16 +// maximum size of a Ptouch printer head in dots 1.17 +const unsigned int PT_HEAD_WIDTH = 1024; 1.18 + 1.19 +// If defined, makes "blank row" blocks visible 1.20 +//#define MAKE_BLANK_ROWS_VISIBLE 1.21 + 1.22 +// custom exception class for file read errors 1.23 +class EReadError : public exception { 1.24 + public: 1.25 + virtual const char* what() const throw() 1.26 + { 1.27 + return "Read error"; 1.28 + } 1.29 +}; 1.30 + 1.31 +FILE *fp; 1.32 + 1.33 +// get next character from file 1.34 +unsigned char getNext() { 1.35 + unsigned char ch; 1.36 + int i; 1.37 + 1.38 + i = fread(&ch, 1, 1, fp); 1.39 + if (i != 1) { 1.40 + throw EReadError(); 1.41 + } else { 1.42 + return ch; 1.43 + } 1.44 +} 1.45 + 1.46 +// Handler for graphics transfer mode 1 1.47 +void runGraphicsXferMode1() 1.48 +{ 1.49 + bool exit = false; 1.50 + unsigned int cm = -1; 1.51 + unsigned long xpos = 0; 1.52 + unsigned long ypos = 0; 1.53 + unsigned long ydim = 128; 1.54 + CImg<unsigned char> img(0, 0, 0, 0, (unsigned char)0); 1.55 + 1.56 + while (!exit) { 1.57 + unsigned char ch = getNext(); 1.58 + unsigned int len = 0; 1.59 + unsigned int rowpos = 0; 1.60 + unsigned char row[PT_HEAD_WIDTH / 8]; // stores uncompressed row data 1.61 + 1.62 + switch (ch) { 1.63 + case 'M': // Set compression mode 1.64 + ch = getNext(); 1.65 + cm = ch; 1.66 + printf("Set compression mode: 0x%02X", ch); 1.67 + switch (cm) { 1.68 + case 0x02: 1.69 + printf(" (TIFF/Packbits)\n"); 1.70 + break; 1.71 + default: 1.72 + printf(" *** Unknown, assuming uncompressed ***\n"); 1.73 + cm = 1; 1.74 + break; 1.75 + } 1.76 + break; 1.77 + 1.78 + case 'Z': // Blank raster line 1.79 + // Increment x-position and resize the image 1.80 + img.resize(xpos+1, ydim, 1, 1, 0, 0); 1.81 + 1.82 + // Blank the new row 1.83 + if (img.dimy() > 0) { 1.84 +// printf("Clear row: x=%lu\n", xpos); 1.85 + for (int i=0; i<img.dimy(); i++) { 1.86 +#ifdef MAKE_BLANK_ROWS_VISIBLE 1.87 + img(xpos, i) = 128; 1.88 +#else 1.89 + img(xpos, i) = 255; 1.90 +#endif 1.91 + } 1.92 + } 1.93 + 1.94 + xpos++; 1.95 + break; 1.96 + 1.97 + case 'G': // Graphics data row 1.98 + // decode the length 1.99 + ch = getNext(); 1.100 + len = (((int)getNext()) << 8) + ch; 1.101 + 1.102 + // Dump the gfx data 1.103 + rowpos = 0; 1.104 + while (len > 0) { 1.105 + // get the prefix byte 1.106 + ch = getNext(); len--; 1.107 + 1.108 + // Is this a "run" (a single byte replicated) or a "copy"? 1.109 + int runlen; 1.110 + if (ch & 0x80) { 1.111 + // MSB set, it's a run 1.112 + runlen = 257 - ((int)ch); 1.113 + 1.114 + // Get the byte to replicate, and replicate it into the o/p buffer 1.115 + ch = getNext(); len--; 1.116 + while (runlen-- > 0) { 1.117 + row[rowpos++] = ch; 1.118 + } 1.119 + } else { 1.120 + // MSB clear, it's a copy 1.121 + runlen = ((int)ch) + 1; 1.122 + 1.123 + // Copy N bytes from the input stream to the output 1.124 + while (runlen-- > 0) { 1.125 + row[rowpos++] = getNext(); 1.126 + len--; 1.127 + } 1.128 + } 1.129 + } 1.130 + 1.131 + // Row decode complete. row contains the image data, and rowpos 1.132 + // contains its length in bytes. Now shuffle it into CImg... 1.133 + 1.134 + // If image height is less than size of image row, then make the 1.135 + // image taller. 1.136 + if (((unsigned int)img.dimy()) < (rowpos * 8)) { 1.137 + ydim = rowpos * 8; 1.138 + } else { 1.139 + ydim = img.dimy(); 1.140 + } 1.141 + 1.142 + // Perform the Y resize if necessary, but also make Xdim=Xdim+1 1.143 + img.resize(xpos+1, ydim, 1, 1, 0, 0); 1.144 + 1.145 + img(xpos, ydim/2) = 128; 1.146 + 1.147 + // Now copy the image data... 1.148 + ypos = 0; 1.149 + for (unsigned int byte=0; byte<rowpos; byte++) { 1.150 + for (unsigned int bit=0; bit<8; bit++) { 1.151 + if (row[byte] & (0x80>>bit)) { 1.152 + img(xpos, ypos) = 0; 1.153 + } else { 1.154 + img(xpos, ypos) = 255; 1.155 + } 1.156 + 1.157 + // Increment y-position 1.158 + ypos++; 1.159 + } 1.160 + } 1.161 + 1.162 + // An entire row has been decoded. Increment x-position. 1.163 + xpos++; 1.164 + break; 1.165 + 1.166 + case 0x0c: // FF 1.167 + printf("Formfeed: Print without label feed (job completed, more labels follow)\n"); 1.168 + exit = true; 1.169 + break; 1.170 + 1.171 + case 0x1a: // Ctrl-Z 1.172 + printf("Ctrl-Z: Print with label feed (job completed, no further labels)\n"); 1.173 + exit = true; 1.174 + break; 1.175 + 1.176 + default: // Something else 1.177 + printf("** Unrecognised command prefix in gfx mode: 0x%02x\n", ch); 1.178 + break; 1.179 + } 1.180 + } 1.181 + 1.182 + // Display the contents of the image 1.183 + img.display(); 1.184 +} 1.185 + 1.186 +// Parse an ESC i command 1.187 +void parse_esc_i() 1.188 +{ 1.189 + unsigned char ch = getNext(); 1.190 + unsigned int tmpI; 1.191 + 1.192 + switch (ch) { 1.193 + case 'B': // ESC i B: Specify baud rate 1.194 + tmpI = getNext(); 1.195 + ch = getNext(); 1.196 + tmpI += ((int)ch)*256; 1.197 + printf("Set baud rate:\t%d00", tmpI); 1.198 + if ((tmpI != 96) && (tmpI != 576) && (tmpI != 1152)) { 1.199 + printf(" [ILLEGAL SETTING]\n"); 1.200 + } else { 1.201 + printf("\n"); 1.202 + } 1.203 + break; 1.204 + 1.205 + case 'S': // ESC i S: Status request 1.206 + printf("Printer status request\n"); 1.207 + break; 1.208 + 1.209 + case 'M': // ESC i M: Set mode 1.210 + ch = getNext(); 1.211 + printf("Set mode 0x%02X:\tAutoCut %s, Mirror %s\n", ch, 1.212 + (ch & 0x40) ? "on" : "off", 1.213 + (ch & 0x80) ? "on" : "off"); 1.214 + break; 1.215 + 1.216 + case 'd': // ESC i d: Set margin amount (feed amount) 1.217 + tmpI = getNext(); 1.218 + ch = getNext(); 1.219 + tmpI += ((int)ch)*256; 1.220 + printf("Set margin:\t%d dots", tmpI); 1.221 + break; 1.222 + 1.223 + case 'K': // ESC i K: Set expanded mode 1.224 + ch = getNext(); 1.225 + printf("Set expanded mode 0x%02X:\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n", ch, 1.226 + (ch & 0x04) ? "Half-cut on" : "Half-cut off", 1.227 + (ch & 0x08) ? "Chain-print off: last label will be fed and cut" : "Chain-print on: last label will NOT be fed or cut", 1.228 + (ch & 0x20) ? "Label end cut: when printing multiple copies, end of last label is cut" : "Label end cut off", 1.229 + (ch & 0x40) ? "High-resolution (360x720dpi)" : "Normal resolution (360x360dpi)", 1.230 + (ch & 0x80) ? "Copy-printing on (expansion buffer not cleared on form-feed)" : "Copy-printing off" 1.231 + ); 1.232 + break; 1.233 + 1.234 + case 'R': // ESC i R: Set graphics transfer mode 1.235 + ch = getNext(); 1.236 + printf("Set graphics transfer mode 0x%02X: ", ch); 1.237 + if (ch == 1) { 1.238 + printf("Raster graphics mode\n"); 1.239 + runGraphicsXferMode1(); 1.240 + } else { 1.241 + printf("\n\tUnrecognised graphics transfer mode: remainder of data may be garbage.\n"); 1.242 + } 1.243 + break; 1.244 + 1.245 + default: 1.246 + printf("Unrecognised cmnd: ESC i 0x%02X\n", ch); 1.247 + break; 1.248 + } 1.249 +} 1.250 + 1.251 +// Parse an ESC command 1.252 +void parse_esc() 1.253 +{ 1.254 + unsigned char ch = getNext(); 1.255 + 1.256 + switch(ch) { 1.257 + case 'i': // ESC i: Brother-specific extensions 1.258 + parse_esc_i(); 1.259 + break; 1.260 + 1.261 + case '@': // ESC @: Initialize 1.262 + printf("Initialize: clear buffer and reset print origin\n"); 1.263 + break; 1.264 + 1.265 + default: 1.266 + printf("Unrecognised cmnd: ESC 0x%02X\n", ch); 1.267 + break; 1.268 + } 1.269 +} 1.270 + 1.271 +int main(int argc, char **argv) 1.272 +{ 1.273 + // check params 1.274 + if (argc != 2) { 1.275 + // wrong! 1.276 + printf("Usage: %s filename\n", argv[0]); 1.277 + return -1; 1.278 + } 1.279 + 1.280 + // open binary dump file 1.281 + fp = fopen(argv[1], "rb"); 1.282 + if (!fp) { 1.283 + printf("Error opening source file\n"); 1.284 + return -1; 1.285 + } 1.286 + 1.287 + try { 1.288 + while (true) { 1.289 + unsigned char ch; 1.290 + 1.291 + ch = getNext(); 1.292 + 1.293 + switch (ch) { 1.294 + case 0x00: // NULL 1.295 + printf("Null\n"); 1.296 + break; 1.297 + case 0x0c: // FF 1.298 + printf("Formfeed: Print without feed\n"); 1.299 + break; 1.300 + case 0x1a: // Ctrl-Z 1.301 + printf("Ctrl-Z: Print with label feed\n"); 1.302 + break; 1.303 + case 0x1b: // ESC 1.304 + parse_esc(); 1.305 + break; 1.306 + default: 1.307 + printf("Unrecognised cmnd: 0x%02X\n", ch); 1.308 + break; 1.309 + } 1.310 + } 1.311 + } catch (EReadError &e) { 1.312 + if (feof(fp)) { 1.313 + printf("EOF reached.\n"); 1.314 + } else { 1.315 + printf("Uncaught EReadException: %s\n", e.what()); 1.316 + } 1.317 + } catch (exception &e) { 1.318 + printf("Uncaught exception: %s\n", e.what()); 1.319 + } catch (...) { 1.320 + printf("Uncaught and unrecognised exception. Something went *really* wrong here...\n"); 1.321 + } 1.322 + 1.323 + // close the file 1.324 + fclose(fp); 1.325 + 1.326 + return 0; 1.327 +}