]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
f7faf1f5 | 2 | * "$Id: raster.c 5671 2006-06-16 11:17:39Z mike $" |
ef416fc2 | 3 | * |
4 | * Raster file routines for the Common UNIX Printing System (CUPS). | |
5 | * | |
6 | * Copyright 1997-2006 by Easy Software Products. | |
7 | * | |
8 | * This file is part of the CUPS Imaging library. | |
9 | * | |
10 | * These coded instructions, statements, and computer programs are the | |
11 | * property of Easy Software Products and are protected by Federal | |
12 | * copyright law. Distribution and use rights are outlined in the file | |
13 | * "LICENSE.txt" which should have been included with this file. If this | |
14 | * file is missing or damaged please contact Easy Software Products | |
15 | * at: | |
16 | * | |
17 | * Attn: CUPS Licensing Information | |
18 | * Easy Software Products | |
19 | * 44141 Airport View Drive, Suite 204 | |
20 | * Hollywood, Maryland 20636 USA | |
21 | * | |
22 | * Voice: (301) 373-9600 | |
23 | * EMail: cups-info@cups.org | |
24 | * WWW: http://www.cups.org | |
25 | * | |
26 | * This code and any derivative of it may be used and distributed | |
27 | * freely under the terms of the GNU General Public License when | |
28 | * used with GNU/GPL Ghostscript or its derivatives. Use of the | |
29 | * code (or any derivative of it) with software other than GNU/GPL | |
30 | * GhostScript (or its derivatives) is governed by the CUPS license | |
31 | * agreement. | |
32 | * | |
33 | * This file is subject to the Apple OS-Developed Software exception. | |
34 | * | |
35 | * Contents: | |
36 | * | |
ed486911 | 37 | * cupsRasterClose() - Close a raster stream. |
38 | * cupsRasterOpen() - Open a raster stream. | |
39 | * cupsRasterReadHeader() - Read a raster page header and store it in a | |
40 | * V1 page header structure. | |
41 | * cupsRasterReadHeader2() - Read a raster page header and store it in a | |
42 | * V2 page header structure. | |
43 | * cupsRasterReadPixels() - Read raster pixels. | |
44 | * cupsRasterWriteHeader() - Write a raster page header from a V1 page | |
45 | * header structure. | |
46 | * cupsRasterWriteHeader2() - Write a raster page header from a V2 page | |
47 | * header structure. | |
48 | * cupsRasterWritePixels() - Write raster pixels. | |
49 | * cups_raster_read() - Read through the raster buffer. | |
50 | * cups_raster_read_header() - Read a raster page header. | |
51 | * cups_raster_update() - Update the raster header and row count for the | |
52 | * current page. | |
ed486911 | 53 | * cups_read() - Read bytes from a file. |
54 | * cups_swap() - Swap bytes in raster data... | |
55 | * cups_write() - Write bytes to a file. | |
ef416fc2 | 56 | */ |
57 | ||
58 | /* | |
59 | * Include necessary headers... | |
60 | */ | |
61 | ||
62 | #include "raster.h" | |
ed486911 | 63 | #include <cups/debug.h> |
ef416fc2 | 64 | #include <stdlib.h> |
65 | #include <errno.h> | |
66 | #include <cups/string.h> | |
67 | ||
68 | #if defined(WIN32) || defined(__EMX__) | |
69 | # include <io.h> | |
70 | #else | |
71 | # include <unistd.h> | |
72 | #endif /* WIN32 || __EMX__ */ | |
73 | ||
74 | ||
f301802f | 75 | /* |
76 | * Private structures... | |
77 | */ | |
78 | ||
79 | struct _cups_raster_s /**** Raster stream data ****/ | |
80 | { | |
81 | unsigned sync; /* Sync word from start of stream */ | |
82 | int fd; /* File descriptor */ | |
83 | cups_mode_t mode; /* Read/write mode */ | |
84 | cups_page_header2_t header; /* Raster header for current page */ | |
85 | int count, /* Current row run-length count */ | |
86 | remaining, /* Remaining rows in page image */ | |
87 | bpp; /* Bytes per pixel/color */ | |
88 | unsigned char *pixels, /* Pixels for current row */ | |
89 | *pend, /* End of pixel buffer */ | |
90 | *pcurrent; /* Current byte in pixel buffer */ | |
ed486911 | 91 | int compressed, /* Non-zero if data is compressed */ |
92 | swapped; /* Non-zero if data is byte-swapped */ | |
93 | unsigned char *buffer, /* Read/write buffer */ | |
94 | *bufptr, /* Current (read) position in buffer */ | |
95 | *bufend; /* End of current (read) buffer */ | |
96 | int bufsize; /* Buffer size */ | |
f301802f | 97 | }; |
98 | ||
ed486911 | 99 | |
ef416fc2 | 100 | /* |
101 | * Local functions... | |
102 | */ | |
103 | ||
104 | static unsigned cups_raster_read_header(cups_raster_t *r); | |
ed486911 | 105 | static int cups_raster_read(cups_raster_t *r, unsigned char *buf, |
106 | int bytes); | |
ef416fc2 | 107 | static void cups_raster_update(cups_raster_t *r); |
ef416fc2 | 108 | static int cups_read(int fd, unsigned char *buf, int bytes); |
ed486911 | 109 | static void cups_swap(unsigned char *buf, int bytes); |
ef416fc2 | 110 | static int cups_write(int fd, const unsigned char *buf, int bytes); |
111 | ||
112 | ||
113 | /* | |
114 | * 'cupsRasterClose()' - Close a raster stream. | |
115 | */ | |
116 | ||
117 | void | |
118 | cupsRasterClose(cups_raster_t *r) /* I - Stream to close */ | |
119 | { | |
120 | if (r != NULL) | |
121 | { | |
ed486911 | 122 | if (r->buffer) |
123 | free(r->buffer); | |
124 | ||
ef416fc2 | 125 | if (r->pixels) |
126 | free(r->pixels); | |
127 | ||
128 | free(r); | |
129 | } | |
130 | } | |
131 | ||
132 | ||
133 | /* | |
134 | * 'cupsRasterOpen()' - Open a raster stream. | |
135 | */ | |
136 | ||
137 | cups_raster_t * /* O - New stream */ | |
138 | cupsRasterOpen(int fd, /* I - File descriptor */ | |
139 | cups_mode_t mode) /* I - Mode */ | |
140 | { | |
141 | cups_raster_t *r; /* New stream */ | |
142 | ||
143 | ||
144 | if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL) | |
145 | return (NULL); | |
146 | ||
147 | r->fd = fd; | |
f7faf1f5 | 148 | r->mode = mode; |
ef416fc2 | 149 | |
150 | if (mode == CUPS_RASTER_READ) | |
151 | { | |
152 | /* | |
153 | * Open for read - get sync word... | |
154 | */ | |
155 | ||
ed486911 | 156 | if (!cups_read(r->fd, (unsigned char *)&(r->sync), sizeof(r->sync))) |
ef416fc2 | 157 | { |
158 | free(r); | |
159 | return (NULL); | |
160 | } | |
161 | ||
162 | if (r->sync != CUPS_RASTER_SYNC && | |
163 | r->sync != CUPS_RASTER_REVSYNC && | |
164 | r->sync != CUPS_RASTER_SYNCv1 && | |
ed486911 | 165 | r->sync != CUPS_RASTER_REVSYNCv1 && |
166 | r->sync != CUPS_RASTER_SYNCv2 && | |
167 | r->sync != CUPS_RASTER_REVSYNCv2) | |
ef416fc2 | 168 | { |
169 | free(r); | |
170 | return (NULL); | |
171 | } | |
ed486911 | 172 | |
173 | if (r->sync == CUPS_RASTER_SYNCv2 || | |
174 | r->sync == CUPS_RASTER_REVSYNCv2) | |
175 | r->compressed = 1; | |
176 | ||
177 | if (r->sync == CUPS_RASTER_REVSYNC || | |
178 | r->sync == CUPS_RASTER_REVSYNCv1 || | |
179 | r->sync == CUPS_RASTER_REVSYNCv2) | |
180 | r->swapped = 1; | |
ef416fc2 | 181 | } |
182 | else | |
183 | { | |
184 | /* | |
185 | * Open for write - put sync word... | |
186 | */ | |
187 | ||
f7faf1f5 | 188 | r->sync = CUPS_RASTER_SYNC; |
ed486911 | 189 | |
ef416fc2 | 190 | if (cups_write(r->fd, (unsigned char *)&(r->sync), sizeof(r->sync)) |
191 | < sizeof(r->sync)) | |
192 | { | |
193 | free(r); | |
194 | return (NULL); | |
195 | } | |
196 | } | |
197 | ||
198 | return (r); | |
199 | } | |
200 | ||
201 | ||
202 | /* | |
b423cd4c | 203 | * 'cupsRasterReadHeader()' - Read a raster page header and store it in a |
204 | * V1 page header structure. | |
ef416fc2 | 205 | */ |
206 | ||
207 | unsigned /* O - 1 on success, 0 on fail */ | |
208 | cupsRasterReadHeader( | |
209 | cups_raster_t *r, /* I - Raster stream */ | |
210 | cups_page_header_t *h) /* I - Pointer to header data */ | |
211 | { | |
212 | /* | |
213 | * Get the raster header... | |
214 | */ | |
215 | ||
216 | if (!cups_raster_read_header(r)) | |
217 | return (0); | |
218 | ||
219 | /* | |
220 | * Copy the header to the user-supplied buffer... | |
221 | */ | |
222 | ||
223 | memcpy(h, &(r->header), sizeof(cups_page_header_t)); | |
224 | ||
225 | return (1); | |
226 | } | |
227 | ||
228 | ||
229 | /* | |
b423cd4c | 230 | * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a |
231 | * V2 page header structure. | |
ef416fc2 | 232 | * |
233 | * @since CUPS 1.2@ | |
234 | */ | |
235 | ||
236 | unsigned /* O - 1 on success, 0 on fail */ | |
237 | cupsRasterReadHeader2( | |
238 | cups_raster_t *r, /* I - Raster stream */ | |
239 | cups_page_header2_t *h) /* I - Pointer to header data */ | |
240 | { | |
241 | /* | |
242 | * Get the raster header... | |
243 | */ | |
244 | ||
245 | if (!cups_raster_read_header(r)) | |
246 | return (0); | |
247 | ||
248 | /* | |
249 | * Copy the header to the user-supplied buffer... | |
250 | */ | |
251 | ||
252 | memcpy(h, &(r->header), sizeof(cups_page_header2_t)); | |
253 | ||
254 | return (1); | |
255 | } | |
256 | ||
257 | ||
258 | /* | |
259 | * 'cupsRasterReadPixels()' - Read raster pixels. | |
260 | */ | |
261 | ||
262 | unsigned /* O - Number of bytes read */ | |
263 | cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */ | |
264 | unsigned char *p, /* I - Pointer to pixel buffer */ | |
265 | unsigned len) /* I - Number of bytes to read */ | |
266 | { | |
267 | int bytes; /* Bytes read */ | |
ed486911 | 268 | unsigned cupsBytesPerLine; /* cupsBytesPerLine value */ |
ef416fc2 | 269 | unsigned remaining; /* Bytes remaining */ |
270 | unsigned char *ptr, /* Pointer to read buffer */ | |
ed486911 | 271 | byte, /* Byte from file */ |
272 | *temp; /* Pointer into buffer */ | |
273 | int count; /* Repetition count */ | |
ef416fc2 | 274 | |
275 | ||
276 | if (r == NULL || r->mode != CUPS_RASTER_READ || r->remaining == 0) | |
277 | return (0); | |
278 | ||
ed486911 | 279 | if (!r->compressed) |
280 | { | |
281 | /* | |
282 | * Read without compression... | |
283 | */ | |
284 | ||
285 | r->remaining -= len / r->header.cupsBytesPerLine; | |
286 | ||
287 | if (!cups_read(r->fd, p, len)) | |
288 | return (0); | |
289 | ||
290 | /* | |
291 | * Swap bytes as needed... | |
292 | */ | |
293 | ||
294 | if ((r->header.cupsBitsPerColor == 16 || | |
295 | r->header.cupsBitsPerPixel == 12 || | |
296 | r->header.cupsBitsPerPixel == 16) && | |
297 | r->swapped) | |
298 | cups_swap(p, len); | |
299 | ||
300 | /* | |
301 | * Return... | |
302 | */ | |
303 | ||
304 | return (len); | |
305 | } | |
306 | ||
307 | /* | |
308 | * Read compressed data... | |
309 | */ | |
310 | ||
311 | remaining = len; | |
312 | cupsBytesPerLine = r->header.cupsBytesPerLine; | |
ef416fc2 | 313 | |
314 | while (remaining > 0 && r->remaining > 0) | |
315 | { | |
316 | if (r->count == 0) | |
317 | { | |
318 | /* | |
319 | * Need to read a new row... | |
320 | */ | |
321 | ||
ed486911 | 322 | if (remaining == cupsBytesPerLine) |
ef416fc2 | 323 | ptr = p; |
324 | else | |
325 | ptr = r->pixels; | |
326 | ||
ed486911 | 327 | /* |
328 | * Read using a modified TIFF "packbits" compression... | |
329 | */ | |
ef416fc2 | 330 | |
ed486911 | 331 | if (!cups_raster_read(r, &byte, 1)) |
332 | return (0); | |
ef416fc2 | 333 | |
ed486911 | 334 | r->count = byte + 1; |
335 | ||
336 | if (r->count > 1) | |
337 | ptr = r->pixels; | |
338 | ||
339 | temp = ptr; | |
340 | bytes = cupsBytesPerLine; | |
341 | ||
342 | while (bytes > 0) | |
ef416fc2 | 343 | { |
344 | /* | |
ed486911 | 345 | * Get a new repeat count... |
ef416fc2 | 346 | */ |
347 | ||
ed486911 | 348 | if (!cups_raster_read(r, &byte, 1)) |
ef416fc2 | 349 | return (0); |
350 | ||
ed486911 | 351 | if (byte & 128) |
ef416fc2 | 352 | { |
353 | /* | |
ed486911 | 354 | * Copy N literal pixels... |
ef416fc2 | 355 | */ |
356 | ||
ed486911 | 357 | count = (257 - byte) * r->bpp; |
ef416fc2 | 358 | |
ed486911 | 359 | if (count > bytes) |
360 | count = bytes; | |
ef416fc2 | 361 | |
ed486911 | 362 | if (!cups_raster_read(r, temp, count)) |
363 | return (0); | |
ef416fc2 | 364 | |
ed486911 | 365 | temp += count; |
366 | bytes -= count; | |
367 | } | |
368 | else | |
369 | { | |
370 | /* | |
371 | * Repeat the next N bytes... | |
372 | */ | |
ef416fc2 | 373 | |
ed486911 | 374 | count = (byte + 1) * r->bpp; |
375 | if (count > bytes) | |
376 | count = bytes; | |
ef416fc2 | 377 | |
ed486911 | 378 | if (count < r->bpp) |
379 | break; | |
ef416fc2 | 380 | |
ed486911 | 381 | bytes -= count; |
ef416fc2 | 382 | |
ed486911 | 383 | if (!cups_raster_read(r, temp, r->bpp)) |
384 | return (0); | |
ef416fc2 | 385 | |
ed486911 | 386 | temp += r->bpp; |
387 | count -= r->bpp; | |
ef416fc2 | 388 | |
ed486911 | 389 | while (count > 0) |
390 | { | |
391 | memcpy(temp, temp - r->bpp, r->bpp); | |
ef416fc2 | 392 | temp += r->bpp; |
393 | count -= r->bpp; | |
ed486911 | 394 | } |
ef416fc2 | 395 | } |
396 | } | |
397 | ||
ed486911 | 398 | /* |
399 | * Swap bytes as needed... | |
400 | */ | |
401 | ||
f301802f | 402 | if ((r->header.cupsBitsPerColor == 16 || |
403 | r->header.cupsBitsPerPixel == 12 || | |
404 | r->header.cupsBitsPerPixel == 16) && | |
ed486911 | 405 | r->swapped) |
406 | cups_swap(ptr, bytes); | |
ef416fc2 | 407 | |
ed486911 | 408 | /* |
409 | * Update pointers... | |
410 | */ | |
ef416fc2 | 411 | |
ed486911 | 412 | if (remaining >= cupsBytesPerLine) |
ef416fc2 | 413 | { |
ed486911 | 414 | bytes = cupsBytesPerLine; |
ef416fc2 | 415 | r->pcurrent = r->pixels; |
416 | r->count --; | |
417 | r->remaining --; | |
418 | } | |
419 | else | |
420 | { | |
421 | bytes = remaining; | |
422 | r->pcurrent = r->pixels + bytes; | |
423 | } | |
424 | ||
ed486911 | 425 | /* |
426 | * Copy data as needed... | |
427 | */ | |
428 | ||
ef416fc2 | 429 | if (ptr != p) |
430 | memcpy(p, ptr, bytes); | |
431 | } | |
432 | else | |
433 | { | |
434 | /* | |
435 | * Copy fragment from buffer... | |
436 | */ | |
437 | ||
438 | if ((bytes = r->pend - r->pcurrent) > remaining) | |
439 | bytes = remaining; | |
440 | ||
441 | memcpy(p, r->pcurrent, bytes); | |
442 | r->pcurrent += bytes; | |
443 | ||
444 | if (r->pcurrent >= r->pend) | |
445 | { | |
446 | r->pcurrent = r->pixels; | |
447 | r->count --; | |
448 | r->remaining --; | |
449 | } | |
450 | } | |
451 | ||
452 | remaining -= bytes; | |
453 | p += bytes; | |
454 | } | |
455 | ||
456 | return (len); | |
457 | } | |
458 | ||
459 | ||
460 | /* | |
b423cd4c | 461 | * 'cupsRasterWriteHeader()' - Write a raster page header from a V1 page |
462 | * header structure. | |
ef416fc2 | 463 | */ |
464 | ||
465 | unsigned /* O - 1 on success, 0 on failure */ | |
466 | cupsRasterWriteHeader( | |
467 | cups_raster_t *r, /* I - Raster stream */ | |
468 | cups_page_header_t *h) /* I - Raster page header */ | |
469 | { | |
470 | if (r == NULL || r->mode != CUPS_RASTER_WRITE) | |
471 | return (0); | |
472 | ||
473 | /* | |
474 | * Make a copy of the header, and compute the number of raster | |
475 | * lines in the page image... | |
476 | */ | |
477 | ||
478 | memset(&(r->header), 0, sizeof(r->header)); | |
479 | memcpy(&(r->header), h, sizeof(cups_page_header_t)); | |
480 | ||
481 | cups_raster_update(r); | |
482 | ||
483 | /* | |
484 | * Write the raster header... | |
485 | */ | |
486 | ||
487 | return (cups_write(r->fd, (unsigned char *)&(r->header), sizeof(r->header)) | |
488 | > 0); | |
489 | } | |
490 | ||
491 | ||
492 | /* | |
b423cd4c | 493 | * 'cupsRasterWriteHeader2()' - Write a raster page header from a V2 page |
494 | * header structure. | |
ef416fc2 | 495 | * |
496 | * @since CUPS 1.2@ | |
497 | */ | |
498 | ||
499 | unsigned /* O - 1 on success, 0 on failure */ | |
500 | cupsRasterWriteHeader2( | |
501 | cups_raster_t *r, /* I - Raster stream */ | |
502 | cups_page_header2_t *h) /* I - Raster page header */ | |
503 | { | |
504 | if (r == NULL || r->mode != CUPS_RASTER_WRITE) | |
505 | return (0); | |
506 | ||
507 | /* | |
508 | * Make a copy of the header, and compute the number of raster | |
509 | * lines in the page image... | |
510 | */ | |
511 | ||
512 | memcpy(&(r->header), h, sizeof(cups_page_header2_t)); | |
513 | ||
514 | cups_raster_update(r); | |
515 | ||
516 | /* | |
517 | * Write the raster header... | |
518 | */ | |
519 | ||
520 | return (cups_write(r->fd, (unsigned char *)&(r->header), sizeof(r->header)) | |
521 | > 0); | |
522 | } | |
523 | ||
524 | ||
525 | /* | |
526 | * 'cupsRasterWritePixels()' - Write raster pixels. | |
527 | */ | |
528 | ||
529 | unsigned /* O - Number of bytes written */ | |
530 | cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */ | |
531 | unsigned char *p, /* I - Bytes to write */ | |
532 | unsigned len)/* I - Number of bytes to write */ | |
533 | { | |
f301802f | 534 | #ifdef DEBUG |
535 | fprintf(stderr, "cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n", | |
536 | r, p, len, r->remaining); | |
537 | #endif /* DEBUG */ | |
538 | ||
ef416fc2 | 539 | if (r == NULL || r->mode != CUPS_RASTER_WRITE || r->remaining == 0) |
540 | return (0); | |
541 | ||
ed486911 | 542 | /* |
f7faf1f5 | 543 | * No write compression, just write the raster data raw... |
ed486911 | 544 | */ |
ef416fc2 | 545 | |
f7faf1f5 | 546 | r->remaining -= len / r->header.cupsBytesPerLine; |
f301802f | 547 | |
f7faf1f5 | 548 | return (cups_write(r->fd, p, len)); |
ef416fc2 | 549 | } |
550 | ||
551 | ||
552 | /* | |
553 | * 'cups_raster_read_header()' - Read a raster page header. | |
554 | */ | |
555 | ||
556 | static unsigned /* O - 1 on success, 0 on fail */ | |
557 | cups_raster_read_header( | |
558 | cups_raster_t *r) /* I - Raster stream */ | |
559 | { | |
560 | int len; /* Number of words to swap */ | |
561 | union swap_s /* Swapping structure */ | |
562 | { | |
563 | unsigned char b[4]; | |
564 | unsigned v; | |
565 | } *s; | |
566 | ||
567 | ||
568 | if (r == NULL || r->mode != CUPS_RASTER_READ) | |
569 | return (0); | |
570 | ||
571 | /* | |
572 | * Get the length of the raster header... | |
573 | */ | |
574 | ||
575 | if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1) | |
576 | len = sizeof(cups_page_header_t); | |
577 | else | |
578 | len = sizeof(cups_page_header2_t); | |
579 | ||
580 | /* | |
581 | * Read the header... | |
582 | */ | |
583 | ||
584 | memset(&(r->header), 0, sizeof(r->header)); | |
585 | ||
ed486911 | 586 | if (cups_raster_read(r, (unsigned char *)&(r->header), len) < len) |
ef416fc2 | 587 | return (0); |
588 | ||
589 | /* | |
590 | * Swap bytes as needed... | |
591 | */ | |
592 | ||
ed486911 | 593 | if (r->swapped) |
fa73b229 | 594 | for (len = 81, s = (union swap_s *)&(r->header.AdvanceDistance); |
ef416fc2 | 595 | len > 0; |
596 | len --, s ++) | |
597 | s->v = (((((s->b[3] << 8) | s->b[2]) << 8) | s->b[1]) << 8) | s->b[0]; | |
598 | ||
599 | /* | |
600 | * Update the header and row count... | |
601 | */ | |
602 | ||
603 | cups_raster_update(r); | |
604 | ||
605 | return (1); | |
606 | } | |
607 | ||
608 | ||
ed486911 | 609 | /* |
610 | * 'cups_raster_read()' - Read through the raster buffer. | |
611 | */ | |
612 | ||
613 | static int /* O - Number of bytes read */ | |
614 | cups_raster_read(cups_raster_t *r, /* I - Raster stream */ | |
615 | unsigned char *buf, /* I - Buffer */ | |
616 | int bytes) /* I - Number of bytes to read */ | |
617 | { | |
618 | int count, /* Number of bytes read */ | |
619 | remaining, /* Remaining bytes in buffer */ | |
620 | total; /* Total bytes read */ | |
621 | ||
622 | ||
623 | DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=%d)\n", r, buf, bytes)); | |
624 | ||
625 | if (!r->compressed) | |
626 | return (cups_read(r->fd, buf, bytes)); | |
627 | ||
628 | /* | |
629 | * Allocate a read buffer as needed... | |
630 | */ | |
631 | ||
632 | count = 2 * r->header.cupsBytesPerLine; | |
633 | ||
634 | if (count > r->bufsize) | |
635 | { | |
636 | int offset = r->bufptr - r->buffer; /* Offset to current start of buffer */ | |
637 | int end = r->bufend - r->buffer; /* Offset to current end of buffer */ | |
638 | unsigned char *rptr; /* Pointer in read buffer */ | |
639 | ||
640 | if (r->buffer) | |
641 | rptr = realloc(r->buffer, count); | |
642 | else | |
643 | rptr = malloc(count); | |
644 | ||
645 | if (!rptr) | |
646 | return (0); | |
647 | ||
648 | r->buffer = rptr; | |
649 | r->bufptr = rptr + offset; | |
650 | r->bufend = rptr + end; | |
651 | r->bufsize = count; | |
652 | } | |
653 | ||
654 | /* | |
655 | * Loop until we have read everything... | |
656 | */ | |
657 | ||
658 | for (total = 0, remaining = r->bufend - r->bufptr; | |
659 | total < bytes; | |
660 | total += count, buf += count) | |
661 | { | |
662 | count = bytes - total; | |
663 | ||
664 | DEBUG_printf(("count=%d, remaining=%d, buf=%p, bufptr=%p, bufend=%p...\n", | |
665 | count, remaining, buf, r->bufptr, r->bufend)); | |
666 | ||
667 | if (remaining == 0) | |
668 | { | |
669 | if (count < 16) | |
670 | { | |
671 | /* | |
672 | * Read into the raster buffer and then copy... | |
673 | */ | |
674 | ||
675 | remaining = cups_read(r->fd, r->buffer, r->bufsize); | |
676 | if (remaining <= 0) | |
677 | return (0); | |
678 | ||
679 | r->bufptr = r->buffer; | |
680 | r->bufend = r->buffer + remaining; | |
681 | } | |
682 | else | |
683 | { | |
684 | /* | |
685 | * Read directly into "buf"... | |
686 | */ | |
687 | ||
688 | count = cups_read(r->fd, buf, count); | |
689 | ||
690 | if (count <= 0) | |
691 | return (0); | |
692 | ||
693 | continue; | |
694 | } | |
695 | } | |
696 | ||
697 | /* | |
698 | * Copy bytes from raster buffer to "buf"... | |
699 | */ | |
700 | ||
701 | if (count > remaining) | |
702 | count = remaining; | |
703 | ||
704 | if (count == 1) | |
705 | { | |
706 | /* | |
707 | * Copy 1 byte... | |
708 | */ | |
709 | ||
710 | *buf = *(r->bufptr)++; | |
711 | remaining --; | |
712 | } | |
713 | else if (count < 128) | |
714 | { | |
715 | /* | |
716 | * Copy up to 127 bytes without using memcpy(); this is | |
717 | * faster because it avoids an extra function call and is | |
718 | * often further optimized by the compiler... | |
719 | */ | |
720 | ||
721 | unsigned char *bufptr; /* Temporary buffer pointer */ | |
722 | ||
723 | ||
724 | remaining -= count; | |
725 | ||
726 | for (bufptr = r->bufptr; count > 0; count --, total ++) | |
727 | *buf++ = *bufptr++; | |
728 | ||
729 | r->bufptr = bufptr; | |
730 | } | |
731 | else | |
732 | { | |
733 | /* | |
734 | * Use memcpy() for a large read... | |
735 | */ | |
736 | ||
737 | memcpy(buf, r->bufptr, count); | |
738 | r->bufptr += count; | |
739 | remaining -= count; | |
740 | } | |
741 | } | |
742 | ||
743 | return (total); | |
744 | } | |
745 | ||
746 | ||
ef416fc2 | 747 | /* |
748 | * 'cups_raster_update()' - Update the raster header and row count for the | |
749 | * current page. | |
750 | */ | |
751 | ||
752 | static void | |
753 | cups_raster_update(cups_raster_t *r) /* I - Raster stream */ | |
754 | { | |
f301802f | 755 | if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1 || |
756 | r->header.cupsNumColors == 0) | |
ef416fc2 | 757 | { |
758 | /* | |
759 | * Set the "cupsNumColors" field according to the colorspace... | |
760 | */ | |
761 | ||
762 | switch (r->header.cupsColorSpace) | |
763 | { | |
764 | case CUPS_CSPACE_W : | |
765 | case CUPS_CSPACE_K : | |
766 | case CUPS_CSPACE_WHITE : | |
767 | case CUPS_CSPACE_GOLD : | |
768 | case CUPS_CSPACE_SILVER : | |
ef416fc2 | 769 | r->header.cupsNumColors = 1; |
770 | break; | |
771 | ||
ef416fc2 | 772 | case CUPS_CSPACE_RGB : |
773 | case CUPS_CSPACE_CMY : | |
774 | case CUPS_CSPACE_YMC : | |
775 | case CUPS_CSPACE_CIEXYZ : | |
776 | case CUPS_CSPACE_CIELab : | |
f301802f | 777 | case CUPS_CSPACE_ICC1 : |
778 | case CUPS_CSPACE_ICC2 : | |
ef416fc2 | 779 | case CUPS_CSPACE_ICC3 : |
f301802f | 780 | case CUPS_CSPACE_ICC4 : |
781 | case CUPS_CSPACE_ICC5 : | |
782 | case CUPS_CSPACE_ICC6 : | |
783 | case CUPS_CSPACE_ICC7 : | |
784 | case CUPS_CSPACE_ICC8 : | |
785 | case CUPS_CSPACE_ICC9 : | |
786 | case CUPS_CSPACE_ICCA : | |
787 | case CUPS_CSPACE_ICCB : | |
788 | case CUPS_CSPACE_ICCC : | |
789 | case CUPS_CSPACE_ICCD : | |
790 | case CUPS_CSPACE_ICCE : | |
791 | case CUPS_CSPACE_ICCF : | |
ef416fc2 | 792 | r->header.cupsNumColors = 3; |
793 | break; | |
794 | ||
795 | case CUPS_CSPACE_RGBA : | |
796 | case CUPS_CSPACE_RGBW : | |
797 | case CUPS_CSPACE_CMYK : | |
798 | case CUPS_CSPACE_YMCK : | |
799 | case CUPS_CSPACE_KCMY : | |
800 | case CUPS_CSPACE_GMCK : | |
801 | case CUPS_CSPACE_GMCS : | |
ef416fc2 | 802 | r->header.cupsNumColors = 4; |
803 | break; | |
804 | ||
805 | case CUPS_CSPACE_KCMYcm : | |
806 | if (r->header.cupsBitsPerPixel < 8) | |
807 | r->header.cupsNumColors = 6; | |
808 | else | |
809 | r->header.cupsNumColors = 4; | |
810 | break; | |
ef416fc2 | 811 | } |
812 | } | |
813 | ||
814 | /* | |
815 | * Set the number of bytes per pixel/color... | |
816 | */ | |
817 | ||
818 | if (r->header.cupsColorOrder == CUPS_ORDER_CHUNKED) | |
819 | r->bpp = (r->header.cupsBitsPerPixel + 7) / 8; | |
820 | else | |
821 | r->bpp = (r->header.cupsBitsPerColor + 7) / 8; | |
822 | ||
823 | /* | |
824 | * Set the number of remaining rows... | |
825 | */ | |
826 | ||
827 | if (r->header.cupsColorOrder == CUPS_ORDER_PLANAR) | |
828 | r->remaining = r->header.cupsHeight * r->header.cupsNumColors; | |
829 | else | |
830 | r->remaining = r->header.cupsHeight; | |
831 | ||
832 | /* | |
ed486911 | 833 | * Allocate the compression buffer... |
ef416fc2 | 834 | */ |
835 | ||
ed486911 | 836 | if (r->compressed) |
837 | { | |
838 | if (r->pixels != NULL) | |
839 | free(r->pixels); | |
ef416fc2 | 840 | |
ed486911 | 841 | r->pixels = calloc(r->header.cupsBytesPerLine, 1); |
842 | r->pcurrent = r->pixels; | |
843 | r->pend = r->pixels + r->header.cupsBytesPerLine; | |
844 | r->count = 0; | |
845 | } | |
ef416fc2 | 846 | } |
847 | ||
848 | ||
ef416fc2 | 849 | /* |
850 | * 'cups_read()' - Read bytes from a file. | |
851 | */ | |
852 | ||
853 | static int /* O - Bytes read or -1 */ | |
854 | cups_read(int fd, /* I - File descriptor */ | |
855 | unsigned char *buf, /* I - Buffer for read */ | |
856 | int bytes) /* I - Number of bytes to read */ | |
857 | { | |
858 | int count, /* Number of bytes read */ | |
859 | total; /* Total bytes read */ | |
860 | ||
861 | ||
862 | for (total = 0; total < bytes; total += count, buf += count) | |
863 | { | |
864 | count = read(fd, buf, bytes - total); | |
865 | ||
866 | if (count == 0) | |
867 | return (0); | |
868 | else if (count < 0) | |
869 | { | |
870 | if (errno == EINTR) | |
871 | count = 0; | |
872 | else | |
873 | return (-1); | |
874 | } | |
875 | } | |
876 | ||
877 | return (total); | |
878 | } | |
879 | ||
880 | ||
ed486911 | 881 | /* |
882 | * 'cups_swap()' - Swap bytes in raster data... | |
883 | */ | |
884 | ||
885 | static void | |
886 | cups_swap(unsigned char *buf, /* I - Buffer to swap */ | |
887 | int bytes) /* I - Number of bytes to swap */ | |
888 | { | |
889 | unsigned char even, odd; /* Temporary variables */ | |
890 | ||
891 | ||
892 | bytes /= 2; | |
893 | ||
894 | while (bytes > 0) | |
895 | { | |
896 | even = buf[0]; | |
897 | odd = buf[1]; | |
898 | buf[0] = odd; | |
899 | buf[1] = even; | |
900 | ||
901 | buf += 2; | |
902 | bytes --; | |
903 | } | |
904 | } | |
905 | ||
906 | ||
ef416fc2 | 907 | /* |
908 | * 'cups_write()' - Write bytes to a file. | |
909 | */ | |
910 | ||
911 | static int /* O - Bytes written or -1 */ | |
912 | cups_write(int fd, /* I - File descriptor */ | |
913 | const unsigned char *buf, /* I - Bytes to write */ | |
914 | int bytes) /* I - Number of bytes to write */ | |
915 | { | |
916 | int count, /* Number of bytes written */ | |
917 | total; /* Total bytes written */ | |
918 | ||
919 | ||
920 | for (total = 0; total < bytes; total += count, buf += count) | |
921 | { | |
922 | count = write(fd, buf, bytes - total); | |
923 | ||
924 | if (count < 0) | |
925 | { | |
926 | if (errno == EINTR) | |
927 | count = 0; | |
928 | else | |
929 | return (-1); | |
930 | } | |
931 | } | |
932 | ||
933 | return (total); | |
934 | } | |
935 | ||
936 | ||
937 | /* | |
f7faf1f5 | 938 | * End of "$Id: raster.c 5671 2006-06-16 11:17:39Z mike $". |
ef416fc2 | 939 | */ |