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