├── rastertozj ├── install ├── Makefile ├── extras └── camera.sh ├── LICENSE ├── README.md ├── gv2_thermal_printer_config.py ├── ZJ-58.ppd └── rastertozj.c /rastertozj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/zj-58/HEAD/rastertozj -------------------------------------------------------------------------------- /install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Installs zj-58 driver 4 | # Tested as working under Ubuntu 14.04 5 | 6 | systemctl stop cups 7 | cp rastertozj /usr/lib/cups/filter/ 8 | mkdir -p /usr/share/cups/model/zjiang 9 | cp ZJ-58.ppd /usr/share/cups/model/zjiang/ 10 | cd /usr/lib/cups/filter 11 | chmod 755 rastertozj 12 | chown root:root rastertozj 13 | cd - 14 | systemctl start cups 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | RM=rm -f 3 | CFLAGS=-Wl,-rpath,/usr/lib -Wall -fPIC -O3 -std=gnu89 4 | LDFLAGS= 5 | LDLIBS=-lcupsimage -lcups 6 | 7 | SRCS=rastertozj.c 8 | OBJS=$(subst .c,.o,$(SRCS)) 9 | 10 | all: rastertozj 11 | 12 | rastertozj: $(OBJS) 13 | gcc $(LDFLAGS) -o rastertozj rastertozj.o $(LDLIBS) 14 | 15 | rastertozj.o: rastertozj.c 16 | gcc $(CFLAGS) -c rastertozj.c 17 | 18 | clean: 19 | rm -f rastertozj rastertozj.o 20 | -------------------------------------------------------------------------------- /extras/camera.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SHUTTER=16 4 | HALT=21 5 | LED=5 6 | 7 | # Initialize GPIO states 8 | gpio -g mode $SHUTTER up 9 | gpio -g mode $HALT up 10 | gpio -g mode $LED out 11 | 12 | # Flash LED on startup to indicate ready state 13 | for i in `seq 1 5`; 14 | do 15 | gpio -g write $LED 1 16 | sleep 0.2 17 | gpio -g write $LED 0 18 | sleep 0.2 19 | done 20 | 21 | while : 22 | do 23 | # Check for shutter button 24 | if [ $(gpio -g read $SHUTTER) -eq 0 ]; then 25 | gpio -g write $LED 1 26 | raspistill -n -t 200 -w 512 -h 384 -o - | lp 27 | sleep 1 28 | # Wait for user to release button before resuming 29 | while [ $(gpio -g read $SHUTTER) -eq 0 ]; do continue; done 30 | gpio -g write $LED 0 31 | fi 32 | 33 | # Check for halt button 34 | if [ $(gpio -g read $HALT) -eq 0 ]; then 35 | # Must be held for 2+ seconds before shutdown is run... 36 | starttime=$(date +%s) 37 | while [ $(gpio -g read $HALT) -eq 0 ]; do 38 | if [ $(($(date +%s)-starttime)) -ge 2 ]; then 39 | gpio -g write $LED 1 40 | shutdown -h now 41 | fi 42 | done 43 | fi 44 | done 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Aleksey N. Vinogradov 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # !!! NOTE !!! 2 | # THIS REPOSITORY IS ARCHIVED AND IS NO LONGER SUPPORTED OR MAINTAINED 3 | 4 | 5 | zj-58 6 | ===== 7 | 8 | CUPS filter for thermal printer Zjiang ZJ-58 9 | 10 | The linux driver provided on Zjiang site unfortunately doesn't work. 11 | First, it is 32-bit binary (and so, on x64 system need some x86 libs to be installed). 12 | Second, it's PPD is not correct - it just doesn't show any advanced settings because of it. 13 | Finally, raster filter just crashes on any try to run it! 14 | But even if you run it, you'll see that it's working with printer is not optimal: for example, if it sees a blank line, it will send the blank raster to print (instead of just use 'feeding' command, which is definitely faster!) 15 | 16 | This is the solution: 17 | PPD is fixed and works. 18 | Filter is provided as src (you can found a list of packages need to be installed in order to build it in the header of source). 19 | Also, printing of blank lines is optimized. 20 | 21 | In order to re-compile the binary (e.g. on a Raspberry Pi), the following libraries must be installed. 22 | 23 | On Debian-based distros (e.g. Raspberry OS, Ubuntu, Mint...) run: 24 | ``` 25 | sudo apt-get install libcups2-dev libcupsimage2-dev g++ cups cups-client 26 | ``` 27 | On Arch-based distros (e.g. Arch, Manjaro...) run: 28 | ``` 29 | sudo pacman -S base-devel cups cups-filters cups-pdf libcups system-config-printer lib32-libcups cups-pk-helper 30 | ``` 31 | 32 | After that, `make` and `sudo ./install` do the right thing. 33 | -------------------------------------------------------------------------------- /gv2_thermal_printer_config.py: -------------------------------------------------------------------------------- 1 | """ 2 | Configurator for thermal printers with "GV2" firmware. Sets printer's 3 | flow control to XON/XOFF and baudrate to 19200, for Raspberry Pi CUPS usage. 4 | Settings are stored in printer's nonvolatile memory, so this config should 5 | only be needed once. This is NOT for older 2.X printers! 6 | """ 7 | 8 | import serial 9 | 10 | PORT = "/dev/ttyS0" # Could be commandline args, but for now... 11 | BAUD = 19200 12 | ser = serial.Serial(PORT, BAUD, timeout=0.5) 13 | 14 | def send(cmd, expect): 15 | """ Issues command bytes to serial port, compares expected response 16 | against actual response. Returns True if match, else False. """ 17 | #print(">", cmd) 18 | ser.write(cmd) 19 | response = ser.read(len(expect)) 20 | #print("<", response) 21 | return response == expect 22 | 23 | # Raw byte commands and responses for printer. HELLO and GOODBYE commands 24 | # are returned verbatim, while the config commands have distinct responses. 25 | # These sequences were taken directly from the debug log of the Windows 26 | # printer config tool...some of these steps seem odd (HELLO appears to 27 | # change the baud rate to 115200, and the GOODBYEs set it back) and could 28 | # maybe be eliminated...but we have NO documentation for these particular 29 | # commands, so we'll do things exactly by the letter, because the 30 | # alternative could be a bricked printer (ask how I know). 31 | 32 | HELLO = b"\x02\x00\x31\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x37\x00" 33 | FLOW_CMD1 = (b"\x02\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08" 34 | b"\x00\x3A\x00\x01\x02\x04\x08\x10\x20\x40\x80\xFF") 35 | FLOW_RESPONSE1 = (b"\x02\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0A\x00" 36 | b"\x38\x00\x41\x32\x00\x00\x00\x00\x00\x00\x00\x01\x72") 37 | FLOW_CMD2 = (b"\x02\x00\x8D\x00\x00\x00\x00\x00\x00" 38 | b"\x00\x00\x00\x01\x00\x8E\x00\x00\x00") 39 | FLOW_RESPONSE2 = (b"\x02\x00\x8D\x00\x00\x00\x00\x00" 40 | b"\x00\x00\x00\x00\x00\x00\x8F\x00") 41 | FLOW_GOODBYE = (b"\x02\x00\x31\x00\x01\x00\x00\x00" 42 | b"\x00\x00\x00\x00\x00\x00\x32\x00") 43 | BAUD_CMD = (b"\x02\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08" 44 | b"\x00\x3A\x00\x01\x02\x04\x08\x10\x20\x40\x80\xFF") 45 | BAUD_RESPONSE = (b"\x02\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0A\x00" 46 | b"\x38\x00\x41\x32\x00\x00\x00\x00\x00\x00\x00\x01\x72") 47 | BAUD_GOODBYE = (b"\x02\x00\x81\x00\x00\x00\x00\x00\x00" 48 | b"\x00\x00\x00\x01\x00\x82\x00\x01\x01") 49 | 50 | print("Setting flow control...", end="") 51 | STATUS = False 52 | if send(HELLO, HELLO): 53 | ser.baudrate = 115200 54 | STATUS = (send(FLOW_CMD1, FLOW_RESPONSE1) and 55 | send(FLOW_CMD2, FLOW_RESPONSE2) and 56 | send(FLOW_GOODBYE, FLOW_GOODBYE)) 57 | print("OK!" if STATUS else "no.") 58 | 59 | print("Setting baudrate...", end="") 60 | ser.baudrate = BAUD 61 | STATUS = False 62 | if send(HELLO, HELLO): 63 | ser.baudrate = 115200 64 | STATUS = (send(BAUD_CMD, BAUD_RESPONSE) and 65 | send(BAUD_GOODBYE, BAUD_GOODBYE)) 66 | print("OK!" if STATUS else "no.") 67 | 68 | ser.close() 69 | -------------------------------------------------------------------------------- /ZJ-58.ppd: -------------------------------------------------------------------------------- 1 | *PPD-Adobe: "4.3" 2 | *FormatVersion: "4.3" 3 | *FileVersion: "1.1" 4 | *LanguageVersion: English 5 | *LanguageEncoding: ISOLatin1 6 | *PCFileName: "zj58.ppd" 7 | *Manufacturer: "Zijiang" 8 | *Product: "(zj-58)" 9 | *1284DeviceID: "MFG:Zijiang;CMD:Zijiang;MDL:ZJ-58;CLS:PRINTER;" 10 | *cupsVersion: 1.1 11 | *cupsManualCopies: True 12 | *cupsModelNumber: 58 13 | *cupsFilter: "application/vnd.cups-raster 0 rastertozj" 14 | *ModelName: "ZJ-58" 15 | *ShortNickName: "ZJ-58" 16 | *NickName: "Zijiang ZJ-58" 17 | *PSVersion: "(3010.000) 550" 18 | *LanguageLevel: "3" 19 | *ColorDevice: False 20 | *DefaultColorSpace: Gray 21 | *FileSystem: False 22 | *Throughput: "1" 23 | *LandscapeOrientation: Plus90 24 | *VariablePaperSize: True 25 | *TTRasterizer: Type42 26 | 27 | *OpenUI *PageSize/Media Size: PickOne 28 | *OrderDependency: 10 AnySetup *PageSize 29 | *DefaultPageSize: X48MMY64MM 30 | 31 | *PageSize X48MMY64MM/58mm x 74mm: "<>setpagedevice" 32 | *PageSize X48MMY210MM/58mm x 210mm: "<>setpagedevice" 33 | *PageSize X48MMY297MM/58mm x 297mm: "<>setpagedevice" 34 | *PageSize X48MMY3276MM/58mm x 3276mm: "<>setpagedevice" 35 | 36 | *CloseUI: *PageSize 37 | 38 | *OpenUI *PageRegion: PickOne 39 | *OrderDependency: 10 AnySetup *PageRegion 40 | *DefaultPageRegion: X48MMY64MM 41 | 42 | *PageRegion X48MMY64MM/58mm x 74mm: "<>setpagedevice" 43 | *PageRegion X48MMY210MM/58mm x 210mm: "<>setpagedevice" 44 | *PageRegion X48MMY297MM/58mm x 297mm: "<>setpagedevice" 45 | *PageRegion X48MMY3276MM/58mm x 3276mm: "<>setpagedevice" 46 | 47 | *DefaultImageableArea: X48MMY64MM 48 | 49 | *ImageableArea X48MMY64MM: "0 0 136 181" 50 | *ImageableArea X48MMY210MM: "0 0 136 595" 51 | *ImageableArea X48MMY297MM: "0 0 136 842" 52 | *ImageableArea X48MMY3276MM: "0 0 136 9286" 53 | 54 | *DefaultPaperDimension: X48MMY64MM 55 | 56 | *PaperDimension X48MMY64MM: "136 181" 57 | *PaperDimension X48MMY210MM: "136 595" 58 | *PaperDimension X48MMY297MM: "136 842" 59 | *PaperDimension X48MMY3276MM: "136 9286" 60 | 61 | *MaxMediaWidth: "136" 62 | *MaxMediaHeight: "9286" 63 | *HWMargins: 0 0 0 0 64 | *CustomPageSize True: "pop pop pop <>setpagedevice" 65 | *ParamCustomPageSize Width: 1 points 48 136 66 | *ParamCustomPageSize Height: 2 points 48 9282 67 | *ParamCustomPageSize WidthOffset: 3 points 0 0 68 | *ParamCustomPageSize HeightOffset: 4 points 0 0 69 | *ParamCustomPageSize Orientation: 5 int 0 0 70 | 71 | *OpenGroup: CutGroup/Cut Options 72 | *OpenUI *FeedDist/Feed distance after print: PickOne 73 | *DefaultFeedDist: 4feed15mm 74 | *FeedDist 0feed3mm/feed 3mm: "" 75 | *FeedDist 1feed6mm/feed 6mm: "" 76 | *FeedDist 2feed9mm/feed 9mm: "" 77 | *FeedDist 3feed12mm/feed 12mm: "" 78 | *FeedDist 4feed15mm/feed 15mm: "" 79 | *FeedDist 5feed18mm/feed 18mm: "" 80 | *FeedDist 6feed21mm/feed 21mm: "" 81 | *FeedDist 7feed24mm/feed 24mm: "" 82 | *FeedDist 8feed27mm/feed 27mm: "" 83 | *FeedDist 9feed30mm/feed 30mm: "" 84 | *FeedDist 10feed33mm/feed 33mm: "" 85 | *FeedDist 11feed36mm/feed 36mm: "" 86 | *FeedDist 12feed39mm/feed 39mm: "" 87 | *FeedDist 13feed42mm/feed 42mm: "" 88 | *FeedDist 14feed45mm/feed 45mm: "" 89 | *CloseUI: *FeedDist 90 | 91 | 92 | *OpenUI *BlankSpace/Blank space at page's end: PickOne 93 | *DefaultBlankSpace: 1NoPrint 94 | *BlankSpace 0Print/Print: "" 95 | *BlankSpace 1NoPrint/Do not print: "" 96 | *CloseUI: *BlankSpace 97 | 98 | *CloseGroup: *CutGroup 99 | 100 | *OpenGroup: *CashDrawerGroup/Cash Drawer Control 101 | *OpenUI *CashDrawer1Setting/Cash Drawer 1: PickOne 102 | *DefaultCashDrawer1Setting: 0NotCashDrawer1 103 | *CashDrawer1Setting 0NotCashDrawer1/Not Cash Drawer 1: "" 104 | *CashDrawer1Setting 1NotCashDrawer1BeforePrinting/Cash Drawer 1 Before Printing: "" 105 | *CashDrawer1Setting 2NotCashDrawer1BeforePrinting/Cash Drawer 1 After Printing: "" 106 | *CloseUI: *CashDrawer1Setting 107 | 108 | *OpenUI *CashDrawer2Setting/Cash Drawer 2: PickOne 109 | *DefaultCashDrawer2Setting: 0NotCashDrawer2 110 | *CashDrawer2Setting 0NotCashDrawer2/Not Cash Drawer 2: "" 111 | *CashDrawer2Setting 1NotCashDrawer2BeforePrinting/Cash Drawer 2 Before Printing: "" 112 | *CashDrawer2Setting 2NotCashDrawer2BeforePrinting/Cash Drawer 2 After Printing: "" 113 | *CloseUI: *CashDrawer2Setting 114 | *CloseGroup: *CashDrawerGroup 115 | 116 | 117 | *% End 118 | -------------------------------------------------------------------------------- /rastertozj.c: -------------------------------------------------------------------------------- 1 | // To get required headers, run 2 | // sudo apt-get install libcups2-dev libcupsimage2-dev 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // uncomment next line in order to have verbose dump in DEBUGFILE 11 | // after print 12 | 13 | //#define DEBUGP 14 | 15 | #define DEBUGFILE "/tmp/debugraster.txt" 16 | 17 | struct settings_ 18 | { 19 | int cashDrawer1; 20 | int cashDrawer2; 21 | int blankSpace; 22 | int feedDist; 23 | }; 24 | struct settings_ settings; 25 | 26 | struct command 27 | { 28 | int length; 29 | char* command; 30 | }; 31 | 32 | // define printer initialize command 33 | static const struct command printerInitializeCommand = 34 | {2,(char[2]){0x1b,0x40}}; 35 | 36 | // define cashDrawerEjector command 37 | static const struct command cashDrawerEject [2] = 38 | {{5,(char[5]){0x1b,0x70,0,0x40,0x50}}, 39 | {5,(char[5]){0x1b,0x70,1,0x40,0x50}}}; 40 | 41 | // define raster mode start command 42 | static const struct command rasterModeStartCommand = 43 | {4,(char[4]){0x1d,0x76,0x30,0}}; 44 | 45 | #ifdef DEBUGP 46 | FILE* lfd = 0; 47 | #endif 48 | 49 | // putchar with debug wrapper 50 | inline void mputchar(char c) 51 | { 52 | unsigned char m = c; 53 | #ifdef DEBUGP 54 | if (lfd) 55 | fprintf (lfd,"%02x ",m); 56 | #endif 57 | putchar(m); 58 | } 59 | 60 | // procedure to output an array 61 | inline void outputarray(const char * array, int length) 62 | { 63 | int i = 0; 64 | for (;i>8); 82 | } 83 | 84 | // enter raster mode and set up x and y dimensions 85 | inline void rasterheader(int xsize, int ysize) 86 | { 87 | outputCommand(rasterModeStartCommand); 88 | mputchar(lo(xsize)); 89 | mputchar(hi(xsize)); 90 | mputchar(lo(ysize)); 91 | mputchar(hi(ysize)); 92 | } 93 | 94 | // print all unprinted (i.e. flush the buffer) 95 | // then feed given number of lines 96 | inline void skiplines(int size) 97 | { 98 | mputchar(0x1b); 99 | mputchar(0x4a); 100 | mputchar(size); 101 | } 102 | 103 | // get an option 104 | inline int getOptionChoiceIndex(const char * choiceName, ppd_file_t * ppd) 105 | { 106 | ppd_choice_t * choice; 107 | ppd_option_t * option; 108 | 109 | choice = ppdFindMarkedChoice(ppd, choiceName); 110 | 111 | if (choice == NULL) 112 | { 113 | if ((option = ppdFindOption(ppd, choiceName)) == NULL) return -1; 114 | if ((choice = ppdFindChoice(option,option->defchoice)) == NULL) return -1; 115 | } 116 | 117 | return atoi(choice->choice); 118 | } 119 | 120 | 121 | void initializeSettings(char * commandLineOptionSettings) 122 | { 123 | ppd_file_t * ppd = NULL; 124 | cups_option_t * options = NULL; 125 | int numOptions = 0; 126 | 127 | ppd = ppdOpenFile(getenv("PPD")); 128 | 129 | ppdMarkDefaults(ppd); 130 | 131 | numOptions = cupsParseOptions(commandLineOptionSettings, 0, &options); 132 | if ((numOptions != 0) && (options != NULL)) 133 | { 134 | cupsMarkOptions(ppd, numOptions, options); 135 | cupsFreeOptions(numOptions, options); 136 | } 137 | 138 | memset(&settings, 0x00, sizeof(struct settings_)); 139 | 140 | settings.cashDrawer1 = getOptionChoiceIndex("CashDrawer1Setting", ppd); 141 | settings.cashDrawer2 = getOptionChoiceIndex("CashDrawer2Setting", ppd); 142 | settings.blankSpace = getOptionChoiceIndex("BlankSpace" , ppd); 143 | settings.feedDist = getOptionChoiceIndex("FeedDist" , ppd); 144 | 145 | ppdClose(ppd); 146 | } 147 | 148 | // sent on the beginning of print job 149 | void jobSetup() 150 | { 151 | if ( settings.cashDrawer1==1 ) 152 | outputCommand(cashDrawerEject[0]); 153 | if ( settings.cashDrawer2==1 ) 154 | outputCommand(cashDrawerEject[1]); 155 | outputCommand(printerInitializeCommand); 156 | } 157 | 158 | // sent at the very end of print job 159 | void ShutDown() 160 | { 161 | if ( settings.cashDrawer1==2 ) 162 | outputCommand(cashDrawerEject[0]); 163 | if ( settings.cashDrawer2==2 ) 164 | outputCommand(cashDrawerEject[1]); 165 | outputCommand(printerInitializeCommand); 166 | } 167 | 168 | // sent at the end of every page 169 | __sighandler_t old_signal; 170 | void EndPage() 171 | { 172 | int i; 173 | for (i=0; i 7) 208 | { 209 | fputs("ERROR: rastertozj job-id user title copies options [file]\n", stderr); 210 | return EXIT_FAILURE; 211 | } 212 | 213 | if (argc == 7) 214 | { 215 | if ((fd = open(argv[6], O_RDONLY)) == -1) 216 | { 217 | perror("ERROR: Unable to open raster file - "); 218 | sleep(1); 219 | return EXIT_FAILURE; 220 | } 221 | } else 222 | fd = 0; 223 | 224 | #ifdef DEBUGP 225 | lfd = fopen ("/tmp/raster.txt","w"); 226 | #endif 227 | 228 | initializeSettings(argv[5]); 229 | jobSetup(); 230 | ras = cupsRasterOpen(fd, CUPS_RASTER_READ); 231 | page = 0; 232 | 233 | while (cupsRasterReadHeader2(ras, &header)) 234 | { 235 | if ((header.cupsHeight == 0) || (header.cupsBytesPerLine == 0)) 236 | break; 237 | 238 | #ifdef DEBUGP 239 | if (lfd) fprintf(lfd,"\nheader.cupsHeight=%d, header.cupsBytesPerLine=%d\n",header.cupsHeight,header.cupsBytesPerLine); 240 | #endif 241 | 242 | if (rasterData == NULL) 243 | { 244 | rasterData = malloc(header.cupsBytesPerLine*24); 245 | if (rasterData == NULL) 246 | { 247 | if (originalRasterDataPtr != NULL) free(originalRasterDataPtr); 248 | cupsRasterClose(ras); 249 | if (fd != 0) 250 | close(fd); 251 | return EXIT_FAILURE; 252 | 253 | } 254 | originalRasterDataPtr = rasterData; // used to later free the memory 255 | } 256 | 257 | fprintf(stderr, "PAGE: %d %d\n", ++page, header.NumCopies); 258 | pageSetup(); 259 | 260 | int foo = ( header.cupsWidth > 0x180 ) ? 0x180 : header.cupsWidth; 261 | foo = (foo+7) & 0xFFFFFFF8; 262 | int width_size = foo >> 3; 263 | 264 | #ifdef DEBUGP 265 | if (lfd) fprintf(lfd,"\nheader.cupsWidth=%d, foo=%d, width_size=%d\n",header.cupsWidth,foo,width_size); 266 | #endif 267 | y = 0; 268 | int zeroy = 0; 269 | 270 | while ( y < header.cupsHeight ) 271 | { 272 | if ((y & 127) != 0) 273 | fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", page, (100 * y / header.cupsHeight)); 274 | 275 | int rest = header.cupsHeight-y; 276 | if (rest>24) 277 | rest=24; 278 | 279 | #ifdef DEBUGP 280 | if (lfd) fprintf(lfd,"\nProcessing block of %d, starting from %d lines\n",rest,y); 281 | #endif 282 | y+=rest; 283 | 284 | if (y) 285 | { 286 | unsigned char * buf = rasterData; 287 | int j; 288 | for ( j=0; j=rest_bytes) 309 | { 310 | ++zeroy; 311 | continue; 312 | } 313 | 314 | for (;zeroy>0;--zeroy) 315 | skiplines(24); 316 | 317 | rasterheader(width_size,rest); 318 | outputarray((char*)rasterData,rest_bytes); 319 | skiplines(0); 320 | } 321 | 322 | if (!settings.blankSpace) 323 | for(;zeroy>0;--zeroy) 324 | skiplines(24); 325 | 326 | EndPage(); 327 | } 328 | 329 | ShutDown(); 330 | 331 | if (originalRasterDataPtr != NULL) free(originalRasterDataPtr); 332 | cupsRasterClose(ras); 333 | if (fd != 0) 334 | close(fd); 335 | 336 | if (page == 0) 337 | fputs("ERROR: No pages found!\n", stderr); 338 | else 339 | fputs("INFO: Ready to print.\n", stderr); 340 | 341 | #ifdef DEBUGP 342 | if (lfd) 343 | fclose(lfd); 344 | #endif 345 | 346 | return (page == 0)?EXIT_FAILURE:EXIT_SUCCESS; 347 | } 348 | 349 | // end of rastertozj.c 350 | --------------------------------------------------------------------------------