]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/raster.c
Merge changes from CUPS 1.4svn-r7386.
[thirdparty/cups.git] / filter / raster.c
1 /*
2 * "$Id: raster.c 6649 2007-07-11 21:46:42Z mike $"
3 *
4 * Raster file routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2007-2008 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
8 *
9 * This file is part of the CUPS Imaging library.
10 *
11 * These coded instructions, statements, and computer programs are the
12 * property of Apple Inc. and are protected by Federal copyright
13 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
14 * which should have been included with this file. If this file is
15 * file is missing or damaged, see the license at "http://www.cups.org/".
16 *
17 * This file is subject to the Apple OS-Developed Software exception.
18 *
19 * Contents:
20 *
21 * cupsRasterClose() - Close a raster stream.
22 * cupsRasterOpen() - Open a raster stream.
23 * cupsRasterReadHeader() - Read a raster page header and store it in a
24 * version 1 page header structure.
25 * cupsRasterReadHeader2() - Read a raster page header and store it in a
26 * version 2 page header structure.
27 * cupsRasterReadPixels() - Read raster pixels.
28 * cupsRasterWriteHeader() - Write a raster page header from a version 1
29 * page header structure.
30 * cupsRasterWriteHeader2() - Write a raster page header from a version 2
31 * page header structure.
32 * cupsRasterWritePixels() - Write raster pixels.
33 * cups_raster_read() - Read through the raster buffer.
34 * cups_raster_read_header() - Read a raster page header.
35 * cups_raster_update() - Update the raster header and row count for the
36 * current page.
37 * cups_raster_write() - Write a row of raster data...
38 * cups_read() - Read bytes from a file.
39 * cups_swap() - Swap bytes in raster data...
40 * cups_write() - Write bytes to a file.
41 */
42
43 /*
44 * Include necessary headers...
45 */
46
47 #include "image-private.h"
48 #include <cups/debug.h>
49 #include <stdlib.h>
50 #include <errno.h>
51 #include <cups/string.h>
52
53 #if defined(WIN32) || defined(__EMX__)
54 # include <io.h>
55 #else
56 # include <unistd.h>
57 #endif /* WIN32 || __EMX__ */
58
59
60 /*
61 * Private structures...
62 */
63
64 struct _cups_raster_s /**** Raster stream data ****/
65 {
66 unsigned sync; /* Sync word from start of stream */
67 int fd; /* File descriptor */
68 cups_mode_t mode; /* Read/write mode */
69 cups_page_header2_t header; /* Raster header for current page */
70 int count, /* Current row run-length count */
71 remaining, /* Remaining rows in page image */
72 bpp; /* Bytes per pixel/color */
73 unsigned char *pixels, /* Pixels for current row */
74 *pend, /* End of pixel buffer */
75 *pcurrent; /* Current byte in pixel buffer */
76 int compressed, /* Non-zero if data is compressed */
77 swapped; /* Non-zero if data is byte-swapped */
78 unsigned char *buffer, /* Read/write buffer */
79 *bufptr, /* Current (read) position in buffer */
80 *bufend; /* End of current (read) buffer */
81 int bufsize; /* Buffer size */
82 };
83
84
85 /*
86 * Local functions...
87 */
88
89 static unsigned cups_raster_read_header(cups_raster_t *r);
90 static int cups_raster_read(cups_raster_t *r, unsigned char *buf,
91 int bytes);
92 static void cups_raster_update(cups_raster_t *r);
93 static int cups_raster_write(cups_raster_t *r, const unsigned char *pixels);
94 static int cups_read(int fd, unsigned char *buf, int bytes);
95 static void cups_swap(unsigned char *buf, int bytes);
96 static int cups_write(int fd, const unsigned char *buf, int bytes);
97
98
99 /*
100 * 'cupsRasterClose()' - Close a raster stream.
101 *
102 * The file descriptor associated with the raster stream must be closed
103 * separately as needed.
104 */
105
106 void
107 cupsRasterClose(cups_raster_t *r) /* I - Stream to close */
108 {
109 if (r != NULL)
110 {
111 if (r->buffer)
112 free(r->buffer);
113
114 if (r->pixels)
115 free(r->pixels);
116
117 free(r);
118 }
119 }
120
121
122 /*
123 * 'cupsRasterOpen()' - Open a raster stream.
124 *
125 * This function associates a raster stream with the given file descriptor.
126 * For most printer driver filters, "fd" will be 0 (stdin). For most raster
127 * image processor (RIP) filters that generate raster data, "fd" will be 1
128 * (stdout).
129 *
130 * When writing raster data, the @code CUPS_RASTER_WRITE@ or
131 * @code CUPS_RASTER_WRITE_COMPRESS@ mode can be used - compressed output
132 * is generally 25-50% smaller but adds a 100-300% execution time overhead.
133 */
134
135 cups_raster_t * /* O - New stream */
136 cupsRasterOpen(int fd, /* I - File descriptor */
137 cups_mode_t mode) /* I - Mode - @code CUPS_RASTER_READ@, @code CUPS_RASTER_WRITE@, or @code CUPS_RASTER_WRITE_COMPRESSED@ */
138 {
139 cups_raster_t *r; /* New stream */
140
141
142 _cupsRasterClearError();
143
144 if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL)
145 {
146 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
147 strerror(errno));
148 return (NULL);
149 }
150
151 r->fd = fd;
152 r->mode = mode == CUPS_RASTER_WRITE_COMPRESSED ? CUPS_RASTER_WRITE : mode;
153
154 if (mode == CUPS_RASTER_READ)
155 {
156 /*
157 * Open for read - get sync word...
158 */
159
160 if (!cups_read(r->fd, (unsigned char *)&(r->sync), sizeof(r->sync)))
161 {
162 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
163 strerror(errno));
164 free(r);
165 return (NULL);
166 }
167
168 if (r->sync != CUPS_RASTER_SYNC &&
169 r->sync != CUPS_RASTER_REVSYNC &&
170 r->sync != CUPS_RASTER_SYNCv1 &&
171 r->sync != CUPS_RASTER_REVSYNCv1 &&
172 r->sync != CUPS_RASTER_SYNCv2 &&
173 r->sync != CUPS_RASTER_REVSYNCv2)
174 {
175 _cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
176 free(r);
177 return (NULL);
178 }
179
180 if (r->sync == CUPS_RASTER_SYNCv2 ||
181 r->sync == CUPS_RASTER_REVSYNCv2)
182 r->compressed = 1;
183
184 if (r->sync == CUPS_RASTER_REVSYNC ||
185 r->sync == CUPS_RASTER_REVSYNCv1 ||
186 r->sync == CUPS_RASTER_REVSYNCv2)
187 r->swapped = 1;
188
189 DEBUG_printf(("r->swapped=%d, r->sync=%08x\n", r->swapped, r->sync));
190 }
191 else
192 {
193 /*
194 * Open for write - put sync word...
195 */
196
197 if (mode == CUPS_RASTER_WRITE_COMPRESSED)
198 {
199 r->compressed = 1;
200 r->sync = CUPS_RASTER_SYNCv2;
201 }
202 else
203 r->sync = CUPS_RASTER_SYNC;
204
205 if (cups_write(r->fd, (unsigned char *)&(r->sync), sizeof(r->sync))
206 < sizeof(r->sync))
207 {
208 _cupsRasterAddError("Unable to write raster stream header: %s\n",
209 strerror(errno));
210 free(r);
211 return (NULL);
212 }
213 }
214
215 return (r);
216 }
217
218
219 /*
220 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
221 * version 1 page header structure.
222 *
223 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
224 *
225 * @deprecated@
226 */
227
228 unsigned /* O - 1 on success, 0 on fail */
229 cupsRasterReadHeader(
230 cups_raster_t *r, /* I - Raster stream */
231 cups_page_header_t *h) /* I - Pointer to header data */
232 {
233 /*
234 * Get the raster header...
235 */
236
237 if (!cups_raster_read_header(r))
238 return (0);
239
240 /*
241 * Copy the header to the user-supplied buffer...
242 */
243
244 memcpy(h, &(r->header), sizeof(cups_page_header_t));
245
246 return (1);
247 }
248
249
250 /*
251 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
252 * version 2 page header structure.
253 *
254 * @since CUPS 1.2/Mac OS X 10.5@
255 */
256
257 unsigned /* O - 1 on success, 0 on fail */
258 cupsRasterReadHeader2(
259 cups_raster_t *r, /* I - Raster stream */
260 cups_page_header2_t *h) /* I - Pointer to header data */
261 {
262 /*
263 * Get the raster header...
264 */
265
266 if (!cups_raster_read_header(r))
267 return (0);
268
269 /*
270 * Copy the header to the user-supplied buffer...
271 */
272
273 memcpy(h, &(r->header), sizeof(cups_page_header2_t));
274
275 return (1);
276 }
277
278
279 /*
280 * 'cupsRasterReadPixels()' - Read raster pixels.
281 */
282
283 unsigned /* O - Number of bytes read */
284 cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */
285 unsigned char *p, /* I - Pointer to pixel buffer */
286 unsigned len) /* I - Number of bytes to read */
287 {
288 int bytes; /* Bytes read */
289 unsigned cupsBytesPerLine; /* cupsBytesPerLine value */
290 unsigned remaining; /* Bytes remaining */
291 unsigned char *ptr, /* Pointer to read buffer */
292 byte, /* Byte from file */
293 *temp; /* Pointer into buffer */
294 int count; /* Repetition count */
295
296
297 if (r == NULL || r->mode != CUPS_RASTER_READ || r->remaining == 0)
298 return (0);
299
300 if (!r->compressed)
301 {
302 /*
303 * Read without compression...
304 */
305
306 r->remaining -= len / r->header.cupsBytesPerLine;
307
308 if (!cups_read(r->fd, p, len))
309 return (0);
310
311 /*
312 * Swap bytes as needed...
313 */
314
315 if ((r->header.cupsBitsPerColor == 16 ||
316 r->header.cupsBitsPerPixel == 12 ||
317 r->header.cupsBitsPerPixel == 16) &&
318 r->swapped)
319 cups_swap(p, len);
320
321 /*
322 * Return...
323 */
324
325 return (len);
326 }
327
328 /*
329 * Read compressed data...
330 */
331
332 remaining = len;
333 cupsBytesPerLine = r->header.cupsBytesPerLine;
334
335 while (remaining > 0 && r->remaining > 0)
336 {
337 if (r->count == 0)
338 {
339 /*
340 * Need to read a new row...
341 */
342
343 if (remaining == cupsBytesPerLine)
344 ptr = p;
345 else
346 ptr = r->pixels;
347
348 /*
349 * Read using a modified TIFF "packbits" compression...
350 */
351
352 if (!cups_raster_read(r, &byte, 1))
353 return (0);
354
355 r->count = byte + 1;
356
357 if (r->count > 1)
358 ptr = r->pixels;
359
360 temp = ptr;
361 bytes = cupsBytesPerLine;
362
363 while (bytes > 0)
364 {
365 /*
366 * Get a new repeat count...
367 */
368
369 if (!cups_raster_read(r, &byte, 1))
370 return (0);
371
372 if (byte & 128)
373 {
374 /*
375 * Copy N literal pixels...
376 */
377
378 count = (257 - byte) * r->bpp;
379
380 if (count > bytes)
381 count = bytes;
382
383 if (!cups_raster_read(r, temp, count))
384 return (0);
385
386 temp += count;
387 bytes -= count;
388 }
389 else
390 {
391 /*
392 * Repeat the next N bytes...
393 */
394
395 count = (byte + 1) * r->bpp;
396 if (count > bytes)
397 count = bytes;
398
399 if (count < r->bpp)
400 break;
401
402 bytes -= count;
403
404 if (!cups_raster_read(r, temp, r->bpp))
405 return (0);
406
407 temp += r->bpp;
408 count -= r->bpp;
409
410 while (count > 0)
411 {
412 memcpy(temp, temp - r->bpp, r->bpp);
413 temp += r->bpp;
414 count -= r->bpp;
415 }
416 }
417 }
418
419 /*
420 * Swap bytes as needed...
421 */
422
423 if ((r->header.cupsBitsPerColor == 16 ||
424 r->header.cupsBitsPerPixel == 12 ||
425 r->header.cupsBitsPerPixel == 16) &&
426 r->swapped)
427 cups_swap(ptr, bytes);
428
429 /*
430 * Update pointers...
431 */
432
433 if (remaining >= cupsBytesPerLine)
434 {
435 bytes = cupsBytesPerLine;
436 r->pcurrent = r->pixels;
437 r->count --;
438 r->remaining --;
439 }
440 else
441 {
442 bytes = remaining;
443 r->pcurrent = r->pixels + bytes;
444 }
445
446 /*
447 * Copy data as needed...
448 */
449
450 if (ptr != p)
451 memcpy(p, ptr, bytes);
452 }
453 else
454 {
455 /*
456 * Copy fragment from buffer...
457 */
458
459 if ((bytes = r->pend - r->pcurrent) > remaining)
460 bytes = remaining;
461
462 memcpy(p, r->pcurrent, bytes);
463 r->pcurrent += bytes;
464
465 if (r->pcurrent >= r->pend)
466 {
467 r->pcurrent = r->pixels;
468 r->count --;
469 r->remaining --;
470 }
471 }
472
473 remaining -= bytes;
474 p += bytes;
475 }
476
477 return (len);
478 }
479
480
481 /*
482 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
483 * header structure.
484 *
485 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
486 *
487 * @deprecated@
488 */
489
490 unsigned /* O - 1 on success, 0 on failure */
491 cupsRasterWriteHeader(
492 cups_raster_t *r, /* I - Raster stream */
493 cups_page_header_t *h) /* I - Raster page header */
494 {
495 if (r == NULL || r->mode != CUPS_RASTER_WRITE)
496 return (0);
497
498 /*
499 * Make a copy of the header, and compute the number of raster
500 * lines in the page image...
501 */
502
503 memset(&(r->header), 0, sizeof(r->header));
504 memcpy(&(r->header), h, sizeof(cups_page_header_t));
505
506 cups_raster_update(r);
507
508 /*
509 * Write the raster header...
510 */
511
512 return (cups_write(r->fd, (unsigned char *)&(r->header), sizeof(r->header))
513 > 0);
514 }
515
516
517 /*
518 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
519 * page header structure.
520 *
521 * The page header can be initialized using @link cupsRasterInterpretPPD@.
522 *
523 * @since CUPS 1.2/Mac OS X 10.5@
524 */
525
526 unsigned /* O - 1 on success, 0 on failure */
527 cupsRasterWriteHeader2(
528 cups_raster_t *r, /* I - Raster stream */
529 cups_page_header2_t *h) /* I - Raster page header */
530 {
531 if (r == NULL || r->mode != CUPS_RASTER_WRITE)
532 return (0);
533
534 /*
535 * Make a copy of the header, and compute the number of raster
536 * lines in the page image...
537 */
538
539 memcpy(&(r->header), h, sizeof(cups_page_header2_t));
540
541 cups_raster_update(r);
542
543 /*
544 * Write the raster header...
545 */
546
547 return (cups_write(r->fd, (unsigned char *)&(r->header), sizeof(r->header))
548 > 0);
549 }
550
551
552 /*
553 * 'cupsRasterWritePixels()' - Write raster pixels.
554 */
555
556 unsigned /* O - Number of bytes written */
557 cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */
558 unsigned char *p, /* I - Bytes to write */
559 unsigned len)/* I - Number of bytes to write */
560 {
561 int bytes; /* Bytes read */
562 unsigned remaining; /* Bytes remaining */
563
564
565 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
566 r, p, len, r->remaining));
567
568 if (r == NULL || r->mode != CUPS_RASTER_WRITE || r->remaining == 0)
569 return (0);
570
571 if (!r->compressed)
572 {
573 /*
574 * Without compression, just write the raster data raw...
575 */
576
577 r->remaining -= len / r->header.cupsBytesPerLine;
578
579 return (cups_write(r->fd, p, len));
580 }
581
582 /*
583 * Otherwise, compress each line...
584 */
585
586 for (remaining = len; remaining > 0; remaining -= bytes, p += bytes)
587 {
588 /*
589 * Figure out the number of remaining bytes on the current line...
590 */
591
592 if ((bytes = remaining) > (r->pend - r->pcurrent))
593 bytes = r->pend - r->pcurrent;
594
595 if (r->count > 0)
596 {
597 /*
598 * Check to see if this line is the same as the previous line...
599 */
600
601 if (memcmp(p, r->pcurrent, bytes))
602 {
603 if (!cups_raster_write(r, r->pixels))
604 return (0);
605
606 r->count = 0;
607 }
608 else
609 {
610 /*
611 * Mark more bytes as the same...
612 */
613
614 r->pcurrent += bytes;
615
616 if (r->pcurrent >= r->pend)
617 {
618 /*
619 * Increase the repeat count...
620 */
621
622 r->count ++;
623 r->pcurrent = r->pixels;
624
625 /*
626 * Flush out this line if it is the last one...
627 */
628
629 r->remaining --;
630
631 if (r->remaining == 0)
632 return (cups_raster_write(r, r->pixels));
633 else if (r->count == 256)
634 {
635 if (cups_raster_write(r, r->pixels) == 0)
636 return (0);
637
638 r->count = 0;
639 }
640 }
641
642 continue;
643 }
644 }
645
646 if (r->count == 0)
647 {
648 /*
649 * Copy the raster data to the buffer...
650 */
651
652 memcpy(r->pcurrent, p, bytes);
653
654 r->pcurrent += bytes;
655
656 if (r->pcurrent >= r->pend)
657 {
658 /*
659 * Increase the repeat count...
660 */
661
662 r->count ++;
663 r->pcurrent = r->pixels;
664
665 /*
666 * Flush out this line if it is the last one...
667 */
668
669 r->remaining --;
670
671 if (r->remaining == 0)
672 return (cups_raster_write(r, r->pixels));
673 }
674 }
675 }
676
677 return (len);
678 }
679
680
681 /*
682 * 'cups_raster_read_header()' - Read a raster page header.
683 */
684
685 static unsigned /* O - 1 on success, 0 on fail */
686 cups_raster_read_header(
687 cups_raster_t *r) /* I - Raster stream */
688 {
689 int len; /* Length for read/swap */
690
691
692 if (r == NULL || r->mode != CUPS_RASTER_READ)
693 return (0);
694
695 /*
696 * Get the length of the raster header...
697 */
698
699 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
700 len = sizeof(cups_page_header_t);
701 else
702 len = sizeof(cups_page_header2_t);
703
704 /*
705 * Read the header...
706 */
707
708 memset(&(r->header), 0, sizeof(r->header));
709
710 if (cups_raster_read(r, (unsigned char *)&(r->header), len) < len)
711 return (0);
712
713 /*
714 * Swap bytes as needed...
715 */
716
717 if (r->swapped)
718 {
719 unsigned *s, /* Current word */
720 temp; /* Temporary copy */
721
722
723 DEBUG_puts("Swapping header bytes...");
724
725 for (len = 81, s = &(r->header.AdvanceDistance);
726 len > 0;
727 len --, s ++)
728 {
729 DEBUG_printf(("%08x =>", *s));
730
731 temp = *s;
732 *s = ((temp & 0xff) << 24) |
733 ((temp & 0xff00) << 8) |
734 ((temp & 0xff0000) >> 8) |
735 ((temp & 0xff000000) >> 24);
736
737 DEBUG_printf((" %08x\n", *s));
738 }
739 }
740
741 /*
742 * Update the header and row count...
743 */
744
745 cups_raster_update(r);
746
747 return (1);
748 }
749
750
751 /*
752 * 'cups_raster_read()' - Read through the raster buffer.
753 */
754
755 static int /* O - Number of bytes read */
756 cups_raster_read(cups_raster_t *r, /* I - Raster stream */
757 unsigned char *buf, /* I - Buffer */
758 int bytes) /* I - Number of bytes to read */
759 {
760 int count, /* Number of bytes read */
761 remaining, /* Remaining bytes in buffer */
762 total; /* Total bytes read */
763
764
765 DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=%d)\n", r, buf, bytes));
766
767 if (!r->compressed)
768 return (cups_read(r->fd, buf, bytes));
769
770 /*
771 * Allocate a read buffer as needed...
772 */
773
774 count = 2 * r->header.cupsBytesPerLine;
775
776 if (count > r->bufsize)
777 {
778 int offset = r->bufptr - r->buffer; /* Offset to current start of buffer */
779 int end = r->bufend - r->buffer; /* Offset to current end of buffer */
780 unsigned char *rptr; /* Pointer in read buffer */
781
782 if (r->buffer)
783 rptr = realloc(r->buffer, count);
784 else
785 rptr = malloc(count);
786
787 if (!rptr)
788 return (0);
789
790 r->buffer = rptr;
791 r->bufptr = rptr + offset;
792 r->bufend = rptr + end;
793 r->bufsize = count;
794 }
795
796 /*
797 * Loop until we have read everything...
798 */
799
800 for (total = 0, remaining = r->bufend - r->bufptr;
801 total < bytes;
802 total += count, buf += count)
803 {
804 count = bytes - total;
805
806 DEBUG_printf(("count=%d, remaining=%d, buf=%p, bufptr=%p, bufend=%p...\n",
807 count, remaining, buf, r->bufptr, r->bufend));
808
809 if (remaining == 0)
810 {
811 if (count < 16)
812 {
813 /*
814 * Read into the raster buffer and then copy...
815 */
816
817 remaining = cups_read(r->fd, r->buffer, r->bufsize);
818 if (remaining <= 0)
819 return (0);
820
821 r->bufptr = r->buffer;
822 r->bufend = r->buffer + remaining;
823 }
824 else
825 {
826 /*
827 * Read directly into "buf"...
828 */
829
830 count = cups_read(r->fd, buf, count);
831
832 if (count <= 0)
833 return (0);
834
835 continue;
836 }
837 }
838
839 /*
840 * Copy bytes from raster buffer to "buf"...
841 */
842
843 if (count > remaining)
844 count = remaining;
845
846 if (count == 1)
847 {
848 /*
849 * Copy 1 byte...
850 */
851
852 *buf = *(r->bufptr)++;
853 remaining --;
854 }
855 else if (count < 128)
856 {
857 /*
858 * Copy up to 127 bytes without using memcpy(); this is
859 * faster because it avoids an extra function call and is
860 * often further optimized by the compiler...
861 */
862
863 unsigned char *bufptr; /* Temporary buffer pointer */
864
865
866 remaining -= count;
867
868 for (bufptr = r->bufptr; count > 0; count --, total ++)
869 *buf++ = *bufptr++;
870
871 r->bufptr = bufptr;
872 }
873 else
874 {
875 /*
876 * Use memcpy() for a large read...
877 */
878
879 memcpy(buf, r->bufptr, count);
880 r->bufptr += count;
881 remaining -= count;
882 }
883 }
884
885 return (total);
886 }
887
888
889 /*
890 * 'cups_raster_update()' - Update the raster header and row count for the
891 * current page.
892 */
893
894 static void
895 cups_raster_update(cups_raster_t *r) /* I - Raster stream */
896 {
897 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1 ||
898 r->header.cupsNumColors == 0)
899 {
900 /*
901 * Set the "cupsNumColors" field according to the colorspace...
902 */
903
904 switch (r->header.cupsColorSpace)
905 {
906 case CUPS_CSPACE_W :
907 case CUPS_CSPACE_K :
908 case CUPS_CSPACE_WHITE :
909 case CUPS_CSPACE_GOLD :
910 case CUPS_CSPACE_SILVER :
911 r->header.cupsNumColors = 1;
912 break;
913
914 case CUPS_CSPACE_RGB :
915 case CUPS_CSPACE_CMY :
916 case CUPS_CSPACE_YMC :
917 case CUPS_CSPACE_CIEXYZ :
918 case CUPS_CSPACE_CIELab :
919 case CUPS_CSPACE_ICC1 :
920 case CUPS_CSPACE_ICC2 :
921 case CUPS_CSPACE_ICC3 :
922 case CUPS_CSPACE_ICC4 :
923 case CUPS_CSPACE_ICC5 :
924 case CUPS_CSPACE_ICC6 :
925 case CUPS_CSPACE_ICC7 :
926 case CUPS_CSPACE_ICC8 :
927 case CUPS_CSPACE_ICC9 :
928 case CUPS_CSPACE_ICCA :
929 case CUPS_CSPACE_ICCB :
930 case CUPS_CSPACE_ICCC :
931 case CUPS_CSPACE_ICCD :
932 case CUPS_CSPACE_ICCE :
933 case CUPS_CSPACE_ICCF :
934 r->header.cupsNumColors = 3;
935 break;
936
937 case CUPS_CSPACE_RGBA :
938 case CUPS_CSPACE_RGBW :
939 case CUPS_CSPACE_CMYK :
940 case CUPS_CSPACE_YMCK :
941 case CUPS_CSPACE_KCMY :
942 case CUPS_CSPACE_GMCK :
943 case CUPS_CSPACE_GMCS :
944 r->header.cupsNumColors = 4;
945 break;
946
947 case CUPS_CSPACE_KCMYcm :
948 if (r->header.cupsBitsPerPixel < 8)
949 r->header.cupsNumColors = 6;
950 else
951 r->header.cupsNumColors = 4;
952 break;
953 }
954 }
955
956 /*
957 * Set the number of bytes per pixel/color...
958 */
959
960 if (r->header.cupsColorOrder == CUPS_ORDER_CHUNKED)
961 r->bpp = (r->header.cupsBitsPerPixel + 7) / 8;
962 else
963 r->bpp = (r->header.cupsBitsPerColor + 7) / 8;
964
965 /*
966 * Set the number of remaining rows...
967 */
968
969 if (r->header.cupsColorOrder == CUPS_ORDER_PLANAR)
970 r->remaining = r->header.cupsHeight * r->header.cupsNumColors;
971 else
972 r->remaining = r->header.cupsHeight;
973
974 /*
975 * Allocate the compression buffer...
976 */
977
978 if (r->compressed)
979 {
980 if (r->pixels != NULL)
981 free(r->pixels);
982
983 r->pixels = calloc(r->header.cupsBytesPerLine, 1);
984 r->pcurrent = r->pixels;
985 r->pend = r->pixels + r->header.cupsBytesPerLine;
986 r->count = 0;
987 }
988 }
989
990
991 /*
992 * 'cups_raster_write()' - Write a row of compressed raster data...
993 */
994
995 static int /* O - Number of bytes written */
996 cups_raster_write(
997 cups_raster_t *r, /* I - Raster stream */
998 const unsigned char *pixels) /* I - Pixel data to write */
999 {
1000 const unsigned char *start, /* Start of sequence */
1001 *ptr, /* Current pointer in sequence */
1002 *pend, /* End of raster buffer */
1003 *plast; /* Pointer to last pixel */
1004 unsigned char *wptr; /* Pointer into write buffer */
1005 int bpp, /* Bytes per pixel */
1006 count, /* Count */
1007 maxrun; /* Maximum run of 128 * bpp */
1008
1009
1010 DEBUG_printf(("cups_raster_write(r=%p, pixels=%p)\n", r, pixels));
1011
1012 /*
1013 * Allocate a write buffer as needed...
1014 */
1015
1016 count = r->header.cupsBytesPerLine * 2;
1017 if (count > r->bufsize)
1018 {
1019 if (r->buffer)
1020 wptr = realloc(r->buffer, count);
1021 else
1022 wptr = malloc(count);
1023
1024 if (!wptr)
1025 return (-1);
1026
1027 r->buffer = wptr;
1028 r->bufsize = count;
1029 }
1030
1031 /*
1032 * Write the row repeat count...
1033 */
1034
1035 bpp = r->bpp;
1036 pend = pixels + r->header.cupsBytesPerLine;
1037 plast = pend - bpp;
1038 wptr = r->buffer;
1039 *wptr++ = r->count - 1;
1040 maxrun = 128 * bpp;
1041
1042 /*
1043 * Write using a modified TIFF "packbits" compression...
1044 */
1045
1046 for (ptr = pixels; ptr < pend;)
1047 {
1048 start = ptr;
1049 ptr += bpp;
1050
1051 if (ptr == pend)
1052 {
1053 /*
1054 * Encode a single pixel at the end...
1055 */
1056
1057 *wptr++ = 0;
1058 for (count = bpp; count > 0; count --)
1059 *wptr++ = *start++;
1060 }
1061 else if (!memcmp(start, ptr, bpp))
1062 {
1063 /*
1064 * Encode a sequence of repeating pixels...
1065 */
1066
1067 for (count = 2; count < 128 && ptr < plast; count ++, ptr += bpp)
1068 if (memcmp(ptr, ptr + bpp, bpp))
1069 break;
1070
1071 *wptr++ = count - 1;
1072 for (count = bpp; count > 0; count --)
1073 *wptr++ = *ptr++;
1074 }
1075 else
1076 {
1077 /*
1078 * Encode a sequence of non-repeating pixels...
1079 */
1080
1081 for (count = 1; count < 127 && ptr < plast; count ++, ptr += bpp)
1082 if (!memcmp(ptr, ptr + bpp, bpp))
1083 break;
1084
1085 if (ptr >= plast && count < 128)
1086 {
1087 count ++;
1088 ptr += bpp;
1089 }
1090
1091 *wptr++ = 257 - count;
1092
1093 count *= bpp;
1094 memcpy(wptr, start, count);
1095 wptr += count;
1096 }
1097 }
1098
1099 return (cups_write(r->fd, r->buffer, wptr - r->buffer));
1100 }
1101
1102
1103 /*
1104 * 'cups_read()' - Read bytes from a file.
1105 */
1106
1107 static int /* O - Bytes read or -1 */
1108 cups_read(int fd, /* I - File descriptor */
1109 unsigned char *buf, /* I - Buffer for read */
1110 int bytes) /* I - Number of bytes to read */
1111 {
1112 int count, /* Number of bytes read */
1113 total; /* Total bytes read */
1114
1115
1116 for (total = 0; total < bytes; total += count, buf += count)
1117 {
1118 count = read(fd, buf, bytes - total);
1119
1120 if (count == 0)
1121 return (0);
1122 else if (count < 0)
1123 {
1124 if (errno == EINTR)
1125 count = 0;
1126 else
1127 return (-1);
1128 }
1129 }
1130
1131 return (total);
1132 }
1133
1134
1135 /*
1136 * 'cups_swap()' - Swap bytes in raster data...
1137 */
1138
1139 static void
1140 cups_swap(unsigned char *buf, /* I - Buffer to swap */
1141 int bytes) /* I - Number of bytes to swap */
1142 {
1143 unsigned char even, odd; /* Temporary variables */
1144
1145
1146 bytes /= 2;
1147
1148 while (bytes > 0)
1149 {
1150 even = buf[0];
1151 odd = buf[1];
1152 buf[0] = odd;
1153 buf[1] = even;
1154
1155 buf += 2;
1156 bytes --;
1157 }
1158 }
1159
1160
1161 /*
1162 * 'cups_write()' - Write bytes to a file.
1163 */
1164
1165 static int /* O - Bytes written or -1 */
1166 cups_write(int fd, /* I - File descriptor */
1167 const unsigned char *buf, /* I - Bytes to write */
1168 int bytes) /* I - Number of bytes to write */
1169 {
1170 int count, /* Number of bytes written */
1171 total; /* Total bytes written */
1172
1173
1174 for (total = 0; total < bytes; total += count, buf += count)
1175 {
1176 count = write(fd, buf, bytes - total);
1177
1178 if (count < 0)
1179 {
1180 if (errno == EINTR)
1181 count = 0;
1182 else
1183 return (-1);
1184 }
1185 }
1186
1187 return (total);
1188 }
1189
1190
1191 /*
1192 * End of "$Id: raster.c 6649 2007-07-11 21:46:42Z mike $".
1193 */