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