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