]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/raster.c
2 * "$Id: raster.c 4903 2006-01-10 20:02:46Z 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 V1 raster page header.
40 * cupsRasterReadHeader2() - Read a V2 raster page header.
41 * cupsRasterReadPixels() - Read raster pixels.
42 * cupsRasterWriteHeader() - Write a V1 raster page header.
43 * cupsRasterWriteHeader2() - Write a V2 raster page header.
44 * cupsRasterWritePixels() - Write raster pixels.
45 * cups_raster_update() - Update the raster header and row count for the
47 * cups_raster_write() - Write a row of raster data...
48 * cups_read() - Read bytes from a file.
49 * cups_write() - Write bytes to a file.
53 * Include necessary headers...
60 #include <cups/string.h>
62 #if defined(WIN32) || defined(__EMX__)
66 #endif /* WIN32 || __EMX__ */
73 static unsigned cups_raster_read_header(cups_raster_t
*r
);
74 static void cups_raster_update(cups_raster_t
*r
);
75 static int cups_raster_write(cups_raster_t
*r
);
76 static int cups_read(int fd
, unsigned char *buf
, int bytes
);
77 static int cups_write(int fd
, const unsigned char *buf
, int bytes
);
81 * 'cupsRasterClose()' - Close a raster stream.
85 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
98 * 'cupsRasterOpen()' - Open a raster stream.
101 cups_raster_t
* /* O - New stream */
102 cupsRasterOpen(int fd
, /* I - File descriptor */
103 cups_mode_t mode
) /* I - Mode */
105 cups_raster_t
*r
; /* New stream */
108 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
114 if (mode
== CUPS_RASTER_READ
)
117 * Open for read - get sync word...
120 if (cups_read(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
))
127 if (r
->sync
!= CUPS_RASTER_SYNC
&&
128 r
->sync
!= CUPS_RASTER_REVSYNC
&&
129 r
->sync
!= CUPS_RASTER_SYNCv1
&&
130 r
->sync
!= CUPS_RASTER_REVSYNCv1
)
139 * Open for write - put sync word...
142 r
->sync
= CUPS_RASTER_SYNC
;
143 if (cups_write(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
))
156 * 'cupsRasterReadHeader()' - Read a V1 raster page header.
159 unsigned /* O - 1 on success, 0 on fail */
160 cupsRasterReadHeader(
161 cups_raster_t
*r
, /* I - Raster stream */
162 cups_page_header_t
*h
) /* I - Pointer to header data */
165 * Get the raster header...
168 if (!cups_raster_read_header(r
))
172 * Copy the header to the user-supplied buffer...
175 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
182 * 'cupsRasterReadHeader2()' - Read a V2 raster page header.
187 unsigned /* O - 1 on success, 0 on fail */
188 cupsRasterReadHeader2(
189 cups_raster_t
*r
, /* I - Raster stream */
190 cups_page_header2_t
*h
) /* I - Pointer to header data */
193 * Get the raster header...
196 if (!cups_raster_read_header(r
))
200 * Copy the header to the user-supplied buffer...
203 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
210 * 'cupsRasterReadPixels()' - Read raster pixels.
213 unsigned /* O - Number of bytes read */
214 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
215 unsigned char *p
, /* I - Pointer to pixel buffer */
216 unsigned len
) /* I - Number of bytes to read */
218 int bytes
; /* Bytes read */
219 unsigned remaining
; /* Bytes remaining */
220 unsigned char *ptr
, /* Pointer to read buffer */
221 byte
; /* Byte from file */
224 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0)
229 while (remaining
> 0 && r
->remaining
> 0)
234 * Need to read a new row...
237 if (remaining
== r
->header
.cupsBytesPerLine
)
242 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
245 * Read without compression...
248 if (cups_read(r
->fd
, ptr
, r
->header
.cupsBytesPerLine
) <
249 r
->header
.cupsBytesPerLine
)
257 * Read using a modified TIFF "packbits" compression...
260 unsigned char *temp
; /* Pointer into buffer */
261 int count
; /* Repetition count */
264 if (cups_read(r
->fd
, &byte
, 1) < 1)
273 bytes
= r
->header
.cupsBytesPerLine
;
278 * Get a new repeat count...
281 if (cups_read(r
->fd
, &byte
, 1) < 1)
287 * Copy N literal pixels...
290 count
= (257 - byte
) * r
->bpp
;
295 if (cups_read(r
->fd
, temp
, count
) < count
)
304 * Repeat the next N bytes...
307 count
= (byte
+ 1) * r
->bpp
;
316 if (cups_read(r
->fd
, temp
, r
->bpp
) < r
->bpp
)
324 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
332 if (r
->header
.cupsBitsPerColor
== 16 &&
333 (r
->sync
== CUPS_RASTER_REVSYNC
|| r
->sync
== CUPS_RASTER_REVSYNCv1
))
336 * Swap bytes in the pixel data...
343 for (temp
= ptr
, count
= r
->header
.cupsBytesPerLine
;
345 temp
+= 2, count
-= 2)
353 if (remaining
>= r
->header
.cupsBytesPerLine
)
355 bytes
= r
->header
.cupsBytesPerLine
;
356 r
->pcurrent
= r
->pixels
;
363 r
->pcurrent
= r
->pixels
+ bytes
;
367 memcpy(p
, ptr
, bytes
);
372 * Copy fragment from buffer...
375 if ((bytes
= r
->pend
- r
->pcurrent
) > remaining
)
378 memcpy(p
, r
->pcurrent
, bytes
);
379 r
->pcurrent
+= bytes
;
381 if (r
->pcurrent
>= r
->pend
)
383 r
->pcurrent
= r
->pixels
;
398 * 'cupsRasterWriteHeader()' - Write a V2 raster page header.
401 unsigned /* O - 1 on success, 0 on failure */
402 cupsRasterWriteHeader(
403 cups_raster_t
*r
, /* I - Raster stream */
404 cups_page_header_t
*h
) /* I - Raster page header */
406 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
410 * Make a copy of the header, and compute the number of raster
411 * lines in the page image...
414 memset(&(r
->header
), 0, sizeof(r
->header
));
415 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
417 cups_raster_update(r
);
420 * Write the raster header...
423 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
429 * 'cupsRasterWriteHeader2()' - Write a V2 raster page header.
434 unsigned /* O - 1 on success, 0 on failure */
435 cupsRasterWriteHeader2(
436 cups_raster_t
*r
, /* I - Raster stream */
437 cups_page_header2_t
*h
) /* I - Raster page header */
439 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
443 * Make a copy of the header, and compute the number of raster
444 * lines in the page image...
447 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
449 cups_raster_update(r
);
452 * Write the raster header...
455 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
461 * 'cupsRasterWritePixels()' - Write raster pixels.
464 unsigned /* O - Number of bytes written */
465 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
466 unsigned char *p
, /* I - Bytes to write */
467 unsigned len
)/* I - Number of bytes to write */
469 int bytes
; /* Bytes read */
470 unsigned remaining
; /* Bytes remaining */
473 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
|| r
->remaining
== 0)
478 while (remaining
> 0)
481 * Figure out the number of remaining bytes on the current line...
484 if ((bytes
= remaining
) > (r
->pend
- r
->pcurrent
))
485 bytes
= r
->pend
- r
->pcurrent
;
490 * Check to see if this line is the same as the previous line...
493 if (memcmp(p
, r
->pcurrent
, bytes
))
495 if (!cups_raster_write(r
))
503 * Mark more bytes as the same...
506 r
->pcurrent
+= bytes
;
508 if (r
->pcurrent
>= r
->pend
)
511 * Increase the repeat count...
515 r
->pcurrent
= r
->pixels
;
518 * Flush out this line if it is the last one...
522 if (r
->remaining
== 0)
523 return (cups_raster_write(r
));
524 else if (r
->count
== 256)
526 cups_raster_write(r
);
536 * Copy the raster data to the buffer...
539 memcpy(r
->pcurrent
, p
, bytes
);
541 r
->pcurrent
+= bytes
;
543 if (r
->pcurrent
>= r
->pend
)
546 * Increase the repeat count...
550 r
->pcurrent
= r
->pixels
;
553 * Flush out this line if it is the last one...
557 if (r
->remaining
== 0)
558 return (cups_raster_write(r
));
571 * 'cups_raster_read_header()' - Read a raster page header.
574 static unsigned /* O - 1 on success, 0 on fail */
575 cups_raster_read_header(
576 cups_raster_t
*r
) /* I - Raster stream */
578 int len
; /* Number of words to swap */
579 union swap_s
/* Swapping structure */
586 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
590 * Get the length of the raster header...
593 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
594 len
= sizeof(cups_page_header_t
);
596 len
= sizeof(cups_page_header2_t
);
602 memset(&(r
->header
), 0, sizeof(r
->header
));
604 if (cups_read(r
->fd
, (unsigned char *)&(r
->header
), len
) < len
)
608 * Swap bytes as needed...
611 if (r
->sync
== CUPS_RASTER_REVSYNC
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
612 for (len
= 74, s
= (union swap_s
*)&(r
->header
.AdvanceDistance
);
615 s
->v
= (((((s
->b
[3] << 8) | s
->b
[2]) << 8) | s
->b
[1]) << 8) | s
->b
[0];
618 * Update the header and row count...
621 cups_raster_update(r
);
628 * 'cups_raster_update()' - Update the raster header and row count for the
633 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
635 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
638 * Set the "cupsNumColors" field according to the colorspace...
641 switch (r
->header
.cupsColorSpace
)
645 case CUPS_CSPACE_WHITE
:
646 case CUPS_CSPACE_GOLD
:
647 case CUPS_CSPACE_SILVER
:
648 case CUPS_CSPACE_ICC1
:
649 r
->header
.cupsNumColors
= 1;
652 case CUPS_CSPACE_ICC2
:
653 r
->header
.cupsNumColors
= 2;
656 case CUPS_CSPACE_RGB
:
657 case CUPS_CSPACE_CMY
:
658 case CUPS_CSPACE_YMC
:
659 case CUPS_CSPACE_CIEXYZ
:
660 case CUPS_CSPACE_CIELab
:
661 case CUPS_CSPACE_ICC3
:
662 r
->header
.cupsNumColors
= 3;
665 case CUPS_CSPACE_RGBA
:
666 case CUPS_CSPACE_RGBW
:
667 case CUPS_CSPACE_CMYK
:
668 case CUPS_CSPACE_YMCK
:
669 case CUPS_CSPACE_KCMY
:
670 case CUPS_CSPACE_GMCK
:
671 case CUPS_CSPACE_GMCS
:
672 case CUPS_CSPACE_ICC4
:
673 r
->header
.cupsNumColors
= 4;
676 case CUPS_CSPACE_KCMYcm
:
677 if (r
->header
.cupsBitsPerPixel
< 8)
678 r
->header
.cupsNumColors
= 6;
680 r
->header
.cupsNumColors
= 4;
683 case CUPS_CSPACE_ICC5
:
684 case CUPS_CSPACE_ICC6
:
685 case CUPS_CSPACE_ICC7
:
686 case CUPS_CSPACE_ICC8
:
687 case CUPS_CSPACE_ICC9
:
688 case CUPS_CSPACE_ICCA
:
689 case CUPS_CSPACE_ICCB
:
690 case CUPS_CSPACE_ICCC
:
691 case CUPS_CSPACE_ICCD
:
692 case CUPS_CSPACE_ICCE
:
693 case CUPS_CSPACE_ICCF
:
694 r
->header
.cupsNumColors
= r
->header
.cupsColorSpace
-
695 CUPS_CSPACE_ICC1
+ 1;
701 * Set the number of bytes per pixel/color...
704 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
705 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
707 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
710 * Set the number of remaining rows...
713 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
714 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
716 r
->remaining
= r
->header
.cupsHeight
;
719 * Allocate the read/write buffer...
722 if (r
->pixels
!= NULL
)
725 r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1);
726 r
->pcurrent
= r
->pixels
;
727 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
733 * 'cups_raster_write()' - Write a row of raster data...
736 static int /* O - Number of bytes written */
737 cups_raster_write(cups_raster_t
*r
) /* I - Raster stream */
739 unsigned char *start
, /* Start of sequence */
740 *ptr
, /* Current pointer in sequence */
741 byte
; /* Byte to write */
742 int count
; /* Count */
746 * Write the row repeat count...
751 if (cups_write(r
->fd
, &byte
, 1) < 1)
755 * Write using a modified TIFF "packbits" compression...
758 for (ptr
= r
->pixels
; ptr
< r
->pend
;)
766 * Encode a single pixel at the end...
770 if (cups_write(r
->fd
, &byte
, 1) < 1)
773 if (cups_write(r
->fd
, start
, r
->bpp
) < r
->bpp
)
776 else if (!memcmp(start
, ptr
, r
->bpp
))
779 * Encode a sequence of repeating pixels...
782 for (count
= 2; count
< 128 && ptr
< (r
->pend
- r
->bpp
); count
++, ptr
+= r
->bpp
)
783 if (memcmp(ptr
, ptr
+ r
->bpp
, r
->bpp
) != 0)
790 if (cups_write(r
->fd
, &byte
, 1) < 1)
793 if (cups_write(r
->fd
, start
, r
->bpp
) < r
->bpp
)
799 * Encode a sequence of non-repeating pixels...
802 for (count
= 1; count
< 127 && ptr
< (r
->pend
- r
->bpp
); count
++, ptr
+= r
->bpp
)
803 if (!memcmp(ptr
, ptr
+ r
->bpp
, r
->bpp
))
806 if (ptr
>= (r
->pend
- r
->bpp
) && count
< 128)
814 if (cups_write(r
->fd
, &byte
, 1) < 1)
819 if (cups_write(r
->fd
, start
, count
) < count
)
824 return (r
->header
.cupsBytesPerLine
);
829 * 'cups_read()' - Read bytes from a file.
832 static int /* O - Bytes read or -1 */
833 cups_read(int fd
, /* I - File descriptor */
834 unsigned char *buf
, /* I - Buffer for read */
835 int bytes
) /* I - Number of bytes to read */
837 int count
, /* Number of bytes read */
838 total
; /* Total bytes read */
841 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
843 count
= read(fd
, buf
, bytes
- total
);
861 * 'cups_write()' - Write bytes to a file.
864 static int /* O - Bytes written or -1 */
865 cups_write(int fd
, /* I - File descriptor */
866 const unsigned char *buf
, /* I - Bytes to write */
867 int bytes
) /* I - Number of bytes to write */
869 int count
, /* Number of bytes written */
870 total
; /* Total bytes written */
873 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
875 count
= write(fd
, buf
, bytes
- total
);
891 * End of "$Id: raster.c 4903 2006-01-10 20:02:46Z mike $".