2 * "$Id: raster.c 5523 2006-05-15 05:02:43Z 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 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_update() - Update the raster header and row count for the
51 * cups_raster_write() - Write a row of raster data...
52 * cups_read() - Read bytes from a file.
53 * cups_write() - Write bytes to a file.
57 * Include necessary headers...
64 #include <cups/string.h>
66 #if defined(WIN32) || defined(__EMX__)
70 #endif /* WIN32 || __EMX__ */
74 * Private structures...
77 struct _cups_raster_s
/**** Raster stream data ****/
79 unsigned sync
; /* Sync word from start of stream */
80 int fd
; /* File descriptor */
81 cups_mode_t mode
; /* Read/write mode */
82 cups_page_header2_t header
; /* Raster header for current page */
83 int count
, /* Current row run-length count */
84 remaining
, /* Remaining rows in page image */
85 bpp
; /* Bytes per pixel/color */
86 unsigned char *pixels
, /* Pixels for current row */
87 *pend
, /* End of pixel buffer */
88 *pcurrent
; /* Current byte in pixel buffer */
95 static unsigned cups_raster_read_header(cups_raster_t
*r
);
96 static void cups_raster_update(cups_raster_t
*r
);
97 static int cups_raster_write(cups_raster_t
*r
);
98 static int cups_read(int fd
, unsigned char *buf
, int bytes
);
99 static int cups_write(int fd
, const unsigned char *buf
, int bytes
);
103 * 'cupsRasterClose()' - Close a raster stream.
107 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
120 * 'cupsRasterOpen()' - Open a raster stream.
123 cups_raster_t
* /* O - New stream */
124 cupsRasterOpen(int fd
, /* I - File descriptor */
125 cups_mode_t mode
) /* I - Mode */
127 cups_raster_t
*r
; /* New stream */
130 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
136 if (mode
== CUPS_RASTER_READ
)
139 * Open for read - get sync word...
142 if (cups_read(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
))
149 if (r
->sync
!= CUPS_RASTER_SYNC
&&
150 r
->sync
!= CUPS_RASTER_REVSYNC
&&
151 r
->sync
!= CUPS_RASTER_SYNCv1
&&
152 r
->sync
!= CUPS_RASTER_REVSYNCv1
)
161 * Open for write - put sync word...
164 r
->sync
= CUPS_RASTER_SYNC
;
165 if (cups_write(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
))
178 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
179 * V1 page header structure.
182 unsigned /* O - 1 on success, 0 on fail */
183 cupsRasterReadHeader(
184 cups_raster_t
*r
, /* I - Raster stream */
185 cups_page_header_t
*h
) /* I - Pointer to header data */
188 * Get the raster header...
191 if (!cups_raster_read_header(r
))
195 * Copy the header to the user-supplied buffer...
198 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
205 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
206 * V2 page header structure.
211 unsigned /* O - 1 on success, 0 on fail */
212 cupsRasterReadHeader2(
213 cups_raster_t
*r
, /* I - Raster stream */
214 cups_page_header2_t
*h
) /* I - Pointer to header data */
217 * Get the raster header...
220 if (!cups_raster_read_header(r
))
224 * Copy the header to the user-supplied buffer...
227 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
234 * 'cupsRasterReadPixels()' - Read raster pixels.
237 unsigned /* O - Number of bytes read */
238 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
239 unsigned char *p
, /* I - Pointer to pixel buffer */
240 unsigned len
) /* I - Number of bytes to read */
242 int bytes
; /* Bytes read */
243 unsigned remaining
; /* Bytes remaining */
244 unsigned char *ptr
, /* Pointer to read buffer */
245 byte
; /* Byte from file */
248 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0)
253 while (remaining
> 0 && r
->remaining
> 0)
258 * Need to read a new row...
261 if (remaining
== r
->header
.cupsBytesPerLine
)
266 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
269 * Read without compression...
272 if (cups_read(r
->fd
, ptr
, r
->header
.cupsBytesPerLine
) <
273 r
->header
.cupsBytesPerLine
)
281 * Read using a modified TIFF "packbits" compression...
284 unsigned char *temp
; /* Pointer into buffer */
285 int count
; /* Repetition count */
288 if (cups_read(r
->fd
, &byte
, 1) < 1)
297 bytes
= r
->header
.cupsBytesPerLine
;
302 * Get a new repeat count...
305 if (cups_read(r
->fd
, &byte
, 1) < 1)
311 * Copy N literal pixels...
314 count
= (257 - byte
) * r
->bpp
;
319 if (cups_read(r
->fd
, temp
, count
) < count
)
328 * Repeat the next N bytes...
331 count
= (byte
+ 1) * r
->bpp
;
340 if (cups_read(r
->fd
, temp
, r
->bpp
) < r
->bpp
)
348 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
356 if ((r
->header
.cupsBitsPerColor
== 16 ||
357 r
->header
.cupsBitsPerPixel
== 12 ||
358 r
->header
.cupsBitsPerPixel
== 16) &&
359 (r
->sync
== CUPS_RASTER_REVSYNC
|| r
->sync
== CUPS_RASTER_REVSYNCv1
))
362 * Swap bytes in the pixel data...
369 for (temp
= ptr
, count
= r
->header
.cupsBytesPerLine
;
371 temp
+= 2, count
-= 2)
379 if (remaining
>= r
->header
.cupsBytesPerLine
)
381 bytes
= r
->header
.cupsBytesPerLine
;
382 r
->pcurrent
= r
->pixels
;
389 r
->pcurrent
= r
->pixels
+ bytes
;
393 memcpy(p
, ptr
, bytes
);
398 * Copy fragment from buffer...
401 if ((bytes
= r
->pend
- r
->pcurrent
) > remaining
)
404 memcpy(p
, r
->pcurrent
, bytes
);
405 r
->pcurrent
+= bytes
;
407 if (r
->pcurrent
>= r
->pend
)
409 r
->pcurrent
= r
->pixels
;
424 * 'cupsRasterWriteHeader()' - Write a raster page header from a V1 page
428 unsigned /* O - 1 on success, 0 on failure */
429 cupsRasterWriteHeader(
430 cups_raster_t
*r
, /* I - Raster stream */
431 cups_page_header_t
*h
) /* I - Raster page header */
433 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
437 * Make a copy of the header, and compute the number of raster
438 * lines in the page image...
441 memset(&(r
->header
), 0, sizeof(r
->header
));
442 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
444 cups_raster_update(r
);
447 * Write the raster header...
450 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
456 * 'cupsRasterWriteHeader2()' - Write a raster page header from a V2 page
462 unsigned /* O - 1 on success, 0 on failure */
463 cupsRasterWriteHeader2(
464 cups_raster_t
*r
, /* I - Raster stream */
465 cups_page_header2_t
*h
) /* I - Raster page header */
467 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
471 * Make a copy of the header, and compute the number of raster
472 * lines in the page image...
475 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
477 cups_raster_update(r
);
480 * Write the raster header...
483 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
489 * 'cupsRasterWritePixels()' - Write raster pixels.
492 unsigned /* O - Number of bytes written */
493 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
494 unsigned char *p
, /* I - Bytes to write */
495 unsigned len
)/* I - Number of bytes to write */
497 int bytes
; /* Bytes read */
498 unsigned remaining
; /* Bytes remaining */
502 fprintf(stderr
, "cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
503 r
, p
, len
, r
->remaining
);
506 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
|| r
->remaining
== 0)
509 for (remaining
= len
; remaining
> 0; remaining
-= bytes
, p
+= bytes
)
513 * Figure out the number of remaining bytes on the current line...
516 if ((bytes
= remaining
) > (r
->pend
- r
->pcurrent
))
517 bytes
= r
->pend
- r
->pcurrent
;
522 * Check to see if this line is the same as the previous line...
525 if (memcmp(p
, r
->pcurrent
, bytes
))
527 if (!cups_raster_write(r
))
535 * Mark more bytes as the same...
538 r
->pcurrent
+= bytes
;
540 if (r
->pcurrent
>= r
->pend
)
543 * Increase the repeat count...
547 r
->pcurrent
= r
->pixels
;
550 * Flush out this line if it is the last one...
555 if (r
->remaining
== 0)
556 return (cups_raster_write(r
));
557 else if (r
->count
== 256)
559 if (cups_raster_write(r
) == 0)
573 * Copy the raster data to the buffer...
576 memcpy(r
->pcurrent
, p
, bytes
);
578 r
->pcurrent
+= bytes
;
580 if (r
->pcurrent
>= r
->pend
)
583 * Increase the repeat count...
587 r
->pcurrent
= r
->pixels
;
590 * Flush out this line if it is the last one...
595 if (r
->remaining
== 0)
596 return (cups_raster_write(r
));
606 * 'cups_raster_read_header()' - Read a raster page header.
609 static unsigned /* O - 1 on success, 0 on fail */
610 cups_raster_read_header(
611 cups_raster_t
*r
) /* I - Raster stream */
613 int len
; /* Number of words to swap */
614 union swap_s
/* Swapping structure */
621 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
625 * Get the length of the raster header...
628 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
629 len
= sizeof(cups_page_header_t
);
631 len
= sizeof(cups_page_header2_t
);
637 memset(&(r
->header
), 0, sizeof(r
->header
));
639 if (cups_read(r
->fd
, (unsigned char *)&(r
->header
), len
) < len
)
643 * Swap bytes as needed...
646 if (r
->sync
== CUPS_RASTER_REVSYNC
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
647 for (len
= 81, s
= (union swap_s
*)&(r
->header
.AdvanceDistance
);
650 s
->v
= (((((s
->b
[3] << 8) | s
->b
[2]) << 8) | s
->b
[1]) << 8) | s
->b
[0];
653 * Update the header and row count...
656 cups_raster_update(r
);
663 * 'cups_raster_update()' - Update the raster header and row count for the
668 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
670 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
671 r
->header
.cupsNumColors
== 0)
674 * Set the "cupsNumColors" field according to the colorspace...
677 switch (r
->header
.cupsColorSpace
)
681 case CUPS_CSPACE_WHITE
:
682 case CUPS_CSPACE_GOLD
:
683 case CUPS_CSPACE_SILVER
:
684 r
->header
.cupsNumColors
= 1;
687 case CUPS_CSPACE_RGB
:
688 case CUPS_CSPACE_CMY
:
689 case CUPS_CSPACE_YMC
:
690 case CUPS_CSPACE_CIEXYZ
:
691 case CUPS_CSPACE_CIELab
:
692 case CUPS_CSPACE_ICC1
:
693 case CUPS_CSPACE_ICC2
:
694 case CUPS_CSPACE_ICC3
:
695 case CUPS_CSPACE_ICC4
:
696 case CUPS_CSPACE_ICC5
:
697 case CUPS_CSPACE_ICC6
:
698 case CUPS_CSPACE_ICC7
:
699 case CUPS_CSPACE_ICC8
:
700 case CUPS_CSPACE_ICC9
:
701 case CUPS_CSPACE_ICCA
:
702 case CUPS_CSPACE_ICCB
:
703 case CUPS_CSPACE_ICCC
:
704 case CUPS_CSPACE_ICCD
:
705 case CUPS_CSPACE_ICCE
:
706 case CUPS_CSPACE_ICCF
:
707 r
->header
.cupsNumColors
= 3;
710 case CUPS_CSPACE_RGBA
:
711 case CUPS_CSPACE_RGBW
:
712 case CUPS_CSPACE_CMYK
:
713 case CUPS_CSPACE_YMCK
:
714 case CUPS_CSPACE_KCMY
:
715 case CUPS_CSPACE_GMCK
:
716 case CUPS_CSPACE_GMCS
:
717 r
->header
.cupsNumColors
= 4;
720 case CUPS_CSPACE_KCMYcm
:
721 if (r
->header
.cupsBitsPerPixel
< 8)
722 r
->header
.cupsNumColors
= 6;
724 r
->header
.cupsNumColors
= 4;
730 * Set the number of bytes per pixel/color...
733 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
734 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
736 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
739 * Set the number of remaining rows...
742 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
743 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
745 r
->remaining
= r
->header
.cupsHeight
;
748 * Allocate the read/write buffer...
751 if (r
->pixels
!= NULL
)
754 r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1);
755 r
->pcurrent
= r
->pixels
;
756 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
762 * 'cups_raster_write()' - Write a row of raster data...
765 static int /* O - Number of bytes written */
766 cups_raster_write(cups_raster_t
*r
) /* I - Raster stream */
768 unsigned char *start
, /* Start of sequence */
769 *ptr
, /* Current pointer in sequence */
770 byte
; /* Byte to write */
771 int count
; /* Count */
775 fprintf(stderr
, "cups_raster_write(r=%p)\n", r
);
779 * Write the row repeat count...
784 if (cups_write(r
->fd
, &byte
, 1) < 1)
787 fputs("cups_raster_write: Unable to write row repeat count...\n",
795 * Write using a modified TIFF "packbits" compression...
798 for (ptr
= r
->pixels
; ptr
< r
->pend
;)
806 * Encode a single pixel at the end...
810 if (cups_write(r
->fd
, &byte
, 1) < 1)
813 fputs("cups_raster_write: Unable to write last pixel count...\n", stderr
);
819 if (cups_write(r
->fd
, start
, r
->bpp
) < r
->bpp
)
822 fputs("cups_raster_write: Unable to write last pixel data...\n", stderr
);
828 else if (!memcmp(start
, ptr
, r
->bpp
))
831 * Encode a sequence of repeating pixels...
834 for (count
= 2; count
< 128 && ptr
< (r
->pend
- r
->bpp
); count
++, ptr
+= r
->bpp
)
835 if (memcmp(ptr
, ptr
+ r
->bpp
, r
->bpp
) != 0)
842 if (cups_write(r
->fd
, &byte
, 1) < 1)
845 fputs("cups_raster_write: Unable to write repeated pixel count...\n", stderr
);
851 if (cups_write(r
->fd
, start
, r
->bpp
) < r
->bpp
)
854 fputs("cups_raster_write: Unable to write repeated pixel data...\n", stderr
);
863 * Encode a sequence of non-repeating pixels...
866 for (count
= 1; count
< 127 && ptr
< (r
->pend
- r
->bpp
); count
++, ptr
+= r
->bpp
)
867 if (!memcmp(ptr
, ptr
+ r
->bpp
, r
->bpp
))
870 if (ptr
>= (r
->pend
- r
->bpp
) && count
< 128)
878 if (cups_write(r
->fd
, &byte
, 1) < 1)
881 fputs("cups_raster_write: Unable to write non-repeating pixel count...\n", stderr
);
889 if (cups_write(r
->fd
, start
, count
) < count
)
892 fputs("cups_raster_write: Unable to write non-repeating pixel data...\n", stderr
);
900 return (r
->header
.cupsBytesPerLine
);
905 * 'cups_read()' - Read bytes from a file.
908 static int /* O - Bytes read or -1 */
909 cups_read(int fd
, /* I - File descriptor */
910 unsigned char *buf
, /* I - Buffer for read */
911 int bytes
) /* I - Number of bytes to read */
913 int count
, /* Number of bytes read */
914 total
; /* Total bytes read */
917 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
919 count
= read(fd
, buf
, bytes
- total
);
937 * 'cups_write()' - Write bytes to a file.
940 static int /* O - Bytes written or -1 */
941 cups_write(int fd
, /* I - File descriptor */
942 const unsigned char *buf
, /* I - Bytes to write */
943 int bytes
) /* I - Number of bytes to write */
945 int count
, /* Number of bytes written */
946 total
; /* Total bytes written */
949 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
951 count
= write(fd
, buf
, bytes
- total
);
967 * End of "$Id: raster.c 5523 2006-05-15 05:02:43Z mike $".