1/*---------------------------------------------------------------------------* 2 | PDFlib - A library for generating PDF on the fly | 3 +---------------------------------------------------------------------------+ 4 | Copyright (c) 1997-2004 Thomas Merz and PDFlib GmbH. All rights reserved. | 5 +---------------------------------------------------------------------------+ 6 | | 7 | This software is subject to the PDFlib license. It is NOT in the | 8 | public domain. Extended versions and commercial licenses are | 9 | available, please check http://www.pdflib.com. | 10 | | 11 *---------------------------------------------------------------------------*/ 12 13/* $Id: p_image.c 14574 2005-10-29 16:27:43Z bonefish $ 14 * 15 * PDFlib image routines 16 * 17 */ 18 19#define P_IMAGE_C 20 21#include "p_intern.h" 22#include "p_image.h" 23#include "p_font.h" 24 25/* must be kept in sync with the pdf_compression enum in p_intern.h */ 26static const char *pdf_filter_names[] = { 27 "", "LZWDecode", "RunLengthDecode", "CCITTFaxDecode", 28 "DCTDecode", "FlateDecode", "JBIG2Decode" 29}; 30 31static const char *pdf_short_filter_names[] = { 32 "", "LZW", "RL", "CCF", "DCT", "Fl", "" 33}; 34 35static void 36pdf_init_image_struct(PDF *p, pdf_image *image) 37{ 38 (void) p; 39 40 /********** option variables *************/ 41 image->verbose = pdc_true; 42 image->bitreverse = pdc_false; 43 image->bpc = pdc_undef; 44 image->components = pdc_undef; 45 image->height_pixel = pdc_undef; 46 image->ignoremask = pdc_false; 47 image->doinline = pdc_false; 48 image->interpolate = pdc_false; 49 image->invert = pdc_false; 50 image->K = 0; 51 image->imagemask = pdc_false; 52 image->mask = pdc_undef; 53 image->ri = AutoIntent; 54 image->page = 1; 55 image->reference = pdf_ref_direct; 56 image->width_pixel = pdc_undef; 57 /*****************************************/ 58 59 image->transparent = pdc_false; 60 image->compression = none; 61 image->predictor = pred_default; 62 image->in_use = pdc_false; 63 image->fp = (pdc_file *) NULL; 64 image->filename = (char *) NULL; 65 image->params = (char *) NULL; 66 image->dpi_x = (float) 0; 67 image->dpi_y = (float) 0; 68 image->strips = 1; 69 image->rowsperstrip = 1; 70 image->colorspace = pdc_undef; 71 image->dochandle = pdc_undef; /* this means "not a PDI page" */ 72 image->use_raw = pdc_false; 73 image->transval[0] = 0; 74 image->transval[1] = 0; 75 image->transval[2] = 0; 76 image->transval[3] = 0; 77} 78 79void 80pdf_init_images(PDF *p) 81{ 82 int im; 83 84 p->images_capacity = IMAGES_CHUNKSIZE; 85 86 p->images = (pdf_image *) 87 pdc_malloc(p->pdc, 88 sizeof(pdf_image) * p->images_capacity, "pdf_init_images"); 89 90 for (im = 0; im < p->images_capacity; im++) 91 pdf_init_image_struct(p, &(p->images[im])); 92} 93 94void 95pdf_grow_images(PDF *p) 96{ 97 int im; 98 99 p->images = (pdf_image *) pdc_realloc(p->pdc, p->images, 100 sizeof(pdf_image) * 2 * p->images_capacity, "pdf_grow_images"); 101 102 for (im = p->images_capacity; im < 2 * p->images_capacity; im++) 103 pdf_init_image_struct(p, &(p->images[im])); 104 105 p->images_capacity *= 2; 106} 107 108void 109pdf_cleanup_image(PDF *p, int im) 110{ 111 /* clean up parameter string if necessary */ 112 if (p->images[im].params) { 113 pdc_free(p->pdc, p->images[im].params); 114 p->images[im].params = NULL; 115 } 116 117 if (p->images[im].filename) { 118 pdc_free(p->pdc, p->images[im].filename); 119 p->images[im].filename = NULL; 120 } 121 122 if (p->images[im].fp) { 123 pdc_fclose(p->images[im].fp); 124 p->images[im].fp = NULL; 125 } 126 127 /* free the image slot and prepare for next use */ 128 pdf_init_image_struct(p, &(p->images[im])); 129} 130 131void 132pdf_cleanup_images(PDF *p) 133{ 134 int im; 135 136 if (!p->images) 137 return; 138 139 /* Free images which the caller left open */ 140 141 /* When we think of inter-document survival of images, 142 ** we MUST NOT FORGET that the current TIFF algorithm 143 ** depends on contiguous image slots for the image strips! 144 */ 145 for (im = 0; im < p->images_capacity; im++) 146 { 147 pdf_image *img = &p->images[im]; 148 149 if (img->in_use) /* found used slot */ 150 pdf_cleanup_image(p, im); /* free image descriptor */ 151 } 152 153 pdc_free(p->pdc, p->images); 154 p->images = NULL; 155} 156 157void 158pdf_init_xobjects(PDF *p) 159{ 160 int idx; 161 162 p->xobjects_number = 0; 163 164 if (p->xobjects == (pdf_xobject *) 0) 165 { 166 p->xobjects_capacity = XOBJECTS_CHUNKSIZE; 167 168 p->xobjects = (pdf_xobject *) 169 pdc_malloc(p->pdc, sizeof(pdf_xobject) * p->xobjects_capacity, 170 "pdf_init_xobjects"); 171 } 172 173 for (idx = 0; idx < p->xobjects_capacity; idx++) 174 p->xobjects[idx].flags = 0; 175} 176 177int 178pdf_new_xobject(PDF *p, pdf_xobj_type type, pdc_id obj_id) 179{ 180 static const char fn[] = "pdf_new_xobject"; 181 int i, slot = p->xobjects_number++; 182 183 if (slot == p->xobjects_capacity) 184 { 185 p->xobjects = (pdf_xobject *) pdc_realloc(p->pdc, p->xobjects, 186 sizeof(pdf_xobject) * 2 * p->xobjects_capacity, fn); 187 188 for (i = p->xobjects_capacity; i < 2 * p->xobjects_capacity; i++) 189 p->xobjects[i].flags = 0; 190 191 p->xobjects_capacity *= 2; 192 } 193 194 if (obj_id == PDC_NEW_ID) 195 obj_id = pdc_begin_obj(p->out, PDC_NEW_ID); 196 197 p->xobjects[slot].obj_id = obj_id; 198 p->xobjects[slot].type = type; 199 p->xobjects[slot].flags = xobj_flag_used; 200 201 return slot; 202} 203 204void 205pdf_write_xobjects(PDF *p) 206{ 207 if (p->xobjects_number > 0) 208 { 209 pdc_bool hit = pdc_false; 210 int i; 211 212 for (i = 0; i < p->xobjects_capacity; ++i) 213 { 214 if (p->xobjects[i].flags & xobj_flag_write) 215 { 216 if (!hit) 217 { 218 pdc_puts(p->out, "/XObject"); 219 pdc_begin_dict(p->out); 220 hit = pdc_true; 221 } 222 223 pdc_printf(p->out, "/I%d %ld 0 R\n", i, p->xobjects[i].obj_id); 224 p->xobjects[i].flags &= ~xobj_flag_write; 225 } 226 } 227 228 if (hit) 229 pdc_end_dict(p->out); 230 } 231} 232 233void 234pdf_cleanup_xobjects(PDF *p) 235{ 236 if (p->xobjects) { 237 pdc_free(p->pdc, p->xobjects); 238 p->xobjects = NULL; 239 } 240} 241 242void 243pdf_put_inline_image(PDF *p, int im) 244{ 245 pdf_image *image; 246 pdc_matrix m; 247 PDF_data_source *src; 248 int i; 249 250 image = &p->images[im]; 251 252 /* Image object */ 253 254 image->no = -1; 255 256 pdf__save(p); 257 258 pdc_scale_matrix(image->width, image->height, &m); 259 260 pdf_concat_raw(p, &m); 261 262 pdc_puts(p->out, "BI"); 263 264 pdc_printf(p->out, "/W %d", (int) image->width); 265 pdc_printf(p->out, "/H %d", (int) image->height); 266 267 if (image->imagemask == pdc_true) { 268 pdc_puts(p->out, "/IM true"); 269 270 } else { 271 272 pdc_printf(p->out, "/BPC %d", image->bpc); 273 274 switch (p->colorspaces[image->colorspace].type) { 275 case DeviceGray: 276 pdc_printf(p->out, "/CS/G"); 277 break; 278 279 case DeviceRGB: 280 pdc_printf(p->out, "/CS/RGB"); 281 break; 282 283 case DeviceCMYK: 284 pdc_printf(p->out, "/CS/CMYK"); 285 break; 286 287 default: 288 pdc_error(p->pdc, PDF_E_INT_BADCS, 289 pdc_errprintf(p->pdc, "%d", image->colorspace), 0, 0, 0); 290 break; 291 } 292 } 293 294 if (image->compression != none) { 295 pdc_printf(p->out, "/F/%s", 296 pdf_short_filter_names[image->compression]); 297 } 298 299 /* prepare precompressed (raw) image data */ 300 if (image->use_raw && 301 (image->params || 302 image->predictor != pred_default || 303 image->compression == ccitt)) { 304 305 pdc_printf(p->out, "/DP[<<"); 306 307 /* write EarlyChange */ 308 if (image->params) 309 pdc_puts(p->out, image->params); 310 311 if (image->compression == ccitt) { 312 if (image->K != 0) 313 pdc_printf(p->out, "/K %d", image->K); 314 } 315 316 if (image->compression == flate || image->compression == lzw) { 317 if (image->predictor != pred_default) { 318 pdc_printf(p->out, "/Predictor %d", (int) image->predictor); 319 pdc_printf(p->out, "/Columns %d", (int) image->width); 320 if (image->bpc != 8) 321 pdc_printf(p->out, "/BitsPerComponent %d", image->bpc); 322 323 if (image->components != 1) /* 1 is default */ 324 pdc_printf(p->out, "/Colors %d", image->components); 325 } 326 } 327 328 if (image->compression == ccitt) { 329 if ((int) image->width != 1728) /* CCITT default width */ 330 pdc_printf(p->out, "/Columns %d", (int) image->width); 331 332 pdc_printf(p->out, "/Rows %d", (int) fabs(image->height)); 333 } 334 pdc_puts(p->out, ">>]"); /* DecodeParms dict and array */ 335 } 336 337 if (image->invert) { 338 pdc_puts(p->out, "/D[1 0"); 339 for (i = 1; i < image->components; i++) 340 pdc_puts(p->out, " 1 0"); 341 pdc_puts(p->out, "]"); 342 } 343 344 if (image->ri != AutoIntent) { 345 pdc_printf(p->out, "/Intent/%s", 346 pdc_get_keyword(image->ri, gs_renderingintents)); 347 } 348 349 if (image->interpolate) { 350 pdc_puts(p->out, "/I true"); 351 } 352 353 pdc_puts(p->out, " ID\n"); 354 355 /* Write the actual image data to the content stream */ 356 357 src = &image->src; 358 359 /* We can't use pdf_copy_stream() here because it automatically 360 * generates a stream object, which is not correct for inline 361 * image data. 362 */ 363 if (src->init) 364 src->init(p, src); 365 366 while (src->fill(p, src)) 367 pdc_write(p->out, src->next_byte, src->bytes_available); 368 369 if (src->terminate) 370 src->terminate(p, src); 371 372 pdc_puts(p->out, "EI\n"); 373 374 pdf__restore(p); 375 376 /* Do the equivalent of PDF_close_image() since the image handle 377 * cannot be re-used anyway. 378 */ 379 pdf_cleanup_image(p, im); 380} 381 382void 383pdf_put_image(PDF *p, int im, pdc_bool firststrip) 384{ 385 pdc_id length_id; 386 pdf_image *image; 387 int i; 388 389 image = &p->images[im]; 390 391 /* Images may also be written to the output before the first page */ 392 if (PDF_GET_STATE(p) == pdf_state_page) 393 pdf_end_contents_section(p); 394 395 /* Image object */ 396 397 image->no = pdf_new_xobject(p, image_xobject, PDC_NEW_ID); 398 399 pdc_begin_dict(p->out); /* XObject */ 400 401 pdc_puts(p->out, "/Subtype/Image\n"); 402 403 pdc_printf(p->out, "/Width %d\n", (int) image->width); 404 pdc_printf(p->out, "/Height %d\n", (int) fabs(image->height)); 405 406 /* 407 * Transparency handling 408 */ 409 410 /* Masking by color: single transparent color value */ 411 if (image->transparent) { 412 pdf_colorspace *cs = &p->colorspaces[image->colorspace]; 413 414 switch (cs->type) { 415 case Indexed: 416 case DeviceGray: 417 pdc_printf(p->out,"/Mask[%d %d]\n", 418 (int) image->transval[0], (int) image->transval[0]); 419 break; 420 421 422 case DeviceRGB: 423 pdc_printf(p->out,"/Mask[%d %d %d %d %d %d]\n", 424 (int) image->transval[0], (int) image->transval[0], 425 (int) image->transval[1], (int) image->transval[1], 426 (int) image->transval[2], (int) image->transval[2]); 427 break; 428 429 case DeviceCMYK: 430 pdc_printf(p->out,"/Mask[%d %d %d %d %d %d %d %d]\n", 431 (int) image->transval[0], (int) image->transval[0], 432 (int) image->transval[1], (int) image->transval[1], 433 (int) image->transval[2], (int) image->transval[2], 434 (int) image->transval[3], (int) image->transval[3]); 435 break; 436 437 default: 438 pdc_error(p->pdc, PDF_E_INT_BADCS, 439 pdc_errprintf(p->pdc, "%d", 440 (int) p->colorspaces[image->colorspace].type), 0, 0, 0); 441 } 442 443 /* Masking by position: separate bitmap mask */ 444 } else if (image->mask != pdc_undef && p->images[image->mask].bpc > 1) { 445 pdc_printf(p->out, "/SMask %ld 0 R\n", 446 p->xobjects[p->images[image->mask].no].obj_id); 447 448 } else if (image->mask != pdc_undef) { 449 pdc_printf(p->out, "/Mask %ld 0 R\n", 450 p->xobjects[p->images[image->mask].no].obj_id); 451 } 452 453 /* 454 * /BitsPerComponent is optional for image masks according to the 455 * PDF reference, but some viewers require it nevertheless. 456 * We must therefore always write it. 457 */ 458 pdc_printf(p->out, "/BitsPerComponent %d\n", image->bpc); 459 460 if (image->imagemask) { 461 pdc_puts(p->out, "/ImageMask true\n"); 462 463 } else { 464 465 switch (p->colorspaces[image->colorspace].type) { 466 case DeviceGray: 467 break; 468 469 case DeviceRGB: 470 break; 471 472 case DeviceCMYK: 473 break; 474 475 case Indexed: 476 break; 477 478 479 480 default: 481 pdc_error(p->pdc, PDF_E_INT_BADCS, 482 pdc_errprintf(p->pdc, "%d", image->colorspace), 0, 0, 0); 483 } 484 485 pdc_puts(p->out, "/ColorSpace"); 486 pdf_write_colorspace(p, image->colorspace, pdc_false); 487 pdc_puts(p->out, "\n"); 488 } 489 490 if (image->invert) { 491 pdc_puts(p->out, "/Decode[1 0"); 492 for (i = 1; i < image->components; i++) 493 pdc_puts(p->out, " 1 0"); 494 pdc_puts(p->out, "]\n"); 495 } 496 497 if (image->ri != AutoIntent) { 498 pdc_printf(p->out, "/Intent/%s\n", 499 pdc_get_keyword(image->ri, gs_renderingintents)); 500 } 501 502 if (image->interpolate) { 503 pdc_puts(p->out, "/Interpolate true\n"); 504 } 505 506 /* special case: referenced image data instead of direct data */ 507 if (image->reference != pdf_ref_direct) { 508 509 if (image->compression != none) { 510 pdc_printf(p->out, "/FFilter[/%s]\n", 511 pdf_filter_names[image->compression]); 512 } 513 514 if (image->compression == ccitt) { 515 pdc_puts(p->out, "/FDecodeParms[<<"); 516 517 if ((int) image->width != 1728) /* CCITT default width */ 518 pdc_printf(p->out, "/Columns %d", (int) image->width); 519 520 pdc_printf(p->out, "/Rows %d", (int) fabs(image->height)); 521 522 if (image->K != 0) 523 pdc_printf(p->out, "/K %d", image->K); 524 525 pdc_puts(p->out, ">>]\n"); 526 527 } 528 529 if (image->reference == pdf_ref_file) { 530 531 /* LATER: make image file name platform-neutral: 532 * Change : to / on the Mac 533 * Change \ to / on Windows 534 */ 535 pdc_puts(p->out, "/F"); 536 pdc_put_pdfstring(p->out, image->filename, 537 (int) strlen(image->filename)); 538 pdc_puts(p->out, "/Length 0"); 539 540 } else if (image->reference == pdf_ref_url) { 541 542 pdc_puts(p->out, "/F<</FS/URL/F"); 543 pdc_put_pdfstring(p->out, image->filename, 544 (int) strlen(image->filename)); 545 pdc_puts(p->out, ">>/Length 0"); 546 } 547 548 pdc_end_dict(p->out); /* XObject */ 549 550 /* We must avoid pdc_begin/end_pdfstream() here in order to 551 * generate a really empty stream. 552 */ 553 pdc_puts(p->out, "stream\n"); /* dummy image stream */ 554 pdc_puts(p->out, "endstream\n"); 555 556 pdc_end_obj(p->out); /* XObject */ 557 558 if (PDF_GET_STATE(p) == pdf_state_page) 559 pdf_begin_contents_section(p); 560 561 return; 562 } 563 564 /* 565 * Now the (more common) handling of actual image 566 * data to be included in the PDF output. 567 */ 568 /* do we need a filter (either ASCII or decompression)? */ 569 570 if (p->debug['a']) { 571 pdc_puts(p->out, "/Filter[/ASCIIHexDecode"); 572 if (image->compression != none) 573 pdc_printf(p->out, "/%s", pdf_filter_names[image->compression]); 574 pdc_puts(p->out, "]\n"); 575 576 } else { 577 /* force compression if not a recognized precompressed image format */ 578 if (!image->use_raw && pdc_get_compresslevel(p->out)) 579 image->compression = flate; 580 581 if (image->compression != none) 582 pdc_printf(p->out, "/Filter/%s\n", 583 pdf_filter_names[image->compression]); 584 } 585 586 /* prepare precompressed (raw) image data; avoid empty DecodeParms */ 587 if (image->use_raw && 588 (image->params || 589 image->predictor != pred_default || 590 image->compression == ccitt)) { 591 592 if (p->debug['a']) 593 pdc_printf(p->out, "/DecodeParms[%s<<", "null"); 594 else 595 pdc_printf(p->out, "/DecodeParms<<"); 596 597 /* write EarlyChange */ 598 if (image->params) 599 pdc_puts(p->out, image->params); 600 601 if (image->compression == ccitt) { 602 if (image->K != 0) 603 pdc_printf(p->out, "/K %d", image->K); 604 } 605 606 if (image->compression == flate || image->compression == lzw) { 607 if (image->predictor != pred_default) { 608 pdc_printf(p->out, "/Predictor %d", (int) image->predictor); 609 pdc_printf(p->out, "/Columns %d", (int) image->width); 610 if (image->bpc != 8) 611 pdc_printf(p->out, "/BitsPerComponent %d", image->bpc); 612 613 if (image->components != 1) /* 1 is default */ 614 pdc_printf(p->out, "/Colors %d", image->components); 615 } 616 } 617 618 if (image->compression == ccitt) { 619 if ((int) image->width != 1728) /* CCITT default width */ 620 pdc_printf(p->out, "/Columns %d", (int) image->width); 621 622 pdc_printf(p->out, "/Rows %d", (int) fabs(image->height)); 623 } 624 625 if (p->debug['a']) 626 pdc_puts(p->out, ">>]\n"); /* DecodeParms dict and array */ 627 else 628 pdc_puts(p->out, ">>\n"); /* DecodeParms dict */ 629 } 630 631 /* Write the actual image data */ 632 length_id = pdc_alloc_id(p->out); 633 634 pdc_printf(p->out,"/Length %ld 0 R\n", length_id); 635 pdc_end_dict(p->out); /* XObject */ 636 637 /* image data */ 638 639 if (p->debug['a']) 640 pdf_ASCIIHexEncode(p, &image->src); 641 else { 642 pdf_copy_stream(p, &image->src, !image->use_raw); /* image data */ 643 } 644 645 pdc_end_obj(p->out); /* XObject */ 646 647 pdc_put_pdfstreamlength(p->out, length_id); 648 649 if (p->flush & pdf_flush_content) 650 pdc_flush_stream(p->out); 651 652 /* 653 * Write colormap information for indexed color spaces 654 */ 655 if (firststrip && p->colorspaces[image->colorspace].type == Indexed) { 656 pdf_write_colormap(p, image->colorspace); 657 } 658 659 if (PDF_GET_STATE(p) == pdf_state_page) 660 pdf_begin_contents_section(p); 661 662 if (p->flush & pdf_flush_content) 663 pdc_flush_stream(p->out); 664} 665 666void 667pdf__fit_image(PDF *p, int im, float x, float y, const char *optlist) 668{ 669 pdf_image *image; 670 int legal_states; 671 672 pdf_check_handle(p, im, pdc_imagehandle); 673 674 image = &p->images[im]; 675 676 if (PDF_GET_STATE(p) == pdf_state_glyph && !pdf_get_t3colorized(p) && 677 image->imagemask == pdc_false) 678 legal_states = pdf_state_page | pdf_state_pattern | pdf_state_template; 679 else 680 legal_states = pdf_state_content; 681 PDF_CHECK_STATE(p, legal_states); 682 683 if (PDF_GET_STATE(p) == pdf_state_template && im == p->templ) 684 pdc_error(p->pdc, PDF_E_TEMPLATE_SELF, 685 pdc_errprintf(p->pdc, "%d", im), 0, 0, 0); 686 687 pdf_place_xobject(p, im, x, y, optlist); 688} 689 690PDFLIB_API void PDFLIB_CALL 691PDF_fit_image(PDF *p, int image, float x, float y, const char *optlist) 692{ 693 static const char fn[] = "PDF_fit_image"; 694 695 /* precise scope diagnosis in pdf__fit_image */ 696 if (pdf_enter_api(p, fn, pdf_state_all, 697 "(p[%p], %d, %g, %g, \"%s\")\n", (void *) p, image, x, y, optlist)) 698 { 699 PDF_INPUT_HANDLE(p, image) 700 pdf__fit_image(p, image, x, y, optlist); 701 } 702} 703 704PDFLIB_API void PDFLIB_CALL 705PDF_place_image(PDF *p, int image, float x, float y, float scale) 706{ 707 static const char fn[] = "PDF_place_image"; 708 709 /* precise scope diagnosis in pdf__fit_image */ 710 if (pdf_enter_api(p, fn, pdf_state_all, 711 "(p[%p], %d, %g, %g, %g)\n", (void *) p, image, x, y, scale)) 712 { 713 char optlist[32]; 714 sprintf(optlist, "dpi none scale %g", scale); 715 PDF_INPUT_HANDLE(p, image) 716 pdf__fit_image(p, image, x, y, optlist); 717 } 718} 719 720/* definitions of place image options */ 721static const pdc_defopt pdf_place_xobject_options[] = 722{ 723 {"dpi", pdc_floatlist, 0, 1, 2, 0.0, INT_MAX, pdf_dpi_keylist}, 724 725 {"scale", pdc_floatlist, PDC_OPT_NOZERO, 1, 2, PDC_FLOAT_MIN, PDC_FLOAT_MAX, 726 NULL}, 727 728 {"orientate", pdc_keywordlist, 0, 1, 1, 0.0, 0.0, pdf_orientate_keylist}, 729 730 {"boxsize", pdc_floatlist, 0, 2, 2, PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, 731 732 {"rotate", pdc_floatlist, 0, 1, 1, PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, 733 734 {"position", pdc_floatlist, 0, 1, 2, PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, 735 736 {"fitmethod", pdc_keywordlist, 0, 1, 1, 0.0, 0.0, pdf_fitmethod_keylist}, 737 738 {"distortionlimit", pdc_floatlist, PDC_OPT_NONE, 1, 1, 0.0, 100.0, NULL}, 739 740 {"adjustpage", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0, NULL}, 741 742 {"blind", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, 743 744 PDC_OPT_TERMINATE 745}; 746 747void 748pdf_place_xobject(PDF *p, int im, float x, float y, const char *optlist) 749{ 750 pdf_image *image; 751 pdc_resopt *results; 752 pdc_clientdata data; 753 pdc_matrix m; 754 pdc_fitmethod method; 755 pdc_vector imgscale, elemsize, elemscale, relpos, polyline[5]; 756 pdc_box fitbox, elembox; 757 pdc_scalar ss, scaley, rowsize = 1, lastratio = 1, minfscale; 758 pdc_bool adjustpage, hasresol; 759 pdc_bool blindmode; 760 pdc_bool negdir = pdc_false; 761 float dpi[2], scale[2], boxsize[2], position[2], angle, distortionlimit; 762 float dpi_x, dpi_y, tx = 0, ty = 0; 763 int orientangle, indangle; 764 int inum, num, is, ip, islast; 765 int imageno; 766 767 image = &p->images[im]; 768 769 /* has resolution (image_xobject) */ 770 hasresol = p->xobjects[image->no].type == image_xobject ? 771 pdc_true : pdc_false; 772 773 /* defaults */ 774 orientangle = 0; 775 dpi[0] = dpi[1] = (float) 0.0; 776 scale[0] = scale[1] = (float) 1.0; 777 boxsize[0] = boxsize[1] = (float) 0.0; 778 position[0] = position[1] = (float) 0.0; 779 angle = (float) 0.0; 780 method = pdc_nofit; 781 distortionlimit = (float) 75.0; 782 adjustpage = pdc_false; 783 blindmode = pdc_false; 784 785 /* parsing optlist */ 786 if (optlist && strlen(optlist)) 787 { 788 data.compatibility = p->compatibility; 789 results = pdc_parse_optionlist(p->pdc, optlist, 790 pdf_place_xobject_options, 791 &data, pdc_true); 792 793 /* save and check options */ 794 if (hasresol) 795 dpi[0] = (float) dpi_internal; 796 if ((num = pdc_get_optvalues(p->pdc, "dpi", results, dpi, NULL)) > 0) 797 { 798 if (!hasresol && dpi[0] != (float) dpi_none) 799 pdc_warning(p->pdc, PDC_E_OPT_IGNORED, "dpi", 0, 0, 0); 800 else if (num == 1) 801 dpi[1] = dpi[0]; 802 } 803 804 if (1 == pdc_get_optvalues(p->pdc, "scale", results, scale, NULL)) 805 scale[1] = scale[0]; 806 807 pdc_get_optvalues(p->pdc, "orientate", results, &orientangle, NULL); 808 809 pdc_get_optvalues(p->pdc, "boxsize", results, boxsize, NULL); 810 811 pdc_get_optvalues(p->pdc, "rotate", results, &angle, NULL); 812 813 if (1 == pdc_get_optvalues(p->pdc, "position", results, position, NULL)) 814 position[1] = position[0]; 815 816 if (pdc_get_optvalues(p->pdc, "fitmethod", results, &inum, NULL)) 817 method = (pdc_fitmethod) inum; 818 819 pdc_get_optvalues(p->pdc, "distortionlimit", results, 820 &distortionlimit, NULL); 821 822 pdc_get_optvalues(p->pdc, "adjustpage", results, &adjustpage, NULL); 823 pdc_get_optvalues(p->pdc, "blind", results, &blindmode, NULL); 824 825 pdc_cleanup_optionlist(p->pdc, results); 826 } 827 828 /* calculation of image scale and size */ 829 imgscale.x = scale[0]; 830 imgscale.y = scale[1]; 831 if (hasresol) 832 { 833 if (dpi[0] == (float) dpi_internal) 834 { 835 dpi_x = image->dpi_x; 836 dpi_y = image->dpi_y; 837 if (dpi_x > 0 && dpi_y > 0) 838 { 839 imgscale.x *= 72.0 / dpi_x; 840 imgscale.y *= 72.0 / dpi_y; 841 } 842 else if (dpi_x < 0 && dpi_y < 0) 843 { 844 imgscale.y *= dpi_y / dpi_x; 845 } 846 } 847 else if (dpi[0] > 0) 848 { 849 imgscale.x *= 72.0 / dpi[0]; 850 imgscale.y *= 72.0 / dpi[1]; 851 } 852 rowsize = imgscale.y * image->rowsperstrip; 853 imgscale.x *= image->width; 854 imgscale.y *= image->height; 855 lastratio = (imgscale.y / rowsize) - (image->strips - 1); 856 elemsize.x = imgscale.x; 857 elemsize.y = imgscale.y; 858 } 859 else 860 { 861 elemsize.x = imgscale.x * image->width; 862 elemsize.y = imgscale.y * image->height; 863 } 864 865 /* negative direction (e.g. BMP images) */ 866 if (image->height < 0) 867 { 868 elemsize.y = -elemsize.y; 869 negdir = pdc_true; 870 } 871 872 /* minimal horizontal scaling factor */ 873 minfscale = distortionlimit / 100.0; 874 875 /* orientation */ 876 indangle = orientangle / 90; 877 if (indangle % 2) 878 { 879 ss = elemsize.x; 880 elemsize.x = elemsize.y; 881 elemsize.y = ss; 882 } 883 884 /* box for fitting */ 885 fitbox.ll.x = 0; 886 fitbox.ll.y = 0; 887 fitbox.ur.x = boxsize[0]; 888 fitbox.ur.y = boxsize[1]; 889 890 /* relative position */ 891 relpos.x = position[0] / 100.0; 892 relpos.y = position[1] / 100.0; 893 894 /* calculate image box */ 895 pdc_place_element(method, minfscale, &fitbox, &relpos, 896 &elemsize, &elembox, &elemscale); 897 898 /* adjust page size */ 899 if (adjustpage && PDF_GET_STATE(p) == pdf_state_page) 900 { 901 float urx, ury, height; 902 903 urx = (float) (2 * x + elembox.ur.x); 904 ury = (float) (2 * y + elembox.ur.y); 905 pdc_transform_point(&p->gstate[p->sl].ctm, 906 urx, ury, &p->width, &height); 907 p->height = (p->ydirection > 0) ? 908 height : p->height - p->ydirection * height; 909 if (p->height < p->ydirection * height / 2.0) 910 pdc_error(p->pdc, PDF_E_IMAGE_NOADJUST, 0, 0, 0, 0); 911 912 p->CropBox.llx = 0.0f; 913 p->CropBox.lly = 0.0f; 914 p->CropBox.urx = p->width; 915 p->CropBox.ury = p->height; 916 917 if ((p->width < PDF_ACRO4_MINPAGE || p->width > PDF_ACRO4_MAXPAGE || 918 p->height < PDF_ACRO4_MINPAGE || p->height > PDF_ACRO4_MAXPAGE)) 919 pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO4, 0, 0, 0, 0); 920 } 921 922 if (!blindmode) 923 { 924 pdf_end_text(p); 925 pdf_begin_contents_section(p); 926 927 pdf__save(p); 928 } 929 930 /* reference point */ 931 pdc_translation_matrix(x, y, &m); 932 pdf_concat_raw_ob(p, &m, blindmode); 933 934 /* clipping */ 935 if (!blindmode && (method == pdc_clip || method == pdc_slice)) 936 { 937 pdf__rect(p, 0, 0, boxsize[0], boxsize[1]); 938 pdf__clip(p); 939 } 940 941 /* optional rotation */ 942 if (fabs((double)(angle)) > PDC_FLOAT_PREC) 943 { 944 pdc_rotation_matrix(p->ydirection * angle, &m); 945 pdf_concat_raw_ob(p, &m, blindmode); 946 } 947 948 /* translation of element box */ 949 elembox.ll.y *= p->ydirection; 950 elembox.ur.y *= p->ydirection; 951 pdc_box2polyline(&elembox, polyline); 952 ip = indangle; 953 if (negdir) 954 { 955 ip = indangle - 1; 956 if (ip < 0) ip = 3; 957 } 958 tx = (float) polyline[ip].x; 959 ty = (float) polyline[ip].y; 960 pdc_translation_matrix(tx, ty, &m); 961 pdf_concat_raw_ob(p, &m, blindmode); 962 963 /* orientation of image */ 964 if (orientangle != 0) 965 { 966 pdc_rotation_matrix(p->ydirection * orientangle, &m); 967 pdf_concat_raw_ob(p, &m, blindmode); 968 if (indangle % 2) 969 { 970 ss = elemscale.x; 971 elemscale.x = elemscale.y; 972 elemscale.y = ss; 973 } 974 } 975 976 /* scaling of image */ 977 if (image->strips == 1) 978 scaley = p->ydirection * imgscale.y * elemscale.y; 979 else 980 scaley = p->ydirection * rowsize * elemscale.y; 981 pdc_scale_matrix((float)(imgscale.x * elemscale.x), (float) scaley, &m); 982 pdf_concat_raw_ob(p, &m, blindmode); 983 984 if (!hasresol && !blindmode) 985 { 986 pdf_reset_gstate(p); 987 pdf_reset_tstate(p); 988 } 989 990 991 if (!blindmode) 992 { 993 /* last strip first */ 994 if (image->strips > 1 && lastratio != 1.0) 995 { 996 pdc_scale_matrix((float) 1.0, (float) lastratio, &m); 997 pdf_concat_raw(p, &m); 998 } 999 1000 /* put out image strips separately if available */ 1001 islast = image->strips - 1; 1002 imageno = image->no + islast; 1003 for (is = islast; is >= 0; is--) 1004 { 1005 pdc_printf(p->out, "/I%d Do\n", imageno); 1006 p->xobjects[imageno].flags |= xobj_flag_write; 1007 if (image->strips > 1 && is > 0) 1008 { 1009 pdc_translation_matrix(0, 1, &m); 1010 pdf_concat_raw(p, &m); 1011 if (is == islast && lastratio != 1.0) 1012 { 1013 pdc_scale_matrix((float) 1.0, (float) (1. / lastratio), &m); 1014 pdf_concat_raw(p, &m); 1015 } 1016 imageno--; 1017 } 1018 } 1019 if (image->mask != pdc_undef) 1020 p->xobjects[p->images[image->mask].no].flags |= xobj_flag_write; 1021 1022 pdf__restore(p); 1023 } 1024} 1025 1026#define MAX_THUMBNAIL_SIZE 106 1027 1028PDFLIB_API void PDFLIB_CALL 1029PDF_add_thumbnail(PDF *p, int im) 1030{ 1031 static const char fn[] = "PDF_add_thumbnail"; 1032 pdf_image *image; 1033 1034 if (!pdf_enter_api(p, fn, pdf_state_page, "(p[%p], %d)\n", (void *) p, im)) 1035 return; 1036 1037 PDF_INPUT_HANDLE(p, im) 1038 pdf_check_handle(p, im, pdc_imagehandle); 1039 1040 if (p->thumb_id != PDC_BAD_ID) 1041 pdc_error(p->pdc, PDF_E_IMAGE_THUMB, 0, 0, 0, 0); 1042 1043 image = &p->images[im]; 1044 1045 if (image->strips > 1) 1046 pdc_error(p->pdc, PDF_E_IMAGE_THUMB_MULTISTRIP, 1047 pdc_errprintf(p->pdc, "%d", im), 0, 0, 0); 1048 1049 if (image->width > MAX_THUMBNAIL_SIZE || image->height > MAX_THUMBNAIL_SIZE) 1050 pdc_error(p->pdc, PDF_E_IMAGE_THUMB_SIZE, 1051 pdc_errprintf(p->pdc, "%d", im), 1052 pdc_errprintf(p->pdc, "%d", MAX_THUMBNAIL_SIZE), 0, 0); 1053 1054 if (image->colorspace != (int) DeviceGray && 1055 image->colorspace != (int) DeviceRGB && 1056 image->colorspace != (int) Indexed) 1057 pdc_error(p->pdc, PDF_E_IMAGE_THUMB_CS, 1058 pdc_errprintf(p->pdc, "%d", im), 0, 0, 0); 1059 1060 /* Add the image to the thumbnail key of the current page. */ 1061 p->thumb_id = p->xobjects[image->no].obj_id; 1062} 1063 1064PDFLIB_API void PDFLIB_CALL 1065PDF_close_image(PDF *p, int image) 1066{ 1067 static const char fn[] = "PDF_close_image"; 1068 1069 if (!pdf_enter_api(p, fn, 1070 (pdf_state) (pdf_state_document | pdf_state_page | pdf_state_font), 1071 "(p[%p], %d)\n", (void *) p, image)) 1072 { 1073 return; 1074 } 1075 1076 PDF_INPUT_HANDLE(p, image) 1077 pdf_check_handle(p, image, pdc_imagehandle); 1078 1079 pdf_cleanup_image(p, image); 1080} 1081 1082/* interface for using image data directly in memory */ 1083 1084PDFLIB_API int PDFLIB_CALL 1085PDF_open_image( 1086 PDF *p, 1087 const char *type, 1088 const char *source, 1089 const char *data, 1090 long length, 1091 int width, 1092 int height, 1093 int components, 1094 int bpc, 1095 const char *params) 1096{ 1097 static const char fn[] = "PDF_open_image"; 1098 const char *filename = data; 1099 char optlist[512]; 1100 pdc_bool memory = pdc_false; 1101 int retval = -1; 1102 1103 /* precise scope diagnosis in pdf__load_image */ 1104 if (!pdf_enter_api(p, fn, pdf_state_all, 1105 "(p[%p], \"%s\", \"%s\", data[%p], %ld, %d, %d, %d, %d, \"%s\")", 1106 (void *) p, type, source, (void *) data, length, 1107 width, height, components, bpc, params)) 1108 { 1109 PDF_RETURN_HANDLE(p, retval) 1110 } 1111 1112 if (type == NULL || *type == '\0') 1113 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0); 1114 1115 if (source == NULL || *source == '\0') 1116 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "source", 0, 0, 0); 1117 1118 if (!strcmp(type, "raw") && data == NULL) 1119 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "data", 0, 0, 0); 1120 1121 /* create optlist */ 1122 optlist[0] = 0; 1123 sprintf(optlist,"width %d height %d components %d bpc %d ", 1124 width, height, components, bpc); 1125 1126 if (length < 0L) 1127 { 1128 strcat(optlist, "bitreverse true "); 1129 length = -length; 1130 } 1131 1132 strcat(optlist, "reftype "); 1133 if (!strcmp(source, "fileref")) 1134 strcat(optlist, "fileref "); 1135 else if (!strcmp(source, "memory")) 1136 { 1137 memory = pdc_true; 1138 strcat(optlist, "direct "); 1139 } 1140 else if (!strcmp(source, "url")) 1141 strcat(optlist, "url "); 1142 1143 if (params != NULL && *params != '\0') 1144 { 1145 char **items; 1146 int i, nitems; 1147 1148 /* separator characters because of compatibility */ 1149 nitems = pdc_split_stringlist(p->pdc, params, "\t :", &items); 1150 for (i = 0; i < nitems; i++) 1151 { 1152 if (!strcmp(items[i], "invert")) 1153 strcat(optlist, "invert true "); 1154 else if (!strcmp(items[i], "ignoremask")) 1155 strcat(optlist, "ignoremask true "); 1156 else if (!strcmp(items[i], "inline")) 1157 strcat(optlist, "inline true "); 1158 else if (!strcmp(items[i], "interpolate")) 1159 strcat(optlist, "interpolate true "); 1160 else if (!strcmp(items[i], "mask")) 1161 strcat(optlist, "mask true "); 1162 else if (!strcmp(items[i], "/K")) 1163 strcat(optlist, "K "); 1164 else if (!strcmp(items[i], "/BlackIs1")) 1165 strcat(optlist, "invert "); 1166 else 1167 strcat(optlist, items[i]); 1168 } 1169 pdc_cleanup_stringlist(p->pdc, items); 1170 } 1171 1172 /* create virtual file */ 1173 if (memory) 1174 { 1175 filename = "__raw__image__data__"; 1176 pdf__create_pvf(p, filename, 0, data, (size_t) length, ""); 1177 } 1178 1179 retval = pdf__load_image(p, type, filename, (const char *) optlist); 1180 1181 if (memory) 1182 (void) pdf__delete_pvf(p, filename, 0); 1183 1184 PDF_RETURN_HANDLE(p, retval) 1185} 1186 1187PDFLIB_API int PDFLIB_CALL 1188PDF_open_image_file( 1189 PDF *p, 1190 const char *type, 1191 const char *filename, 1192 const char *stringparam, 1193 int intparam) 1194{ 1195 static const char fn[] = "PDF_open_image_file"; 1196 char optlist[256]; 1197 int retval = -1; 1198 1199 /* precise scope diagnosis in pdf__load_image */ 1200 if (!pdf_enter_api(p, fn, pdf_state_all, 1201 "(p[%p], \"%s\", \"%s\", \"%s\", %d)", 1202 (void *) p, type, filename, stringparam, intparam)) 1203 { 1204 PDF_RETURN_HANDLE(p, retval) 1205 } 1206 1207 optlist[0] = 0; 1208 if (stringparam != NULL && *stringparam != '\0') 1209 { 1210 if (!strcmp(stringparam, "invert")) 1211 strcpy(optlist, "invert true "); 1212 else if (!strcmp(stringparam, "inline")) 1213 strcpy(optlist, "inline true "); 1214 else if (!strcmp(stringparam, "ignoremask")) 1215 strcpy(optlist, "ignoremask true "); 1216 else if (!strcmp(stringparam, "mask")) 1217 strcpy(optlist, "mask true "); 1218 else if (!strcmp(stringparam, "masked")) 1219 sprintf(optlist, "masked %d ", intparam); 1220 else if (!strcmp(stringparam, "colorize")) 1221 sprintf(optlist, "colorize %d ", intparam); 1222 else if (!strcmp(stringparam, "page")) 1223 sprintf(optlist, "page %d ", intparam); 1224 else if (!strcmp(stringparam, "iccprofile")) 1225 sprintf(optlist, "iccprofile %d ", intparam); 1226 } 1227 1228 retval = pdf__load_image(p, type, filename, (const char *) optlist); 1229 1230 PDF_RETURN_HANDLE(p, retval) 1231} 1232 1233PDFLIB_API int PDFLIB_CALL 1234PDF_open_CCITT(PDF *p, const char *filename, int width, int height, 1235 int BitReverse, int K, int BlackIs1) 1236{ 1237 static const char fn[] = "PDF_open_CCITT"; 1238 int retval = -1; 1239 1240 if (pdf_enter_api(p, fn, 1241 (pdf_state) (pdf_state_document | pdf_state_page | pdf_state_font), 1242 "(p[%p], \"%s\", %d, %d, %d, %d, %d)", 1243 (void *) p, filename, width, height, BitReverse, K, BlackIs1)) 1244 { 1245 /* create optlist */ 1246 char optlist[256]; 1247 sprintf(optlist,"width %d height %d bitreverse %s K %d invert %s", 1248 width, height, PDC_BOOLSTR(BitReverse), K, PDC_BOOLSTR(BlackIs1)); 1249 1250 retval = pdf__load_image(p, "CCITT", filename, (const char *) optlist); 1251 } 1252 1253 PDF_RETURN_HANDLE(p, retval) 1254} 1255 1256PDFLIB_API int PDFLIB_CALL 1257PDF_load_image( 1258 PDF *p, 1259 const char *type, 1260 const char *filename, 1261 int reserved, 1262 const char *optlist) 1263{ 1264 static const char fn[] = "PDF_load_image"; 1265 int retval = -1; 1266 1267 /* precise scope diagnosis in pdf__load_image */ 1268 if (pdf_enter_api(p, fn, pdf_state_all, 1269 "(p[%p], \"%s\", \"%s\", %d ,\"%s\")", 1270 (void *) p, type, filename, reserved, optlist)) 1271 { 1272 retval = pdf__load_image(p, type, filename, optlist); 1273 } 1274 1275 PDF_RETURN_HANDLE(p, retval) 1276} 1277 1278 1279/* keywords for options 'reftype' */ 1280static const pdc_keyconn pdf_reftype_keys[] = 1281{ 1282 {"direct", pdf_ref_direct}, 1283 {"fileref", pdf_ref_file}, 1284 {"url", pdf_ref_url}, 1285 {NULL, 0} 1286}; 1287 1288/* allowed values for options 'bcp' */ 1289static const pdc_keyconn pdf_bpcvalues[] = 1290{ 1291 {"1", 1}, {"2", 2}, {"4", 4}, {"8", 8}, {NULL, 0} 1292}; 1293 1294/* allowed values for options 'components' */ 1295static const pdc_keyconn pdf_compvalues[] = 1296{ 1297 {"1", 1}, {"3", 3}, {"4", 4}, {NULL, 0} 1298}; 1299 1300#define PDF_ICCOPT_FLAG PDC_OPT_UNSUPP 1301 1302/* definitions of open image options */ 1303static const pdc_defopt pdf_open_image_options[] = 1304{ 1305 {"bitreverse", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, 1306 1307 {"bpc", pdc_integerlist, PDC_OPT_INTLIST, 1, 1, 1.0, 8.0, pdf_bpcvalues}, 1308 1309 {"components", pdc_integerlist, PDC_OPT_INTLIST, 1, 1, 1.0, 4.0, 1310 pdf_compvalues}, 1311 1312 {"height", pdc_integerlist, 0, 1, 1, 1.0, INT_MAX, NULL}, 1313 1314 {"honoriccprofile", pdc_booleanlist, PDF_ICCOPT_FLAG, 1, 1, 0.0, 0.0, NULL}, 1315 1316 /* ordering of the next three options is significant */ 1317 1318 {"iccprofile", pdc_iccprofilehandle, PDF_ICCOPT_FLAG, 1, 1, 1.0, 0.0, NULL}, 1319 1320 {"colorize", pdc_colorhandle, PDC_OPT_IGNOREIF1, 1, 1, 0.0, 0.0, NULL}, 1321 1322 {"mask", pdc_booleanlist, PDC_OPT_IGNOREIF2, 1, 1, 0.0, 0.0, NULL}, 1323 1324 {"ignoremask", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, 1325 1326 {"imagewarning", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, 1327 1328 {"inline", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, 1329 1330 {"interpolate", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, 1331 1332 {"invert", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, 1333 1334 {"K", pdc_integerlist, 0, 1, 1, -1.0, 1.0, NULL}, 1335 1336 {"masked", pdc_imagehandle, 0, 1, 1, 0.0, 0.0, NULL}, 1337 1338 {"page", pdc_integerlist, 0, 1, 1, 1.0, INT_MAX, NULL}, 1339 1340 {"renderingintent", pdc_keywordlist, 0, 1, 1, 0.0, 0.0, 1341 gs_renderingintents}, 1342 1343 {"reftype", pdc_keywordlist, 0, 1, 1, 0.0, 0.0, pdf_reftype_keys}, 1344 1345 {"width", pdc_integerlist, 0, 1, 1, 1.0, INT_MAX, NULL}, 1346 1347 PDC_OPT_TERMINATE 1348}; 1349 1350int 1351pdf__load_image( 1352 PDF *p, 1353 const char *type, 1354 const char *filename, 1355 const char *optlist) 1356{ 1357 const char *keyword = NULL; 1358 char qualname[32]; 1359 pdc_clientdata data; 1360 pdc_resopt *results; 1361 pdf_image_type imgtype; 1362 int colorize = pdc_undef; 1363 pdf_image *image; 1364 pdc_bool indjpeg = pdc_false; 1365 int legal_states = 0; 1366 int k, inum, imageslot, retval = -1; 1367 1368 if (type == NULL || *type == '\0') 1369 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0); 1370 1371 if (filename == NULL || *filename == '\0') 1372 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "filename", 0, 0, 0); 1373 1374 /* parsing image type */ 1375 k = pdc_get_keycode_ci(type, pdf_image_keylist); 1376 if (k == PDC_KEY_NOTFOUND) 1377 pdc_error(p->pdc, PDC_E_ILLARG_STRING, "type", type, 0, 0); 1378 imgtype = (pdf_image_type) k; 1379 type = pdc_get_keyword(imgtype, pdf_image_keylist); 1380 1381 /* automatic check */ 1382 if (imgtype == pdf_img_auto) 1383 { 1384 pdc_file *fp; 1385 pdf_jpeg_info jpeg_info; 1386 pdf_tiff_info tiff_info; 1387 1388 if ((fp = pdf_fopen(p, filename, "", PDC_FILE_BINARY)) == NULL) 1389 { 1390 if (p->debug['i']) 1391 pdc_error(p->pdc, -1, 0, 0, 0, 0); 1392 1393 return -1; 1394 } 1395 1396 if (pdf_is_BMP_file(p, fp)) 1397 imgtype = pdf_img_bmp; 1398 else if (pdf_is_GIF_file(p, fp)) 1399 imgtype = pdf_img_gif; 1400 else if (pdf_is_PNG_file(p, fp)) 1401 imgtype = pdf_img_png; 1402 else if (pdf_is_TIFF_file(p, fp, &tiff_info, pdc_true)) 1403 imgtype = pdf_img_tiff; 1404 else if (pdf_is_JPEG_file(p, fp, &jpeg_info)) 1405 imgtype = pdf_img_jpeg; 1406 else 1407 { 1408 pdc_fclose(fp); 1409 1410 pdc_set_errmsg(p->pdc, PDF_E_IMAGE_UNKNOWN, filename, 0, 0, 0); 1411 1412 if (p->debug['i']) 1413 pdc_error(p->pdc, -1, 0, 0, 0, 0); 1414 1415 return -1; 1416 } 1417 pdc_fclose(fp); 1418 type = pdc_get_keyword(imgtype, pdf_image_keylist); 1419 } 1420 1421 /* find free slot */ 1422 for (imageslot = 0; imageslot < p->images_capacity; imageslot++) 1423 if (!p->images[imageslot].in_use) 1424 break; 1425 1426 if (imageslot == p->images_capacity) 1427 pdf_grow_images(p); 1428 image = &p->images[imageslot]; 1429 1430 /* inherit global flags */ 1431 image->verbose = p->debug['i']; 1432 image->ri = p->rendintent; 1433 1434 /* parsing optlist */ 1435 if (optlist && strlen(optlist)) 1436 { 1437 data.compatibility = p->compatibility; 1438 data.maxcolor = p->colorspaces_number - 1; 1439 data.maximage = p->images_capacity - 1; 1440 data.hastobepos = p->hastobepos; 1441 results = pdc_parse_optionlist(p->pdc, optlist, pdf_open_image_options, 1442 &data, image->verbose); 1443 if (!results) 1444 return -1; 1445 1446 /* save and check options */ 1447 keyword = "imagewarning"; 1448 pdc_get_optvalues(p->pdc, keyword, results, 1449 &image->verbose, NULL); 1450 keyword = "reftype"; 1451 if (pdc_get_optvalues(p->pdc, keyword, results, &inum, NULL)) 1452 { 1453 image->reference = (pdf_ref_type) inum; 1454 if (image->reference != pdf_ref_direct && 1455 imgtype != pdf_img_ccitt && 1456 imgtype != pdf_img_jpeg && 1457 imgtype != pdf_img_raw) 1458 { 1459 if (image->verbose) 1460 pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNSUPP, keyword, type, 1461 0, 0); 1462 image->reference = pdf_ref_direct; 1463 } 1464 } 1465 indjpeg = (imgtype == pdf_img_jpeg && 1466 image->reference != pdf_ref_direct) ? pdc_true : pdc_false; 1467 1468 keyword = "bpc"; 1469 if (pdc_get_optvalues(p->pdc, keyword, results, 1470 &image->bpc, NULL)) 1471 { 1472 if (image->verbose && imgtype != pdf_img_raw && !indjpeg) 1473 pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, type, 0, 0); 1474 } 1475 1476 keyword = "components"; 1477 if (pdc_get_optvalues(p->pdc, keyword, results, 1478 &image->components, NULL)) 1479 { 1480 if (image->verbose && imgtype != pdf_img_raw && !indjpeg) 1481 pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, type, 0, 0); 1482 } 1483 1484 keyword = "height"; 1485 if (pdc_get_optvalues(p->pdc, keyword, results, 1486 &image->height_pixel, NULL)) 1487 { 1488 if (image->verbose && imgtype != pdf_img_ccitt && 1489 imgtype != pdf_img_raw && !indjpeg) 1490 pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, type, 0, 0); 1491 } 1492 1493 keyword = "width"; 1494 if (pdc_get_optvalues(p->pdc, keyword, results, 1495 &image->width_pixel, NULL)) 1496 { 1497 if (image->verbose && imgtype != pdf_img_raw && 1498 imgtype != pdf_img_ccitt && !indjpeg) 1499 pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, type, 0, 0); 1500 } 1501 1502 keyword = "bitreverse"; 1503 if (pdc_get_optvalues(p->pdc, keyword, results, 1504 &image->bitreverse, NULL)) 1505 { 1506 if (image->verbose && image->bitreverse && 1507 (imgtype != pdf_img_ccitt || image->reference != pdf_ref_direct)) 1508 pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, type, 0, 0); 1509 } 1510 1511 keyword = "colorize"; 1512 pdc_get_optvalues(p->pdc, keyword, results, &colorize, NULL); 1513 1514 1515 keyword = "ignoremask"; 1516 if (pdc_get_optvalues(p->pdc, keyword, results, 1517 &image->ignoremask, NULL)) 1518 { 1519 if (image->verbose && (imgtype == pdf_img_bmp || 1520 imgtype == pdf_img_ccitt || 1521 imgtype == pdf_img_raw)) 1522 pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNSUPP, keyword, type, 0, 0); 1523 } 1524 1525 keyword = "inline"; 1526 if (pdc_get_optvalues(p->pdc, keyword, results, 1527 &image->doinline, NULL) && image->doinline) 1528 { 1529 if (imgtype != pdf_img_ccitt && 1530 imgtype != pdf_img_jpeg && 1531 imgtype != pdf_img_raw) 1532 { 1533 if (image->verbose) 1534 pdc_warning(p->pdc, 1535 PDF_E_IMAGE_OPTUNSUPP, keyword, type, 0, 0); 1536 image->doinline = pdc_false; 1537 } 1538 else if (image->verbose && image->reference != pdf_ref_direct) 1539 { 1540 pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, type, 0, 0); 1541 image->doinline = pdc_false; 1542 } 1543 } 1544 1545 keyword = "interpolate"; 1546 pdc_get_optvalues(p->pdc, keyword, results, 1547 &image->interpolate, NULL); 1548 1549 keyword = "invert"; 1550 pdc_get_optvalues(p->pdc, keyword, results, 1551 &image->invert, NULL); 1552 1553 keyword = "K"; 1554 if (pdc_get_optvalues(p->pdc, keyword, results, 1555 &image->K, NULL)) 1556 { 1557 if (image->verbose && imgtype != pdf_img_ccitt) 1558 pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, type, 0, 0); 1559 } 1560 1561 keyword = "mask"; 1562 pdc_get_optvalues(p->pdc, keyword, results, 1563 &image->imagemask, NULL); 1564 1565 keyword = "masked"; 1566 if (pdc_get_optvalues(p->pdc, keyword, results, 1567 &image->mask, NULL)) 1568 { 1569 if (!p->images[image->mask].in_use || 1570 p->images[image->mask].strips != 1 || 1571 (p->compatibility <= PDC_1_3 && 1572 (p->images[image->mask].imagemask != pdc_true || 1573 p->images[image->mask].bpc != 1))) 1574 { 1575 pdc_set_errmsg(p->pdc, PDF_E_IMAGE_OPTBADMASK, keyword, 1576 pdc_errprintf(p->pdc, "%d", image->mask), 0, 0); 1577 1578 if (image->verbose) 1579 pdc_error(p->pdc, -1, 0, 0, 0, 0); 1580 1581 pdc_cleanup_optionlist(p->pdc, results); 1582 pdf_cleanup_image(p, imageslot); 1583 return -1; 1584 } 1585 } 1586 1587 keyword = "renderingintent"; 1588 if (pdc_get_optvalues(p->pdc, keyword, results, &inum, NULL)) 1589 image->ri = (pdf_renderingintent) inum; 1590 1591 keyword = "page"; 1592 if (pdc_get_optvalues(p->pdc, keyword, results, 1593 &image->page, NULL)) 1594 { 1595 if (imgtype != pdf_img_gif && imgtype != pdf_img_tiff) 1596 { 1597 if (image->page == 1) 1598 { 1599 if (image->verbose) 1600 pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNSUPP, keyword, 1601 type, 0, 0); 1602 } 1603 else 1604 { 1605 pdc_set_errmsg(p->pdc, PDF_E_IMAGE_NOPAGE, 1606 pdc_errprintf(p->pdc, "%d", image->page), type, 1607 pdc_errprintf(p->pdc, "%s", filename), 0); 1608 1609 if (image->verbose) 1610 pdc_error(p->pdc, -1, 0, 0, 0, 0); 1611 1612 pdc_cleanup_optionlist(p->pdc, results); 1613 pdf_cleanup_image(p, imageslot); 1614 return -1; 1615 } 1616 } 1617 } 1618 1619 pdc_cleanup_optionlist(p->pdc, results); 1620 } 1621 1622 /* precise scope diagnosis */ 1623 if (image->doinline) 1624 legal_states = pdf_state_content; 1625 else 1626 legal_states = pdf_state_document | pdf_state_page | pdf_state_font; 1627 PDF_CHECK_STATE(p, legal_states); 1628 1629 /* required options */ 1630 if (imgtype == pdf_img_raw || imgtype == pdf_img_ccitt || indjpeg) 1631 { 1632 keyword = ""; 1633 if (image->height_pixel == pdc_undef) 1634 keyword = "height"; 1635 else if (image->width_pixel == pdc_undef) 1636 keyword = "width"; 1637 else 1638 { 1639 image->width = (float) image->width_pixel; 1640 image->height = (float) image->height_pixel; 1641 } 1642 1643 if (imgtype == pdf_img_ccitt) 1644 { 1645 image->components = 1; 1646 image->bpc = 1; 1647 } 1648 if (image->bpc == pdc_undef) 1649 keyword = "bpc"; 1650 else if (image->components == pdc_undef) 1651 keyword = "components"; 1652 1653 if (*keyword) 1654 { 1655 pdc_set_errmsg(p->pdc, PDC_E_OPT_NOTFOUND, keyword, 0, 0, 0); 1656 1657 if (image->verbose) 1658 pdc_error(p->pdc, -1, 0, 0, 0, 0); 1659 1660 pdf_cleanup_image(p, imageslot); 1661 return -1; 1662 } 1663 } 1664 1665 /* set colorspace */ 1666 if (colorize != pdc_undef) 1667 { 1668 image->colorspace = colorize; 1669 } 1670 else if (image->imagemask == pdc_true) 1671 { 1672 image->colorspace = (int) DeviceGray; 1673 } 1674 else 1675 { 1676 switch(image->components) 1677 { 1678 case 1: 1679 image->colorspace = DeviceGray; 1680 break; 1681 1682 case 3: 1683 image->colorspace = DeviceRGB; 1684 break; 1685 1686 case 4: 1687 image->colorspace = DeviceCMYK; 1688 break; 1689 1690 default: 1691 break; 1692 } 1693 } 1694 1695 /* try to open image file */ 1696 if (image->reference == pdf_ref_direct) 1697 { 1698 strcpy(qualname, type); 1699 strcat(qualname, " "); 1700 image->fp = pdf_fopen(p, filename, qualname, PDC_FILE_BINARY); 1701 1702 if (image->fp == NULL) 1703 { 1704 if (image->verbose) 1705 pdc_error(p->pdc, -1, 0, 0, 0, 0); 1706 1707 pdf_cleanup_image(p, imageslot); 1708 return -1; 1709 } 1710 } 1711 1712 /* copy filename */ 1713 image->filename = pdc_strdup(p->pdc, filename); 1714 1715 1716 /* call working function */ 1717 switch (imgtype) 1718 { 1719 case pdf_img_bmp: 1720 retval = pdf_process_BMP_data(p, imageslot); 1721 break; 1722 1723 case pdf_img_ccitt: 1724 retval = pdf_process_CCITT_data(p, imageslot); 1725 break; 1726 1727 case pdf_img_gif: 1728 retval = pdf_process_GIF_data(p, imageslot); 1729 break; 1730 1731 case pdf_img_jpeg: 1732 retval = pdf_process_JPEG_data(p, imageslot); 1733 break; 1734 1735 case pdf_img_png: 1736 retval = pdf_process_PNG_data(p, imageslot); 1737 break; 1738 1739 default: 1740 case pdf_img_raw: 1741 retval = pdf_process_RAW_data(p, imageslot); 1742 break; 1743 1744 case pdf_img_tiff: 1745 retval = pdf_process_TIFF_data(p, imageslot); 1746 break; 1747 } 1748 1749 /* cleanup */ 1750 if (retval == -1) 1751 { 1752 pdf_cleanup_image(p, imageslot); 1753 } 1754 else 1755 { 1756 if (image->fp) 1757 pdc_fclose(image->fp); 1758 image->fp = NULL; 1759 } 1760 1761 return retval; 1762} 1763