]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/imagetops.c
ippWrite() and ipp_write_file() fixes for name-with-language and
[thirdparty/cups.git] / filter / imagetops.c
CommitLineData
516ba4c9 1/*
7ce9aa3d 2 * "$Id: imagetops.c,v 1.28 2000/08/01 16:06:00 mike Exp $"
516ba4c9 3 *
ed19bd98 4 * Image file to PostScript filter for the Common UNIX Printing System (CUPS).
516ba4c9 5 *
71fe22b7 6 * Copyright 1993-2000 by Easy Software Products.
516ba4c9 7 *
ed19bd98 8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
516ba4c9 14 *
ed19bd98 15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
af526a52 19 *
ed19bd98 20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
d850a9e1 23 *
ed19bd98 24 * Contents:
516ba4c9 25 *
ed19bd98 26 * main() - Main entry...
27 * ps_hex() - Print binary data as a series of hexadecimal numbers.
28 * ps_ascii85() - Print binary data as a series of base-85 numbers.
516ba4c9 29 */
30
31/*
32 * Include necessary headers...
33 */
34
ed19bd98 35#include "common.h"
516ba4c9 36#include "image.h"
ed19bd98 37#include <math.h>
516ba4c9 38
39
40/*
41 * Globals...
42 */
43
ed19bd98 44int Flip = 0, /* Flip/mirror pages */
c5da5726 45 XPosition = 0, /* Horizontal position on page */
46 YPosition = 0, /* Vertical position on page */
ed19bd98 47 Collate = 0, /* Collate copies? */
48 Copies = 1; /* Number of copies */
516ba4c9 49
50
51/*
52 * Local functions...
53 */
54
ed19bd98 55static void ps_hex(ib_t *, int);
56static void ps_ascii85(ib_t *, int, int);
516ba4c9 57
58
59/*
60 * 'main()' - Main entry...
61 */
62
ed19bd98 63int /* O - Exit status */
516ba4c9 64main(int argc, /* I - Number of command-line arguments */
65 char *argv[]) /* I - Command-line arguments */
66{
ed19bd98 67 image_t *img; /* Image to print */
68 float xprint, /* Printable area */
69 yprint,
70 xinches, /* Total size in inches */
71 yinches;
72 float xsize, /* Total size in points */
48c4ffef 73 ysize,
74 xsize2,
75 ysize2;
332197a2 76 float aspect; /* Aspect ratio */
ed19bd98 77 int xpages, /* # x pages */
78 ypages, /* # y pages */
79 xpage, /* Current x page */
80 ypage, /* Current y page */
81 page; /* Current page number */
82 int x0, y0, /* Corners of the page in image coords */
83 x1, y1;
84 ib_t *row; /* Current row */
85 int y; /* Current Y coordinate in image */
86 int colorspace; /* Output colorspace */
87 int out_offset, /* Offset into output buffer */
88 out_length; /* Length of output buffer */
89 ppd_file_t *ppd; /* PPD file */
90 int num_options; /* Number of print options */
91 cups_option_t *options; /* Print options */
568d2c2f 92 const char *val; /* Option value */
ed19bd98 93 int slowcollate; /* Collate copies the slow way */
94 float g; /* Gamma correction value */
95 float b; /* Brightness factor */
96 float zoom; /* Zoom facter */
332197a2 97 int xppi, yppi; /* Pixels-per-inch */
ed19bd98 98 int hue, sat; /* Hue and saturation adjustment */
19ec0c2c 99 int realcopies; /* Real copies being printed */
c5da5726 100 float left, top; /* Left and top of image */
7ce9aa3d 101 char filename[1024]; /* Name of file to print */
ed19bd98 102
103
7ce9aa3d 104 /*
105 * Check arguments...
106 */
107
108 if (argc < 6 || argc > 7)
ed19bd98 109 {
7ce9aa3d 110 fputs("ERROR: imagetops job-id user title copies options [file]\n", stderr);
ed19bd98 111 return (1);
112 }
516ba4c9 113
7ce9aa3d 114 fprintf(stderr, "INFO: %s %s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
115 argv[3], argv[4], argv[5], argv[6] ? argv[6] : "(null)");
116
117 /*
118 * Copy stdin as needed...
119 */
120
121 if (argc == 6)
122 {
123 FILE *fp; /* File to read from */
124 char buffer[8192]; /* Buffer to read into */
125 int bytes; /* # of bytes to read */
126
127
128 if ((fp = fopen(cupsTempFile(filename, sizeof(filename)), "w")) == NULL)
129 {
130 perror("ERROR: Unable to copy image file");
131 return (1);
132 }
133
134 fprintf(stderr, "DEBUG: imagetops - copying to temp print file \"%s\"\n",
135 filename);
136
137 while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
138 fwrite(buffer, 1, bytes, fp);
139 fclose(fp);
140 }
141 else
142 {
143 strncpy(filename, argv[6], sizeof(filename) - 1);
144 filename[sizeof(filename) - 1] = '\0';
145 }
146
516ba4c9 147 /*
ed19bd98 148 * Process command-line options and write the prolog...
516ba4c9 149 */
150
ed19bd98 151 zoom = 0.0;
332197a2 152 xppi = 0;
153 yppi = 0;
ed19bd98 154 hue = 0;
155 sat = 100;
f0d2f1a4 156 g = 1.0;
ed19bd98 157 b = 1.0;
516ba4c9 158
ae818f4d 159 Copies = atoi(argv[4]);
160
ed19bd98 161 options = NULL;
162 num_options = cupsParseOptions(argv[5], 0, &options);
516ba4c9 163
4e989042 164 ppd = SetCommonOptions(num_options, options, 1);
516ba4c9 165
ed19bd98 166 if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
516ba4c9 167 {
ed19bd98 168 /*
169 * This IPP attribute is unnecessarily complicated...
170 *
171 * single-document, separate-documents-collated-copies, and
172 * single-document-new-sheet all require collated copies.
173 *
174 * separate-documents-collated-copies allows for uncollated copies.
175 */
516ba4c9 176
a7b3e92e 177 Collate = strcasecmp(val, "separate-documents-collated-copies") != 0;
ed19bd98 178 }
516ba4c9 179
ed19bd98 180 if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
a7b3e92e 181 strcasecmp(val, "True") == 0)
ed19bd98 182 Collate = 1;
516ba4c9 183
ed19bd98 184 if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
185 g = atoi(val) * 0.001f;
516ba4c9 186
ed19bd98 187 if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
188 b = atoi(val) * 0.01f;
516ba4c9 189
ed19bd98 190 if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
191 zoom = atoi(val) * 0.01;
516ba4c9 192
ed19bd98 193 if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
332197a2 194 if (sscanf(val, "%dx%d", &xppi, &yppi) < 2)
195 yppi = xppi;
516ba4c9 196
c5da5726 197 if ((val = cupsGetOption("position", num_options, options)) != NULL)
198 {
199 if (strcasecmp(val, "center") == 0)
200 {
201 XPosition = 0;
202 YPosition = 0;
203 }
204 else if (strcasecmp(val, "top") == 0)
205 {
206 XPosition = 0;
207 YPosition = 1;
208 }
209 else if (strcasecmp(val, "left") == 0)
210 {
211 XPosition = -1;
212 YPosition = 0;
213 }
214 else if (strcasecmp(val, "right") == 0)
215 {
216 XPosition = 1;
217 YPosition = 0;
218 }
219 else if (strcasecmp(val, "top-left") == 0)
220 {
221 XPosition = -1;
222 YPosition = 1;
223 }
224 else if (strcasecmp(val, "top-right") == 0)
225 {
226 XPosition = 1;
227 YPosition = 1;
228 }
229 else if (strcasecmp(val, "bottom") == 0)
230 {
231 XPosition = 0;
232 YPosition = -1;
233 }
234 else if (strcasecmp(val, "bottom-left") == 0)
235 {
236 XPosition = -1;
237 YPosition = -1;
238 }
239 else if (strcasecmp(val, "bottom-right") == 0)
240 {
241 XPosition = 1;
242 YPosition = -1;
243 }
244 }
245
ed19bd98 246 if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
247 sat = atoi(val);
248
249 if ((val = cupsGetOption("hue", num_options, options)) != NULL)
250 hue = atoi(val);
516ba4c9 251
252 /*
253 * Open the input image to print...
254 */
255
ed19bd98 256 colorspace = ColorDevice ? IMAGE_RGB : IMAGE_WHITE;
516ba4c9 257
7ce9aa3d 258 img = ImageOpen(filename, colorspace, IMAGE_WHITE, sat, hue, NULL);
259
260 if (argc == 6)
261 unlink(filename);
262
263 if (img == NULL)
ed19bd98 264 {
265 fputs("ERROR: Unable to open image file for printing!\n", stderr);
266 ppdClose(ppd);
267 return (1);
268 }
516ba4c9 269
ed19bd98 270 colorspace = img->colorspace;
516ba4c9 271
272 /*
273 * Scale as necessary...
274 */
275
48c4ffef 276 xprint = (PageRight - PageLeft) / 72.0;
277 yprint = (PageTop - PageBottom) / 72.0;
278
332197a2 279 if (zoom == 0.0 && xppi == 0)
280 {
281 xppi = img->xppi;
282 yppi = img->yppi;
283 }
284
285 if (yppi == 0)
286 yppi = xppi;
287
288 if (xppi > 0)
516ba4c9 289 {
290 /*
291 * Scale the image as neccesary to match the desired pixels-per-inch.
292 */
293
332197a2 294 xinches = (float)img->xsize / (float)xppi;
295 yinches = (float)img->ysize / (float)yppi;
48c4ffef 296
b16dd9cb 297 if (cupsGetOption("orientation", num_options, options) == NULL &&
298 cupsGetOption("landscape", num_options, options) == NULL)
48c4ffef 299 {
300 /*
b16dd9cb 301 * Rotate the image if it will fit landscape but not portrait...
48c4ffef 302 */
303
b16dd9cb 304 if ((xinches > xprint || yinches > yprint) &&
305 xinches <= yprint && yinches <= xprint)
306 {
307 /*
308 * Rotate the image as needed...
309 */
310
311 Orientation = (Orientation + 1) & 3;
312 xsize = yprint;
313 yprint = xprint;
314 xprint = xsize;
315
316 xsize = PageLeft;
317 PageLeft = PageBottom;
318 PageBottom = PageWidth - PageRight;
319 PageRight = PageTop;
320 PageTop = PageLength - xsize;
321
322 xsize = PageWidth;
323 PageWidth = PageLength;
324 PageLength = xsize;
325 }
48c4ffef 326 }
516ba4c9 327 }
328 else
329 {
330 /*
331 * Scale percentage of page size...
332 */
333
332197a2 334 aspect = (float)img->yppi / (float)img->xppi;
335
336 fprintf(stderr, "DEBUG: img->xppi = %d, img->yppi = %d, aspect = %f\n",
337 img->xppi, img->yppi, aspect);
338
ed19bd98 339 xsize = xprint * zoom;
332197a2 340 ysize = xsize * img->ysize / img->xsize / aspect;
0169953d 341
ed19bd98 342 if (ysize > (yprint * zoom))
516ba4c9 343 {
ed19bd98 344 ysize = yprint * zoom;
332197a2 345 xsize = ysize * img->xsize * aspect / img->ysize;
516ba4c9 346 }
0169953d 347
48c4ffef 348 xsize2 = yprint * zoom;
332197a2 349 ysize2 = xsize2 * img->ysize / img->xsize / aspect;
48c4ffef 350
351 if (ysize2 > (xprint * zoom))
352 {
353 ysize2 = xprint * zoom;
332197a2 354 xsize2 = ysize2 * img->xsize * aspect / img->ysize;
48c4ffef 355 }
356
332197a2 357 fprintf(stderr, "DEBUG: xsize = %.0f, ysize = %.0f\n", xsize, ysize);
358 fprintf(stderr, "DEBUG: xsize2 = %.0f, ysize2 = %.0f\n", xsize2, ysize2);
359
b16dd9cb 360 if (cupsGetOption("orientation", num_options, options) == NULL &&
361 cupsGetOption("landscape", num_options, options) == NULL)
48c4ffef 362 {
363 /*
b16dd9cb 364 * Choose the rotation with the largest area, but prefer
365 * portrait if they are equal...
48c4ffef 366 */
367
b16dd9cb 368 if ((xsize * ysize) < (xsize2 * xsize2))
369 {
370 /*
371 * Do landscape orientation...
372 */
373
374 Orientation = 1;
375 xinches = xsize2;
376 yinches = ysize2;
377 xprint = (PageTop - PageBottom) / 72.0;
378 yprint = (PageRight - PageLeft) / 72.0;
379
380 xsize = PageLeft;
381 PageLeft = PageBottom;
382 PageBottom = PageWidth - PageRight;
383 PageRight = PageTop;
384 PageTop = PageLength - xsize;
385
386 xsize = PageWidth;
387 PageWidth = PageLength;
388 PageLength = xsize;
389 }
390 else
391 {
392 /*
393 * Do portrait orientation...
394 */
395
396 Orientation = 0;
397 xinches = xsize;
398 yinches = ysize;
399 }
400 }
401 else if (Orientation & 1)
402 {
48c4ffef 403 xinches = xsize2;
404 yinches = ysize2;
405 xprint = (PageTop - PageBottom) / 72.0;
406 yprint = (PageRight - PageLeft) / 72.0;
407
408 xsize = PageLeft;
409 PageLeft = PageBottom;
410 PageBottom = PageWidth - PageRight;
411 PageRight = PageTop;
412 PageTop = PageLength - xsize;
413
414 xsize = PageWidth;
415 PageWidth = PageLength;
416 PageLength = xsize;
417 }
ed19bd98 418 }
516ba4c9 419
ed19bd98 420 xpages = ceil(xinches / xprint);
421 ypages = ceil(yinches / yprint);
0169953d 422
ed19bd98 423 /*
424 * See if we need to collate, and if so how we need to do it...
425 */
516ba4c9 426
ed19bd98 427 if (xpages == 1 && ypages == 1)
428 Collate = 0;
516ba4c9 429
ed19bd98 430 slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
516ba4c9 431
ed19bd98 432 /*
433 * Write any "exit server" options that have been selected...
434 */
516ba4c9 435
ed19bd98 436 ppdEmit(ppd, stdout, PPD_ORDER_EXIT);
516ba4c9 437
ed19bd98 438 /*
439 * Write any JCL commands that are needed to print PostScript code...
440 */
441
ed19bd98 442 if (ppd != NULL && ppd->jcl_begin && ppd->jcl_ps)
516ba4c9 443 {
6853ae56 444 fputs(ppd->jcl_begin, stdout);
5ec6832f 445 ppdEmit(ppd, stdout, PPD_ORDER_JCL);
6853ae56 446 fputs(ppd->jcl_ps, stdout);
ed19bd98 447 }
516ba4c9 448
449 /*
ed19bd98 450 * Start sending the document with any commands needed...
516ba4c9 451 */
452
ed19bd98 453 puts("%!");
454
37b19c12 455 if (ppd != NULL && ppd->patches != NULL)
456 puts(ppd->patches);
457
ed19bd98 458 ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT);
459 ppdEmit(ppd, stdout, PPD_ORDER_ANY);
460 ppdEmit(ppd, stdout, PPD_ORDER_PROLOG);
516ba4c9 461
ed19bd98 462 if (g != 1.0 || b != 1.0)
37b19c12 463 printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
464 "ifelse %.3f mul } bind settransfer\n", g, b);
ed19bd98 465
466 if (Copies > 1 && !slowcollate)
516ba4c9 467 {
ed19bd98 468 printf("/#copies %d def\n", Copies);
19ec0c2c 469 realcopies = Copies;
470 Copies = 1;
ed19bd98 471 }
19ec0c2c 472 else
473 realcopies = 1;
516ba4c9 474
475 /*
476 * Output the pages...
477 */
478
0169953d 479 xprint = xinches / xpages;
480 yprint = yinches / ypages;
ed19bd98 481 row = malloc(img->xsize * abs(colorspace) + 3);
0169953d 482
ed19bd98 483 for (page = 1; Copies > 0; Copies --)
484 for (xpage = 0; xpage < xpages; xpage ++)
485 for (ypage = 0; ypage < ypages; ypage ++, page ++)
486 {
19ec0c2c 487 fprintf(stderr, "PAGE: %d %d\n", page, realcopies);
ed19bd98 488 fprintf(stderr, "INFO: Printing page %d...\n", page);
516ba4c9 489
ed19bd98 490 ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
516ba4c9 491
ed19bd98 492 puts("gsave");
516ba4c9 493
ed19bd98 494 if (Flip)
495 printf("%.0f 0 translate -1 1 scale\n", PageWidth);
496
497 switch (Orientation)
498 {
499 case 1 : /* Landscape */
500 printf("%.0f 0 translate 90 rotate\n", PageLength);
501 break;
502 case 2 : /* Reverse Portrait */
503 printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength);
504 break;
505 case 3 : /* Reverse Landscape */
506 printf("0 %.0f translate -90 rotate\n", PageWidth);
507 break;
508 }
516ba4c9 509
5398375f 510 x0 = img->xsize * xpage / xpages;
511 x1 = img->xsize * (xpage + 1) / xpages - 1;
512 y0 = img->ysize * ypage / ypages;
513 y1 = img->ysize * (ypage + 1) / ypages - 1;
516ba4c9 514
c5da5726 515 switch (XPosition)
516 {
517 case -1 :
518 left = PageLeft;
519 break;
520 case 0 :
521 left = (PageWidth - xprint * 72.0) * 0.5;
522 break;
523 case 1 :
524 left = PageRight - xprint * 72.0;
525 break;
526 }
527
528 switch (YPosition)
529 {
530 case -1 :
531 top = PageBottom + 72.0 * yprint;
532 break;
533 case 0 :
534 top = (PageLength + yprint * 72.0) * 0.5;
535 break;
536 case 1 :
537 top = PageTop;
538 break;
539 }
540
541 printf("%.1f %.1f translate\n", left, top);
542
ed19bd98 543 printf("%.3f %.3f scale\n\n",
544 xprint * 72.0 / (x1 - x0 + 1),
545 yprint * 72.0 / (y1 - y0 + 1));
516ba4c9 546
ed19bd98 547 if (LanguageLevel == 1)
af526a52 548 {
ed19bd98 549 printf("/picture %d string def\n", (x1 - x0 + 1) * abs(colorspace));
550 printf("%d %d 8[1 0 0 -1 0 1]", (x1 - x0 + 1), (y1 - y0 + 1));
551
552 if (colorspace == IMAGE_WHITE)
553 puts("{currentfile picture readhexstring pop} image");
af526a52 554 else
ed19bd98 555 puts("{currentfile picture readhexstring pop} false 3 colorimage");
556
557 for (y = y0; y <= y1; y ++)
558 {
559 ImageGetRow(img, x0, y, x1 - x0 + 1, row);
560 ps_hex(row, (x1 - x0 + 1) * abs(colorspace));
561 }
af526a52 562 }
563 else
564 {
ed19bd98 565 if (colorspace == IMAGE_WHITE)
566 puts("/DeviceGray setcolorspace");
af526a52 567 else
ed19bd98 568 puts("/DeviceRGB setcolorspace");
af526a52 569
ed19bd98 570 printf("<<"
571 "/ImageType 1"
572 "/Width %d"
573 "/Height %d"
574 "/BitsPerComponent 8",
575 x1 - x0 + 1, y1 - y0 + 1);
af526a52 576
ed19bd98 577 if (colorspace == IMAGE_WHITE)
578 fputs("/Decode[0 1]", stdout);
579 else
580 fputs("/Decode[0 1 0 1 0 1]", stdout);
af526a52 581
ed19bd98 582 fputs("/DataSource currentfile /ASCII85Decode filter", stdout);
af526a52 583
ed19bd98 584 if (((x1 - x0 + 1) / xprint) < 100.0)
585 fputs("/Interpolate true", stdout);
5398375f 586
ed19bd98 587 puts("/ImageMatrix[1 0 0 -1 0 1]>>image");
af526a52 588
ed19bd98 589 for (y = y0, out_offset = 0; y <= y1; y ++)
590 {
591 ImageGetRow(img, x0, y, x1 - x0 + 1, row + out_offset);
af526a52 592
ed19bd98 593 out_length = (x1 - x0 + 1) * abs(colorspace) + out_offset;
594 out_offset = out_length & 3;
516ba4c9 595
ed19bd98 596 ps_ascii85(row, out_length, y == y1);
516ba4c9 597
ed19bd98 598 if (out_offset > 0)
599 memcpy(row, row + out_length - out_offset, out_offset);
600 }
601 }
516ba4c9 602
ed19bd98 603 puts("grestore");
604 puts("showpage");
605 }
516ba4c9 606
ed19bd98 607 /*
608 * End the job with the appropriate JCL command or CTRL-D otherwise.
609 */
516ba4c9 610
ed19bd98 611 if (ppd != NULL && ppd->jcl_end)
6853ae56 612 fputs(ppd->jcl_end, stdout);
ed19bd98 613 else
614 putchar(0x04);
516ba4c9 615
ed19bd98 616 /*
617 * Close files...
618 */
516ba4c9 619
620 ImageClose(img);
ed19bd98 621 ppdClose(ppd);
516ba4c9 622
ed19bd98 623 return (0);
516ba4c9 624}
625
626
627/*
628 * 'ps_hex()' - Print binary data as a series of hexadecimal numbers.
629 */
630
631static void
ed19bd98 632ps_hex(ib_t *data, /* I - Data to print */
516ba4c9 633 int length) /* I - Number of bytes to print */
634{
af526a52 635 int col;
516ba4c9 636 static char *hex = "0123456789ABCDEF";
637
638
af526a52 639 col = 0;
640
516ba4c9 641 while (length > 0)
642 {
643 /*
ed19bd98 644 * Put the hex chars out to the file; note that we don't use printf()
516ba4c9 645 * for speed reasons...
646 */
647
ed19bd98 648 putchar(hex[*data >> 4]);
649 putchar(hex[*data & 15]);
516ba4c9 650
651 data ++;
652 length --;
af526a52 653
654 col = (col + 1) & 31;
655 if (col == 0 && length > 0)
ed19bd98 656 putchar('\n');
657 }
516ba4c9 658
ed19bd98 659 putchar('\n');
516ba4c9 660}
661
662
663/*
664 * 'ps_ascii85()' - Print binary data as a series of base-85 numbers.
665 */
666
667static void
ed19bd98 668ps_ascii85(ib_t *data, /* I - Data to print */
516ba4c9 669 int length, /* I - Number of bytes to print */
670 int last_line) /* I - Last line of raster data? */
671{
672 unsigned b; /* Binary data word */
673 unsigned char c[5]; /* ASCII85 encoded chars */
516ba4c9 674
675
516ba4c9 676 while (length > 3)
677 {
678 b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
679
680 if (b == 0)
ed19bd98 681 putchar('z');
516ba4c9 682 else
683 {
684 c[4] = (b % 85) + '!';
685 b /= 85;
686 c[3] = (b % 85) + '!';
687 b /= 85;
688 c[2] = (b % 85) + '!';
689 b /= 85;
690 c[1] = (b % 85) + '!';
691 b /= 85;
692 c[0] = b + '!';
693
ed19bd98 694 fwrite(c, 5, 1, stdout);
695 }
516ba4c9 696
697 data += 4;
698 length -= 4;
ed19bd98 699 }
516ba4c9 700
701 if (last_line)
702 {
703 if (length > 0)
704 {
4364903a 705 memset(data + length, 0, 4 - length);
706 b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
516ba4c9 707
708 c[4] = (b % 85) + '!';
709 b /= 85;
710 c[3] = (b % 85) + '!';
711 b /= 85;
712 c[2] = (b % 85) + '!';
713 b /= 85;
714 c[1] = (b % 85) + '!';
715 b /= 85;
716 c[0] = b + '!';
717
ed19bd98 718 fwrite(c, length + 1, 1, stdout);
719 }
516ba4c9 720
ed19bd98 721 puts("~>");
516ba4c9 722 }
516ba4c9 723}
724
725
726/*
7ce9aa3d 727 * End of "$Id: imagetops.c,v 1.28 2000/08/01 16:06:00 mike Exp $".
516ba4c9 728 */