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 $".