2 * "$Id: raster.c 6584 2007-06-21 17:22:26Z mike $"
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 file is subject to the Apple OS-Developed Software exception.
30 * cupsRasterClose() - Close a raster stream.
31 * cupsRasterOpen() - Open a raster stream.
32 * cupsRasterReadHeader() - Read a raster page header and store it in a
33 * V1 page header structure.
34 * cupsRasterReadHeader2() - Read a raster page header and store it in a
35 * V2 page header structure.
36 * cupsRasterReadPixels() - Read raster pixels.
37 * cupsRasterWriteHeader() - Write a raster page header from a V1 page
39 * cupsRasterWriteHeader2() - Write a raster page header from a V2 page
41 * cupsRasterWritePixels() - Write raster pixels.
42 * cups_raster_read() - Read through the raster buffer.
43 * cups_raster_read_header() - Read a raster page header.
44 * cups_raster_update() - Update the raster header and row count for the
46 * cups_raster_write() - Write a row of raster data...
47 * cups_read() - Read bytes from a file.
48 * cups_swap() - Swap bytes in raster data...
49 * cups_write() - Write bytes to a file.
53 * Include necessary headers...
56 #include "image-private.h"
57 #include <cups/debug.h>
60 #include <cups/string.h>
62 #if defined(WIN32) || defined(__EMX__)
66 #endif /* WIN32 || __EMX__ */
70 * Private structures...
73 struct _cups_raster_s
/**** Raster stream data ****/
75 unsigned sync
; /* Sync word from start of stream */
76 int fd
; /* File descriptor */
77 cups_mode_t mode
; /* Read/write mode */
78 cups_page_header2_t header
; /* Raster header for current page */
79 int count
, /* Current row run-length count */
80 remaining
, /* Remaining rows in page image */
81 bpp
; /* Bytes per pixel/color */
82 unsigned char *pixels
, /* Pixels for current row */
83 *pend
, /* End of pixel buffer */
84 *pcurrent
; /* Current byte in pixel buffer */
85 int compressed
, /* Non-zero if data is compressed */
86 swapped
; /* Non-zero if data is byte-swapped */
87 unsigned char *buffer
, /* Read/write buffer */
88 *bufptr
, /* Current (read) position in buffer */
89 *bufend
; /* End of current (read) buffer */
90 int bufsize
; /* Buffer size */
98 static unsigned cups_raster_read_header(cups_raster_t
*r
);
99 static int cups_raster_read(cups_raster_t
*r
, unsigned char *buf
,
101 static void cups_raster_update(cups_raster_t
*r
);
102 static int cups_raster_write(cups_raster_t
*r
, const unsigned char *pixels
);
103 static int cups_read(int fd
, unsigned char *buf
, int bytes
);
104 static void cups_swap(unsigned char *buf
, int bytes
);
105 static int cups_write(int fd
, const unsigned char *buf
, int bytes
);
109 * 'cupsRasterClose()' - Close a raster stream.
113 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
129 * 'cupsRasterOpen()' - Open a raster stream.
132 cups_raster_t
* /* O - New stream */
133 cupsRasterOpen(int fd
, /* I - File descriptor */
134 cups_mode_t mode
) /* I - Mode */
136 cups_raster_t
*r
; /* New stream */
139 _cupsRasterClearError();
141 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
143 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
149 r
->mode
= mode
== CUPS_RASTER_WRITE_COMPRESSED
? CUPS_RASTER_WRITE
: mode
;
151 if (mode
== CUPS_RASTER_READ
)
154 * Open for read - get sync word...
157 if (!cups_read(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)))
159 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
165 if (r
->sync
!= CUPS_RASTER_SYNC
&&
166 r
->sync
!= CUPS_RASTER_REVSYNC
&&
167 r
->sync
!= CUPS_RASTER_SYNCv1
&&
168 r
->sync
!= CUPS_RASTER_REVSYNCv1
&&
169 r
->sync
!= CUPS_RASTER_SYNCv2
&&
170 r
->sync
!= CUPS_RASTER_REVSYNCv2
)
172 _cupsRasterAddError("Unknown raster format %08x!\n", r
->sync
);
177 if (r
->sync
== CUPS_RASTER_SYNCv2
||
178 r
->sync
== CUPS_RASTER_REVSYNCv2
)
181 if (r
->sync
== CUPS_RASTER_REVSYNC
||
182 r
->sync
== CUPS_RASTER_REVSYNCv1
||
183 r
->sync
== CUPS_RASTER_REVSYNCv2
)
186 DEBUG_printf(("r->swapped=%d, r->sync=%08x\n", r
->swapped
, r
->sync
));
191 * Open for write - put sync word...
194 if (mode
== CUPS_RASTER_WRITE_COMPRESSED
)
197 r
->sync
= CUPS_RASTER_SYNCv2
;
200 r
->sync
= CUPS_RASTER_SYNC
;
202 if (cups_write(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
))
205 _cupsRasterAddError("Unable to write raster stream header: %s\n",
217 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
218 * V1 page header structure.
221 unsigned /* O - 1 on success, 0 on fail */
222 cupsRasterReadHeader(
223 cups_raster_t
*r
, /* I - Raster stream */
224 cups_page_header_t
*h
) /* I - Pointer to header data */
227 * Get the raster header...
230 if (!cups_raster_read_header(r
))
234 * Copy the header to the user-supplied buffer...
237 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
244 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
245 * V2 page header structure.
250 unsigned /* O - 1 on success, 0 on fail */
251 cupsRasterReadHeader2(
252 cups_raster_t
*r
, /* I - Raster stream */
253 cups_page_header2_t
*h
) /* I - Pointer to header data */
256 * Get the raster header...
259 if (!cups_raster_read_header(r
))
263 * Copy the header to the user-supplied buffer...
266 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
273 * 'cupsRasterReadPixels()' - Read raster pixels.
276 unsigned /* O - Number of bytes read */
277 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
278 unsigned char *p
, /* I - Pointer to pixel buffer */
279 unsigned len
) /* I - Number of bytes to read */
281 int bytes
; /* Bytes read */
282 unsigned cupsBytesPerLine
; /* cupsBytesPerLine value */
283 unsigned remaining
; /* Bytes remaining */
284 unsigned char *ptr
, /* Pointer to read buffer */
285 byte
, /* Byte from file */
286 *temp
; /* Pointer into buffer */
287 int count
; /* Repetition count */
290 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0)
296 * Read without compression...
299 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
301 if (!cups_read(r
->fd
, p
, len
))
305 * Swap bytes as needed...
308 if ((r
->header
.cupsBitsPerColor
== 16 ||
309 r
->header
.cupsBitsPerPixel
== 12 ||
310 r
->header
.cupsBitsPerPixel
== 16) &&
322 * Read compressed data...
326 cupsBytesPerLine
= r
->header
.cupsBytesPerLine
;
328 while (remaining
> 0 && r
->remaining
> 0)
333 * Need to read a new row...
336 if (remaining
== cupsBytesPerLine
)
342 * Read using a modified TIFF "packbits" compression...
345 if (!cups_raster_read(r
, &byte
, 1))
354 bytes
= cupsBytesPerLine
;
359 * Get a new repeat count...
362 if (!cups_raster_read(r
, &byte
, 1))
368 * Copy N literal pixels...
371 count
= (257 - byte
) * r
->bpp
;
376 if (!cups_raster_read(r
, temp
, count
))
385 * Repeat the next N bytes...
388 count
= (byte
+ 1) * r
->bpp
;
397 if (!cups_raster_read(r
, temp
, r
->bpp
))
405 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
413 * Swap bytes as needed...
416 if ((r
->header
.cupsBitsPerColor
== 16 ||
417 r
->header
.cupsBitsPerPixel
== 12 ||
418 r
->header
.cupsBitsPerPixel
== 16) &&
420 cups_swap(ptr
, bytes
);
426 if (remaining
>= cupsBytesPerLine
)
428 bytes
= cupsBytesPerLine
;
429 r
->pcurrent
= r
->pixels
;
436 r
->pcurrent
= r
->pixels
+ bytes
;
440 * Copy data as needed...
444 memcpy(p
, ptr
, bytes
);
449 * Copy fragment from buffer...
452 if ((bytes
= r
->pend
- r
->pcurrent
) > remaining
)
455 memcpy(p
, r
->pcurrent
, bytes
);
456 r
->pcurrent
+= bytes
;
458 if (r
->pcurrent
>= r
->pend
)
460 r
->pcurrent
= r
->pixels
;
475 * 'cupsRasterWriteHeader()' - Write a raster page header from a V1 page
479 unsigned /* O - 1 on success, 0 on failure */
480 cupsRasterWriteHeader(
481 cups_raster_t
*r
, /* I - Raster stream */
482 cups_page_header_t
*h
) /* I - Raster page header */
484 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
488 * Make a copy of the header, and compute the number of raster
489 * lines in the page image...
492 memset(&(r
->header
), 0, sizeof(r
->header
));
493 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
495 cups_raster_update(r
);
498 * Write the raster header...
501 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
507 * 'cupsRasterWriteHeader2()' - Write a raster page header from a V2 page
513 unsigned /* O - 1 on success, 0 on failure */
514 cupsRasterWriteHeader2(
515 cups_raster_t
*r
, /* I - Raster stream */
516 cups_page_header2_t
*h
) /* I - Raster page header */
518 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
522 * Make a copy of the header, and compute the number of raster
523 * lines in the page image...
526 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
528 cups_raster_update(r
);
531 * Write the raster header...
534 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
540 * 'cupsRasterWritePixels()' - Write raster pixels.
543 unsigned /* O - Number of bytes written */
544 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
545 unsigned char *p
, /* I - Bytes to write */
546 unsigned len
)/* I - Number of bytes to write */
548 int bytes
; /* Bytes read */
549 unsigned remaining
; /* Bytes remaining */
552 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
553 r
, p
, len
, r
->remaining
));
555 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
|| r
->remaining
== 0)
561 * Without compression, just write the raster data raw...
564 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
566 return (cups_write(r
->fd
, p
, len
));
570 * Otherwise, compress each line...
573 for (remaining
= len
; remaining
> 0; remaining
-= bytes
, p
+= bytes
)
576 * Figure out the number of remaining bytes on the current line...
579 if ((bytes
= remaining
) > (r
->pend
- r
->pcurrent
))
580 bytes
= r
->pend
- r
->pcurrent
;
585 * Check to see if this line is the same as the previous line...
588 if (memcmp(p
, r
->pcurrent
, bytes
))
590 if (!cups_raster_write(r
, r
->pixels
))
598 * Mark more bytes as the same...
601 r
->pcurrent
+= bytes
;
603 if (r
->pcurrent
>= r
->pend
)
606 * Increase the repeat count...
610 r
->pcurrent
= r
->pixels
;
613 * Flush out this line if it is the last one...
618 if (r
->remaining
== 0)
619 return (cups_raster_write(r
, r
->pixels
));
620 else if (r
->count
== 256)
622 if (cups_raster_write(r
, r
->pixels
) == 0)
636 * Copy the raster data to the buffer...
639 memcpy(r
->pcurrent
, p
, bytes
);
641 r
->pcurrent
+= bytes
;
643 if (r
->pcurrent
>= r
->pend
)
646 * Increase the repeat count...
650 r
->pcurrent
= r
->pixels
;
653 * Flush out this line if it is the last one...
658 if (r
->remaining
== 0)
659 return (cups_raster_write(r
, r
->pixels
));
669 * 'cups_raster_read_header()' - Read a raster page header.
672 static unsigned /* O - 1 on success, 0 on fail */
673 cups_raster_read_header(
674 cups_raster_t
*r
) /* I - Raster stream */
676 int len
; /* Length for read/swap */
679 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
683 * Get the length of the raster header...
686 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
687 len
= sizeof(cups_page_header_t
);
689 len
= sizeof(cups_page_header2_t
);
695 memset(&(r
->header
), 0, sizeof(r
->header
));
697 if (cups_raster_read(r
, (unsigned char *)&(r
->header
), len
) < len
)
701 * Swap bytes as needed...
706 unsigned *s
, /* Current word */
707 temp
; /* Temporary copy */
710 DEBUG_puts("Swapping header bytes...");
712 for (len
= 81, s
= &(r
->header
.AdvanceDistance
);
716 DEBUG_printf(("%08x =>", *s
));
719 *s
= ((temp
& 0xff) << 24) |
720 ((temp
& 0xff00) << 8) |
721 ((temp
& 0xff0000) >> 8) |
722 ((temp
& 0xff000000) >> 24);
724 DEBUG_printf((" %08x\n", *s
));
729 * Update the header and row count...
732 cups_raster_update(r
);
739 * 'cups_raster_read()' - Read through the raster buffer.
742 static int /* O - Number of bytes read */
743 cups_raster_read(cups_raster_t
*r
, /* I - Raster stream */
744 unsigned char *buf
, /* I - Buffer */
745 int bytes
) /* I - Number of bytes to read */
747 int count
, /* Number of bytes read */
748 remaining
, /* Remaining bytes in buffer */
749 total
; /* Total bytes read */
752 DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=%d)\n", r
, buf
, bytes
));
755 return (cups_read(r
->fd
, buf
, bytes
));
758 * Allocate a read buffer as needed...
761 count
= 2 * r
->header
.cupsBytesPerLine
;
763 if (count
> r
->bufsize
)
765 int offset
= r
->bufptr
- r
->buffer
; /* Offset to current start of buffer */
766 int end
= r
->bufend
- r
->buffer
; /* Offset to current end of buffer */
767 unsigned char *rptr
; /* Pointer in read buffer */
770 rptr
= realloc(r
->buffer
, count
);
772 rptr
= malloc(count
);
778 r
->bufptr
= rptr
+ offset
;
779 r
->bufend
= rptr
+ end
;
784 * Loop until we have read everything...
787 for (total
= 0, remaining
= r
->bufend
- r
->bufptr
;
789 total
+= count
, buf
+= count
)
791 count
= bytes
- total
;
793 DEBUG_printf(("count=%d, remaining=%d, buf=%p, bufptr=%p, bufend=%p...\n",
794 count
, remaining
, buf
, r
->bufptr
, r
->bufend
));
801 * Read into the raster buffer and then copy...
804 remaining
= cups_read(r
->fd
, r
->buffer
, r
->bufsize
);
808 r
->bufptr
= r
->buffer
;
809 r
->bufend
= r
->buffer
+ remaining
;
814 * Read directly into "buf"...
817 count
= cups_read(r
->fd
, buf
, count
);
827 * Copy bytes from raster buffer to "buf"...
830 if (count
> remaining
)
839 *buf
= *(r
->bufptr
)++;
842 else if (count
< 128)
845 * Copy up to 127 bytes without using memcpy(); this is
846 * faster because it avoids an extra function call and is
847 * often further optimized by the compiler...
850 unsigned char *bufptr
; /* Temporary buffer pointer */
855 for (bufptr
= r
->bufptr
; count
> 0; count
--, total
++)
863 * Use memcpy() for a large read...
866 memcpy(buf
, r
->bufptr
, count
);
877 * 'cups_raster_update()' - Update the raster header and row count for the
882 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
884 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
885 r
->header
.cupsNumColors
== 0)
888 * Set the "cupsNumColors" field according to the colorspace...
891 switch (r
->header
.cupsColorSpace
)
895 case CUPS_CSPACE_WHITE
:
896 case CUPS_CSPACE_GOLD
:
897 case CUPS_CSPACE_SILVER
:
898 r
->header
.cupsNumColors
= 1;
901 case CUPS_CSPACE_RGB
:
902 case CUPS_CSPACE_CMY
:
903 case CUPS_CSPACE_YMC
:
904 case CUPS_CSPACE_CIEXYZ
:
905 case CUPS_CSPACE_CIELab
:
906 case CUPS_CSPACE_ICC1
:
907 case CUPS_CSPACE_ICC2
:
908 case CUPS_CSPACE_ICC3
:
909 case CUPS_CSPACE_ICC4
:
910 case CUPS_CSPACE_ICC5
:
911 case CUPS_CSPACE_ICC6
:
912 case CUPS_CSPACE_ICC7
:
913 case CUPS_CSPACE_ICC8
:
914 case CUPS_CSPACE_ICC9
:
915 case CUPS_CSPACE_ICCA
:
916 case CUPS_CSPACE_ICCB
:
917 case CUPS_CSPACE_ICCC
:
918 case CUPS_CSPACE_ICCD
:
919 case CUPS_CSPACE_ICCE
:
920 case CUPS_CSPACE_ICCF
:
921 r
->header
.cupsNumColors
= 3;
924 case CUPS_CSPACE_RGBA
:
925 case CUPS_CSPACE_RGBW
:
926 case CUPS_CSPACE_CMYK
:
927 case CUPS_CSPACE_YMCK
:
928 case CUPS_CSPACE_KCMY
:
929 case CUPS_CSPACE_GMCK
:
930 case CUPS_CSPACE_GMCS
:
931 r
->header
.cupsNumColors
= 4;
934 case CUPS_CSPACE_KCMYcm
:
935 if (r
->header
.cupsBitsPerPixel
< 8)
936 r
->header
.cupsNumColors
= 6;
938 r
->header
.cupsNumColors
= 4;
944 * Set the number of bytes per pixel/color...
947 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
948 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
950 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
953 * Set the number of remaining rows...
956 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
957 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
959 r
->remaining
= r
->header
.cupsHeight
;
962 * Allocate the compression buffer...
967 if (r
->pixels
!= NULL
)
970 r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1);
971 r
->pcurrent
= r
->pixels
;
972 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
979 * 'cups_raster_write()' - Write a row of compressed raster data...
982 static int /* O - Number of bytes written */
984 cups_raster_t
*r
, /* I - Raster stream */
985 const unsigned char *pixels
) /* I - Pixel data to write */
987 const unsigned char *start
, /* Start of sequence */
988 *ptr
, /* Current pointer in sequence */
989 *pend
, /* End of raster buffer */
990 *plast
; /* Pointer to last pixel */
991 unsigned char *wptr
; /* Pointer into write buffer */
992 int bpp
, /* Bytes per pixel */
994 maxrun
; /* Maximum run of 128 * bpp */
997 DEBUG_printf(("cups_raster_write(r=%p, pixels=%p)\n", r
, pixels
));
1000 * Allocate a write buffer as needed...
1003 count
= r
->header
.cupsBytesPerLine
* 2;
1004 if (count
> r
->bufsize
)
1007 wptr
= realloc(r
->buffer
, count
);
1009 wptr
= malloc(count
);
1019 * Write the row repeat count...
1023 pend
= pixels
+ r
->header
.cupsBytesPerLine
;
1026 *wptr
++ = r
->count
- 1;
1030 * Write using a modified TIFF "packbits" compression...
1033 for (ptr
= pixels
; ptr
< pend
;)
1041 * Encode a single pixel at the end...
1045 for (count
= bpp
; count
> 0; count
--)
1048 else if (!memcmp(start
, ptr
, bpp
))
1051 * Encode a sequence of repeating pixels...
1054 for (count
= 2; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1055 if (memcmp(ptr
, ptr
+ bpp
, bpp
))
1058 *wptr
++ = count
- 1;
1059 for (count
= bpp
; count
> 0; count
--)
1065 * Encode a sequence of non-repeating pixels...
1068 for (count
= 1; count
< 127 && ptr
< plast
; count
++, ptr
+= bpp
)
1069 if (!memcmp(ptr
, ptr
+ bpp
, bpp
))
1072 if (ptr
>= plast
&& count
< 128)
1078 *wptr
++ = 257 - count
;
1081 memcpy(wptr
, start
, count
);
1086 return (cups_write(r
->fd
, r
->buffer
, wptr
- r
->buffer
));
1091 * 'cups_read()' - Read bytes from a file.
1094 static int /* O - Bytes read or -1 */
1095 cups_read(int fd
, /* I - File descriptor */
1096 unsigned char *buf
, /* I - Buffer for read */
1097 int bytes
) /* I - Number of bytes to read */
1099 int count
, /* Number of bytes read */
1100 total
; /* Total bytes read */
1103 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
1105 count
= read(fd
, buf
, bytes
- total
);
1123 * 'cups_swap()' - Swap bytes in raster data...
1127 cups_swap(unsigned char *buf
, /* I - Buffer to swap */
1128 int bytes
) /* I - Number of bytes to swap */
1130 unsigned char even
, odd
; /* Temporary variables */
1149 * 'cups_write()' - Write bytes to a file.
1152 static int /* O - Bytes written or -1 */
1153 cups_write(int fd
, /* I - File descriptor */
1154 const unsigned char *buf
, /* I - Bytes to write */
1155 int bytes
) /* I - Number of bytes to write */
1157 int count
, /* Number of bytes written */
1158 total
; /* Total bytes written */
1161 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
1163 count
= write(fd
, buf
, bytes
- total
);
1179 * End of "$Id: raster.c 6584 2007-06-21 17:22:26Z mike $".