]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/raster.c
Load cups into easysw/current.
[thirdparty/cups.git] / filter / raster.c
CommitLineData
ef416fc2 1/*
b423cd4c 2 * "$Id: raster.c 5192 2006-02-27 03:08:47Z mike $"
ef416fc2 3 *
4 * Raster file routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2006 by Easy Software Products.
7 *
8 * This file is part of the CUPS Imaging library.
9 *
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
15 * at:
16 *
17 * Attn: CUPS Licensing Information
18 * Easy Software Products
19 * 44141 Airport View Drive, Suite 204
20 * Hollywood, Maryland 20636 USA
21 *
22 * Voice: (301) 373-9600
23 * EMail: cups-info@cups.org
24 * WWW: http://www.cups.org
25 *
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
31 * agreement.
32 *
33 * This file is subject to the Apple OS-Developed Software exception.
34 *
35 * Contents:
36 *
37 * cupsRasterClose() - Close a raster stream.
38 * cupsRasterOpen() - Open a raster stream.
b423cd4c 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.
ef416fc2 43 * cupsRasterReadPixels() - Read raster pixels.
b423cd4c 44 * cupsRasterWriteHeader() - Write a raster page header from a V1 page
45 * header structure.
46 * cupsRasterWriteHeader2() - Write a raster page header from a V2 page
47 * header structure.
ef416fc2 48 * cupsRasterWritePixels() - Write raster pixels.
49 * cups_raster_update() - Update the raster header and row count for the
50 * current page.
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.
54 */
55
56/*
57 * Include necessary headers...
58 */
59
60#include "raster.h"
61#include <stdio.h>
62#include <stdlib.h>
63#include <errno.h>
64#include <cups/string.h>
65
66#if defined(WIN32) || defined(__EMX__)
67# include <io.h>
68#else
69# include <unistd.h>
70#endif /* WIN32 || __EMX__ */
71
72
73/*
74 * Local functions...
75 */
76
77static unsigned cups_raster_read_header(cups_raster_t *r);
78static void cups_raster_update(cups_raster_t *r);
79static int cups_raster_write(cups_raster_t *r);
80static int cups_read(int fd, unsigned char *buf, int bytes);
81static int cups_write(int fd, const unsigned char *buf, int bytes);
82
83
84/*
85 * 'cupsRasterClose()' - Close a raster stream.
86 */
87
88void
89cupsRasterClose(cups_raster_t *r) /* I - Stream to close */
90{
91 if (r != NULL)
92 {
93 if (r->pixels)
94 free(r->pixels);
95
96 free(r);
97 }
98}
99
100
101/*
102 * 'cupsRasterOpen()' - Open a raster stream.
103 */
104
105cups_raster_t * /* O - New stream */
106cupsRasterOpen(int fd, /* I - File descriptor */
107 cups_mode_t mode) /* I - Mode */
108{
109 cups_raster_t *r; /* New stream */
110
111
112 if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL)
113 return (NULL);
114
115 r->fd = fd;
116 r->mode = mode;
117
118 if (mode == CUPS_RASTER_READ)
119 {
120 /*
121 * Open for read - get sync word...
122 */
123
124 if (cups_read(r->fd, (unsigned char *)&(r->sync), sizeof(r->sync))
125 < sizeof(r->sync))
126 {
127 free(r);
128 return (NULL);
129 }
130
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)
135 {
136 free(r);
137 return (NULL);
138 }
139 }
140 else
141 {
142 /*
143 * Open for write - put sync word...
144 */
145
146 r->sync = CUPS_RASTER_SYNC;
147 if (cups_write(r->fd, (unsigned char *)&(r->sync), sizeof(r->sync))
148 < sizeof(r->sync))
149 {
150 free(r);
151 return (NULL);
152 }
153 }
154
155 return (r);
156}
157
158
159/*
b423cd4c 160 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
161 * V1 page header structure.
ef416fc2 162 */
163
164unsigned /* O - 1 on success, 0 on fail */
165cupsRasterReadHeader(
166 cups_raster_t *r, /* I - Raster stream */
167 cups_page_header_t *h) /* I - Pointer to header data */
168{
169 /*
170 * Get the raster header...
171 */
172
173 if (!cups_raster_read_header(r))
174 return (0);
175
176 /*
177 * Copy the header to the user-supplied buffer...
178 */
179
180 memcpy(h, &(r->header), sizeof(cups_page_header_t));
181
182 return (1);
183}
184
185
186/*
b423cd4c 187 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
188 * V2 page header structure.
ef416fc2 189 *
190 * @since CUPS 1.2@
191 */
192
193unsigned /* O - 1 on success, 0 on fail */
194cupsRasterReadHeader2(
195 cups_raster_t *r, /* I - Raster stream */
196 cups_page_header2_t *h) /* I - Pointer to header data */
197{
198 /*
199 * Get the raster header...
200 */
201
202 if (!cups_raster_read_header(r))
203 return (0);
204
205 /*
206 * Copy the header to the user-supplied buffer...
207 */
208
209 memcpy(h, &(r->header), sizeof(cups_page_header2_t));
210
211 return (1);
212}
213
214
215/*
216 * 'cupsRasterReadPixels()' - Read raster pixels.
217 */
218
219unsigned /* O - Number of bytes read */
220cupsRasterReadPixels(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 */
223{
224 int bytes; /* Bytes read */
225 unsigned remaining; /* Bytes remaining */
226 unsigned char *ptr, /* Pointer to read buffer */
227 byte; /* Byte from file */
228
229
230 if (r == NULL || r->mode != CUPS_RASTER_READ || r->remaining == 0)
231 return (0);
232
233 remaining = len;
234
235 while (remaining > 0 && r->remaining > 0)
236 {
237 if (r->count == 0)
238 {
239 /*
240 * Need to read a new row...
241 */
242
243 if (remaining == r->header.cupsBytesPerLine)
244 ptr = p;
245 else
246 ptr = r->pixels;
247
248 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
249 {
250 /*
251 * Read without compression...
252 */
253
254 if (cups_read(r->fd, ptr, r->header.cupsBytesPerLine) <
255 r->header.cupsBytesPerLine)
256 return (0);
257
258 r->count = 1;
259 }
260 else
261 {
262 /*
263 * Read using a modified TIFF "packbits" compression...
264 */
265
266 unsigned char *temp; /* Pointer into buffer */
267 int count; /* Repetition count */
268
269
270 if (cups_read(r->fd, &byte, 1) < 1)
271 return (0);
272
273 r->count = byte + 1;
274
275 if (r->count > 1)
276 ptr = r->pixels;
277
278 temp = ptr;
279 bytes = r->header.cupsBytesPerLine;
280
281 while (bytes > 0)
282 {
283 /*
284 * Get a new repeat count...
285 */
286
287 if (cups_read(r->fd, &byte, 1) < 1)
288 return (0);
289
290 if (byte & 128)
291 {
292 /*
293 * Copy N literal pixels...
294 */
295
296 count = (257 - byte) * r->bpp;
297
298 if (count > bytes)
299 count = bytes;
300
301 if (cups_read(r->fd, temp, count) < count)
302 return (0);
303
304 temp += count;
305 bytes -= count;
306 }
307 else
308 {
309 /*
310 * Repeat the next N bytes...
311 */
312
313 count = (byte + 1) * r->bpp;
314 if (count > bytes)
315 count = bytes;
316
317 if (count < r->bpp)
318 break;
319
320 bytes -= count;
321
322 if (cups_read(r->fd, temp, r->bpp) < r->bpp)
323 return (0);
324
325 temp += r->bpp;
326 count -= r->bpp;
327
328 while (count > 0)
329 {
330 memcpy(temp, temp - r->bpp, r->bpp);
331 temp += r->bpp;
332 count -= r->bpp;
333 }
334 }
335 }
336 }
337
338 if (r->header.cupsBitsPerColor == 16 &&
339 (r->sync == CUPS_RASTER_REVSYNC || r->sync == CUPS_RASTER_REVSYNCv1))
340 {
341 /*
342 * Swap bytes in the pixel data...
343 */
344
345 unsigned char *temp;
346 int count;
347
348
349 for (temp = ptr, count = r->header.cupsBytesPerLine;
350 count > 0;
351 temp += 2, count -= 2)
352 {
353 byte = temp[0];
354 temp[0] = temp[1];
355 temp[1] = byte;
356 }
357 }
358
359 if (remaining >= r->header.cupsBytesPerLine)
360 {
361 bytes = r->header.cupsBytesPerLine;
362 r->pcurrent = r->pixels;
363 r->count --;
364 r->remaining --;
365 }
366 else
367 {
368 bytes = remaining;
369 r->pcurrent = r->pixels + bytes;
370 }
371
372 if (ptr != p)
373 memcpy(p, ptr, bytes);
374 }
375 else
376 {
377 /*
378 * Copy fragment from buffer...
379 */
380
381 if ((bytes = r->pend - r->pcurrent) > remaining)
382 bytes = remaining;
383
384 memcpy(p, r->pcurrent, bytes);
385 r->pcurrent += bytes;
386
387 if (r->pcurrent >= r->pend)
388 {
389 r->pcurrent = r->pixels;
390 r->count --;
391 r->remaining --;
392 }
393 }
394
395 remaining -= bytes;
396 p += bytes;
397 }
398
399 return (len);
400}
401
402
403/*
b423cd4c 404 * 'cupsRasterWriteHeader()' - Write a raster page header from a V1 page
405 * header structure.
ef416fc2 406 */
407
408unsigned /* O - 1 on success, 0 on failure */
409cupsRasterWriteHeader(
410 cups_raster_t *r, /* I - Raster stream */
411 cups_page_header_t *h) /* I - Raster page header */
412{
413 if (r == NULL || r->mode != CUPS_RASTER_WRITE)
414 return (0);
415
416 /*
417 * Make a copy of the header, and compute the number of raster
418 * lines in the page image...
419 */
420
421 memset(&(r->header), 0, sizeof(r->header));
422 memcpy(&(r->header), h, sizeof(cups_page_header_t));
423
424 cups_raster_update(r);
425
426 /*
427 * Write the raster header...
428 */
429
430 return (cups_write(r->fd, (unsigned char *)&(r->header), sizeof(r->header))
431 > 0);
432}
433
434
435/*
b423cd4c 436 * 'cupsRasterWriteHeader2()' - Write a raster page header from a V2 page
437 * header structure.
ef416fc2 438 *
439 * @since CUPS 1.2@
440 */
441
442unsigned /* O - 1 on success, 0 on failure */
443cupsRasterWriteHeader2(
444 cups_raster_t *r, /* I - Raster stream */
445 cups_page_header2_t *h) /* I - Raster page header */
446{
447 if (r == NULL || r->mode != CUPS_RASTER_WRITE)
448 return (0);
449
450 /*
451 * Make a copy of the header, and compute the number of raster
452 * lines in the page image...
453 */
454
455 memcpy(&(r->header), h, sizeof(cups_page_header2_t));
456
457 cups_raster_update(r);
458
459 /*
460 * Write the raster header...
461 */
462
463 return (cups_write(r->fd, (unsigned char *)&(r->header), sizeof(r->header))
464 > 0);
465}
466
467
468/*
469 * 'cupsRasterWritePixels()' - Write raster pixels.
470 */
471
472unsigned /* O - Number of bytes written */
473cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */
474 unsigned char *p, /* I - Bytes to write */
475 unsigned len)/* I - Number of bytes to write */
476{
477 int bytes; /* Bytes read */
478 unsigned remaining; /* Bytes remaining */
479
480
481 if (r == NULL || r->mode != CUPS_RASTER_WRITE || r->remaining == 0)
482 return (0);
483
484 remaining = len;
485
486 while (remaining > 0)
487 {
488 /*
489 * Figure out the number of remaining bytes on the current line...
490 */
491
492 if ((bytes = remaining) > (r->pend - r->pcurrent))
493 bytes = r->pend - r->pcurrent;
494
495 if (r->count > 0)
496 {
497 /*
498 * Check to see if this line is the same as the previous line...
499 */
500
501 if (memcmp(p, r->pcurrent, bytes))
502 {
503 if (!cups_raster_write(r))
504 return (0);
505
506 r->count = 0;
507 }
508 else
509 {
510 /*
511 * Mark more bytes as the same...
512 */
513
514 r->pcurrent += bytes;
515
516 if (r->pcurrent >= r->pend)
517 {
518 /*
519 * Increase the repeat count...
520 */
521
522 r->count ++;
523 r->pcurrent = r->pixels;
524
525 /*
526 * Flush out this line if it is the last one...
527 */
528
529 r->remaining --;
530 if (r->remaining == 0)
531 return (cups_raster_write(r));
532 else if (r->count == 256)
533 {
534 cups_raster_write(r);
535 r->count = 0;
536 }
537 }
538 }
539 }
540
541 if (r->count == 0)
542 {
543 /*
544 * Copy the raster data to the buffer...
545 */
546
547 memcpy(r->pcurrent, p, bytes);
548
549 r->pcurrent += bytes;
550
551 if (r->pcurrent >= r->pend)
552 {
553 /*
554 * Increase the repeat count...
555 */
556
557 r->count ++;
558 r->pcurrent = r->pixels;
559
560 /*
561 * Flush out this line if it is the last one...
562 */
563
564 r->remaining --;
565 if (r->remaining == 0)
566 return (cups_raster_write(r));
567 }
568 }
569
570 remaining -= bytes;
571 p += bytes;
572 }
573
574 return (len);
575}
576
577
578/*
579 * 'cups_raster_read_header()' - Read a raster page header.
580 */
581
582static unsigned /* O - 1 on success, 0 on fail */
583cups_raster_read_header(
584 cups_raster_t *r) /* I - Raster stream */
585{
586 int len; /* Number of words to swap */
587 union swap_s /* Swapping structure */
588 {
589 unsigned char b[4];
590 unsigned v;
591 } *s;
592
593
594 if (r == NULL || r->mode != CUPS_RASTER_READ)
595 return (0);
596
597 /*
598 * Get the length of the raster header...
599 */
600
601 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
602 len = sizeof(cups_page_header_t);
603 else
604 len = sizeof(cups_page_header2_t);
605
606 /*
607 * Read the header...
608 */
609
610 memset(&(r->header), 0, sizeof(r->header));
611
612 if (cups_read(r->fd, (unsigned char *)&(r->header), len) < len)
613 return (0);
614
615 /*
616 * Swap bytes as needed...
617 */
618
619 if (r->sync == CUPS_RASTER_REVSYNC || r->sync == CUPS_RASTER_REVSYNCv1)
fa73b229 620 for (len = 81, s = (union swap_s *)&(r->header.AdvanceDistance);
ef416fc2 621 len > 0;
622 len --, s ++)
623 s->v = (((((s->b[3] << 8) | s->b[2]) << 8) | s->b[1]) << 8) | s->b[0];
624
625 /*
626 * Update the header and row count...
627 */
628
629 cups_raster_update(r);
630
631 return (1);
632}
633
634
635/*
636 * 'cups_raster_update()' - Update the raster header and row count for the
637 * current page.
638 */
639
640static void
641cups_raster_update(cups_raster_t *r) /* I - Raster stream */
642{
643 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
644 {
645 /*
646 * Set the "cupsNumColors" field according to the colorspace...
647 */
648
649 switch (r->header.cupsColorSpace)
650 {
651 case CUPS_CSPACE_W :
652 case CUPS_CSPACE_K :
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;
658 break;
659
660 case CUPS_CSPACE_ICC2 :
661 r->header.cupsNumColors = 2;
662 break;
663
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;
671 break;
672
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;
682 break;
683
684 case CUPS_CSPACE_KCMYcm :
685 if (r->header.cupsBitsPerPixel < 8)
686 r->header.cupsNumColors = 6;
687 else
688 r->header.cupsNumColors = 4;
689 break;
690
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;
704 break;
705 }
706 }
707
708 /*
709 * Set the number of bytes per pixel/color...
710 */
711
712 if (r->header.cupsColorOrder == CUPS_ORDER_CHUNKED)
713 r->bpp = (r->header.cupsBitsPerPixel + 7) / 8;
714 else
715 r->bpp = (r->header.cupsBitsPerColor + 7) / 8;
716
717 /*
718 * Set the number of remaining rows...
719 */
720
721 if (r->header.cupsColorOrder == CUPS_ORDER_PLANAR)
722 r->remaining = r->header.cupsHeight * r->header.cupsNumColors;
723 else
724 r->remaining = r->header.cupsHeight;
725
726 /*
727 * Allocate the read/write buffer...
728 */
729
730 if (r->pixels != NULL)
731 free(r->pixels);
732
733 r->pixels = calloc(r->header.cupsBytesPerLine, 1);
734 r->pcurrent = r->pixels;
735 r->pend = r->pixels + r->header.cupsBytesPerLine;
736 r->count = 0;
737}
738
739
740/*
741 * 'cups_raster_write()' - Write a row of raster data...
742 */
743
744static int /* O - Number of bytes written */
745cups_raster_write(cups_raster_t *r) /* I - Raster stream */
746{
747 unsigned char *start, /* Start of sequence */
748 *ptr, /* Current pointer in sequence */
749 byte; /* Byte to write */
750 int count; /* Count */
751
752
753 /*
754 * Write the row repeat count...
755 */
756
757 byte = r->count - 1;
758
759 if (cups_write(r->fd, &byte, 1) < 1)
760 return (0);
761
762 /*
763 * Write using a modified TIFF "packbits" compression...
764 */
765
766 for (ptr = r->pixels; ptr < r->pend;)
767 {
768 start = ptr;
769 ptr += r->bpp;
770
771 if (ptr == r->pend)
772 {
773 /*
774 * Encode a single pixel at the end...
775 */
776
777 byte = 0;
778 if (cups_write(r->fd, &byte, 1) < 1)
779 return (0);
780
781 if (cups_write(r->fd, start, r->bpp) < r->bpp)
782 return (0);
783 }
784 else if (!memcmp(start, ptr, r->bpp))
785 {
786 /*
787 * Encode a sequence of repeating pixels...
788 */
789
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)
792 break;
793
794 ptr += r->bpp;
795
796 byte = count - 1;
797
798 if (cups_write(r->fd, &byte, 1) < 1)
799 return (0);
800
801 if (cups_write(r->fd, start, r->bpp) < r->bpp)
802 return (0);
803 }
804 else
805 {
806 /*
807 * Encode a sequence of non-repeating pixels...
808 */
809
810 for (count = 1; count < 127 && ptr < (r->pend - r->bpp); count ++, ptr += r->bpp)
811 if (!memcmp(ptr, ptr + r->bpp, r->bpp))
812 break;
813
814 if (ptr >= (r->pend - r->bpp) && count < 128)
815 {
816 count ++;
817 ptr += r->bpp;
818 }
819
820 byte = 257 - count;
821
822 if (cups_write(r->fd, &byte, 1) < 1)
823 return (0);
824
825 count *= r->bpp;
826
827 if (cups_write(r->fd, start, count) < count)
828 return (0);
829 }
830 }
831
832 return (r->header.cupsBytesPerLine);
833}
834
835
836/*
837 * 'cups_read()' - Read bytes from a file.
838 */
839
840static int /* O - Bytes read or -1 */
841cups_read(int fd, /* I - File descriptor */
842 unsigned char *buf, /* I - Buffer for read */
843 int bytes) /* I - Number of bytes to read */
844{
845 int count, /* Number of bytes read */
846 total; /* Total bytes read */
847
848
849 for (total = 0; total < bytes; total += count, buf += count)
850 {
851 count = read(fd, buf, bytes - total);
852
853 if (count == 0)
854 return (0);
855 else if (count < 0)
856 {
857 if (errno == EINTR)
858 count = 0;
859 else
860 return (-1);
861 }
862 }
863
864 return (total);
865}
866
867
868/*
869 * 'cups_write()' - Write bytes to a file.
870 */
871
872static int /* O - Bytes written or -1 */
873cups_write(int fd, /* I - File descriptor */
874 const unsigned char *buf, /* I - Bytes to write */
875 int bytes) /* I - Number of bytes to write */
876{
877 int count, /* Number of bytes written */
878 total; /* Total bytes written */
879
880
881 for (total = 0; total < bytes; total += count, buf += count)
882 {
883 count = write(fd, buf, bytes - total);
884
885 if (count < 0)
886 {
887 if (errno == EINTR)
888 count = 0;
889 else
890 return (-1);
891 }
892 }
893
894 return (total);
895}
896
897
898/*
b423cd4c 899 * End of "$Id: raster.c 5192 2006-02-27 03:08:47Z mike $".
ef416fc2 900 */