PTdecode/src/main.cpp

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