]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/raster.c
Merge changes from CUPS 1.5svn-r9641
[thirdparty/cups.git] / filter / raster.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: raster.c 7720 2008-07-11 22:46:21Z mike $"
ef416fc2 3 *
c7017ecc 4 * Raster file routines for CUPS.
ef416fc2 5 *
c8fef167 6 * Copyright 2007-2011 by Apple Inc.
ef416fc2 7 * Copyright 1997-2006 by Easy Software Products.
8 *
9 * This file is part of the CUPS Imaging library.
10 *
11 * These coded instructions, statements, and computer programs are the
bc44d920 12 * property of Apple Inc. and are protected by Federal copyright
13 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
14 * which should have been included with this file. If this file is
15 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 16 *
ef416fc2 17 * This file is subject to the Apple OS-Developed Software exception.
18 *
19 * Contents:
20 *
ed486911 21 * cupsRasterClose() - Close a raster stream.
c8fef167
MS
22 * cupsRasterOpen() - Open a raster stream using a file descriptor.
23 * cupsRasterOpenIO() - Open a raster stream using a callback function.
ed486911 24 * cupsRasterReadHeader() - Read a raster page header and store it in a
db0bd74a 25 * version 1 page header structure.
ed486911 26 * cupsRasterReadHeader2() - Read a raster page header and store it in a
db0bd74a 27 * version 2 page header structure.
ed486911 28 * cupsRasterReadPixels() - Read raster pixels.
db0bd74a
MS
29 * cupsRasterWriteHeader() - Write a raster page header from a version 1
30 * page header structure.
31 * cupsRasterWriteHeader2() - Write a raster page header from a version 2
32 * page header structure.
ed486911 33 * cupsRasterWritePixels() - Write raster pixels.
ed486911 34 * cups_raster_read_header() - Read a raster page header.
c8fef167 35 * cups_raster_read() - Read through the raster buffer.
ed486911 36 * cups_raster_update() - Update the raster header and row count for the
37 * current page.
c8fef167
MS
38 * cups_raster_write() - Write a row of compressed raster data...
39 * cups_read_fd() - Read bytes from a file.
ed486911 40 * cups_swap() - Swap bytes in raster data...
c8fef167 41 * cups_write_fd() - Write bytes to a file.
ef416fc2 42 */
43
44/*
45 * Include necessary headers...
46 */
47
f7deaa1a 48#include "image-private.h"
ef416fc2 49#if defined(WIN32) || defined(__EMX__)
50# include <io.h>
c8fef167 51# include <winsock2.h> /* for htonl() definition */
ef416fc2 52#else
53# include <unistd.h>
54#endif /* WIN32 || __EMX__ */
55
56
f301802f 57/*
58 * Private structures...
59 */
60
61struct _cups_raster_s /**** Raster stream data ****/
62{
63 unsigned sync; /* Sync word from start of stream */
c8fef167
MS
64 void *ctx; /* File descriptor */
65 cups_raster_iocb_t iocb; /* IO callback */
f301802f 66 cups_mode_t mode; /* Read/write mode */
67 cups_page_header2_t header; /* Raster header for current page */
68 int count, /* Current row run-length count */
69 remaining, /* Remaining rows in page image */
70 bpp; /* Bytes per pixel/color */
71 unsigned char *pixels, /* Pixels for current row */
72 *pend, /* End of pixel buffer */
73 *pcurrent; /* Current byte in pixel buffer */
ed486911 74 int compressed, /* Non-zero if data is compressed */
75 swapped; /* Non-zero if data is byte-swapped */
76 unsigned char *buffer, /* Read/write buffer */
77 *bufptr, /* Current (read) position in buffer */
78 *bufend; /* End of current (read) buffer */
c8fef167 79 size_t bufsize; /* Buffer size */
f301802f 80};
81
ed486911 82
ef416fc2 83/*
84 * Local functions...
85 */
86
f14324a7 87static int cups_raster_io(cups_raster_t *r, unsigned char *buf, int bytes);
ef416fc2 88static unsigned cups_raster_read_header(cups_raster_t *r);
ed486911 89static int cups_raster_read(cups_raster_t *r, unsigned char *buf,
90 int bytes);
ef416fc2 91static void cups_raster_update(cups_raster_t *r);
c8fef167
MS
92static int cups_raster_write(cups_raster_t *r,
93 const unsigned char *pixels);
94static ssize_t cups_read_fd(void *ctx, unsigned char *buf, size_t bytes);
ed486911 95static void cups_swap(unsigned char *buf, int bytes);
c8fef167 96static ssize_t cups_write_fd(void *ctx, unsigned char *buf, size_t bytes);
ef416fc2 97
98
99/*
100 * 'cupsRasterClose()' - Close a raster stream.
db0bd74a
MS
101 *
102 * The file descriptor associated with the raster stream must be closed
103 * separately as needed.
ef416fc2 104 */
105
106void
107cupsRasterClose(cups_raster_t *r) /* I - Stream to close */
108{
109 if (r != NULL)
110 {
ed486911 111 if (r->buffer)
112 free(r->buffer);
113
ef416fc2 114 if (r->pixels)
115 free(r->pixels);
116
117 free(r);
118 }
119}
120
121
122/*
c8fef167 123 * 'cupsRasterOpen()' - Open a raster stream using a file descriptor.
db0bd74a
MS
124 *
125 * This function associates a raster stream with the given file descriptor.
126 * For most printer driver filters, "fd" will be 0 (stdin). For most raster
127 * image processor (RIP) filters that generate raster data, "fd" will be 1
128 * (stdout).
129 *
c8fef167
MS
130 * When writing raster data, the @code CUPS_RASTER_WRITE@,
131 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
132 * be used - compressed and PWG output is generally 25-50% smaller but adds a
133 * 100-300% execution time overhead.
ef416fc2 134 */
135
136cups_raster_t * /* O - New stream */
137cupsRasterOpen(int fd, /* I - File descriptor */
c8fef167
MS
138 cups_mode_t mode) /* I - Mode - @code CUPS_RASTER_READ@,
139 @code CUPS_RASTER_WRITE@,
140 @code CUPS_RASTER_WRITE_COMPRESSED@,
141 or @code CUPS_RASTER_WRITE_PWG@ */
142{
143 if (mode == CUPS_RASTER_READ)
144 return (cupsRasterOpenIO(cups_read_fd, (void *)((intptr_t)fd), mode));
145 else
146 return (cupsRasterOpenIO(cups_write_fd, (void *)((intptr_t)fd), mode));
147}
148
149
150/*
151 * 'cupsRasterOpenIO()' - Open a raster stream using a callback function.
152 *
153 * This function associates a raster stream with the given callback function and
154 * context pointer.
155 *
156 * When writing raster data, the @code CUPS_RASTER_WRITE@,
157 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
158 * be used - compressed and PWG output is generally 25-50% smaller but adds a
159 * 100-300% execution time overhead.
160 */
161
162cups_raster_t * /* O - New stream */
163cupsRasterOpenIO(
164 cups_raster_iocb_t iocb, /* I - Read/write callback */
165 void *ctx, /* I - Context pointer for callback */
166 cups_mode_t mode) /* I - Mode - @code CUPS_RASTER_READ@,
167 @code CUPS_RASTER_WRITE@,
168 @code CUPS_RASTER_WRITE_COMPRESSED@,
169 or @code CUPS_RASTER_WRITE_PWG@ */
ef416fc2 170{
171 cups_raster_t *r; /* New stream */
172
173
f7deaa1a 174 _cupsRasterClearError();
175
ef416fc2 176 if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL)
f7deaa1a 177 {
178 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
179 strerror(errno));
ef416fc2 180 return (NULL);
f7deaa1a 181 }
ef416fc2 182
c8fef167
MS
183 r->ctx = ctx;
184 r->iocb = iocb;
185 r->mode = mode;
ef416fc2 186
187 if (mode == CUPS_RASTER_READ)
188 {
189 /*
190 * Open for read - get sync word...
191 */
192
f14324a7 193 if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) !=
c8fef167 194 sizeof(r->sync))
ef416fc2 195 {
f7deaa1a 196 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
197 strerror(errno));
ef416fc2 198 free(r);
199 return (NULL);
200 }
201
202 if (r->sync != CUPS_RASTER_SYNC &&
203 r->sync != CUPS_RASTER_REVSYNC &&
204 r->sync != CUPS_RASTER_SYNCv1 &&
ed486911 205 r->sync != CUPS_RASTER_REVSYNCv1 &&
206 r->sync != CUPS_RASTER_SYNCv2 &&
207 r->sync != CUPS_RASTER_REVSYNCv2)
ef416fc2 208 {
f7deaa1a 209 _cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
ef416fc2 210 free(r);
211 return (NULL);
212 }
ed486911 213
214 if (r->sync == CUPS_RASTER_SYNCv2 ||
215 r->sync == CUPS_RASTER_REVSYNCv2)
216 r->compressed = 1;
217
218 if (r->sync == CUPS_RASTER_REVSYNC ||
219 r->sync == CUPS_RASTER_REVSYNCv1 ||
220 r->sync == CUPS_RASTER_REVSYNCv2)
221 r->swapped = 1;
09a101d6 222
223 DEBUG_printf(("r->swapped=%d, r->sync=%08x\n", r->swapped, r->sync));
ef416fc2 224 }
225 else
226 {
227 /*
228 * Open for write - put sync word...
229 */
230
c8fef167 231 switch (mode)
f7deaa1a 232 {
c8fef167
MS
233 default :
234 case CUPS_RASTER_WRITE :
235 r->sync = CUPS_RASTER_SYNC;
236 break;
237
238 case CUPS_RASTER_WRITE_COMPRESSED :
239 r->compressed = 1;
240 r->sync = CUPS_RASTER_SYNCv2;
241 break;
242
243 case CUPS_RASTER_WRITE_PWG :
244 r->compressed = 1;
245 r->sync = htonl(CUPS_RASTER_SYNC_PWG);
246 r->swapped = r->sync != CUPS_RASTER_SYNC_PWG;
247 break;
f7deaa1a 248 }
ed486911 249
f14324a7 250 if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync))
ef416fc2 251 < sizeof(r->sync))
252 {
f7deaa1a 253 _cupsRasterAddError("Unable to write raster stream header: %s\n",
254 strerror(errno));
ef416fc2 255 free(r);
256 return (NULL);
257 }
258 }
259
260 return (r);
261}
262
263
264/*
b423cd4c 265 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
db0bd74a
MS
266 * version 1 page header structure.
267 *
268 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
269 *
79e1d494
MS
270 * Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset
271 * of the version 2 page header data. This function handles reading version 2
272 * page headers and copying only the version 1 data into the provided buffer.
273 *
db0bd74a 274 * @deprecated@
ef416fc2 275 */
276
79e1d494 277unsigned /* O - 1 on success, 0 on failure/end-of-file */
ef416fc2 278cupsRasterReadHeader(
279 cups_raster_t *r, /* I - Raster stream */
280 cups_page_header_t *h) /* I - Pointer to header data */
281{
282 /*
283 * Get the raster header...
284 */
285
286 if (!cups_raster_read_header(r))
287 return (0);
f14324a7 288
ef416fc2 289 /*
290 * Copy the header to the user-supplied buffer...
291 */
292
293 memcpy(h, &(r->header), sizeof(cups_page_header_t));
294
295 return (1);
296}
297
298
299/*
b423cd4c 300 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
db0bd74a 301 * version 2 page header structure.
ef416fc2 302 *
db0bd74a 303 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 304 */
305
79e1d494 306unsigned /* O - 1 on success, 0 on failure/end-of-file */
ef416fc2 307cupsRasterReadHeader2(
308 cups_raster_t *r, /* I - Raster stream */
309 cups_page_header2_t *h) /* I - Pointer to header data */
310{
311 /*
312 * Get the raster header...
313 */
314
315 if (!cups_raster_read_header(r))
316 return (0);
f14324a7 317
ef416fc2 318 /*
319 * Copy the header to the user-supplied buffer...
320 */
321
322 memcpy(h, &(r->header), sizeof(cups_page_header2_t));
323
324 return (1);
325}
326
327
328/*
329 * 'cupsRasterReadPixels()' - Read raster pixels.
79e1d494
MS
330 *
331 * For best performance, filters should read one or more whole lines.
332 * The "cupsBytesPerLine" value from the page header can be used to allocate
333 * the line buffer and as the number of bytes to read.
ef416fc2 334 */
335
336unsigned /* O - Number of bytes read */
337cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */
338 unsigned char *p, /* I - Pointer to pixel buffer */
339 unsigned len) /* I - Number of bytes to read */
340{
341 int bytes; /* Bytes read */
ed486911 342 unsigned cupsBytesPerLine; /* cupsBytesPerLine value */
ef416fc2 343 unsigned remaining; /* Bytes remaining */
344 unsigned char *ptr, /* Pointer to read buffer */
ed486911 345 byte, /* Byte from file */
346 *temp; /* Pointer into buffer */
347 int count; /* Repetition count */
ef416fc2 348
349
350 if (r == NULL || r->mode != CUPS_RASTER_READ || r->remaining == 0)
351 return (0);
352
ed486911 353 if (!r->compressed)
354 {
355 /*
356 * Read without compression...
357 */
358
359 r->remaining -= len / r->header.cupsBytesPerLine;
360
f14324a7 361 if (cups_raster_io(r, p, len) < (ssize_t)len)
ed486911 362 return (0);
363
364 /*
365 * Swap bytes as needed...
366 */
367
c8fef167
MS
368 if (r->swapped &&
369 (r->header.cupsBitsPerColor == 16 ||
ed486911 370 r->header.cupsBitsPerPixel == 12 ||
c8fef167 371 r->header.cupsBitsPerPixel == 16))
ed486911 372 cups_swap(p, len);
373
374 /*
375 * Return...
376 */
377
378 return (len);
379 }
380
381 /*
382 * Read compressed data...
383 */
384
385 remaining = len;
386 cupsBytesPerLine = r->header.cupsBytesPerLine;
ef416fc2 387
388 while (remaining > 0 && r->remaining > 0)
389 {
390 if (r->count == 0)
391 {
392 /*
393 * Need to read a new row...
394 */
395
ed486911 396 if (remaining == cupsBytesPerLine)
ef416fc2 397 ptr = p;
398 else
399 ptr = r->pixels;
400
ed486911 401 /*
c8fef167 402 * Read using a modified PackBits compression...
ed486911 403 */
ef416fc2 404
ed486911 405 if (!cups_raster_read(r, &byte, 1))
406 return (0);
ef416fc2 407
ed486911 408 r->count = byte + 1;
409
410 if (r->count > 1)
411 ptr = r->pixels;
412
413 temp = ptr;
414 bytes = cupsBytesPerLine;
415
416 while (bytes > 0)
ef416fc2 417 {
418 /*
ed486911 419 * Get a new repeat count...
ef416fc2 420 */
421
ed486911 422 if (!cups_raster_read(r, &byte, 1))
ef416fc2 423 return (0);
424
ed486911 425 if (byte & 128)
ef416fc2 426 {
427 /*
ed486911 428 * Copy N literal pixels...
ef416fc2 429 */
430
ed486911 431 count = (257 - byte) * r->bpp;
ef416fc2 432
ed486911 433 if (count > bytes)
434 count = bytes;
ef416fc2 435
ed486911 436 if (!cups_raster_read(r, temp, count))
437 return (0);
ef416fc2 438
ed486911 439 temp += count;
440 bytes -= count;
441 }
442 else
443 {
444 /*
445 * Repeat the next N bytes...
446 */
ef416fc2 447
ed486911 448 count = (byte + 1) * r->bpp;
449 if (count > bytes)
450 count = bytes;
ef416fc2 451
ed486911 452 if (count < r->bpp)
453 break;
ef416fc2 454
ed486911 455 bytes -= count;
ef416fc2 456
ed486911 457 if (!cups_raster_read(r, temp, r->bpp))
458 return (0);
ef416fc2 459
ed486911 460 temp += r->bpp;
461 count -= r->bpp;
ef416fc2 462
ed486911 463 while (count > 0)
464 {
465 memcpy(temp, temp - r->bpp, r->bpp);
ef416fc2 466 temp += r->bpp;
467 count -= r->bpp;
ed486911 468 }
ef416fc2 469 }
470 }
471
ed486911 472 /*
473 * Swap bytes as needed...
474 */
475
f301802f 476 if ((r->header.cupsBitsPerColor == 16 ||
477 r->header.cupsBitsPerPixel == 12 ||
478 r->header.cupsBitsPerPixel == 16) &&
ed486911 479 r->swapped)
480 cups_swap(ptr, bytes);
ef416fc2 481
ed486911 482 /*
483 * Update pointers...
484 */
ef416fc2 485
ed486911 486 if (remaining >= cupsBytesPerLine)
ef416fc2 487 {
ed486911 488 bytes = cupsBytesPerLine;
ef416fc2 489 r->pcurrent = r->pixels;
490 r->count --;
491 r->remaining --;
492 }
493 else
494 {
495 bytes = remaining;
496 r->pcurrent = r->pixels + bytes;
497 }
498
ed486911 499 /*
500 * Copy data as needed...
501 */
502
ef416fc2 503 if (ptr != p)
504 memcpy(p, ptr, bytes);
505 }
506 else
507 {
508 /*
509 * Copy fragment from buffer...
510 */
511
c8fef167 512 if ((unsigned)(bytes = r->pend - r->pcurrent) > remaining)
ef416fc2 513 bytes = remaining;
514
515 memcpy(p, r->pcurrent, bytes);
516 r->pcurrent += bytes;
517
518 if (r->pcurrent >= r->pend)
519 {
520 r->pcurrent = r->pixels;
521 r->count --;
522 r->remaining --;
523 }
524 }
525
526 remaining -= bytes;
527 p += bytes;
528 }
529
530 return (len);
531}
532
533
534/*
db0bd74a 535 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
b423cd4c 536 * header structure.
db0bd74a
MS
537 *
538 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
539 *
540 * @deprecated@
ef416fc2 541 */
f14324a7 542
ef416fc2 543unsigned /* O - 1 on success, 0 on failure */
544cupsRasterWriteHeader(
545 cups_raster_t *r, /* I - Raster stream */
546 cups_page_header_t *h) /* I - Raster page header */
547{
c8fef167 548 if (r == NULL || r->mode == CUPS_RASTER_READ)
ef416fc2 549 return (0);
550
551 /*
552 * Make a copy of the header, and compute the number of raster
553 * lines in the page image...
554 */
555
556 memset(&(r->header), 0, sizeof(r->header));
557 memcpy(&(r->header), h, sizeof(cups_page_header_t));
558
559 cups_raster_update(r);
560
561 /*
562 * Write the raster header...
563 */
564
c8fef167
MS
565 if (r->mode == CUPS_RASTER_WRITE_PWG)
566 {
567 /*
568 * PWG raster data is always network byte order with most of the page header
569 * zeroed.
570 */
571
572 cups_page_header2_t fh; /* File page header */
573
574 memset(&fh, 0, sizeof(fh));
575 fh.HWResolution[0] = htonl(r->header.HWResolution[0]);
576 fh.HWResolution[1] = htonl(r->header.HWResolution[1]);
577 fh.cupsWidth = htonl(r->header.cupsWidth);
578 fh.cupsHeight = htonl(r->header.cupsHeight);
579 fh.cupsBitsPerColor = htonl(r->header.cupsBitsPerColor);
580 fh.cupsBitsPerPixel = htonl(r->header.cupsBitsPerPixel);
581 fh.cupsBytesPerLine = htonl(r->header.cupsBytesPerLine);
582 fh.cupsColorOrder = htonl(r->header.cupsColorOrder);
583 fh.cupsColorSpace = htonl(r->header.cupsColorSpace);
584
f14324a7 585 return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
c8fef167
MS
586 }
587 else
f14324a7 588 return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
c8fef167 589 == sizeof(r->header));
ef416fc2 590}
591
592
593/*
db0bd74a
MS
594 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
595 * page header structure.
596 *
597 * The page header can be initialized using @link cupsRasterInterpretPPD@.
ef416fc2 598 *
db0bd74a 599 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 600 */
f14324a7 601
ef416fc2 602unsigned /* O - 1 on success, 0 on failure */
603cupsRasterWriteHeader2(
604 cups_raster_t *r, /* I - Raster stream */
605 cups_page_header2_t *h) /* I - Raster page header */
606{
c8fef167 607 if (r == NULL || r->mode == CUPS_RASTER_READ)
ef416fc2 608 return (0);
609
610 /*
611 * Make a copy of the header, and compute the number of raster
612 * lines in the page image...
613 */
614
615 memcpy(&(r->header), h, sizeof(cups_page_header2_t));
616
617 cups_raster_update(r);
618
619 /*
620 * Write the raster header...
621 */
622
c8fef167
MS
623 if (r->mode == CUPS_RASTER_WRITE_PWG)
624 {
625 /*
626 * PWG raster data is always network byte order with most of the page header
627 * zeroed.
628 */
629
630 cups_page_header2_t fh; /* File page header */
631
632 memset(&fh, 0, sizeof(fh));
633 fh.HWResolution[0] = htonl(r->header.HWResolution[0]);
634 fh.HWResolution[1] = htonl(r->header.HWResolution[1]);
635 fh.cupsWidth = htonl(r->header.cupsWidth);
636 fh.cupsHeight = htonl(r->header.cupsHeight);
637 fh.cupsBitsPerColor = htonl(r->header.cupsBitsPerColor);
638 fh.cupsBitsPerPixel = htonl(r->header.cupsBitsPerPixel);
639 fh.cupsBytesPerLine = htonl(r->header.cupsBytesPerLine);
640 fh.cupsColorOrder = htonl(r->header.cupsColorOrder);
641 fh.cupsColorSpace = htonl(r->header.cupsColorSpace);
642
f14324a7 643 return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
c8fef167
MS
644 }
645 else
f14324a7 646 return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
c8fef167 647 == sizeof(r->header));
ef416fc2 648}
649
650
651/*
652 * 'cupsRasterWritePixels()' - Write raster pixels.
79e1d494
MS
653 *
654 * For best performance, filters should write one or more whole lines.
655 * The "cupsBytesPerLine" value from the page header can be used to allocate
656 * the line buffer and as the number of bytes to write.
ef416fc2 657 */
658
659unsigned /* O - Number of bytes written */
660cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */
661 unsigned char *p, /* I - Bytes to write */
662 unsigned len)/* I - Number of bytes to write */
663{
f7deaa1a 664 int bytes; /* Bytes read */
665 unsigned remaining; /* Bytes remaining */
666
667
09a101d6 668 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
669 r, p, len, r->remaining));
f301802f 670
c8fef167 671 if (r == NULL || r->mode == CUPS_RASTER_READ || r->remaining == 0)
ef416fc2 672 return (0);
673
f7deaa1a 674 if (!r->compressed)
675 {
676 /*
c8fef167
MS
677 * Without compression, just write the raster data raw unless the data needs
678 * to be swapped...
f7deaa1a 679 */
680
681 r->remaining -= len / r->header.cupsBytesPerLine;
682
c8fef167
MS
683 if (r->swapped &&
684 (r->header.cupsBitsPerColor == 16 ||
685 r->header.cupsBitsPerPixel == 12 ||
686 r->header.cupsBitsPerPixel == 16))
687 {
688 unsigned char *bufptr; /* Pointer into write buffer */
689 unsigned count; /* Remaining count */
690
691 /*
692 * Allocate a write buffer as needed...
693 */
694
695 if ((size_t)len > r->bufsize)
696 {
697 if (r->buffer)
698 bufptr = realloc(r->buffer, len);
699 else
700 bufptr = malloc(len);
701
702 if (!bufptr)
703 return (0);
704
705 r->buffer = bufptr;
706 r->bufsize = len;
707 }
708
709 /*
710 * Byte swap the pixels...
711 */
712
713 for (bufptr = r->buffer, count = len; count > 1; count -= 2, bufptr += 2)
714 {
715 bufptr[1] = *p++;
716 bufptr[0] = *p++;
717 }
718
719 if (count) /* This should never happen... */
720 *bufptr = *p;
721
722 /*
723 * Write the byte-swapped buffer...
724 */
725
f14324a7 726 return (cups_raster_io(r, r->buffer, len));
c8fef167
MS
727 }
728 else
f14324a7 729 return (cups_raster_io(r, p, len));
f7deaa1a 730 }
731
ed486911 732 /*
f7deaa1a 733 * Otherwise, compress each line...
ed486911 734 */
ef416fc2 735
f7deaa1a 736 for (remaining = len; remaining > 0; remaining -= bytes, p += bytes)
737 {
738 /*
739 * Figure out the number of remaining bytes on the current line...
740 */
741
742 if ((bytes = remaining) > (r->pend - r->pcurrent))
743 bytes = r->pend - r->pcurrent;
744
745 if (r->count > 0)
746 {
747 /*
748 * Check to see if this line is the same as the previous line...
749 */
750
751 if (memcmp(p, r->pcurrent, bytes))
752 {
753 if (!cups_raster_write(r, r->pixels))
754 return (0);
755
756 r->count = 0;
757 }
758 else
759 {
760 /*
761 * Mark more bytes as the same...
762 */
763
764 r->pcurrent += bytes;
765
766 if (r->pcurrent >= r->pend)
767 {
768 /*
769 * Increase the repeat count...
770 */
771
772 r->count ++;
773 r->pcurrent = r->pixels;
774
775 /*
776 * Flush out this line if it is the last one...
777 */
778
779 r->remaining --;
780
781 if (r->remaining == 0)
782 return (cups_raster_write(r, r->pixels));
783 else if (r->count == 256)
784 {
785 if (cups_raster_write(r, r->pixels) == 0)
786 return (0);
f301802f 787
f7deaa1a 788 r->count = 0;
789 }
790 }
791
792 continue;
793 }
794 }
795
796 if (r->count == 0)
797 {
798 /*
799 * Copy the raster data to the buffer...
800 */
801
802 memcpy(r->pcurrent, p, bytes);
803
804 r->pcurrent += bytes;
805
806 if (r->pcurrent >= r->pend)
807 {
808 /*
809 * Increase the repeat count...
810 */
811
812 r->count ++;
813 r->pcurrent = r->pixels;
814
815 /*
816 * Flush out this line if it is the last one...
817 */
818
819 r->remaining --;
820
821 if (r->remaining == 0)
822 return (cups_raster_write(r, r->pixels));
823 }
824 }
825 }
826
827 return (len);
ef416fc2 828}
829
830
831/*
832 * 'cups_raster_read_header()' - Read a raster page header.
833 */
834
835static unsigned /* O - 1 on success, 0 on fail */
836cups_raster_read_header(
837 cups_raster_t *r) /* I - Raster stream */
838{
09a101d6 839 int len; /* Length for read/swap */
ef416fc2 840
841
842 if (r == NULL || r->mode != CUPS_RASTER_READ)
843 return (0);
844
845 /*
846 * Get the length of the raster header...
847 */
848
849 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
850 len = sizeof(cups_page_header_t);
851 else
852 len = sizeof(cups_page_header2_t);
853
854 /*
855 * Read the header...
856 */
857
858 memset(&(r->header), 0, sizeof(r->header));
859
ed486911 860 if (cups_raster_read(r, (unsigned char *)&(r->header), len) < len)
ef416fc2 861 return (0);
862
863 /*
864 * Swap bytes as needed...
865 */
866
ed486911 867 if (r->swapped)
09a101d6 868 {
869 unsigned *s, /* Current word */
870 temp; /* Temporary copy */
871
872
873 DEBUG_puts("Swapping header bytes...");
874
875 for (len = 81, s = &(r->header.AdvanceDistance);
ef416fc2 876 len > 0;
877 len --, s ++)
09a101d6 878 {
879 DEBUG_printf(("%08x =>", *s));
880
881 temp = *s;
882 *s = ((temp & 0xff) << 24) |
883 ((temp & 0xff00) << 8) |
884 ((temp & 0xff0000) >> 8) |
885 ((temp & 0xff000000) >> 24);
886
887 DEBUG_printf((" %08x\n", *s));
888 }
889 }
ef416fc2 890
891 /*
892 * Update the header and row count...
893 */
894
895 cups_raster_update(r);
896
897 return (1);
898}
899
900
f14324a7
MS
901/*
902 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
903 */
904
905static int /* O - Bytes read or -1 */
906cups_raster_io(cups_raster_t *r, /* I - Raster stream */
907 unsigned char *buf, /* I - Buffer for read/write */
908 int bytes) /* I - Number of bytes to read/write */
909{
910 ssize_t count; /* Number of bytes read/written */
911 size_t total; /* Total bytes read/written */
912
913
914 DEBUG_printf(("4cups_raster_io(r=%p, buf=%p, bytes=%d)", r, buf, bytes));
915
916 for (total = 0; total < bytes; total += count, buf += count)
917 {
918 count = (*r->iocb)(r->ctx, buf, bytes - total);
919
920 DEBUG_printf(("5cups_raster_io: count=%d, total=%d", (int)count,
921 (int)total));
922 if (count == 0)
923 return (0);
924 else if (count < 0)
925 return (-1);
926 }
927
928 return ((int)total);
929}
930
931
ed486911 932/*
933 * 'cups_raster_read()' - Read through the raster buffer.
934 */
935
936static int /* O - Number of bytes read */
937cups_raster_read(cups_raster_t *r, /* I - Raster stream */
938 unsigned char *buf, /* I - Buffer */
939 int bytes) /* I - Number of bytes to read */
940{
941 int count, /* Number of bytes read */
942 remaining, /* Remaining bytes in buffer */
943 total; /* Total bytes read */
944
945
946 DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=%d)\n", r, buf, bytes));
947
948 if (!r->compressed)
f14324a7 949 return (cups_raster_io(r, buf, bytes));
ed486911 950
951 /*
952 * Allocate a read buffer as needed...
953 */
954
955 count = 2 * r->header.cupsBytesPerLine;
956
c8fef167 957 if ((size_t)count > r->bufsize)
ed486911 958 {
959 int offset = r->bufptr - r->buffer; /* Offset to current start of buffer */
960 int end = r->bufend - r->buffer; /* Offset to current end of buffer */
961 unsigned char *rptr; /* Pointer in read buffer */
962
963 if (r->buffer)
964 rptr = realloc(r->buffer, count);
965 else
966 rptr = malloc(count);
967
968 if (!rptr)
969 return (0);
970
971 r->buffer = rptr;
972 r->bufptr = rptr + offset;
973 r->bufend = rptr + end;
974 r->bufsize = count;
975 }
976
977 /*
978 * Loop until we have read everything...
979 */
980
981 for (total = 0, remaining = r->bufend - r->bufptr;
982 total < bytes;
983 total += count, buf += count)
984 {
985 count = bytes - total;
986
987 DEBUG_printf(("count=%d, remaining=%d, buf=%p, bufptr=%p, bufend=%p...\n",
988 count, remaining, buf, r->bufptr, r->bufend));
989
990 if (remaining == 0)
991 {
992 if (count < 16)
993 {
994 /*
995 * Read into the raster buffer and then copy...
996 */
997
c8fef167 998 remaining = (*r->iocb)(r->ctx, r->buffer, r->bufsize);
ed486911 999 if (remaining <= 0)
1000 return (0);
1001
1002 r->bufptr = r->buffer;
1003 r->bufend = r->buffer + remaining;
1004 }
1005 else
1006 {
1007 /*
1008 * Read directly into "buf"...
1009 */
1010
c8fef167 1011 count = (*r->iocb)(r->ctx, buf, count);
ed486911 1012
1013 if (count <= 0)
1014 return (0);
1015
1016 continue;
1017 }
1018 }
1019
1020 /*
1021 * Copy bytes from raster buffer to "buf"...
1022 */
1023
1024 if (count > remaining)
1025 count = remaining;
1026
1027 if (count == 1)
1028 {
1029 /*
1030 * Copy 1 byte...
1031 */
1032
1033 *buf = *(r->bufptr)++;
1034 remaining --;
1035 }
1036 else if (count < 128)
1037 {
1038 /*
1039 * Copy up to 127 bytes without using memcpy(); this is
1040 * faster because it avoids an extra function call and is
1041 * often further optimized by the compiler...
1042 */
1043
1044 unsigned char *bufptr; /* Temporary buffer pointer */
1045
1046
1047 remaining -= count;
1048
1049 for (bufptr = r->bufptr; count > 0; count --, total ++)
1050 *buf++ = *bufptr++;
1051
1052 r->bufptr = bufptr;
1053 }
1054 else
1055 {
1056 /*
1057 * Use memcpy() for a large read...
1058 */
1059
1060 memcpy(buf, r->bufptr, count);
1061 r->bufptr += count;
1062 remaining -= count;
1063 }
1064 }
1065
1066 return (total);
1067}
1068
1069
ef416fc2 1070/*
1071 * 'cups_raster_update()' - Update the raster header and row count for the
1072 * current page.
1073 */
1074
1075static void
1076cups_raster_update(cups_raster_t *r) /* I - Raster stream */
1077{
f301802f 1078 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1 ||
1079 r->header.cupsNumColors == 0)
ef416fc2 1080 {
1081 /*
1082 * Set the "cupsNumColors" field according to the colorspace...
1083 */
1084
1085 switch (r->header.cupsColorSpace)
1086 {
1087 case CUPS_CSPACE_W :
1088 case CUPS_CSPACE_K :
1089 case CUPS_CSPACE_WHITE :
1090 case CUPS_CSPACE_GOLD :
1091 case CUPS_CSPACE_SILVER :
c7017ecc 1092 case CUPS_CSPACE_SW :
ef416fc2 1093 r->header.cupsNumColors = 1;
1094 break;
1095
ef416fc2 1096 case CUPS_CSPACE_RGB :
1097 case CUPS_CSPACE_CMY :
1098 case CUPS_CSPACE_YMC :
1099 case CUPS_CSPACE_CIEXYZ :
1100 case CUPS_CSPACE_CIELab :
c7017ecc
MS
1101 case CUPS_CSPACE_SRGB :
1102 case CUPS_CSPACE_ADOBERGB :
f301802f 1103 case CUPS_CSPACE_ICC1 :
1104 case CUPS_CSPACE_ICC2 :
ef416fc2 1105 case CUPS_CSPACE_ICC3 :
f301802f 1106 case CUPS_CSPACE_ICC4 :
1107 case CUPS_CSPACE_ICC5 :
1108 case CUPS_CSPACE_ICC6 :
1109 case CUPS_CSPACE_ICC7 :
1110 case CUPS_CSPACE_ICC8 :
1111 case CUPS_CSPACE_ICC9 :
1112 case CUPS_CSPACE_ICCA :
1113 case CUPS_CSPACE_ICCB :
1114 case CUPS_CSPACE_ICCC :
1115 case CUPS_CSPACE_ICCD :
1116 case CUPS_CSPACE_ICCE :
1117 case CUPS_CSPACE_ICCF :
ef416fc2 1118 r->header.cupsNumColors = 3;
1119 break;
1120
1121 case CUPS_CSPACE_RGBA :
1122 case CUPS_CSPACE_RGBW :
1123 case CUPS_CSPACE_CMYK :
1124 case CUPS_CSPACE_YMCK :
1125 case CUPS_CSPACE_KCMY :
1126 case CUPS_CSPACE_GMCK :
1127 case CUPS_CSPACE_GMCS :
ef416fc2 1128 r->header.cupsNumColors = 4;
1129 break;
1130
1131 case CUPS_CSPACE_KCMYcm :
1132 if (r->header.cupsBitsPerPixel < 8)
1133 r->header.cupsNumColors = 6;
1134 else
1135 r->header.cupsNumColors = 4;
1136 break;
c7017ecc
MS
1137
1138 case CUPS_CSPACE_DEVICE1 :
1139 case CUPS_CSPACE_DEVICE2 :
1140 case CUPS_CSPACE_DEVICE3 :
1141 case CUPS_CSPACE_DEVICE4 :
1142 case CUPS_CSPACE_DEVICE5 :
1143 case CUPS_CSPACE_DEVICE6 :
1144 case CUPS_CSPACE_DEVICE7 :
1145 case CUPS_CSPACE_DEVICE8 :
1146 case CUPS_CSPACE_DEVICE9 :
1147 case CUPS_CSPACE_DEVICEA :
1148 case CUPS_CSPACE_DEVICEB :
1149 case CUPS_CSPACE_DEVICEC :
1150 case CUPS_CSPACE_DEVICED :
1151 case CUPS_CSPACE_DEVICEE :
1152 case CUPS_CSPACE_DEVICEF :
1153 r->header.cupsNumColors = r->header.cupsColorSpace -
1154 CUPS_CSPACE_DEVICE1 + 1;
1155 break;
ef416fc2 1156 }
1157 }
1158
1159 /*
1160 * Set the number of bytes per pixel/color...
1161 */
1162
1163 if (r->header.cupsColorOrder == CUPS_ORDER_CHUNKED)
1164 r->bpp = (r->header.cupsBitsPerPixel + 7) / 8;
1165 else
1166 r->bpp = (r->header.cupsBitsPerColor + 7) / 8;
1167
1168 /*
1169 * Set the number of remaining rows...
1170 */
1171
1172 if (r->header.cupsColorOrder == CUPS_ORDER_PLANAR)
1173 r->remaining = r->header.cupsHeight * r->header.cupsNumColors;
1174 else
1175 r->remaining = r->header.cupsHeight;
1176
1177 /*
ed486911 1178 * Allocate the compression buffer...
ef416fc2 1179 */
1180
ed486911 1181 if (r->compressed)
1182 {
1183 if (r->pixels != NULL)
1184 free(r->pixels);
ef416fc2 1185
ed486911 1186 r->pixels = calloc(r->header.cupsBytesPerLine, 1);
1187 r->pcurrent = r->pixels;
1188 r->pend = r->pixels + r->header.cupsBytesPerLine;
1189 r->count = 0;
1190 }
ef416fc2 1191}
1192
1193
f7deaa1a 1194/*
1195 * 'cups_raster_write()' - Write a row of compressed raster data...
1196 */
1197
1198static int /* O - Number of bytes written */
1199cups_raster_write(
1200 cups_raster_t *r, /* I - Raster stream */
1201 const unsigned char *pixels) /* I - Pixel data to write */
1202{
1203 const unsigned char *start, /* Start of sequence */
1204 *ptr, /* Current pointer in sequence */
1205 *pend, /* End of raster buffer */
1206 *plast; /* Pointer to last pixel */
1207 unsigned char *wptr; /* Pointer into write buffer */
1208 int bpp, /* Bytes per pixel */
1f0275e3 1209 count; /* Count */
f7deaa1a 1210
1211
09a101d6 1212 DEBUG_printf(("cups_raster_write(r=%p, pixels=%p)\n", r, pixels));
f7deaa1a 1213
1214 /*
1215 * Allocate a write buffer as needed...
1216 */
1217
1218 count = r->header.cupsBytesPerLine * 2;
c8fef167 1219 if ((size_t)count > r->bufsize)
f7deaa1a 1220 {
1221 if (r->buffer)
1222 wptr = realloc(r->buffer, count);
1223 else
1224 wptr = malloc(count);
1225
1226 if (!wptr)
1227 return (-1);
1228
1229 r->buffer = wptr;
1230 r->bufsize = count;
1231 }
1232
1233 /*
1234 * Write the row repeat count...
1235 */
1236
1237 bpp = r->bpp;
1238 pend = pixels + r->header.cupsBytesPerLine;
1239 plast = pend - bpp;
1240 wptr = r->buffer;
1241 *wptr++ = r->count - 1;
f7deaa1a 1242
1243 /*
1244 * Write using a modified TIFF "packbits" compression...
1245 */
1246
1247 for (ptr = pixels; ptr < pend;)
1248 {
1249 start = ptr;
1250 ptr += bpp;
1251
1252 if (ptr == pend)
1253 {
1254 /*
1255 * Encode a single pixel at the end...
1256 */
1257
1258 *wptr++ = 0;
1259 for (count = bpp; count > 0; count --)
1260 *wptr++ = *start++;
1261 }
1262 else if (!memcmp(start, ptr, bpp))
1263 {
1264 /*
1265 * Encode a sequence of repeating pixels...
1266 */
1267
1268 for (count = 2; count < 128 && ptr < plast; count ++, ptr += bpp)
1269 if (memcmp(ptr, ptr + bpp, bpp))
1270 break;
1271
1272 *wptr++ = count - 1;
1273 for (count = bpp; count > 0; count --)
1274 *wptr++ = *ptr++;
1275 }
1276 else
1277 {
1278 /*
1279 * Encode a sequence of non-repeating pixels...
1280 */
1281
1282 for (count = 1; count < 127 && ptr < plast; count ++, ptr += bpp)
1283 if (!memcmp(ptr, ptr + bpp, bpp))
1284 break;
1285
1286 if (ptr >= plast && count < 128)
1287 {
1288 count ++;
1289 ptr += bpp;
1290 }
f14324a7 1291
f7deaa1a 1292 *wptr++ = 257 - count;
1293
1294 count *= bpp;
1295 memcpy(wptr, start, count);
1296 wptr += count;
1297 }
1298 }
1299
f14324a7 1300 return (cups_raster_io(r, r->buffer, wptr - r->buffer));
f7deaa1a 1301}
1302
1303
ef416fc2 1304/*
c8fef167 1305 * 'cups_read_fd()' - Read bytes from a file.
ef416fc2 1306 */
1307
c8fef167
MS
1308static ssize_t /* O - Bytes read or -1 */
1309cups_read_fd(void *ctx, /* I - File descriptor as pointer */
1310 unsigned char *buf, /* I - Buffer for read */
f14324a7 1311 size_t bytes) /* I - Maximum number of bytes to read */
ef416fc2 1312{
c8fef167
MS
1313 int fd = (int)((intptr_t)ctx);
1314 /* File descriptor */
1315 ssize_t count; /* Number of bytes read */
ef416fc2 1316
ef416fc2 1317
f14324a7
MS
1318 while ((count = read(fd, buf, bytes)) < 0)
1319 if (errno != EINTR && errno != EAGAIN)
1320 return (-1);
ef416fc2 1321
f14324a7 1322 return (count);
ef416fc2 1323}
1324
1325
ed486911 1326/*
1327 * 'cups_swap()' - Swap bytes in raster data...
1328 */
1329
1330static void
1331cups_swap(unsigned char *buf, /* I - Buffer to swap */
1332 int bytes) /* I - Number of bytes to swap */
1333{
1334 unsigned char even, odd; /* Temporary variables */
1335
1336
1337 bytes /= 2;
1338
1339 while (bytes > 0)
1340 {
1341 even = buf[0];
1342 odd = buf[1];
1343 buf[0] = odd;
1344 buf[1] = even;
1345
1346 buf += 2;
1347 bytes --;
1348 }
1349}
1350
1351
ef416fc2 1352/*
c8fef167 1353 * 'cups_write_fd()' - Write bytes to a file.
ef416fc2 1354 */
1355
c8fef167
MS
1356static ssize_t /* O - Bytes written or -1 */
1357cups_write_fd(void *ctx, /* I - File descriptor pointer */
1358 unsigned char *buf, /* I - Bytes to write */
1359 size_t bytes) /* I - Number of bytes to write */
ef416fc2 1360{
c8fef167
MS
1361 int fd = (int)((intptr_t)ctx);
1362 /* File descriptor */
1363 ssize_t count; /* Number of bytes written */
ef416fc2 1364
ef416fc2 1365
f14324a7
MS
1366 while ((count = write(fd, buf, bytes)) < 0)
1367 if (errno != EINTR && errno != EAGAIN)
1368 return (-1);
ef416fc2 1369
f14324a7 1370 return (count);
ef416fc2 1371}
1372
1373
1374/*
b19ccc9e 1375 * End of "$Id: raster.c 7720 2008-07-11 22:46:21Z mike $".
ef416fc2 1376 */