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