Wed, 05 Aug 2009 15:04:55 +0100
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 *