4 * Raster file routines for CUPS.
6 * Copyright 2007-2015 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 * Include necessary headers...
24 #include <cups/raster-private.h>
27 #endif /* HAVE_STDINT_H */
31 * Private structures...
34 struct _cups_raster_s
/**** Raster stream data ****/
36 unsigned sync
; /* Sync word from start of stream */
37 void *ctx
; /* File descriptor */
38 cups_raster_iocb_t iocb
; /* IO callback */
39 cups_mode_t mode
; /* Read/write mode */
40 cups_page_header2_t header
; /* Raster header for current page */
41 unsigned count
, /* Current row run-length count */
42 remaining
, /* Remaining rows in page image */
43 bpp
; /* Bytes per pixel/color */
44 unsigned char *pixels
, /* Pixels for current row */
45 *pend
, /* End of pixel buffer */
46 *pcurrent
; /* Current byte in pixel buffer */
47 int compressed
, /* Non-zero if data is compressed */
48 swapped
; /* Non-zero if data is byte-swapped */
49 unsigned char *buffer
, /* Read/write buffer */
50 *bufptr
, /* Current (read) position in buffer */
51 *bufend
; /* End of current (read) buffer */
52 size_t bufsize
; /* Buffer size */
54 size_t iocount
; /* Number of bytes read/written */
63 static ssize_t
cups_raster_io(cups_raster_t
*r
, unsigned char *buf
, size_t bytes
);
64 static unsigned cups_raster_read_header(cups_raster_t
*r
);
65 static ssize_t
cups_raster_read(cups_raster_t
*r
, unsigned char *buf
,
67 static int cups_raster_update(cups_raster_t
*r
);
68 static ssize_t
cups_raster_write(cups_raster_t
*r
,
69 const unsigned char *pixels
);
70 static ssize_t
cups_read_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
71 static void cups_swap(unsigned char *buf
, size_t bytes
);
72 static ssize_t
cups_write_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
76 * 'cupsRasterClose()' - Close a raster stream.
78 * The file descriptor associated with the raster stream must be closed
79 * separately as needed.
83 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
99 * 'cupsRasterOpen()' - Open a raster stream using a file descriptor.
101 * This function associates a raster stream with the given file descriptor.
102 * For most printer driver filters, "fd" will be 0 (stdin). For most raster
103 * image processor (RIP) filters that generate raster data, "fd" will be 1
106 * When writing raster data, the @code CUPS_RASTER_WRITE@,
107 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
108 * be used - compressed and PWG output is generally 25-50% smaller but adds a
109 * 100-300% execution time overhead.
112 cups_raster_t
* /* O - New stream */
113 cupsRasterOpen(int fd
, /* I - File descriptor */
114 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
115 @code CUPS_RASTER_WRITE@,
116 @code CUPS_RASTER_WRITE_COMPRESSED@,
117 or @code CUPS_RASTER_WRITE_PWG@ */
119 if (mode
== CUPS_RASTER_READ
)
120 return (cupsRasterOpenIO(cups_read_fd
, (void *)((intptr_t)fd
), mode
));
122 return (cupsRasterOpenIO(cups_write_fd
, (void *)((intptr_t)fd
), mode
));
127 * 'cupsRasterOpenIO()' - Open a raster stream using a callback function.
129 * This function associates a raster stream with the given callback function and
132 * When writing raster data, the @code CUPS_RASTER_WRITE@,
133 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
134 * be used - compressed and PWG output is generally 25-50% smaller but adds a
135 * 100-300% execution time overhead.
138 cups_raster_t
* /* O - New stream */
140 cups_raster_iocb_t iocb
, /* I - Read/write callback */
141 void *ctx
, /* I - Context pointer for callback */
142 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
143 @code CUPS_RASTER_WRITE@,
144 @code CUPS_RASTER_WRITE_COMPRESSED@,
145 or @code CUPS_RASTER_WRITE_PWG@ */
147 cups_raster_t
*r
; /* New stream */
150 _cupsRasterClearError();
152 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
154 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
163 if (mode
== CUPS_RASTER_READ
)
166 * Open for read - get sync word...
169 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) !=
172 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
178 if (r
->sync
!= CUPS_RASTER_SYNC
&&
179 r
->sync
!= CUPS_RASTER_REVSYNC
&&
180 r
->sync
!= CUPS_RASTER_SYNCv1
&&
181 r
->sync
!= CUPS_RASTER_REVSYNCv1
&&
182 r
->sync
!= CUPS_RASTER_SYNCv2
&&
183 r
->sync
!= CUPS_RASTER_REVSYNCv2
)
185 _cupsRasterAddError("Unknown raster format %08x!\n", r
->sync
);
190 if (r
->sync
== CUPS_RASTER_SYNCv2
||
191 r
->sync
== CUPS_RASTER_REVSYNCv2
)
194 if (r
->sync
== CUPS_RASTER_REVSYNC
||
195 r
->sync
== CUPS_RASTER_REVSYNCv1
||
196 r
->sync
== CUPS_RASTER_REVSYNCv2
)
199 DEBUG_printf(("1cupsRasterOpenIO: r->swapped=%d, r->sync=%08x\n", r
->swapped
, r
->sync
));
204 * Open for write - put sync word...
210 case CUPS_RASTER_WRITE
:
211 r
->sync
= CUPS_RASTER_SYNC
;
214 case CUPS_RASTER_WRITE_COMPRESSED
:
216 r
->sync
= CUPS_RASTER_SYNCv2
;
219 case CUPS_RASTER_WRITE_PWG
:
221 r
->sync
= htonl(CUPS_RASTER_SYNC_PWG
);
222 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNC_PWG
;
226 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) < (ssize_t
)sizeof(r
->sync
))
228 _cupsRasterAddError("Unable to write raster stream header: %s\n",
240 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
241 * version 1 page header structure.
243 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
245 * Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset
246 * of the version 2 page header data. This function handles reading version 2
247 * page headers and copying only the version 1 data into the provided buffer.
252 unsigned /* O - 1 on success, 0 on failure/end-of-file */
253 cupsRasterReadHeader(
254 cups_raster_t
*r
, /* I - Raster stream */
255 cups_page_header_t
*h
) /* I - Pointer to header data */
258 * Get the raster header...
261 if (!cups_raster_read_header(r
))
263 memset(h
, 0, sizeof(cups_page_header_t
));
268 * Copy the header to the user-supplied buffer...
271 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
278 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
279 * version 2 page header structure.
281 * @since CUPS 1.2/OS X 10.5@
284 unsigned /* O - 1 on success, 0 on failure/end-of-file */
285 cupsRasterReadHeader2(
286 cups_raster_t
*r
, /* I - Raster stream */
287 cups_page_header2_t
*h
) /* I - Pointer to header data */
290 * Get the raster header...
293 DEBUG_printf(("cupsRasterReadHeader2(r=%p, h=%p)", r
, h
));
295 if (!cups_raster_read_header(r
))
297 memset(h
, 0, sizeof(cups_page_header2_t
));
302 * Copy the header to the user-supplied buffer...
305 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
312 * 'cupsRasterReadPixels()' - Read raster pixels.
314 * For best performance, filters should read one or more whole lines.
315 * The "cupsBytesPerLine" value from the page header can be used to allocate
316 * the line buffer and as the number of bytes to read.
319 unsigned /* O - Number of bytes read */
320 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
321 unsigned char *p
, /* I - Pointer to pixel buffer */
322 unsigned len
) /* I - Number of bytes to read */
324 ssize_t bytes
; /* Bytes read */
325 unsigned cupsBytesPerLine
; /* cupsBytesPerLine value */
326 unsigned remaining
; /* Bytes remaining */
327 unsigned char *ptr
, /* Pointer to read buffer */
328 byte
, /* Byte from file */
329 *temp
; /* Pointer into buffer */
330 unsigned count
; /* Repetition count */
333 DEBUG_printf(("cupsRasterReadPixels(r=%p, p=%p, len=%u)", r
, p
, len
));
335 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0 ||
336 r
->header
.cupsBytesPerLine
== 0)
338 DEBUG_puts("1cupsRasterReadPixels: Returning 0.");
342 DEBUG_printf(("1cupsRasterReadPixels: compressed=%d, remaining=%u", r
->compressed
, r
->remaining
));
347 * Read without compression...
350 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
352 if (cups_raster_io(r
, p
, len
) < (ssize_t
)len
)
354 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
359 * Swap bytes as needed...
363 (r
->header
.cupsBitsPerColor
== 16 ||
364 r
->header
.cupsBitsPerPixel
== 12 ||
365 r
->header
.cupsBitsPerPixel
== 16))
372 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len
));
378 * Read compressed data...
382 cupsBytesPerLine
= r
->header
.cupsBytesPerLine
;
384 while (remaining
> 0 && r
->remaining
> 0)
389 * Need to read a new row...
392 if (remaining
== cupsBytesPerLine
)
398 * Read using a modified PackBits compression...
401 if (!cups_raster_read(r
, &byte
, 1))
403 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
407 r
->count
= (unsigned)byte
+ 1;
413 bytes
= (ssize_t
)cupsBytesPerLine
;
418 * Get a new repeat count...
421 if (!cups_raster_read(r
, &byte
, 1))
423 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
430 * Copy N literal pixels...
433 count
= (unsigned)(257 - byte
) * r
->bpp
;
435 if (count
> (unsigned)bytes
)
436 count
= (unsigned)bytes
;
438 if (!cups_raster_read(r
, temp
, count
))
440 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
450 * Repeat the next N bytes...
453 count
= ((unsigned)byte
+ 1) * r
->bpp
;
454 if (count
> (unsigned)bytes
)
455 count
= (unsigned)bytes
;
462 if (!cups_raster_read(r
, temp
, r
->bpp
))
464 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
473 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
481 * Swap bytes as needed...
484 if ((r
->header
.cupsBitsPerColor
== 16 ||
485 r
->header
.cupsBitsPerPixel
== 12 ||
486 r
->header
.cupsBitsPerPixel
== 16) &&
488 cups_swap(ptr
, (size_t)bytes
);
494 if (remaining
>= cupsBytesPerLine
)
496 bytes
= (ssize_t
)cupsBytesPerLine
;
497 r
->pcurrent
= r
->pixels
;
503 bytes
= (ssize_t
)remaining
;
504 r
->pcurrent
= r
->pixels
+ bytes
;
508 * Copy data as needed...
512 memcpy(p
, ptr
, (size_t)bytes
);
517 * Copy fragment from buffer...
520 if ((unsigned)(bytes
= (int)(r
->pend
- r
->pcurrent
)) > remaining
)
521 bytes
= (ssize_t
)remaining
;
523 memcpy(p
, r
->pcurrent
, (size_t)bytes
);
524 r
->pcurrent
+= bytes
;
526 if (r
->pcurrent
>= r
->pend
)
528 r
->pcurrent
= r
->pixels
;
534 remaining
-= (unsigned)bytes
;
538 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len
));
545 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
548 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
553 unsigned /* O - 1 on success, 0 on failure */
554 cupsRasterWriteHeader(
555 cups_raster_t
*r
, /* I - Raster stream */
556 cups_page_header_t
*h
) /* I - Raster page header */
558 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
562 * Make a copy of the header, and compute the number of raster
563 * lines in the page image...
566 memset(&(r
->header
), 0, sizeof(r
->header
));
567 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
569 if (!cups_raster_update(r
))
573 * Write the raster header...
576 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
579 * PWG raster data is always network byte order with much of the page header
583 cups_page_header2_t fh
; /* File page header */
585 memset(&fh
, 0, sizeof(fh
));
587 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
589 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
590 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
591 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
592 /* PrintContentType */
594 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
595 fh
.Duplex
= htonl(r
->header
.Duplex
);
596 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
597 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
598 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
599 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
600 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
601 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
602 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
603 fh
.Jog
= htonl(r
->header
.Jog
);
604 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
605 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
606 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
607 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
608 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
609 fh
.Orientation
= htonl(r
->header
.Orientation
);
610 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
611 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
612 fh
.Tumble
= htonl(r
->header
.Tumble
);
613 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
614 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
615 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
616 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
617 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
618 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
619 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
620 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
621 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
623 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
624 /* CrossFeedTransform */
625 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
627 fh
.cupsInteger
[3] = htonl(r
->header
.cupsInteger
[3]);
629 fh
.cupsInteger
[4] = htonl(r
->header
.cupsInteger
[4]);
631 fh
.cupsInteger
[5] = htonl(r
->header
.cupsInteger
[5]);
633 fh
.cupsInteger
[6] = htonl(r
->header
.cupsInteger
[6]);
635 fh
.cupsInteger
[7] = htonl(r
->header
.cupsInteger
[7]);
637 fh
.cupsInteger
[8] = htonl(r
->header
.cupsInteger
[8]);
639 fh
.cupsInteger
[14] = htonl(r
->header
.cupsInteger
[14]);
640 /* VendorIdentifier */
641 fh
.cupsInteger
[15] = htonl(r
->header
.cupsInteger
[15]);
644 void *dst
= fh
.cupsReal
; /* Bypass bogus compiler warning */
645 void *src
= r
->header
.cupsReal
;
646 memcpy(dst
, src
, sizeof(fh
.cupsReal
) + sizeof(fh
.cupsString
));
649 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
650 sizeof(fh
.cupsRenderingIntent
));
651 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
652 sizeof(fh
.cupsPageSizeName
));
654 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
657 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
658 == sizeof(r
->header
));
663 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
664 * page header structure.
666 * The page header can be initialized using @link cupsRasterInterpretPPD@.
668 * @since CUPS 1.2/OS X 10.5@
671 unsigned /* O - 1 on success, 0 on failure */
672 cupsRasterWriteHeader2(
673 cups_raster_t
*r
, /* I - Raster stream */
674 cups_page_header2_t
*h
) /* I - Raster page header */
676 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
680 * Make a copy of the header, and compute the number of raster
681 * lines in the page image...
684 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
686 if (!cups_raster_update(r
))
690 * Write the raster header...
693 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
696 * PWG raster data is always network byte order with most of the page header
700 cups_page_header2_t fh
; /* File page header */
702 memset(&fh
, 0, sizeof(fh
));
703 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
704 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
705 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
706 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
707 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
708 sizeof(fh
.cupsRenderingIntent
));
709 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
710 sizeof(fh
.cupsPageSizeName
));
712 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
713 fh
.Duplex
= htonl(r
->header
.Duplex
);
714 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
715 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
716 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
717 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
718 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
719 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
720 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
721 fh
.Jog
= htonl(r
->header
.Jog
);
722 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
723 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
724 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
725 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
726 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
727 fh
.Orientation
= htonl(r
->header
.Orientation
);
728 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
729 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
730 fh
.Tumble
= htonl(r
->header
.Tumble
);
731 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
732 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
733 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
734 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
735 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
736 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
737 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
738 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
739 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
740 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
741 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
742 fh
.cupsInteger
[3] = htonl((unsigned)(r
->header
.cupsImagingBBox
[0] * r
->header
.HWResolution
[0] / 72.0));
743 fh
.cupsInteger
[4] = htonl((unsigned)(r
->header
.cupsImagingBBox
[1] * r
->header
.HWResolution
[1] / 72.0));
744 fh
.cupsInteger
[5] = htonl((unsigned)(r
->header
.cupsImagingBBox
[2] * r
->header
.HWResolution
[0] / 72.0));
745 fh
.cupsInteger
[6] = htonl((unsigned)(r
->header
.cupsImagingBBox
[3] * r
->header
.HWResolution
[1] / 72.0));
746 fh
.cupsInteger
[7] = htonl(0xffffff);
748 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
751 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
752 == sizeof(r
->header
));
757 * 'cupsRasterWritePixels()' - Write raster pixels.
759 * For best performance, filters should write one or more whole lines.
760 * The "cupsBytesPerLine" value from the page header can be used to allocate
761 * the line buffer and as the number of bytes to write.
764 unsigned /* O - Number of bytes written */
765 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
766 unsigned char *p
, /* I - Bytes to write */
767 unsigned len
)/* I - Number of bytes to write */
769 ssize_t bytes
; /* Bytes read */
770 unsigned remaining
; /* Bytes remaining */
773 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
774 r
, p
, len
, r
->remaining
));
776 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
|| r
->remaining
== 0)
782 * Without compression, just write the raster data raw unless the data needs
786 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
789 (r
->header
.cupsBitsPerColor
== 16 ||
790 r
->header
.cupsBitsPerPixel
== 12 ||
791 r
->header
.cupsBitsPerPixel
== 16))
793 unsigned char *bufptr
; /* Pointer into write buffer */
794 unsigned count
; /* Remaining count */
797 * Allocate a write buffer as needed...
800 if ((size_t)len
> r
->bufsize
)
803 bufptr
= realloc(r
->buffer
, len
);
805 bufptr
= malloc(len
);
815 * Byte swap the pixels...
818 for (bufptr
= r
->buffer
, count
= len
; count
> 1; count
-= 2, bufptr
+= 2)
824 if (count
) /* This should never happen... */
828 * Write the byte-swapped buffer...
831 bytes
= cups_raster_io(r
, r
->buffer
, len
);
834 bytes
= cups_raster_io(r
, p
, len
);
843 * Otherwise, compress each line...
846 for (remaining
= len
; remaining
> 0; remaining
-= (unsigned)bytes
, p
+= bytes
)
849 * Figure out the number of remaining bytes on the current line...
852 if ((bytes
= (ssize_t
)remaining
) > (ssize_t
)(r
->pend
- r
->pcurrent
))
853 bytes
= (ssize_t
)(r
->pend
- r
->pcurrent
);
858 * Check to see if this line is the same as the previous line...
861 if (memcmp(p
, r
->pcurrent
, (size_t)bytes
))
863 if (cups_raster_write(r
, r
->pixels
) <= 0)
871 * Mark more bytes as the same...
874 r
->pcurrent
+= bytes
;
876 if (r
->pcurrent
>= r
->pend
)
879 * Increase the repeat count...
883 r
->pcurrent
= r
->pixels
;
886 * Flush out this line if it is the last one...
891 if (r
->remaining
== 0)
893 if (cups_raster_write(r
, r
->pixels
) <= 0)
898 else if (r
->count
== 256)
900 if (cups_raster_write(r
, r
->pixels
) <= 0)
914 * Copy the raster data to the buffer...
917 memcpy(r
->pcurrent
, p
, (size_t)bytes
);
919 r
->pcurrent
+= bytes
;
921 if (r
->pcurrent
>= r
->pend
)
924 * Increase the repeat count...
928 r
->pcurrent
= r
->pixels
;
931 * Flush out this line if it is the last one...
936 if (r
->remaining
== 0)
938 if (cups_raster_write(r
, r
->pixels
) <= 0)
950 * 'cups_raster_read_header()' - Read a raster page header.
953 static unsigned /* O - 1 on success, 0 on fail */
954 cups_raster_read_header(
955 cups_raster_t
*r
) /* I - Raster stream */
957 size_t len
; /* Length for read/swap */
960 DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%d", r
, r
? r
->mode
: 0));
962 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
965 DEBUG_printf(("4cups_raster_read_header: r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
968 * Get the length of the raster header...
971 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
972 len
= sizeof(cups_page_header_t
);
974 len
= sizeof(cups_page_header2_t
);
976 DEBUG_printf(("4cups_raster_read_header: len=%d", (int)len
));
982 memset(&(r
->header
), 0, sizeof(r
->header
));
984 if (cups_raster_read(r
, (unsigned char *)&(r
->header
), len
) < (ssize_t
)len
)
986 DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
991 * Swap bytes as needed...
996 unsigned *s
, /* Current word */
997 temp
; /* Temporary copy */
1000 DEBUG_puts("4cups_raster_read_header: Swapping header bytes.");
1002 for (len
= 81, s
= &(r
->header
.AdvanceDistance
);
1007 *s
= ((temp
& 0xff) << 24) |
1008 ((temp
& 0xff00) << 8) |
1009 ((temp
& 0xff0000) >> 8) |
1010 ((temp
& 0xff000000) >> 24);
1012 DEBUG_printf(("4cups_raster_read_header: %08x => %08x", temp
, *s
));
1017 * Update the header and row count...
1020 if (!cups_raster_update(r
))
1023 DEBUG_printf(("4cups_raster_read_header: cupsBitsPerPixel=%u, cupsBitsPerColor=%u, cupsBytesPerLine=%u, cupsWidth=%u, cupsHeight=%u, r->bpp=%d", r
->header
.cupsBitsPerPixel
, r
->header
.cupsBitsPerColor
, r
->header
.cupsBytesPerLine
, r
->header
.cupsWidth
, r
->header
.cupsHeight
, r
->bpp
));
1025 return (r
->header
.cupsBitsPerPixel
> 0 && r
->header
.cupsBitsPerPixel
<= 240 && r
->header
.cupsBitsPerColor
> 0 && r
->header
.cupsBitsPerColor
<= 16 && r
->header
.cupsBytesPerLine
!= 0 && r
->header
.cupsHeight
!= 0 && (r
->header
.cupsBytesPerLine
% r
->bpp
) == 0);
1030 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
1033 static ssize_t
/* O - Bytes read/write or -1 */
1034 cups_raster_io(cups_raster_t
*r
, /* I - Raster stream */
1035 unsigned char *buf
, /* I - Buffer for read/write */
1036 size_t bytes
) /* I - Number of bytes to read/write */
1038 ssize_t count
, /* Number of bytes read/written */
1039 total
; /* Total bytes read/written */
1042 DEBUG_printf(("5cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT
")", r
, buf
, CUPS_LLCAST bytes
));
1044 for (total
= 0; total
< (ssize_t
)bytes
; total
+= count
, buf
+= count
)
1046 count
= (*r
->iocb
)(r
->ctx
, buf
, bytes
- (size_t)total
);
1048 DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count
, (int)total
));
1051 DEBUG_puts("6cups_raster_io: Returning 0.");
1056 DEBUG_puts("6cups_raster_io: Returning -1 on error.");
1061 r
->iocount
+= (size_t)count
;
1065 DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT
".", CUPS_LLCAST total
));
1072 * 'cups_raster_read()' - Read through the raster buffer.
1075 static ssize_t
/* O - Number of bytes read */
1076 cups_raster_read(cups_raster_t
*r
, /* I - Raster stream */
1077 unsigned char *buf
, /* I - Buffer */
1078 size_t bytes
) /* I - Number of bytes to read */
1080 ssize_t count
, /* Number of bytes read */
1081 remaining
, /* Remaining bytes in buffer */
1082 total
; /* Total bytes read */
1085 DEBUG_printf(("5cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT
")\n", r
, buf
, CUPS_LLCAST bytes
));
1088 return (cups_raster_io(r
, buf
, bytes
));
1091 * Allocate a read buffer as needed...
1094 count
= (ssize_t
)(2 * r
->header
.cupsBytesPerLine
);
1098 if ((size_t)count
> r
->bufsize
)
1100 ssize_t offset
= r
->bufptr
- r
->buffer
;
1101 /* Offset to current start of buffer */
1102 ssize_t end
= r
->bufend
- r
->buffer
;/* Offset to current end of buffer */
1103 unsigned char *rptr
; /* Pointer in read buffer */
1106 rptr
= realloc(r
->buffer
, (size_t)count
);
1108 rptr
= malloc((size_t)count
);
1114 r
->bufptr
= rptr
+ offset
;
1115 r
->bufend
= rptr
+ end
;
1116 r
->bufsize
= (size_t)count
;
1120 * Loop until we have read everything...
1123 for (total
= 0, remaining
= (int)(r
->bufend
- r
->bufptr
);
1124 total
< (ssize_t
)bytes
;
1125 total
+= count
, buf
+= count
)
1127 count
= (ssize_t
)bytes
- total
;
1129 DEBUG_printf(("6cups_raster_read: count=" CUPS_LLFMT
", remaining=" CUPS_LLFMT
", buf=%p, bufptr=%p, bufend=%p", CUPS_LLCAST count
, CUPS_LLCAST remaining
, buf
, r
->bufptr
, r
->bufend
));
1136 * Read into the raster buffer and then copy...
1139 remaining
= (*r
->iocb
)(r
->ctx
, r
->buffer
, r
->bufsize
);
1143 r
->bufptr
= r
->buffer
;
1144 r
->bufend
= r
->buffer
+ remaining
;
1147 r
->iocount
+= (size_t)remaining
;
1153 * Read directly into "buf"...
1156 count
= (*r
->iocb
)(r
->ctx
, buf
, (size_t)count
);
1162 r
->iocount
+= (size_t)count
;
1170 * Copy bytes from raster buffer to "buf"...
1173 if (count
> remaining
)
1182 *buf
= *(r
->bufptr
)++;
1185 else if (count
< 128)
1188 * Copy up to 127 bytes without using memcpy(); this is
1189 * faster because it avoids an extra function call and is
1190 * often further optimized by the compiler...
1193 unsigned char *bufptr
; /* Temporary buffer pointer */
1197 for (bufptr
= r
->bufptr
; count
> 0; count
--, total
++)
1205 * Use memcpy() for a large read...
1208 memcpy(buf
, r
->bufptr
, (size_t)count
);
1214 DEBUG_printf(("6cups_raster_read: Returning %ld", (long)total
));
1221 * 'cups_raster_update()' - Update the raster header and row count for the
1225 static int /* O - 1 on success, 0 on failure */
1226 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
1228 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
1229 r
->header
.cupsNumColors
== 0)
1232 * Set the "cupsNumColors" field according to the colorspace...
1235 switch (r
->header
.cupsColorSpace
)
1237 case CUPS_CSPACE_W
:
1238 case CUPS_CSPACE_K
:
1239 case CUPS_CSPACE_WHITE
:
1240 case CUPS_CSPACE_GOLD
:
1241 case CUPS_CSPACE_SILVER
:
1242 case CUPS_CSPACE_SW
:
1243 r
->header
.cupsNumColors
= 1;
1246 case CUPS_CSPACE_RGB
:
1247 case CUPS_CSPACE_CMY
:
1248 case CUPS_CSPACE_YMC
:
1249 case CUPS_CSPACE_CIEXYZ
:
1250 case CUPS_CSPACE_CIELab
:
1251 case CUPS_CSPACE_SRGB
:
1252 case CUPS_CSPACE_ADOBERGB
:
1253 case CUPS_CSPACE_ICC1
:
1254 case CUPS_CSPACE_ICC2
:
1255 case CUPS_CSPACE_ICC3
:
1256 case CUPS_CSPACE_ICC4
:
1257 case CUPS_CSPACE_ICC5
:
1258 case CUPS_CSPACE_ICC6
:
1259 case CUPS_CSPACE_ICC7
:
1260 case CUPS_CSPACE_ICC8
:
1261 case CUPS_CSPACE_ICC9
:
1262 case CUPS_CSPACE_ICCA
:
1263 case CUPS_CSPACE_ICCB
:
1264 case CUPS_CSPACE_ICCC
:
1265 case CUPS_CSPACE_ICCD
:
1266 case CUPS_CSPACE_ICCE
:
1267 case CUPS_CSPACE_ICCF
:
1268 r
->header
.cupsNumColors
= 3;
1271 case CUPS_CSPACE_RGBA
:
1272 case CUPS_CSPACE_RGBW
:
1273 case CUPS_CSPACE_CMYK
:
1274 case CUPS_CSPACE_YMCK
:
1275 case CUPS_CSPACE_KCMY
:
1276 case CUPS_CSPACE_GMCK
:
1277 case CUPS_CSPACE_GMCS
:
1278 r
->header
.cupsNumColors
= 4;
1281 case CUPS_CSPACE_KCMYcm
:
1282 if (r
->header
.cupsBitsPerPixel
< 8)
1283 r
->header
.cupsNumColors
= 6;
1285 r
->header
.cupsNumColors
= 4;
1288 case CUPS_CSPACE_DEVICE1
:
1289 case CUPS_CSPACE_DEVICE2
:
1290 case CUPS_CSPACE_DEVICE3
:
1291 case CUPS_CSPACE_DEVICE4
:
1292 case CUPS_CSPACE_DEVICE5
:
1293 case CUPS_CSPACE_DEVICE6
:
1294 case CUPS_CSPACE_DEVICE7
:
1295 case CUPS_CSPACE_DEVICE8
:
1296 case CUPS_CSPACE_DEVICE9
:
1297 case CUPS_CSPACE_DEVICEA
:
1298 case CUPS_CSPACE_DEVICEB
:
1299 case CUPS_CSPACE_DEVICEC
:
1300 case CUPS_CSPACE_DEVICED
:
1301 case CUPS_CSPACE_DEVICEE
:
1302 case CUPS_CSPACE_DEVICEF
:
1303 r
->header
.cupsNumColors
= r
->header
.cupsColorSpace
-
1304 CUPS_CSPACE_DEVICE1
+ 1;
1308 /* Unknown color space */
1314 * Set the number of bytes per pixel/color...
1317 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
1318 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
1320 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
1326 * Set the number of remaining rows...
1329 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
1330 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
1332 r
->remaining
= r
->header
.cupsHeight
;
1335 * Allocate the compression buffer...
1340 if (r
->pixels
!= NULL
)
1343 r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1);
1344 r
->pcurrent
= r
->pixels
;
1345 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
1354 * 'cups_raster_write()' - Write a row of compressed raster data...
1357 static ssize_t
/* O - Number of bytes written */
1359 cups_raster_t
*r
, /* I - Raster stream */
1360 const unsigned char *pixels
) /* I - Pixel data to write */
1362 const unsigned char *start
, /* Start of sequence */
1363 *ptr
, /* Current pointer in sequence */
1364 *pend
, /* End of raster buffer */
1365 *plast
; /* Pointer to last pixel */
1366 unsigned char *wptr
; /* Pointer into write buffer */
1367 unsigned bpp
, /* Bytes per pixel */
1371 DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)\n", r
, pixels
));
1374 * Allocate a write buffer as needed...
1377 count
= r
->header
.cupsBytesPerLine
* 2;
1381 if ((size_t)count
> r
->bufsize
)
1384 wptr
= realloc(r
->buffer
, count
);
1386 wptr
= malloc(count
);
1390 DEBUG_printf(("4cups_raster_write: Unable to allocate " CUPS_LLFMT
" bytes for raster buffer: %s", CUPS_LLCAST count
, strerror(errno
)));
1399 * Write the row repeat count...
1403 pend
= pixels
+ r
->header
.cupsBytesPerLine
;
1406 *wptr
++ = (unsigned char)(r
->count
- 1);
1409 * Write using a modified PackBits compression...
1412 for (ptr
= pixels
; ptr
< pend
;)
1420 * Encode a single pixel at the end...
1424 for (count
= bpp
; count
> 0; count
--)
1427 else if (!memcmp(start
, ptr
, bpp
))
1430 * Encode a sequence of repeating pixels...
1433 for (count
= 2; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1434 if (memcmp(ptr
, ptr
+ bpp
, bpp
))
1437 *wptr
++ = (unsigned char)(count
- 1);
1438 for (count
= bpp
; count
> 0; count
--)
1444 * Encode a sequence of non-repeating pixels...
1447 for (count
= 1; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1448 if (!memcmp(ptr
, ptr
+ bpp
, bpp
))
1451 if (ptr
>= plast
&& count
< 128)
1457 *wptr
++ = (unsigned char)(257 - count
);
1460 memcpy(wptr
, start
, count
);
1465 DEBUG_printf(("4cups_raster_write: Writing " CUPS_LLFMT
" bytes.", CUPS_LLCAST (wptr
- r
->buffer
)));
1467 return (cups_raster_io(r
, r
->buffer
, (size_t)(wptr
- r
->buffer
)));
1472 * 'cups_read_fd()' - Read bytes from a file.
1475 static ssize_t
/* O - Bytes read or -1 */
1476 cups_read_fd(void *ctx
, /* I - File descriptor as pointer */
1477 unsigned char *buf
, /* I - Buffer for read */
1478 size_t bytes
) /* I - Maximum number of bytes to read */
1480 int fd
= (int)((intptr_t)ctx
);
1481 /* File descriptor */
1482 ssize_t count
; /* Number of bytes read */
1485 #ifdef WIN32 /* Sigh */
1486 while ((count
= read(fd
, buf
, (unsigned)bytes
)) < 0)
1488 while ((count
= read(fd
, buf
, bytes
)) < 0)
1490 if (errno
!= EINTR
&& errno
!= EAGAIN
)
1492 DEBUG_printf(("4cups_read_fd: %s", strerror(errno
)));
1496 DEBUG_printf(("4cups_read_fd: Returning %d bytes.", (int)count
));
1503 * 'cups_swap()' - Swap bytes in raster data...
1507 cups_swap(unsigned char *buf
, /* I - Buffer to swap */
1508 size_t bytes
) /* I - Number of bytes to swap */
1510 unsigned char even
, odd
; /* Temporary variables */
1529 * 'cups_write_fd()' - Write bytes to a file.
1532 static ssize_t
/* O - Bytes written or -1 */
1533 cups_write_fd(void *ctx
, /* I - File descriptor pointer */
1534 unsigned char *buf
, /* I - Bytes to write */
1535 size_t bytes
) /* I - Number of bytes to write */
1537 int fd
= (int)((intptr_t)ctx
);
1538 /* File descriptor */
1539 ssize_t count
; /* Number of bytes written */
1542 #ifdef WIN32 /* Sigh */
1543 while ((count
= write(fd
, buf
, (unsigned)bytes
)) < 0)
1545 while ((count
= write(fd
, buf
, bytes
)) < 0)
1547 if (errno
!= EINTR
&& errno
!= EAGAIN
)
1549 DEBUG_printf(("4cups_write_fd: %s", strerror(errno
)));