Fixed printing so uncompressed mode is no longer used; now sends an uncompressed Packbits stream instead.

Wed, 05 Aug 2009 15:04:55 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Wed, 05 Aug 2009 15:04:55 +0100
changeset 14
088286f9e1e4
parent 13
a933b13e087f
child 15
e5577dd259c6

Fixed printing so uncompressed mode is no longer used; now sends an uncompressed Packbits stream instead.
Added SetOption and GetOption, so can now turn autocut and mirror on and off. Defaults to both off after init.

src/ptouch.c file | annotate | diff | revisions
src/ptouch.h file | annotate | diff | revisions
     1.1 --- a/src/ptouch.c	Wed Aug 05 15:02:31 2009 +0100
     1.2 +++ b/src/ptouch.c	Wed Aug 05 15:04:55 2009 +0100
     1.3 @@ -11,6 +11,10 @@
     1.4  // TODO: disable
     1.5  #define DEBUG
     1.6  
     1.7 +// This debug option forces Request Status to always "see" a good status
     1.8 +// block. Mostly useful for testing using write-to-file mode.
     1.9 +#define DEBUG_SKIP_STATUS_READ
    1.10 +
    1.11  #include <stdio.h>
    1.12  #include <stdlib.h>
    1.13  #include <stdbool.h>
    1.14 @@ -56,6 +60,18 @@
    1.15  
    1.16  int pt_GetStatus(pt_Device *dev)
    1.17  {
    1.18 +#ifdef DEBUG_SKIP_STATUS_READ
    1.19 +	unsigned char buf[32];
    1.20 +	memset(buf, 0x00, 32);
    1.21 +	buf[0] = 0x80;
    1.22 +	buf[1] = 0x20;
    1.23 +	buf[2] = 0x42;
    1.24 +	buf[3] = 0x30;
    1.25 +	buf[4] = 0x4b;
    1.26 +	buf[5] = 0x30;
    1.27 +	buf[10] = 0x0c;
    1.28 +	buf[11] = 0x01;
    1.29 +#else
    1.30  	// REQUEST STATUS
    1.31  	fprintf(dev->fp, "%c%c%c", ESC, 'i', 'S');
    1.32  
    1.33 @@ -71,6 +87,7 @@
    1.34  		// Timeout
    1.35  		return PT_ERR_TIMEOUT;
    1.36  	}
    1.37 +#endif
    1.38  
    1.39  #ifdef DEBUG
    1.40  	printf("DEBUG: Printer status buffer = \n");
    1.41 @@ -104,16 +121,60 @@
    1.42  		dev->pixelWidth = ((dev->mediaWidth * 180 * 10) / 254) - 2;
    1.43  	}
    1.44  
    1.45 +	// Set printing parameters to defaults --
    1.46 +	//   Mirror off
    1.47 +	//   Autocut on
    1.48 +	dev->mirror = false;
    1.49 +	dev->autocut = false;
    1.50 +
    1.51  	// Operation succeeded
    1.52  	return PT_ERR_SUCCESS;
    1.53  }
    1.54  
    1.55 -// TODO: print options struct parameter (e.g. fullcut, halfcut, print res, ...)
    1.56 -//
    1.57 -//
    1.58 +int pt_SetOption(pt_Device *dev, PT_E_OPTION option, int value)
    1.59 +{
    1.60 +	// trap dev == NULL
    1.61 +	if (dev == NULL) {
    1.62 +		return PT_ERR_BAD_PARAMETER;
    1.63 +	}
    1.64 +
    1.65 +	// set option
    1.66 +	switch(option) {
    1.67 +		case PT_OPTION_MIRROR:			// Mirror
    1.68 +			dev->mirror = (value ? 1 : 0);
    1.69 +			return PT_ERR_SUCCESS;
    1.70 +
    1.71 +		case PT_OPTION_AUTOCUT:		// Auto-cutter enable/disable
    1.72 +			dev->autocut = (value ? 1 : 0);
    1.73 +			return PT_ERR_SUCCESS;
    1.74 +
    1.75 +		default:
    1.76 +			return PT_ERR_BAD_PARAMETER;
    1.77 +	}
    1.78 +}
    1.79  
    1.80 -// labels: 1 or more labels
    1.81 -// count: number of labels, 0<count<MAXINT
    1.82 +int pt_GetOption(pt_Device *dev, PT_E_OPTION option, int *value)
    1.83 +{
    1.84 +	// trap dev == NULL or value == NULL
    1.85 +	if ((dev == NULL) || (value == NULL)) {
    1.86 +		return PT_ERR_BAD_PARAMETER;
    1.87 +	}
    1.88 +
    1.89 +	// get option value
    1.90 +	switch(option) {
    1.91 +		case PT_OPTION_MIRROR:			// Mirror
    1.92 +			*value = dev->mirror;
    1.93 +			return PT_ERR_SUCCESS;
    1.94 +
    1.95 +		case PT_OPTION_AUTOCUT:		// Auto-cutter enable/disable
    1.96 +			*value = dev->autocut;
    1.97 +			return PT_ERR_SUCCESS;
    1.98 +
    1.99 +		default:
   1.100 +			return PT_ERR_BAD_PARAMETER;
   1.101 +	}
   1.102 +}
   1.103 +
   1.104  int pt_Print(pt_Device *dev, gdImagePtr *labels, int count)
   1.105  {
   1.106  	int err;
   1.107 @@ -159,9 +220,11 @@
   1.108  
   1.109  	// M {n1} -- Set Compression Mode
   1.110  	//   {n1} = 0x00 ==> no compression
   1.111 +	//   	Doesn't seem to work on the PT-2450DX...
   1.112  	//   {n1} = 0x01 ==> reserved
   1.113  	//   {n1} = 0x02 ==> TIFF/Packbits
   1.114 -	fprintf(dev->fp, "M%c", 0x00);
   1.115 +	//   	But this works fine on the PT-2450DX...
   1.116 +	fprintf(dev->fp, "M%c", 0x02);
   1.117  
   1.118  	// Loop over the images that were passed in
   1.119  	for (int imnum=0; imnum < count; imnum++) {
   1.120 @@ -170,10 +233,15 @@
   1.121  			return PT_ERR_LABEL_TOO_WIDE;
   1.122  		}
   1.123  
   1.124 -		//
   1.125 -		// TODO: trap image height / width == 0?
   1.126 -		// will libgd allow an image with a zero dimension?
   1.127 -		//
   1.128 +		// Trap a label with a width of zero
   1.129 +		// I'm not sure if this can happen, but it's a single if statement, so
   1.130 +		// probably worth checking anyway...
   1.131 +		if (gdImageSX(*curLabel) == 0) {
   1.132 +			return PT_ERR_LABEL_ZERO_LENGTH;
   1.133 +		}
   1.134 +
   1.135 +		// Get the index of the colour "white" (RGB:255,255,255) in the Gd image
   1.136 +		int col_white = gdImageColorResolve(*curLabel, 255, 255, 255);
   1.137  
   1.138  		// Iterate left-to-right over the source image
   1.139  		for (int xpos = 0; xpos < gdImageSX(*curLabel); xpos++) {
   1.140 @@ -185,12 +253,12 @@
   1.141  
   1.142  			// Calculate left-side margin for this label size
   1.143  			// Again, 128-dot printhead.
   1.144 -			int margin = (128 + dev->pixelWidth) / 2;
   1.145 +			int margin = (128 / 2) - (dev->pixelWidth / 2);
   1.146  
   1.147  			// Copy data from the image to the bit-buffer
   1.148  			for (int ypos = 0; ypos < gdImageSY(*curLabel); ypos++) {
   1.149 -				// Get pixel from gd, is it white (palette entry 0)?
   1.150 -				if (gdImageGetPixel(*curLabel, xpos, ypos) != 0) {
   1.151 +				// Get pixel from gd, is it white?
   1.152 +				if (gdImageGetPixel(*curLabel, xpos, ypos) != col_white) {
   1.153  					// No. Set the bit.
   1.154  					int bit = 1 << (7 - ((margin+ypos) % 8));
   1.155  					bitbuf[(margin+ypos) / 8] |= bit;
   1.156 @@ -211,7 +279,15 @@
   1.157  				// Row is not clear -- send the pixel data
   1.158  				//
   1.159  				// TODO: the printer supports Packbits compression. Implement!
   1.160 -				fprintf(dev->fp, "G");
   1.161 +				// TODO: After Packbits is implemented, ((128/8)+1) must be
   1.162 +				//   changed to the length of the Packbits compressed data.
   1.163 +				//   (note: 128/8 is the printhead size in bytes, the +1 is for
   1.164 +				//   the control byte we add below...)
   1.165 +				fprintf(dev->fp, "G%c%c", ((128/8)+1) & 0xff, ((128/8)+1) >> 8);
   1.166 +
   1.167 +				// This printer asks for Packbits compressed data. In this
   1.168 +				// case, we send a "run of N" control byte and fake it...
   1.169 +				fputc(sizeof(bitbuf) - 1, dev->fp);
   1.170  				for (int i=0; i<sizeof(bitbuf); i++) {
   1.171  					fputc(bitbuf[i], dev->fp);
   1.172  				}
     2.1 --- a/src/ptouch.h	Wed Aug 05 15:02:31 2009 +0100
     2.2 +++ b/src/ptouch.h	Wed Aug 05 15:04:55 2009 +0100
     2.3 @@ -59,13 +59,25 @@
     2.4  /// Label image is too large for this label tape
     2.5  	PT_ERR_LABEL_TOO_WIDE		= -3,
     2.6  
     2.7 +/// Label has a length of zero
     2.8 +	PT_ERR_LABEL_ZERO_LENGTH	= -4,
     2.9 +
    2.10  /// Printer is not ready
    2.11 -	PT_ERR_PRINTER_NOT_READY	= -4
    2.12 +	PT_ERR_PRINTER_NOT_READY	= -5
    2.13  };
    2.14  
    2.15 +/*
    2.16 + * Job options
    2.17 + */
    2.18 +typedef enum {
    2.19 +/// Mirror -- mirror the printed label along the long edge
    2.20 +	PT_OPTION_MIRROR,
    2.21 +/// Auto-cutter -- enable or disable automatic label cutting
    2.22 +	PT_OPTION_AUTOCUT
    2.23 +} PT_E_OPTION;
    2.24  
    2.25  /**
    2.26 - * @brief	Initialise the printer
    2.27 + * @brief	Initialise the printer.
    2.28   * 
    2.29   * Initialises the printer and returns a pointer to a pt_Device struct
    2.30   * describing it.
    2.31 @@ -77,7 +89,7 @@
    2.32  pt_Device *pt_Initialise(char *path);
    2.33  
    2.34  /**
    2.35 - * @brief	Close a printer device
    2.36 + * @brief	Close a printer device.
    2.37   *
    2.38   * Closes the connection to the printer, and destroys the pt_Device struct.
    2.39   *
    2.40 @@ -86,7 +98,7 @@
    2.41  void pt_Close(pt_Device *dev);
    2.42  
    2.43  /**
    2.44 - * @brief	Get the current status of the printer
    2.45 + * @brief	Get the current status of the printer.
    2.46   *
    2.47   * Queries the printer for its current status, then returns the result.
    2.48   *
    2.49 @@ -97,7 +109,45 @@
    2.50  int pt_GetStatus(pt_Device *dev);
    2.51  
    2.52  /**
    2.53 - * @brief	Print one or more labels
    2.54 + * @brief	Set a job option for the next print job.
    2.55 + *
    2.56 + * Sets a job option (specified by <b>option</b>) for the next print job.
    2.57 + * These options include printer features like auto-cutting and mirroring
    2.58 + * of the label image.
    2.59 + *
    2.60 + * @param	dev		A pt_Device struct created by pt_Initialise.
    2.61 + * @param	option	One of the PT_OPTION_* constants specifying the parameter
    2.62 + * 	that is to be set.
    2.63 + * @param	value	The value to assign to the job option.
    2.64 + * @return	<b>PT_ERR_BAD_PARAMETER:</b> Either <b>dev</b> was equal to NULL,
    2.65 + * 	or the option value specified in <b>option</b> was invalid.<br>
    2.66 + * 	<b>PT_ERR_SUCCESS:</b> Operation completed successfully, the current value
    2.67 + * 	of the option parameter is now set to the contents of <b>value</b>.
    2.68 + */
    2.69 +int pt_SetOption(pt_Device *dev, PT_E_OPTION option, int value);
    2.70 +
    2.71 +/**
    2.72 + * @brief	Get the current value of a job option for the next print job.
    2.73 + *
    2.74 + * Returns the current value of a job option (specified by <b>option</b>)
    2.75 + * for the next print job.
    2.76 + * These options include printer features like auto-cutting and mirroring
    2.77 + * of the label image.
    2.78 + *
    2.79 + * @param	dev		A pt_Device struct created by pt_Initialise.
    2.80 + * @param	option	One of the PT_OPTION_* constants specifying the parameter
    2.81 + * 	that is to be returned.
    2.82 + * @param	value	A pointer to an <b>int</b> that will contain the value
    2.83 + * 	of the job option.
    2.84 + * @return	<b>PT_ERR_BAD_PARAMETER:</b> Either <b>dev</b> or <b>value</b> was
    2.85 + * 	equal to NULL, or the option value specified in <b>option</b> was invalid.<br>
    2.86 + * 	<b>PT_ERR_SUCCESS:</b> Operation completed successfully, the current value
    2.87 + * 	of the option parameter is now stored in <b>value</b>.
    2.88 + */
    2.89 +int pt_GetOption(pt_Device *dev, PT_E_OPTION option, int *value);
    2.90 +
    2.91 +/**
    2.92 + * @brief	Print one or more labels.
    2.93   *
    2.94   * Takes a pointer to an array of Libgd images, and prints each of them.
    2.95   *