4 * Raster file routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 by Easy Software Products.
8 * This file is part of the CUPS Imaging library.
10 * These coded instructions, statements, and computer programs are the
11 * property of Easy Software Products and are protected by Federal
12 * copyright law. Distribution and use rights are outlined in the file
13 * "LICENSE.txt" which should have been included with this file. If this
14 * file is missing or damaged please contact Easy Software Products
17 * Attn: CUPS Licensing Information
18 * Easy Software Products
19 * 44141 Airport View Drive, Suite 204
20 * Hollywood, Maryland 20636 USA
22 * Voice: (301) 373-9600
23 * EMail: cups-info@cups.org
24 * WWW: http://www.cups.org
26 * This code and any derivative of it may be used and distributed
27 * freely under the terms of the GNU General Public License when
28 * used with GNU/GPL Ghostscript or its derivatives. Use of the
29 * code (or any derivative of it) with software other than GNU/GPL
30 * GhostScript (or its derivatives) is governed by the CUPS license
33 * This file is subject to the Apple OS-Developed Software exception.
37 * cupsRasterClose() - Close a raster stream.
38 * cupsRasterOpen() - Open a raster stream.
39 * cupsRasterReadHeader() - Read a raster page header and store it in a
40 * V1 page header structure.
41 * cupsRasterReadHeader2() - Read a raster page header and store it in a
42 * V2 page header structure.
43 * cupsRasterReadPixels() - Read raster pixels.
44 * cupsRasterWriteHeader() - Write a raster page header from a V1 page
46 * cupsRasterWriteHeader2() - Write a raster page header from a V2 page
48 * cupsRasterWritePixels() - Write raster pixels.
49 * cups_raster_read() - Read through the raster buffer.
50 * cups_raster_read_header() - Read a raster page header.
51 * cups_raster_update() - Update the raster header and row count for the
53 * cups_raster_write() - Write a row of raster data...
54 * cups_read() - Read bytes from a file.
55 * cups_swap() - Swap bytes in raster data...
56 * cups_write() - Write bytes to a file.
60 * Include necessary headers...
64 #include <cups/debug.h>
67 #include <cups/string.h>
69 #if defined(WIN32) || defined(__EMX__)
73 #endif /* WIN32 || __EMX__ */
77 * Private structures...
80 struct _cups_raster_s
/**** Raster stream data ****/
82 unsigned sync
; /* Sync word from start of stream */
83 int fd
; /* File descriptor */
84 cups_mode_t mode
; /* Read/write mode */
85 cups_page_header2_t header
; /* Raster header for current page */
86 int count
, /* Current row run-length count */
87 remaining
, /* Remaining rows in page image */
88 bpp
; /* Bytes per pixel/color */
89 unsigned char *pixels
, /* Pixels for current row */
90 *pend
, /* End of pixel buffer */
91 *pcurrent
; /* Current byte in pixel buffer */
92 int compressed
, /* Non-zero if data is compressed */
93 swapped
; /* Non-zero if data is byte-swapped */
94 unsigned char *buffer
, /* Read/write buffer */
95 *bufptr
, /* Current (read) position in buffer */
96 *bufend
; /* End of current (read) buffer */
97 int bufsize
; /* Buffer size */
105 static unsigned cups_raster_read_header(cups_raster_t
*r
);
106 static int cups_raster_read(cups_raster_t
*r
, unsigned char *buf
,
108 static void cups_raster_update(cups_raster_t
*r
);
109 static int cups_raster_write(cups_raster_t
*r
, const unsigned char *pixels
);
110 static int cups_read(int fd
, unsigned char *buf
, int bytes
);
111 static void cups_swap(unsigned char *buf
, int bytes
);
112 static int cups_write(int fd
, const unsigned char *buf
, int bytes
);
116 * 'cupsRasterClose()' - Close a raster stream.
120 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
136 * 'cupsRasterOpen()' - Open a raster stream.
139 cups_raster_t
* /* O - New stream */
140 cupsRasterOpen(int fd
, /* I - File descriptor */
141 cups_mode_t mode
) /* I - Mode */
143 cups_raster_t
*r
; /* New stream */
146 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
150 r
->mode
= mode
== CUPS_RASTER_WRITE_COMPRESSED
? CUPS_RASTER_WRITE
: mode
;
152 if (mode
== CUPS_RASTER_READ
)
155 * Open for read - get sync word...
158 if (!cups_read(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)))
164 if (r
->sync
!= CUPS_RASTER_SYNC
&&
165 r
->sync
!= CUPS_RASTER_REVSYNC
&&
166 r
->sync
!= CUPS_RASTER_SYNCv1
&&
167 r
->sync
!= CUPS_RASTER_REVSYNCv1
&&
168 r
->sync
!= CUPS_RASTER_SYNCv2
&&
169 r
->sync
!= CUPS_RASTER_REVSYNCv2
)
175 if (r
->sync
== CUPS_RASTER_SYNCv2
||
176 r
->sync
== CUPS_RASTER_REVSYNCv2
)
179 if (r
->sync
== CUPS_RASTER_REVSYNC
||
180 r
->sync
== CUPS_RASTER_REVSYNCv1
||
181 r
->sync
== CUPS_RASTER_REVSYNCv2
)
187 * Open for write - put sync word...
190 if (mode
== CUPS_RASTER_WRITE_COMPRESSED
)
193 r
->sync
= CUPS_RASTER_SYNCv2
;
196 r
->sync
= CUPS_RASTER_SYNC
;
198 if (cups_write(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
))
211 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
212 * V1 page header structure.
215 unsigned /* O - 1 on success, 0 on fail */
216 cupsRasterReadHeader(
217 cups_raster_t
*r
, /* I - Raster stream */
218 cups_page_header_t
*h
) /* I - Pointer to header data */
221 * Get the raster header...
224 if (!cups_raster_read_header(r
))
228 * Copy the header to the user-supplied buffer...
231 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
238 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
239 * V2 page header structure.
244 unsigned /* O - 1 on success, 0 on fail */
245 cupsRasterReadHeader2(
246 cups_raster_t
*r
, /* I - Raster stream */
247 cups_page_header2_t
*h
) /* I - Pointer to header data */
250 * Get the raster header...
253 if (!cups_raster_read_header(r
))
257 * Copy the header to the user-supplied buffer...
260 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
267 * 'cupsRasterReadPixels()' - Read raster pixels.
270 unsigned /* O - Number of bytes read */
271 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
272 unsigned char *p
, /* I - Pointer to pixel buffer */
273 unsigned len
) /* I - Number of bytes to read */
275 int bytes
; /* Bytes read */
276 unsigned cupsBytesPerLine
; /* cupsBytesPerLine value */
277 unsigned remaining
; /* Bytes remaining */
278 unsigned char *ptr
, /* Pointer to read buffer */
279 byte
, /* Byte from file */
280 *temp
; /* Pointer into buffer */
281 int count
; /* Repetition count */
284 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0)
290 * Read without compression...
293 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
295 if (!cups_read(r
->fd
, p
, len
))
299 * Swap bytes as needed...
302 if ((r
->header
.cupsBitsPerColor
== 16 ||
303 r
->header
.cupsBitsPerPixel
== 12 ||
304 r
->header
.cupsBitsPerPixel
== 16) &&
316 * Read compressed data...
320 cupsBytesPerLine
= r
->header
.cupsBytesPerLine
;
322 while (remaining
> 0 && r
->remaining
> 0)
327 * Need to read a new row...
330 if (remaining
== cupsBytesPerLine
)
336 * Read using a modified TIFF "packbits" compression...
339 if (!cups_raster_read(r
, &byte
, 1))
348 bytes
= cupsBytesPerLine
;
353 * Get a new repeat count...
356 if (!cups_raster_read(r
, &byte
, 1))
362 * Copy N literal pixels...
365 count
= (257 - byte
) * r
->bpp
;
370 if (!cups_raster_read(r
, temp
, count
))
379 * Repeat the next N bytes...
382 count
= (byte
+ 1) * r
->bpp
;
391 if (!cups_raster_read(r
, temp
, r
->bpp
))
399 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
407 * Swap bytes as needed...
410 if ((r
->header
.cupsBitsPerColor
== 16 ||
411 r
->header
.cupsBitsPerPixel
== 12 ||
412 r
->header
.cupsBitsPerPixel
== 16) &&
414 cups_swap(ptr
, bytes
);
420 if (remaining
>= cupsBytesPerLine
)
422 bytes
= cupsBytesPerLine
;
423 r
->pcurrent
= r
->pixels
;
430 r
->pcurrent
= r
->pixels
+ bytes
;
434 * Copy data as needed...
438 memcpy(p
, ptr
, bytes
);
443 * Copy fragment from buffer...
446 if ((bytes
= r
->pend
- r
->pcurrent
) > remaining
)
449 memcpy(p
, r
->pcurrent
, bytes
);
450 r
->pcurrent
+= bytes
;
452 if (r
->pcurrent
>= r
->pend
)
454 r
->pcurrent
= r
->pixels
;
469 * 'cupsRasterWriteHeader()' - Write a raster page header from a V1 page
473 unsigned /* O - 1 on success, 0 on failure */
474 cupsRasterWriteHeader(
475 cups_raster_t
*r
, /* I - Raster stream */
476 cups_page_header_t
*h
) /* I - Raster page header */
478 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
482 * Make a copy of the header, and compute the number of raster
483 * lines in the page image...
486 memset(&(r
->header
), 0, sizeof(r
->header
));
487 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
489 cups_raster_update(r
);
492 * Write the raster header...
495 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
501 * 'cupsRasterWriteHeader2()' - Write a raster page header from a V2 page
507 unsigned /* O - 1 on success, 0 on failure */
508 cupsRasterWriteHeader2(
509 cups_raster_t
*r
, /* I - Raster stream */
510 cups_page_header2_t
*h
) /* I - Raster page header */
512 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
516 * Make a copy of the header, and compute the number of raster
517 * lines in the page image...
520 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
522 cups_raster_update(r
);
525 * Write the raster header...
528 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
534 * 'cupsRasterWritePixels()' - Write raster pixels.
537 unsigned /* O - Number of bytes written */
538 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
539 unsigned char *p
, /* I - Bytes to write */
540 unsigned len
)/* I - Number of bytes to write */
542 int bytes
; /* Bytes read */
543 unsigned remaining
; /* Bytes remaining */
547 fprintf(stderr
, "cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
548 r
, p
, len
, r
->remaining
);
551 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
|| r
->remaining
== 0)
557 * Without compression, just write the raster data raw...
560 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
562 return (cups_write(r
->fd
, p
, len
));
566 * Otherwise, compress each line...
569 for (remaining
= len
; remaining
> 0; remaining
-= bytes
, p
+= bytes
)
572 * Figure out the number of remaining bytes on the current line...
575 if ((bytes
= remaining
) > (r
->pend
- r
->pcurrent
))
576 bytes
= r
->pend
- r
->pcurrent
;
581 * Check to see if this line is the same as the previous line...
584 if (memcmp(p
, r
->pcurrent
, bytes
))
586 if (!cups_raster_write(r
, r
->pixels
))
594 * Mark more bytes as the same...
597 r
->pcurrent
+= bytes
;
599 if (r
->pcurrent
>= r
->pend
)
602 * Increase the repeat count...
606 r
->pcurrent
= r
->pixels
;
609 * Flush out this line if it is the last one...
614 if (r
->remaining
== 0)
615 return (cups_raster_write(r
, r
->pixels
));
616 else if (r
->count
== 256)
618 if (cups_raster_write(r
, r
->pixels
) == 0)
632 * Copy the raster data to the buffer...
635 memcpy(r
->pcurrent
, p
, bytes
);
637 r
->pcurrent
+= bytes
;
639 if (r
->pcurrent
>= r
->pend
)
642 * Increase the repeat count...
646 r
->pcurrent
= r
->pixels
;
649 * Flush out this line if it is the last one...
654 if (r
->remaining
== 0)
655 return (cups_raster_write(r
, r
->pixels
));
665 * 'cups_raster_read_header()' - Read a raster page header.
668 static unsigned /* O - 1 on success, 0 on fail */
669 cups_raster_read_header(
670 cups_raster_t
*r
) /* I - Raster stream */
672 int len
; /* Number of words to swap */
673 union swap_s
/* Swapping structure */
680 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
684 * Get the length of the raster header...
687 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
688 len
= sizeof(cups_page_header_t
);
690 len
= sizeof(cups_page_header2_t
);
696 memset(&(r
->header
), 0, sizeof(r
->header
));
698 if (cups_raster_read(r
, (unsigned char *)&(r
->header
), len
) < len
)
702 * Swap bytes as needed...
706 for (len
= 81, s
= (union swap_s
*)&(r
->header
.AdvanceDistance
);
709 s
->v
= (((((s
->b
[3] << 8) | s
->b
[2]) << 8) | s
->b
[1]) << 8) | s
->b
[0];
712 * Update the header and row count...
715 cups_raster_update(r
);
722 * 'cups_raster_read()' - Read through the raster buffer.
725 static int /* O - Number of bytes read */
726 cups_raster_read(cups_raster_t
*r
, /* I - Raster stream */
727 unsigned char *buf
, /* I - Buffer */
728 int bytes
) /* I - Number of bytes to read */
730 int count
, /* Number of bytes read */
731 remaining
, /* Remaining bytes in buffer */
732 total
; /* Total bytes read */
735 DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=%d)\n", r
, buf
, bytes
));
738 return (cups_read(r
->fd
, buf
, bytes
));
741 * Allocate a read buffer as needed...
744 count
= 2 * r
->header
.cupsBytesPerLine
;
746 if (count
> r
->bufsize
)
748 int offset
= r
->bufptr
- r
->buffer
; /* Offset to current start of buffer */
749 int end
= r
->bufend
- r
->buffer
; /* Offset to current end of buffer */
750 unsigned char *rptr
; /* Pointer in read buffer */
753 rptr
= realloc(r
->buffer
, count
);
755 rptr
= malloc(count
);
761 r
->bufptr
= rptr
+ offset
;
762 r
->bufend
= rptr
+ end
;
767 * Loop until we have read everything...
770 for (total
= 0, remaining
= r
->bufend
- r
->bufptr
;
772 total
+= count
, buf
+= count
)
774 count
= bytes
- total
;
776 DEBUG_printf(("count=%d, remaining=%d, buf=%p, bufptr=%p, bufend=%p...\n",
777 count
, remaining
, buf
, r
->bufptr
, r
->bufend
));
784 * Read into the raster buffer and then copy...
787 remaining
= cups_read(r
->fd
, r
->buffer
, r
->bufsize
);
791 r
->bufptr
= r
->buffer
;
792 r
->bufend
= r
->buffer
+ remaining
;
797 * Read directly into "buf"...
800 count
= cups_read(r
->fd
, buf
, count
);
810 * Copy bytes from raster buffer to "buf"...
813 if (count
> remaining
)
822 *buf
= *(r
->bufptr
)++;
825 else if (count
< 128)
828 * Copy up to 127 bytes without using memcpy(); this is
829 * faster because it avoids an extra function call and is
830 * often further optimized by the compiler...
833 unsigned char *bufptr
; /* Temporary buffer pointer */
838 for (bufptr
= r
->bufptr
; count
> 0; count
--, total
++)
846 * Use memcpy() for a large read...
849 memcpy(buf
, r
->bufptr
, count
);
860 * 'cups_raster_update()' - Update the raster header and row count for the
865 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
867 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
868 r
->header
.cupsNumColors
== 0)
871 * Set the "cupsNumColors" field according to the colorspace...
874 switch (r
->header
.cupsColorSpace
)
878 case CUPS_CSPACE_WHITE
:
879 case CUPS_CSPACE_GOLD
:
880 case CUPS_CSPACE_SILVER
:
881 r
->header
.cupsNumColors
= 1;
884 case CUPS_CSPACE_RGB
:
885 case CUPS_CSPACE_CMY
:
886 case CUPS_CSPACE_YMC
:
887 case CUPS_CSPACE_CIEXYZ
:
888 case CUPS_CSPACE_CIELab
:
889 case CUPS_CSPACE_ICC1
:
890 case CUPS_CSPACE_ICC2
:
891 case CUPS_CSPACE_ICC3
:
892 case CUPS_CSPACE_ICC4
:
893 case CUPS_CSPACE_ICC5
:
894 case CUPS_CSPACE_ICC6
:
895 case CUPS_CSPACE_ICC7
:
896 case CUPS_CSPACE_ICC8
:
897 case CUPS_CSPACE_ICC9
:
898 case CUPS_CSPACE_ICCA
:
899 case CUPS_CSPACE_ICCB
:
900 case CUPS_CSPACE_ICCC
:
901 case CUPS_CSPACE_ICCD
:
902 case CUPS_CSPACE_ICCE
:
903 case CUPS_CSPACE_ICCF
:
904 r
->header
.cupsNumColors
= 3;
907 case CUPS_CSPACE_RGBA
:
908 case CUPS_CSPACE_RGBW
:
909 case CUPS_CSPACE_CMYK
:
910 case CUPS_CSPACE_YMCK
:
911 case CUPS_CSPACE_KCMY
:
912 case CUPS_CSPACE_GMCK
:
913 case CUPS_CSPACE_GMCS
:
914 r
->header
.cupsNumColors
= 4;
917 case CUPS_CSPACE_KCMYcm
:
918 if (r
->header
.cupsBitsPerPixel
< 8)
919 r
->header
.cupsNumColors
= 6;
921 r
->header
.cupsNumColors
= 4;
927 * Set the number of bytes per pixel/color...
930 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
931 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
933 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
936 * Set the number of remaining rows...
939 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
940 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
942 r
->remaining
= r
->header
.cupsHeight
;
945 * Allocate the compression buffer...
950 if (r
->pixels
!= NULL
)
953 r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1);
954 r
->pcurrent
= r
->pixels
;
955 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
962 * 'cups_raster_write()' - Write a row of compressed raster data...
965 static int /* O - Number of bytes written */
967 cups_raster_t
*r
, /* I - Raster stream */
968 const unsigned char *pixels
) /* I - Pixel data to write */
970 const unsigned char *start
, /* Start of sequence */
971 *ptr
, /* Current pointer in sequence */
972 *pend
, /* End of raster buffer */
973 *plast
; /* Pointer to last pixel */
974 unsigned char *wptr
; /* Pointer into write buffer */
975 int bpp
, /* Bytes per pixel */
977 maxrun
; /* Maximum run of 128 * bpp */
981 fprintf(stderr
, "cups_raster_write(r=%p, pixels=%p)\n", r
, pixels
);
985 * Allocate a write buffer as needed...
988 count
= r
->header
.cupsBytesPerLine
* 2;
989 if (count
> r
->bufsize
)
992 wptr
= realloc(r
->buffer
, count
);
994 wptr
= malloc(count
);
1004 * Write the row repeat count...
1008 pend
= pixels
+ r
->header
.cupsBytesPerLine
;
1011 *wptr
++ = r
->count
- 1;
1015 * Write using a modified TIFF "packbits" compression...
1018 for (ptr
= pixels
; ptr
< pend
;)
1026 * Encode a single pixel at the end...
1030 for (count
= bpp
; count
> 0; count
--)
1033 else if (!memcmp(start
, ptr
, bpp
))
1036 * Encode a sequence of repeating pixels...
1039 for (count
= 2; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1040 if (memcmp(ptr
, ptr
+ bpp
, bpp
))
1043 *wptr
++ = count
- 1;
1044 for (count
= bpp
; count
> 0; count
--)
1050 * Encode a sequence of non-repeating pixels...
1053 for (count
= 1; count
< 127 && ptr
< plast
; count
++, ptr
+= bpp
)
1054 if (!memcmp(ptr
, ptr
+ bpp
, bpp
))
1057 if (ptr
>= plast
&& count
< 128)
1063 *wptr
++ = 257 - count
;
1066 memcpy(wptr
, start
, count
);
1071 return (cups_write(r
->fd
, r
->buffer
, wptr
- r
->buffer
));
1076 * 'cups_read()' - Read bytes from a file.
1079 static int /* O - Bytes read or -1 */
1080 cups_read(int fd
, /* I - File descriptor */
1081 unsigned char *buf
, /* I - Buffer for read */
1082 int bytes
) /* I - Number of bytes to read */
1084 int count
, /* Number of bytes read */
1085 total
; /* Total bytes read */
1088 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
1090 count
= read(fd
, buf
, bytes
- total
);
1108 * 'cups_swap()' - Swap bytes in raster data...
1112 cups_swap(unsigned char *buf
, /* I - Buffer to swap */
1113 int bytes
) /* I - Number of bytes to swap */
1115 unsigned char even
, odd
; /* Temporary variables */
1134 * 'cups_write()' - Write bytes to a file.
1137 static int /* O - Bytes written or -1 */
1138 cups_write(int fd
, /* I - File descriptor */
1139 const unsigned char *buf
, /* I - Bytes to write */
1140 int bytes
) /* I - Number of bytes to write */
1142 int count
, /* Number of bytes written */
1143 total
; /* Total bytes written */
1146 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
1148 count
= write(fd
, buf
, bytes
- total
);