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