2 * Raster file routines for CUPS.
4 * Copyright 2007-2018 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products.
7 * This file is part of the CUPS Imaging library.
9 * Licensed under Apache License v2.0. See the file "LICENSE" for more
14 * Include necessary headers...
17 #include <cups/raster-private.h>
20 #endif /* HAVE_STDINT_H */
24 * Private structures...
27 struct _cups_raster_s
/**** Raster stream data ****/
29 unsigned sync
; /* Sync word from start of stream */
30 void *ctx
; /* File descriptor */
31 cups_raster_iocb_t iocb
; /* IO callback */
32 cups_mode_t mode
; /* Read/write mode */
33 cups_page_header2_t header
; /* Raster header for current page */
34 unsigned rowheight
, /* Row height in lines */
35 count
, /* Current row run-length count */
36 remaining
, /* Remaining rows in page image */
37 bpp
; /* Bytes per pixel/color */
38 unsigned char *pixels
, /* Pixels for current row */
39 *pend
, /* End of pixel buffer */
40 *pcurrent
; /* Current byte in pixel buffer */
41 int compressed
, /* Non-zero if data is compressed */
42 swapped
; /* Non-zero if data is byte-swapped */
43 unsigned char *buffer
, /* Read/write buffer */
44 *bufptr
, /* Current (read) position in buffer */
45 *bufend
; /* End of current (read) buffer */
46 size_t bufsize
; /* Buffer size */
48 size_t iostart
, /* Start of read/write buffer */
49 iocount
; /* Number of bytes read/written */
51 unsigned apple_page_count
;/* Apple raster page count */
54 typedef void (*_cups_copyfunc_t
)(void *dst
, const void *src
, size_t bytes
);
62 static const char * const cups_color_spaces
[] =
84 "CUPS_CSPACE_ADOBERGB",
112 "CUPS_CSPACE_DEVICE1",
113 "CUPS_CSPACE_DEVICE2",
114 "CUPS_CSPACE_DEVICE3",
115 "CUPS_CSPACE_DEVICE4",
116 "CUPS_CSPACE_DEVICE5",
117 "CUPS_CSPACE_DEVICE6",
118 "CUPS_CSPACE_DEVICE7",
119 "CUPS_CSPACE_DEVICE8",
120 "CUPS_CSPACE_DEVICE9",
121 "CUPS_CSPACE_DEVICEA",
122 "CUPS_CSPACE_DEVICEB",
123 "CUPS_CSPACE_DEVICEC",
124 "CUPS_CSPACE_DEVICED",
125 "CUPS_CSPACE_DEVICEE",
126 "CUPS_CSPACE_DEVICEF"
128 static const char * const cups_modes
[] =
132 "CUPS_RASTER_WRITE_COMPRESSED",
133 "CUPS_RASTER_WRITE_PWG",
134 "CUPS_RASTER_WRITE_APPLE"
143 static ssize_t
cups_raster_io(cups_raster_t
*r
, unsigned char *buf
, size_t bytes
);
144 static unsigned cups_raster_read_header(cups_raster_t
*r
);
145 static ssize_t
cups_raster_read(cups_raster_t
*r
, unsigned char *buf
, size_t bytes
);
146 static int cups_raster_update(cups_raster_t
*r
);
147 static ssize_t
cups_raster_write(cups_raster_t
*r
, const unsigned char *pixels
);
148 static ssize_t
cups_read_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
149 static void cups_swap(unsigned char *buf
, size_t bytes
);
150 static void cups_swap_copy(unsigned char *dst
, const unsigned char *src
, size_t bytes
);
151 static ssize_t
cups_write_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
155 * 'cupsRasterClose()' - Close a raster stream.
157 * The file descriptor associated with the raster stream must be closed
158 * separately as needed.
162 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
178 * 'cupsRasterInitPWGHeader()' - Initialize a page header for PWG Raster output.
180 * The "media" argument specifies the media to use.
182 * The "type" argument specifies a "pwg-raster-document-type-supported" value
183 * that controls the color space and bit depth of the raster data.
185 * The "xres" and "yres" arguments specify the raster resolution in dots per
188 * The "sheet_back" argument specifies a "pwg-raster-document-sheet-back" value
189 * to apply for the back side of a page. Pass @code NULL@ for the front side.
191 * @since CUPS 2.2/macOS 10.12@
194 int /* O - 1 on success, 0 on failure */
195 cupsRasterInitPWGHeader(
196 cups_page_header2_t
*h
, /* I - Page header */
197 pwg_media_t
*media
, /* I - PWG media information */
198 const char *type
, /* I - PWG raster type string */
199 int xdpi
, /* I - Cross-feed direction (horizontal) resolution */
200 int ydpi
, /* I - Feed direction (vertical) resolution */
201 const char *sides
, /* I - IPP "sides" option value */
202 const char *sheet_back
) /* I - Transform for back side or @code NULL@ for none */
204 if (!h
|| !media
|| !type
|| xdpi
<= 0 || ydpi
<= 0)
206 _cupsRasterAddError("%s", strerror(EINVAL
));
211 * Initialize the page header...
214 memset(h
, 0, sizeof(cups_page_header2_t
));
216 strlcpy(h
->cupsPageSizeName
, media
->pwg
, sizeof(h
->cupsPageSizeName
));
218 h
->PageSize
[0] = (unsigned)(72 * media
->width
/ 2540);
219 h
->PageSize
[1] = (unsigned)(72 * media
->length
/ 2540);
221 /* This never gets written but is needed for some applications */
222 h
->cupsPageSize
[0] = 72.0f
* media
->width
/ 2540.0f
;
223 h
->cupsPageSize
[1] = 72.0f
* media
->length
/ 2540.0f
;
225 h
->ImagingBoundingBox
[2] = h
->PageSize
[0];
226 h
->ImagingBoundingBox
[3] = h
->PageSize
[1];
228 h
->HWResolution
[0] = (unsigned)xdpi
;
229 h
->HWResolution
[1] = (unsigned)ydpi
;
231 h
->cupsWidth
= (unsigned)(media
->width
* xdpi
/ 2540);
232 h
->cupsHeight
= (unsigned)(media
->length
* ydpi
/ 2540);
234 if (h
->cupsWidth
> 0x00ffffff || h
->cupsHeight
> 0x00ffffff)
236 _cupsRasterAddError("Raster dimensions too large.");
240 h
->cupsInteger
[CUPS_RASTER_PWG_ImageBoxRight
] = h
->cupsWidth
;
241 h
->cupsInteger
[CUPS_RASTER_PWG_ImageBoxBottom
] = h
->cupsHeight
;
244 * Colorspace and bytes per line...
247 if (!strcmp(type
, "adobe-rgb_8"))
249 h
->cupsBitsPerColor
= 8;
250 h
->cupsBitsPerPixel
= 24;
251 h
->cupsColorSpace
= CUPS_CSPACE_ADOBERGB
;
253 else if (!strcmp(type
, "adobe-rgb_16"))
255 h
->cupsBitsPerColor
= 16;
256 h
->cupsBitsPerPixel
= 48;
257 h
->cupsColorSpace
= CUPS_CSPACE_ADOBERGB
;
259 else if (!strcmp(type
, "black_1"))
261 h
->cupsBitsPerColor
= 1;
262 h
->cupsBitsPerPixel
= 1;
263 h
->cupsColorSpace
= CUPS_CSPACE_K
;
265 else if (!strcmp(type
, "black_8"))
267 h
->cupsBitsPerColor
= 8;
268 h
->cupsBitsPerPixel
= 8;
269 h
->cupsColorSpace
= CUPS_CSPACE_K
;
271 else if (!strcmp(type
, "black_16"))
273 h
->cupsBitsPerColor
= 16;
274 h
->cupsBitsPerPixel
= 16;
275 h
->cupsColorSpace
= CUPS_CSPACE_K
;
277 else if (!strcmp(type
, "cmyk_8"))
279 h
->cupsBitsPerColor
= 8;
280 h
->cupsBitsPerPixel
= 32;
281 h
->cupsColorSpace
= CUPS_CSPACE_CMYK
;
283 else if (!strcmp(type
, "cmyk_16"))
285 h
->cupsBitsPerColor
= 16;
286 h
->cupsBitsPerPixel
= 64;
287 h
->cupsColorSpace
= CUPS_CSPACE_CMYK
;
289 else if (!strncmp(type
, "device", 6) && type
[6] >= '1' && type
[6] <= '9')
291 int ncolors
, bits
; /* Number of colors and bits */
294 if (sscanf(type
, "device%d_%d", &ncolors
, &bits
) != 2 || ncolors
> 15 || (bits
!= 8 && bits
!= 16))
296 _cupsRasterAddError("Unsupported raster type \'%s\'.", type
);
300 h
->cupsBitsPerColor
= (unsigned)bits
;
301 h
->cupsBitsPerPixel
= (unsigned)(ncolors
* bits
);
302 h
->cupsColorSpace
= (cups_cspace_t
)(CUPS_CSPACE_DEVICE1
+ ncolors
- 1);
304 else if (!strcmp(type
, "rgb_8"))
306 h
->cupsBitsPerColor
= 8;
307 h
->cupsBitsPerPixel
= 24;
308 h
->cupsColorSpace
= CUPS_CSPACE_RGB
;
310 else if (!strcmp(type
, "rgb_16"))
312 h
->cupsBitsPerColor
= 16;
313 h
->cupsBitsPerPixel
= 48;
314 h
->cupsColorSpace
= CUPS_CSPACE_RGB
;
316 else if (!strcmp(type
, "sgray_1"))
318 h
->cupsBitsPerColor
= 1;
319 h
->cupsBitsPerPixel
= 1;
320 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
322 else if (!strcmp(type
, "sgray_8"))
324 h
->cupsBitsPerColor
= 8;
325 h
->cupsBitsPerPixel
= 8;
326 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
328 else if (!strcmp(type
, "sgray_16"))
330 h
->cupsBitsPerColor
= 16;
331 h
->cupsBitsPerPixel
= 16;
332 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
334 else if (!strcmp(type
, "srgb_8"))
336 h
->cupsBitsPerColor
= 8;
337 h
->cupsBitsPerPixel
= 24;
338 h
->cupsColorSpace
= CUPS_CSPACE_SRGB
;
340 else if (!strcmp(type
, "srgb_16"))
342 h
->cupsBitsPerColor
= 16;
343 h
->cupsBitsPerPixel
= 48;
344 h
->cupsColorSpace
= CUPS_CSPACE_SRGB
;
348 _cupsRasterAddError("Unsupported raster type \'%s\'.", type
);
352 h
->cupsColorOrder
= CUPS_ORDER_CHUNKED
;
353 h
->cupsNumColors
= h
->cupsBitsPerPixel
/ h
->cupsBitsPerColor
;
354 h
->cupsBytesPerLine
= (h
->cupsWidth
* h
->cupsBitsPerPixel
+ 7) / 8;
360 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 1;
361 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 1;
365 if (!strcmp(sides
, "two-sided-long-edge"))
369 else if (!strcmp(sides
, "two-sided-short-edge"))
374 else if (strcmp(sides
, "one-sided"))
376 _cupsRasterAddError("Unsupported sides value \'%s\'.", sides
);
382 if (!strcmp(sheet_back
, "flipped"))
385 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
387 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
389 else if (!strcmp(sheet_back
, "manual-tumble"))
393 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
394 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
397 else if (!strcmp(sheet_back
, "rotated"))
401 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
402 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
405 else if (strcmp(sheet_back
, "normal"))
407 _cupsRasterAddError("Unsupported sheet_back value \'%s\'.", sheet_back
);
418 * 'cupsRasterOpen()' - Open a raster stream using a file descriptor.
420 * This function associates a raster stream with the given file descriptor.
421 * For most printer driver filters, "fd" will be 0 (stdin). For most raster
422 * image processor (RIP) filters that generate raster data, "fd" will be 1
425 * When writing raster data, the @code CUPS_RASTER_WRITE@,
426 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
427 * be used - compressed and PWG output is generally 25-50% smaller but adds a
428 * 100-300% execution time overhead.
431 cups_raster_t
* /* O - New stream */
432 cupsRasterOpen(int fd
, /* I - File descriptor */
433 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
434 @code CUPS_RASTER_WRITE@,
435 @code CUPS_RASTER_WRITE_COMPRESSED@,
436 or @code CUPS_RASTER_WRITE_PWG@ */
438 DEBUG_printf(("cupsRasterOpen(fd=%d, mode=%s)", fd
, cups_modes
[mode
]));
440 if (mode
== CUPS_RASTER_READ
)
441 return (cupsRasterOpenIO(cups_read_fd
, (void *)((intptr_t)fd
), mode
));
443 return (cupsRasterOpenIO(cups_write_fd
, (void *)((intptr_t)fd
), mode
));
448 * 'cupsRasterOpenIO()' - Open a raster stream using a callback function.
450 * This function associates a raster stream with the given callback function and
453 * When writing raster data, the @code CUPS_RASTER_WRITE@,
454 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
455 * be used - compressed and PWG output is generally 25-50% smaller but adds a
456 * 100-300% execution time overhead.
459 cups_raster_t
* /* O - New stream */
461 cups_raster_iocb_t iocb
, /* I - Read/write callback */
462 void *ctx
, /* I - Context pointer for callback */
463 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
464 @code CUPS_RASTER_WRITE@,
465 @code CUPS_RASTER_WRITE_COMPRESSED@,
466 or @code CUPS_RASTER_WRITE_PWG@ */
468 cups_raster_t
*r
; /* New stream */
471 DEBUG_printf(("cupsRasterOpenIO(iocb=%p, ctx=%p, mode=%s)", (void *)iocb
, ctx
, cups_modes
[mode
]));
473 _cupsRasterClearError();
475 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
477 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
479 DEBUG_puts("1cupsRasterOpenIO: Returning NULL.");
487 if (mode
== CUPS_RASTER_READ
)
490 * Open for read - get sync word...
493 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) !=
496 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
499 DEBUG_puts("1cupsRasterOpenIO: Unable to read header, returning NULL.");
503 if (r
->sync
!= CUPS_RASTER_SYNC
&&
504 r
->sync
!= CUPS_RASTER_REVSYNC
&&
505 r
->sync
!= CUPS_RASTER_SYNCv1
&&
506 r
->sync
!= CUPS_RASTER_REVSYNCv1
&&
507 r
->sync
!= CUPS_RASTER_SYNCv2
&&
508 r
->sync
!= CUPS_RASTER_REVSYNCv2
&&
509 r
->sync
!= CUPS_RASTER_SYNCapple
&&
510 r
->sync
!= CUPS_RASTER_REVSYNCapple
)
512 _cupsRasterAddError("Unknown raster format %08x!\n", r
->sync
);
514 DEBUG_puts("1cupsRasterOpenIO: Unknown format, returning NULL.");
518 if (r
->sync
== CUPS_RASTER_SYNCv2
||
519 r
->sync
== CUPS_RASTER_REVSYNCv2
||
520 r
->sync
== CUPS_RASTER_SYNCapple
||
521 r
->sync
== CUPS_RASTER_REVSYNCapple
)
524 DEBUG_printf(("1cupsRasterOpenIO: sync=%08x", r
->sync
));
526 if (r
->sync
== CUPS_RASTER_REVSYNC
||
527 r
->sync
== CUPS_RASTER_REVSYNCv1
||
528 r
->sync
== CUPS_RASTER_REVSYNCv2
||
529 r
->sync
== CUPS_RASTER_REVSYNCapple
)
532 if (r
->sync
== CUPS_RASTER_SYNCapple
||
533 r
->sync
== CUPS_RASTER_REVSYNCapple
)
535 unsigned char header
[8]; /* File header */
537 if (cups_raster_io(r
, (unsigned char *)header
, sizeof(header
)) !=
540 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
543 DEBUG_puts("1cupsRasterOpenIO: Unable to read header, returning NULL.");
549 r
->iostart
= r
->iocount
;
555 * Open for write - put sync word...
561 case CUPS_RASTER_WRITE
:
562 r
->sync
= CUPS_RASTER_SYNC
;
565 case CUPS_RASTER_WRITE_COMPRESSED
:
567 r
->sync
= CUPS_RASTER_SYNCv2
;
570 case CUPS_RASTER_WRITE_PWG
:
572 r
->sync
= htonl(CUPS_RASTER_SYNC_PWG
);
573 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNC_PWG
;
576 case CUPS_RASTER_WRITE_APPLE
:
578 r
->sync
= htonl(CUPS_RASTER_SYNCapple
);
579 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNCapple
;
580 r
->apple_page_count
= 0xffffffffU
;
584 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) < (ssize_t
)sizeof(r
->sync
))
586 _cupsRasterAddError("Unable to write raster stream header: %s\n",
589 DEBUG_puts("1cupsRasterOpenIO: Unable to write header, returning NULL.");
594 DEBUG_printf(("1cupsRasterOpenIO: compressed=%d, swapped=%d, returning %p", r
->compressed
, r
->swapped
, (void *)r
));
601 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
602 * version 1 page header structure.
604 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
606 * Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset
607 * of the version 2 page header data. This function handles reading version 2
608 * page headers and copying only the version 1 data into the provided buffer.
613 unsigned /* O - 1 on success, 0 on failure/end-of-file */
614 cupsRasterReadHeader(
615 cups_raster_t
*r
, /* I - Raster stream */
616 cups_page_header_t
*h
) /* I - Pointer to header data */
618 DEBUG_printf(("cupsRasterReadHeader(r=%p, h=%p)", (void *)r
, (void *)h
));
621 * Get the raster header...
624 if (!cups_raster_read_header(r
))
626 memset(h
, 0, sizeof(cups_page_header_t
));
627 DEBUG_puts("1cupsRasterReadHeader: Unable to read page header, returning 0.");
632 * Copy the header to the user-supplied buffer...
635 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
637 DEBUG_printf(("1cupsRasterReadHeader: cupsColorSpace=%s", cups_color_spaces
[h
->cupsColorSpace
]));
638 DEBUG_printf(("1cupsRasterReadHeader: cupsBitsPerColor=%u", h
->cupsBitsPerColor
));
639 DEBUG_printf(("1cupsRasterReadHeader: cupsBitsPerPixel=%u", h
->cupsBitsPerPixel
));
640 DEBUG_printf(("1cupsRasterReadHeader: cupsBytesPerLine=%u", h
->cupsBytesPerLine
));
641 DEBUG_printf(("1cupsRasterReadHeader: cupsWidth=%u", h
->cupsWidth
));
642 DEBUG_printf(("1cupsRasterReadHeader: cupsHeight=%u", h
->cupsHeight
));
644 DEBUG_puts("1cupsRasterReadHeader: Returning 1.");
650 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
651 * version 2 page header structure.
653 * @since CUPS 1.2/macOS 10.5@
656 unsigned /* O - 1 on success, 0 on failure/end-of-file */
657 cupsRasterReadHeader2(
658 cups_raster_t
*r
, /* I - Raster stream */
659 cups_page_header2_t
*h
) /* I - Pointer to header data */
662 * Get the raster header...
665 DEBUG_printf(("cupsRasterReadHeader2(r=%p, h=%p)", (void *)r
, (void *)h
));
667 if (!cups_raster_read_header(r
))
669 memset(h
, 0, sizeof(cups_page_header2_t
));
670 DEBUG_puts("1cupsRasterReadHeader2: Unable to read header, returning 0.");
675 * Copy the header to the user-supplied buffer...
678 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
680 DEBUG_printf(("1cupsRasterReadHeader2: cupsColorSpace=%s", cups_color_spaces
[h
->cupsColorSpace
]));
681 DEBUG_printf(("1cupsRasterReadHeader2: cupsBitsPerColor=%u", h
->cupsBitsPerColor
));
682 DEBUG_printf(("1cupsRasterReadHeader2: cupsBitsPerPixel=%u", h
->cupsBitsPerPixel
));
683 DEBUG_printf(("1cupsRasterReadHeader2: cupsBytesPerLine=%u", h
->cupsBytesPerLine
));
684 DEBUG_printf(("1cupsRasterReadHeader2: cupsWidth=%u", h
->cupsWidth
));
685 DEBUG_printf(("1cupsRasterReadHeader2: cupsHeight=%u", h
->cupsHeight
));
687 DEBUG_puts("1cupsRasterReadHeader2: Returning 1.");
693 * 'cupsRasterReadPixels()' - Read raster pixels.
695 * For best performance, filters should read one or more whole lines.
696 * The "cupsBytesPerLine" value from the page header can be used to allocate
697 * the line buffer and as the number of bytes to read.
700 unsigned /* O - Number of bytes read */
701 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
702 unsigned char *p
, /* I - Pointer to pixel buffer */
703 unsigned len
) /* I - Number of bytes to read */
705 ssize_t bytes
; /* Bytes read */
706 unsigned cupsBytesPerLine
; /* cupsBytesPerLine value */
707 unsigned remaining
; /* Bytes remaining */
708 unsigned char *ptr
, /* Pointer to read buffer */
709 byte
, /* Byte from file */
710 *temp
; /* Pointer into buffer */
711 unsigned count
; /* Repetition count */
714 DEBUG_printf(("cupsRasterReadPixels(r=%p, p=%p, len=%u)", (void *)r
, (void *)p
, len
));
716 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0 ||
717 r
->header
.cupsBytesPerLine
== 0)
719 DEBUG_puts("1cupsRasterReadPixels: Returning 0.");
723 DEBUG_printf(("1cupsRasterReadPixels: compressed=%d, remaining=%u", r
->compressed
, r
->remaining
));
728 * Read without compression...
731 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
733 if (cups_raster_io(r
, p
, len
) < (ssize_t
)len
)
735 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
740 * Swap bytes as needed...
744 (r
->header
.cupsBitsPerColor
== 16 ||
745 r
->header
.cupsBitsPerPixel
== 12 ||
746 r
->header
.cupsBitsPerPixel
== 16))
753 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len
));
759 * Read compressed data...
763 cupsBytesPerLine
= r
->header
.cupsBytesPerLine
;
765 while (remaining
> 0 && r
->remaining
> 0)
770 * Need to read a new row...
773 if (remaining
== cupsBytesPerLine
)
779 * Read using a modified PackBits compression...
782 if (!cups_raster_read(r
, &byte
, 1))
784 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
788 r
->count
= (unsigned)byte
+ 1;
794 bytes
= (ssize_t
)cupsBytesPerLine
;
799 * Get a new repeat count...
802 if (!cups_raster_read(r
, &byte
, 1))
804 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
811 * Clear to end of line...
814 switch (r
->header
.cupsColorSpace
)
817 case CUPS_CSPACE_RGB
:
818 case CUPS_CSPACE_SW
:
819 case CUPS_CSPACE_SRGB
:
820 case CUPS_CSPACE_RGBW
:
821 case CUPS_CSPACE_ADOBERGB
:
822 memset(temp
, 0xff, (size_t)bytes
);
825 memset(temp
, 0x00, (size_t)bytes
);
835 * Copy N literal pixels...
838 count
= (unsigned)(257 - byte
) * r
->bpp
;
840 if (count
> (unsigned)bytes
)
841 count
= (unsigned)bytes
;
843 if (!cups_raster_read(r
, temp
, count
))
845 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
850 bytes
-= (ssize_t
)count
;
855 * Repeat the next N bytes...
858 count
= ((unsigned)byte
+ 1) * r
->bpp
;
859 if (count
> (unsigned)bytes
)
860 count
= (unsigned)bytes
;
865 bytes
-= (ssize_t
)count
;
867 if (!cups_raster_read(r
, temp
, r
->bpp
))
869 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
878 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
886 * Swap bytes as needed...
889 if ((r
->header
.cupsBitsPerColor
== 16 ||
890 r
->header
.cupsBitsPerPixel
== 12 ||
891 r
->header
.cupsBitsPerPixel
== 16) &&
894 DEBUG_puts("1cupsRasterReadPixels: Swapping bytes.");
895 cups_swap(ptr
, (size_t)cupsBytesPerLine
);
902 if (remaining
>= cupsBytesPerLine
)
904 bytes
= (ssize_t
)cupsBytesPerLine
;
905 r
->pcurrent
= r
->pixels
;
911 bytes
= (ssize_t
)remaining
;
912 r
->pcurrent
= r
->pixels
+ bytes
;
916 * Copy data as needed...
920 memcpy(p
, ptr
, (size_t)bytes
);
925 * Copy fragment from buffer...
928 if ((unsigned)(bytes
= (int)(r
->pend
- r
->pcurrent
)) > remaining
)
929 bytes
= (ssize_t
)remaining
;
931 memcpy(p
, r
->pcurrent
, (size_t)bytes
);
932 r
->pcurrent
+= bytes
;
934 if (r
->pcurrent
>= r
->pend
)
936 r
->pcurrent
= r
->pixels
;
942 remaining
-= (unsigned)bytes
;
946 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len
));
953 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
956 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
961 unsigned /* O - 1 on success, 0 on failure */
962 cupsRasterWriteHeader(
963 cups_raster_t
*r
, /* I - Raster stream */
964 cups_page_header_t
*h
) /* I - Raster page header */
966 DEBUG_printf(("cupsRasterWriteHeader(r=%p, h=%p)", (void *)r
, (void *)h
));
968 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
970 DEBUG_puts("1cupsRasterWriteHeader: Returning 0.");
974 DEBUG_printf(("1cupsRasterWriteHeader: cupsColorSpace=%s", cups_color_spaces
[h
->cupsColorSpace
]));
975 DEBUG_printf(("1cupsRasterWriteHeader: cupsBitsPerColor=%u", h
->cupsBitsPerColor
));
976 DEBUG_printf(("1cupsRasterWriteHeader: cupsBitsPerPixel=%u", h
->cupsBitsPerPixel
));
977 DEBUG_printf(("1cupsRasterWriteHeader: cupsBytesPerLine=%u", h
->cupsBytesPerLine
));
978 DEBUG_printf(("1cupsRasterWriteHeader: cupsWidth=%u", h
->cupsWidth
));
979 DEBUG_printf(("1cupsRasterWriteHeader: cupsHeight=%u", h
->cupsHeight
));
982 * Make a copy of the header, and compute the number of raster
983 * lines in the page image...
986 memset(&(r
->header
), 0, sizeof(r
->header
));
987 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
989 if (!cups_raster_update(r
))
991 DEBUG_puts("1cupsRasterWriteHeader: Unable to update parameters, returning 0.");
995 if (r
->mode
== CUPS_RASTER_WRITE_APPLE
)
997 r
->rowheight
= h
->HWResolution
[0] / h
->HWResolution
[1];
999 if (h
->HWResolution
[0] != (r
->rowheight
* h
->HWResolution
[1]))
1006 * Write the raster header...
1009 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
1012 * PWG raster data is always network byte order with much of the page header
1016 cups_page_header2_t fh
; /* File page header */
1018 memset(&fh
, 0, sizeof(fh
));
1020 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
1022 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
1023 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
1024 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
1025 /* PrintContentType */
1027 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
1028 fh
.Duplex
= htonl(r
->header
.Duplex
);
1029 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
1030 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
1031 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
1032 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
1033 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
1034 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
1035 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
1036 fh
.Jog
= htonl(r
->header
.Jog
);
1037 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
1038 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
1039 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
1040 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
1041 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
1042 fh
.Orientation
= htonl(r
->header
.Orientation
);
1043 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
1044 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
1045 fh
.Tumble
= htonl(r
->header
.Tumble
);
1046 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
1047 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
1048 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
1049 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
1050 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
1051 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
1052 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
1053 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
1054 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
1055 /* TotalPageCount */
1056 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
1057 /* CrossFeedTransform */
1058 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
1060 fh
.cupsInteger
[3] = htonl(r
->header
.cupsInteger
[3]);
1062 fh
.cupsInteger
[4] = htonl(r
->header
.cupsInteger
[4]);
1064 fh
.cupsInteger
[5] = htonl(r
->header
.cupsInteger
[5]);
1066 fh
.cupsInteger
[6] = htonl(r
->header
.cupsInteger
[6]);
1067 /* ImageBoxBottom */
1068 fh
.cupsInteger
[7] = htonl(r
->header
.cupsInteger
[7]);
1070 fh
.cupsInteger
[8] = htonl(r
->header
.cupsInteger
[8]);
1072 fh
.cupsInteger
[14] = htonl(r
->header
.cupsInteger
[14]);
1073 /* VendorIdentifier */
1074 fh
.cupsInteger
[15] = htonl(r
->header
.cupsInteger
[15]);
1077 void *dst
= fh
.cupsReal
; /* Bypass bogus compiler warning */
1078 void *src
= r
->header
.cupsReal
;
1079 memcpy(dst
, src
, sizeof(fh
.cupsReal
) + sizeof(fh
.cupsString
));
1082 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
1083 sizeof(fh
.cupsRenderingIntent
));
1084 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
1085 sizeof(fh
.cupsPageSizeName
));
1087 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
1089 else if (r
->mode
== CUPS_RASTER_WRITE_APPLE
)
1092 * Raw raster data is always network byte order with most of the page header
1096 unsigned char appleheader
[32]; /* Raw page header */
1098 if (r
->apple_page_count
== 0xffffffffU
)
1101 * Write raw page count from raster page header...
1104 r
->apple_page_count
= r
->header
.cupsInteger
[0];
1106 appleheader
[0] = 'A';
1107 appleheader
[1] = 'S';
1108 appleheader
[2] = 'T';
1110 appleheader
[4] = (unsigned char)(r
->apple_page_count
>> 24);
1111 appleheader
[5] = (unsigned char)(r
->apple_page_count
>> 16);
1112 appleheader
[6] = (unsigned char)(r
->apple_page_count
>> 8);
1113 appleheader
[7] = (unsigned char)(r
->apple_page_count
);
1115 if (cups_raster_io(r
, appleheader
, 8) != 8)
1119 memset(appleheader
, 0, sizeof(appleheader
));
1121 appleheader
[0] = (unsigned char)r
->header
.cupsBitsPerPixel
;
1122 appleheader
[1] = r
->header
.cupsColorSpace
== CUPS_CSPACE_SRGB
? 1 :
1123 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGBW
? 2 :
1124 r
->header
.cupsColorSpace
== CUPS_CSPACE_ADOBERGB
? 3 :
1125 r
->header
.cupsColorSpace
== CUPS_CSPACE_W
? 4 :
1126 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGB
? 5 :
1127 r
->header
.cupsColorSpace
== CUPS_CSPACE_CMYK
? 6 : 0;
1128 appleheader
[12] = (unsigned char)(r
->header
.cupsWidth
>> 24);
1129 appleheader
[13] = (unsigned char)(r
->header
.cupsWidth
>> 16);
1130 appleheader
[14] = (unsigned char)(r
->header
.cupsWidth
>> 8);
1131 appleheader
[15] = (unsigned char)(r
->header
.cupsWidth
);
1132 appleheader
[16] = (unsigned char)(r
->header
.cupsHeight
>> 24);
1133 appleheader
[17] = (unsigned char)(r
->header
.cupsHeight
>> 16);
1134 appleheader
[18] = (unsigned char)(r
->header
.cupsHeight
>> 8);
1135 appleheader
[19] = (unsigned char)(r
->header
.cupsHeight
);
1136 appleheader
[20] = (unsigned char)(r
->header
.HWResolution
[0] >> 24);
1137 appleheader
[21] = (unsigned char)(r
->header
.HWResolution
[0] >> 16);
1138 appleheader
[22] = (unsigned char)(r
->header
.HWResolution
[0] >> 8);
1139 appleheader
[23] = (unsigned char)(r
->header
.HWResolution
[0]);
1141 return (cups_raster_io(r
, appleheader
, sizeof(appleheader
)) == sizeof(appleheader
));
1144 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
1145 == sizeof(r
->header
));
1150 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
1151 * page header structure.
1153 * The page header can be initialized using @link cupsRasterInitPWGHeader@.
1155 * @since CUPS 1.2/macOS 10.5@
1158 unsigned /* O - 1 on success, 0 on failure */
1159 cupsRasterWriteHeader2(
1160 cups_raster_t
*r
, /* I - Raster stream */
1161 cups_page_header2_t
*h
) /* I - Raster page header */
1163 DEBUG_printf(("cupsRasterWriteHeader(r=%p, h=%p)", (void *)r
, (void *)h
));
1165 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
1167 DEBUG_puts("1cupsRasterWriteHeader2: Returning 0.");
1171 DEBUG_printf(("1cupsRasterWriteHeader2: cupsColorSpace=%s", cups_color_spaces
[h
->cupsColorSpace
]));
1172 DEBUG_printf(("1cupsRasterWriteHeader2: cupsBitsPerColor=%u", h
->cupsBitsPerColor
));
1173 DEBUG_printf(("1cupsRasterWriteHeader2: cupsBitsPerPixel=%u", h
->cupsBitsPerPixel
));
1174 DEBUG_printf(("1cupsRasterWriteHeader2: cupsBytesPerLine=%u", h
->cupsBytesPerLine
));
1175 DEBUG_printf(("1cupsRasterWriteHeader2: cupsWidth=%u", h
->cupsWidth
));
1176 DEBUG_printf(("1cupsRasterWriteHeader2: cupsHeight=%u", h
->cupsHeight
));
1179 * Make a copy of the header, and compute the number of raster
1180 * lines in the page image...
1183 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
1185 if (!cups_raster_update(r
))
1187 DEBUG_puts("1cupsRasterWriteHeader: Unable to update parameters, returning 0.");
1191 if (r
->mode
== CUPS_RASTER_WRITE_APPLE
)
1193 r
->rowheight
= h
->HWResolution
[0] / h
->HWResolution
[1];
1195 if (h
->HWResolution
[0] != (r
->rowheight
* h
->HWResolution
[1]))
1202 * Write the raster header...
1205 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
1208 * PWG raster data is always network byte order with most of the page header
1212 cups_page_header2_t fh
; /* File page header */
1214 memset(&fh
, 0, sizeof(fh
));
1215 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
1216 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
1217 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
1218 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
1219 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
1220 sizeof(fh
.cupsRenderingIntent
));
1221 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
1222 sizeof(fh
.cupsPageSizeName
));
1224 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
1225 fh
.Duplex
= htonl(r
->header
.Duplex
);
1226 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
1227 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
1228 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
1229 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
1230 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
1231 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
1232 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
1233 fh
.Jog
= htonl(r
->header
.Jog
);
1234 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
1235 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
1236 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
1237 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
1238 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
1239 fh
.Orientation
= htonl(r
->header
.Orientation
);
1240 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
1241 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
1242 fh
.Tumble
= htonl(r
->header
.Tumble
);
1243 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
1244 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
1245 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
1246 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
1247 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
1248 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
1249 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
1250 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
1251 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
1252 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
1253 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
1254 fh
.cupsInteger
[3] = htonl((unsigned)(r
->header
.cupsImagingBBox
[0] * r
->header
.HWResolution
[0] / 72.0));
1255 fh
.cupsInteger
[4] = htonl((unsigned)(r
->header
.cupsImagingBBox
[1] * r
->header
.HWResolution
[1] / 72.0));
1256 fh
.cupsInteger
[5] = htonl((unsigned)(r
->header
.cupsImagingBBox
[2] * r
->header
.HWResolution
[0] / 72.0));
1257 fh
.cupsInteger
[6] = htonl((unsigned)(r
->header
.cupsImagingBBox
[3] * r
->header
.HWResolution
[1] / 72.0));
1258 fh
.cupsInteger
[7] = htonl(0xffffff);
1260 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
1262 else if (r
->mode
== CUPS_RASTER_WRITE_APPLE
)
1265 * Raw raster data is always network byte order with most of the page header
1269 unsigned char appleheader
[32]; /* Raw page header */
1270 unsigned height
= r
->header
.cupsHeight
* r
->rowheight
;
1271 /* Computed page height */
1273 if (r
->apple_page_count
== 0xffffffffU
)
1276 * Write raw page count from raster page header...
1279 r
->apple_page_count
= r
->header
.cupsInteger
[0];
1281 appleheader
[0] = 'A';
1282 appleheader
[1] = 'S';
1283 appleheader
[2] = 'T';
1285 appleheader
[4] = (unsigned char)(r
->apple_page_count
>> 24);
1286 appleheader
[5] = (unsigned char)(r
->apple_page_count
>> 16);
1287 appleheader
[6] = (unsigned char)(r
->apple_page_count
>> 8);
1288 appleheader
[7] = (unsigned char)(r
->apple_page_count
);
1290 if (cups_raster_io(r
, appleheader
, 8) != 8)
1294 memset(appleheader
, 0, sizeof(appleheader
));
1296 appleheader
[0] = (unsigned char)r
->header
.cupsBitsPerPixel
;
1297 appleheader
[1] = r
->header
.cupsColorSpace
== CUPS_CSPACE_SRGB
? 1 :
1298 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGBW
? 2 :
1299 r
->header
.cupsColorSpace
== CUPS_CSPACE_ADOBERGB
? 3 :
1300 r
->header
.cupsColorSpace
== CUPS_CSPACE_W
? 4 :
1301 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGB
? 5 :
1302 r
->header
.cupsColorSpace
== CUPS_CSPACE_CMYK
? 6 : 0;
1303 appleheader
[12] = (unsigned char)(r
->header
.cupsWidth
>> 24);
1304 appleheader
[13] = (unsigned char)(r
->header
.cupsWidth
>> 16);
1305 appleheader
[14] = (unsigned char)(r
->header
.cupsWidth
>> 8);
1306 appleheader
[15] = (unsigned char)(r
->header
.cupsWidth
);
1307 appleheader
[16] = (unsigned char)(height
>> 24);
1308 appleheader
[17] = (unsigned char)(height
>> 16);
1309 appleheader
[18] = (unsigned char)(height
>> 8);
1310 appleheader
[19] = (unsigned char)(height
);
1311 appleheader
[20] = (unsigned char)(r
->header
.HWResolution
[0] >> 24);
1312 appleheader
[21] = (unsigned char)(r
->header
.HWResolution
[0] >> 16);
1313 appleheader
[22] = (unsigned char)(r
->header
.HWResolution
[0] >> 8);
1314 appleheader
[23] = (unsigned char)(r
->header
.HWResolution
[0]);
1316 return (cups_raster_io(r
, appleheader
, sizeof(appleheader
)) == sizeof(appleheader
));
1319 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
1320 == sizeof(r
->header
));
1325 * 'cupsRasterWritePixels()' - Write raster pixels.
1327 * For best performance, filters should write one or more whole lines.
1328 * The "cupsBytesPerLine" value from the page header can be used to allocate
1329 * the line buffer and as the number of bytes to write.
1332 unsigned /* O - Number of bytes written */
1333 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
1334 unsigned char *p
, /* I - Bytes to write */
1335 unsigned len
)/* I - Number of bytes to write */
1337 ssize_t bytes
; /* Bytes read */
1338 unsigned remaining
; /* Bytes remaining */
1341 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u", (void *)r
, (void *)p
, len
, r
->remaining
));
1343 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
|| r
->remaining
== 0)
1349 * Without compression, just write the raster data raw unless the data needs
1353 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
1356 (r
->header
.cupsBitsPerColor
== 16 ||
1357 r
->header
.cupsBitsPerPixel
== 12 ||
1358 r
->header
.cupsBitsPerPixel
== 16))
1360 unsigned char *bufptr
; /* Pointer into write buffer */
1363 * Allocate a write buffer as needed...
1366 if ((size_t)len
> r
->bufsize
)
1369 bufptr
= realloc(r
->buffer
, len
);
1371 bufptr
= malloc(len
);
1381 * Byte swap the pixels and write them...
1384 cups_swap_copy(r
->buffer
, p
, len
);
1386 bytes
= cups_raster_io(r
, r
->buffer
, len
);
1389 bytes
= cups_raster_io(r
, p
, len
);
1398 * Otherwise, compress each line...
1401 for (remaining
= len
; remaining
> 0; remaining
-= (unsigned)bytes
, p
+= bytes
)
1404 * Figure out the number of remaining bytes on the current line...
1407 if ((bytes
= (ssize_t
)remaining
) > (ssize_t
)(r
->pend
- r
->pcurrent
))
1408 bytes
= (ssize_t
)(r
->pend
- r
->pcurrent
);
1413 * Check to see if this line is the same as the previous line...
1416 if (memcmp(p
, r
->pcurrent
, (size_t)bytes
))
1418 if (cups_raster_write(r
, r
->pixels
) <= 0)
1426 * Mark more bytes as the same...
1429 r
->pcurrent
+= bytes
;
1431 if (r
->pcurrent
>= r
->pend
)
1434 * Increase the repeat count...
1437 r
->count
+= r
->rowheight
;
1438 r
->pcurrent
= r
->pixels
;
1441 * Flush out this line if it is the last one...
1446 if (r
->remaining
== 0)
1448 if (cups_raster_write(r
, r
->pixels
) <= 0)
1453 else if (r
->count
> (256 - r
->rowheight
))
1455 if (cups_raster_write(r
, r
->pixels
) <= 0)
1469 * Copy the raster data to the buffer...
1472 memcpy(r
->pcurrent
, p
, (size_t)bytes
);
1474 r
->pcurrent
+= bytes
;
1476 if (r
->pcurrent
>= r
->pend
)
1479 * Increase the repeat count...
1482 r
->count
+= r
->rowheight
;
1483 r
->pcurrent
= r
->pixels
;
1486 * Flush out this line if it is the last one...
1491 if (r
->remaining
== 0)
1493 if (cups_raster_write(r
, r
->pixels
) <= 0)
1505 * 'cups_raster_read_header()' - Read a raster page header.
1508 static unsigned /* O - 1 on success, 0 on fail */
1509 cups_raster_read_header(
1510 cups_raster_t
*r
) /* I - Raster stream */
1512 size_t len
; /* Length for read/swap */
1515 DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%s", (void *)r
, r
? cups_modes
[r
->mode
] : ""));
1517 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
1520 DEBUG_printf(("4cups_raster_read_header: r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1522 memset(&(r
->header
), 0, sizeof(r
->header
));
1525 * Read the header...
1532 * Get the length of the raster header...
1535 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
1536 len
= sizeof(cups_page_header_t
);
1538 len
= sizeof(cups_page_header2_t
);
1540 DEBUG_printf(("4cups_raster_read_header: len=%d", (int)len
));
1546 if (cups_raster_read(r
, (unsigned char *)&(r
->header
), len
) < (ssize_t
)len
)
1548 DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1553 * Swap bytes as needed...
1558 unsigned *s
, /* Current word */
1559 temp
; /* Temporary copy */
1562 DEBUG_puts("4cups_raster_read_header: Swapping header bytes.");
1564 for (len
= 81, s
= &(r
->header
.AdvanceDistance
);
1569 *s
= ((temp
& 0xff) << 24) |
1570 ((temp
& 0xff00) << 8) |
1571 ((temp
& 0xff0000) >> 8) |
1572 ((temp
& 0xff000000) >> 24);
1574 DEBUG_printf(("4cups_raster_read_header: %08x => %08x", temp
, *s
));
1579 case CUPS_RASTER_SYNCapple
:
1580 case CUPS_RASTER_REVSYNCapple
:
1582 unsigned char appleheader
[32]; /* Raw header */
1583 static const unsigned rawcspace
[] =
1588 CUPS_CSPACE_ADOBERGB
,
1593 static const unsigned rawnumcolors
[] =
1604 if (cups_raster_read(r
, appleheader
, sizeof(appleheader
)) < (ssize_t
)sizeof(appleheader
))
1606 DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1610 strlcpy(r
->header
.MediaClass
, "PwgRaster", sizeof(r
->header
.MediaClass
));
1612 r
->header
.cupsBitsPerPixel
= appleheader
[0];
1613 r
->header
.cupsColorSpace
= appleheader
[1] >= (sizeof(rawcspace
) / sizeof(rawcspace
[0])) ? CUPS_CSPACE_DEVICE1
: rawcspace
[appleheader
[1]];
1614 r
->header
.cupsNumColors
= appleheader
[1] >= (sizeof(rawnumcolors
) / sizeof(rawnumcolors
[0])) ? 1 : rawnumcolors
[appleheader
[1]];
1615 r
->header
.cupsBitsPerColor
= r
->header
.cupsBitsPerPixel
/ r
->header
.cupsNumColors
;
1616 r
->header
.cupsWidth
= ((((((unsigned)appleheader
[12] << 8) | (unsigned)appleheader
[13]) << 8) | (unsigned)appleheader
[14]) << 8) | (unsigned)appleheader
[15];
1617 r
->header
.cupsHeight
= ((((((unsigned)appleheader
[16] << 8) | (unsigned)appleheader
[17]) << 8) | (unsigned)appleheader
[18]) << 8) | (unsigned)appleheader
[19];
1618 r
->header
.cupsBytesPerLine
= r
->header
.cupsWidth
* r
->header
.cupsBitsPerPixel
/ 8;
1619 r
->header
.cupsColorOrder
= CUPS_ORDER_CHUNKED
;
1620 r
->header
.HWResolution
[0] = r
->header
.HWResolution
[1] = ((((((unsigned)appleheader
[20] << 8) | (unsigned)appleheader
[21]) << 8) | (unsigned)appleheader
[22]) << 8) | (unsigned)appleheader
[23];
1622 if (r
->header
.HWResolution
[0] > 0)
1624 r
->header
.PageSize
[0] = (unsigned)(r
->header
.cupsWidth
* 72 / r
->header
.HWResolution
[0]);
1625 r
->header
.PageSize
[1] = (unsigned)(r
->header
.cupsHeight
* 72 / r
->header
.HWResolution
[1]);
1626 r
->header
.cupsPageSize
[0] = (float)(r
->header
.cupsWidth
* 72.0 / r
->header
.HWResolution
[0]);
1627 r
->header
.cupsPageSize
[1] = (float)(r
->header
.cupsHeight
* 72.0 / r
->header
.HWResolution
[1]);
1630 r
->header
.cupsInteger
[0] = r
->apple_page_count
;
1631 r
->header
.cupsInteger
[7] = 0xffffff;
1637 * Update the header and row count...
1640 if (!cups_raster_update(r
))
1643 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
));
1645 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);
1650 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
1653 static ssize_t
/* O - Bytes read/write or -1 */
1654 cups_raster_io(cups_raster_t
*r
, /* I - Raster stream */
1655 unsigned char *buf
, /* I - Buffer for read/write */
1656 size_t bytes
) /* I - Number of bytes to read/write */
1658 ssize_t count
, /* Number of bytes read/written */
1659 total
; /* Total bytes read/written */
1662 DEBUG_printf(("5cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT
")", (void *)r
, (void *)buf
, CUPS_LLCAST bytes
));
1664 for (total
= 0; total
< (ssize_t
)bytes
; total
+= count
, buf
+= count
)
1666 count
= (*r
->iocb
)(r
->ctx
, buf
, bytes
- (size_t)total
);
1668 DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count
, (int)total
));
1672 // DEBUG_puts("6cups_raster_io: Returning 0.");
1677 DEBUG_puts("6cups_raster_io: Returning -1 on error.");
1682 r
->iocount
+= (size_t)count
;
1686 DEBUG_printf(("6cups_raster_io: iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1687 DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT
".", CUPS_LLCAST total
));
1694 * 'cups_raster_read()' - Read through the raster buffer.
1697 static ssize_t
/* O - Number of bytes read */
1698 cups_raster_read(cups_raster_t
*r
, /* I - Raster stream */
1699 unsigned char *buf
, /* I - Buffer */
1700 size_t bytes
) /* I - Number of bytes to read */
1702 ssize_t count
, /* Number of bytes read */
1703 remaining
, /* Remaining bytes in buffer */
1704 total
; /* Total bytes read */
1707 DEBUG_printf(("4cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT
"), offset=" CUPS_LLFMT
, (void *)r
, (void *)buf
, CUPS_LLCAST bytes
, CUPS_LLCAST (r
->iostart
+ r
->bufptr
- r
->buffer
)));
1710 return (cups_raster_io(r
, buf
, bytes
));
1713 * Allocate a read buffer as needed...
1716 count
= (ssize_t
)(2 * r
->header
.cupsBytesPerLine
);
1720 if ((size_t)count
> r
->bufsize
)
1722 ssize_t offset
= r
->bufptr
- r
->buffer
;
1723 /* Offset to current start of buffer */
1724 ssize_t end
= r
->bufend
- r
->buffer
;/* Offset to current end of buffer */
1725 unsigned char *rptr
; /* Pointer in read buffer */
1728 rptr
= realloc(r
->buffer
, (size_t)count
);
1730 rptr
= malloc((size_t)count
);
1736 r
->bufptr
= rptr
+ offset
;
1737 r
->bufend
= rptr
+ end
;
1738 r
->bufsize
= (size_t)count
;
1742 * Loop until we have read everything...
1745 for (total
= 0, remaining
= (int)(r
->bufend
- r
->bufptr
);
1746 total
< (ssize_t
)bytes
;
1747 total
+= count
, buf
+= count
)
1749 count
= (ssize_t
)bytes
- total
;
1751 DEBUG_printf(("5cups_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
));
1758 * Read into the raster buffer and then copy...
1762 r
->iostart
+= (size_t)(r
->bufend
- r
->buffer
);
1765 remaining
= (*r
->iocb
)(r
->ctx
, r
->buffer
, r
->bufsize
);
1769 r
->bufptr
= r
->buffer
;
1770 r
->bufend
= r
->buffer
+ remaining
;
1773 r
->iocount
+= (size_t)remaining
;
1779 * Read directly into "buf"...
1782 count
= (*r
->iocb
)(r
->ctx
, buf
, (size_t)count
);
1788 r
->iostart
+= (size_t)count
;
1789 r
->iocount
+= (size_t)count
;
1797 * Copy bytes from raster buffer to "buf"...
1800 if (count
> remaining
)
1809 *buf
= *(r
->bufptr
)++;
1812 else if (count
< 128)
1815 * Copy up to 127 bytes without using memcpy(); this is
1816 * faster because it avoids an extra function call and is
1817 * often further optimized by the compiler...
1820 unsigned char *bufptr
; /* Temporary buffer pointer */
1824 for (bufptr
= r
->bufptr
; count
> 0; count
--, total
++)
1832 * Use memcpy() for a large read...
1835 memcpy(buf
, r
->bufptr
, (size_t)count
);
1841 DEBUG_printf(("5cups_raster_read: Returning %ld", (long)total
));
1848 * 'cups_raster_update()' - Update the raster header and row count for the
1852 static int /* O - 1 on success, 0 on failure */
1853 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
1855 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
1856 r
->header
.cupsNumColors
== 0)
1859 * Set the "cupsNumColors" field according to the colorspace...
1862 switch (r
->header
.cupsColorSpace
)
1864 case CUPS_CSPACE_W
:
1865 case CUPS_CSPACE_K
:
1866 case CUPS_CSPACE_WHITE
:
1867 case CUPS_CSPACE_GOLD
:
1868 case CUPS_CSPACE_SILVER
:
1869 case CUPS_CSPACE_SW
:
1870 r
->header
.cupsNumColors
= 1;
1873 case CUPS_CSPACE_RGB
:
1874 case CUPS_CSPACE_CMY
:
1875 case CUPS_CSPACE_YMC
:
1876 case CUPS_CSPACE_CIEXYZ
:
1877 case CUPS_CSPACE_CIELab
:
1878 case CUPS_CSPACE_SRGB
:
1879 case CUPS_CSPACE_ADOBERGB
:
1880 case CUPS_CSPACE_ICC1
:
1881 case CUPS_CSPACE_ICC2
:
1882 case CUPS_CSPACE_ICC3
:
1883 case CUPS_CSPACE_ICC4
:
1884 case CUPS_CSPACE_ICC5
:
1885 case CUPS_CSPACE_ICC6
:
1886 case CUPS_CSPACE_ICC7
:
1887 case CUPS_CSPACE_ICC8
:
1888 case CUPS_CSPACE_ICC9
:
1889 case CUPS_CSPACE_ICCA
:
1890 case CUPS_CSPACE_ICCB
:
1891 case CUPS_CSPACE_ICCC
:
1892 case CUPS_CSPACE_ICCD
:
1893 case CUPS_CSPACE_ICCE
:
1894 case CUPS_CSPACE_ICCF
:
1895 r
->header
.cupsNumColors
= 3;
1898 case CUPS_CSPACE_RGBA
:
1899 case CUPS_CSPACE_RGBW
:
1900 case CUPS_CSPACE_CMYK
:
1901 case CUPS_CSPACE_YMCK
:
1902 case CUPS_CSPACE_KCMY
:
1903 case CUPS_CSPACE_GMCK
:
1904 case CUPS_CSPACE_GMCS
:
1905 r
->header
.cupsNumColors
= 4;
1908 case CUPS_CSPACE_KCMYcm
:
1909 if (r
->header
.cupsBitsPerPixel
< 8)
1910 r
->header
.cupsNumColors
= 6;
1912 r
->header
.cupsNumColors
= 4;
1915 case CUPS_CSPACE_DEVICE1
:
1916 case CUPS_CSPACE_DEVICE2
:
1917 case CUPS_CSPACE_DEVICE3
:
1918 case CUPS_CSPACE_DEVICE4
:
1919 case CUPS_CSPACE_DEVICE5
:
1920 case CUPS_CSPACE_DEVICE6
:
1921 case CUPS_CSPACE_DEVICE7
:
1922 case CUPS_CSPACE_DEVICE8
:
1923 case CUPS_CSPACE_DEVICE9
:
1924 case CUPS_CSPACE_DEVICEA
:
1925 case CUPS_CSPACE_DEVICEB
:
1926 case CUPS_CSPACE_DEVICEC
:
1927 case CUPS_CSPACE_DEVICED
:
1928 case CUPS_CSPACE_DEVICEE
:
1929 case CUPS_CSPACE_DEVICEF
:
1930 r
->header
.cupsNumColors
= r
->header
.cupsColorSpace
-
1931 CUPS_CSPACE_DEVICE1
+ 1;
1935 /* Unknown color space */
1941 * Set the number of bytes per pixel/color...
1944 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
1945 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
1947 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
1953 * Set the number of remaining rows...
1956 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
1957 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
1959 r
->remaining
= r
->header
.cupsHeight
;
1962 * Allocate the compression buffer...
1967 if (r
->pixels
!= NULL
)
1970 if ((r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1)) == NULL
)
1979 r
->pcurrent
= r
->pixels
;
1980 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
1989 * 'cups_raster_write()' - Write a row of compressed raster data...
1992 static ssize_t
/* O - Number of bytes written */
1994 cups_raster_t
*r
, /* I - Raster stream */
1995 const unsigned char *pixels
) /* I - Pixel data to write */
1997 const unsigned char *start
, /* Start of sequence */
1998 *ptr
, /* Current pointer in sequence */
1999 *pend
, /* End of raster buffer */
2000 *plast
; /* Pointer to last pixel */
2001 unsigned char *wptr
; /* Pointer into write buffer */
2002 unsigned bpp
, /* Bytes per pixel */
2004 _cups_copyfunc_t cf
; /* Copy function */
2007 DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)", (void *)r
, (void *)pixels
));
2010 * Determine whether we need to swap bytes...
2013 if (r
->swapped
&& (r
->header
.cupsBitsPerColor
== 16 || r
->header
.cupsBitsPerPixel
== 12 || r
->header
.cupsBitsPerPixel
== 16))
2015 DEBUG_puts("4cups_raster_write: Swapping bytes when writing.");
2016 cf
= (_cups_copyfunc_t
)cups_swap_copy
;
2019 cf
= (_cups_copyfunc_t
)memcpy
;
2022 * Allocate a write buffer as needed...
2025 count
= r
->header
.cupsBytesPerLine
* 2;
2029 if ((size_t)count
> r
->bufsize
)
2032 wptr
= realloc(r
->buffer
, count
);
2034 wptr
= malloc(count
);
2038 DEBUG_printf(("4cups_raster_write: Unable to allocate " CUPS_LLFMT
" bytes for raster buffer: %s", CUPS_LLCAST count
, strerror(errno
)));
2047 * Write the row repeat count...
2051 pend
= pixels
+ r
->header
.cupsBytesPerLine
;
2054 *wptr
++ = (unsigned char)(r
->count
- 1);
2057 * Write using a modified PackBits compression...
2060 for (ptr
= pixels
; ptr
< pend
;)
2068 * Encode a single pixel at the end...
2072 (*cf
)(wptr
, start
, bpp
);
2075 else if (!memcmp(start
, ptr
, bpp
))
2078 * Encode a sequence of repeating pixels...
2081 for (count
= 2; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
2082 if (memcmp(ptr
, ptr
+ bpp
, bpp
))
2085 *wptr
++ = (unsigned char)(count
- 1);
2086 (*cf
)(wptr
, ptr
, bpp
);
2093 * Encode a sequence of non-repeating pixels...
2096 for (count
= 1; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
2097 if (!memcmp(ptr
, ptr
+ bpp
, bpp
))
2100 if (ptr
>= plast
&& count
< 128)
2106 *wptr
++ = (unsigned char)(257 - count
);
2109 (*cf
)(wptr
, start
, count
);
2114 DEBUG_printf(("4cups_raster_write: Writing " CUPS_LLFMT
" bytes.", CUPS_LLCAST (wptr
- r
->buffer
)));
2116 return (cups_raster_io(r
, r
->buffer
, (size_t)(wptr
- r
->buffer
)));
2121 * 'cups_read_fd()' - Read bytes from a file.
2124 static ssize_t
/* O - Bytes read or -1 */
2125 cups_read_fd(void *ctx
, /* I - File descriptor as pointer */
2126 unsigned char *buf
, /* I - Buffer for read */
2127 size_t bytes
) /* I - Maximum number of bytes to read */
2129 int fd
= (int)((intptr_t)ctx
);
2130 /* File descriptor */
2131 ssize_t count
; /* Number of bytes read */
2134 #ifdef WIN32 /* Sigh */
2135 while ((count
= read(fd
, buf
, (unsigned)bytes
)) < 0)
2137 while ((count
= read(fd
, buf
, bytes
)) < 0)
2139 if (errno
!= EINTR
&& errno
!= EAGAIN
)
2141 DEBUG_printf(("8cups_read_fd: %s", strerror(errno
)));
2145 DEBUG_printf(("8cups_read_fd: Returning %d bytes.", (int)count
));
2152 * 'cups_swap()' - Swap bytes in raster data...
2156 cups_swap(unsigned char *buf
, /* I - Buffer to swap */
2157 size_t bytes
) /* I - Number of bytes to swap */
2159 unsigned char even
, odd
; /* Temporary variables */
2178 * 'cups_swap_copy()' - Copy and swap bytes in raster data...
2183 unsigned char *dst
, /* I - Destination */
2184 const unsigned char *src
, /* I - Source */
2185 size_t bytes
) /* I - Number of bytes to swap */
2202 * 'cups_write_fd()' - Write bytes to a file.
2205 static ssize_t
/* O - Bytes written or -1 */
2206 cups_write_fd(void *ctx
, /* I - File descriptor pointer */
2207 unsigned char *buf
, /* I - Bytes to write */
2208 size_t bytes
) /* I - Number of bytes to write */
2210 int fd
= (int)((intptr_t)ctx
);
2211 /* File descriptor */
2212 ssize_t count
; /* Number of bytes written */
2215 #ifdef WIN32 /* Sigh */
2216 while ((count
= write(fd
, buf
, (unsigned)bytes
)) < 0)
2218 while ((count
= write(fd
, buf
, bytes
)) < 0)
2220 if (errno
!= EINTR
&& errno
!= EAGAIN
)
2222 DEBUG_printf(("8cups_write_fd: %s", strerror(errno
)));