2 * Raster file routines for CUPS.
4 * Copyright 2007-2015 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products.
7 * This file is part of the CUPS Imaging library.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * Include necessary headers...
22 #include <cups/raster-private.h>
25 #endif /* HAVE_STDINT_H */
29 * Private structures...
32 struct _cups_raster_s
/**** Raster stream data ****/
34 unsigned sync
; /* Sync word from start of stream */
35 void *ctx
; /* File descriptor */
36 cups_raster_iocb_t iocb
; /* IO callback */
37 cups_mode_t mode
; /* Read/write mode */
38 cups_page_header2_t header
; /* Raster header for current page */
39 unsigned count
, /* Current row run-length count */
40 remaining
, /* Remaining rows in page image */
41 bpp
; /* Bytes per pixel/color */
42 unsigned char *pixels
, /* Pixels for current row */
43 *pend
, /* End of pixel buffer */
44 *pcurrent
; /* Current byte in pixel buffer */
45 int compressed
, /* Non-zero if data is compressed */
46 swapped
; /* Non-zero if data is byte-swapped */
47 unsigned char *buffer
, /* Read/write buffer */
48 *bufptr
, /* Current (read) position in buffer */
49 *bufend
; /* End of current (read) buffer */
50 size_t bufsize
; /* Buffer size */
52 size_t iocount
; /* Number of bytes read/written */
61 static ssize_t
cups_raster_io(cups_raster_t
*r
, unsigned char *buf
, size_t bytes
);
62 static unsigned cups_raster_read_header(cups_raster_t
*r
);
63 static ssize_t
cups_raster_read(cups_raster_t
*r
, unsigned char *buf
,
65 static int cups_raster_update(cups_raster_t
*r
);
66 static ssize_t
cups_raster_write(cups_raster_t
*r
,
67 const unsigned char *pixels
);
68 static ssize_t
cups_read_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
69 static void cups_swap(unsigned char *buf
, size_t bytes
);
70 static ssize_t
cups_write_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
74 * 'cupsRasterClose()' - Close a raster stream.
76 * The file descriptor associated with the raster stream must be closed
77 * separately as needed.
81 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
97 * 'cupsRasterInitPWGHeader()' - Initialize a page header for PWG Raster output.
99 * The "media" argument specifies the media to use.
101 * The "type" argument specifies a "pwg-raster-document-type-supported" value
102 * that controls the color space and bit depth of the raster data.
104 * The "xres" and "yres" arguments specify the raster resolution in dots per
107 * The "sheet_back" argument specifies a "pwg-raster-document-sheet-back" value
108 * to apply for the back side of a page. Pass @code NULL@ for the front side.
113 int /* O - 1 on success, 0 on failure */
114 cupsRasterInitPWGHeader(
115 cups_page_header2_t
*h
, /* I - Page header */
116 pwg_media_t
*media
, /* I - PWG media information */
117 const char *type
, /* I - PWG raster type string */
118 int xdpi
, /* I - Cross-feed direction (horizontal) resolution */
119 int ydpi
, /* I - Feed direction (vertical) resolution */
120 const char *sides
, /* I - IPP "sides" option value */
121 const char *sheet_back
) /* I - Transform for back side or @code NULL@ for none */
123 if (!h
|| !media
|| !type
|| xdpi
<= 0 || ydpi
<= 0)
125 _cupsRasterAddError("%s", strerror(EINVAL
));
130 * Initialize the page header...
133 memset(h
, 0, sizeof(cups_page_header2_t
));
135 strlcpy(h
->cupsPageSizeName
, media
->pwg
, sizeof(h
->cupsPageSizeName
));
137 h
->PageSize
[0] = (unsigned)(72 * media
->width
/ 2540);
138 h
->PageSize
[1] = (unsigned)(72 * media
->length
/ 2540);
140 /* This never gets written but is needed for some applications */
141 h
->cupsPageSize
[0] = 72.0f
* media
->width
/ 2540.0f
;
142 h
->cupsPageSize
[1] = 72.0f
* media
->length
/ 2540.0f
;
144 h
->ImagingBoundingBox
[2] = h
->PageSize
[0];
145 h
->ImagingBoundingBox
[3] = h
->PageSize
[1];
147 h
->HWResolution
[0] = (unsigned)xdpi
;
148 h
->HWResolution
[1] = (unsigned)ydpi
;
150 h
->cupsWidth
= (unsigned)(media
->width
* xdpi
/ 2540);
151 h
->cupsHeight
= (unsigned)(media
->length
* ydpi
/ 2540);
153 if (h
->cupsWidth
> 0x00ffffff || h
->cupsHeight
> 0x00ffffff)
155 _cupsRasterAddError("Raster dimensions too large.");
159 h
->cupsInteger
[CUPS_RASTER_PWG_ImageBoxRight
] = h
->cupsWidth
;
160 h
->cupsInteger
[CUPS_RASTER_PWG_ImageBoxBottom
] = h
->cupsHeight
;
163 * Colorspace and bytes per line...
166 if (!strcmp(type
, "adobe-rgb_8"))
168 h
->cupsBitsPerColor
= 8;
169 h
->cupsBitsPerPixel
= 24;
170 h
->cupsColorSpace
= CUPS_CSPACE_ADOBERGB
;
172 else if (!strcmp(type
, "adobe-rgb_16"))
174 h
->cupsBitsPerColor
= 16;
175 h
->cupsBitsPerPixel
= 48;
176 h
->cupsColorSpace
= CUPS_CSPACE_ADOBERGB
;
178 else if (!strcmp(type
, "black_1"))
180 h
->cupsBitsPerColor
= 1;
181 h
->cupsBitsPerPixel
= 1;
182 h
->cupsColorSpace
= CUPS_CSPACE_K
;
184 else if (!strcmp(type
, "black_8"))
186 h
->cupsBitsPerColor
= 8;
187 h
->cupsBitsPerPixel
= 8;
188 h
->cupsColorSpace
= CUPS_CSPACE_K
;
190 else if (!strcmp(type
, "black_16"))
192 h
->cupsBitsPerColor
= 16;
193 h
->cupsBitsPerPixel
= 16;
194 h
->cupsColorSpace
= CUPS_CSPACE_K
;
196 else if (!strcmp(type
, "cmyk_8"))
198 h
->cupsBitsPerColor
= 8;
199 h
->cupsBitsPerPixel
= 32;
200 h
->cupsColorSpace
= CUPS_CSPACE_CMYK
;
202 else if (!strcmp(type
, "cmyk_16"))
204 h
->cupsBitsPerColor
= 16;
205 h
->cupsBitsPerPixel
= 64;
206 h
->cupsColorSpace
= CUPS_CSPACE_CMYK
;
208 else if (!strncmp(type
, "device", 6) && type
[6] >= '1' && type
[6] <= '9')
210 int ncolors
, bits
; /* Number of colors and bits */
213 if (sscanf(type
, "device%d_%d", &ncolors
, &bits
) != 2 || ncolors
> 15 || (bits
!= 8 && bits
!= 16))
215 _cupsRasterAddError("Unsupported raster type \'%s\'.", type
);
219 h
->cupsBitsPerColor
= (unsigned)bits
;
220 h
->cupsBitsPerPixel
= (unsigned)(ncolors
* bits
);
221 h
->cupsColorSpace
= (cups_cspace_t
)(CUPS_CSPACE_DEVICE1
+ ncolors
- 1);
223 else if (!strcmp(type
, "rgb_8"))
225 h
->cupsBitsPerColor
= 8;
226 h
->cupsBitsPerPixel
= 24;
227 h
->cupsColorSpace
= CUPS_CSPACE_RGB
;
229 else if (!strcmp(type
, "rgb_16"))
231 h
->cupsBitsPerColor
= 16;
232 h
->cupsBitsPerPixel
= 48;
233 h
->cupsColorSpace
= CUPS_CSPACE_RGB
;
235 else if (!strcmp(type
, "sgray_1"))
237 h
->cupsBitsPerColor
= 1;
238 h
->cupsBitsPerPixel
= 1;
239 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
241 else if (!strcmp(type
, "sgray_8"))
243 h
->cupsBitsPerColor
= 8;
244 h
->cupsBitsPerPixel
= 8;
245 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
247 else if (!strcmp(type
, "sgray_16"))
249 h
->cupsBitsPerColor
= 16;
250 h
->cupsBitsPerPixel
= 16;
251 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
253 else if (!strcmp(type
, "srgb_8"))
255 h
->cupsBitsPerColor
= 8;
256 h
->cupsBitsPerPixel
= 24;
257 h
->cupsColorSpace
= CUPS_CSPACE_SRGB
;
259 else if (!strcmp(type
, "srgb_16"))
261 h
->cupsBitsPerColor
= 16;
262 h
->cupsBitsPerPixel
= 48;
263 h
->cupsColorSpace
= CUPS_CSPACE_SRGB
;
267 _cupsRasterAddError("Unsupported raster type \'%s\'.", type
);
271 h
->cupsColorOrder
= CUPS_ORDER_CHUNKED
;
272 h
->cupsNumColors
= h
->cupsBitsPerPixel
/ h
->cupsBitsPerColor
;
273 h
->cupsBytesPerLine
= (h
->cupsWidth
* h
->cupsBitsPerPixel
+ 7) / 8;
279 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 1;
280 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 1;
284 if (!strcmp(sides
, "two-sided-long-edge"))
288 else if (!strcmp(sides
, "two-sided-short-edge"))
293 else if (strcmp(sides
, "one-sided"))
295 _cupsRasterAddError("Unsupported sides value \'%s\'.", sides
);
301 if (!strcmp(sheet_back
, "flipped"))
304 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
306 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
308 else if (!strcmp(sheet_back
, "manual-tumble"))
312 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
313 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
316 else if (!strcmp(sheet_back
, "rotated"))
320 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
321 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
324 else if (strcmp(sheet_back
, "normal"))
326 _cupsRasterAddError("Unsupported sheet_back value \'%s\'.", sheet_back
);
337 * 'cupsRasterOpen()' - Open a raster stream using a file descriptor.
339 * This function associates a raster stream with the given file descriptor.
340 * For most printer driver filters, "fd" will be 0 (stdin). For most raster
341 * image processor (RIP) filters that generate raster data, "fd" will be 1
344 * When writing raster data, the @code CUPS_RASTER_WRITE@,
345 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
346 * be used - compressed and PWG output is generally 25-50% smaller but adds a
347 * 100-300% execution time overhead.
350 cups_raster_t
* /* O - New stream */
351 cupsRasterOpen(int fd
, /* I - File descriptor */
352 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
353 @code CUPS_RASTER_WRITE@,
354 @code CUPS_RASTER_WRITE_COMPRESSED@,
355 or @code CUPS_RASTER_WRITE_PWG@ */
357 if (mode
== CUPS_RASTER_READ
)
358 return (cupsRasterOpenIO(cups_read_fd
, (void *)((intptr_t)fd
), mode
));
360 return (cupsRasterOpenIO(cups_write_fd
, (void *)((intptr_t)fd
), mode
));
365 * 'cupsRasterOpenIO()' - Open a raster stream using a callback function.
367 * This function associates a raster stream with the given callback function and
370 * When writing raster data, the @code CUPS_RASTER_WRITE@,
371 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
372 * be used - compressed and PWG output is generally 25-50% smaller but adds a
373 * 100-300% execution time overhead.
376 cups_raster_t
* /* O - New stream */
378 cups_raster_iocb_t iocb
, /* I - Read/write callback */
379 void *ctx
, /* I - Context pointer for callback */
380 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
381 @code CUPS_RASTER_WRITE@,
382 @code CUPS_RASTER_WRITE_COMPRESSED@,
383 or @code CUPS_RASTER_WRITE_PWG@ */
385 cups_raster_t
*r
; /* New stream */
388 _cupsRasterClearError();
390 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
392 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
401 if (mode
== CUPS_RASTER_READ
)
404 * Open for read - get sync word...
407 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) !=
410 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
416 if (r
->sync
!= CUPS_RASTER_SYNC
&&
417 r
->sync
!= CUPS_RASTER_REVSYNC
&&
418 r
->sync
!= CUPS_RASTER_SYNCv1
&&
419 r
->sync
!= CUPS_RASTER_REVSYNCv1
&&
420 r
->sync
!= CUPS_RASTER_SYNCv2
&&
421 r
->sync
!= CUPS_RASTER_REVSYNCv2
)
423 _cupsRasterAddError("Unknown raster format %08x!\n", r
->sync
);
428 if (r
->sync
== CUPS_RASTER_SYNCv2
||
429 r
->sync
== CUPS_RASTER_REVSYNCv2
)
432 if (r
->sync
== CUPS_RASTER_REVSYNC
||
433 r
->sync
== CUPS_RASTER_REVSYNCv1
||
434 r
->sync
== CUPS_RASTER_REVSYNCv2
)
437 DEBUG_printf(("1cupsRasterOpenIO: r->swapped=%d, r->sync=%08x\n", r
->swapped
, r
->sync
));
442 * Open for write - put sync word...
448 case CUPS_RASTER_WRITE
:
449 r
->sync
= CUPS_RASTER_SYNC
;
452 case CUPS_RASTER_WRITE_COMPRESSED
:
454 r
->sync
= CUPS_RASTER_SYNCv2
;
457 case CUPS_RASTER_WRITE_PWG
:
459 r
->sync
= htonl(CUPS_RASTER_SYNC_PWG
);
460 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNC_PWG
;
464 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) < (ssize_t
)sizeof(r
->sync
))
466 _cupsRasterAddError("Unable to write raster stream header: %s\n",
478 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
479 * version 1 page header structure.
481 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
483 * Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset
484 * of the version 2 page header data. This function handles reading version 2
485 * page headers and copying only the version 1 data into the provided buffer.
490 unsigned /* O - 1 on success, 0 on failure/end-of-file */
491 cupsRasterReadHeader(
492 cups_raster_t
*r
, /* I - Raster stream */
493 cups_page_header_t
*h
) /* I - Pointer to header data */
496 * Get the raster header...
499 if (!cups_raster_read_header(r
))
501 memset(h
, 0, sizeof(cups_page_header_t
));
506 * Copy the header to the user-supplied buffer...
509 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
516 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
517 * version 2 page header structure.
519 * @since CUPS 1.2/OS X 10.5@
522 unsigned /* O - 1 on success, 0 on failure/end-of-file */
523 cupsRasterReadHeader2(
524 cups_raster_t
*r
, /* I - Raster stream */
525 cups_page_header2_t
*h
) /* I - Pointer to header data */
528 * Get the raster header...
531 DEBUG_printf(("cupsRasterReadHeader2(r=%p, h=%p)", (void *)r
, (void *)h
));
533 if (!cups_raster_read_header(r
))
535 memset(h
, 0, sizeof(cups_page_header2_t
));
540 * Copy the header to the user-supplied buffer...
543 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
550 * 'cupsRasterReadPixels()' - Read raster pixels.
552 * For best performance, filters should read one or more whole lines.
553 * The "cupsBytesPerLine" value from the page header can be used to allocate
554 * the line buffer and as the number of bytes to read.
557 unsigned /* O - Number of bytes read */
558 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
559 unsigned char *p
, /* I - Pointer to pixel buffer */
560 unsigned len
) /* I - Number of bytes to read */
562 ssize_t bytes
; /* Bytes read */
563 unsigned cupsBytesPerLine
; /* cupsBytesPerLine value */
564 unsigned remaining
; /* Bytes remaining */
565 unsigned char *ptr
, /* Pointer to read buffer */
566 byte
, /* Byte from file */
567 *temp
; /* Pointer into buffer */
568 unsigned count
; /* Repetition count */
571 DEBUG_printf(("cupsRasterReadPixels(r=%p, p=%p, len=%u)", (void *)r
, (void *)p
, len
));
573 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0 ||
574 r
->header
.cupsBytesPerLine
== 0)
576 DEBUG_puts("1cupsRasterReadPixels: Returning 0.");
580 DEBUG_printf(("1cupsRasterReadPixels: compressed=%d, remaining=%u", r
->compressed
, r
->remaining
));
585 * Read without compression...
588 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
590 if (cups_raster_io(r
, p
, len
) < (ssize_t
)len
)
592 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
597 * Swap bytes as needed...
601 (r
->header
.cupsBitsPerColor
== 16 ||
602 r
->header
.cupsBitsPerPixel
== 12 ||
603 r
->header
.cupsBitsPerPixel
== 16))
610 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len
));
616 * Read compressed data...
620 cupsBytesPerLine
= r
->header
.cupsBytesPerLine
;
622 while (remaining
> 0 && r
->remaining
> 0)
627 * Need to read a new row...
630 if (remaining
== cupsBytesPerLine
)
636 * Read using a modified PackBits compression...
639 if (!cups_raster_read(r
, &byte
, 1))
641 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
645 r
->count
= (unsigned)byte
+ 1;
651 bytes
= (ssize_t
)cupsBytesPerLine
;
656 * Get a new repeat count...
659 if (!cups_raster_read(r
, &byte
, 1))
661 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
668 * Copy N literal pixels...
671 count
= (unsigned)(257 - byte
) * r
->bpp
;
673 if (count
> (unsigned)bytes
)
674 count
= (unsigned)bytes
;
676 if (!cups_raster_read(r
, temp
, count
))
678 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
688 * Repeat the next N bytes...
691 count
= ((unsigned)byte
+ 1) * r
->bpp
;
692 if (count
> (unsigned)bytes
)
693 count
= (unsigned)bytes
;
700 if (!cups_raster_read(r
, temp
, r
->bpp
))
702 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
711 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
719 * Swap bytes as needed...
722 if ((r
->header
.cupsBitsPerColor
== 16 ||
723 r
->header
.cupsBitsPerPixel
== 12 ||
724 r
->header
.cupsBitsPerPixel
== 16) &&
726 cups_swap(ptr
, (size_t)bytes
);
732 if (remaining
>= cupsBytesPerLine
)
734 bytes
= (ssize_t
)cupsBytesPerLine
;
735 r
->pcurrent
= r
->pixels
;
741 bytes
= (ssize_t
)remaining
;
742 r
->pcurrent
= r
->pixels
+ bytes
;
746 * Copy data as needed...
750 memcpy(p
, ptr
, (size_t)bytes
);
755 * Copy fragment from buffer...
758 if ((unsigned)(bytes
= (int)(r
->pend
- r
->pcurrent
)) > remaining
)
759 bytes
= (ssize_t
)remaining
;
761 memcpy(p
, r
->pcurrent
, (size_t)bytes
);
762 r
->pcurrent
+= bytes
;
764 if (r
->pcurrent
>= r
->pend
)
766 r
->pcurrent
= r
->pixels
;
772 remaining
-= (unsigned)bytes
;
776 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len
));
783 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
786 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
791 unsigned /* O - 1 on success, 0 on failure */
792 cupsRasterWriteHeader(
793 cups_raster_t
*r
, /* I - Raster stream */
794 cups_page_header_t
*h
) /* I - Raster page header */
796 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
800 * Make a copy of the header, and compute the number of raster
801 * lines in the page image...
804 memset(&(r
->header
), 0, sizeof(r
->header
));
805 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
807 if (!cups_raster_update(r
))
811 * Write the raster header...
814 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
817 * PWG raster data is always network byte order with much of the page header
821 cups_page_header2_t fh
; /* File page header */
823 memset(&fh
, 0, sizeof(fh
));
825 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
827 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
828 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
829 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
830 /* PrintContentType */
832 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
833 fh
.Duplex
= htonl(r
->header
.Duplex
);
834 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
835 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
836 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
837 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
838 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
839 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
840 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
841 fh
.Jog
= htonl(r
->header
.Jog
);
842 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
843 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
844 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
845 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
846 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
847 fh
.Orientation
= htonl(r
->header
.Orientation
);
848 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
849 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
850 fh
.Tumble
= htonl(r
->header
.Tumble
);
851 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
852 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
853 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
854 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
855 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
856 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
857 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
858 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
859 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
861 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
862 /* CrossFeedTransform */
863 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
865 fh
.cupsInteger
[3] = htonl(r
->header
.cupsInteger
[3]);
867 fh
.cupsInteger
[4] = htonl(r
->header
.cupsInteger
[4]);
869 fh
.cupsInteger
[5] = htonl(r
->header
.cupsInteger
[5]);
871 fh
.cupsInteger
[6] = htonl(r
->header
.cupsInteger
[6]);
873 fh
.cupsInteger
[7] = htonl(r
->header
.cupsInteger
[7]);
875 fh
.cupsInteger
[8] = htonl(r
->header
.cupsInteger
[8]);
877 fh
.cupsInteger
[14] = htonl(r
->header
.cupsInteger
[14]);
878 /* VendorIdentifier */
879 fh
.cupsInteger
[15] = htonl(r
->header
.cupsInteger
[15]);
882 void *dst
= fh
.cupsReal
; /* Bypass bogus compiler warning */
883 void *src
= r
->header
.cupsReal
;
884 memcpy(dst
, src
, sizeof(fh
.cupsReal
) + sizeof(fh
.cupsString
));
887 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
888 sizeof(fh
.cupsRenderingIntent
));
889 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
890 sizeof(fh
.cupsPageSizeName
));
892 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
895 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
896 == sizeof(r
->header
));
901 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
902 * page header structure.
904 * The page header can be initialized using @link cupsRasterInterpretPPD@.
906 * @since CUPS 1.2/OS X 10.5@
909 unsigned /* O - 1 on success, 0 on failure */
910 cupsRasterWriteHeader2(
911 cups_raster_t
*r
, /* I - Raster stream */
912 cups_page_header2_t
*h
) /* I - Raster page header */
914 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
918 * Make a copy of the header, and compute the number of raster
919 * lines in the page image...
922 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
924 if (!cups_raster_update(r
))
928 * Write the raster header...
931 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
934 * PWG raster data is always network byte order with most of the page header
938 cups_page_header2_t fh
; /* File page header */
940 memset(&fh
, 0, sizeof(fh
));
941 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
942 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
943 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
944 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
945 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
946 sizeof(fh
.cupsRenderingIntent
));
947 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
948 sizeof(fh
.cupsPageSizeName
));
950 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
951 fh
.Duplex
= htonl(r
->header
.Duplex
);
952 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
953 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
954 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
955 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
956 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
957 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
958 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
959 fh
.Jog
= htonl(r
->header
.Jog
);
960 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
961 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
962 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
963 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
964 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
965 fh
.Orientation
= htonl(r
->header
.Orientation
);
966 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
967 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
968 fh
.Tumble
= htonl(r
->header
.Tumble
);
969 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
970 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
971 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
972 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
973 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
974 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
975 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
976 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
977 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
978 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
979 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
980 fh
.cupsInteger
[3] = htonl((unsigned)(r
->header
.cupsImagingBBox
[0] * r
->header
.HWResolution
[0] / 72.0));
981 fh
.cupsInteger
[4] = htonl((unsigned)(r
->header
.cupsImagingBBox
[1] * r
->header
.HWResolution
[1] / 72.0));
982 fh
.cupsInteger
[5] = htonl((unsigned)(r
->header
.cupsImagingBBox
[2] * r
->header
.HWResolution
[0] / 72.0));
983 fh
.cupsInteger
[6] = htonl((unsigned)(r
->header
.cupsImagingBBox
[3] * r
->header
.HWResolution
[1] / 72.0));
984 fh
.cupsInteger
[7] = htonl(0xffffff);
986 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
989 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
990 == sizeof(r
->header
));
995 * 'cupsRasterWritePixels()' - Write raster pixels.
997 * For best performance, filters should write one or more whole lines.
998 * The "cupsBytesPerLine" value from the page header can be used to allocate
999 * the line buffer and as the number of bytes to write.
1002 unsigned /* O - Number of bytes written */
1003 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
1004 unsigned char *p
, /* I - Bytes to write */
1005 unsigned len
)/* I - Number of bytes to write */
1007 ssize_t bytes
; /* Bytes read */
1008 unsigned remaining
; /* Bytes remaining */
1011 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u", (void *)r
, (void *)p
, len
, r
->remaining
));
1013 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
|| r
->remaining
== 0)
1019 * Without compression, just write the raster data raw unless the data needs
1023 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
1026 (r
->header
.cupsBitsPerColor
== 16 ||
1027 r
->header
.cupsBitsPerPixel
== 12 ||
1028 r
->header
.cupsBitsPerPixel
== 16))
1030 unsigned char *bufptr
; /* Pointer into write buffer */
1031 unsigned count
; /* Remaining count */
1034 * Allocate a write buffer as needed...
1037 if ((size_t)len
> r
->bufsize
)
1040 bufptr
= realloc(r
->buffer
, len
);
1042 bufptr
= malloc(len
);
1052 * Byte swap the pixels...
1055 for (bufptr
= r
->buffer
, count
= len
; count
> 1; count
-= 2, bufptr
+= 2)
1061 if (count
) /* This should never happen... */
1065 * Write the byte-swapped buffer...
1068 bytes
= cups_raster_io(r
, r
->buffer
, len
);
1071 bytes
= cups_raster_io(r
, p
, len
);
1080 * Otherwise, compress each line...
1083 for (remaining
= len
; remaining
> 0; remaining
-= (unsigned)bytes
, p
+= bytes
)
1086 * Figure out the number of remaining bytes on the current line...
1089 if ((bytes
= (ssize_t
)remaining
) > (ssize_t
)(r
->pend
- r
->pcurrent
))
1090 bytes
= (ssize_t
)(r
->pend
- r
->pcurrent
);
1095 * Check to see if this line is the same as the previous line...
1098 if (memcmp(p
, r
->pcurrent
, (size_t)bytes
))
1100 if (cups_raster_write(r
, r
->pixels
) <= 0)
1108 * Mark more bytes as the same...
1111 r
->pcurrent
+= bytes
;
1113 if (r
->pcurrent
>= r
->pend
)
1116 * Increase the repeat count...
1120 r
->pcurrent
= r
->pixels
;
1123 * Flush out this line if it is the last one...
1128 if (r
->remaining
== 0)
1130 if (cups_raster_write(r
, r
->pixels
) <= 0)
1135 else if (r
->count
== 256)
1137 if (cups_raster_write(r
, r
->pixels
) <= 0)
1151 * Copy the raster data to the buffer...
1154 memcpy(r
->pcurrent
, p
, (size_t)bytes
);
1156 r
->pcurrent
+= bytes
;
1158 if (r
->pcurrent
>= r
->pend
)
1161 * Increase the repeat count...
1165 r
->pcurrent
= r
->pixels
;
1168 * Flush out this line if it is the last one...
1173 if (r
->remaining
== 0)
1175 if (cups_raster_write(r
, r
->pixels
) <= 0)
1187 * 'cups_raster_read_header()' - Read a raster page header.
1190 static unsigned /* O - 1 on success, 0 on fail */
1191 cups_raster_read_header(
1192 cups_raster_t
*r
) /* I - Raster stream */
1194 size_t len
; /* Length for read/swap */
1197 DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%d", (void *)r
, r
? r
->mode
: 0));
1199 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
1202 DEBUG_printf(("4cups_raster_read_header: r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1205 * Get the length of the raster header...
1208 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
1209 len
= sizeof(cups_page_header_t
);
1211 len
= sizeof(cups_page_header2_t
);
1213 DEBUG_printf(("4cups_raster_read_header: len=%d", (int)len
));
1216 * Read the header...
1219 memset(&(r
->header
), 0, sizeof(r
->header
));
1221 if (cups_raster_read(r
, (unsigned char *)&(r
->header
), len
) < (ssize_t
)len
)
1223 DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1228 * Swap bytes as needed...
1233 unsigned *s
, /* Current word */
1234 temp
; /* Temporary copy */
1237 DEBUG_puts("4cups_raster_read_header: Swapping header bytes.");
1239 for (len
= 81, s
= &(r
->header
.AdvanceDistance
);
1244 *s
= ((temp
& 0xff) << 24) |
1245 ((temp
& 0xff00) << 8) |
1246 ((temp
& 0xff0000) >> 8) |
1247 ((temp
& 0xff000000) >> 24);
1249 DEBUG_printf(("4cups_raster_read_header: %08x => %08x", temp
, *s
));
1254 * Update the header and row count...
1257 if (!cups_raster_update(r
))
1260 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
));
1262 return (r
->header
.cupsBitsPerPixel
> 0 && r
->header
.cupsBitsPerPixel
<= 240 && r
->header
.cupsBitsPerColor
> 0 && r
->header
.cupsBitsPerColor
<= 16 && r
->header
.cupsBytesPerLine
> 0 && r
->header
.cupsBytesPerLine
<= 0x7fffffff && r
->header
.cupsHeight
!= 0 && (r
->header
.cupsBytesPerLine
% r
->bpp
) == 0);
1267 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
1270 static ssize_t
/* O - Bytes read/write or -1 */
1271 cups_raster_io(cups_raster_t
*r
, /* I - Raster stream */
1272 unsigned char *buf
, /* I - Buffer for read/write */
1273 size_t bytes
) /* I - Number of bytes to read/write */
1275 ssize_t count
, /* Number of bytes read/written */
1276 total
; /* Total bytes read/written */
1279 DEBUG_printf(("5cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT
")", (void *)r
, (void *)buf
, CUPS_LLCAST bytes
));
1281 for (total
= 0; total
< (ssize_t
)bytes
; total
+= count
, buf
+= count
)
1283 count
= (*r
->iocb
)(r
->ctx
, buf
, bytes
- (size_t)total
);
1285 DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count
, (int)total
));
1288 DEBUG_puts("6cups_raster_io: Returning 0.");
1293 DEBUG_puts("6cups_raster_io: Returning -1 on error.");
1298 r
->iocount
+= (size_t)count
;
1302 DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT
".", CUPS_LLCAST total
));
1309 * 'cups_raster_read()' - Read through the raster buffer.
1312 static ssize_t
/* O - Number of bytes read */
1313 cups_raster_read(cups_raster_t
*r
, /* I - Raster stream */
1314 unsigned char *buf
, /* I - Buffer */
1315 size_t bytes
) /* I - Number of bytes to read */
1317 ssize_t count
, /* Number of bytes read */
1318 remaining
, /* Remaining bytes in buffer */
1319 total
; /* Total bytes read */
1322 DEBUG_printf(("5cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT
")", (void *)r
, (void *)buf
, CUPS_LLCAST bytes
));
1325 return (cups_raster_io(r
, buf
, bytes
));
1328 * Allocate a read buffer as needed...
1331 count
= (ssize_t
)(2 * r
->header
.cupsBytesPerLine
);
1335 if ((size_t)count
> r
->bufsize
)
1337 ssize_t offset
= r
->bufptr
- r
->buffer
;
1338 /* Offset to current start of buffer */
1339 ssize_t end
= r
->bufend
- r
->buffer
;/* Offset to current end of buffer */
1340 unsigned char *rptr
; /* Pointer in read buffer */
1343 rptr
= realloc(r
->buffer
, (size_t)count
);
1345 rptr
= malloc((size_t)count
);
1351 r
->bufptr
= rptr
+ offset
;
1352 r
->bufend
= rptr
+ end
;
1353 r
->bufsize
= (size_t)count
;
1357 * Loop until we have read everything...
1360 for (total
= 0, remaining
= (int)(r
->bufend
- r
->bufptr
);
1361 total
< (ssize_t
)bytes
;
1362 total
+= count
, buf
+= count
)
1364 count
= (ssize_t
)bytes
- total
;
1366 DEBUG_printf(("6cups_raster_read: count=" CUPS_LLFMT
", remaining=" CUPS_LLFMT
", buf=%p, bufptr=%p, bufend=%p", CUPS_LLCAST count
, CUPS_LLCAST remaining
, (void *)buf
, (void *)r
->bufptr
, (void *)r
->bufend
));
1373 * Read into the raster buffer and then copy...
1376 remaining
= (*r
->iocb
)(r
->ctx
, r
->buffer
, r
->bufsize
);
1380 r
->bufptr
= r
->buffer
;
1381 r
->bufend
= r
->buffer
+ remaining
;
1384 r
->iocount
+= (size_t)remaining
;
1390 * Read directly into "buf"...
1393 count
= (*r
->iocb
)(r
->ctx
, buf
, (size_t)count
);
1399 r
->iocount
+= (size_t)count
;
1407 * Copy bytes from raster buffer to "buf"...
1410 if (count
> remaining
)
1419 *buf
= *(r
->bufptr
)++;
1422 else if (count
< 128)
1425 * Copy up to 127 bytes without using memcpy(); this is
1426 * faster because it avoids an extra function call and is
1427 * often further optimized by the compiler...
1430 unsigned char *bufptr
; /* Temporary buffer pointer */
1434 for (bufptr
= r
->bufptr
; count
> 0; count
--, total
++)
1442 * Use memcpy() for a large read...
1445 memcpy(buf
, r
->bufptr
, (size_t)count
);
1451 DEBUG_printf(("6cups_raster_read: Returning %ld", (long)total
));
1458 * 'cups_raster_update()' - Update the raster header and row count for the
1462 static int /* O - 1 on success, 0 on failure */
1463 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
1465 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
1466 r
->header
.cupsNumColors
== 0)
1469 * Set the "cupsNumColors" field according to the colorspace...
1472 switch (r
->header
.cupsColorSpace
)
1474 case CUPS_CSPACE_W
:
1475 case CUPS_CSPACE_K
:
1476 case CUPS_CSPACE_WHITE
:
1477 case CUPS_CSPACE_GOLD
:
1478 case CUPS_CSPACE_SILVER
:
1479 case CUPS_CSPACE_SW
:
1480 r
->header
.cupsNumColors
= 1;
1483 case CUPS_CSPACE_RGB
:
1484 case CUPS_CSPACE_CMY
:
1485 case CUPS_CSPACE_YMC
:
1486 case CUPS_CSPACE_CIEXYZ
:
1487 case CUPS_CSPACE_CIELab
:
1488 case CUPS_CSPACE_SRGB
:
1489 case CUPS_CSPACE_ADOBERGB
:
1490 case CUPS_CSPACE_ICC1
:
1491 case CUPS_CSPACE_ICC2
:
1492 case CUPS_CSPACE_ICC3
:
1493 case CUPS_CSPACE_ICC4
:
1494 case CUPS_CSPACE_ICC5
:
1495 case CUPS_CSPACE_ICC6
:
1496 case CUPS_CSPACE_ICC7
:
1497 case CUPS_CSPACE_ICC8
:
1498 case CUPS_CSPACE_ICC9
:
1499 case CUPS_CSPACE_ICCA
:
1500 case CUPS_CSPACE_ICCB
:
1501 case CUPS_CSPACE_ICCC
:
1502 case CUPS_CSPACE_ICCD
:
1503 case CUPS_CSPACE_ICCE
:
1504 case CUPS_CSPACE_ICCF
:
1505 r
->header
.cupsNumColors
= 3;
1508 case CUPS_CSPACE_RGBA
:
1509 case CUPS_CSPACE_RGBW
:
1510 case CUPS_CSPACE_CMYK
:
1511 case CUPS_CSPACE_YMCK
:
1512 case CUPS_CSPACE_KCMY
:
1513 case CUPS_CSPACE_GMCK
:
1514 case CUPS_CSPACE_GMCS
:
1515 r
->header
.cupsNumColors
= 4;
1518 case CUPS_CSPACE_KCMYcm
:
1519 if (r
->header
.cupsBitsPerPixel
< 8)
1520 r
->header
.cupsNumColors
= 6;
1522 r
->header
.cupsNumColors
= 4;
1525 case CUPS_CSPACE_DEVICE1
:
1526 case CUPS_CSPACE_DEVICE2
:
1527 case CUPS_CSPACE_DEVICE3
:
1528 case CUPS_CSPACE_DEVICE4
:
1529 case CUPS_CSPACE_DEVICE5
:
1530 case CUPS_CSPACE_DEVICE6
:
1531 case CUPS_CSPACE_DEVICE7
:
1532 case CUPS_CSPACE_DEVICE8
:
1533 case CUPS_CSPACE_DEVICE9
:
1534 case CUPS_CSPACE_DEVICEA
:
1535 case CUPS_CSPACE_DEVICEB
:
1536 case CUPS_CSPACE_DEVICEC
:
1537 case CUPS_CSPACE_DEVICED
:
1538 case CUPS_CSPACE_DEVICEE
:
1539 case CUPS_CSPACE_DEVICEF
:
1540 r
->header
.cupsNumColors
= r
->header
.cupsColorSpace
-
1541 CUPS_CSPACE_DEVICE1
+ 1;
1545 /* Unknown color space */
1551 * Set the number of bytes per pixel/color...
1554 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
1555 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
1557 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
1563 * Set the number of remaining rows...
1566 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
1567 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
1569 r
->remaining
= r
->header
.cupsHeight
;
1572 * Allocate the compression buffer...
1577 if (r
->pixels
!= NULL
)
1580 if ((r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1)) == NULL
)
1589 r
->pcurrent
= r
->pixels
;
1590 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
1599 * 'cups_raster_write()' - Write a row of compressed raster data...
1602 static ssize_t
/* O - Number of bytes written */
1604 cups_raster_t
*r
, /* I - Raster stream */
1605 const unsigned char *pixels
) /* I - Pixel data to write */
1607 const unsigned char *start
, /* Start of sequence */
1608 *ptr
, /* Current pointer in sequence */
1609 *pend
, /* End of raster buffer */
1610 *plast
; /* Pointer to last pixel */
1611 unsigned char *wptr
; /* Pointer into write buffer */
1612 unsigned bpp
, /* Bytes per pixel */
1616 DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)", (void *)r
, (void *)pixels
));
1619 * Allocate a write buffer as needed...
1622 count
= r
->header
.cupsBytesPerLine
* 2;
1626 if ((size_t)count
> r
->bufsize
)
1629 wptr
= realloc(r
->buffer
, count
);
1631 wptr
= malloc(count
);
1635 DEBUG_printf(("4cups_raster_write: Unable to allocate " CUPS_LLFMT
" bytes for raster buffer: %s", CUPS_LLCAST count
, strerror(errno
)));
1644 * Write the row repeat count...
1648 pend
= pixels
+ r
->header
.cupsBytesPerLine
;
1651 *wptr
++ = (unsigned char)(r
->count
- 1);
1654 * Write using a modified PackBits compression...
1657 for (ptr
= pixels
; ptr
< pend
;)
1665 * Encode a single pixel at the end...
1669 for (count
= bpp
; count
> 0; count
--)
1672 else if (!memcmp(start
, ptr
, bpp
))
1675 * Encode a sequence of repeating pixels...
1678 for (count
= 2; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1679 if (memcmp(ptr
, ptr
+ bpp
, bpp
))
1682 *wptr
++ = (unsigned char)(count
- 1);
1683 for (count
= bpp
; count
> 0; count
--)
1689 * Encode a sequence of non-repeating pixels...
1692 for (count
= 1; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1693 if (!memcmp(ptr
, ptr
+ bpp
, bpp
))
1696 if (ptr
>= plast
&& count
< 128)
1702 *wptr
++ = (unsigned char)(257 - count
);
1705 memcpy(wptr
, start
, count
);
1710 DEBUG_printf(("4cups_raster_write: Writing " CUPS_LLFMT
" bytes.", CUPS_LLCAST (wptr
- r
->buffer
)));
1712 return (cups_raster_io(r
, r
->buffer
, (size_t)(wptr
- r
->buffer
)));
1717 * 'cups_read_fd()' - Read bytes from a file.
1720 static ssize_t
/* O - Bytes read or -1 */
1721 cups_read_fd(void *ctx
, /* I - File descriptor as pointer */
1722 unsigned char *buf
, /* I - Buffer for read */
1723 size_t bytes
) /* I - Maximum number of bytes to read */
1725 int fd
= (int)((intptr_t)ctx
);
1726 /* File descriptor */
1727 ssize_t count
; /* Number of bytes read */
1730 #ifdef WIN32 /* Sigh */
1731 while ((count
= read(fd
, buf
, (unsigned)bytes
)) < 0)
1733 while ((count
= read(fd
, buf
, bytes
)) < 0)
1735 if (errno
!= EINTR
&& errno
!= EAGAIN
)
1737 DEBUG_printf(("4cups_read_fd: %s", strerror(errno
)));
1741 DEBUG_printf(("4cups_read_fd: Returning %d bytes.", (int)count
));
1748 * 'cups_swap()' - Swap bytes in raster data...
1752 cups_swap(unsigned char *buf
, /* I - Buffer to swap */
1753 size_t bytes
) /* I - Number of bytes to swap */
1755 unsigned char even
, odd
; /* Temporary variables */
1774 * 'cups_write_fd()' - Write bytes to a file.
1777 static ssize_t
/* O - Bytes written or -1 */
1778 cups_write_fd(void *ctx
, /* I - File descriptor pointer */
1779 unsigned char *buf
, /* I - Bytes to write */
1780 size_t bytes
) /* I - Number of bytes to write */
1782 int fd
= (int)((intptr_t)ctx
);
1783 /* File descriptor */
1784 ssize_t count
; /* Number of bytes written */
1787 #ifdef WIN32 /* Sigh */
1788 while ((count
= write(fd
, buf
, (unsigned)bytes
)) < 0)
1790 while ((count
= write(fd
, buf
, bytes
)) < 0)
1792 if (errno
!= EINTR
&& errno
!= EAGAIN
)
1794 DEBUG_printf(("4cups_write_fd: %s", strerror(errno
)));