]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/raster.c
Add missing length check (<rdar://problem/23133230>)
[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);
3c0659cd 67static int 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
3c0659cd
MS
569 if (!cups_raster_update(r))
570 return (0);
ef416fc2 571
572 /*
573 * Write the raster header...
574 */
575
c8fef167
MS
576 if (r->mode == CUPS_RASTER_WRITE_PWG)
577 {
578 /*
10ddcf65 579 * PWG raster data is always network byte order with much of the page header
c8fef167
MS
580 * zeroed.
581 */
582
583 cups_page_header2_t fh; /* File page header */
584
585 memset(&fh, 0, sizeof(fh));
10ddcf65
MS
586
587 strlcpy(fh.MediaClass, "PwgRaster", sizeof(fh.MediaClass));
588 /* PwgRaster */
589 strlcpy(fh.MediaColor, r->header.MediaColor, sizeof(fh.MediaColor));
590 strlcpy(fh.MediaType, r->header.MediaType, sizeof(fh.MediaType));
591 strlcpy(fh.OutputType, r->header.OutputType, sizeof(fh.OutputType));
592 /* PrintContentType */
593
594 fh.CutMedia = htonl(r->header.CutMedia);
595 fh.Duplex = htonl(r->header.Duplex);
596 fh.HWResolution[0] = htonl(r->header.HWResolution[0]);
597 fh.HWResolution[1] = htonl(r->header.HWResolution[1]);
598 fh.ImagingBoundingBox[0] = htonl(r->header.ImagingBoundingBox[0]);
599 fh.ImagingBoundingBox[1] = htonl(r->header.ImagingBoundingBox[1]);
600 fh.ImagingBoundingBox[2] = htonl(r->header.ImagingBoundingBox[2]);
601 fh.ImagingBoundingBox[3] = htonl(r->header.ImagingBoundingBox[3]);
602 fh.InsertSheet = htonl(r->header.InsertSheet);
603 fh.Jog = htonl(r->header.Jog);
604 fh.LeadingEdge = htonl(r->header.LeadingEdge);
605 fh.ManualFeed = htonl(r->header.ManualFeed);
606 fh.MediaPosition = htonl(r->header.MediaPosition);
607 fh.MediaWeight = htonl(r->header.MediaWeight);
608 fh.NumCopies = htonl(r->header.NumCopies);
609 fh.Orientation = htonl(r->header.Orientation);
610 fh.PageSize[0] = htonl(r->header.PageSize[0]);
611 fh.PageSize[1] = htonl(r->header.PageSize[1]);
612 fh.Tumble = htonl(r->header.Tumble);
613 fh.cupsWidth = htonl(r->header.cupsWidth);
614 fh.cupsHeight = htonl(r->header.cupsHeight);
615 fh.cupsBitsPerColor = htonl(r->header.cupsBitsPerColor);
616 fh.cupsBitsPerPixel = htonl(r->header.cupsBitsPerPixel);
617 fh.cupsBytesPerLine = htonl(r->header.cupsBytesPerLine);
618 fh.cupsColorOrder = htonl(r->header.cupsColorOrder);
619 fh.cupsColorSpace = htonl(r->header.cupsColorSpace);
620 fh.cupsNumColors = htonl(r->header.cupsNumColors);
621 fh.cupsInteger[0] = htonl(r->header.cupsInteger[0]);
622 /* TotalPageCount */
623 fh.cupsInteger[1] = htonl(r->header.cupsInteger[1]);
624 /* CrossFeedTransform */
625 fh.cupsInteger[2] = htonl(r->header.cupsInteger[2]);
626 /* FeedTransform */
627 fh.cupsInteger[3] = htonl(r->header.cupsInteger[3]);
628 /* ImageBoxLeft */
629 fh.cupsInteger[4] = htonl(r->header.cupsInteger[4]);
630 /* ImageBoxTop */
631 fh.cupsInteger[5] = htonl(r->header.cupsInteger[5]);
632 /* ImageBoxRight */
633 fh.cupsInteger[6] = htonl(r->header.cupsInteger[6]);
634 /* ImageBoxBottom */
635 fh.cupsInteger[7] = htonl(r->header.cupsInteger[7]);
636 /* BlackPrimary */
637 fh.cupsInteger[8] = htonl(r->header.cupsInteger[8]);
638 /* PrintQuality */
639 fh.cupsInteger[14] = htonl(r->header.cupsInteger[14]);
640 /* VendorIdentifier */
641 fh.cupsInteger[15] = htonl(r->header.cupsInteger[15]);
642 /* VendorLength */
643
cf1d7281
MS
644 void *dst = fh.cupsReal; /* Bypass bogus compiler warning */
645 void *src = r->header.cupsReal;
646 memcpy(dst, src, sizeof(fh.cupsReal) + sizeof(fh.cupsString));
10ddcf65
MS
647 /* VendorData */
648
649 strlcpy(fh.cupsRenderingIntent, r->header.cupsRenderingIntent,
650 sizeof(fh.cupsRenderingIntent));
651 strlcpy(fh.cupsPageSizeName, r->header.cupsPageSizeName,
652 sizeof(fh.cupsPageSizeName));
c8fef167 653
f14324a7 654 return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
c8fef167
MS
655 }
656 else
f14324a7 657 return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
c8fef167 658 == sizeof(r->header));
ef416fc2 659}
660
661
662/*
db0bd74a
MS
663 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
664 * page header structure.
665 *
666 * The page header can be initialized using @link cupsRasterInterpretPPD@.
ef416fc2 667 *
f3c17241 668 * @since CUPS 1.2/OS X 10.5@
ef416fc2 669 */
f14324a7 670
ef416fc2 671unsigned /* O - 1 on success, 0 on failure */
672cupsRasterWriteHeader2(
673 cups_raster_t *r, /* I - Raster stream */
674 cups_page_header2_t *h) /* I - Raster page header */
675{
c8fef167 676 if (r == NULL || r->mode == CUPS_RASTER_READ)
ef416fc2 677 return (0);
678
679 /*
680 * Make a copy of the header, and compute the number of raster
681 * lines in the page image...
682 */
683
684 memcpy(&(r->header), h, sizeof(cups_page_header2_t));
685
3c0659cd
MS
686 if (!cups_raster_update(r))
687 return (0);
ef416fc2 688
689 /*
690 * Write the raster header...
691 */
692
c8fef167
MS
693 if (r->mode == CUPS_RASTER_WRITE_PWG)
694 {
695 /*
696 * PWG raster data is always network byte order with most of the page header
697 * zeroed.
698 */
699
700 cups_page_header2_t fh; /* File page header */
701
702 memset(&fh, 0, sizeof(fh));
771bd8cb
MS
703 strlcpy(fh.MediaClass, "PwgRaster", sizeof(fh.MediaClass));
704 strlcpy(fh.MediaColor, r->header.MediaColor, sizeof(fh.MediaColor));
705 strlcpy(fh.MediaType, r->header.MediaType, sizeof(fh.MediaType));
706 strlcpy(fh.OutputType, r->header.OutputType, sizeof(fh.OutputType));
707 strlcpy(fh.cupsRenderingIntent, r->header.cupsRenderingIntent,
708 sizeof(fh.cupsRenderingIntent));
709 strlcpy(fh.cupsPageSizeName, r->header.cupsPageSizeName,
710 sizeof(fh.cupsPageSizeName));
711
712 fh.CutMedia = htonl(r->header.CutMedia);
713 fh.Duplex = htonl(r->header.Duplex);
714 fh.HWResolution[0] = htonl(r->header.HWResolution[0]);
715 fh.HWResolution[1] = htonl(r->header.HWResolution[1]);
716 fh.ImagingBoundingBox[0] = htonl(r->header.ImagingBoundingBox[0]);
717 fh.ImagingBoundingBox[1] = htonl(r->header.ImagingBoundingBox[1]);
718 fh.ImagingBoundingBox[2] = htonl(r->header.ImagingBoundingBox[2]);
719 fh.ImagingBoundingBox[3] = htonl(r->header.ImagingBoundingBox[3]);
720 fh.InsertSheet = htonl(r->header.InsertSheet);
721 fh.Jog = htonl(r->header.Jog);
722 fh.LeadingEdge = htonl(r->header.LeadingEdge);
723 fh.ManualFeed = htonl(r->header.ManualFeed);
724 fh.MediaPosition = htonl(r->header.MediaPosition);
725 fh.MediaWeight = htonl(r->header.MediaWeight);
726 fh.NumCopies = htonl(r->header.NumCopies);
727 fh.Orientation = htonl(r->header.Orientation);
728 fh.PageSize[0] = htonl(r->header.PageSize[0]);
729 fh.PageSize[1] = htonl(r->header.PageSize[1]);
730 fh.Tumble = htonl(r->header.Tumble);
731 fh.cupsWidth = htonl(r->header.cupsWidth);
732 fh.cupsHeight = htonl(r->header.cupsHeight);
733 fh.cupsBitsPerColor = htonl(r->header.cupsBitsPerColor);
734 fh.cupsBitsPerPixel = htonl(r->header.cupsBitsPerPixel);
735 fh.cupsBytesPerLine = htonl(r->header.cupsBytesPerLine);
736 fh.cupsColorOrder = htonl(r->header.cupsColorOrder);
737 fh.cupsColorSpace = htonl(r->header.cupsColorSpace);
738 fh.cupsNumColors = htonl(r->header.cupsNumColors);
739 fh.cupsInteger[0] = htonl(r->header.cupsInteger[0]);
740 fh.cupsInteger[1] = htonl(r->header.cupsInteger[1]);
741 fh.cupsInteger[2] = htonl(r->header.cupsInteger[2]);
89665c51
MS
742 fh.cupsInteger[3] = htonl((unsigned)(r->header.cupsImagingBBox[0] * r->header.HWResolution[0] / 72.0));
743 fh.cupsInteger[4] = htonl((unsigned)(r->header.cupsImagingBBox[1] * r->header.HWResolution[1] / 72.0));
744 fh.cupsInteger[5] = htonl((unsigned)(r->header.cupsImagingBBox[2] * r->header.HWResolution[0] / 72.0));
745 fh.cupsInteger[6] = htonl((unsigned)(r->header.cupsImagingBBox[3] * r->header.HWResolution[1] / 72.0));
771bd8cb 746 fh.cupsInteger[7] = htonl(0xffffff);
c8fef167 747
f14324a7 748 return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
c8fef167
MS
749 }
750 else
f14324a7 751 return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
c8fef167 752 == sizeof(r->header));
ef416fc2 753}
754
755
756/*
757 * 'cupsRasterWritePixels()' - Write raster pixels.
79e1d494
MS
758 *
759 * For best performance, filters should write one or more whole lines.
760 * The "cupsBytesPerLine" value from the page header can be used to allocate
761 * the line buffer and as the number of bytes to write.
ef416fc2 762 */
763
764unsigned /* O - Number of bytes written */
765cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */
766 unsigned char *p, /* I - Bytes to write */
767 unsigned len)/* I - Number of bytes to write */
768{
7e86f2f6 769 ssize_t bytes; /* Bytes read */
f7deaa1a 770 unsigned remaining; /* Bytes remaining */
771
772
09a101d6 773 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
774 r, p, len, r->remaining));
f301802f 775
c8fef167 776 if (r == NULL || r->mode == CUPS_RASTER_READ || r->remaining == 0)
ef416fc2 777 return (0);
778
f7deaa1a 779 if (!r->compressed)
780 {
781 /*
c8fef167
MS
782 * Without compression, just write the raster data raw unless the data needs
783 * to be swapped...
f7deaa1a 784 */
785
786 r->remaining -= len / r->header.cupsBytesPerLine;
787
c8fef167
MS
788 if (r->swapped &&
789 (r->header.cupsBitsPerColor == 16 ||
790 r->header.cupsBitsPerPixel == 12 ||
791 r->header.cupsBitsPerPixel == 16))
792 {
793 unsigned char *bufptr; /* Pointer into write buffer */
794 unsigned count; /* Remaining count */
795
796 /*
797 * Allocate a write buffer as needed...
798 */
799
800 if ((size_t)len > r->bufsize)
801 {
802 if (r->buffer)
803 bufptr = realloc(r->buffer, len);
804 else
805 bufptr = malloc(len);
806
807 if (!bufptr)
808 return (0);
809
810 r->buffer = bufptr;
811 r->bufsize = len;
812 }
813
814 /*
815 * Byte swap the pixels...
816 */
817
818 for (bufptr = r->buffer, count = len; count > 1; count -= 2, bufptr += 2)
819 {
820 bufptr[1] = *p++;
821 bufptr[0] = *p++;
822 }
823
824 if (count) /* This should never happen... */
825 *bufptr = *p;
826
827 /*
828 * Write the byte-swapped buffer...
829 */
830
a5425f93 831 bytes = cups_raster_io(r, r->buffer, len);
c8fef167
MS
832 }
833 else
a5425f93
MS
834 bytes = cups_raster_io(r, p, len);
835
836 if (bytes < len)
837 return (0);
838 else
839 return (len);
f7deaa1a 840 }
841
ed486911 842 /*
f7deaa1a 843 * Otherwise, compress each line...
ed486911 844 */
ef416fc2 845
7e86f2f6 846 for (remaining = len; remaining > 0; remaining -= (unsigned)bytes, p += bytes)
f7deaa1a 847 {
848 /*
849 * Figure out the number of remaining bytes on the current line...
850 */
851
7e86f2f6
MS
852 if ((bytes = (ssize_t)remaining) > (ssize_t)(r->pend - r->pcurrent))
853 bytes = (ssize_t)(r->pend - r->pcurrent);
f7deaa1a 854
855 if (r->count > 0)
856 {
857 /*
858 * Check to see if this line is the same as the previous line...
859 */
860
7e86f2f6 861 if (memcmp(p, r->pcurrent, (size_t)bytes))
f7deaa1a 862 {
a5425f93 863 if (cups_raster_write(r, r->pixels) <= 0)
f7deaa1a 864 return (0);
865
866 r->count = 0;
867 }
868 else
869 {
870 /*
871 * Mark more bytes as the same...
872 */
873
874 r->pcurrent += bytes;
875
876 if (r->pcurrent >= r->pend)
877 {
878 /*
879 * Increase the repeat count...
880 */
881
882 r->count ++;
883 r->pcurrent = r->pixels;
884
885 /*
886 * Flush out this line if it is the last one...
887 */
888
889 r->remaining --;
890
891 if (r->remaining == 0)
a5425f93
MS
892 {
893 if (cups_raster_write(r, r->pixels) <= 0)
894 return (0);
895 else
896 return (len);
897 }
f7deaa1a 898 else if (r->count == 256)
899 {
a5425f93 900 if (cups_raster_write(r, r->pixels) <= 0)
f7deaa1a 901 return (0);
f301802f 902
f7deaa1a 903 r->count = 0;
904 }
905 }
906
907 continue;
908 }
909 }
910
911 if (r->count == 0)
912 {
913 /*
914 * Copy the raster data to the buffer...
915 */
916
07623986 917 memcpy(r->pcurrent, p, (size_t)bytes);
f7deaa1a 918
919 r->pcurrent += bytes;
920
921 if (r->pcurrent >= r->pend)
922 {
923 /*
924 * Increase the repeat count...
925 */
926
927 r->count ++;
928 r->pcurrent = r->pixels;
929
930 /*
931 * Flush out this line if it is the last one...
932 */
933
934 r->remaining --;
935
936 if (r->remaining == 0)
a5425f93
MS
937 {
938 if (cups_raster_write(r, r->pixels) <= 0)
939 return (0);
940 }
f7deaa1a 941 }
942 }
943 }
944
945 return (len);
ef416fc2 946}
947
948
949/*
950 * 'cups_raster_read_header()' - Read a raster page header.
951 */
952
953static unsigned /* O - 1 on success, 0 on fail */
954cups_raster_read_header(
955 cups_raster_t *r) /* I - Raster stream */
956{
7e86f2f6 957 size_t len; /* Length for read/swap */
ef416fc2 958
959
590e44a4
MS
960 DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%d", r, r ? r->mode : 0));
961
ef416fc2 962 if (r == NULL || r->mode != CUPS_RASTER_READ)
963 return (0);
964
d9564ec7
MS
965 DEBUG_printf(("4cups_raster_read_header: r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
966
ef416fc2 967 /*
968 * Get the length of the raster header...
969 */
970
971 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
972 len = sizeof(cups_page_header_t);
973 else
974 len = sizeof(cups_page_header2_t);
975
590e44a4
MS
976 DEBUG_printf(("4cups_raster_read_header: len=%d", (int)len));
977
ef416fc2 978 /*
979 * Read the header...
980 */
981
982 memset(&(r->header), 0, sizeof(r->header));
983
7e86f2f6 984 if (cups_raster_read(r, (unsigned char *)&(r->header), len) < (ssize_t)len)
590e44a4 985 {
d9564ec7 986 DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
ef416fc2 987 return (0);
590e44a4 988 }
ef416fc2 989
990 /*
991 * Swap bytes as needed...
992 */
993
ed486911 994 if (r->swapped)
09a101d6 995 {
996 unsigned *s, /* Current word */
997 temp; /* Temporary copy */
998
999
590e44a4 1000 DEBUG_puts("4cups_raster_read_header: Swapping header bytes.");
09a101d6 1001
1002 for (len = 81, s = &(r->header.AdvanceDistance);
ef416fc2 1003 len > 0;
1004 len --, s ++)
09a101d6 1005 {
09a101d6 1006 temp = *s;
1007 *s = ((temp & 0xff) << 24) |
1008 ((temp & 0xff00) << 8) |
1009 ((temp & 0xff0000) >> 8) |
1010 ((temp & 0xff000000) >> 24);
1011
590e44a4 1012 DEBUG_printf(("4cups_raster_read_header: %08x => %08x", temp, *s));
09a101d6 1013 }
1014 }
ef416fc2 1015
1016 /*
1017 * Update the header and row count...
1018 */
1019
3c0659cd
MS
1020 if (!cups_raster_update(r))
1021 return (0);
ef416fc2 1022
590e44a4
MS
1023 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));
1024
3c0659cd 1025 return (r->header.cupsBitsPerPixel > 0 && r->header.cupsBitsPerPixel <= 240 && r->header.cupsBitsPerColor > 0 && r->header.cupsBitsPerColor <= 16 && r->header.cupsBytesPerLine != 0 && r->header.cupsHeight != 0 && (r->header.cupsBytesPerLine % r->bpp) == 0);
ef416fc2 1026}
1027
1028
f14324a7
MS
1029/*
1030 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
1031 */
1032
7e86f2f6 1033static ssize_t /* O - Bytes read/write or -1 */
83e08001 1034cups_raster_io(cups_raster_t *r, /* I - Raster stream */
7e86f2f6
MS
1035 unsigned char *buf, /* I - Buffer for read/write */
1036 size_t bytes) /* I - Number of bytes to read/write */
f14324a7 1037{
7e86f2f6
MS
1038 ssize_t count, /* Number of bytes read/written */
1039 total; /* Total bytes read/written */
f14324a7
MS
1040
1041
590e44a4 1042 DEBUG_printf(("5cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT ")", r, buf, CUPS_LLCAST bytes));
f14324a7 1043
7e86f2f6 1044 for (total = 0; total < (ssize_t)bytes; total += count, buf += count)
f14324a7 1045 {
7e86f2f6 1046 count = (*r->iocb)(r->ctx, buf, bytes - (size_t)total);
f14324a7 1047
a5425f93 1048 DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count, (int)total));
f14324a7 1049 if (count == 0)
a5425f93
MS
1050 {
1051 DEBUG_puts("6cups_raster_io: Returning 0.");
f14324a7 1052 return (0);
a5425f93 1053 }
f14324a7 1054 else if (count < 0)
a5425f93
MS
1055 {
1056 DEBUG_puts("6cups_raster_io: Returning -1 on error.");
f14324a7 1057 return (-1);
a5425f93 1058 }
d9564ec7
MS
1059
1060#ifdef DEBUG
1061 r->iocount += (size_t)count;
1062#endif /* DEBUG */
f14324a7
MS
1063 }
1064
a5425f93
MS
1065 DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT ".", CUPS_LLCAST total));
1066
7e86f2f6 1067 return (total);
f14324a7
MS
1068}
1069
1070
ed486911 1071/*
1072 * 'cups_raster_read()' - Read through the raster buffer.
1073 */
1074
7e86f2f6 1075static ssize_t /* O - Number of bytes read */
ed486911 1076cups_raster_read(cups_raster_t *r, /* I - Raster stream */
1077 unsigned char *buf, /* I - Buffer */
7e86f2f6 1078 size_t bytes) /* I - Number of bytes to read */
ed486911 1079{
7e86f2f6 1080 ssize_t count, /* Number of bytes read */
ed486911 1081 remaining, /* Remaining bytes in buffer */
1082 total; /* Total bytes read */
1083
1084
590e44a4 1085 DEBUG_printf(("5cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT ")\n", r, buf, CUPS_LLCAST bytes));
ed486911 1086
1087 if (!r->compressed)
f14324a7 1088 return (cups_raster_io(r, buf, bytes));
ed486911 1089
1090 /*
1091 * Allocate a read buffer as needed...
1092 */
1093
7e86f2f6 1094 count = (ssize_t)(2 * r->header.cupsBytesPerLine);
d9564ec7
MS
1095 if (count < 65536)
1096 count = 65536;
ed486911 1097
c8fef167 1098 if ((size_t)count > r->bufsize)
ed486911 1099 {
7e86f2f6 1100 ssize_t offset = r->bufptr - r->buffer;
a2326b5b 1101 /* Offset to current start of buffer */
7e86f2f6 1102 ssize_t end = r->bufend - r->buffer;/* Offset to current end of buffer */
ed486911 1103 unsigned char *rptr; /* Pointer in read buffer */
1104
1105 if (r->buffer)
7e86f2f6 1106 rptr = realloc(r->buffer, (size_t)count);
ed486911 1107 else
7e86f2f6 1108 rptr = malloc((size_t)count);
ed486911 1109
1110 if (!rptr)
1111 return (0);
1112
1113 r->buffer = rptr;
1114 r->bufptr = rptr + offset;
1115 r->bufend = rptr + end;
7e86f2f6 1116 r->bufsize = (size_t)count;
ed486911 1117 }
1118
1119 /*
1120 * Loop until we have read everything...
1121 */
1122
a2326b5b 1123 for (total = 0, remaining = (int)(r->bufend - r->bufptr);
7e86f2f6 1124 total < (ssize_t)bytes;
ed486911 1125 total += count, buf += count)
1126 {
7e86f2f6 1127 count = (ssize_t)bytes - total;
ed486911 1128
590e44a4 1129 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 1130
1131 if (remaining == 0)
1132 {
1133 if (count < 16)
1134 {
1135 /*
1136 * Read into the raster buffer and then copy...
1137 */
1138
c8fef167 1139 remaining = (*r->iocb)(r->ctx, r->buffer, r->bufsize);
ed486911 1140 if (remaining <= 0)
1141 return (0);
1142
1143 r->bufptr = r->buffer;
1144 r->bufend = r->buffer + remaining;
d9564ec7
MS
1145
1146#ifdef DEBUG
1147 r->iocount += (size_t)remaining;
1148#endif /* DEBUG */
ed486911 1149 }
1150 else
1151 {
1152 /*
1153 * Read directly into "buf"...
1154 */
1155
7e86f2f6 1156 count = (*r->iocb)(r->ctx, buf, (size_t)count);
ed486911 1157
1158 if (count <= 0)
1159 return (0);
1160
d9564ec7
MS
1161#ifdef DEBUG
1162 r->iocount += (size_t)count;
1163#endif /* DEBUG */
1164
ed486911 1165 continue;
1166 }
1167 }
1168
1169 /*
1170 * Copy bytes from raster buffer to "buf"...
1171 */
1172
1173 if (count > remaining)
1174 count = remaining;
1175
1176 if (count == 1)
1177 {
1178 /*
1179 * Copy 1 byte...
1180 */
1181
1182 *buf = *(r->bufptr)++;
1183 remaining --;
1184 }
1185 else if (count < 128)
1186 {
1187 /*
1188 * Copy up to 127 bytes without using memcpy(); this is
1189 * faster because it avoids an extra function call and is
1190 * often further optimized by the compiler...
1191 */
1192
1193 unsigned char *bufptr; /* Temporary buffer pointer */
1194
ed486911 1195 remaining -= count;
1196
1197 for (bufptr = r->bufptr; count > 0; count --, total ++)
1198 *buf++ = *bufptr++;
1199
1200 r->bufptr = bufptr;
1201 }
1202 else
1203 {
1204 /*
1205 * Use memcpy() for a large read...
1206 */
1207
07623986 1208 memcpy(buf, r->bufptr, (size_t)count);
ed486911 1209 r->bufptr += count;
1210 remaining -= count;
1211 }
1212 }
1213
590e44a4
MS
1214 DEBUG_printf(("6cups_raster_read: Returning %ld", (long)total));
1215
ed486911 1216 return (total);
1217}
1218
1219
ef416fc2 1220/*
1221 * 'cups_raster_update()' - Update the raster header and row count for the
1222 * current page.
1223 */
1224
3c0659cd 1225static int /* O - 1 on success, 0 on failure */
ef416fc2 1226cups_raster_update(cups_raster_t *r) /* I - Raster stream */
1227{
f301802f 1228 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1 ||
1229 r->header.cupsNumColors == 0)
ef416fc2 1230 {
1231 /*
1232 * Set the "cupsNumColors" field according to the colorspace...
1233 */
1234
1235 switch (r->header.cupsColorSpace)
1236 {
1237 case CUPS_CSPACE_W :
1238 case CUPS_CSPACE_K :
1239 case CUPS_CSPACE_WHITE :
1240 case CUPS_CSPACE_GOLD :
1241 case CUPS_CSPACE_SILVER :
c7017ecc 1242 case CUPS_CSPACE_SW :
ef416fc2 1243 r->header.cupsNumColors = 1;
1244 break;
1245
ef416fc2 1246 case CUPS_CSPACE_RGB :
1247 case CUPS_CSPACE_CMY :
1248 case CUPS_CSPACE_YMC :
1249 case CUPS_CSPACE_CIEXYZ :
1250 case CUPS_CSPACE_CIELab :
c7017ecc
MS
1251 case CUPS_CSPACE_SRGB :
1252 case CUPS_CSPACE_ADOBERGB :
f301802f 1253 case CUPS_CSPACE_ICC1 :
1254 case CUPS_CSPACE_ICC2 :
ef416fc2 1255 case CUPS_CSPACE_ICC3 :
f301802f 1256 case CUPS_CSPACE_ICC4 :
1257 case CUPS_CSPACE_ICC5 :
1258 case CUPS_CSPACE_ICC6 :
1259 case CUPS_CSPACE_ICC7 :
1260 case CUPS_CSPACE_ICC8 :
1261 case CUPS_CSPACE_ICC9 :
1262 case CUPS_CSPACE_ICCA :
1263 case CUPS_CSPACE_ICCB :
1264 case CUPS_CSPACE_ICCC :
1265 case CUPS_CSPACE_ICCD :
1266 case CUPS_CSPACE_ICCE :
1267 case CUPS_CSPACE_ICCF :
ef416fc2 1268 r->header.cupsNumColors = 3;
1269 break;
1270
1271 case CUPS_CSPACE_RGBA :
1272 case CUPS_CSPACE_RGBW :
1273 case CUPS_CSPACE_CMYK :
1274 case CUPS_CSPACE_YMCK :
1275 case CUPS_CSPACE_KCMY :
1276 case CUPS_CSPACE_GMCK :
1277 case CUPS_CSPACE_GMCS :
ef416fc2 1278 r->header.cupsNumColors = 4;
1279 break;
1280
1281 case CUPS_CSPACE_KCMYcm :
1282 if (r->header.cupsBitsPerPixel < 8)
1283 r->header.cupsNumColors = 6;
1284 else
1285 r->header.cupsNumColors = 4;
1286 break;
c7017ecc
MS
1287
1288 case CUPS_CSPACE_DEVICE1 :
1289 case CUPS_CSPACE_DEVICE2 :
1290 case CUPS_CSPACE_DEVICE3 :
1291 case CUPS_CSPACE_DEVICE4 :
1292 case CUPS_CSPACE_DEVICE5 :
1293 case CUPS_CSPACE_DEVICE6 :
1294 case CUPS_CSPACE_DEVICE7 :
1295 case CUPS_CSPACE_DEVICE8 :
1296 case CUPS_CSPACE_DEVICE9 :
1297 case CUPS_CSPACE_DEVICEA :
1298 case CUPS_CSPACE_DEVICEB :
1299 case CUPS_CSPACE_DEVICEC :
1300 case CUPS_CSPACE_DEVICED :
1301 case CUPS_CSPACE_DEVICEE :
1302 case CUPS_CSPACE_DEVICEF :
1303 r->header.cupsNumColors = r->header.cupsColorSpace -
1304 CUPS_CSPACE_DEVICE1 + 1;
1305 break;
3c0659cd
MS
1306
1307 default :
1308 /* Unknown color space */
1309 return (0);
ef416fc2 1310 }
1311 }
1312
1313 /*
1314 * Set the number of bytes per pixel/color...
1315 */
1316
1317 if (r->header.cupsColorOrder == CUPS_ORDER_CHUNKED)
1318 r->bpp = (r->header.cupsBitsPerPixel + 7) / 8;
1319 else
1320 r->bpp = (r->header.cupsBitsPerColor + 7) / 8;
1321
33076d24
MS
1322 if (r->bpp == 0)
1323 r->bpp = 1;
1324
ef416fc2 1325 /*
1326 * Set the number of remaining rows...
1327 */
1328
1329 if (r->header.cupsColorOrder == CUPS_ORDER_PLANAR)
1330 r->remaining = r->header.cupsHeight * r->header.cupsNumColors;
1331 else
1332 r->remaining = r->header.cupsHeight;
1333
1334 /*
ed486911 1335 * Allocate the compression buffer...
ef416fc2 1336 */
1337
ed486911 1338 if (r->compressed)
1339 {
1340 if (r->pixels != NULL)
1341 free(r->pixels);
ef416fc2 1342
ed486911 1343 r->pixels = calloc(r->header.cupsBytesPerLine, 1);
1344 r->pcurrent = r->pixels;
1345 r->pend = r->pixels + r->header.cupsBytesPerLine;
1346 r->count = 0;
1347 }
58e9f268
MS
1348
1349 return (1);
ef416fc2 1350}
1351
1352
f7deaa1a 1353/*
1354 * 'cups_raster_write()' - Write a row of compressed raster data...
1355 */
1356
7e86f2f6 1357static ssize_t /* O - Number of bytes written */
f7deaa1a 1358cups_raster_write(
1359 cups_raster_t *r, /* I - Raster stream */
1360 const unsigned char *pixels) /* I - Pixel data to write */
1361{
1362 const unsigned char *start, /* Start of sequence */
1363 *ptr, /* Current pointer in sequence */
1364 *pend, /* End of raster buffer */
1365 *plast; /* Pointer to last pixel */
1366 unsigned char *wptr; /* Pointer into write buffer */
7e86f2f6 1367 unsigned bpp, /* Bytes per pixel */
1f0275e3 1368 count; /* Count */
f7deaa1a 1369
1370
590e44a4 1371 DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)\n", r, pixels));
f7deaa1a 1372
1373 /*
1374 * Allocate a write buffer as needed...
1375 */
1376
1377 count = r->header.cupsBytesPerLine * 2;
a5425f93
MS
1378 if (count < 65536)
1379 count = 65536;
f8e5a7b4 1380
c8fef167 1381 if ((size_t)count > r->bufsize)
f7deaa1a 1382 {
1383 if (r->buffer)
1384 wptr = realloc(r->buffer, count);
1385 else
1386 wptr = malloc(count);
1387
1388 if (!wptr)
a5425f93
MS
1389 {
1390 DEBUG_printf(("4cups_raster_write: Unable to allocate " CUPS_LLFMT " bytes for raster buffer: %s", CUPS_LLCAST count, strerror(errno)));
f7deaa1a 1391 return (-1);
a5425f93 1392 }
f7deaa1a 1393
1394 r->buffer = wptr;
1395 r->bufsize = count;
1396 }
1397
1398 /*
1399 * Write the row repeat count...
1400 */
1401
1402 bpp = r->bpp;
1403 pend = pixels + r->header.cupsBytesPerLine;
1404 plast = pend - bpp;
1405 wptr = r->buffer;
7e86f2f6 1406 *wptr++ = (unsigned char)(r->count - 1);
f7deaa1a 1407
1408 /*
07ed0e9a 1409 * Write using a modified PackBits compression...
f7deaa1a 1410 */
1411
1412 for (ptr = pixels; ptr < pend;)
1413 {
1414 start = ptr;
1415 ptr += bpp;
1416
1417 if (ptr == pend)
1418 {
1419 /*
1420 * Encode a single pixel at the end...
1421 */
1422
1423 *wptr++ = 0;
1424 for (count = bpp; count > 0; count --)
1425 *wptr++ = *start++;
1426 }
1427 else if (!memcmp(start, ptr, bpp))
1428 {
1429 /*
1430 * Encode a sequence of repeating pixels...
1431 */
1432
1433 for (count = 2; count < 128 && ptr < plast; count ++, ptr += bpp)
1434 if (memcmp(ptr, ptr + bpp, bpp))
1435 break;
1436
7e86f2f6 1437 *wptr++ = (unsigned char)(count - 1);
f7deaa1a 1438 for (count = bpp; count > 0; count --)
1439 *wptr++ = *ptr++;
1440 }
1441 else
1442 {
1443 /*
1444 * Encode a sequence of non-repeating pixels...
1445 */
1446
07ed0e9a 1447 for (count = 1; count < 128 && ptr < plast; count ++, ptr += bpp)
f7deaa1a 1448 if (!memcmp(ptr, ptr + bpp, bpp))
1449 break;
1450
1451 if (ptr >= plast && count < 128)
1452 {
1453 count ++;
1454 ptr += bpp;
1455 }
f14324a7 1456
7e86f2f6 1457 *wptr++ = (unsigned char)(257 - count);
f7deaa1a 1458
1459 count *= bpp;
1460 memcpy(wptr, start, count);
1461 wptr += count;
1462 }
1463 }
1464
a5425f93
MS
1465 DEBUG_printf(("4cups_raster_write: Writing " CUPS_LLFMT " bytes.", CUPS_LLCAST (wptr - r->buffer)));
1466
7e86f2f6 1467 return (cups_raster_io(r, r->buffer, (size_t)(wptr - r->buffer)));
f7deaa1a 1468}
1469
1470
ef416fc2 1471/*
c8fef167 1472 * 'cups_read_fd()' - Read bytes from a file.
ef416fc2 1473 */
1474
c8fef167
MS
1475static ssize_t /* O - Bytes read or -1 */
1476cups_read_fd(void *ctx, /* I - File descriptor as pointer */
1477 unsigned char *buf, /* I - Buffer for read */
f14324a7 1478 size_t bytes) /* I - Maximum number of bytes to read */
ef416fc2 1479{
c8fef167
MS
1480 int fd = (int)((intptr_t)ctx);
1481 /* File descriptor */
1482 ssize_t count; /* Number of bytes read */
ef416fc2 1483
ef416fc2 1484
a2326b5b
MS
1485#ifdef WIN32 /* Sigh */
1486 while ((count = read(fd, buf, (unsigned)bytes)) < 0)
1487#else
f14324a7 1488 while ((count = read(fd, buf, bytes)) < 0)
a2326b5b 1489#endif /* WIN32 */
f14324a7 1490 if (errno != EINTR && errno != EAGAIN)
d9564ec7
MS
1491 {
1492 DEBUG_printf(("4cups_read_fd: %s", strerror(errno)));
f14324a7 1493 return (-1);
d9564ec7
MS
1494 }
1495
1496 DEBUG_printf(("4cups_read_fd: Returning %d bytes.", (int)count));
ef416fc2 1497
f14324a7 1498 return (count);
ef416fc2 1499}
1500
1501
ed486911 1502/*
1503 * 'cups_swap()' - Swap bytes in raster data...
1504 */
1505
1506static void
1507cups_swap(unsigned char *buf, /* I - Buffer to swap */
7e86f2f6 1508 size_t bytes) /* I - Number of bytes to swap */
ed486911 1509{
1510 unsigned char even, odd; /* Temporary variables */
1511
1512
1513 bytes /= 2;
1514
1515 while (bytes > 0)
1516 {
1517 even = buf[0];
1518 odd = buf[1];
1519 buf[0] = odd;
1520 buf[1] = even;
1521
1522 buf += 2;
1523 bytes --;
1524 }
1525}
1526
1527
ef416fc2 1528/*
c8fef167 1529 * 'cups_write_fd()' - Write bytes to a file.
ef416fc2 1530 */
1531
c8fef167
MS
1532static ssize_t /* O - Bytes written or -1 */
1533cups_write_fd(void *ctx, /* I - File descriptor pointer */
1534 unsigned char *buf, /* I - Bytes to write */
1535 size_t bytes) /* I - Number of bytes to write */
ef416fc2 1536{
c8fef167
MS
1537 int fd = (int)((intptr_t)ctx);
1538 /* File descriptor */
1539 ssize_t count; /* Number of bytes written */
ef416fc2 1540
ef416fc2 1541
a2326b5b
MS
1542#ifdef WIN32 /* Sigh */
1543 while ((count = write(fd, buf, (unsigned)bytes)) < 0)
1544#else
f14324a7 1545 while ((count = write(fd, buf, bytes)) < 0)
a2326b5b 1546#endif /* WIN32 */
f14324a7 1547 if (errno != EINTR && errno != EAGAIN)
a5425f93
MS
1548 {
1549 DEBUG_printf(("4cups_write_fd: %s", strerror(errno)));
f14324a7 1550 return (-1);
a5425f93 1551 }
ef416fc2 1552
f14324a7 1553 return (count);
ef416fc2 1554}
1555
1556
1557/*
f2d18633 1558 * End of "$Id$".
ef416fc2 1559 */