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