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