2 * "$Id: raster.c 7720 2008-07-11 22:46:21Z mike $"
4 * Raster file routines for CUPS.
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
9 * This file is part of the CUPS Imaging library.
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/".
17 * This file is subject to the Apple OS-Developed Software exception.
21 * cupsRasterClose() - Close a raster stream.
22 * cupsRasterOpen() - Open a raster stream using a file descriptor.
23 * cupsRasterOpenIO() - Open a raster stream using a callback function.
24 * cupsRasterReadHeader() - Read a raster page header and store it in a
25 * version 1 page header structure.
26 * cupsRasterReadHeader2() - Read a raster page header and store it in a
27 * version 2 page header structure.
28 * cupsRasterReadPixels() - Read raster pixels.
29 * cupsRasterWriteHeader() - Write a raster page header from a version 1
30 * page header structure.
31 * cupsRasterWriteHeader2() - Write a raster page header from a version 2
32 * page header structure.
33 * cupsRasterWritePixels() - Write raster pixels.
34 * cups_raster_read_header() - Read a raster page header.
35 * cups_raster_read() - Read through the raster buffer.
36 * cups_raster_update() - Update the raster header and row count for the
38 * cups_raster_write() - Write a row of compressed raster data...
39 * cups_read_fd() - Read bytes from a file.
40 * cups_swap() - Swap bytes in raster data...
41 * cups_write_fd() - Write bytes to a file.
45 * Include necessary headers...
48 #include "image-private.h"
49 #if defined(WIN32) || defined(__EMX__)
51 # include <winsock2.h> /* for htonl() definition */
54 #endif /* WIN32 || __EMX__ */
58 * Private structures...
61 struct _cups_raster_s
/**** Raster stream data ****/
63 unsigned sync
; /* Sync word from start of stream */
64 void *ctx
; /* File descriptor */
65 cups_raster_iocb_t iocb
; /* IO callback */
66 cups_mode_t mode
; /* Read/write mode */
67 cups_page_header2_t header
; /* Raster header for current page */
68 int count
, /* Current row run-length count */
69 remaining
, /* Remaining rows in page image */
70 bpp
; /* Bytes per pixel/color */
71 unsigned char *pixels
, /* Pixels for current row */
72 *pend
, /* End of pixel buffer */
73 *pcurrent
; /* Current byte in pixel buffer */
74 int compressed
, /* Non-zero if data is compressed */
75 swapped
; /* Non-zero if data is byte-swapped */
76 unsigned char *buffer
, /* Read/write buffer */
77 *bufptr
, /* Current (read) position in buffer */
78 *bufend
; /* End of current (read) buffer */
79 size_t bufsize
; /* Buffer size */
87 static unsigned cups_raster_read_header(cups_raster_t
*r
);
88 static int cups_raster_read(cups_raster_t
*r
, unsigned char *buf
,
90 static void cups_raster_update(cups_raster_t
*r
);
91 static int cups_raster_write(cups_raster_t
*r
,
92 const unsigned char *pixels
);
93 static ssize_t
cups_read_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
94 static void cups_swap(unsigned char *buf
, int bytes
);
95 static ssize_t
cups_write_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
99 * 'cupsRasterClose()' - Close a raster stream.
101 * The file descriptor associated with the raster stream must be closed
102 * separately as needed.
106 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
122 * 'cupsRasterOpen()' - Open a raster stream using a file descriptor.
124 * This function associates a raster stream with the given file descriptor.
125 * For most printer driver filters, "fd" will be 0 (stdin). For most raster
126 * image processor (RIP) filters that generate raster data, "fd" will be 1
129 * When writing raster data, the @code CUPS_RASTER_WRITE@,
130 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
131 * be used - compressed and PWG output is generally 25-50% smaller but adds a
132 * 100-300% execution time overhead.
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@,
138 @code CUPS_RASTER_WRITE@,
139 @code CUPS_RASTER_WRITE_COMPRESSED@,
140 or @code CUPS_RASTER_WRITE_PWG@ */
142 if (mode
== CUPS_RASTER_READ
)
143 return (cupsRasterOpenIO(cups_read_fd
, (void *)((intptr_t)fd
), mode
));
145 return (cupsRasterOpenIO(cups_write_fd
, (void *)((intptr_t)fd
), mode
));
150 * 'cupsRasterOpenIO()' - Open a raster stream using a callback function.
152 * This function associates a raster stream with the given callback function and
155 * When writing raster data, the @code CUPS_RASTER_WRITE@,
156 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
157 * be used - compressed and PWG output is generally 25-50% smaller but adds a
158 * 100-300% execution time overhead.
161 cups_raster_t
* /* O - New stream */
163 cups_raster_iocb_t iocb
, /* I - Read/write callback */
164 void *ctx
, /* I - Context pointer for callback */
165 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
166 @code CUPS_RASTER_WRITE@,
167 @code CUPS_RASTER_WRITE_COMPRESSED@,
168 or @code CUPS_RASTER_WRITE_PWG@ */
170 cups_raster_t
*r
; /* New stream */
173 _cupsRasterClearError();
175 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
177 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
186 if (mode
== CUPS_RASTER_READ
)
189 * Open for read - get sync word...
192 if ((*r
->iocb
)(r
->ctx
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) !=
195 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
201 if (r
->sync
!= CUPS_RASTER_SYNC
&&
202 r
->sync
!= CUPS_RASTER_REVSYNC
&&
203 r
->sync
!= CUPS_RASTER_SYNCv1
&&
204 r
->sync
!= CUPS_RASTER_REVSYNCv1
&&
205 r
->sync
!= CUPS_RASTER_SYNCv2
&&
206 r
->sync
!= CUPS_RASTER_REVSYNCv2
)
208 _cupsRasterAddError("Unknown raster format %08x!\n", r
->sync
);
213 if (r
->sync
== CUPS_RASTER_SYNCv2
||
214 r
->sync
== CUPS_RASTER_REVSYNCv2
)
217 if (r
->sync
== CUPS_RASTER_REVSYNC
||
218 r
->sync
== CUPS_RASTER_REVSYNCv1
||
219 r
->sync
== CUPS_RASTER_REVSYNCv2
)
222 DEBUG_printf(("r->swapped=%d, r->sync=%08x\n", r
->swapped
, r
->sync
));
227 * Open for write - put sync word...
233 case CUPS_RASTER_WRITE
:
234 r
->sync
= CUPS_RASTER_SYNC
;
237 case CUPS_RASTER_WRITE_COMPRESSED
:
239 r
->sync
= CUPS_RASTER_SYNCv2
;
242 case CUPS_RASTER_WRITE_PWG
:
244 r
->sync
= htonl(CUPS_RASTER_SYNC_PWG
);
245 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNC_PWG
;
249 if ((*r
->iocb
)(r
->ctx
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
))
252 _cupsRasterAddError("Unable to write raster stream header: %s\n",
264 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
265 * version 1 page header structure.
267 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
269 * Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset
270 * of the version 2 page header data. This function handles reading version 2
271 * page headers and copying only the version 1 data into the provided buffer.
276 unsigned /* O - 1 on success, 0 on failure/end-of-file */
277 cupsRasterReadHeader(
278 cups_raster_t
*r
, /* I - Raster stream */
279 cups_page_header_t
*h
) /* I - Pointer to header data */
282 * Get the raster header...
285 if (!cups_raster_read_header(r
))
289 * Copy the header to the user-supplied buffer...
292 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
299 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
300 * version 2 page header structure.
302 * @since CUPS 1.2/Mac OS X 10.5@
305 unsigned /* O - 1 on success, 0 on failure/end-of-file */
306 cupsRasterReadHeader2(
307 cups_raster_t
*r
, /* I - Raster stream */
308 cups_page_header2_t
*h
) /* I - Pointer to header data */
311 * Get the raster header...
314 if (!cups_raster_read_header(r
))
318 * Copy the header to the user-supplied buffer...
321 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
328 * 'cupsRasterReadPixels()' - Read raster pixels.
330 * For best performance, filters should read one or more whole lines.
331 * The "cupsBytesPerLine" value from the page header can be used to allocate
332 * the line buffer and as the number of bytes to read.
335 unsigned /* O - Number of bytes read */
336 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
337 unsigned char *p
, /* I - Pointer to pixel buffer */
338 unsigned len
) /* I - Number of bytes to read */
340 int bytes
; /* Bytes read */
341 unsigned cupsBytesPerLine
; /* cupsBytesPerLine value */
342 unsigned remaining
; /* Bytes remaining */
343 unsigned char *ptr
, /* Pointer to read buffer */
344 byte
, /* Byte from file */
345 *temp
; /* Pointer into buffer */
346 int count
; /* Repetition count */
349 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0)
355 * Read without compression...
358 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
360 if ((*r
->iocb
)(r
->ctx
, p
, len
) < (ssize_t
)len
)
364 * Swap bytes as needed...
368 (r
->header
.cupsBitsPerColor
== 16 ||
369 r
->header
.cupsBitsPerPixel
== 12 ||
370 r
->header
.cupsBitsPerPixel
== 16))
381 * Read compressed data...
385 cupsBytesPerLine
= r
->header
.cupsBytesPerLine
;
387 while (remaining
> 0 && r
->remaining
> 0)
392 * Need to read a new row...
395 if (remaining
== cupsBytesPerLine
)
401 * Read using a modified PackBits compression...
404 if (!cups_raster_read(r
, &byte
, 1))
413 bytes
= cupsBytesPerLine
;
418 * Get a new repeat count...
421 if (!cups_raster_read(r
, &byte
, 1))
427 * Copy N literal pixels...
430 count
= (257 - byte
) * r
->bpp
;
435 if (!cups_raster_read(r
, temp
, count
))
444 * Repeat the next N bytes...
447 count
= (byte
+ 1) * r
->bpp
;
456 if (!cups_raster_read(r
, temp
, r
->bpp
))
464 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
472 * Swap bytes as needed...
475 if ((r
->header
.cupsBitsPerColor
== 16 ||
476 r
->header
.cupsBitsPerPixel
== 12 ||
477 r
->header
.cupsBitsPerPixel
== 16) &&
479 cups_swap(ptr
, bytes
);
485 if (remaining
>= cupsBytesPerLine
)
487 bytes
= cupsBytesPerLine
;
488 r
->pcurrent
= r
->pixels
;
495 r
->pcurrent
= r
->pixels
+ bytes
;
499 * Copy data as needed...
503 memcpy(p
, ptr
, bytes
);
508 * Copy fragment from buffer...
511 if ((unsigned)(bytes
= r
->pend
- r
->pcurrent
) > remaining
)
514 memcpy(p
, r
->pcurrent
, bytes
);
515 r
->pcurrent
+= bytes
;
517 if (r
->pcurrent
>= r
->pend
)
519 r
->pcurrent
= r
->pixels
;
534 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
537 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
542 unsigned /* O - 1 on success, 0 on failure */
543 cupsRasterWriteHeader(
544 cups_raster_t
*r
, /* I - Raster stream */
545 cups_page_header_t
*h
) /* I - Raster page header */
547 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
551 * Make a copy of the header, and compute the number of raster
552 * lines in the page image...
555 memset(&(r
->header
), 0, sizeof(r
->header
));
556 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
558 cups_raster_update(r
);
561 * Write the raster header...
564 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
567 * PWG raster data is always network byte order with most of the page header
571 cups_page_header2_t fh
; /* File page header */
573 memset(&fh
, 0, sizeof(fh
));
574 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
575 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
576 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
577 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
578 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
579 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
580 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
581 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
582 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
584 return ((*r
->iocb
)(r
->ctx
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
587 return ((*r
->iocb
)(r
->ctx
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
588 == sizeof(r
->header
));
593 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
594 * page header structure.
596 * The page header can be initialized using @link cupsRasterInterpretPPD@.
598 * @since CUPS 1.2/Mac OS X 10.5@
601 unsigned /* O - 1 on success, 0 on failure */
602 cupsRasterWriteHeader2(
603 cups_raster_t
*r
, /* I - Raster stream */
604 cups_page_header2_t
*h
) /* I - Raster page header */
606 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
610 * Make a copy of the header, and compute the number of raster
611 * lines in the page image...
614 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
616 cups_raster_update(r
);
619 * Write the raster header...
622 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
625 * PWG raster data is always network byte order with most of the page header
629 cups_page_header2_t fh
; /* File page header */
631 memset(&fh
, 0, sizeof(fh
));
632 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
633 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
634 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
635 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
636 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
637 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
638 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
639 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
640 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
642 return ((*r
->iocb
)(r
->ctx
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
645 return ((*r
->iocb
)(r
->ctx
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
646 == sizeof(r
->header
));
651 * 'cupsRasterWritePixels()' - Write raster pixels.
653 * For best performance, filters should write one or more whole lines.
654 * The "cupsBytesPerLine" value from the page header can be used to allocate
655 * the line buffer and as the number of bytes to write.
658 unsigned /* O - Number of bytes written */
659 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
660 unsigned char *p
, /* I - Bytes to write */
661 unsigned len
)/* I - Number of bytes to write */
663 int bytes
; /* Bytes read */
664 unsigned remaining
; /* Bytes remaining */
667 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
668 r
, p
, len
, r
->remaining
));
670 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
|| r
->remaining
== 0)
676 * Without compression, just write the raster data raw unless the data needs
680 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
683 (r
->header
.cupsBitsPerColor
== 16 ||
684 r
->header
.cupsBitsPerPixel
== 12 ||
685 r
->header
.cupsBitsPerPixel
== 16))
687 unsigned char *bufptr
; /* Pointer into write buffer */
688 unsigned count
; /* Remaining count */
691 * Allocate a write buffer as needed...
694 if ((size_t)len
> r
->bufsize
)
697 bufptr
= realloc(r
->buffer
, len
);
699 bufptr
= malloc(len
);
709 * Byte swap the pixels...
712 for (bufptr
= r
->buffer
, count
= len
; count
> 1; count
-= 2, bufptr
+= 2)
718 if (count
) /* This should never happen... */
722 * Write the byte-swapped buffer...
725 return ((*r
->iocb
)(r
->ctx
, r
->buffer
, len
));
728 return ((*r
->iocb
)(r
->ctx
, p
, len
));
732 * Otherwise, compress each line...
735 for (remaining
= len
; remaining
> 0; remaining
-= bytes
, p
+= bytes
)
738 * Figure out the number of remaining bytes on the current line...
741 if ((bytes
= remaining
) > (r
->pend
- r
->pcurrent
))
742 bytes
= r
->pend
- r
->pcurrent
;
747 * Check to see if this line is the same as the previous line...
750 if (memcmp(p
, r
->pcurrent
, bytes
))
752 if (!cups_raster_write(r
, r
->pixels
))
760 * Mark more bytes as the same...
763 r
->pcurrent
+= bytes
;
765 if (r
->pcurrent
>= r
->pend
)
768 * Increase the repeat count...
772 r
->pcurrent
= r
->pixels
;
775 * Flush out this line if it is the last one...
780 if (r
->remaining
== 0)
781 return (cups_raster_write(r
, r
->pixels
));
782 else if (r
->count
== 256)
784 if (cups_raster_write(r
, r
->pixels
) == 0)
798 * Copy the raster data to the buffer...
801 memcpy(r
->pcurrent
, p
, bytes
);
803 r
->pcurrent
+= bytes
;
805 if (r
->pcurrent
>= r
->pend
)
808 * Increase the repeat count...
812 r
->pcurrent
= r
->pixels
;
815 * Flush out this line if it is the last one...
820 if (r
->remaining
== 0)
821 return (cups_raster_write(r
, r
->pixels
));
831 * 'cups_raster_read_header()' - Read a raster page header.
834 static unsigned /* O - 1 on success, 0 on fail */
835 cups_raster_read_header(
836 cups_raster_t
*r
) /* I - Raster stream */
838 int len
; /* Length for read/swap */
841 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
845 * Get the length of the raster header...
848 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
849 len
= sizeof(cups_page_header_t
);
851 len
= sizeof(cups_page_header2_t
);
857 memset(&(r
->header
), 0, sizeof(r
->header
));
859 if (cups_raster_read(r
, (unsigned char *)&(r
->header
), len
) < len
)
863 * Swap bytes as needed...
868 unsigned *s
, /* Current word */
869 temp
; /* Temporary copy */
872 DEBUG_puts("Swapping header bytes...");
874 for (len
= 81, s
= &(r
->header
.AdvanceDistance
);
878 DEBUG_printf(("%08x =>", *s
));
881 *s
= ((temp
& 0xff) << 24) |
882 ((temp
& 0xff00) << 8) |
883 ((temp
& 0xff0000) >> 8) |
884 ((temp
& 0xff000000) >> 24);
886 DEBUG_printf((" %08x\n", *s
));
891 * Update the header and row count...
894 cups_raster_update(r
);
901 * 'cups_raster_read()' - Read through the raster buffer.
904 static int /* O - Number of bytes read */
905 cups_raster_read(cups_raster_t
*r
, /* I - Raster stream */
906 unsigned char *buf
, /* I - Buffer */
907 int bytes
) /* I - Number of bytes to read */
909 int count
, /* Number of bytes read */
910 remaining
, /* Remaining bytes in buffer */
911 total
; /* Total bytes read */
914 DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=%d)\n", r
, buf
, bytes
));
917 return ((*r
->iocb
)(r
->ctx
, buf
, bytes
));
920 * Allocate a read buffer as needed...
923 count
= 2 * r
->header
.cupsBytesPerLine
;
925 if ((size_t)count
> r
->bufsize
)
927 int offset
= r
->bufptr
- r
->buffer
; /* Offset to current start of buffer */
928 int end
= r
->bufend
- r
->buffer
; /* Offset to current end of buffer */
929 unsigned char *rptr
; /* Pointer in read buffer */
932 rptr
= realloc(r
->buffer
, count
);
934 rptr
= malloc(count
);
940 r
->bufptr
= rptr
+ offset
;
941 r
->bufend
= rptr
+ end
;
946 * Loop until we have read everything...
949 for (total
= 0, remaining
= r
->bufend
- r
->bufptr
;
951 total
+= count
, buf
+= count
)
953 count
= bytes
- total
;
955 DEBUG_printf(("count=%d, remaining=%d, buf=%p, bufptr=%p, bufend=%p...\n",
956 count
, remaining
, buf
, r
->bufptr
, r
->bufend
));
963 * Read into the raster buffer and then copy...
966 remaining
= (*r
->iocb
)(r
->ctx
, r
->buffer
, r
->bufsize
);
970 r
->bufptr
= r
->buffer
;
971 r
->bufend
= r
->buffer
+ remaining
;
976 * Read directly into "buf"...
979 count
= (*r
->iocb
)(r
->ctx
, buf
, count
);
989 * Copy bytes from raster buffer to "buf"...
992 if (count
> remaining
)
1001 *buf
= *(r
->bufptr
)++;
1004 else if (count
< 128)
1007 * Copy up to 127 bytes without using memcpy(); this is
1008 * faster because it avoids an extra function call and is
1009 * often further optimized by the compiler...
1012 unsigned char *bufptr
; /* Temporary buffer pointer */
1017 for (bufptr
= r
->bufptr
; count
> 0; count
--, total
++)
1025 * Use memcpy() for a large read...
1028 memcpy(buf
, r
->bufptr
, count
);
1039 * 'cups_raster_update()' - Update the raster header and row count for the
1044 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
1046 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
1047 r
->header
.cupsNumColors
== 0)
1050 * Set the "cupsNumColors" field according to the colorspace...
1053 switch (r
->header
.cupsColorSpace
)
1055 case CUPS_CSPACE_W
:
1056 case CUPS_CSPACE_K
:
1057 case CUPS_CSPACE_WHITE
:
1058 case CUPS_CSPACE_GOLD
:
1059 case CUPS_CSPACE_SILVER
:
1060 case CUPS_CSPACE_SW
:
1061 r
->header
.cupsNumColors
= 1;
1064 case CUPS_CSPACE_RGB
:
1065 case CUPS_CSPACE_CMY
:
1066 case CUPS_CSPACE_YMC
:
1067 case CUPS_CSPACE_CIEXYZ
:
1068 case CUPS_CSPACE_CIELab
:
1069 case CUPS_CSPACE_SRGB
:
1070 case CUPS_CSPACE_ADOBERGB
:
1071 case CUPS_CSPACE_ICC1
:
1072 case CUPS_CSPACE_ICC2
:
1073 case CUPS_CSPACE_ICC3
:
1074 case CUPS_CSPACE_ICC4
:
1075 case CUPS_CSPACE_ICC5
:
1076 case CUPS_CSPACE_ICC6
:
1077 case CUPS_CSPACE_ICC7
:
1078 case CUPS_CSPACE_ICC8
:
1079 case CUPS_CSPACE_ICC9
:
1080 case CUPS_CSPACE_ICCA
:
1081 case CUPS_CSPACE_ICCB
:
1082 case CUPS_CSPACE_ICCC
:
1083 case CUPS_CSPACE_ICCD
:
1084 case CUPS_CSPACE_ICCE
:
1085 case CUPS_CSPACE_ICCF
:
1086 r
->header
.cupsNumColors
= 3;
1089 case CUPS_CSPACE_RGBA
:
1090 case CUPS_CSPACE_RGBW
:
1091 case CUPS_CSPACE_CMYK
:
1092 case CUPS_CSPACE_YMCK
:
1093 case CUPS_CSPACE_KCMY
:
1094 case CUPS_CSPACE_GMCK
:
1095 case CUPS_CSPACE_GMCS
:
1096 r
->header
.cupsNumColors
= 4;
1099 case CUPS_CSPACE_KCMYcm
:
1100 if (r
->header
.cupsBitsPerPixel
< 8)
1101 r
->header
.cupsNumColors
= 6;
1103 r
->header
.cupsNumColors
= 4;
1106 case CUPS_CSPACE_DEVICE1
:
1107 case CUPS_CSPACE_DEVICE2
:
1108 case CUPS_CSPACE_DEVICE3
:
1109 case CUPS_CSPACE_DEVICE4
:
1110 case CUPS_CSPACE_DEVICE5
:
1111 case CUPS_CSPACE_DEVICE6
:
1112 case CUPS_CSPACE_DEVICE7
:
1113 case CUPS_CSPACE_DEVICE8
:
1114 case CUPS_CSPACE_DEVICE9
:
1115 case CUPS_CSPACE_DEVICEA
:
1116 case CUPS_CSPACE_DEVICEB
:
1117 case CUPS_CSPACE_DEVICEC
:
1118 case CUPS_CSPACE_DEVICED
:
1119 case CUPS_CSPACE_DEVICEE
:
1120 case CUPS_CSPACE_DEVICEF
:
1121 r
->header
.cupsNumColors
= r
->header
.cupsColorSpace
-
1122 CUPS_CSPACE_DEVICE1
+ 1;
1128 * Set the number of bytes per pixel/color...
1131 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
1132 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
1134 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
1137 * Set the number of remaining rows...
1140 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
1141 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
1143 r
->remaining
= r
->header
.cupsHeight
;
1146 * Allocate the compression buffer...
1151 if (r
->pixels
!= NULL
)
1154 r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1);
1155 r
->pcurrent
= r
->pixels
;
1156 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
1163 * 'cups_raster_write()' - Write a row of compressed raster data...
1166 static int /* O - Number of bytes written */
1168 cups_raster_t
*r
, /* I - Raster stream */
1169 const unsigned char *pixels
) /* I - Pixel data to write */
1171 const unsigned char *start
, /* Start of sequence */
1172 *ptr
, /* Current pointer in sequence */
1173 *pend
, /* End of raster buffer */
1174 *plast
; /* Pointer to last pixel */
1175 unsigned char *wptr
; /* Pointer into write buffer */
1176 int bpp
, /* Bytes per pixel */
1180 DEBUG_printf(("cups_raster_write(r=%p, pixels=%p)\n", r
, pixels
));
1183 * Allocate a write buffer as needed...
1186 count
= r
->header
.cupsBytesPerLine
* 2;
1187 if ((size_t)count
> r
->bufsize
)
1190 wptr
= realloc(r
->buffer
, count
);
1192 wptr
= malloc(count
);
1202 * Write the row repeat count...
1206 pend
= pixels
+ r
->header
.cupsBytesPerLine
;
1209 *wptr
++ = r
->count
- 1;
1212 * Write using a modified TIFF "packbits" compression...
1215 for (ptr
= pixels
; ptr
< pend
;)
1223 * Encode a single pixel at the end...
1227 for (count
= bpp
; count
> 0; count
--)
1230 else if (!memcmp(start
, ptr
, bpp
))
1233 * Encode a sequence of repeating pixels...
1236 for (count
= 2; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1237 if (memcmp(ptr
, ptr
+ bpp
, bpp
))
1240 *wptr
++ = count
- 1;
1241 for (count
= bpp
; count
> 0; count
--)
1247 * Encode a sequence of non-repeating pixels...
1250 for (count
= 1; count
< 127 && ptr
< plast
; count
++, ptr
+= bpp
)
1251 if (!memcmp(ptr
, ptr
+ bpp
, bpp
))
1254 if (ptr
>= plast
&& count
< 128)
1260 *wptr
++ = 257 - count
;
1263 memcpy(wptr
, start
, count
);
1268 return ((*r
->iocb
)(r
->ctx
, r
->buffer
, wptr
- r
->buffer
));
1273 * 'cups_read_fd()' - Read bytes from a file.
1276 static ssize_t
/* O - Bytes read or -1 */
1277 cups_read_fd(void *ctx
, /* I - File descriptor as pointer */
1278 unsigned char *buf
, /* I - Buffer for read */
1279 size_t bytes
) /* I - Number of bytes to read */
1281 int fd
= (int)((intptr_t)ctx
);
1282 /* File descriptor */
1283 ssize_t count
; /* Number of bytes read */
1284 size_t total
; /* Total bytes read */
1287 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
1289 count
= read(fd
, buf
, bytes
- total
);
1302 return ((ssize_t
)total
);
1307 * 'cups_swap()' - Swap bytes in raster data...
1311 cups_swap(unsigned char *buf
, /* I - Buffer to swap */
1312 int bytes
) /* I - Number of bytes to swap */
1314 unsigned char even
, odd
; /* Temporary variables */
1333 * 'cups_write_fd()' - Write bytes to a file.
1336 static ssize_t
/* O - Bytes written or -1 */
1337 cups_write_fd(void *ctx
, /* I - File descriptor pointer */
1338 unsigned char *buf
, /* I - Bytes to write */
1339 size_t bytes
) /* I - Number of bytes to write */
1341 int fd
= (int)((intptr_t)ctx
);
1342 /* File descriptor */
1343 ssize_t count
; /* Number of bytes written */
1344 size_t total
; /* Total bytes written */
1347 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
1349 count
= write(fd
, buf
, bytes
- total
);
1360 return ((ssize_t
)total
);
1365 * End of "$Id: raster.c 7720 2008-07-11 22:46:21Z mike $".