Line 0
Link Here
|
|
|
1 |
--- foo2hbpl1.c.orig 2016-08-11 08:05:24 UTC |
2 |
+++ foo2hbpl1.c |
3 |
@@ -0,0 +1,692 @@ |
4 |
+/* |
5 |
+ |
6 |
+GENERAL |
7 |
+This program converts bilevel PBM, 8-bit PGM, 24-bit PPM, and 32-bit |
8 |
+CMYK PAM files (output by Ghostscript as "pbmraw", "pgmraw", "ppmraw", |
9 |
+and "pamcmyk32" respectively) to HBPL version 1 for the consumption |
10 |
+of various Dell, Epson, and Fuji-Xerox printers. |
11 |
+ |
12 |
+With this utility, you can print to some Dell and Fuji printers, such as these: |
13 |
+ - Dell 1250c B/W and Color |
14 |
+ - Dell C1660 B/W and Color |
15 |
+ - Dell C1760 B/W and Color |
16 |
+ - Epson AcuLaser C1700 B/W and Color |
17 |
+ - Fuji-Xerox DocuPrint CP105 B/W and Color |
18 |
+ |
19 |
+AUTHORS |
20 |
+This program was originally written by Dave Coffin in March 2014. |
21 |
+ |
22 |
+LICENSE |
23 |
+This program is free software; you can redistribute it and/or modify |
24 |
+it under the terms of the GNU General Public License as published by |
25 |
+the Free Software Foundation; either version 2 of the License, or (at |
26 |
+your option) any later version. |
27 |
+ |
28 |
+This program is distributed in the hope that it will be useful, |
29 |
+but WITHOUT ANY WARRANTY; without even the implied warranty of |
30 |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
31 |
+GNU General Public License for more details. |
32 |
+ |
33 |
+You should have received a copy of the GNU General Public License |
34 |
+along with this program; if not, write to the Free Software |
35 |
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
36 |
+ |
37 |
+If you want to use this program under different license conditions, |
38 |
+then contact the author for an arrangement. |
39 |
+ |
40 |
+*/ |
41 |
+ |
42 |
+static char Version[] = "$Id: foo2hbpl1.c,v 1.3 2014/03/30 05:08:32 rick Exp $"; |
43 |
+ |
44 |
+#include <time.h> |
45 |
+#include <stdio.h> |
46 |
+#include <stdlib.h> |
47 |
+#include <ctype.h> |
48 |
+#include <string.h> |
49 |
+#include <unistd.h> |
50 |
+#include <stdarg.h> |
51 |
+#ifdef linux |
52 |
+ #include <sys/utsname.h> |
53 |
+#endif |
54 |
+ |
55 |
+/* |
56 |
+ * Command line options |
57 |
+ */ |
58 |
+int MediaCode = 0; |
59 |
+char *Username = NULL; |
60 |
+char *Filename = NULL; |
61 |
+int Clip[] = { 8,8,8,8 }; |
62 |
+ |
63 |
+void |
64 |
+usage(void) |
65 |
+{ |
66 |
+ fprintf(stderr, |
67 |
+"Usage:\n" |
68 |
+" foo2hbpl1 [options] <pamcmyk32-file >hbpl-file\n" |
69 |
+"\n" |
70 |
+" Convert Ghostscript pbmraw, pgmraw, ppmraw, or pamcmyk32\n" |
71 |
+" format to HBPLv1, for the Dell C1660w and other printers.\n" |
72 |
+"\n" |
73 |
+" gs -q -dBATCH -dSAFER -dQUIET -dNOPAUSE \\ \n" |
74 |
+" -sPAPERSIZE=letter -r600x600 -sDEVICE=pamcmyk32 \\ \n" |
75 |
+" -sOutputFile=- - < testpage.ps \\ \n" |
76 |
+" | foo2hbpl1 >testpage.zc\n" |
77 |
+"\n" |
78 |
+"Options:\n" |
79 |
+"-m media Media code to send to printer [1 or 6]\n" |
80 |
+" 1=plain, 2=bond, 3=lwcard, 4=lwgcard, 5=labels,\n" |
81 |
+" 6=envelope, 7=recycled, 8=plain2, 9=bond2,\n" |
82 |
+" 10=lwcard2, 11=lwgcard2, 12=recycled2\n" |
83 |
+"-u left,top,right,bottom\n" |
84 |
+" Erase margins of specified width [%d,%d,%d,%d]\n" |
85 |
+"-J filename Filename string to send to printer\n" |
86 |
+"-U username Username string to send to printer\n" |
87 |
+"-V Version %s\n" |
88 |
+ , Clip[0], Clip[1], Clip[2], Clip[3] |
89 |
+ , Version); |
90 |
+} |
91 |
+ |
92 |
+void |
93 |
+error(int fatal, char *fmt, ...) |
94 |
+{ |
95 |
+ va_list ap; |
96 |
+ |
97 |
+ va_start(ap, fmt); |
98 |
+ vfprintf(stderr, fmt, ap); |
99 |
+ va_end(ap); |
100 |
+ |
101 |
+ if (fatal) exit(fatal); |
102 |
+} |
103 |
+ |
104 |
+struct stream |
105 |
+{ |
106 |
+ unsigned char *buf; |
107 |
+ int size, off, bits; |
108 |
+}; |
109 |
+ |
110 |
+void |
111 |
+putbits(struct stream *s, unsigned val, int nbits) |
112 |
+{ |
113 |
+ if (s->off + 16 > s->size && |
114 |
+ !(s->buf = realloc(s->buf, s->size += 0x100000))) |
115 |
+ error (1, "Out of memory\n"); |
116 |
+ if (s->bits) |
117 |
+ { |
118 |
+ s->off--; |
119 |
+ val |= s->buf[s->off] >> (8-s->bits) << nbits; |
120 |
+ nbits += s->bits; |
121 |
+ } |
122 |
+ s->bits = nbits & 7; |
123 |
+ while ((nbits -= 8) > 0) |
124 |
+ s->buf[s->off++] = val >> nbits; |
125 |
+ s->buf[s->off++] = val << -nbits; |
126 |
+} |
127 |
+ |
128 |
+/* |
129 |
+ Runlengths are integers between 1 and 17057 encoded as follows: |
130 |
+ |
131 |
+ 1 00 |
132 |
+ 2 01 0 |
133 |
+ 3 01 1 |
134 |
+ 4 100 0 |
135 |
+ 5 100 1 |
136 |
+ 6 101 00 |
137 |
+ 7 101 01 |
138 |
+ 8 101 10 |
139 |
+ 9 101 11 |
140 |
+ 10 110 0000 |
141 |
+ 11 110 0001 |
142 |
+ 12 110 0010 |
143 |
+ ... |
144 |
+ 25 110 1111 |
145 |
+ 26 111 000 000 |
146 |
+ 27 111 000 001 |
147 |
+ 28 111 000 010 |
148 |
+ 29 111 000 011 |
149 |
+ ... |
150 |
+ 33 111 000 111 |
151 |
+ 34 111 001 000 |
152 |
+ ... |
153 |
+ 41 111 001 111 |
154 |
+ 42 111 010 000 |
155 |
+ 50 111 011 0000 |
156 |
+ 66 111 100 00000 |
157 |
+ 98 111 101 000000 |
158 |
+ 162 111 110 000000000 |
159 |
+ 674 111 111 00000000000000 |
160 |
+ 17057 111 111 11111111111111 |
161 |
+*/ |
162 |
+void |
163 |
+put_len(struct stream *s, unsigned val) |
164 |
+{ |
165 |
+ unsigned code[] = |
166 |
+ { |
167 |
+ 1, 0, 2, |
168 |
+ 2, 2, 3, |
169 |
+ 4, 8, 4, |
170 |
+ 6, 0x14, 5, |
171 |
+ 10, 0x60, 7, |
172 |
+ 26, 0x1c0, 9, |
173 |
+ 50, 0x3b0, 10, |
174 |
+ 66, 0x780, 11, |
175 |
+ 98, 0xf40, 12, |
176 |
+ 162, 0x7c00, 15, |
177 |
+ 674, 0xfc000, 20, |
178 |
+ 17058 |
179 |
+ }; |
180 |
+ int c = 0; |
181 |
+ |
182 |
+ if (val < 1 || val > 17057) return; |
183 |
+ while (val >= code[c+3]) c += 3; |
184 |
+ putbits(s, val-code[c] + code[c+1], code[c+2]); |
185 |
+} |
186 |
+ |
187 |
+/* |
188 |
+ CMYK byte differences are encoded as follows: |
189 |
+ |
190 |
+ 0 000 |
191 |
+ +1 001 |
192 |
+ -1 010 |
193 |
+ 2 011s0 s = 0 for +, 1 for - |
194 |
+ 3 011s1 |
195 |
+ 4 100s00 |
196 |
+ 5 100s01 |
197 |
+ 6 100s10 |
198 |
+ 7 100s11 |
199 |
+ 8 101s000 |
200 |
+ 9 101s001 |
201 |
+ ... |
202 |
+ 14 101s110 |
203 |
+ 15 101s111 |
204 |
+ 16 110s00000 |
205 |
+ 17 110s00001 |
206 |
+ 18 110s00010 |
207 |
+ ... |
208 |
+ 46 110s11110 |
209 |
+ 47 110s11111 |
210 |
+ 48 1110s00000 |
211 |
+ 49 1110s00001 |
212 |
+ ... |
213 |
+ 78 1110s11110 |
214 |
+ 79 1110s11111 |
215 |
+ 80 1111s000000 |
216 |
+ 81 1111s000001 |
217 |
+ ... |
218 |
+ 126 1111s101110 |
219 |
+ 127 1111s101111 |
220 |
+ 128 11111110000 |
221 |
+*/ |
222 |
+void |
223 |
+put_diff(struct stream *s, signed char val) |
224 |
+{ |
225 |
+ static unsigned short code[] = |
226 |
+ { |
227 |
+ 2, 3, 3, 1, |
228 |
+ 4, 4, 3, 2, |
229 |
+ 8, 5, 3, 3, |
230 |
+ 16, 6, 3, 5, |
231 |
+ 48, 14, 4, 5, |
232 |
+ 80, 15, 4, 6, |
233 |
+ 129 |
234 |
+ }; |
235 |
+ int sign, abs, c = 0; |
236 |
+ |
237 |
+ switch (val) |
238 |
+ { |
239 |
+ case 0: putbits(s, 0, 3); return; |
240 |
+ case 1: putbits(s, 1, 3); return; |
241 |
+ case -1: putbits(s, 2, 3); return; |
242 |
+ } |
243 |
+ abs = ((sign = val < 0)) ? -val:val; |
244 |
+ while (abs >= code[c+4]) c += 4; |
245 |
+ putbits(s, code[c+1], code[c+2]); |
246 |
+ putbits(s, sign, 1); |
247 |
+ putbits(s, abs-code[c], code[c+3]); |
248 |
+} |
249 |
+ |
250 |
+void |
251 |
+setle(unsigned char *c, int s, int i) |
252 |
+{ |
253 |
+ while (s--) |
254 |
+ { |
255 |
+ *c++ = i; |
256 |
+ i >>= 8; |
257 |
+ } |
258 |
+} |
259 |
+ |
260 |
+void |
261 |
+start_doc(int color) |
262 |
+{ |
263 |
+ char reca[] = { 0x41,0x81,0xa1,0x00,0x82,0xa2,0x07,0x00,0x83,0xa2,0x01,0x00 }; |
264 |
+ time_t t; |
265 |
+ struct tm *tmp; |
266 |
+ char datestr[16], timestr[16]; |
267 |
+ char cname[128] = "My Computer"; |
268 |
+ char *mname[] = |
269 |
+ { "", |
270 |
+ "NORMAL", |
271 |
+ "THICK", |
272 |
+ "HIGHQUALITY", |
273 |
+ "COAT2", |
274 |
+ "LABEL", |
275 |
+ "ENVELOPE", |
276 |
+ "RECYCLED", |
277 |
+ "NORMALREV", |
278 |
+ "THICKSIDE2", |
279 |
+ "HIGHQUALITYREV", |
280 |
+ "COATEDPAPER2REV", |
281 |
+ "RECYCLEREV", |
282 |
+ }; |
283 |
+ |
284 |
+ t = time(NULL); |
285 |
+ tmp = localtime(&t); |
286 |
+ strftime(datestr, sizeof datestr, "%m/%d/%Y", tmp); |
287 |
+ strftime(timestr, sizeof timestr, "%H:%M:%S", tmp); |
288 |
+ |
289 |
+ #ifdef linux |
290 |
+ { |
291 |
+ struct utsname u; |
292 |
+ |
293 |
+ uname(&u); |
294 |
+ strncpy(cname, u.nodename, 128); |
295 |
+ cname[127] = 0; |
296 |
+ } |
297 |
+ #endif |
298 |
+ |
299 |
+/* Lines end with \n, not \r\n */ |
300 |
+ |
301 |
+ printf( |
302 |
+ "\033%%-12345X@PJL SET STRINGCODESET=UTF8\n" |
303 |
+ "@PJL COMMENT DATE=%s\n" |
304 |
+ "@PJL COMMENT TIME=%s\n" |
305 |
+ "@PJL COMMENT DNAME=%s\n" |
306 |
+ "@PJL JOB MODE=PRINTER\n" |
307 |
+ "@PJL SET JOBATTR=\"@LUNA=%s\"\n" |
308 |
+ "@PJL SET JOBATTR=\"@TRCH=OFF\"\n" |
309 |
+ "@PJL SET DUPLEX=OFF\n" |
310 |
+ "@PJL SET BINDING=LONGEDGE\n" |
311 |
+ "@PJL SET IWAMANUALDUP=OFF\n" |
312 |
+ "@PJL SET JOBATTR=\"@MSIP=%s\"\n" |
313 |
+ "@PJL SET RENDERMODE=%s\n" |
314 |
+ "@PJL SET ECONOMODE=OFF\n" |
315 |
+ "@PJL SET RET=ON\n" |
316 |
+ "@PJL SET JOBATTR=\"@IREC=OFF\"\n" |
317 |
+ "@PJL SET JOBATTR=\"@TRAP=ON\"\n" |
318 |
+ "@PJL SET JOBATTR=\"@JOAU=%s\"\n" |
319 |
+ "@PJL SET JOBATTR=\"@CNAM=%s\"\n" |
320 |
+ "@PJL SET COPIES=1\n" |
321 |
+ "@PJL SET QTY=1\n" |
322 |
+ "@PJL SET PAPERDIRECTION=SEF\n" |
323 |
+ "@PJL SET RESOLUTION=600\n" |
324 |
+ "@PJL SET BITSPERPIXEL=8\n" |
325 |
+ "@PJL SET JOBATTR=\"@DRDM=XRC\"\n" |
326 |
+ "@PJL SET JOBATTR=\"@TSCR=11\"\n" |
327 |
+ "@PJL SET JOBATTR=\"@GSCR=11\"\n" |
328 |
+ "@PJL SET JOBATTR=\"@ISCR=12\"\n" |
329 |
+ "@PJL SET JOBATTR=\"@TTRC=11\"\n" |
330 |
+ "@PJL SET JOBATTR=\"@GTRC=11\"\n" |
331 |
+ "@PJL SET JOBATTR=\"@ITRC=12\"\n" |
332 |
+ "@PJL SET JOBATTR=\"@TCPR=11\"\n" |
333 |
+ "@PJL SET JOBATTR=\"@GCPR=11\"\n" |
334 |
+ "@PJL SET JOBATTR=\"@ICPR=12\"\n" |
335 |
+ "@PJL SET JOBATTR=\"@TUCR=11\"\n" |
336 |
+ "@PJL SET JOBATTR=\"@GUCR=11\"\n" |
337 |
+ "@PJL SET JOBATTR=\"@IUCR=12\"\n" |
338 |
+ "@PJL SET JOBATTR=\"@BSPM=OFF\"\n" |
339 |
+ "@PJL SET JOBATTR=\"@TDFT=0\"\n" |
340 |
+ "@PJL SET JOBATTR=\"@GDFT=0\"\n" |
341 |
+ "@PJL SET JOBATTR=\"@IDFT=0\"\n" |
342 |
+ "@PJL ENTER LANGUAGE=HBPL\n" |
343 |
+ , datestr, timestr |
344 |
+ , Filename ? Filename : "" |
345 |
+ , Username ? Username : "" |
346 |
+ , mname[MediaCode] |
347 |
+ , color ? "COLOR" : "GRAYSCALE" |
348 |
+ , Username ? Username : "" |
349 |
+ , cname); |
350 |
+ fwrite (reca, 1, sizeof reca, stdout); |
351 |
+} |
352 |
+ |
353 |
+#define IP (((int *)image) + off) |
354 |
+#define CP (((char *)image) + off) |
355 |
+#define DP (((char *)image) + off*deep) |
356 |
+#define BP(x) ((blank[(off+x) >> 3] << ((off+x) & 7)) & 128) |
357 |
+#define put_token(s,x) putbits(s, huff[hsel][x] >> 4, huff[hsel][x] & 15) |
358 |
+ |
359 |
+void |
360 |
+encode_page(int color, int width, int height, char *image) |
361 |
+{ |
362 |
+ unsigned char head[90] = |
363 |
+ { |
364 |
+ 0x43,0x91,0xa1,0x00,0x92,0xa1,0x01,0x93,0xa1,0x01,0x94,0xa1, |
365 |
+ 0x00,0x95,0xc2,0x00,0x00,0x00,0x00,0x96,0xa1,0x00,0x97,0xc3, |
366 |
+ 0x00,0x00,0x00,0x00,0x98,0xa1,0x00,0x99,0xa4,0x01,0x00,0x00, |
367 |
+ 0x00,0x9a,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9b, |
368 |
+ 0xa1,0x00,0x9c,0xa1,0x01,0x9d,0xa1,0x00,0x9e,0xa1,0x02,0x9f, |
369 |
+ 0xa1,0x05,0xa0,0xa1,0x08,0xa1,0xa1,0x00,0xa2,0xc4,0x00,0x00, |
370 |
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x52,0xa3,0xa1,0x00,0xa4, |
371 |
+ 0xb1,0xa4 |
372 |
+ }; |
373 |
+ unsigned char body[52] = |
374 |
+ { |
375 |
+ 0x20,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x32,0x04,0x00, |
376 |
+ 0xa1,0x42,0x00,0x00,0x00,0x00,0xff |
377 |
+ }; |
378 |
+ static short papers[] = |
379 |
+ { // Official sizes to nearest 1/600 inch |
380 |
+ // will accept +-1.5mm (35/600 inch) tolerance |
381 |
+ 0, 5100, 6600, // Letter |
382 |
+ 2, 5100, 8400, // Legal |
383 |
+ 4, 4961, 7016, // A4 |
384 |
+ 6, 4350, 6300, // Executive |
385 |
+ 13, 2475, 5700, // #10 envelope |
386 |
+ 15, 2325, 4500, // Monarch envelope |
387 |
+ 17, 3827, 5409, // C5 envelope |
388 |
+ 19, 2599, 5197, // DL envelope |
389 |
+// ??, 4158, 5906, // B5 ISO |
390 |
+ 22, 4299, 6071, // B5 JIS |
391 |
+ 30, 3496, 4961, // A5 |
392 |
+ 410, 5100, 7800, // Folio |
393 |
+ }; |
394 |
+ static const unsigned short huff[2][8] = |
395 |
+ { |
396 |
+ { 0x01,0x63,0x1c5,0x1d5,0x1e5,0x22,0x3e6 }, // for text & graphics |
397 |
+ { 0x22,0x63,0x1c5,0x1d5,0x1e5,0x01,0x3e6 }, // for images |
398 |
+ }; |
399 |
+ unsigned char *blank; |
400 |
+ static int pagenum = 0; |
401 |
+ struct stream stream[5] = { { 0 } }; |
402 |
+ int dirs[] = { -1,0,-1,1,2 }, rotor[] = { 0,1,2,3,4 }; |
403 |
+ int i, j, row, col, deep, dir, run, try, bdir, brun, total; |
404 |
+ int paper = 510, hsel = 0, off = 0, bit = 0, stat = 0; |
405 |
+ int margin = width-96; |
406 |
+ |
407 |
+ for (i = 0; i < sizeof papers / sizeof *papers; i++) |
408 |
+ if (abs(width-papers[i+1]) < 36 && abs(height-papers[i+2]) < 36) |
409 |
+ paper = papers[i]; |
410 |
+ if (!MediaCode) |
411 |
+ MediaCode = paper & 1 ? 6 : 1; |
412 |
+ if (!pagenum) |
413 |
+ start_doc(color); |
414 |
+ head[12] = paper >> 1; |
415 |
+ if (paper == 510) |
416 |
+ { |
417 |
+ setle (head+15, 2, (width*254+300)/600); // units of 0.1mm |
418 |
+ setle (head+17, 2, (height*254+300)/600); |
419 |
+ head[21] = 2; |
420 |
+ } |
421 |
+ width = -(-width & -8); |
422 |
+ setle (head+33, 4, ++pagenum); |
423 |
+ setle (head+39, 4, width); |
424 |
+ setle (head+43, 4, height); |
425 |
+ setle (head+70, 4, width); |
426 |
+ setle (head+74, 4, height); |
427 |
+ head[55] = 9 + color*130; |
428 |
+ if (color) body[6] = 1; |
429 |
+ else body[4] = 8; |
430 |
+ |
431 |
+ deep = 1 + color*3; |
432 |
+ for (i=1; i < 5; i++) |
433 |
+ dirs[i] -= width; |
434 |
+ if (!color) dirs[4] = -8; |
435 |
+ |
436 |
+ blank = calloc(height+2, width/8); |
437 |
+ memset (blank++, -color, width/8+1); |
438 |
+ for (row = 1; row <= height; row++) |
439 |
+ { |
440 |
+ for (col = deep; col < deep*2; col++) |
441 |
+ image[row*width*deep + col] = -1; |
442 |
+ for (col = 8; col < width*deep; col += 4) |
443 |
+ if (*(int *)(image + row*width*deep + col)) |
444 |
+ { |
445 |
+ for (col = 12; col < margin/8; col++) |
446 |
+ blank[row*(width/8)+col] = -1; |
447 |
+ blank[row*(width/8)+col] = -2 << (~margin & 7); |
448 |
+ break; |
449 |
+ } |
450 |
+ } |
451 |
+ memset (image, -color, (width+1)*deep); |
452 |
+ image += (width+1)*deep; |
453 |
+ blank += width/8; |
454 |
+ |
455 |
+ while (off < width * height) |
456 |
+ { |
457 |
+ for (bdir = brun = dir = 0; dir < 5; dir++) |
458 |
+ { |
459 |
+ try = dirs[rotor[dir]]; |
460 |
+ for (run = 0; run < 17057; run++, try++) |
461 |
+ { |
462 |
+ if (color) |
463 |
+ { |
464 |
+ if (IP[run] != IP[try]) break; |
465 |
+ } |
466 |
+ else |
467 |
+ if (CP[run] != CP[try]) break; |
468 |
+ |
469 |
+ if (BP(run) != BP(try)) break; |
470 |
+ } |
471 |
+ if (run > brun) |
472 |
+ { |
473 |
+ bdir = dir; |
474 |
+ brun = run; |
475 |
+ } |
476 |
+ } |
477 |
+ if (brun == 0) |
478 |
+ { |
479 |
+ put_token(stream, 5); |
480 |
+ for (i = 0; i < deep; i++) |
481 |
+ put_diff(stream+1+i, DP[i] - DP[i-deep]); |
482 |
+ bit = 0; |
483 |
+ off++; |
484 |
+ stat--; |
485 |
+ continue; |
486 |
+ } |
487 |
+ if (brun > width * height - off) |
488 |
+ brun = width * height - off; |
489 |
+ if (bdir) |
490 |
+ { |
491 |
+ j = rotor[bdir]; |
492 |
+ for (i = bdir; i; i--) |
493 |
+ rotor[i] = rotor[i-1]; |
494 |
+ rotor[0] = j; |
495 |
+ } |
496 |
+ if ((off-1+brun)/width != (off-1)/width) |
497 |
+ { |
498 |
+ if (abs(stat) > 8 && ((stat >> 31) & 1) != hsel) |
499 |
+ { |
500 |
+ hsel ^= 1; |
501 |
+ put_token(stream, 6); |
502 |
+ } |
503 |
+ stat = 0; |
504 |
+ } |
505 |
+ stat += bdir == bit; |
506 |
+ put_token(stream, bdir - bit); |
507 |
+ put_len(stream, brun); |
508 |
+ bit = brun < 17057; |
509 |
+ off += brun; |
510 |
+ } |
511 |
+ |
512 |
+ putbits(stream, 0xff, 8); |
513 |
+ for (total = 48, i = 0; i <= deep; i++) |
514 |
+ { |
515 |
+ putbits(stream+i, 0xff, 8); |
516 |
+ stream[i].off--; |
517 |
+ setle (body+32 + i*4, 4, stream[i].off); |
518 |
+ total += stream[i].off; |
519 |
+ } |
520 |
+ head[85] = 0xa2 + (total > 0xffff)*2; |
521 |
+ setle (head+86, 4, total); |
522 |
+ fwrite(head, 1, 88+(total > 0xffff)*2, stdout); |
523 |
+ fwrite(body, 1, 48, stdout); |
524 |
+ for (i = 0; i <= deep; i++) |
525 |
+ { |
526 |
+ fwrite(stream[i].buf, 1, stream[i].off, stdout); |
527 |
+ free(stream[i].buf); |
528 |
+ } |
529 |
+ free(blank-width/8-1); |
530 |
+ printf("SD"); |
531 |
+} |
532 |
+#undef IP |
533 |
+#undef CP |
534 |
+#undef DP |
535 |
+#undef BP |
536 |
+#undef put_token |
537 |
+ |
538 |
+int |
539 |
+getint(FILE *fp) |
540 |
+{ |
541 |
+ int c, ret; |
542 |
+ |
543 |
+ for (;;) |
544 |
+ { |
545 |
+ while (isspace(c = fgetc(fp))); |
546 |
+ if (c == '#') |
547 |
+ while (fgetc(fp) != '\n'); |
548 |
+ else break; |
549 |
+ } |
550 |
+ if (!isdigit(c)) return -1; |
551 |
+ for (ret = c-'0'; isdigit(c = fgetc(fp)); ) |
552 |
+ ret = ret*10 + c-'0'; |
553 |
+ return ret; |
554 |
+} |
555 |
+ |
556 |
+void |
557 |
+do_file(FILE *fp) |
558 |
+{ |
559 |
+ int type, iwide, ihigh, ideep, imax, ibyte; |
560 |
+ int wide, deep, byte, row, col, i, k; |
561 |
+ char tupl[128], line[128]; |
562 |
+ unsigned char *image, *sp, *dp; |
563 |
+ |
564 |
+ while ((type = fgetc(fp)) != EOF) |
565 |
+ { |
566 |
+ type = ((type - 'P') << 8) | fgetc(fp); |
567 |
+ tupl[0] = iwide = ihigh = ideep = deep = imax = ibyte = -1; |
568 |
+ switch (type) |
569 |
+ { |
570 |
+ case '4': |
571 |
+ deep = 1 + (ideep = 0); |
572 |
+ goto six; |
573 |
+ case '5': |
574 |
+ deep = ideep = 1; |
575 |
+ goto six; |
576 |
+ case '6': |
577 |
+ deep = 1 + (ideep = 3); |
578 |
+six: iwide = getint(fp); |
579 |
+ ihigh = getint(fp); |
580 |
+ imax = type == '4' ? 255 : getint(fp); |
581 |
+ break; |
582 |
+ case '7': |
583 |
+ do |
584 |
+ { |
585 |
+ if (!fgets(line, 128, fp)) goto fail; |
586 |
+ if (!strncmp(line, "WIDTH ",6)) |
587 |
+ iwide = atoi(line + 6); |
588 |
+ if (!strncmp(line, "HEIGHT ",7)) |
589 |
+ ihigh = atoi(line + 7); |
590 |
+ if (!strncmp(line, "DEPTH ",6)) |
591 |
+ deep = ideep = atoi(line + 6); |
592 |
+ if (!strncmp(line, "MAXVAL ",7)) |
593 |
+ imax = atoi(line + 7); |
594 |
+ if (!strncmp(line, "TUPLTYPE ",9)) |
595 |
+ strcpy (tupl, line + 9); |
596 |
+ } while (strcmp(line, "ENDHDR\n")); |
597 |
+ if (ideep != 4 || strcmp(tupl, "CMYK\n")) goto fail; |
598 |
+ break; |
599 |
+ default: |
600 |
+ goto fail; |
601 |
+ } |
602 |
+ if (iwide <= 0 || ihigh <= 0 || imax != 255) goto fail; |
603 |
+ wide = -(-iwide & -8); |
604 |
+ if (ideep) |
605 |
+ ibyte = iwide * ideep; |
606 |
+ else |
607 |
+ ibyte = wide >> 3; |
608 |
+ byte = wide * deep; |
609 |
+ image = calloc (ihigh+2, byte); |
610 |
+ for (row = 1; row <= ihigh; row++) |
611 |
+ { |
612 |
+ i = fread (image, ibyte, 1, fp); |
613 |
+ sp = image; |
614 |
+ dp = image + row*byte; |
615 |
+ for (col = 0; col < iwide; col++) |
616 |
+ { |
617 |
+ dp += deep; |
618 |
+ switch (ideep) |
619 |
+ { |
620 |
+ case 0: |
621 |
+ *dp = ((image[col >> 3] >> (~col & 7)) & 1) * 255; |
622 |
+ break; |
623 |
+ case 1: |
624 |
+ *dp = ~*sp; |
625 |
+ break; |
626 |
+ case 3: |
627 |
+ for (k = sp[2], i = 0; i < 2; i++) |
628 |
+ if (k < sp[i]) k = sp[i]; |
629 |
+ *dp = ~k; |
630 |
+ for (i = 0; i < 3; i++) |
631 |
+ dp[i+1] = k ? (k - sp[i]) * 255 / k : 255; |
632 |
+ break; |
633 |
+ case 4: |
634 |
+ for (i=0; i < 4; i++) |
635 |
+ dp[i] = sp[((i-1) & 3)]; |
636 |
+ break; |
637 |
+ } |
638 |
+ sp += ideep; |
639 |
+ } |
640 |
+ for (i = 0; i < deep*Clip[0]; i++) |
641 |
+ image[row*byte + deep+i] = 0; |
642 |
+ for (i = deep*(iwide-Clip[2]); i < byte; i++) |
643 |
+ image[row*byte + deep+i] = 0; |
644 |
+ } |
645 |
+ memset(image+deep, 0, byte*(Clip[1]+1)); |
646 |
+ memset(image+deep + byte*(ihigh-Clip[3]+1), 0, byte*Clip[3]); |
647 |
+ encode_page(deep > 1, iwide, ihigh, (char *) image); |
648 |
+ free(image); |
649 |
+ } |
650 |
+ return; |
651 |
+fail: |
652 |
+ fprintf (stderr, "Not an acceptable PBM, PPM or PAM file!!!\n"); |
653 |
+} |
654 |
+ |
655 |
+int |
656 |
+main(int argc, char *argv[]) |
657 |
+{ |
658 |
+ int c, i; |
659 |
+ |
660 |
+ while ( (c = getopt(argc, argv, "m:u:J:U:V")) != EOF) |
661 |
+ switch (c) |
662 |
+ { |
663 |
+ case 'm': MediaCode = atoi(optarg); break; |
664 |
+ case 'u': if (sscanf(optarg, "%d,%d,%d,%d", |
665 |
+ Clip, Clip+1, Clip+2, Clip+3) != 4) |
666 |
+ error(1, "Must specify four clipping margins!\n"); |
667 |
+ break; |
668 |
+ case 'J': if (optarg[0]) Filename = optarg; break; |
669 |
+ case 'U': if (optarg[0]) Username = optarg; break; |
670 |
+ case 'V': printf("%s\n", Version); return 0; |
671 |
+ default: usage(); return 1; |
672 |
+ } |
673 |
+ |
674 |
+ argc -= optind; |
675 |
+ argv += optind; |
676 |
+ |
677 |
+ if (argc == 0) |
678 |
+ { |
679 |
+ do_file(stdin); |
680 |
+ } |
681 |
+ else |
682 |
+ { |
683 |
+ for (i = 0; i < argc; ++i) |
684 |
+ { |
685 |
+ FILE *ifp; |
686 |
+ |
687 |
+ if (!(ifp = fopen(argv[i], "r"))) |
688 |
+ error(1, "Can't open '%s' for reading\n", argv[i]); |
689 |
+ do_file(ifp); |
690 |
+ fclose(ifp); |
691 |
+ } |
692 |
+ } |
693 |
+ puts("B\033%-12345X@PJL EOJ"); |
694 |
+ return 0; |
695 |
+} |