2 * "$Id: raster.c 7720 2008-07-11 22:46:21Z mike $"
4 * Raster file routines for CUPS.
6 * Copyright 2007-2010 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
9 * This file is part of the CUPS Imaging library.
11 * These coded instructions, statements, and computer programs are the
12 * property of Apple Inc. and are protected by Federal copyright
13 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
14 * which should have been included with this file. If this file is
15 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * This file is subject to the Apple OS-Developed Software exception.
21 * cupsRasterClose() - Close a raster stream.
22 * cupsRasterOpen() - Open a raster stream.
23 * cupsRasterReadHeader() - Read a raster page header and store it in a
24 * version 1 page header structure.
25 * cupsRasterReadHeader2() - Read a raster page header and store it in a
26 * version 2 page header structure.
27 * cupsRasterReadPixels() - Read raster pixels.
28 * cupsRasterWriteHeader() - Write a raster page header from a version 1
29 * page header structure.
30 * cupsRasterWriteHeader2() - Write a raster page header from a version 2
31 * page header structure.
32 * cupsRasterWritePixels() - Write raster pixels.
33 * cups_raster_read() - Read through the raster buffer.
34 * cups_raster_read_header() - Read a raster page header.
35 * cups_raster_update() - Update the raster header and row count for the
37 * cups_raster_write() - Write a row of raster data...
38 * cups_read() - Read bytes from a file.
39 * cups_swap() - Swap bytes in raster data...
40 * cups_write() - Write bytes to a file.
44 * Include necessary headers...
47 #include "image-private.h"
48 #if defined(WIN32) || defined(__EMX__)
52 #endif /* WIN32 || __EMX__ */
56 * Private structures...
59 struct _cups_raster_s
/**** Raster stream data ****/
61 unsigned sync
; /* Sync word from start of stream */
62 int fd
; /* File descriptor */
63 cups_mode_t mode
; /* Read/write mode */
64 cups_page_header2_t header
; /* Raster header for current page */
65 int count
, /* Current row run-length count */
66 remaining
, /* Remaining rows in page image */
67 bpp
; /* Bytes per pixel/color */
68 unsigned char *pixels
, /* Pixels for current row */
69 *pend
, /* End of pixel buffer */
70 *pcurrent
; /* Current byte in pixel buffer */
71 int compressed
, /* Non-zero if data is compressed */
72 swapped
; /* Non-zero if data is byte-swapped */
73 unsigned char *buffer
, /* Read/write buffer */
74 *bufptr
, /* Current (read) position in buffer */
75 *bufend
; /* End of current (read) buffer */
76 int bufsize
; /* Buffer size */
84 static unsigned cups_raster_read_header(cups_raster_t
*r
);
85 static int cups_raster_read(cups_raster_t
*r
, unsigned char *buf
,
87 static void cups_raster_update(cups_raster_t
*r
);
88 static int cups_raster_write(cups_raster_t
*r
, const unsigned char *pixels
);
89 static int cups_read(int fd
, unsigned char *buf
, int bytes
);
90 static void cups_swap(unsigned char *buf
, int bytes
);
91 static int cups_write(int fd
, const unsigned char *buf
, int bytes
);
95 * 'cupsRasterClose()' - Close a raster stream.
97 * The file descriptor associated with the raster stream must be closed
98 * separately as needed.
102 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
118 * 'cupsRasterOpen()' - Open a raster stream.
120 * This function associates a raster stream with the given file descriptor.
121 * For most printer driver filters, "fd" will be 0 (stdin). For most raster
122 * image processor (RIP) filters that generate raster data, "fd" will be 1
125 * When writing raster data, the @code CUPS_RASTER_WRITE@ or
126 * @code CUPS_RASTER_WRITE_COMPRESS@ mode can be used - compressed output
127 * is generally 25-50% smaller but adds a 100-300% execution time overhead.
130 cups_raster_t
* /* O - New stream */
131 cupsRasterOpen(int fd
, /* I - File descriptor */
132 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@, @code CUPS_RASTER_WRITE@, or @code CUPS_RASTER_WRITE_COMPRESSED@ */
134 cups_raster_t
*r
; /* New stream */
137 _cupsRasterClearError();
139 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
141 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
147 r
->mode
= mode
== CUPS_RASTER_WRITE_COMPRESSED
? CUPS_RASTER_WRITE
: mode
;
149 if (mode
== CUPS_RASTER_READ
)
152 * Open for read - get sync word...
155 if (!cups_read(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)))
157 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
163 if (r
->sync
!= CUPS_RASTER_SYNC
&&
164 r
->sync
!= CUPS_RASTER_REVSYNC
&&
165 r
->sync
!= CUPS_RASTER_SYNCv1
&&
166 r
->sync
!= CUPS_RASTER_REVSYNCv1
&&
167 r
->sync
!= CUPS_RASTER_SYNCv2
&&
168 r
->sync
!= CUPS_RASTER_REVSYNCv2
)
170 _cupsRasterAddError("Unknown raster format %08x!\n", r
->sync
);
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
)
184 DEBUG_printf(("r->swapped=%d, r->sync=%08x\n", r
->swapped
, r
->sync
));
189 * Open for write - put sync word...
192 if (mode
== CUPS_RASTER_WRITE_COMPRESSED
)
195 r
->sync
= CUPS_RASTER_SYNCv2
;
198 r
->sync
= CUPS_RASTER_SYNC
;
200 if (cups_write(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
))
203 _cupsRasterAddError("Unable to write raster stream header: %s\n",
215 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
216 * version 1 page header structure.
218 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
220 * Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset
221 * of the version 2 page header data. This function handles reading version 2
222 * page headers and copying only the version 1 data into the provided buffer.
227 unsigned /* O - 1 on success, 0 on failure/end-of-file */
228 cupsRasterReadHeader(
229 cups_raster_t
*r
, /* I - Raster stream */
230 cups_page_header_t
*h
) /* I - Pointer to header data */
233 * Get the raster header...
236 if (!cups_raster_read_header(r
))
240 * Copy the header to the user-supplied buffer...
243 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
250 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
251 * version 2 page header structure.
253 * @since CUPS 1.2/Mac OS X 10.5@
256 unsigned /* O - 1 on success, 0 on failure/end-of-file */
257 cupsRasterReadHeader2(
258 cups_raster_t
*r
, /* I - Raster stream */
259 cups_page_header2_t
*h
) /* I - Pointer to header data */
262 * Get the raster header...
265 if (!cups_raster_read_header(r
))
269 * Copy the header to the user-supplied buffer...
272 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
279 * 'cupsRasterReadPixels()' - Read raster pixels.
281 * For best performance, filters should read one or more whole lines.
282 * The "cupsBytesPerLine" value from the page header can be used to allocate
283 * the line buffer and as the number of bytes to read.
286 unsigned /* O - Number of bytes read */
287 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
288 unsigned char *p
, /* I - Pointer to pixel buffer */
289 unsigned len
) /* I - Number of bytes to read */
291 int bytes
; /* Bytes read */
292 unsigned cupsBytesPerLine
; /* cupsBytesPerLine value */
293 unsigned remaining
; /* Bytes remaining */
294 unsigned char *ptr
, /* Pointer to read buffer */
295 byte
, /* Byte from file */
296 *temp
; /* Pointer into buffer */
297 int count
; /* Repetition count */
300 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0)
306 * Read without compression...
309 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
311 if (!cups_read(r
->fd
, p
, len
))
315 * Swap bytes as needed...
318 if ((r
->header
.cupsBitsPerColor
== 16 ||
319 r
->header
.cupsBitsPerPixel
== 12 ||
320 r
->header
.cupsBitsPerPixel
== 16) &&
332 * Read compressed data...
336 cupsBytesPerLine
= r
->header
.cupsBytesPerLine
;
338 while (remaining
> 0 && r
->remaining
> 0)
343 * Need to read a new row...
346 if (remaining
== cupsBytesPerLine
)
352 * Read using a modified TIFF "packbits" compression...
355 if (!cups_raster_read(r
, &byte
, 1))
364 bytes
= cupsBytesPerLine
;
369 * Get a new repeat count...
372 if (!cups_raster_read(r
, &byte
, 1))
378 * Copy N literal pixels...
381 count
= (257 - byte
) * r
->bpp
;
386 if (!cups_raster_read(r
, temp
, count
))
395 * Repeat the next N bytes...
398 count
= (byte
+ 1) * r
->bpp
;
407 if (!cups_raster_read(r
, temp
, r
->bpp
))
415 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
423 * Swap bytes as needed...
426 if ((r
->header
.cupsBitsPerColor
== 16 ||
427 r
->header
.cupsBitsPerPixel
== 12 ||
428 r
->header
.cupsBitsPerPixel
== 16) &&
430 cups_swap(ptr
, bytes
);
436 if (remaining
>= cupsBytesPerLine
)
438 bytes
= cupsBytesPerLine
;
439 r
->pcurrent
= r
->pixels
;
446 r
->pcurrent
= r
->pixels
+ bytes
;
450 * Copy data as needed...
454 memcpy(p
, ptr
, bytes
);
459 * Copy fragment from buffer...
462 if ((bytes
= r
->pend
- r
->pcurrent
) > remaining
)
465 memcpy(p
, r
->pcurrent
, bytes
);
466 r
->pcurrent
+= bytes
;
468 if (r
->pcurrent
>= r
->pend
)
470 r
->pcurrent
= r
->pixels
;
485 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
488 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
493 unsigned /* O - 1 on success, 0 on failure */
494 cupsRasterWriteHeader(
495 cups_raster_t
*r
, /* I - Raster stream */
496 cups_page_header_t
*h
) /* I - Raster page header */
498 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
502 * Make a copy of the header, and compute the number of raster
503 * lines in the page image...
506 memset(&(r
->header
), 0, sizeof(r
->header
));
507 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
509 cups_raster_update(r
);
512 * Write the raster header...
515 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
521 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
522 * page header structure.
524 * The page header can be initialized using @link cupsRasterInterpretPPD@.
526 * @since CUPS 1.2/Mac OS X 10.5@
529 unsigned /* O - 1 on success, 0 on failure */
530 cupsRasterWriteHeader2(
531 cups_raster_t
*r
, /* I - Raster stream */
532 cups_page_header2_t
*h
) /* I - Raster page header */
534 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
538 * Make a copy of the header, and compute the number of raster
539 * lines in the page image...
542 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
544 cups_raster_update(r
);
547 * Write the raster header...
550 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
556 * 'cupsRasterWritePixels()' - Write raster pixels.
558 * For best performance, filters should write one or more whole lines.
559 * The "cupsBytesPerLine" value from the page header can be used to allocate
560 * the line buffer and as the number of bytes to write.
563 unsigned /* O - Number of bytes written */
564 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
565 unsigned char *p
, /* I - Bytes to write */
566 unsigned len
)/* I - Number of bytes to write */
568 int bytes
; /* Bytes read */
569 unsigned remaining
; /* Bytes remaining */
572 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
573 r
, p
, len
, r
->remaining
));
575 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
|| r
->remaining
== 0)
581 * Without compression, just write the raster data raw...
584 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
586 return (cups_write(r
->fd
, p
, len
));
590 * Otherwise, compress each line...
593 for (remaining
= len
; remaining
> 0; remaining
-= bytes
, p
+= bytes
)
596 * Figure out the number of remaining bytes on the current line...
599 if ((bytes
= remaining
) > (r
->pend
- r
->pcurrent
))
600 bytes
= r
->pend
- r
->pcurrent
;
605 * Check to see if this line is the same as the previous line...
608 if (memcmp(p
, r
->pcurrent
, bytes
))
610 if (!cups_raster_write(r
, r
->pixels
))
618 * Mark more bytes as the same...
621 r
->pcurrent
+= bytes
;
623 if (r
->pcurrent
>= r
->pend
)
626 * Increase the repeat count...
630 r
->pcurrent
= r
->pixels
;
633 * Flush out this line if it is the last one...
638 if (r
->remaining
== 0)
639 return (cups_raster_write(r
, r
->pixels
));
640 else if (r
->count
== 256)
642 if (cups_raster_write(r
, r
->pixels
) == 0)
656 * Copy the raster data to the buffer...
659 memcpy(r
->pcurrent
, p
, bytes
);
661 r
->pcurrent
+= bytes
;
663 if (r
->pcurrent
>= r
->pend
)
666 * Increase the repeat count...
670 r
->pcurrent
= r
->pixels
;
673 * Flush out this line if it is the last one...
678 if (r
->remaining
== 0)
679 return (cups_raster_write(r
, r
->pixels
));
689 * 'cups_raster_read_header()' - Read a raster page header.
692 static unsigned /* O - 1 on success, 0 on fail */
693 cups_raster_read_header(
694 cups_raster_t
*r
) /* I - Raster stream */
696 int len
; /* Length for read/swap */
699 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
703 * Get the length of the raster header...
706 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
707 len
= sizeof(cups_page_header_t
);
709 len
= sizeof(cups_page_header2_t
);
715 memset(&(r
->header
), 0, sizeof(r
->header
));
717 if (cups_raster_read(r
, (unsigned char *)&(r
->header
), len
) < len
)
721 * Swap bytes as needed...
726 unsigned *s
, /* Current word */
727 temp
; /* Temporary copy */
730 DEBUG_puts("Swapping header bytes...");
732 for (len
= 81, s
= &(r
->header
.AdvanceDistance
);
736 DEBUG_printf(("%08x =>", *s
));
739 *s
= ((temp
& 0xff) << 24) |
740 ((temp
& 0xff00) << 8) |
741 ((temp
& 0xff0000) >> 8) |
742 ((temp
& 0xff000000) >> 24);
744 DEBUG_printf((" %08x\n", *s
));
749 * Update the header and row count...
752 cups_raster_update(r
);
759 * 'cups_raster_read()' - Read through the raster buffer.
762 static int /* O - Number of bytes read */
763 cups_raster_read(cups_raster_t
*r
, /* I - Raster stream */
764 unsigned char *buf
, /* I - Buffer */
765 int bytes
) /* I - Number of bytes to read */
767 int count
, /* Number of bytes read */
768 remaining
, /* Remaining bytes in buffer */
769 total
; /* Total bytes read */
772 DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=%d)\n", r
, buf
, bytes
));
775 return (cups_read(r
->fd
, buf
, bytes
));
778 * Allocate a read buffer as needed...
781 count
= 2 * r
->header
.cupsBytesPerLine
;
783 if (count
> r
->bufsize
)
785 int offset
= r
->bufptr
- r
->buffer
; /* Offset to current start of buffer */
786 int end
= r
->bufend
- r
->buffer
; /* Offset to current end of buffer */
787 unsigned char *rptr
; /* Pointer in read buffer */
790 rptr
= realloc(r
->buffer
, count
);
792 rptr
= malloc(count
);
798 r
->bufptr
= rptr
+ offset
;
799 r
->bufend
= rptr
+ end
;
804 * Loop until we have read everything...
807 for (total
= 0, remaining
= r
->bufend
- r
->bufptr
;
809 total
+= count
, buf
+= count
)
811 count
= bytes
- total
;
813 DEBUG_printf(("count=%d, remaining=%d, buf=%p, bufptr=%p, bufend=%p...\n",
814 count
, remaining
, buf
, r
->bufptr
, r
->bufend
));
821 * Read into the raster buffer and then copy...
824 remaining
= cups_read(r
->fd
, r
->buffer
, r
->bufsize
);
828 r
->bufptr
= r
->buffer
;
829 r
->bufend
= r
->buffer
+ remaining
;
834 * Read directly into "buf"...
837 count
= cups_read(r
->fd
, buf
, count
);
847 * Copy bytes from raster buffer to "buf"...
850 if (count
> remaining
)
859 *buf
= *(r
->bufptr
)++;
862 else if (count
< 128)
865 * Copy up to 127 bytes without using memcpy(); this is
866 * faster because it avoids an extra function call and is
867 * often further optimized by the compiler...
870 unsigned char *bufptr
; /* Temporary buffer pointer */
875 for (bufptr
= r
->bufptr
; count
> 0; count
--, total
++)
883 * Use memcpy() for a large read...
886 memcpy(buf
, r
->bufptr
, count
);
897 * 'cups_raster_update()' - Update the raster header and row count for the
902 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
904 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
905 r
->header
.cupsNumColors
== 0)
908 * Set the "cupsNumColors" field according to the colorspace...
911 switch (r
->header
.cupsColorSpace
)
915 case CUPS_CSPACE_WHITE
:
916 case CUPS_CSPACE_GOLD
:
917 case CUPS_CSPACE_SILVER
:
918 case CUPS_CSPACE_SW
:
919 r
->header
.cupsNumColors
= 1;
922 case CUPS_CSPACE_RGB
:
923 case CUPS_CSPACE_CMY
:
924 case CUPS_CSPACE_YMC
:
925 case CUPS_CSPACE_CIEXYZ
:
926 case CUPS_CSPACE_CIELab
:
927 case CUPS_CSPACE_SRGB
:
928 case CUPS_CSPACE_ADOBERGB
:
929 case CUPS_CSPACE_ICC1
:
930 case CUPS_CSPACE_ICC2
:
931 case CUPS_CSPACE_ICC3
:
932 case CUPS_CSPACE_ICC4
:
933 case CUPS_CSPACE_ICC5
:
934 case CUPS_CSPACE_ICC6
:
935 case CUPS_CSPACE_ICC7
:
936 case CUPS_CSPACE_ICC8
:
937 case CUPS_CSPACE_ICC9
:
938 case CUPS_CSPACE_ICCA
:
939 case CUPS_CSPACE_ICCB
:
940 case CUPS_CSPACE_ICCC
:
941 case CUPS_CSPACE_ICCD
:
942 case CUPS_CSPACE_ICCE
:
943 case CUPS_CSPACE_ICCF
:
944 r
->header
.cupsNumColors
= 3;
947 case CUPS_CSPACE_RGBA
:
948 case CUPS_CSPACE_RGBW
:
949 case CUPS_CSPACE_CMYK
:
950 case CUPS_CSPACE_YMCK
:
951 case CUPS_CSPACE_KCMY
:
952 case CUPS_CSPACE_GMCK
:
953 case CUPS_CSPACE_GMCS
:
954 r
->header
.cupsNumColors
= 4;
957 case CUPS_CSPACE_KCMYcm
:
958 if (r
->header
.cupsBitsPerPixel
< 8)
959 r
->header
.cupsNumColors
= 6;
961 r
->header
.cupsNumColors
= 4;
964 case CUPS_CSPACE_DEVICE1
:
965 case CUPS_CSPACE_DEVICE2
:
966 case CUPS_CSPACE_DEVICE3
:
967 case CUPS_CSPACE_DEVICE4
:
968 case CUPS_CSPACE_DEVICE5
:
969 case CUPS_CSPACE_DEVICE6
:
970 case CUPS_CSPACE_DEVICE7
:
971 case CUPS_CSPACE_DEVICE8
:
972 case CUPS_CSPACE_DEVICE9
:
973 case CUPS_CSPACE_DEVICEA
:
974 case CUPS_CSPACE_DEVICEB
:
975 case CUPS_CSPACE_DEVICEC
:
976 case CUPS_CSPACE_DEVICED
:
977 case CUPS_CSPACE_DEVICEE
:
978 case CUPS_CSPACE_DEVICEF
:
979 r
->header
.cupsNumColors
= r
->header
.cupsColorSpace
-
980 CUPS_CSPACE_DEVICE1
+ 1;
986 * Set the number of bytes per pixel/color...
989 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
990 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
992 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
995 * Set the number of remaining rows...
998 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
999 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
1001 r
->remaining
= r
->header
.cupsHeight
;
1004 * Allocate the compression buffer...
1009 if (r
->pixels
!= NULL
)
1012 r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1);
1013 r
->pcurrent
= r
->pixels
;
1014 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
1021 * 'cups_raster_write()' - Write a row of compressed raster data...
1024 static int /* O - Number of bytes written */
1026 cups_raster_t
*r
, /* I - Raster stream */
1027 const unsigned char *pixels
) /* I - Pixel data to write */
1029 const unsigned char *start
, /* Start of sequence */
1030 *ptr
, /* Current pointer in sequence */
1031 *pend
, /* End of raster buffer */
1032 *plast
; /* Pointer to last pixel */
1033 unsigned char *wptr
; /* Pointer into write buffer */
1034 int bpp
, /* Bytes per pixel */
1038 DEBUG_printf(("cups_raster_write(r=%p, pixels=%p)\n", r
, pixels
));
1041 * Allocate a write buffer as needed...
1044 count
= r
->header
.cupsBytesPerLine
* 2;
1045 if (count
> r
->bufsize
)
1048 wptr
= realloc(r
->buffer
, count
);
1050 wptr
= malloc(count
);
1060 * Write the row repeat count...
1064 pend
= pixels
+ r
->header
.cupsBytesPerLine
;
1067 *wptr
++ = r
->count
- 1;
1070 * Write using a modified TIFF "packbits" compression...
1073 for (ptr
= pixels
; ptr
< pend
;)
1081 * Encode a single pixel at the end...
1085 for (count
= bpp
; count
> 0; count
--)
1088 else if (!memcmp(start
, ptr
, bpp
))
1091 * Encode a sequence of repeating pixels...
1094 for (count
= 2; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1095 if (memcmp(ptr
, ptr
+ bpp
, bpp
))
1098 *wptr
++ = count
- 1;
1099 for (count
= bpp
; count
> 0; count
--)
1105 * Encode a sequence of non-repeating pixels...
1108 for (count
= 1; count
< 127 && ptr
< plast
; count
++, ptr
+= bpp
)
1109 if (!memcmp(ptr
, ptr
+ bpp
, bpp
))
1112 if (ptr
>= plast
&& count
< 128)
1118 *wptr
++ = 257 - count
;
1121 memcpy(wptr
, start
, count
);
1126 return (cups_write(r
->fd
, r
->buffer
, wptr
- r
->buffer
));
1131 * 'cups_read()' - Read bytes from a file.
1134 static int /* O - Bytes read or -1 */
1135 cups_read(int fd
, /* I - File descriptor */
1136 unsigned char *buf
, /* I - Buffer for read */
1137 int bytes
) /* I - Number of bytes to read */
1139 int count
, /* Number of bytes read */
1140 total
; /* Total bytes read */
1143 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
1145 count
= read(fd
, buf
, bytes
- total
);
1163 * 'cups_swap()' - Swap bytes in raster data...
1167 cups_swap(unsigned char *buf
, /* I - Buffer to swap */
1168 int bytes
) /* I - Number of bytes to swap */
1170 unsigned char even
, odd
; /* Temporary variables */
1189 * 'cups_write()' - Write bytes to a file.
1192 static int /* O - Bytes written or -1 */
1193 cups_write(int fd
, /* I - File descriptor */
1194 const unsigned char *buf
, /* I - Bytes to write */
1195 int bytes
) /* I - Number of bytes to write */
1197 int count
, /* Number of bytes written */
1198 total
; /* Total bytes written */
1201 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
1203 count
= write(fd
, buf
, bytes
- total
);
1219 * End of "$Id: raster.c 7720 2008-07-11 22:46:21Z mike $".