2 * Raster file routines for CUPS.
4 * Copyright 2007-2019 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 "raster-private.h"
18 #include "debug-internal.h"
21 #endif /* HAVE_STDINT_H */
25 * Private structures...
28 typedef void (*_cups_copyfunc_t
)(void *dst
, const void *src
, size_t bytes
);
35 static const char * const apple_media_types
[] =
36 { /* media-type values for Apple Raster */
43 "stationery-letterhead",
47 "photographic-semi-gloss",
48 "photographic-glossy",
49 "photographic-high-gloss",
54 static const char * const cups_modes
[] =
58 "CUPS_RASTER_WRITE_COMPRESSED",
59 "CUPS_RASTER_WRITE_PWG",
60 "CUPS_RASTER_WRITE_APPLE"
69 static ssize_t
cups_raster_io(cups_raster_t
*r
, unsigned char *buf
, size_t bytes
);
70 static ssize_t
cups_raster_read(cups_raster_t
*r
, unsigned char *buf
, size_t bytes
);
71 static int cups_raster_update(cups_raster_t
*r
);
72 static ssize_t
cups_raster_write(cups_raster_t
*r
, const unsigned char *pixels
);
73 static void cups_swap(unsigned char *buf
, size_t bytes
);
74 static void cups_swap_copy(unsigned char *dst
, const unsigned char *src
, size_t bytes
);
78 * '_cupsRasterColorSpaceString()' - Return the colorspace name for a
79 * cupsColorSpace value.
83 _cupsRasterColorSpaceString(
84 cups_cspace_t cspace
) /* I - cupsColorSpace value */
86 static const char * const cups_color_spaces
[] =
153 if (cspace
< CUPS_CSPACE_W
|| cspace
> CUPS_CSPACE_DEVICEF
)
156 return (cups_color_spaces
[cspace
]);
161 * '_cupsRasterDelete()' - Free a raster stream.
163 * The file descriptor associated with the raster stream must be closed
164 * separately as needed.
168 _cupsRasterDelete(cups_raster_t
*r
) /* I - Stream to free */
184 * '_cupsRasterInitPWGHeader()' - Initialize a page header for PWG Raster output.
186 * The "media" argument specifies the media to use.
188 * The "type" argument specifies a "pwg-raster-document-type-supported" value
189 * that controls the color space and bit depth of the raster data.
191 * The "xres" and "yres" arguments specify the raster resolution in dots per
194 * The "sheet_back" argument specifies a "pwg-raster-document-sheet-back" value
195 * to apply for the back side of a page. Pass @code NULL@ for the front side.
197 * @since CUPS 2.2/macOS 10.12@
200 int /* O - 1 on success, 0 on failure */
201 _cupsRasterInitPWGHeader(
202 cups_page_header2_t
*h
, /* I - Page header */
203 pwg_media_t
*media
, /* I - PWG media information */
204 const char *type
, /* I - PWG raster type string */
205 int xdpi
, /* I - Cross-feed direction (horizontal) resolution */
206 int ydpi
, /* I - Feed direction (vertical) resolution */
207 const char *sides
, /* I - IPP "sides" option value */
208 const char *sheet_back
) /* I - Transform for back side or @code NULL@ for none */
210 if (!h
|| !media
|| !type
|| xdpi
<= 0 || ydpi
<= 0)
212 _cupsRasterAddError("%s", strerror(EINVAL
));
217 * Initialize the page header...
220 memset(h
, 0, sizeof(cups_page_header2_t
));
222 strlcpy(h
->cupsPageSizeName
, media
->pwg
, sizeof(h
->cupsPageSizeName
));
224 h
->PageSize
[0] = (unsigned)(72 * media
->width
/ 2540);
225 h
->PageSize
[1] = (unsigned)(72 * media
->length
/ 2540);
227 /* This never gets written but is needed for some applications */
228 h
->cupsPageSize
[0] = 72.0f
* media
->width
/ 2540.0f
;
229 h
->cupsPageSize
[1] = 72.0f
* media
->length
/ 2540.0f
;
231 h
->ImagingBoundingBox
[2] = h
->PageSize
[0];
232 h
->ImagingBoundingBox
[3] = h
->PageSize
[1];
234 h
->HWResolution
[0] = (unsigned)xdpi
;
235 h
->HWResolution
[1] = (unsigned)ydpi
;
237 h
->cupsWidth
= (unsigned)(media
->width
* xdpi
/ 2540);
238 h
->cupsHeight
= (unsigned)(media
->length
* ydpi
/ 2540);
240 if (h
->cupsWidth
> 0x00ffffff || h
->cupsHeight
> 0x00ffffff)
242 _cupsRasterAddError("Raster dimensions too large.");
246 h
->cupsInteger
[CUPS_RASTER_PWG_ImageBoxRight
] = h
->cupsWidth
;
247 h
->cupsInteger
[CUPS_RASTER_PWG_ImageBoxBottom
] = h
->cupsHeight
;
250 * Colorspace and bytes per line...
253 if (!strcmp(type
, "adobe-rgb_8"))
255 h
->cupsBitsPerColor
= 8;
256 h
->cupsBitsPerPixel
= 24;
257 h
->cupsColorSpace
= CUPS_CSPACE_ADOBERGB
;
259 else if (!strcmp(type
, "adobe-rgb_16"))
261 h
->cupsBitsPerColor
= 16;
262 h
->cupsBitsPerPixel
= 48;
263 h
->cupsColorSpace
= CUPS_CSPACE_ADOBERGB
;
265 else if (!strcmp(type
, "black_1"))
267 h
->cupsBitsPerColor
= 1;
268 h
->cupsBitsPerPixel
= 1;
269 h
->cupsColorSpace
= CUPS_CSPACE_K
;
271 else if (!strcmp(type
, "black_8"))
273 h
->cupsBitsPerColor
= 8;
274 h
->cupsBitsPerPixel
= 8;
275 h
->cupsColorSpace
= CUPS_CSPACE_K
;
277 else if (!strcmp(type
, "black_16"))
279 h
->cupsBitsPerColor
= 16;
280 h
->cupsBitsPerPixel
= 16;
281 h
->cupsColorSpace
= CUPS_CSPACE_K
;
283 else if (!strcmp(type
, "cmyk_8"))
285 h
->cupsBitsPerColor
= 8;
286 h
->cupsBitsPerPixel
= 32;
287 h
->cupsColorSpace
= CUPS_CSPACE_CMYK
;
289 else if (!strcmp(type
, "cmyk_16"))
291 h
->cupsBitsPerColor
= 16;
292 h
->cupsBitsPerPixel
= 64;
293 h
->cupsColorSpace
= CUPS_CSPACE_CMYK
;
295 else if (!strncmp(type
, "device", 6) && type
[6] >= '1' && type
[6] <= '9')
297 int ncolors
, bits
; /* Number of colors and bits */
300 if (sscanf(type
, "device%d_%d", &ncolors
, &bits
) != 2 || ncolors
> 15 || (bits
!= 8 && bits
!= 16))
302 _cupsRasterAddError("Unsupported raster type \'%s\'.", type
);
306 h
->cupsBitsPerColor
= (unsigned)bits
;
307 h
->cupsBitsPerPixel
= (unsigned)(ncolors
* bits
);
308 h
->cupsColorSpace
= (cups_cspace_t
)(CUPS_CSPACE_DEVICE1
+ ncolors
- 1);
310 else if (!strcmp(type
, "rgb_8"))
312 h
->cupsBitsPerColor
= 8;
313 h
->cupsBitsPerPixel
= 24;
314 h
->cupsColorSpace
= CUPS_CSPACE_RGB
;
316 else if (!strcmp(type
, "rgb_16"))
318 h
->cupsBitsPerColor
= 16;
319 h
->cupsBitsPerPixel
= 48;
320 h
->cupsColorSpace
= CUPS_CSPACE_RGB
;
322 else if (!strcmp(type
, "sgray_1"))
324 h
->cupsBitsPerColor
= 1;
325 h
->cupsBitsPerPixel
= 1;
326 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
328 else if (!strcmp(type
, "sgray_8"))
330 h
->cupsBitsPerColor
= 8;
331 h
->cupsBitsPerPixel
= 8;
332 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
334 else if (!strcmp(type
, "sgray_16"))
336 h
->cupsBitsPerColor
= 16;
337 h
->cupsBitsPerPixel
= 16;
338 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
340 else if (!strcmp(type
, "srgb_8"))
342 h
->cupsBitsPerColor
= 8;
343 h
->cupsBitsPerPixel
= 24;
344 h
->cupsColorSpace
= CUPS_CSPACE_SRGB
;
346 else if (!strcmp(type
, "srgb_16"))
348 h
->cupsBitsPerColor
= 16;
349 h
->cupsBitsPerPixel
= 48;
350 h
->cupsColorSpace
= CUPS_CSPACE_SRGB
;
354 _cupsRasterAddError("Unsupported raster type \'%s\'.", type
);
358 h
->cupsColorOrder
= CUPS_ORDER_CHUNKED
;
359 h
->cupsNumColors
= h
->cupsBitsPerPixel
/ h
->cupsBitsPerColor
;
360 h
->cupsBytesPerLine
= (h
->cupsWidth
* h
->cupsBitsPerPixel
+ 7) / 8;
366 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 1;
367 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 1;
371 if (!strcmp(sides
, "two-sided-long-edge"))
375 else if (!strcmp(sides
, "two-sided-short-edge"))
380 else if (strcmp(sides
, "one-sided"))
382 _cupsRasterAddError("Unsupported sides value \'%s\'.", sides
);
388 if (!strcmp(sheet_back
, "flipped"))
391 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
393 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
395 else if (!strcmp(sheet_back
, "manual-tumble"))
399 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
400 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
403 else if (!strcmp(sheet_back
, "rotated"))
407 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
408 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
411 else if (strcmp(sheet_back
, "normal"))
413 _cupsRasterAddError("Unsupported sheet_back value \'%s\'.", sheet_back
);
424 * '_cupsRasterNew()' - Create a raster stream using a callback function.
426 * This function associates a raster stream with the given callback function and
429 * When writing raster data, the @code CUPS_RASTER_WRITE@,
430 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
431 * be used - compressed and PWG output is generally 25-50% smaller but adds a
432 * 100-300% execution time overhead.
435 cups_raster_t
* /* O - New stream */
437 cups_raster_iocb_t iocb
, /* I - Read/write callback */
438 void *ctx
, /* I - Context pointer for callback */
439 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
440 @code CUPS_RASTER_WRITE@,
441 @code CUPS_RASTER_WRITE_COMPRESSED@,
442 or @code CUPS_RASTER_WRITE_PWG@ */
444 cups_raster_t
*r
; /* New stream */
447 DEBUG_printf(("_cupsRasterOpenIO(iocb=%p, ctx=%p, mode=%s)", (void *)iocb
, ctx
, cups_modes
[mode
]));
449 _cupsRasterClearError();
451 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
453 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
455 DEBUG_puts("1_cupsRasterOpenIO: Returning NULL.");
463 if (mode
== CUPS_RASTER_READ
)
466 * Open for read - get sync word...
469 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) !=
472 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
475 DEBUG_puts("1_cupsRasterOpenIO: Unable to read header, returning NULL.");
479 if (r
->sync
!= CUPS_RASTER_SYNC
&&
480 r
->sync
!= CUPS_RASTER_REVSYNC
&&
481 r
->sync
!= CUPS_RASTER_SYNCv1
&&
482 r
->sync
!= CUPS_RASTER_REVSYNCv1
&&
483 r
->sync
!= CUPS_RASTER_SYNCv2
&&
484 r
->sync
!= CUPS_RASTER_REVSYNCv2
&&
485 r
->sync
!= CUPS_RASTER_SYNCapple
&&
486 r
->sync
!= CUPS_RASTER_REVSYNCapple
)
488 _cupsRasterAddError("Unknown raster format %08x!\n", r
->sync
);
490 DEBUG_puts("1_cupsRasterOpenIO: Unknown format, returning NULL.");
494 if (r
->sync
== CUPS_RASTER_SYNCv2
||
495 r
->sync
== CUPS_RASTER_REVSYNCv2
||
496 r
->sync
== CUPS_RASTER_SYNCapple
||
497 r
->sync
== CUPS_RASTER_REVSYNCapple
)
500 DEBUG_printf(("1_cupsRasterOpenIO: sync=%08x", r
->sync
));
502 if (r
->sync
== CUPS_RASTER_REVSYNC
||
503 r
->sync
== CUPS_RASTER_REVSYNCv1
||
504 r
->sync
== CUPS_RASTER_REVSYNCv2
||
505 r
->sync
== CUPS_RASTER_REVSYNCapple
)
508 if (r
->sync
== CUPS_RASTER_SYNCapple
||
509 r
->sync
== CUPS_RASTER_REVSYNCapple
)
511 unsigned char header
[8]; /* File header */
513 if (cups_raster_io(r
, (unsigned char *)header
, sizeof(header
)) !=
516 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
519 DEBUG_puts("1_cupsRasterOpenIO: Unable to read header, returning NULL.");
525 r
->iostart
= r
->iocount
;
531 * Open for write - put sync word...
537 case CUPS_RASTER_WRITE
:
538 r
->sync
= CUPS_RASTER_SYNC
;
541 case CUPS_RASTER_WRITE_COMPRESSED
:
543 r
->sync
= CUPS_RASTER_SYNCv2
;
546 case CUPS_RASTER_WRITE_PWG
:
548 r
->sync
= htonl(CUPS_RASTER_SYNC_PWG
);
549 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNC_PWG
;
552 case CUPS_RASTER_WRITE_APPLE
:
554 r
->sync
= htonl(CUPS_RASTER_SYNCapple
);
555 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNCapple
;
556 r
->apple_page_count
= 0xffffffffU
;
560 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) < (ssize_t
)sizeof(r
->sync
))
562 _cupsRasterAddError("Unable to write raster stream header: %s\n",
565 DEBUG_puts("1_cupsRasterOpenIO: Unable to write header, returning NULL.");
570 DEBUG_printf(("1_cupsRasterOpenIO: compressed=%d, swapped=%d, returning %p", r
->compressed
, r
->swapped
, (void *)r
));
577 * '_cupsRasterReadHeader()' - Read a raster page header.
580 unsigned /* O - 1 on success, 0 on fail */
581 _cupsRasterReadHeader(
582 cups_raster_t
*r
) /* I - Raster stream */
584 size_t len
; /* Length for read/swap */
587 DEBUG_printf(("3_cupsRasterReadHeader(r=%p), r->mode=%s", (void *)r
, r
? cups_modes
[r
->mode
] : ""));
589 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
592 DEBUG_printf(("4_cupsRasterReadHeader: r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
594 memset(&(r
->header
), 0, sizeof(r
->header
));
604 * Get the length of the raster header...
607 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
608 len
= sizeof(cups_page_header_t
);
610 len
= sizeof(cups_page_header2_t
);
612 DEBUG_printf(("4_cupsRasterReadHeader: len=%d", (int)len
));
618 if (cups_raster_read(r
, (unsigned char *)&(r
->header
), len
) < (ssize_t
)len
)
620 DEBUG_printf(("4_cupsRasterReadHeader: EOF, r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
625 * Swap bytes as needed...
630 unsigned *s
, /* Current word */
631 temp
; /* Temporary copy */
634 DEBUG_puts("4_cupsRasterReadHeader: Swapping header bytes.");
636 for (len
= 81, s
= &(r
->header
.AdvanceDistance
);
641 *s
= ((temp
& 0xff) << 24) |
642 ((temp
& 0xff00) << 8) |
643 ((temp
& 0xff0000) >> 8) |
644 ((temp
& 0xff000000) >> 24);
646 DEBUG_printf(("4_cupsRasterReadHeader: %08x => %08x", temp
, *s
));
651 case CUPS_RASTER_SYNCapple
:
652 case CUPS_RASTER_REVSYNCapple
:
654 unsigned char appleheader
[32]; /* Raw header */
655 static const unsigned rawcspace
[] =
660 CUPS_CSPACE_ADOBERGB
,
665 static const unsigned rawnumcolors
[] =
676 if (cups_raster_read(r
, appleheader
, sizeof(appleheader
)) < (ssize_t
)sizeof(appleheader
))
678 DEBUG_printf(("4_cupsRasterReadHeader: EOF, r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
682 strlcpy(r
->header
.MediaClass
, "PwgRaster", sizeof(r
->header
.MediaClass
));
684 r
->header
.cupsBitsPerPixel
= appleheader
[0];
685 r
->header
.cupsColorSpace
= appleheader
[1] >= (sizeof(rawcspace
) / sizeof(rawcspace
[0])) ? CUPS_CSPACE_DEVICE1
: rawcspace
[appleheader
[1]];
686 r
->header
.cupsNumColors
= appleheader
[1] >= (sizeof(rawnumcolors
) / sizeof(rawnumcolors
[0])) ? 1 : rawnumcolors
[appleheader
[1]];
687 r
->header
.cupsBitsPerColor
= r
->header
.cupsBitsPerPixel
/ r
->header
.cupsNumColors
;
688 r
->header
.cupsWidth
= ((((((unsigned)appleheader
[12] << 8) | (unsigned)appleheader
[13]) << 8) | (unsigned)appleheader
[14]) << 8) | (unsigned)appleheader
[15];
689 r
->header
.cupsHeight
= ((((((unsigned)appleheader
[16] << 8) | (unsigned)appleheader
[17]) << 8) | (unsigned)appleheader
[18]) << 8) | (unsigned)appleheader
[19];
690 r
->header
.cupsBytesPerLine
= r
->header
.cupsWidth
* r
->header
.cupsBitsPerPixel
/ 8;
691 r
->header
.cupsColorOrder
= CUPS_ORDER_CHUNKED
;
692 r
->header
.HWResolution
[0] = r
->header
.HWResolution
[1] = ((((((unsigned)appleheader
[20] << 8) | (unsigned)appleheader
[21]) << 8) | (unsigned)appleheader
[22]) << 8) | (unsigned)appleheader
[23];
694 if (r
->header
.HWResolution
[0] > 0)
696 r
->header
.PageSize
[0] = (unsigned)(r
->header
.cupsWidth
* 72 / r
->header
.HWResolution
[0]);
697 r
->header
.PageSize
[1] = (unsigned)(r
->header
.cupsHeight
* 72 / r
->header
.HWResolution
[1]);
698 r
->header
.cupsPageSize
[0] = (float)(r
->header
.cupsWidth
* 72.0 / r
->header
.HWResolution
[0]);
699 r
->header
.cupsPageSize
[1] = (float)(r
->header
.cupsHeight
* 72.0 / r
->header
.HWResolution
[1]);
702 r
->header
.cupsInteger
[CUPS_RASTER_PWG_TotalPageCount
] = r
->apple_page_count
;
703 r
->header
.cupsInteger
[CUPS_RASTER_PWG_AlternatePrimary
] = 0xffffff;
704 r
->header
.cupsInteger
[CUPS_RASTER_PWG_PrintQuality
] = appleheader
[3];
706 if (appleheader
[2] >= 2)
707 r
->header
.Duplex
= 1;
708 if (appleheader
[2] == 2)
709 r
->header
.Tumble
= 1;
711 r
->header
.MediaPosition
= appleheader
[5];
713 if (appleheader
[4] < (int)(sizeof(apple_media_types
) / sizeof(apple_media_types
[0])))
714 strlcpy(r
->header
.MediaType
, apple_media_types
[appleheader
[4]], sizeof(r
->header
.MediaType
));
716 strlcpy(r
->header
.MediaType
, "other", sizeof(r
->header
.MediaType
));
722 * Update the header and row count...
725 if (!cups_raster_update(r
))
728 DEBUG_printf(("4_cupsRasterReadHeader: cupsColorSpace=%s", _cupsRasterColorSpaceString(r
->header
.cupsColorSpace
)));
729 DEBUG_printf(("4_cupsRasterReadHeader: cupsBitsPerColor=%u", r
->header
.cupsBitsPerColor
));
730 DEBUG_printf(("4_cupsRasterReadHeader: cupsBitsPerPixel=%u", r
->header
.cupsBitsPerPixel
));
731 DEBUG_printf(("4_cupsRasterReadHeader: cupsBytesPerLine=%u", r
->header
.cupsBytesPerLine
));
732 DEBUG_printf(("4_cupsRasterReadHeader: cupsWidth=%u", r
->header
.cupsWidth
));
733 DEBUG_printf(("4_cupsRasterReadHeader: cupsHeight=%u", r
->header
.cupsHeight
));
734 DEBUG_printf(("4_cupsRasterReadHeader: r->bpp=%d", r
->bpp
));
736 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);
741 * '_cupsRasterReadPixels()' - Read raster pixels.
743 * For best performance, filters should read one or more whole lines.
744 * The "cupsBytesPerLine" value from the page header can be used to allocate
745 * the line buffer and as the number of bytes to read.
748 unsigned /* O - Number of bytes read */
749 _cupsRasterReadPixels(
750 cups_raster_t
*r
, /* I - Raster stream */
751 unsigned char *p
, /* I - Pointer to pixel buffer */
752 unsigned len
) /* I - Number of bytes to read */
754 ssize_t bytes
; /* Bytes read */
755 unsigned cupsBytesPerLine
; /* cupsBytesPerLine value */
756 unsigned remaining
; /* Bytes remaining */
757 unsigned char *ptr
, /* Pointer to read buffer */
758 byte
, /* Byte from file */
759 *temp
; /* Pointer into buffer */
760 unsigned count
; /* Repetition count */
763 DEBUG_printf(("_cupsRasterReadPixels(r=%p, p=%p, len=%u)", (void *)r
, (void *)p
, len
));
765 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0 ||
766 r
->header
.cupsBytesPerLine
== 0)
768 DEBUG_puts("1_cupsRasterReadPixels: Returning 0.");
772 DEBUG_printf(("1_cupsRasterReadPixels: compressed=%d, remaining=%u", r
->compressed
, r
->remaining
));
777 * Read without compression...
780 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
782 if (cups_raster_io(r
, p
, len
) < (ssize_t
)len
)
784 DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
789 * Swap bytes as needed...
793 (r
->header
.cupsBitsPerColor
== 16 ||
794 r
->header
.cupsBitsPerPixel
== 12 ||
795 r
->header
.cupsBitsPerPixel
== 16))
802 DEBUG_printf(("1_cupsRasterReadPixels: Returning %u", len
));
808 * Read compressed data...
812 cupsBytesPerLine
= r
->header
.cupsBytesPerLine
;
814 while (remaining
> 0 && r
->remaining
> 0)
819 * Need to read a new row...
822 if (remaining
== cupsBytesPerLine
)
828 * Read using a modified PackBits compression...
831 if (!cups_raster_read(r
, &byte
, 1))
833 DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
837 r
->count
= (unsigned)byte
+ 1;
843 bytes
= (ssize_t
)cupsBytesPerLine
;
848 * Get a new repeat count...
851 if (!cups_raster_read(r
, &byte
, 1))
853 DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
860 * Clear to end of line...
863 switch (r
->header
.cupsColorSpace
)
866 case CUPS_CSPACE_RGB
:
867 case CUPS_CSPACE_SW
:
868 case CUPS_CSPACE_SRGB
:
869 case CUPS_CSPACE_RGBW
:
870 case CUPS_CSPACE_ADOBERGB
:
871 memset(temp
, 0xff, (size_t)bytes
);
874 memset(temp
, 0x00, (size_t)bytes
);
884 * Copy N literal pixels...
887 count
= (unsigned)(257 - byte
) * r
->bpp
;
889 if (count
> (unsigned)bytes
)
890 count
= (unsigned)bytes
;
892 if (!cups_raster_read(r
, temp
, count
))
894 DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
899 bytes
-= (ssize_t
)count
;
904 * Repeat the next N bytes...
907 count
= ((unsigned)byte
+ 1) * r
->bpp
;
908 if (count
> (unsigned)bytes
)
909 count
= (unsigned)bytes
;
914 bytes
-= (ssize_t
)count
;
916 if (!cups_raster_read(r
, temp
, r
->bpp
))
918 DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
927 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
935 * Swap bytes as needed...
938 if ((r
->header
.cupsBitsPerColor
== 16 ||
939 r
->header
.cupsBitsPerPixel
== 12 ||
940 r
->header
.cupsBitsPerPixel
== 16) &&
943 DEBUG_puts("1_cupsRasterReadPixels: Swapping bytes.");
944 cups_swap(ptr
, (size_t)cupsBytesPerLine
);
951 if (remaining
>= cupsBytesPerLine
)
953 bytes
= (ssize_t
)cupsBytesPerLine
;
954 r
->pcurrent
= r
->pixels
;
960 bytes
= (ssize_t
)remaining
;
961 r
->pcurrent
= r
->pixels
+ bytes
;
965 * Copy data as needed...
969 memcpy(p
, ptr
, (size_t)bytes
);
974 * Copy fragment from buffer...
977 if ((unsigned)(bytes
= (int)(r
->pend
- r
->pcurrent
)) > remaining
)
978 bytes
= (ssize_t
)remaining
;
980 memcpy(p
, r
->pcurrent
, (size_t)bytes
);
981 r
->pcurrent
+= bytes
;
983 if (r
->pcurrent
>= r
->pend
)
985 r
->pcurrent
= r
->pixels
;
991 remaining
-= (unsigned)bytes
;
995 DEBUG_printf(("1_cupsRasterReadPixels: Returning %u", len
));
1002 * '_cupsRasterWriteHeader()' - Write a raster page header.
1005 unsigned /* O - 1 on success, 0 on failure */
1006 _cupsRasterWriteHeader(
1007 cups_raster_t
*r
) /* I - Raster stream */
1009 DEBUG_printf(("_cupsRasterWriteHeader(r=%p)", (void *)r
));
1011 DEBUG_printf(("1_cupsRasterWriteHeader: cupsColorSpace=%s", _cupsRasterColorSpaceString(r
->header
.cupsColorSpace
)));
1012 DEBUG_printf(("1_cupsRasterWriteHeader: cupsBitsPerColor=%u", r
->header
.cupsBitsPerColor
));
1013 DEBUG_printf(("1_cupsRasterWriteHeader: cupsBitsPerPixel=%u", r
->header
.cupsBitsPerPixel
));
1014 DEBUG_printf(("1_cupsRasterWriteHeader: cupsBytesPerLine=%u", r
->header
.cupsBytesPerLine
));
1015 DEBUG_printf(("1_cupsRasterWriteHeader: cupsWidth=%u", r
->header
.cupsWidth
));
1016 DEBUG_printf(("1_cupsRasterWriteHeader: cupsHeight=%u", r
->header
.cupsHeight
));
1019 * Compute the number of raster lines in the page image...
1022 if (!cups_raster_update(r
))
1024 DEBUG_puts("1_cupsRasterWriteHeader: Unable to update parameters, returning 0.");
1028 if (r
->mode
== CUPS_RASTER_WRITE_APPLE
)
1030 r
->rowheight
= r
->header
.HWResolution
[0] / r
->header
.HWResolution
[1];
1032 if (r
->header
.HWResolution
[0] != (r
->rowheight
* r
->header
.HWResolution
[1]))
1039 * Write the raster header...
1042 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
1045 * PWG raster data is always network byte order with much of the page header
1049 cups_page_header2_t fh
; /* File page header */
1051 memset(&fh
, 0, sizeof(fh
));
1052 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
1053 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
1054 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
1055 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
1056 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
1057 sizeof(fh
.cupsRenderingIntent
));
1058 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
1059 sizeof(fh
.cupsPageSizeName
));
1061 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
1062 fh
.Duplex
= htonl(r
->header
.Duplex
);
1063 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
1064 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
1065 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
1066 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
1067 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
1068 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
1069 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
1070 fh
.Jog
= htonl(r
->header
.Jog
);
1071 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
1072 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
1073 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
1074 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
1075 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
1076 fh
.Orientation
= htonl(r
->header
.Orientation
);
1077 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
1078 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
1079 fh
.Tumble
= htonl(r
->header
.Tumble
);
1080 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
1081 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
1082 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
1083 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
1084 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
1085 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
1086 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
1087 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
1088 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
1089 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
1090 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
1091 fh
.cupsInteger
[3] = htonl((unsigned)(r
->header
.cupsImagingBBox
[0] * r
->header
.HWResolution
[0] / 72.0));
1092 fh
.cupsInteger
[4] = htonl((unsigned)(r
->header
.cupsImagingBBox
[1] * r
->header
.HWResolution
[1] / 72.0));
1093 fh
.cupsInteger
[5] = htonl((unsigned)(r
->header
.cupsImagingBBox
[2] * r
->header
.HWResolution
[0] / 72.0));
1094 fh
.cupsInteger
[6] = htonl((unsigned)(r
->header
.cupsImagingBBox
[3] * r
->header
.HWResolution
[1] / 72.0));
1095 fh
.cupsInteger
[7] = htonl(0xffffff);
1097 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
1099 else if (r
->mode
== CUPS_RASTER_WRITE_APPLE
)
1102 * Raw raster data is always network byte order with most of the page header
1106 int i
; /* Looping var */
1107 unsigned char appleheader
[32];/* Raw page header */
1108 unsigned height
= r
->header
.cupsHeight
* r
->rowheight
;
1109 /* Computed page height */
1111 if (r
->apple_page_count
== 0xffffffffU
)
1114 * Write raw page count from raster page header...
1117 r
->apple_page_count
= r
->header
.cupsInteger
[0];
1119 appleheader
[0] = 'A';
1120 appleheader
[1] = 'S';
1121 appleheader
[2] = 'T';
1123 appleheader
[4] = (unsigned char)(r
->apple_page_count
>> 24);
1124 appleheader
[5] = (unsigned char)(r
->apple_page_count
>> 16);
1125 appleheader
[6] = (unsigned char)(r
->apple_page_count
>> 8);
1126 appleheader
[7] = (unsigned char)(r
->apple_page_count
);
1128 if (cups_raster_io(r
, appleheader
, 8) != 8)
1132 memset(appleheader
, 0, sizeof(appleheader
));
1134 appleheader
[0] = (unsigned char)r
->header
.cupsBitsPerPixel
;
1135 appleheader
[1] = r
->header
.cupsColorSpace
== CUPS_CSPACE_SRGB
? 1 :
1136 r
->header
.cupsColorSpace
== CUPS_CSPACE_CIELab
? 2 :
1137 r
->header
.cupsColorSpace
== CUPS_CSPACE_ADOBERGB
? 3 :
1138 r
->header
.cupsColorSpace
== CUPS_CSPACE_W
? 4 :
1139 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGB
? 5 :
1140 r
->header
.cupsColorSpace
== CUPS_CSPACE_CMYK
? 6 : 0;
1141 appleheader
[2] = r
->header
.Duplex
? (r
->header
.Tumble
? 2 : 3) : 1;
1142 appleheader
[3] = (unsigned char)(r
->header
.cupsInteger
[CUPS_RASTER_PWG_PrintQuality
]);
1143 appleheader
[5] = (unsigned char)(r
->header
.MediaPosition
);
1144 appleheader
[12] = (unsigned char)(r
->header
.cupsWidth
>> 24);
1145 appleheader
[13] = (unsigned char)(r
->header
.cupsWidth
>> 16);
1146 appleheader
[14] = (unsigned char)(r
->header
.cupsWidth
>> 8);
1147 appleheader
[15] = (unsigned char)(r
->header
.cupsWidth
);
1148 appleheader
[16] = (unsigned char)(height
>> 24);
1149 appleheader
[17] = (unsigned char)(height
>> 16);
1150 appleheader
[18] = (unsigned char)(height
>> 8);
1151 appleheader
[19] = (unsigned char)(height
);
1152 appleheader
[20] = (unsigned char)(r
->header
.HWResolution
[0] >> 24);
1153 appleheader
[21] = (unsigned char)(r
->header
.HWResolution
[0] >> 16);
1154 appleheader
[22] = (unsigned char)(r
->header
.HWResolution
[0] >> 8);
1155 appleheader
[23] = (unsigned char)(r
->header
.HWResolution
[0]);
1157 for (i
= 0; i
< (int)(sizeof(apple_media_types
) / sizeof(apple_media_types
[0])); i
++)
1159 if (!strcmp(r
->header
.MediaType
, apple_media_types
[i
]))
1161 appleheader
[4] = (unsigned char)i
;
1166 return (cups_raster_io(r
, appleheader
, sizeof(appleheader
)) == sizeof(appleheader
));
1169 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
1170 == sizeof(r
->header
));
1175 * '_cupsRasterWritePixels()' - Write raster pixels.
1177 * For best performance, filters should write one or more whole lines.
1178 * The "cupsBytesPerLine" value from the page header can be used to allocate
1179 * the line buffer and as the number of bytes to write.
1182 unsigned /* O - Number of bytes written */
1183 _cupsRasterWritePixels(
1184 cups_raster_t
*r
, /* I - Raster stream */
1185 unsigned char *p
, /* I - Bytes to write */
1186 unsigned len
) /* I - Number of bytes to write */
1188 ssize_t bytes
; /* Bytes read */
1189 unsigned remaining
; /* Bytes remaining */
1192 DEBUG_printf(("_cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u", (void *)r
, (void *)p
, len
, r
->remaining
));
1194 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
|| r
->remaining
== 0)
1200 * Without compression, just write the raster data raw unless the data needs
1204 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
1207 (r
->header
.cupsBitsPerColor
== 16 ||
1208 r
->header
.cupsBitsPerPixel
== 12 ||
1209 r
->header
.cupsBitsPerPixel
== 16))
1211 unsigned char *bufptr
; /* Pointer into write buffer */
1214 * Allocate a write buffer as needed...
1217 if ((size_t)len
> r
->bufsize
)
1220 bufptr
= realloc(r
->buffer
, len
);
1222 bufptr
= malloc(len
);
1232 * Byte swap the pixels and write them...
1235 cups_swap_copy(r
->buffer
, p
, len
);
1237 bytes
= cups_raster_io(r
, r
->buffer
, len
);
1240 bytes
= cups_raster_io(r
, p
, len
);
1242 if (bytes
< (ssize_t
)len
)
1249 * Otherwise, compress each line...
1252 for (remaining
= len
; remaining
> 0; remaining
-= (unsigned)bytes
, p
+= bytes
)
1255 * Figure out the number of remaining bytes on the current line...
1258 if ((bytes
= (ssize_t
)remaining
) > (ssize_t
)(r
->pend
- r
->pcurrent
))
1259 bytes
= (ssize_t
)(r
->pend
- r
->pcurrent
);
1264 * Check to see if this line is the same as the previous line...
1267 if (memcmp(p
, r
->pcurrent
, (size_t)bytes
))
1269 if (cups_raster_write(r
, r
->pixels
) <= 0)
1277 * Mark more bytes as the same...
1280 r
->pcurrent
+= bytes
;
1282 if (r
->pcurrent
>= r
->pend
)
1285 * Increase the repeat count...
1288 r
->count
+= r
->rowheight
;
1289 r
->pcurrent
= r
->pixels
;
1292 * Flush out this line if it is the last one...
1297 if (r
->remaining
== 0)
1299 if (cups_raster_write(r
, r
->pixels
) <= 0)
1304 else if (r
->count
> (256 - r
->rowheight
))
1306 if (cups_raster_write(r
, r
->pixels
) <= 0)
1320 * Copy the raster data to the buffer...
1323 memcpy(r
->pcurrent
, p
, (size_t)bytes
);
1325 r
->pcurrent
+= bytes
;
1327 if (r
->pcurrent
>= r
->pend
)
1330 * Increase the repeat count...
1333 r
->count
+= r
->rowheight
;
1334 r
->pcurrent
= r
->pixels
;
1337 * Flush out this line if it is the last one...
1342 if (r
->remaining
== 0)
1344 if (cups_raster_write(r
, r
->pixels
) <= 0)
1356 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
1359 static ssize_t
/* O - Bytes read/write or -1 */
1360 cups_raster_io(cups_raster_t
*r
, /* I - Raster stream */
1361 unsigned char *buf
, /* I - Buffer for read/write */
1362 size_t bytes
) /* I - Number of bytes to read/write */
1364 ssize_t count
, /* Number of bytes read/written */
1365 total
; /* Total bytes read/written */
1368 DEBUG_printf(("5cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT
")", (void *)r
, (void *)buf
, CUPS_LLCAST bytes
));
1370 for (total
= 0; total
< (ssize_t
)bytes
; total
+= count
, buf
+= count
)
1372 count
= (*r
->iocb
)(r
->ctx
, buf
, bytes
- (size_t)total
);
1374 DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count
, (int)total
));
1378 // DEBUG_puts("6cups_raster_io: Returning 0.");
1383 DEBUG_puts("6cups_raster_io: Returning -1 on error.");
1388 r
->iocount
+= (size_t)count
;
1392 DEBUG_printf(("6cups_raster_io: iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1393 DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT
".", CUPS_LLCAST total
));
1400 * 'cups_raster_read()' - Read through the raster buffer.
1403 static ssize_t
/* O - Number of bytes read */
1404 cups_raster_read(cups_raster_t
*r
, /* I - Raster stream */
1405 unsigned char *buf
, /* I - Buffer */
1406 size_t bytes
) /* I - Number of bytes to read */
1408 ssize_t count
, /* Number of bytes read */
1409 remaining
, /* Remaining bytes in buffer */
1410 total
; /* Total bytes read */
1413 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
)));
1416 return (cups_raster_io(r
, buf
, bytes
));
1419 * Allocate a read buffer as needed...
1422 count
= (ssize_t
)(2 * r
->header
.cupsBytesPerLine
);
1426 if ((size_t)count
> r
->bufsize
)
1428 ssize_t offset
= r
->bufptr
- r
->buffer
;
1429 /* Offset to current start of buffer */
1430 ssize_t end
= r
->bufend
- r
->buffer
;/* Offset to current end of buffer */
1431 unsigned char *rptr
; /* Pointer in read buffer */
1434 rptr
= realloc(r
->buffer
, (size_t)count
);
1436 rptr
= malloc((size_t)count
);
1442 r
->bufptr
= rptr
+ offset
;
1443 r
->bufend
= rptr
+ end
;
1444 r
->bufsize
= (size_t)count
;
1448 * Loop until we have read everything...
1451 for (total
= 0, remaining
= (int)(r
->bufend
- r
->bufptr
);
1452 total
< (ssize_t
)bytes
;
1453 total
+= count
, buf
+= count
)
1455 count
= (ssize_t
)bytes
- total
;
1457 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
));
1464 * Read into the raster buffer and then copy...
1468 r
->iostart
+= (size_t)(r
->bufend
- r
->buffer
);
1471 remaining
= (*r
->iocb
)(r
->ctx
, r
->buffer
, r
->bufsize
);
1475 r
->bufptr
= r
->buffer
;
1476 r
->bufend
= r
->buffer
+ remaining
;
1479 r
->iocount
+= (size_t)remaining
;
1485 * Read directly into "buf"...
1488 count
= (*r
->iocb
)(r
->ctx
, buf
, (size_t)count
);
1494 r
->iostart
+= (size_t)count
;
1495 r
->iocount
+= (size_t)count
;
1503 * Copy bytes from raster buffer to "buf"...
1506 if (count
> remaining
)
1515 *buf
= *(r
->bufptr
)++;
1518 else if (count
< 128)
1521 * Copy up to 127 bytes without using memcpy(); this is
1522 * faster because it avoids an extra function call and is
1523 * often further optimized by the compiler...
1526 unsigned char *bufptr
; /* Temporary buffer pointer */
1530 for (bufptr
= r
->bufptr
; count
> 0; count
--, total
++)
1538 * Use memcpy() for a large read...
1541 memcpy(buf
, r
->bufptr
, (size_t)count
);
1547 DEBUG_printf(("5cups_raster_read: Returning %ld", (long)total
));
1554 * 'cups_raster_update()' - Update the raster header and row count for the
1558 static int /* O - 1 on success, 0 on failure */
1559 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
1561 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
1562 r
->header
.cupsNumColors
== 0)
1565 * Set the "cupsNumColors" field according to the colorspace...
1568 switch (r
->header
.cupsColorSpace
)
1570 case CUPS_CSPACE_W
:
1571 case CUPS_CSPACE_K
:
1572 case CUPS_CSPACE_WHITE
:
1573 case CUPS_CSPACE_GOLD
:
1574 case CUPS_CSPACE_SILVER
:
1575 case CUPS_CSPACE_SW
:
1576 r
->header
.cupsNumColors
= 1;
1579 case CUPS_CSPACE_RGB
:
1580 case CUPS_CSPACE_CMY
:
1581 case CUPS_CSPACE_YMC
:
1582 case CUPS_CSPACE_CIEXYZ
:
1583 case CUPS_CSPACE_CIELab
:
1584 case CUPS_CSPACE_SRGB
:
1585 case CUPS_CSPACE_ADOBERGB
:
1586 case CUPS_CSPACE_ICC1
:
1587 case CUPS_CSPACE_ICC2
:
1588 case CUPS_CSPACE_ICC3
:
1589 case CUPS_CSPACE_ICC4
:
1590 case CUPS_CSPACE_ICC5
:
1591 case CUPS_CSPACE_ICC6
:
1592 case CUPS_CSPACE_ICC7
:
1593 case CUPS_CSPACE_ICC8
:
1594 case CUPS_CSPACE_ICC9
:
1595 case CUPS_CSPACE_ICCA
:
1596 case CUPS_CSPACE_ICCB
:
1597 case CUPS_CSPACE_ICCC
:
1598 case CUPS_CSPACE_ICCD
:
1599 case CUPS_CSPACE_ICCE
:
1600 case CUPS_CSPACE_ICCF
:
1601 r
->header
.cupsNumColors
= 3;
1604 case CUPS_CSPACE_RGBA
:
1605 case CUPS_CSPACE_RGBW
:
1606 case CUPS_CSPACE_CMYK
:
1607 case CUPS_CSPACE_YMCK
:
1608 case CUPS_CSPACE_KCMY
:
1609 case CUPS_CSPACE_GMCK
:
1610 case CUPS_CSPACE_GMCS
:
1611 r
->header
.cupsNumColors
= 4;
1614 case CUPS_CSPACE_KCMYcm
:
1615 if (r
->header
.cupsBitsPerPixel
< 8)
1616 r
->header
.cupsNumColors
= 6;
1618 r
->header
.cupsNumColors
= 4;
1621 case CUPS_CSPACE_DEVICE1
:
1622 case CUPS_CSPACE_DEVICE2
:
1623 case CUPS_CSPACE_DEVICE3
:
1624 case CUPS_CSPACE_DEVICE4
:
1625 case CUPS_CSPACE_DEVICE5
:
1626 case CUPS_CSPACE_DEVICE6
:
1627 case CUPS_CSPACE_DEVICE7
:
1628 case CUPS_CSPACE_DEVICE8
:
1629 case CUPS_CSPACE_DEVICE9
:
1630 case CUPS_CSPACE_DEVICEA
:
1631 case CUPS_CSPACE_DEVICEB
:
1632 case CUPS_CSPACE_DEVICEC
:
1633 case CUPS_CSPACE_DEVICED
:
1634 case CUPS_CSPACE_DEVICEE
:
1635 case CUPS_CSPACE_DEVICEF
:
1636 r
->header
.cupsNumColors
= r
->header
.cupsColorSpace
-
1637 CUPS_CSPACE_DEVICE1
+ 1;
1641 /* Unknown color space */
1647 * Set the number of bytes per pixel/color...
1650 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
1651 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
1653 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
1659 * Set the number of remaining rows...
1662 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
1663 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
1665 r
->remaining
= r
->header
.cupsHeight
;
1668 * Allocate the compression buffer...
1673 if (r
->pixels
!= NULL
)
1676 if ((r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1)) == NULL
)
1685 r
->pcurrent
= r
->pixels
;
1686 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
1695 * 'cups_raster_write()' - Write a row of compressed raster data...
1698 static ssize_t
/* O - Number of bytes written */
1700 cups_raster_t
*r
, /* I - Raster stream */
1701 const unsigned char *pixels
) /* I - Pixel data to write */
1703 const unsigned char *start
, /* Start of sequence */
1704 *ptr
, /* Current pointer in sequence */
1705 *pend
, /* End of raster buffer */
1706 *plast
; /* Pointer to last pixel */
1707 unsigned char *wptr
; /* Pointer into write buffer */
1708 unsigned bpp
, /* Bytes per pixel */
1710 _cups_copyfunc_t cf
; /* Copy function */
1713 DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)", (void *)r
, (void *)pixels
));
1716 * Determine whether we need to swap bytes...
1719 if (r
->swapped
&& (r
->header
.cupsBitsPerColor
== 16 || r
->header
.cupsBitsPerPixel
== 12 || r
->header
.cupsBitsPerPixel
== 16))
1721 DEBUG_puts("4cups_raster_write: Swapping bytes when writing.");
1722 cf
= (_cups_copyfunc_t
)cups_swap_copy
;
1725 cf
= (_cups_copyfunc_t
)memcpy
;
1728 * Allocate a write buffer as needed...
1731 count
= r
->header
.cupsBytesPerLine
* 2;
1735 if ((size_t)count
> r
->bufsize
)
1738 wptr
= realloc(r
->buffer
, count
);
1740 wptr
= malloc(count
);
1744 DEBUG_printf(("4cups_raster_write: Unable to allocate " CUPS_LLFMT
" bytes for raster buffer: %s", CUPS_LLCAST count
, strerror(errno
)));
1753 * Write the row repeat count...
1757 pend
= pixels
+ r
->header
.cupsBytesPerLine
;
1760 *wptr
++ = (unsigned char)(r
->count
- 1);
1763 * Write using a modified PackBits compression...
1766 for (ptr
= pixels
; ptr
< pend
;)
1774 * Encode a single pixel at the end...
1778 (*cf
)(wptr
, start
, bpp
);
1781 else if (!memcmp(start
, ptr
, bpp
))
1784 * Encode a sequence of repeating pixels...
1787 for (count
= 2; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1788 if (memcmp(ptr
, ptr
+ bpp
, bpp
))
1791 *wptr
++ = (unsigned char)(count
- 1);
1792 (*cf
)(wptr
, ptr
, bpp
);
1799 * Encode a sequence of non-repeating pixels...
1802 for (count
= 1; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1803 if (!memcmp(ptr
, ptr
+ bpp
, bpp
))
1806 if (ptr
>= plast
&& count
< 128)
1812 *wptr
++ = (unsigned char)(257 - count
);
1815 (*cf
)(wptr
, start
, count
);
1820 DEBUG_printf(("4cups_raster_write: Writing " CUPS_LLFMT
" bytes.", CUPS_LLCAST (wptr
- r
->buffer
)));
1822 return (cups_raster_io(r
, r
->buffer
, (size_t)(wptr
- r
->buffer
)));
1827 * 'cups_swap()' - Swap bytes in raster data...
1831 cups_swap(unsigned char *buf
, /* I - Buffer to swap */
1832 size_t bytes
) /* I - Number of bytes to swap */
1834 unsigned char even
, odd
; /* Temporary variables */
1853 * 'cups_swap_copy()' - Copy and swap bytes in raster data...
1858 unsigned char *dst
, /* I - Destination */
1859 const unsigned char *src
, /* I - Source */
1860 size_t bytes
) /* I - Number of bytes to swap */