]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/raster.c
2 * "$Id: raster.c 5192 2006-02-27 03:08:47Z 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__ */
77 static unsigned cups_raster_read_header(cups_raster_t
*r
);
78 static void cups_raster_update(cups_raster_t
*r
);
79 static int cups_raster_write(cups_raster_t
*r
);
80 static int cups_read(int fd
, unsigned char *buf
, int bytes
);
81 static int cups_write(int fd
, const unsigned char *buf
, int bytes
);
85 * 'cupsRasterClose()' - Close a raster stream.
89 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
102 * 'cupsRasterOpen()' - Open a raster stream.
105 cups_raster_t
* /* O - New stream */
106 cupsRasterOpen(int fd
, /* I - File descriptor */
107 cups_mode_t mode
) /* I - Mode */
109 cups_raster_t
*r
; /* New stream */
112 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
118 if (mode
== CUPS_RASTER_READ
)
121 * Open for read - get sync word...
124 if (cups_read(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
))
131 if (r
->sync
!= CUPS_RASTER_SYNC
&&
132 r
->sync
!= CUPS_RASTER_REVSYNC
&&
133 r
->sync
!= CUPS_RASTER_SYNCv1
&&
134 r
->sync
!= CUPS_RASTER_REVSYNCv1
)
143 * Open for write - put sync word...
146 r
->sync
= CUPS_RASTER_SYNC
;
147 if (cups_write(r
->fd
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
))
160 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
161 * V1 page header structure.
164 unsigned /* O - 1 on success, 0 on fail */
165 cupsRasterReadHeader(
166 cups_raster_t
*r
, /* I - Raster stream */
167 cups_page_header_t
*h
) /* I - Pointer to header data */
170 * Get the raster header...
173 if (!cups_raster_read_header(r
))
177 * Copy the header to the user-supplied buffer...
180 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
187 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
188 * V2 page header structure.
193 unsigned /* O - 1 on success, 0 on fail */
194 cupsRasterReadHeader2(
195 cups_raster_t
*r
, /* I - Raster stream */
196 cups_page_header2_t
*h
) /* I - Pointer to header data */
199 * Get the raster header...
202 if (!cups_raster_read_header(r
))
206 * Copy the header to the user-supplied buffer...
209 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
216 * 'cupsRasterReadPixels()' - Read raster pixels.
219 unsigned /* O - Number of bytes read */
220 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
221 unsigned char *p
, /* I - Pointer to pixel buffer */
222 unsigned len
) /* I - Number of bytes to read */
224 int bytes
; /* Bytes read */
225 unsigned remaining
; /* Bytes remaining */
226 unsigned char *ptr
, /* Pointer to read buffer */
227 byte
; /* Byte from file */
230 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0)
235 while (remaining
> 0 && r
->remaining
> 0)
240 * Need to read a new row...
243 if (remaining
== r
->header
.cupsBytesPerLine
)
248 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
251 * Read without compression...
254 if (cups_read(r
->fd
, ptr
, r
->header
.cupsBytesPerLine
) <
255 r
->header
.cupsBytesPerLine
)
263 * Read using a modified TIFF "packbits" compression...
266 unsigned char *temp
; /* Pointer into buffer */
267 int count
; /* Repetition count */
270 if (cups_read(r
->fd
, &byte
, 1) < 1)
279 bytes
= r
->header
.cupsBytesPerLine
;
284 * Get a new repeat count...
287 if (cups_read(r
->fd
, &byte
, 1) < 1)
293 * Copy N literal pixels...
296 count
= (257 - byte
) * r
->bpp
;
301 if (cups_read(r
->fd
, temp
, count
) < count
)
310 * Repeat the next N bytes...
313 count
= (byte
+ 1) * r
->bpp
;
322 if (cups_read(r
->fd
, temp
, r
->bpp
) < r
->bpp
)
330 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
338 if (r
->header
.cupsBitsPerColor
== 16 &&
339 (r
->sync
== CUPS_RASTER_REVSYNC
|| r
->sync
== CUPS_RASTER_REVSYNCv1
))
342 * Swap bytes in the pixel data...
349 for (temp
= ptr
, count
= r
->header
.cupsBytesPerLine
;
351 temp
+= 2, count
-= 2)
359 if (remaining
>= r
->header
.cupsBytesPerLine
)
361 bytes
= r
->header
.cupsBytesPerLine
;
362 r
->pcurrent
= r
->pixels
;
369 r
->pcurrent
= r
->pixels
+ bytes
;
373 memcpy(p
, ptr
, bytes
);
378 * Copy fragment from buffer...
381 if ((bytes
= r
->pend
- r
->pcurrent
) > remaining
)
384 memcpy(p
, r
->pcurrent
, bytes
);
385 r
->pcurrent
+= bytes
;
387 if (r
->pcurrent
>= r
->pend
)
389 r
->pcurrent
= r
->pixels
;
404 * 'cupsRasterWriteHeader()' - Write a raster page header from a V1 page
408 unsigned /* O - 1 on success, 0 on failure */
409 cupsRasterWriteHeader(
410 cups_raster_t
*r
, /* I - Raster stream */
411 cups_page_header_t
*h
) /* I - Raster page header */
413 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
417 * Make a copy of the header, and compute the number of raster
418 * lines in the page image...
421 memset(&(r
->header
), 0, sizeof(r
->header
));
422 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
424 cups_raster_update(r
);
427 * Write the raster header...
430 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
436 * 'cupsRasterWriteHeader2()' - Write a raster page header from a V2 page
442 unsigned /* O - 1 on success, 0 on failure */
443 cupsRasterWriteHeader2(
444 cups_raster_t
*r
, /* I - Raster stream */
445 cups_page_header2_t
*h
) /* I - Raster page header */
447 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
)
451 * Make a copy of the header, and compute the number of raster
452 * lines in the page image...
455 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
457 cups_raster_update(r
);
460 * Write the raster header...
463 return (cups_write(r
->fd
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
469 * 'cupsRasterWritePixels()' - Write raster pixels.
472 unsigned /* O - Number of bytes written */
473 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
474 unsigned char *p
, /* I - Bytes to write */
475 unsigned len
)/* I - Number of bytes to write */
477 int bytes
; /* Bytes read */
478 unsigned remaining
; /* Bytes remaining */
481 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_WRITE
|| r
->remaining
== 0)
486 while (remaining
> 0)
489 * Figure out the number of remaining bytes on the current line...
492 if ((bytes
= remaining
) > (r
->pend
- r
->pcurrent
))
493 bytes
= r
->pend
- r
->pcurrent
;
498 * Check to see if this line is the same as the previous line...
501 if (memcmp(p
, r
->pcurrent
, bytes
))
503 if (!cups_raster_write(r
))
511 * Mark more bytes as the same...
514 r
->pcurrent
+= bytes
;
516 if (r
->pcurrent
>= r
->pend
)
519 * Increase the repeat count...
523 r
->pcurrent
= r
->pixels
;
526 * Flush out this line if it is the last one...
530 if (r
->remaining
== 0)
531 return (cups_raster_write(r
));
532 else if (r
->count
== 256)
534 cups_raster_write(r
);
544 * Copy the raster data to the buffer...
547 memcpy(r
->pcurrent
, p
, bytes
);
549 r
->pcurrent
+= bytes
;
551 if (r
->pcurrent
>= r
->pend
)
554 * Increase the repeat count...
558 r
->pcurrent
= r
->pixels
;
561 * Flush out this line if it is the last one...
565 if (r
->remaining
== 0)
566 return (cups_raster_write(r
));
579 * 'cups_raster_read_header()' - Read a raster page header.
582 static unsigned /* O - 1 on success, 0 on fail */
583 cups_raster_read_header(
584 cups_raster_t
*r
) /* I - Raster stream */
586 int len
; /* Number of words to swap */
587 union swap_s
/* Swapping structure */
594 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
598 * Get the length of the raster header...
601 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
602 len
= sizeof(cups_page_header_t
);
604 len
= sizeof(cups_page_header2_t
);
610 memset(&(r
->header
), 0, sizeof(r
->header
));
612 if (cups_read(r
->fd
, (unsigned char *)&(r
->header
), len
) < len
)
616 * Swap bytes as needed...
619 if (r
->sync
== CUPS_RASTER_REVSYNC
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
620 for (len
= 81, s
= (union swap_s
*)&(r
->header
.AdvanceDistance
);
623 s
->v
= (((((s
->b
[3] << 8) | s
->b
[2]) << 8) | s
->b
[1]) << 8) | s
->b
[0];
626 * Update the header and row count...
629 cups_raster_update(r
);
636 * 'cups_raster_update()' - Update the raster header and row count for the
641 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
643 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
646 * Set the "cupsNumColors" field according to the colorspace...
649 switch (r
->header
.cupsColorSpace
)
653 case CUPS_CSPACE_WHITE
:
654 case CUPS_CSPACE_GOLD
:
655 case CUPS_CSPACE_SILVER
:
656 case CUPS_CSPACE_ICC1
:
657 r
->header
.cupsNumColors
= 1;
660 case CUPS_CSPACE_ICC2
:
661 r
->header
.cupsNumColors
= 2;
664 case CUPS_CSPACE_RGB
:
665 case CUPS_CSPACE_CMY
:
666 case CUPS_CSPACE_YMC
:
667 case CUPS_CSPACE_CIEXYZ
:
668 case CUPS_CSPACE_CIELab
:
669 case CUPS_CSPACE_ICC3
:
670 r
->header
.cupsNumColors
= 3;
673 case CUPS_CSPACE_RGBA
:
674 case CUPS_CSPACE_RGBW
:
675 case CUPS_CSPACE_CMYK
:
676 case CUPS_CSPACE_YMCK
:
677 case CUPS_CSPACE_KCMY
:
678 case CUPS_CSPACE_GMCK
:
679 case CUPS_CSPACE_GMCS
:
680 case CUPS_CSPACE_ICC4
:
681 r
->header
.cupsNumColors
= 4;
684 case CUPS_CSPACE_KCMYcm
:
685 if (r
->header
.cupsBitsPerPixel
< 8)
686 r
->header
.cupsNumColors
= 6;
688 r
->header
.cupsNumColors
= 4;
691 case CUPS_CSPACE_ICC5
:
692 case CUPS_CSPACE_ICC6
:
693 case CUPS_CSPACE_ICC7
:
694 case CUPS_CSPACE_ICC8
:
695 case CUPS_CSPACE_ICC9
:
696 case CUPS_CSPACE_ICCA
:
697 case CUPS_CSPACE_ICCB
:
698 case CUPS_CSPACE_ICCC
:
699 case CUPS_CSPACE_ICCD
:
700 case CUPS_CSPACE_ICCE
:
701 case CUPS_CSPACE_ICCF
:
702 r
->header
.cupsNumColors
= r
->header
.cupsColorSpace
-
703 CUPS_CSPACE_ICC1
+ 1;
709 * Set the number of bytes per pixel/color...
712 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
713 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
715 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
718 * Set the number of remaining rows...
721 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
722 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
724 r
->remaining
= r
->header
.cupsHeight
;
727 * Allocate the read/write buffer...
730 if (r
->pixels
!= NULL
)
733 r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1);
734 r
->pcurrent
= r
->pixels
;
735 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
741 * 'cups_raster_write()' - Write a row of raster data...
744 static int /* O - Number of bytes written */
745 cups_raster_write(cups_raster_t
*r
) /* I - Raster stream */
747 unsigned char *start
, /* Start of sequence */
748 *ptr
, /* Current pointer in sequence */
749 byte
; /* Byte to write */
750 int count
; /* Count */
754 * Write the row repeat count...
759 if (cups_write(r
->fd
, &byte
, 1) < 1)
763 * Write using a modified TIFF "packbits" compression...
766 for (ptr
= r
->pixels
; ptr
< r
->pend
;)
774 * Encode a single pixel at the end...
778 if (cups_write(r
->fd
, &byte
, 1) < 1)
781 if (cups_write(r
->fd
, start
, r
->bpp
) < r
->bpp
)
784 else if (!memcmp(start
, ptr
, r
->bpp
))
787 * Encode a sequence of repeating pixels...
790 for (count
= 2; count
< 128 && ptr
< (r
->pend
- r
->bpp
); count
++, ptr
+= r
->bpp
)
791 if (memcmp(ptr
, ptr
+ r
->bpp
, r
->bpp
) != 0)
798 if (cups_write(r
->fd
, &byte
, 1) < 1)
801 if (cups_write(r
->fd
, start
, r
->bpp
) < r
->bpp
)
807 * Encode a sequence of non-repeating pixels...
810 for (count
= 1; count
< 127 && ptr
< (r
->pend
- r
->bpp
); count
++, ptr
+= r
->bpp
)
811 if (!memcmp(ptr
, ptr
+ r
->bpp
, r
->bpp
))
814 if (ptr
>= (r
->pend
- r
->bpp
) && count
< 128)
822 if (cups_write(r
->fd
, &byte
, 1) < 1)
827 if (cups_write(r
->fd
, start
, count
) < count
)
832 return (r
->header
.cupsBytesPerLine
);
837 * 'cups_read()' - Read bytes from a file.
840 static int /* O - Bytes read or -1 */
841 cups_read(int fd
, /* I - File descriptor */
842 unsigned char *buf
, /* I - Buffer for read */
843 int bytes
) /* I - Number of bytes to read */
845 int count
, /* Number of bytes read */
846 total
; /* Total bytes read */
849 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
851 count
= read(fd
, buf
, bytes
- total
);
869 * 'cups_write()' - Write bytes to a file.
872 static int /* O - Bytes written or -1 */
873 cups_write(int fd
, /* I - File descriptor */
874 const unsigned char *buf
, /* I - Bytes to write */
875 int bytes
) /* I - Number of bytes to write */
877 int count
, /* Number of bytes written */
878 total
; /* Total bytes written */
881 for (total
= 0; total
< bytes
; total
+= count
, buf
+= count
)
883 count
= write(fd
, buf
, bytes
- total
);
899 * End of "$Id: raster.c 5192 2006-02-27 03:08:47Z mike $".