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