1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % PPPP DDDD FFFFF % 7 % P P D D F % 8 % PPPP D D FFF % 9 % P D D F % 10 % P DDDD F % 11 % % 12 % % 13 % Read/Write Portable Document Format % 14 % % 15 % Software Design % 16 % Cristy % 17 % July 1992 % 18 % % 19 % % 20 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 21 % dedicated to making software imaging solutions freely available. % 22 % % 23 % You may not use this file except in compliance with the License. You may % 24 % obtain a copy of the License at % 25 % % 26 % http://www.imagemagick.org/script/license.php % 27 % % 28 % Unless required by applicable law or agreed to in writing, software % 29 % distributed under the License is distributed on an "AS IS" BASIS, % 30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31 % See the License for the specific language governing permissions and % 32 % limitations under the License. % 33 % % 34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 % 36 % 37 */ 38 39 /* 41 Include declarations. 42 */ 43 #include "MagickCore/studio.h" 44 #include "MagickCore/attribute.h" 45 #include "MagickCore/artifact.h" 46 #include "MagickCore/blob.h" 47 #include "MagickCore/blob-private.h" 48 #include "MagickCore/cache.h" 49 #include "MagickCore/color.h" 50 #include "MagickCore/color-private.h" 51 #include "MagickCore/colorspace.h" 52 #include "MagickCore/colorspace-private.h" 53 #include "MagickCore/compress.h" 54 #include "MagickCore/constitute.h" 55 #include "MagickCore/delegate.h" 56 #include "MagickCore/delegate-private.h" 57 #include "MagickCore/draw.h" 58 #include "MagickCore/exception.h" 59 #include "MagickCore/exception-private.h" 60 #include "MagickCore/geometry.h" 61 #include "MagickCore/image.h" 62 #include "MagickCore/image-private.h" 63 #include "MagickCore/list.h" 64 #include "MagickCore/magick.h" 65 #include "MagickCore/memory_.h" 66 #include "MagickCore/monitor.h" 67 #include "MagickCore/monitor-private.h" 68 #include "MagickCore/nt-base-private.h" 69 #include "MagickCore/option.h" 70 #include "MagickCore/pixel-accessor.h" 71 #include "MagickCore/profile.h" 72 #include "MagickCore/property.h" 73 #include "MagickCore/quantum-private.h" 74 #include "MagickCore/resource_.h" 75 #include "MagickCore/resize.h" 76 #include "MagickCore/signature.h" 77 #include "MagickCore/static.h" 78 #include "MagickCore/string_.h" 79 #include "MagickCore/module.h" 80 #include "MagickCore/token.h" 81 #include "MagickCore/transform.h" 82 #include "MagickCore/utility.h" 83 #include "MagickCore/module.h" 84 85 /* 87 Define declarations. 88 */ 89 #if defined(MAGICKCORE_TIFF_DELEGATE) 90 #define CCITTParam "-1" 91 #else 92 #define CCITTParam "0" 93 #endif 94 95 /* 97 Forward declarations. 98 */ 99 static MagickBooleanType 100 WritePDFImage(const ImageInfo *,Image *,ExceptionInfo *); 101 102 /* 104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 105 % % 106 % % 107 % % 108 % I n v o k e P D F D e l e g a t e % 109 % % 110 % % 111 % % 112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 113 % 114 % InvokePDFDelegate() executes the PDF interpreter with the specified command. 115 % 116 % The format of the InvokePDFDelegate method is: 117 % 118 % MagickBooleanType InvokePDFDelegate(const MagickBooleanType verbose, 119 % const char *command,ExceptionInfo *exception) 120 % 121 % A description of each parameter follows: 122 % 123 % o verbose: A value other than zero displays the command prior to 124 % executing it. 125 % 126 % o command: the address of a character string containing the command to 127 % execute. 128 % 129 % o exception: return any errors or warnings in this structure. 130 % 131 */ 132 #if defined(MAGICKCORE_GS_DELEGATE) || defined(MAGICKCORE_WINDOWS_SUPPORT) 133 static int MagickDLLCall PDFDelegateMessage(void *handle,const char *message, 134 int length) 135 { 136 char 137 **messages; 138 139 ssize_t 140 offset; 141 142 offset=0; 143 messages=(char **) handle; 144 if (*messages == (char *) NULL) 145 *messages=(char *) AcquireQuantumMemory(length+1,sizeof(char *)); 146 else 147 { 148 offset=strlen(*messages); 149 *messages=(char *) ResizeQuantumMemory(*messages,offset+length+1, 150 sizeof(char *)); 151 } 152 (void) memcpy(*messages+offset,message,length); 153 (*messages)[length+offset] ='\0'; 154 return(length); 155 } 156 #endif 157 158 static MagickBooleanType InvokePDFDelegate(const MagickBooleanType verbose, 159 const char *command,char *message,ExceptionInfo *exception) 160 { 161 int 162 status; 163 164 #if defined(MAGICKCORE_GS_DELEGATE) || defined(MAGICKCORE_WINDOWS_SUPPORT) 165 #define SetArgsStart(command,args_start) \ 166 if (args_start == (const char *) NULL) \ 167 { \ 168 if (*command != '"') \ 169 args_start=strchr(command,' '); \ 170 else \ 171 { \ 172 args_start=strchr(command+1,'"'); \ 173 if (args_start != (const char *) NULL) \ 174 args_start++; \ 175 } \ 176 } 177 178 #define ExecuteGhostscriptCommand(command,status) \ 179 { \ 180 status=ExternalDelegateCommand(MagickFalse,verbose,command,message, \ 181 exception); \ 182 if (status == 0) \ 183 return(MagickTrue); \ 184 if (status < 0) \ 185 return(MagickFalse); \ 186 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError, \ 187 "FailedToExecuteCommand","`%s' (%d)",command,status); \ 188 return(MagickFalse); \ 189 } 190 191 char 192 **argv, 193 *errors; 194 195 const char 196 *args_start = (const char *) NULL; 197 198 const GhostInfo 199 *ghost_info; 200 201 gs_main_instance 202 *interpreter; 203 204 gsapi_revision_t 205 revision; 206 207 int 208 argc, 209 code; 210 211 register ssize_t 212 i; 213 214 #if defined(MAGICKCORE_WINDOWS_SUPPORT) 215 ghost_info=NTGhostscriptDLLVectors(); 216 #else 217 GhostInfo 218 ghost_info_struct; 219 220 ghost_info=(&ghost_info_struct); 221 (void) ResetMagickMemory(&ghost_info_struct,0,sizeof(ghost_info_struct)); 222 ghost_info_struct.delete_instance=(void (*)(gs_main_instance *)) 223 gsapi_delete_instance; 224 ghost_info_struct.exit=(int (*)(gs_main_instance *)) gsapi_exit; 225 ghost_info_struct.new_instance=(int (*)(gs_main_instance **,void *)) 226 gsapi_new_instance; 227 ghost_info_struct.init_with_args=(int (*)(gs_main_instance *,int,char **)) 228 gsapi_init_with_args; 229 ghost_info_struct.run_string=(int (*)(gs_main_instance *,const char *,int, 230 int *)) gsapi_run_string; 231 ghost_info_struct.set_stdio=(int (*)(gs_main_instance *,int(*)(void *,char *, 232 int),int(*)(void *,const char *,int),int(*)(void *, const char *, int))) 233 gsapi_set_stdio; 234 ghost_info_struct.revision=(int (*)(gsapi_revision_t *,int)) gsapi_revision; 235 #endif 236 if (ghost_info == (GhostInfo *) NULL) 237 ExecuteGhostscriptCommand(command,status); 238 if ((ghost_info->revision)(&revision,sizeof(revision)) != 0) 239 revision.revision=0; 240 if (verbose != MagickFalse) 241 { 242 (void) fprintf(stdout,"[ghostscript library %.2f]",(double) 243 revision.revision/100.0); 244 SetArgsStart(command,args_start); 245 (void) fputs(args_start,stdout); 246 } 247 errors=(char *) NULL; 248 status=(ghost_info->new_instance)(&interpreter,(void *) &errors); 249 if (status < 0) 250 ExecuteGhostscriptCommand(command,status); 251 code=0; 252 argv=StringToArgv(command,&argc); 253 if (argv == (char **) NULL) 254 { 255 (ghost_info->delete_instance)(interpreter); 256 return(MagickFalse); 257 } 258 (void) (ghost_info->set_stdio)(interpreter,(int(MagickDLLCall *)(void *, 259 char *,int)) NULL,PDFDelegateMessage,PDFDelegateMessage); 260 status=(ghost_info->init_with_args)(interpreter,argc-1,argv+1); 261 if (status == 0) 262 status=(ghost_info->run_string)(interpreter,"systemdict /start get exec\n", 263 0,&code); 264 (ghost_info->exit)(interpreter); 265 (ghost_info->delete_instance)(interpreter); 266 for (i=0; i < (ssize_t) argc; i++) 267 argv[i]=DestroyString(argv[i]); 268 argv=(char **) RelinquishMagickMemory(argv); 269 if (status != 0) 270 { 271 SetArgsStart(command,args_start); 272 if (status == -101) /* quit */ 273 (void) FormatLocaleString(message,MagickPathExtent, 274 "[ghostscript library %.2f]%s: %s",(double)revision.revision / 100, 275 args_start,errors); 276 else 277 { 278 (void) ThrowMagickException(exception,GetMagickModule(), 279 DelegateError,"PDFDelegateFailed", 280 "`[ghostscript library %.2f]%s': %s", 281 (double)revision.revision / 100,args_start,errors); 282 if (errors != (char *) NULL) 283 errors=DestroyString(errors); 284 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 285 "Ghostscript returns status %d, exit code %d",status,code); 286 return(MagickFalse); 287 } 288 } 289 if (errors != (char *) NULL) 290 errors=DestroyString(errors); 291 return(MagickTrue); 292 #else 293 status=ExternalDelegateCommand(MagickFalse,verbose,command,message,exception); 294 return(status == 0 ? MagickTrue : MagickFalse); 295 #endif 296 } 297 298 /* 300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 301 % % 302 % % 303 % % 304 % I s P D F % 305 % % 306 % % 307 % % 308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 309 % 310 % IsPDF() returns MagickTrue if the image format type, identified by the 311 % magick string, is PDF. 312 % 313 % The format of the IsPDF method is: 314 % 315 % MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset) 316 % 317 % A description of each parameter follows: 318 % 319 % o magick: compare image format pattern against these bytes. 320 % 321 % o offset: Specifies the offset of the magick string. 322 % 323 */ 324 static MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset) 325 { 326 if (offset < 5) 327 return(MagickFalse); 328 if (LocaleNCompare((const char *) magick,"%PDF-",5) == 0) 329 return(MagickTrue); 330 return(MagickFalse); 331 } 332 333 /* 335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 336 % % 337 % % 338 % % 339 % R e a d P D F I m a g e % 340 % % 341 % % 342 % % 343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 344 % 345 % ReadPDFImage() reads a Portable Document Format image file and 346 % returns it. It allocates the memory necessary for the new Image structure 347 % and returns a pointer to the new image. 348 % 349 % The format of the ReadPDFImage method is: 350 % 351 % Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception) 352 % 353 % A description of each parameter follows: 354 % 355 % o image_info: the image info. 356 % 357 % o exception: return any errors or warnings in this structure. 358 % 359 */ 360 361 static MagickBooleanType IsPDFRendered(const char *path) 362 { 363 MagickBooleanType 364 status; 365 366 struct stat 367 attributes; 368 369 if ((path == (const char *) NULL) || (*path == '\0')) 370 return(MagickFalse); 371 status=GetPathAttributes(path,&attributes); 372 if ((status != MagickFalse) && S_ISREG(attributes.st_mode) && 373 (attributes.st_size > 0)) 374 return(MagickTrue); 375 return(MagickFalse); 376 } 377 378 static Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception) 379 { 380 #define CMYKProcessColor "CMYKProcessColor" 381 #define CropBox "CropBox" 382 #define DefaultCMYK "DefaultCMYK" 383 #define DeviceCMYK "DeviceCMYK" 384 #define MediaBox "MediaBox" 385 #define RenderPostscriptText "Rendering Postscript... " 386 #define PDFRotate "Rotate" 387 #define SpotColor "Separation" 388 #define TrimBox "TrimBox" 389 #define PDFVersion "PDF-" 390 391 char 392 command[MagickPathExtent], 393 *density, 394 filename[MagickPathExtent], 395 geometry[MagickPathExtent], 396 input_filename[MagickPathExtent], 397 message[MagickPathExtent], 398 *options, 399 postscript_filename[MagickPathExtent]; 400 401 const char 402 *option; 403 404 const DelegateInfo 405 *delegate_info; 406 407 double 408 angle; 409 410 GeometryInfo 411 geometry_info; 412 413 Image 414 *image, 415 *next, 416 *pdf_image; 417 418 ImageInfo 419 *read_info; 420 421 int 422 c, 423 file; 424 425 MagickBooleanType 426 cmyk, 427 cropbox, 428 fitPage, 429 status, 430 stop_on_error, 431 trimbox; 432 433 MagickStatusType 434 flags; 435 436 PointInfo 437 delta; 438 439 RectangleInfo 440 bounding_box, 441 page; 442 443 register char 444 *p; 445 446 register ssize_t 447 i; 448 449 SegmentInfo 450 bounds, 451 hires_bounds; 452 453 size_t 454 scene, 455 spotcolor; 456 457 ssize_t 458 count; 459 460 assert(image_info != (const ImageInfo *) NULL); 461 assert(image_info->signature == MagickCoreSignature); 462 if (image_info->debug != MagickFalse) 463 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 464 image_info->filename); 465 assert(exception != (ExceptionInfo *) NULL); 466 assert(exception->signature == MagickCoreSignature); 467 /* 468 Open image file. 469 */ 470 image=AcquireImage(image_info,exception); 471 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 472 if (status == MagickFalse) 473 { 474 image=DestroyImageList(image); 475 return((Image *) NULL); 476 } 477 status=AcquireUniqueSymbolicLink(image_info->filename,input_filename); 478 if (status == MagickFalse) 479 { 480 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile", 481 image_info->filename); 482 image=DestroyImageList(image); 483 return((Image *) NULL); 484 } 485 /* 486 Set the page density. 487 */ 488 delta.x=DefaultResolution; 489 delta.y=DefaultResolution; 490 if ((image->resolution.x == 0.0) || (image->resolution.y == 0.0)) 491 { 492 flags=ParseGeometry(PSDensityGeometry,&geometry_info); 493 image->resolution.x=geometry_info.rho; 494 image->resolution.y=geometry_info.sigma; 495 if ((flags & SigmaValue) == 0) 496 image->resolution.y=image->resolution.x; 497 } 498 if (image_info->density != (char *) NULL) 499 { 500 flags=ParseGeometry(image_info->density,&geometry_info); 501 image->resolution.x=geometry_info.rho; 502 image->resolution.y=geometry_info.sigma; 503 if ((flags & SigmaValue) == 0) 504 image->resolution.y=image->resolution.x; 505 } 506 (void) ResetMagickMemory(&page,0,sizeof(page)); 507 (void) ParseAbsoluteGeometry(PSPageGeometry,&page); 508 if (image_info->page != (char *) NULL) 509 (void) ParseAbsoluteGeometry(image_info->page,&page); 510 page.width=(size_t) ceil((double) (page.width*image->resolution.x/delta.x)- 511 0.5); 512 page.height=(size_t) ceil((double) (page.height*image->resolution.y/delta.y)- 513 0.5); 514 /* 515 Determine page geometry from the PDF media box. 516 */ 517 cmyk=image_info->colorspace == CMYKColorspace ? MagickTrue : MagickFalse; 518 cropbox=IsStringTrue(GetImageOption(image_info,"pdf:use-cropbox")); 519 stop_on_error=IsStringTrue(GetImageOption(image_info,"pdf:stop-on-error")); 520 trimbox=IsStringTrue(GetImageOption(image_info,"pdf:use-trimbox")); 521 count=0; 522 spotcolor=0; 523 (void) ResetMagickMemory(&bounding_box,0,sizeof(bounding_box)); 524 (void) ResetMagickMemory(&bounds,0,sizeof(bounds)); 525 (void) ResetMagickMemory(&hires_bounds,0,sizeof(hires_bounds)); 526 (void) ResetMagickMemory(command,0,sizeof(command)); 527 angle=0.0; 528 p=command; 529 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image)) 530 { 531 /* 532 Note PDF elements. 533 */ 534 if (c == '\n') 535 c=' '; 536 *p++=(char) c; 537 if ((c != (int) '/') && (c != (int) '%') && 538 ((size_t) (p-command) < (MagickPathExtent-1))) 539 continue; 540 *(--p)='\0'; 541 p=command; 542 if (LocaleNCompare(PDFRotate,command,strlen(PDFRotate)) == 0) 543 count=(ssize_t) sscanf(command,"Rotate %lf",&angle); 544 /* 545 Is this a CMYK document? 546 */ 547 if (LocaleNCompare(DefaultCMYK,command,strlen(DefaultCMYK)) == 0) 548 cmyk=MagickTrue; 549 if (LocaleNCompare(DeviceCMYK,command,strlen(DeviceCMYK)) == 0) 550 cmyk=MagickTrue; 551 if (LocaleNCompare(CMYKProcessColor,command,strlen(CMYKProcessColor)) == 0) 552 cmyk=MagickTrue; 553 if (LocaleNCompare(SpotColor,command,strlen(SpotColor)) == 0) 554 { 555 char 556 name[MagickPathExtent], 557 property[MagickPathExtent], 558 *value; 559 560 /* 561 Note spot names. 562 */ 563 (void) FormatLocaleString(property,MagickPathExtent, 564 "pdf:SpotColor-%.20g",(double) spotcolor++); 565 i=0; 566 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image)) 567 { 568 if ((isspace(c) != 0) || (c == '/') || ((i+1) == MagickPathExtent)) 569 break; 570 name[i++]=(char) c; 571 } 572 name[i]='\0'; 573 value=AcquireString(name); 574 (void) SubstituteString(&value,"#20"," "); 575 (void) SetImageProperty(image,property,value,exception); 576 value=DestroyString(value); 577 continue; 578 } 579 if (LocaleNCompare(PDFVersion,command,strlen(PDFVersion)) == 0) 580 (void) SetImageProperty(image,"pdf:Version",command,exception); 581 if (image_info->page != (char *) NULL) 582 continue; 583 count=0; 584 if (cropbox != MagickFalse) 585 { 586 if (LocaleNCompare(CropBox,command,strlen(CropBox)) == 0) 587 { 588 /* 589 Note region defined by crop box. 590 */ 591 count=(ssize_t) sscanf(command,"CropBox [%lf %lf %lf %lf", 592 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2); 593 if (count != 4) 594 count=(ssize_t) sscanf(command,"CropBox[%lf %lf %lf %lf", 595 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2); 596 } 597 } 598 else 599 if (trimbox != MagickFalse) 600 { 601 if (LocaleNCompare(TrimBox,command,strlen(TrimBox)) == 0) 602 { 603 /* 604 Note region defined by trim box. 605 */ 606 count=(ssize_t) sscanf(command,"TrimBox [%lf %lf %lf %lf", 607 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2); 608 if (count != 4) 609 count=(ssize_t) sscanf(command,"TrimBox[%lf %lf %lf %lf", 610 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2); 611 } 612 } 613 else 614 if (LocaleNCompare(MediaBox,command,strlen(MediaBox)) == 0) 615 { 616 /* 617 Note region defined by media box. 618 */ 619 count=(ssize_t) sscanf(command,"MediaBox [%lf %lf %lf %lf", 620 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2); 621 if (count != 4) 622 count=(ssize_t) sscanf(command,"MediaBox[%lf %lf %lf %lf", 623 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2); 624 } 625 if (count != 4) 626 continue; 627 if ((fabs(bounds.x2-bounds.x1) <= fabs(hires_bounds.x2-hires_bounds.x1)) || 628 (fabs(bounds.y2-bounds.y1) <= fabs(hires_bounds.y2-hires_bounds.y1))) 629 continue; 630 hires_bounds=bounds; 631 } 632 if ((fabs(hires_bounds.x2-hires_bounds.x1) >= MagickEpsilon) && 633 (fabs(hires_bounds.y2-hires_bounds.y1) >= MagickEpsilon)) 634 { 635 /* 636 Set PDF render geometry. 637 */ 638 (void) FormatLocaleString(geometry,MagickPathExtent,"%gx%g%+.15g%+.15g", 639 hires_bounds.x2-bounds.x1,hires_bounds.y2-hires_bounds.y1, 640 hires_bounds.x1,hires_bounds.y1); 641 (void) SetImageProperty(image,"pdf:HiResBoundingBox",geometry,exception); 642 page.width=(size_t) ceil((double) ((hires_bounds.x2-hires_bounds.x1)* 643 image->resolution.x/delta.x)-0.5); 644 page.height=(size_t) ceil((double) ((hires_bounds.y2-hires_bounds.y1)* 645 image->resolution.y/delta.y)-0.5); 646 } 647 fitPage=MagickFalse; 648 option=GetImageOption(image_info,"pdf:fit-page"); 649 if (option != (char *) NULL) 650 { 651 char 652 *page_geometry; 653 654 page_geometry=GetPageGeometry(option); 655 flags=ParseMetaGeometry(page_geometry,&page.x,&page.y,&page.width, 656 &page.height); 657 page_geometry=DestroyString(page_geometry); 658 if (flags == NoValue) 659 { 660 (void) ThrowMagickException(exception,GetMagickModule(),OptionError, 661 "InvalidGeometry","`%s'",option); 662 image=DestroyImage(image); 663 return((Image *) NULL); 664 } 665 page.width=(size_t) ceil((double) (page.width*image->resolution.x/delta.x) 666 -0.5); 667 page.height=(size_t) ceil((double) (page.height*image->resolution.y/ 668 delta.y) -0.5); 669 fitPage=MagickTrue; 670 } 671 (void) CloseBlob(image); 672 if ((fabs(angle) == 90.0) || (fabs(angle) == 270.0)) 673 { 674 size_t 675 swap; 676 677 swap=page.width; 678 page.width=page.height; 679 page.height=swap; 680 } 681 if (IssRGBCompatibleColorspace(image_info->colorspace) != MagickFalse) 682 cmyk=MagickFalse; 683 /* 684 Create Ghostscript control file. 685 */ 686 file=AcquireUniqueFileResource(postscript_filename); 687 if (file == -1) 688 { 689 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile", 690 image_info->filename); 691 image=DestroyImage(image); 692 return((Image *) NULL); 693 } 694 count=write(file," ",1); 695 file=close(file)-1; 696 /* 697 Render Postscript with the Ghostscript delegate. 698 */ 699 if (image_info->monochrome != MagickFalse) 700 delegate_info=GetDelegateInfo("ps:mono",(char *) NULL,exception); 701 else 702 if (cmyk != MagickFalse) 703 delegate_info=GetDelegateInfo("ps:cmyk",(char *) NULL,exception); 704 else 705 delegate_info=GetDelegateInfo("ps:alpha",(char *) NULL,exception); 706 if (delegate_info == (const DelegateInfo *) NULL) 707 { 708 (void) RelinquishUniqueFileResource(postscript_filename); 709 image=DestroyImage(image); 710 return((Image *) NULL); 711 } 712 density=AcquireString(""); 713 options=AcquireString(""); 714 (void) FormatLocaleString(density,MagickPathExtent,"%gx%g", 715 image->resolution.x,image->resolution.y); 716 if ((image_info->page != (char *) NULL) || (fitPage != MagickFalse)) 717 (void) FormatLocaleString(options,MagickPathExtent,"-g%.20gx%.20g ",(double) 718 page.width,(double) page.height); 719 if (fitPage != MagickFalse) 720 (void) ConcatenateMagickString(options,"-dPSFitPage ",MagickPathExtent); 721 if (cmyk != MagickFalse) 722 (void) ConcatenateMagickString(options,"-dUseCIEColor ",MagickPathExtent); 723 if (cropbox != MagickFalse) 724 (void) ConcatenateMagickString(options,"-dUseCropBox ",MagickPathExtent); 725 if (stop_on_error != MagickFalse) 726 (void) ConcatenateMagickString(options,"-dPDFSTOPONERROR ", 727 MagickPathExtent); 728 if (trimbox != MagickFalse) 729 (void) ConcatenateMagickString(options,"-dUseTrimBox ",MagickPathExtent); 730 read_info=CloneImageInfo(image_info); 731 *read_info->magick='\0'; 732 if (read_info->number_scenes != 0) 733 { 734 char 735 pages[MagickPathExtent]; 736 737 (void) FormatLocaleString(pages,MagickPathExtent,"-dFirstPage=%.20g " 738 "-dLastPage=%.20g",(double) read_info->scene+1,(double) 739 (read_info->scene+read_info->number_scenes)); 740 (void) ConcatenateMagickString(options,pages,MagickPathExtent); 741 read_info->number_scenes=0; 742 if (read_info->scenes != (char *) NULL) 743 *read_info->scenes='\0'; 744 } 745 (void) CopyMagickString(filename,read_info->filename,MagickPathExtent); 746 (void) AcquireUniqueFilename(filename); 747 (void) RelinquishUniqueFileResource(filename); 748 (void) ConcatenateMagickString(filename,"%d",MagickPathExtent); 749 (void) FormatLocaleString(command,MagickPathExtent, 750 GetDelegateCommands(delegate_info), 751 read_info->antialias != MagickFalse ? 4 : 1, 752 read_info->antialias != MagickFalse ? 4 : 1,density,options,filename, 753 postscript_filename,input_filename); 754 options=DestroyString(options); 755 density=DestroyString(density); 756 *message='\0'; 757 status=InvokePDFDelegate(read_info->verbose,command,message,exception); 758 (void) RelinquishUniqueFileResource(postscript_filename); 759 (void) RelinquishUniqueFileResource(input_filename); 760 pdf_image=(Image *) NULL; 761 if (status == MagickFalse) 762 for (i=1; ; i++) 763 { 764 (void) InterpretImageFilename(image_info,image,filename,(int) i, 765 read_info->filename,exception); 766 if (IsPDFRendered(read_info->filename) == MagickFalse) 767 break; 768 (void) RelinquishUniqueFileResource(read_info->filename); 769 } 770 else 771 for (i=1; ; i++) 772 { 773 (void) InterpretImageFilename(image_info,image,filename,(int) i, 774 read_info->filename,exception); 775 if (IsPDFRendered(read_info->filename) == MagickFalse) 776 break; 777 read_info->blob=NULL; 778 read_info->length=0; 779 next=ReadImage(read_info,exception); 780 (void) RelinquishUniqueFileResource(read_info->filename); 781 if (next == (Image *) NULL) 782 break; 783 AppendImageToList(&pdf_image,next); 784 } 785 read_info=DestroyImageInfo(read_info); 786 if (pdf_image == (Image *) NULL) 787 { 788 if (*message != '\0') 789 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError, 790 "PDFDelegateFailed","`%s'",message); 791 image=DestroyImage(image); 792 return((Image *) NULL); 793 } 794 if (LocaleCompare(pdf_image->magick,"BMP") == 0) 795 { 796 Image 797 *cmyk_image; 798 799 cmyk_image=ConsolidateCMYKImages(pdf_image,exception); 800 if (cmyk_image != (Image *) NULL) 801 { 802 pdf_image=DestroyImageList(pdf_image); 803 pdf_image=cmyk_image; 804 } 805 } 806 if (image_info->number_scenes != 0) 807 { 808 Image 809 *clone_image; 810 811 /* 812 Add place holder images to meet the subimage specification requirement. 813 */ 814 for (i=0; i < (ssize_t) image_info->scene; i++) 815 { 816 clone_image=CloneImage(pdf_image,1,1,MagickTrue,exception); 817 if (clone_image != (Image *) NULL) 818 PrependImageToList(&pdf_image,clone_image); 819 } 820 } 821 do 822 { 823 (void) CopyMagickString(pdf_image->filename,filename,MagickPathExtent); 824 (void) CopyMagickString(pdf_image->magick,image->magick,MagickPathExtent); 825 pdf_image->page=page; 826 (void) CloneImageProfiles(pdf_image,image); 827 (void) CloneImageProperties(pdf_image,image); 828 next=SyncNextImageInList(pdf_image); 829 if (next != (Image *) NULL) 830 pdf_image=next; 831 } while (next != (Image *) NULL); 832 image=DestroyImage(image); 833 scene=0; 834 for (next=GetFirstImageInList(pdf_image); next != (Image *) NULL; ) 835 { 836 next->scene=scene++; 837 next=GetNextImageInList(next); 838 } 839 return(GetFirstImageInList(pdf_image)); 840 } 841 842 /* 844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 845 % % 846 % % 847 % % 848 % R e g i s t e r P D F I m a g e % 849 % % 850 % % 851 % % 852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 853 % 854 % RegisterPDFImage() adds properties for the PDF image format to 855 % the list of supported formats. The properties include the image format 856 % tag, a method to read and/or write the format, whether the format 857 % supports the saving of more than one frame to the same file or blob, 858 % whether the format supports native in-memory I/O, and a brief 859 % description of the format. 860 % 861 % The format of the RegisterPDFImage method is: 862 % 863 % size_t RegisterPDFImage(void) 864 % 865 */ 866 ModuleExport size_t RegisterPDFImage(void) 867 { 868 MagickInfo 869 *entry; 870 871 entry=AcquireMagickInfo("PDF","AI","Adobe Illustrator CS2"); 872 entry->decoder=(DecodeImageHandler *) ReadPDFImage; 873 entry->encoder=(EncodeImageHandler *) WritePDFImage; 874 entry->flags^=CoderAdjoinFlag; 875 entry->flags^=CoderBlobSupportFlag; 876 entry->flags|=CoderSeekableStreamFlag; 877 entry->mime_type=ConstantString("application/pdf"); 878 (void) RegisterMagickInfo(entry); 879 entry=AcquireMagickInfo("PDF","EPDF", 880 "Encapsulated Portable Document Format"); 881 entry->decoder=(DecodeImageHandler *) ReadPDFImage; 882 entry->encoder=(EncodeImageHandler *) WritePDFImage; 883 entry->flags^=CoderAdjoinFlag; 884 entry->flags^=CoderBlobSupportFlag; 885 entry->flags|=CoderSeekableStreamFlag; 886 entry->mime_type=ConstantString("application/pdf"); 887 (void) RegisterMagickInfo(entry); 888 entry=AcquireMagickInfo("PDF","PDF","Portable Document Format"); 889 entry->decoder=(DecodeImageHandler *) ReadPDFImage; 890 entry->encoder=(EncodeImageHandler *) WritePDFImage; 891 entry->magick=(IsImageFormatHandler *) IsPDF; 892 entry->flags^=CoderBlobSupportFlag; 893 entry->flags|=CoderSeekableStreamFlag; 894 entry->mime_type=ConstantString("application/pdf"); 895 (void) RegisterMagickInfo(entry); 896 entry=AcquireMagickInfo("PDF","PDFA","Portable Document Archive Format"); 897 entry->decoder=(DecodeImageHandler *) ReadPDFImage; 898 entry->encoder=(EncodeImageHandler *) WritePDFImage; 899 entry->magick=(IsImageFormatHandler *) IsPDF; 900 entry->flags^=CoderBlobSupportFlag; 901 entry->flags|=CoderSeekableStreamFlag; 902 entry->mime_type=ConstantString("application/pdf"); 903 (void) RegisterMagickInfo(entry); 904 return(MagickImageCoderSignature); 905 } 906 907 /* 909 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 910 % % 911 % % 912 % % 913 % U n r e g i s t e r P D F I m a g e % 914 % % 915 % % 916 % % 917 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 918 % 919 % UnregisterPDFImage() removes format registrations made by the 920 % PDF module from the list of supported formats. 921 % 922 % The format of the UnregisterPDFImage method is: 923 % 924 % UnregisterPDFImage(void) 925 % 926 */ 927 ModuleExport void UnregisterPDFImage(void) 928 { 929 (void) UnregisterMagickInfo("AI"); 930 (void) UnregisterMagickInfo("EPDF"); 931 (void) UnregisterMagickInfo("PDF"); 932 (void) UnregisterMagickInfo("PDFA"); 933 } 934 935 /* 937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 938 % % 939 % % 940 % % 941 % W r i t e P D F I m a g e % 942 % % 943 % % 944 % % 945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 946 % 947 % WritePDFImage() writes an image in the Portable Document image 948 % format. 949 % 950 % The format of the WritePDFImage method is: 951 % 952 % MagickBooleanType WritePDFImage(const ImageInfo *image_info, 953 % Image *image,ExceptionInfo *exception) 954 % 955 % A description of each parameter follows. 956 % 957 % o image_info: the image info. 958 % 959 % o image: The image. 960 % 961 % o exception: return any errors or warnings in this structure. 962 % 963 */ 964 965 static char *EscapeParenthesis(const char *source) 966 { 967 char 968 *destination; 969 970 register char 971 *q; 972 973 register const char 974 *p; 975 976 size_t 977 length; 978 979 assert(source != (const char *) NULL); 980 length=0; 981 for (p=source; *p != '\0'; p++) 982 { 983 if ((*p == '\\') || (*p == '(') || (*p == ')')) 984 { 985 if (~length < 1) 986 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString"); 987 length++; 988 } 989 length++; 990 } 991 destination=(char *) NULL; 992 if (~length >= (MagickPathExtent-1)) 993 destination=(char *) AcquireQuantumMemory(length+MagickPathExtent, 994 sizeof(*destination)); 995 if (destination == (char *) NULL) 996 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString"); 997 *destination='\0'; 998 q=destination; 999 for (p=source; *p != '\0'; p++) 1000 { 1001 if ((*p == '\\') || (*p == '(') || (*p == ')')) 1002 *q++='\\'; 1003 *q++=(*p); 1004 } 1005 *q='\0'; 1006 return(destination); 1007 } 1008 1009 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16) 1010 { 1011 register const unsigned char 1012 *p; 1013 1014 if (utf16 != (wchar_t *) NULL) 1015 { 1016 register wchar_t 1017 *q; 1018 1019 wchar_t 1020 c; 1021 1022 /* 1023 Convert UTF-8 to UTF-16. 1024 */ 1025 q=utf16; 1026 for (p=utf8; *p != '\0'; p++) 1027 { 1028 if ((*p & 0x80) == 0) 1029 *q=(*p); 1030 else 1031 if ((*p & 0xE0) == 0xC0) 1032 { 1033 c=(*p); 1034 *q=(c & 0x1F) << 6; 1035 p++; 1036 if ((*p & 0xC0) != 0x80) 1037 return(0); 1038 *q|=(*p & 0x3F); 1039 } 1040 else 1041 if ((*p & 0xF0) == 0xE0) 1042 { 1043 c=(*p); 1044 *q=c << 12; 1045 p++; 1046 if ((*p & 0xC0) != 0x80) 1047 return(0); 1048 c=(*p); 1049 *q|=(c & 0x3F) << 6; 1050 p++; 1051 if ((*p & 0xC0) != 0x80) 1052 return(0); 1053 *q|=(*p & 0x3F); 1054 } 1055 else 1056 return(0); 1057 q++; 1058 } 1059 *q++='\0'; 1060 return(q-utf16); 1061 } 1062 /* 1063 Compute UTF-16 string length. 1064 */ 1065 for (p=utf8; *p != '\0'; p++) 1066 { 1067 if ((*p & 0x80) == 0) 1068 ; 1069 else 1070 if ((*p & 0xE0) == 0xC0) 1071 { 1072 p++; 1073 if ((*p & 0xC0) != 0x80) 1074 return(0); 1075 } 1076 else 1077 if ((*p & 0xF0) == 0xE0) 1078 { 1079 p++; 1080 if ((*p & 0xC0) != 0x80) 1081 return(0); 1082 p++; 1083 if ((*p & 0xC0) != 0x80) 1084 return(0); 1085 } 1086 else 1087 return(0); 1088 } 1089 return(p-utf8); 1090 } 1091 1092 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source,size_t *length) 1093 { 1094 wchar_t 1095 *utf16; 1096 1097 *length=UTF8ToUTF16(source,(wchar_t *) NULL); 1098 if (*length == 0) 1099 { 1100 register ssize_t 1101 i; 1102 1103 /* 1104 Not UTF-8, just copy. 1105 */ 1106 *length=strlen((const char *) source); 1107 utf16=(wchar_t *) AcquireQuantumMemory(*length+1,sizeof(*utf16)); 1108 if (utf16 == (wchar_t *) NULL) 1109 return((wchar_t *) NULL); 1110 for (i=0; i <= (ssize_t) *length; i++) 1111 utf16[i]=source[i]; 1112 return(utf16); 1113 } 1114 utf16=(wchar_t *) AcquireQuantumMemory(*length+1,sizeof(*utf16)); 1115 if (utf16 == (wchar_t *) NULL) 1116 return((wchar_t *) NULL); 1117 *length=UTF8ToUTF16(source,utf16); 1118 return(utf16); 1119 } 1120 1121 static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info, 1122 Image *image,Image *inject_image,ExceptionInfo *exception) 1123 { 1124 Image 1125 *group4_image; 1126 1127 ImageInfo 1128 *write_info; 1129 1130 MagickBooleanType 1131 status; 1132 1133 size_t 1134 length; 1135 1136 unsigned char 1137 *group4; 1138 1139 status=MagickTrue; 1140 write_info=CloneImageInfo(image_info); 1141 (void) CopyMagickString(write_info->filename,"GROUP4:",MagickPathExtent); 1142 (void) CopyMagickString(write_info->magick,"GROUP4",MagickPathExtent); 1143 group4_image=CloneImage(inject_image,0,0,MagickTrue,exception); 1144 if (group4_image == (Image *) NULL) 1145 return(MagickFalse); 1146 group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length, 1147 exception); 1148 group4_image=DestroyImage(group4_image); 1149 if (group4 == (unsigned char *) NULL) 1150 return(MagickFalse); 1151 write_info=DestroyImageInfo(write_info); 1152 if (WriteBlob(image,length,group4) != (ssize_t) length) 1153 status=MagickFalse; 1154 group4=(unsigned char *) RelinquishMagickMemory(group4); 1155 return(status); 1156 } 1157 1158 static MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image, 1159 ExceptionInfo *exception) 1160 { 1161 #define CFormat "/Filter [ /%s ]\n" 1162 #define ObjectsPerImage 14 1163 1164 DisableMSCWarning(4310) 1165 static const char 1166 XMPProfile[]= 1167 { 1168 "<?xpacket begin=\"%s\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n" 1169 "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"Adobe XMP Core 4.0-c316 44.253921, Sun Oct 01 2006 17:08:23\">\n" 1170 " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n" 1171 " <rdf:Description rdf:about=\"\"\n" 1172 " xmlns:xap=\"http://ns.adobe.com/xap/1.0/\">\n" 1173 " <xap:ModifyDate>%s</xap:ModifyDate>\n" 1174 " <xap:CreateDate>%s</xap:CreateDate>\n" 1175 " <xap:MetadataDate>%s</xap:MetadataDate>\n" 1176 " <xap:CreatorTool>%s</xap:CreatorTool>\n" 1177 " </rdf:Description>\n" 1178 " <rdf:Description rdf:about=\"\"\n" 1179 " xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n" 1180 " <dc:format>application/pdf</dc:format>\n" 1181 " <dc:title>\n" 1182 " <rdf:Alt>\n" 1183 " <rdf:li xml:lang=\"x-default\">%s</rdf:li>\n" 1184 " </rdf:Alt>\n" 1185 " </dc:title>\n" 1186 " </rdf:Description>\n" 1187 " <rdf:Description rdf:about=\"\"\n" 1188 " xmlns:xapMM=\"http://ns.adobe.com/xap/1.0/mm/\">\n" 1189 " <xapMM:DocumentID>uuid:6ec119d7-7982-4f56-808d-dfe64f5b35cf</xapMM:DocumentID>\n" 1190 " <xapMM:InstanceID>uuid:a79b99b4-6235-447f-9f6c-ec18ef7555cb</xapMM:InstanceID>\n" 1191 " </rdf:Description>\n" 1192 " <rdf:Description rdf:about=\"\"\n" 1193 " xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n" 1194 " <pdf:Producer>%s</pdf:Producer>\n" 1195 " </rdf:Description>\n" 1196 " <rdf:Description rdf:about=\"\"\n" 1197 " xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n" 1198 " <pdfaid:part>3</pdfaid:part>\n" 1199 " <pdfaid:conformance>B</pdfaid:conformance>\n" 1200 " </rdf:Description>\n" 1201 " </rdf:RDF>\n" 1202 "</x:xmpmeta>\n" 1203 "<?xpacket end=\"w\"?>\n" 1204 }, 1205 XMPProfileMagick[4]= { (char) 0xef, (char) 0xbb, (char) 0xbf, (char) 0x00 }; 1206 RestoreMSCWarning 1207 1208 char 1209 basename[MagickPathExtent], 1210 buffer[MagickPathExtent], 1211 date[MagickPathExtent], 1212 **labels, 1213 page_geometry[MagickPathExtent]; 1214 1215 CompressionType 1216 compression; 1217 1218 const char 1219 *option, 1220 *value; 1221 1222 double 1223 pointsize; 1224 1225 GeometryInfo 1226 geometry_info; 1227 1228 Image 1229 *next, 1230 *tile_image; 1231 1232 MagickBooleanType 1233 status; 1234 1235 MagickOffsetType 1236 offset, 1237 scene, 1238 *xref; 1239 1240 MagickSizeType 1241 number_pixels; 1242 1243 MagickStatusType 1244 flags; 1245 1246 PointInfo 1247 delta, 1248 resolution, 1249 scale; 1250 1251 RectangleInfo 1252 geometry, 1253 media_info, 1254 page_info; 1255 1256 register const Quantum 1257 *p; 1258 1259 register unsigned char 1260 *q; 1261 1262 register ssize_t 1263 i, 1264 x; 1265 1266 size_t 1267 info_id, 1268 length, 1269 object, 1270 pages_id, 1271 root_id, 1272 text_size, 1273 version; 1274 1275 ssize_t 1276 count, 1277 y; 1278 1279 struct tm 1280 local_time; 1281 1282 time_t 1283 seconds; 1284 1285 unsigned char 1286 *pixels; 1287 1288 wchar_t 1289 *utf16; 1290 1291 /* 1292 Open output image file. 1293 */ 1294 assert(image_info != (const ImageInfo *) NULL); 1295 assert(image_info->signature == MagickCoreSignature); 1296 assert(image != (Image *) NULL); 1297 assert(image->signature == MagickCoreSignature); 1298 if (image->debug != MagickFalse) 1299 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1300 assert(exception != (ExceptionInfo *) NULL); 1301 assert(exception->signature == MagickCoreSignature); 1302 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 1303 if (status == MagickFalse) 1304 return(status); 1305 /* 1306 Allocate X ref memory. 1307 */ 1308 xref=(MagickOffsetType *) AcquireQuantumMemory(2048UL,sizeof(*xref)); 1309 if (xref == (MagickOffsetType *) NULL) 1310 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1311 (void) ResetMagickMemory(xref,0,2048UL*sizeof(*xref)); 1312 /* 1313 Write Info object. 1314 */ 1315 object=0; 1316 version=3; 1317 if (image_info->compression == JPEG2000Compression) 1318 version=(size_t) MagickMax(version,5); 1319 for (next=image; next != (Image *) NULL; next=GetNextImageInList(next)) 1320 if (next->alpha_trait != UndefinedPixelTrait) 1321 version=(size_t) MagickMax(version,4); 1322 if (LocaleCompare(image_info->magick,"PDFA") == 0) 1323 version=(size_t) MagickMax(version,6); 1324 (void) FormatLocaleString(buffer,MagickPathExtent,"%%PDF-1.%.20g \n",(double) 1325 version); 1326 (void) WriteBlobString(image,buffer); 1327 if (LocaleCompare(image_info->magick,"PDFA") == 0) 1328 { 1329 (void) WriteBlobByte(image,'%'); 1330 (void) WriteBlobByte(image,0xe2); 1331 (void) WriteBlobByte(image,0xe3); 1332 (void) WriteBlobByte(image,0xcf); 1333 (void) WriteBlobByte(image,0xd3); 1334 (void) WriteBlobByte(image,'\n'); 1335 } 1336 /* 1337 Write Catalog object. 1338 */ 1339 xref[object++]=TellBlob(image); 1340 root_id=object; 1341 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 1342 object); 1343 (void) WriteBlobString(image,buffer); 1344 (void) WriteBlobString(image,"<<\n"); 1345 if (LocaleCompare(image_info->magick,"PDFA") != 0) 1346 (void) FormatLocaleString(buffer,MagickPathExtent,"/Pages %.20g 0 R\n", 1347 (double) object+1); 1348 else 1349 { 1350 (void) FormatLocaleString(buffer,MagickPathExtent,"/Metadata %.20g 0 R\n", 1351 (double) object+1); 1352 (void) WriteBlobString(image,buffer); 1353 (void) FormatLocaleString(buffer,MagickPathExtent,"/Pages %.20g 0 R\n", 1354 (double) object+2); 1355 } 1356 (void) WriteBlobString(image,buffer); 1357 (void) WriteBlobString(image,"/Type /Catalog"); 1358 option=GetImageOption(image_info,"pdf:page-direction"); 1359 if ((option != (const char *) NULL) && 1360 (LocaleCompare(option,"right-to-left") != MagickFalse)) 1361 (void) WriteBlobString(image,"/ViewerPreferences<</PageDirection/R2L>>\n"); 1362 (void) WriteBlobString(image,"\n"); 1363 (void) WriteBlobString(image,">>\n"); 1364 (void) WriteBlobString(image,"endobj\n"); 1365 GetPathComponent(image->filename,BasePath,basename); 1366 if (LocaleCompare(image_info->magick,"PDFA") == 0) 1367 { 1368 char 1369 create_date[MagickPathExtent], 1370 modify_date[MagickPathExtent], 1371 timestamp[MagickPathExtent], 1372 xmp_profile[MagickPathExtent]; 1373 1374 /* 1375 Write XMP object. 1376 */ 1377 xref[object++]=TellBlob(image); 1378 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 1379 object); 1380 (void) WriteBlobString(image,buffer); 1381 (void) WriteBlobString(image,"<<\n"); 1382 (void) WriteBlobString(image,"/Subtype /XML\n"); 1383 *modify_date='\0'; 1384 value=GetImageProperty(image,"date:modify",exception); 1385 if (value != (const char *) NULL) 1386 (void) CopyMagickString(modify_date,value,MagickPathExtent); 1387 *create_date='\0'; 1388 value=GetImageProperty(image,"date:create",exception); 1389 if (value != (const char *) NULL) 1390 (void) CopyMagickString(create_date,value,MagickPathExtent); 1391 (void) FormatMagickTime(time((time_t *) NULL),MagickPathExtent,timestamp); 1392 i=FormatLocaleString(xmp_profile,MagickPathExtent,XMPProfile, 1393 XMPProfileMagick,modify_date,create_date,timestamp, 1394 GetMagickVersion(&version),EscapeParenthesis(basename), 1395 GetMagickVersion(&version)); 1396 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g\n", 1397 (double) i); 1398 (void) WriteBlobString(image,buffer); 1399 (void) WriteBlobString(image,"/Type /Metadata\n"); 1400 (void) WriteBlobString(image,">>\nstream\n"); 1401 (void) WriteBlobString(image,xmp_profile); 1402 (void) WriteBlobString(image,"\nendstream\n"); 1403 (void) WriteBlobString(image,"endobj\n"); 1404 } 1405 /* 1406 Write Pages object. 1407 */ 1408 xref[object++]=TellBlob(image); 1409 pages_id=object; 1410 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 1411 object); 1412 (void) WriteBlobString(image,buffer); 1413 (void) WriteBlobString(image,"<<\n"); 1414 (void) WriteBlobString(image,"/Type /Pages\n"); 1415 (void) FormatLocaleString(buffer,MagickPathExtent,"/Kids [ %.20g 0 R ", 1416 (double) object+1); 1417 (void) WriteBlobString(image,buffer); 1418 count=(ssize_t) (pages_id+ObjectsPerImage+1); 1419 if (image_info->adjoin != MagickFalse) 1420 { 1421 Image 1422 *kid_image; 1423 1424 /* 1425 Predict page object id's. 1426 */ 1427 kid_image=image; 1428 for ( ; GetNextImageInList(kid_image) != (Image *) NULL; count+=ObjectsPerImage) 1429 { 1430 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 R ",(double) 1431 count); 1432 (void) WriteBlobString(image,buffer); 1433 kid_image=GetNextImageInList(kid_image); 1434 } 1435 xref=(MagickOffsetType *) ResizeQuantumMemory(xref,(size_t) count+2048UL, 1436 sizeof(*xref)); 1437 if (xref == (MagickOffsetType *) NULL) 1438 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1439 } 1440 (void) WriteBlobString(image,"]\n"); 1441 (void) FormatLocaleString(buffer,MagickPathExtent,"/Count %.20g\n",(double) 1442 ((count-pages_id)/ObjectsPerImage)); 1443 (void) WriteBlobString(image,buffer); 1444 (void) WriteBlobString(image,">>\n"); 1445 (void) WriteBlobString(image,"endobj\n"); 1446 scene=0; 1447 do 1448 { 1449 compression=image->compression; 1450 if (image_info->compression != UndefinedCompression) 1451 compression=image_info->compression; 1452 switch (compression) 1453 { 1454 case FaxCompression: 1455 case Group4Compression: 1456 { 1457 if ((SetImageMonochrome(image,exception) == MagickFalse) || 1458 (image->alpha_trait != UndefinedPixelTrait)) 1459 compression=RLECompression; 1460 break; 1461 } 1462 #if !defined(MAGICKCORE_JPEG_DELEGATE) 1463 case JPEGCompression: 1464 { 1465 compression=RLECompression; 1466 (void) ThrowMagickException(exception,GetMagickModule(), 1467 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)", 1468 image->filename); 1469 break; 1470 } 1471 #endif 1472 #if !defined(MAGICKCORE_LIBOPENJP2_DELEGATE) 1473 case JPEG2000Compression: 1474 { 1475 compression=RLECompression; 1476 (void) ThrowMagickException(exception,GetMagickModule(), 1477 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JP2)", 1478 image->filename); 1479 break; 1480 } 1481 #endif 1482 #if !defined(MAGICKCORE_ZLIB_DELEGATE) 1483 case ZipCompression: 1484 { 1485 compression=RLECompression; 1486 (void) ThrowMagickException(exception,GetMagickModule(), 1487 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (ZLIB)", 1488 image->filename); 1489 break; 1490 } 1491 #endif 1492 case LZWCompression: 1493 { 1494 if (LocaleCompare(image_info->magick,"PDFA") == 0) 1495 compression=RLECompression; /* LZW compression is forbidden */ 1496 break; 1497 } 1498 case NoCompression: 1499 { 1500 if (LocaleCompare(image_info->magick,"PDFA") == 0) 1501 compression=RLECompression; /* ASCII 85 compression is forbidden */ 1502 break; 1503 } 1504 default: 1505 break; 1506 } 1507 if (compression == JPEG2000Compression) 1508 (void) TransformImageColorspace(image,sRGBColorspace,exception); 1509 /* 1510 Scale relative to dots-per-inch. 1511 */ 1512 delta.x=DefaultResolution; 1513 delta.y=DefaultResolution; 1514 resolution.x=image->resolution.x; 1515 resolution.y=image->resolution.y; 1516 if ((resolution.x == 0.0) || (resolution.y == 0.0)) 1517 { 1518 flags=ParseGeometry(PSDensityGeometry,&geometry_info); 1519 resolution.x=geometry_info.rho; 1520 resolution.y=geometry_info.sigma; 1521 if ((flags & SigmaValue) == 0) 1522 resolution.y=resolution.x; 1523 } 1524 if (image_info->density != (char *) NULL) 1525 { 1526 flags=ParseGeometry(image_info->density,&geometry_info); 1527 resolution.x=geometry_info.rho; 1528 resolution.y=geometry_info.sigma; 1529 if ((flags & SigmaValue) == 0) 1530 resolution.y=resolution.x; 1531 } 1532 if (image->units == PixelsPerCentimeterResolution) 1533 { 1534 resolution.x=(double) ((size_t) (100.0*2.54*resolution.x+0.5)/100.0); 1535 resolution.y=(double) ((size_t) (100.0*2.54*resolution.y+0.5)/100.0); 1536 } 1537 SetGeometry(image,&geometry); 1538 (void) FormatLocaleString(page_geometry,MagickPathExtent,"%.20gx%.20g", 1539 (double) image->columns,(double) image->rows); 1540 if (image_info->page != (char *) NULL) 1541 (void) CopyMagickString(page_geometry,image_info->page,MagickPathExtent); 1542 else 1543 if ((image->page.width != 0) && (image->page.height != 0)) 1544 (void) FormatLocaleString(page_geometry,MagickPathExtent, 1545 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,(double) 1546 image->page.height,(double) image->page.x,(double) image->page.y); 1547 else 1548 if ((image->gravity != UndefinedGravity) && 1549 (LocaleCompare(image_info->magick,"PDF") == 0)) 1550 (void) CopyMagickString(page_geometry,PSPageGeometry, 1551 MagickPathExtent); 1552 (void) ConcatenateMagickString(page_geometry,">",MagickPathExtent); 1553 (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y, 1554 &geometry.width,&geometry.height); 1555 scale.x=(double) (geometry.width*delta.x)/resolution.x; 1556 geometry.width=(size_t) floor(scale.x+0.5); 1557 scale.y=(double) (geometry.height*delta.y)/resolution.y; 1558 geometry.height=(size_t) floor(scale.y+0.5); 1559 (void) ParseAbsoluteGeometry(page_geometry,&media_info); 1560 (void) ParseGravityGeometry(image,page_geometry,&page_info,exception); 1561 if (image->gravity != UndefinedGravity) 1562 { 1563 geometry.x=(-page_info.x); 1564 geometry.y=(ssize_t) (media_info.height+page_info.y-image->rows); 1565 } 1566 pointsize=12.0; 1567 if (image_info->pointsize != 0.0) 1568 pointsize=image_info->pointsize; 1569 text_size=0; 1570 value=GetImageProperty(image,"label",exception); 1571 if (value != (const char *) NULL) 1572 text_size=(size_t) (MultilineCensus(value)*pointsize+12); 1573 (void) text_size; 1574 /* 1575 Write Page object. 1576 */ 1577 xref[object++]=TellBlob(image); 1578 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 1579 object); 1580 (void) WriteBlobString(image,buffer); 1581 (void) WriteBlobString(image,"<<\n"); 1582 (void) WriteBlobString(image,"/Type /Page\n"); 1583 (void) FormatLocaleString(buffer,MagickPathExtent,"/Parent %.20g 0 R\n", 1584 (double) pages_id); 1585 (void) WriteBlobString(image,buffer); 1586 (void) WriteBlobString(image,"/Resources <<\n"); 1587 labels=(char **) NULL; 1588 value=GetImageProperty(image,"label",exception); 1589 if (value != (const char *) NULL) 1590 labels=StringToList(value); 1591 if (labels != (char **) NULL) 1592 { 1593 (void) FormatLocaleString(buffer,MagickPathExtent, 1594 "/Font << /F%.20g %.20g 0 R >>\n",(double) image->scene,(double) 1595 object+4); 1596 (void) WriteBlobString(image,buffer); 1597 } 1598 (void) FormatLocaleString(buffer,MagickPathExtent, 1599 "/XObject << /Im%.20g %.20g 0 R >>\n",(double) image->scene,(double) 1600 object+5); 1601 (void) WriteBlobString(image,buffer); 1602 (void) FormatLocaleString(buffer,MagickPathExtent,"/ProcSet %.20g 0 R >>\n", 1603 (double) object+3); 1604 (void) WriteBlobString(image,buffer); 1605 (void) FormatLocaleString(buffer,MagickPathExtent, 1606 "/MediaBox [0 0 %g %g]\n",72.0*media_info.width/resolution.x, 1607 72.0*media_info.height/resolution.y); 1608 (void) WriteBlobString(image,buffer); 1609 (void) FormatLocaleString(buffer,MagickPathExtent, 1610 "/CropBox [0 0 %g %g]\n",72.0*media_info.width/resolution.x, 1611 72.0*media_info.height/resolution.y); 1612 (void) WriteBlobString(image,buffer); 1613 (void) FormatLocaleString(buffer,MagickPathExtent,"/Contents %.20g 0 R\n", 1614 (double) object+1); 1615 (void) WriteBlobString(image,buffer); 1616 (void) FormatLocaleString(buffer,MagickPathExtent,"/Thumb %.20g 0 R\n",(double) 1617 object+8); 1618 (void) WriteBlobString(image,buffer); 1619 (void) WriteBlobString(image,">>\n"); 1620 (void) WriteBlobString(image,"endobj\n"); 1621 /* 1622 Write Contents object. 1623 */ 1624 xref[object++]=TellBlob(image); 1625 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 1626 object); 1627 (void) WriteBlobString(image,buffer); 1628 (void) WriteBlobString(image,"<<\n"); 1629 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n", 1630 (double) object+1); 1631 (void) WriteBlobString(image,buffer); 1632 (void) WriteBlobString(image,">>\n"); 1633 (void) WriteBlobString(image,"stream\n"); 1634 offset=TellBlob(image); 1635 (void) WriteBlobString(image,"q\n"); 1636 if (labels != (char **) NULL) 1637 for (i=0; labels[i] != (char *) NULL; i++) 1638 { 1639 (void) WriteBlobString(image,"BT\n"); 1640 (void) FormatLocaleString(buffer,MagickPathExtent,"/F%.20g %g Tf\n", 1641 (double) image->scene,pointsize); 1642 (void) WriteBlobString(image,buffer); 1643 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g Td\n", 1644 (double) geometry.x,(double) (geometry.y+geometry.height+i*pointsize+ 1645 12)); 1646 (void) WriteBlobString(image,buffer); 1647 (void) FormatLocaleString(buffer,MagickPathExtent,"(%s) Tj\n", 1648 labels[i]); 1649 (void) WriteBlobString(image,buffer); 1650 (void) WriteBlobString(image,"ET\n"); 1651 labels[i]=DestroyString(labels[i]); 1652 } 1653 (void) FormatLocaleString(buffer,MagickPathExtent, 1654 "%g 0 0 %g %.20g %.20g cm\n",scale.x,scale.y,(double) geometry.x, 1655 (double) geometry.y); 1656 (void) WriteBlobString(image,buffer); 1657 (void) FormatLocaleString(buffer,MagickPathExtent,"/Im%.20g Do\n",(double) 1658 image->scene); 1659 (void) WriteBlobString(image,buffer); 1660 (void) WriteBlobString(image,"Q\n"); 1661 offset=TellBlob(image)-offset; 1662 (void) WriteBlobString(image,"\nendstream\n"); 1663 (void) WriteBlobString(image,"endobj\n"); 1664 /* 1665 Write Length object. 1666 */ 1667 xref[object++]=TellBlob(image); 1668 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 1669 object); 1670 (void) WriteBlobString(image,buffer); 1671 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n", 1672 (double) offset); 1673 (void) WriteBlobString(image,buffer); 1674 (void) WriteBlobString(image,"endobj\n"); 1675 /* 1676 Write Procset object. 1677 */ 1678 xref[object++]=TellBlob(image); 1679 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 1680 object); 1681 (void) WriteBlobString(image,buffer); 1682 if ((image->storage_class == DirectClass) || (image->colors > 256)) 1683 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageC",MagickPathExtent); 1684 else 1685 if ((compression == FaxCompression) || (compression == Group4Compression)) 1686 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageB",MagickPathExtent); 1687 else 1688 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageI",MagickPathExtent); 1689 (void) WriteBlobString(image,buffer); 1690 (void) WriteBlobString(image," ]\n"); 1691 (void) WriteBlobString(image,"endobj\n"); 1692 /* 1693 Write Font object. 1694 */ 1695 xref[object++]=TellBlob(image); 1696 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 1697 object); 1698 (void) WriteBlobString(image,buffer); 1699 (void) WriteBlobString(image,"<<\n"); 1700 if (labels != (char **) NULL) 1701 { 1702 (void) WriteBlobString(image,"/Type /Font\n"); 1703 (void) WriteBlobString(image,"/Subtype /Type1\n"); 1704 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /F%.20g\n", 1705 (double) image->scene); 1706 (void) WriteBlobString(image,buffer); 1707 (void) WriteBlobString(image,"/BaseFont /Helvetica\n"); 1708 (void) WriteBlobString(image,"/Encoding /MacRomanEncoding\n"); 1709 labels=(char **) RelinquishMagickMemory(labels); 1710 } 1711 (void) WriteBlobString(image,">>\n"); 1712 (void) WriteBlobString(image,"endobj\n"); 1713 /* 1714 Write XObject object. 1715 */ 1716 xref[object++]=TellBlob(image); 1717 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 1718 object); 1719 (void) WriteBlobString(image,buffer); 1720 (void) WriteBlobString(image,"<<\n"); 1721 (void) WriteBlobString(image,"/Type /XObject\n"); 1722 (void) WriteBlobString(image,"/Subtype /Image\n"); 1723 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /Im%.20g\n",(double) 1724 image->scene); 1725 (void) WriteBlobString(image,buffer); 1726 switch (compression) 1727 { 1728 case NoCompression: 1729 { 1730 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"ASCII85Decode"); 1731 break; 1732 } 1733 case JPEGCompression: 1734 { 1735 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"DCTDecode"); 1736 if (image->colorspace != CMYKColorspace) 1737 break; 1738 (void) WriteBlobString(image,buffer); 1739 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n", 1740 MagickPathExtent); 1741 break; 1742 } 1743 case JPEG2000Compression: 1744 { 1745 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"JPXDecode"); 1746 if (image->colorspace != CMYKColorspace) 1747 break; 1748 (void) WriteBlobString(image,buffer); 1749 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n", 1750 MagickPathExtent); 1751 break; 1752 } 1753 case LZWCompression: 1754 { 1755 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"LZWDecode"); 1756 break; 1757 } 1758 case ZipCompression: 1759 { 1760 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat, 1761 "FlateDecode"); 1762 break; 1763 } 1764 case FaxCompression: 1765 case Group4Compression: 1766 { 1767 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n", 1768 MagickPathExtent); 1769 (void) WriteBlobString(image,buffer); 1770 (void) FormatLocaleString(buffer,MagickPathExtent,"/DecodeParms [ << " 1771 "/K %s /BlackIs1 false /Columns %.20g /Rows %.20g >> ]\n",CCITTParam, 1772 (double) image->columns,(double) image->rows); 1773 break; 1774 } 1775 default: 1776 { 1777 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat, 1778 "RunLengthDecode"); 1779 break; 1780 } 1781 } 1782 (void) WriteBlobString(image,buffer); 1783 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n",(double) 1784 image->columns); 1785 (void) WriteBlobString(image,buffer); 1786 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n",(double) 1787 image->rows); 1788 (void) WriteBlobString(image,buffer); 1789 (void) FormatLocaleString(buffer,MagickPathExtent,"/ColorSpace %.20g 0 R\n", 1790 (double) object+2); 1791 (void) WriteBlobString(image,buffer); 1792 (void) FormatLocaleString(buffer,MagickPathExtent,"/BitsPerComponent %d\n", 1793 (compression == FaxCompression) || (compression == Group4Compression) ? 1794 1 : 8); 1795 (void) WriteBlobString(image,buffer); 1796 if (image->alpha_trait != UndefinedPixelTrait) 1797 { 1798 (void) FormatLocaleString(buffer,MagickPathExtent,"/SMask %.20g 0 R\n", 1799 (double) object+7); 1800 (void) WriteBlobString(image,buffer); 1801 } 1802 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n", 1803 (double) object+1); 1804 (void) WriteBlobString(image,buffer); 1805 (void) WriteBlobString(image,">>\n"); 1806 (void) WriteBlobString(image,"stream\n"); 1807 offset=TellBlob(image); 1808 number_pixels=(MagickSizeType) image->columns*image->rows; 1809 if ((4*number_pixels) != (MagickSizeType) ((size_t) (4*number_pixels))) 1810 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1811 if ((compression == FaxCompression) || (compression == Group4Compression) || 1812 ((image_info->type != TrueColorType) && 1813 (SetImageGray(image,exception) != MagickFalse))) 1814 { 1815 switch (compression) 1816 { 1817 case FaxCompression: 1818 case Group4Compression: 1819 { 1820 if (LocaleCompare(CCITTParam,"0") == 0) 1821 { 1822 (void) HuffmanEncodeImage(image_info,image,image,exception); 1823 break; 1824 } 1825 (void) Huffman2DEncodeImage(image_info,image,image,exception); 1826 break; 1827 } 1828 case JPEGCompression: 1829 { 1830 status=InjectImageBlob(image_info,image,image,"jpeg",exception); 1831 if (status == MagickFalse) 1832 { 1833 (void) CloseBlob(image); 1834 return(MagickFalse); 1835 } 1836 break; 1837 } 1838 case JPEG2000Compression: 1839 { 1840 status=InjectImageBlob(image_info,image,image,"jp2",exception); 1841 if (status == MagickFalse) 1842 { 1843 (void) CloseBlob(image); 1844 return(MagickFalse); 1845 } 1846 break; 1847 } 1848 case RLECompression: 1849 default: 1850 { 1851 MemoryInfo 1852 *pixel_info; 1853 1854 /* 1855 Allocate pixel array. 1856 */ 1857 length=(size_t) number_pixels; 1858 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels)); 1859 if (pixel_info == (MemoryInfo *) NULL) 1860 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1861 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 1862 /* 1863 Dump Runlength encoded pixels. 1864 */ 1865 q=pixels; 1866 for (y=0; y < (ssize_t) image->rows; y++) 1867 { 1868 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1869 if (p == (const Quantum *) NULL) 1870 break; 1871 for (x=0; x < (ssize_t) image->columns; x++) 1872 { 1873 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma(image,p))); 1874 p+=GetPixelChannels(image); 1875 } 1876 if (image->previous == (Image *) NULL) 1877 { 1878 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 1879 y,image->rows); 1880 if (status == MagickFalse) 1881 break; 1882 } 1883 } 1884 #if defined(MAGICKCORE_ZLIB_DELEGATE) 1885 if (compression == ZipCompression) 1886 status=ZLIBEncodeImage(image,length,pixels,exception); 1887 else 1888 #endif 1889 if (compression == LZWCompression) 1890 status=LZWEncodeImage(image,length,pixels,exception); 1891 else 1892 status=PackbitsEncodeImage(image,length,pixels,exception); 1893 pixel_info=RelinquishVirtualMemory(pixel_info); 1894 if (status == MagickFalse) 1895 { 1896 (void) CloseBlob(image); 1897 return(MagickFalse); 1898 } 1899 break; 1900 } 1901 case NoCompression: 1902 { 1903 /* 1904 Dump uncompressed PseudoColor packets. 1905 */ 1906 Ascii85Initialize(image); 1907 for (y=0; y < (ssize_t) image->rows; y++) 1908 { 1909 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1910 if (p == (const Quantum *) NULL) 1911 break; 1912 for (x=0; x < (ssize_t) image->columns; x++) 1913 { 1914 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum( 1915 GetPixelLuma(image,p)))); 1916 p+=GetPixelChannels(image); 1917 } 1918 if (image->previous == (Image *) NULL) 1919 { 1920 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 1921 y,image->rows); 1922 if (status == MagickFalse) 1923 break; 1924 } 1925 } 1926 Ascii85Flush(image); 1927 break; 1928 } 1929 } 1930 } 1931 else 1932 if ((image->storage_class == DirectClass) || (image->colors > 256) || 1933 (compression == JPEGCompression) || 1934 (compression == JPEG2000Compression)) 1935 switch (compression) 1936 { 1937 case JPEGCompression: 1938 { 1939 status=InjectImageBlob(image_info,image,image,"jpeg",exception); 1940 if (status == MagickFalse) 1941 { 1942 (void) CloseBlob(image); 1943 return(MagickFalse); 1944 } 1945 break; 1946 } 1947 case JPEG2000Compression: 1948 { 1949 status=InjectImageBlob(image_info,image,image,"jp2",exception); 1950 if (status == MagickFalse) 1951 { 1952 (void) CloseBlob(image); 1953 return(MagickFalse); 1954 } 1955 break; 1956 } 1957 case RLECompression: 1958 default: 1959 { 1960 MemoryInfo 1961 *pixel_info; 1962 1963 /* 1964 Allocate pixel array. 1965 */ 1966 length=(size_t) number_pixels; 1967 length*=image->colorspace == CMYKColorspace ? 4UL : 3UL; 1968 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels)); 1969 if (pixel_info == (MemoryInfo *) NULL) 1970 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1971 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 1972 /* 1973 Dump runoffset encoded pixels. 1974 */ 1975 q=pixels; 1976 for (y=0; y < (ssize_t) image->rows; y++) 1977 { 1978 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1979 if (p == (const Quantum *) NULL) 1980 break; 1981 for (x=0; x < (ssize_t) image->columns; x++) 1982 { 1983 *q++=ScaleQuantumToChar(GetPixelRed(image,p)); 1984 *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); 1985 *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); 1986 if (image->colorspace == CMYKColorspace) 1987 *q++=ScaleQuantumToChar(GetPixelBlack(image,p)); 1988 p+=GetPixelChannels(image); 1989 } 1990 if (image->previous == (Image *) NULL) 1991 { 1992 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 1993 y,image->rows); 1994 if (status == MagickFalse) 1995 break; 1996 } 1997 } 1998 #if defined(MAGICKCORE_ZLIB_DELEGATE) 1999 if (compression == ZipCompression) 2000 status=ZLIBEncodeImage(image,length,pixels,exception); 2001 else 2002 #endif 2003 if (compression == LZWCompression) 2004 status=LZWEncodeImage(image,length,pixels,exception); 2005 else 2006 status=PackbitsEncodeImage(image,length,pixels,exception); 2007 pixel_info=RelinquishVirtualMemory(pixel_info); 2008 if (status == MagickFalse) 2009 { 2010 (void) CloseBlob(image); 2011 return(MagickFalse); 2012 } 2013 break; 2014 } 2015 case NoCompression: 2016 { 2017 /* 2018 Dump uncompressed DirectColor packets. 2019 */ 2020 Ascii85Initialize(image); 2021 for (y=0; y < (ssize_t) image->rows; y++) 2022 { 2023 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 2024 if (p == (const Quantum *) NULL) 2025 break; 2026 for (x=0; x < (ssize_t) image->columns; x++) 2027 { 2028 Ascii85Encode(image,ScaleQuantumToChar(GetPixelRed(image,p))); 2029 Ascii85Encode(image,ScaleQuantumToChar(GetPixelGreen(image,p))); 2030 Ascii85Encode(image,ScaleQuantumToChar(GetPixelBlue(image,p))); 2031 if (image->colorspace == CMYKColorspace) 2032 Ascii85Encode(image,ScaleQuantumToChar( 2033 GetPixelBlack(image,p))); 2034 p+=GetPixelChannels(image); 2035 } 2036 if (image->previous == (Image *) NULL) 2037 { 2038 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 2039 y,image->rows); 2040 if (status == MagickFalse) 2041 break; 2042 } 2043 } 2044 Ascii85Flush(image); 2045 break; 2046 } 2047 } 2048 else 2049 { 2050 /* 2051 Dump number of colors and colormap. 2052 */ 2053 switch (compression) 2054 { 2055 case RLECompression: 2056 default: 2057 { 2058 MemoryInfo 2059 *pixel_info; 2060 2061 /* 2062 Allocate pixel array. 2063 */ 2064 length=(size_t) number_pixels; 2065 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels)); 2066 if (pixel_info == (MemoryInfo *) NULL) 2067 ThrowWriterException(ResourceLimitError, 2068 "MemoryAllocationFailed"); 2069 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 2070 /* 2071 Dump Runlength encoded pixels. 2072 */ 2073 q=pixels; 2074 for (y=0; y < (ssize_t) image->rows; y++) 2075 { 2076 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 2077 if (p == (const Quantum *) NULL) 2078 break; 2079 for (x=0; x < (ssize_t) image->columns; x++) 2080 { 2081 *q++=(unsigned char) GetPixelIndex(image,p); 2082 p+=GetPixelChannels(image); 2083 } 2084 if (image->previous == (Image *) NULL) 2085 { 2086 status=SetImageProgress(image,SaveImageTag, 2087 (MagickOffsetType) y,image->rows); 2088 if (status == MagickFalse) 2089 break; 2090 } 2091 } 2092 #if defined(MAGICKCORE_ZLIB_DELEGATE) 2093 if (compression == ZipCompression) 2094 status=ZLIBEncodeImage(image,length,pixels,exception); 2095 else 2096 #endif 2097 if (compression == LZWCompression) 2098 status=LZWEncodeImage(image,length,pixels,exception); 2099 else 2100 status=PackbitsEncodeImage(image,length,pixels,exception); 2101 pixel_info=RelinquishVirtualMemory(pixel_info); 2102 if (status == MagickFalse) 2103 { 2104 (void) CloseBlob(image); 2105 return(MagickFalse); 2106 } 2107 break; 2108 } 2109 case NoCompression: 2110 { 2111 /* 2112 Dump uncompressed PseudoColor packets. 2113 */ 2114 Ascii85Initialize(image); 2115 for (y=0; y < (ssize_t) image->rows; y++) 2116 { 2117 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 2118 if (p == (const Quantum *) NULL) 2119 break; 2120 for (x=0; x < (ssize_t) image->columns; x++) 2121 { 2122 Ascii85Encode(image,(unsigned char) GetPixelIndex(image,p)); 2123 p+=GetPixelChannels(image); 2124 } 2125 if (image->previous == (Image *) NULL) 2126 { 2127 status=SetImageProgress(image,SaveImageTag, 2128 (MagickOffsetType) y,image->rows); 2129 if (status == MagickFalse) 2130 break; 2131 } 2132 } 2133 Ascii85Flush(image); 2134 break; 2135 } 2136 } 2137 } 2138 offset=TellBlob(image)-offset; 2139 (void) WriteBlobString(image,"\nendstream\n"); 2140 (void) WriteBlobString(image,"endobj\n"); 2141 /* 2142 Write Length object. 2143 */ 2144 xref[object++]=TellBlob(image); 2145 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 2146 object); 2147 (void) WriteBlobString(image,buffer); 2148 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double) 2149 offset); 2150 (void) WriteBlobString(image,buffer); 2151 (void) WriteBlobString(image,"endobj\n"); 2152 /* 2153 Write Colorspace object. 2154 */ 2155 xref[object++]=TellBlob(image); 2156 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 2157 object); 2158 (void) WriteBlobString(image,buffer); 2159 if (image->colorspace == CMYKColorspace) 2160 (void) CopyMagickString(buffer,"/DeviceCMYK\n",MagickPathExtent); 2161 else 2162 if ((compression == FaxCompression) || 2163 (compression == Group4Compression) || 2164 ((image_info->type != TrueColorType) && 2165 (SetImageGray(image,exception) != MagickFalse))) 2166 (void) CopyMagickString(buffer,"/DeviceGray\n",MagickPathExtent); 2167 else 2168 if ((image->storage_class == DirectClass) || (image->colors > 256) || 2169 (compression == JPEGCompression) || 2170 (compression == JPEG2000Compression)) 2171 (void) CopyMagickString(buffer,"/DeviceRGB\n",MagickPathExtent); 2172 else 2173 (void) FormatLocaleString(buffer,MagickPathExtent, 2174 "[ /Indexed /DeviceRGB %.20g %.20g 0 R ]\n",(double) image->colors- 2175 1,(double) object+3); 2176 (void) WriteBlobString(image,buffer); 2177 (void) WriteBlobString(image,"endobj\n"); 2178 /* 2179 Write Thumb object. 2180 */ 2181 SetGeometry(image,&geometry); 2182 (void) ParseMetaGeometry("106x106+0+0>",&geometry.x,&geometry.y, 2183 &geometry.width,&geometry.height); 2184 tile_image=ThumbnailImage(image,geometry.width,geometry.height,exception); 2185 if (tile_image == (Image *) NULL) 2186 return(MagickFalse); 2187 xref[object++]=TellBlob(image); 2188 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 2189 object); 2190 (void) WriteBlobString(image,buffer); 2191 (void) WriteBlobString(image,"<<\n"); 2192 switch (compression) 2193 { 2194 case NoCompression: 2195 { 2196 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat, 2197 "ASCII85Decode"); 2198 break; 2199 } 2200 case JPEGCompression: 2201 { 2202 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"DCTDecode"); 2203 if (image->colorspace != CMYKColorspace) 2204 break; 2205 (void) WriteBlobString(image,buffer); 2206 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n", 2207 MagickPathExtent); 2208 break; 2209 } 2210 case JPEG2000Compression: 2211 { 2212 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"JPXDecode"); 2213 if (image->colorspace != CMYKColorspace) 2214 break; 2215 (void) WriteBlobString(image,buffer); 2216 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n", 2217 MagickPathExtent); 2218 break; 2219 } 2220 case LZWCompression: 2221 { 2222 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"LZWDecode"); 2223 break; 2224 } 2225 case ZipCompression: 2226 { 2227 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat, 2228 "FlateDecode"); 2229 break; 2230 } 2231 case FaxCompression: 2232 case Group4Compression: 2233 { 2234 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n", 2235 MagickPathExtent); 2236 (void) WriteBlobString(image,buffer); 2237 (void) FormatLocaleString(buffer,MagickPathExtent,"/DecodeParms [ << " 2238 "/K %s /BlackIs1 false /Columns %.20g /Rows %.20g >> ]\n",CCITTParam, 2239 (double) tile_image->columns,(double) tile_image->rows); 2240 break; 2241 } 2242 default: 2243 { 2244 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat, 2245 "RunLengthDecode"); 2246 break; 2247 } 2248 } 2249 (void) WriteBlobString(image,buffer); 2250 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n",(double) 2251 tile_image->columns); 2252 (void) WriteBlobString(image,buffer); 2253 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n",(double) 2254 tile_image->rows); 2255 (void) WriteBlobString(image,buffer); 2256 (void) FormatLocaleString(buffer,MagickPathExtent,"/ColorSpace %.20g 0 R\n", 2257 (double) object-1); 2258 (void) WriteBlobString(image,buffer); 2259 (void) FormatLocaleString(buffer,MagickPathExtent,"/BitsPerComponent %d\n", 2260 (compression == FaxCompression) || (compression == Group4Compression) ? 2261 1 : 8); 2262 (void) WriteBlobString(image,buffer); 2263 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n", 2264 (double) object+1); 2265 (void) WriteBlobString(image,buffer); 2266 (void) WriteBlobString(image,">>\n"); 2267 (void) WriteBlobString(image,"stream\n"); 2268 offset=TellBlob(image); 2269 number_pixels=(MagickSizeType) tile_image->columns*tile_image->rows; 2270 if ((compression == FaxCompression) || 2271 (compression == Group4Compression) || 2272 ((image_info->type != TrueColorType) && 2273 (SetImageGray(tile_image,exception) != MagickFalse))) 2274 { 2275 switch (compression) 2276 { 2277 case FaxCompression: 2278 case Group4Compression: 2279 { 2280 if (LocaleCompare(CCITTParam,"0") == 0) 2281 { 2282 (void) HuffmanEncodeImage(image_info,image,tile_image, 2283 exception); 2284 break; 2285 } 2286 (void) Huffman2DEncodeImage(image_info,image,tile_image,exception); 2287 break; 2288 } 2289 case JPEGCompression: 2290 { 2291 status=InjectImageBlob(image_info,image,tile_image,"jpeg", 2292 exception); 2293 if (status == MagickFalse) 2294 { 2295 (void) CloseBlob(image); 2296 return(MagickFalse); 2297 } 2298 break; 2299 } 2300 case JPEG2000Compression: 2301 { 2302 status=InjectImageBlob(image_info,image,tile_image,"jp2",exception); 2303 if (status == MagickFalse) 2304 { 2305 (void) CloseBlob(image); 2306 return(MagickFalse); 2307 } 2308 break; 2309 } 2310 case RLECompression: 2311 default: 2312 { 2313 MemoryInfo 2314 *pixel_info; 2315 2316 /* 2317 Allocate pixel array. 2318 */ 2319 length=(size_t) number_pixels; 2320 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels)); 2321 if (pixel_info == (MemoryInfo *) NULL) 2322 { 2323 tile_image=DestroyImage(tile_image); 2324 ThrowWriterException(ResourceLimitError, 2325 "MemoryAllocationFailed"); 2326 } 2327 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 2328 /* 2329 Dump runlength encoded pixels. 2330 */ 2331 q=pixels; 2332 for (y=0; y < (ssize_t) tile_image->rows; y++) 2333 { 2334 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1, 2335 exception); 2336 if (p == (const Quantum *) NULL) 2337 break; 2338 for (x=0; x < (ssize_t) tile_image->columns; x++) 2339 { 2340 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma( 2341 tile_image,p))); 2342 p+=GetPixelChannels(tile_image); 2343 } 2344 } 2345 #if defined(MAGICKCORE_ZLIB_DELEGATE) 2346 if (compression == ZipCompression) 2347 status=ZLIBEncodeImage(image,length,pixels,exception); 2348 else 2349 #endif 2350 if (compression == LZWCompression) 2351 status=LZWEncodeImage(image,length,pixels,exception); 2352 else 2353 status=PackbitsEncodeImage(image,length,pixels,exception); 2354 pixel_info=RelinquishVirtualMemory(pixel_info); 2355 if (status == MagickFalse) 2356 { 2357 (void) CloseBlob(image); 2358 return(MagickFalse); 2359 } 2360 break; 2361 } 2362 case NoCompression: 2363 { 2364 /* 2365 Dump uncompressed PseudoColor packets. 2366 */ 2367 Ascii85Initialize(image); 2368 for (y=0; y < (ssize_t) tile_image->rows; y++) 2369 { 2370 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1, 2371 exception); 2372 if (p == (const Quantum *) NULL) 2373 break; 2374 for (x=0; x < (ssize_t) tile_image->columns; x++) 2375 { 2376 Ascii85Encode(tile_image,ScaleQuantumToChar(ClampToQuantum( 2377 GetPixelLuma(tile_image,p)))); 2378 p+=GetPixelChannels(tile_image); 2379 } 2380 } 2381 Ascii85Flush(image); 2382 break; 2383 } 2384 } 2385 } 2386 else 2387 if ((tile_image->storage_class == DirectClass) || 2388 (tile_image->colors > 256) || (compression == JPEGCompression) || 2389 (compression == JPEG2000Compression)) 2390 switch (compression) 2391 { 2392 case JPEGCompression: 2393 { 2394 status=InjectImageBlob(image_info,image,tile_image,"jpeg", 2395 exception); 2396 if (status == MagickFalse) 2397 { 2398 (void) CloseBlob(image); 2399 return(MagickFalse); 2400 } 2401 break; 2402 } 2403 case JPEG2000Compression: 2404 { 2405 status=InjectImageBlob(image_info,image,tile_image,"jp2",exception); 2406 if (status == MagickFalse) 2407 { 2408 (void) CloseBlob(image); 2409 return(MagickFalse); 2410 } 2411 break; 2412 } 2413 case RLECompression: 2414 default: 2415 { 2416 MemoryInfo 2417 *pixel_info; 2418 2419 /* 2420 Allocate pixel array. 2421 */ 2422 length=(size_t) number_pixels; 2423 length*=tile_image->colorspace == CMYKColorspace ? 4UL : 3UL; 2424 pixel_info=AcquireVirtualMemory(length,4*sizeof(*pixels)); 2425 if (pixel_info == (MemoryInfo *) NULL) 2426 { 2427 tile_image=DestroyImage(tile_image); 2428 ThrowWriterException(ResourceLimitError, 2429 "MemoryAllocationFailed"); 2430 } 2431 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 2432 /* 2433 Dump runlength encoded pixels. 2434 */ 2435 q=pixels; 2436 for (y=0; y < (ssize_t) tile_image->rows; y++) 2437 { 2438 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1, 2439 exception); 2440 if (p == (const Quantum *) NULL) 2441 break; 2442 for (x=0; x < (ssize_t) tile_image->columns; x++) 2443 { 2444 *q++=ScaleQuantumToChar(GetPixelRed(tile_image,p)); 2445 *q++=ScaleQuantumToChar(GetPixelGreen(tile_image,p)); 2446 *q++=ScaleQuantumToChar(GetPixelBlue(tile_image,p)); 2447 if (tile_image->colorspace == CMYKColorspace) 2448 *q++=ScaleQuantumToChar(GetPixelBlack(tile_image,p)); 2449 p+=GetPixelChannels(tile_image); 2450 } 2451 } 2452 #if defined(MAGICKCORE_ZLIB_DELEGATE) 2453 if (compression == ZipCompression) 2454 status=ZLIBEncodeImage(image,length,pixels,exception); 2455 else 2456 #endif 2457 if (compression == LZWCompression) 2458 status=LZWEncodeImage(image,length,pixels,exception); 2459 else 2460 status=PackbitsEncodeImage(image,length,pixels,exception); 2461 pixel_info=RelinquishVirtualMemory(pixel_info); 2462 if (status == MagickFalse) 2463 { 2464 (void) CloseBlob(image); 2465 return(MagickFalse); 2466 } 2467 break; 2468 } 2469 case NoCompression: 2470 { 2471 /* 2472 Dump uncompressed DirectColor packets. 2473 */ 2474 Ascii85Initialize(image); 2475 for (y=0; y < (ssize_t) tile_image->rows; y++) 2476 { 2477 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1, 2478 exception); 2479 if (p == (const Quantum *) NULL) 2480 break; 2481 for (x=0; x < (ssize_t) tile_image->columns; x++) 2482 { 2483 Ascii85Encode(image,ScaleQuantumToChar( 2484 GetPixelRed(tile_image,p))); 2485 Ascii85Encode(image,ScaleQuantumToChar( 2486 GetPixelGreen(tile_image,p))); 2487 Ascii85Encode(image,ScaleQuantumToChar( 2488 GetPixelBlue(tile_image,p))); 2489 if (image->colorspace == CMYKColorspace) 2490 Ascii85Encode(image,ScaleQuantumToChar( 2491 GetPixelBlack(tile_image,p))); 2492 p+=GetPixelChannels(tile_image); 2493 } 2494 } 2495 Ascii85Flush(image); 2496 break; 2497 } 2498 } 2499 else 2500 { 2501 /* 2502 Dump number of colors and colormap. 2503 */ 2504 switch (compression) 2505 { 2506 case RLECompression: 2507 default: 2508 { 2509 MemoryInfo 2510 *pixel_info; 2511 2512 /* 2513 Allocate pixel array. 2514 */ 2515 length=(size_t) number_pixels; 2516 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels)); 2517 if (pixel_info == (MemoryInfo *) NULL) 2518 { 2519 tile_image=DestroyImage(tile_image); 2520 ThrowWriterException(ResourceLimitError, 2521 "MemoryAllocationFailed"); 2522 } 2523 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 2524 /* 2525 Dump runlength encoded pixels. 2526 */ 2527 q=pixels; 2528 for (y=0; y < (ssize_t) tile_image->rows; y++) 2529 { 2530 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1, 2531 exception); 2532 if (p == (const Quantum *) NULL) 2533 break; 2534 for (x=0; x < (ssize_t) tile_image->columns; x++) 2535 { 2536 *q++=(unsigned char) GetPixelIndex(tile_image,p); 2537 p+=GetPixelChannels(tile_image); 2538 } 2539 } 2540 #if defined(MAGICKCORE_ZLIB_DELEGATE) 2541 if (compression == ZipCompression) 2542 status=ZLIBEncodeImage(image,length,pixels,exception); 2543 else 2544 #endif 2545 if (compression == LZWCompression) 2546 status=LZWEncodeImage(image,length,pixels,exception); 2547 else 2548 status=PackbitsEncodeImage(image,length,pixels,exception); 2549 pixel_info=RelinquishVirtualMemory(pixel_info); 2550 if (status == MagickFalse) 2551 { 2552 (void) CloseBlob(image); 2553 return(MagickFalse); 2554 } 2555 break; 2556 } 2557 case NoCompression: 2558 { 2559 /* 2560 Dump uncompressed PseudoColor packets. 2561 */ 2562 Ascii85Initialize(image); 2563 for (y=0; y < (ssize_t) tile_image->rows; y++) 2564 { 2565 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1, 2566 exception); 2567 if (p == (const Quantum *) NULL) 2568 break; 2569 for (x=0; x < (ssize_t) tile_image->columns; x++) 2570 { 2571 Ascii85Encode(image,(unsigned char) 2572 GetPixelIndex(tile_image,p)); 2573 p+=GetPixelChannels(image); 2574 } 2575 } 2576 Ascii85Flush(image); 2577 break; 2578 } 2579 } 2580 } 2581 tile_image=DestroyImage(tile_image); 2582 offset=TellBlob(image)-offset; 2583 (void) WriteBlobString(image,"\nendstream\n"); 2584 (void) WriteBlobString(image,"endobj\n"); 2585 /* 2586 Write Length object. 2587 */ 2588 xref[object++]=TellBlob(image); 2589 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 2590 object); 2591 (void) WriteBlobString(image,buffer); 2592 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double) 2593 offset); 2594 (void) WriteBlobString(image,buffer); 2595 (void) WriteBlobString(image,"endobj\n"); 2596 xref[object++]=TellBlob(image); 2597 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 2598 object); 2599 (void) WriteBlobString(image,buffer); 2600 (void) WriteBlobString(image,"<<\n"); 2601 if ((image->storage_class == DirectClass) || (image->colors > 256) || 2602 (compression == FaxCompression) || (compression == Group4Compression)) 2603 (void) WriteBlobString(image,">>\n"); 2604 else 2605 { 2606 /* 2607 Write Colormap object. 2608 */ 2609 if (compression == NoCompression) 2610 (void) WriteBlobString(image,"/Filter [ /ASCII85Decode ]\n"); 2611 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n", 2612 (double) object+1); 2613 (void) WriteBlobString(image,buffer); 2614 (void) WriteBlobString(image,">>\n"); 2615 (void) WriteBlobString(image,"stream\n"); 2616 offset=TellBlob(image); 2617 if (compression == NoCompression) 2618 Ascii85Initialize(image); 2619 for (i=0; i < (ssize_t) image->colors; i++) 2620 { 2621 if (compression == NoCompression) 2622 { 2623 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum( 2624 image->colormap[i].red))); 2625 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum( 2626 image->colormap[i].green))); 2627 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum( 2628 image->colormap[i].blue))); 2629 continue; 2630 } 2631 (void) WriteBlobByte(image,ScaleQuantumToChar( 2632 ClampToQuantum(image->colormap[i].red))); 2633 (void) WriteBlobByte(image,ScaleQuantumToChar( 2634 ClampToQuantum(image->colormap[i].green))); 2635 (void) WriteBlobByte(image,ScaleQuantumToChar( 2636 ClampToQuantum(image->colormap[i].blue))); 2637 } 2638 if (compression == NoCompression) 2639 Ascii85Flush(image); 2640 offset=TellBlob(image)-offset; 2641 (void) WriteBlobString(image,"\nendstream\n"); 2642 } 2643 (void) WriteBlobString(image,"endobj\n"); 2644 /* 2645 Write Length object. 2646 */ 2647 xref[object++]=TellBlob(image); 2648 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 2649 object); 2650 (void) WriteBlobString(image,buffer); 2651 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double) 2652 offset); 2653 (void) WriteBlobString(image,buffer); 2654 (void) WriteBlobString(image,"endobj\n"); 2655 /* 2656 Write softmask object. 2657 */ 2658 xref[object++]=TellBlob(image); 2659 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 2660 object); 2661 (void) WriteBlobString(image,buffer); 2662 (void) WriteBlobString(image,"<<\n"); 2663 if (image->alpha_trait == UndefinedPixelTrait) 2664 (void) WriteBlobString(image,">>\n"); 2665 else 2666 { 2667 (void) WriteBlobString(image,"/Type /XObject\n"); 2668 (void) WriteBlobString(image,"/Subtype /Image\n"); 2669 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /Ma%.20g\n", 2670 (double) image->scene); 2671 (void) WriteBlobString(image,buffer); 2672 switch (compression) 2673 { 2674 case NoCompression: 2675 { 2676 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat, 2677 "ASCII85Decode"); 2678 break; 2679 } 2680 case LZWCompression: 2681 { 2682 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat, 2683 "LZWDecode"); 2684 break; 2685 } 2686 case ZipCompression: 2687 { 2688 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat, 2689 "FlateDecode"); 2690 break; 2691 } 2692 default: 2693 { 2694 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat, 2695 "RunLengthDecode"); 2696 break; 2697 } 2698 } 2699 (void) WriteBlobString(image,buffer); 2700 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n", 2701 (double) image->columns); 2702 (void) WriteBlobString(image,buffer); 2703 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n", 2704 (double) image->rows); 2705 (void) WriteBlobString(image,buffer); 2706 (void) WriteBlobString(image,"/ColorSpace /DeviceGray\n"); 2707 (void) FormatLocaleString(buffer,MagickPathExtent, 2708 "/BitsPerComponent %d\n",(compression == FaxCompression) || 2709 (compression == Group4Compression) ? 1 : 8); 2710 (void) WriteBlobString(image,buffer); 2711 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n", 2712 (double) object+1); 2713 (void) WriteBlobString(image,buffer); 2714 (void) WriteBlobString(image,">>\n"); 2715 (void) WriteBlobString(image,"stream\n"); 2716 offset=TellBlob(image); 2717 number_pixels=(MagickSizeType) image->columns*image->rows; 2718 switch (compression) 2719 { 2720 case RLECompression: 2721 default: 2722 { 2723 MemoryInfo 2724 *pixel_info; 2725 2726 /* 2727 Allocate pixel array. 2728 */ 2729 length=(size_t) number_pixels; 2730 pixel_info=AcquireVirtualMemory(length,4*sizeof(*pixels)); 2731 if (pixel_info == (MemoryInfo *) NULL) 2732 { 2733 image=DestroyImage(image); 2734 ThrowWriterException(ResourceLimitError, 2735 "MemoryAllocationFailed"); 2736 } 2737 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 2738 /* 2739 Dump Runlength encoded pixels. 2740 */ 2741 q=pixels; 2742 for (y=0; y < (ssize_t) image->rows; y++) 2743 { 2744 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 2745 if (p == (const Quantum *) NULL) 2746 break; 2747 for (x=0; x < (ssize_t) image->columns; x++) 2748 { 2749 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p)); 2750 p+=GetPixelChannels(image); 2751 } 2752 } 2753 #if defined(MAGICKCORE_ZLIB_DELEGATE) 2754 if (compression == ZipCompression) 2755 status=ZLIBEncodeImage(image,length,pixels,exception); 2756 else 2757 #endif 2758 if (compression == LZWCompression) 2759 status=LZWEncodeImage(image,length,pixels,exception); 2760 else 2761 status=PackbitsEncodeImage(image,length,pixels,exception); 2762 pixel_info=RelinquishVirtualMemory(pixel_info); 2763 if (status == MagickFalse) 2764 { 2765 (void) CloseBlob(image); 2766 return(MagickFalse); 2767 } 2768 break; 2769 } 2770 case NoCompression: 2771 { 2772 /* 2773 Dump uncompressed PseudoColor packets. 2774 */ 2775 Ascii85Initialize(image); 2776 for (y=0; y < (ssize_t) image->rows; y++) 2777 { 2778 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 2779 if (p == (const Quantum *) NULL) 2780 break; 2781 for (x=0; x < (ssize_t) image->columns; x++) 2782 { 2783 Ascii85Encode(image,ScaleQuantumToChar(GetPixelAlpha(image,p))); 2784 p+=GetPixelChannels(image); 2785 } 2786 } 2787 Ascii85Flush(image); 2788 break; 2789 } 2790 } 2791 offset=TellBlob(image)-offset; 2792 (void) WriteBlobString(image,"\nendstream\n"); 2793 } 2794 (void) WriteBlobString(image,"endobj\n"); 2795 /* 2796 Write Length object. 2797 */ 2798 xref[object++]=TellBlob(image); 2799 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 2800 object); 2801 (void) WriteBlobString(image,buffer); 2802 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double) 2803 offset); 2804 (void) WriteBlobString(image,buffer); 2805 (void) WriteBlobString(image,"endobj\n"); 2806 if (GetNextImageInList(image) == (Image *) NULL) 2807 break; 2808 image=SyncNextImageInList(image); 2809 status=SetImageProgress(image,SaveImagesTag,scene++, 2810 GetImageListLength(image)); 2811 if (status == MagickFalse) 2812 break; 2813 } while (image_info->adjoin != MagickFalse); 2814 /* 2815 Write Metadata object. 2816 */ 2817 xref[object++]=TellBlob(image); 2818 info_id=object; 2819 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double) 2820 object); 2821 (void) WriteBlobString(image,buffer); 2822 (void) WriteBlobString(image,"<<\n"); 2823 utf16=ConvertUTF8ToUTF16((unsigned char *) basename,&length); 2824 if (utf16 != (wchar_t *) NULL) 2825 { 2826 (void) FormatLocaleString(buffer,MagickPathExtent,"/Title (\xfe\xff"); 2827 (void) WriteBlobString(image,buffer); 2828 for (i=0; i < (ssize_t) length; i++) 2829 WriteBlobMSBShort(image,(unsigned short) utf16[i]); 2830 (void) FormatLocaleString(buffer,MagickPathExtent,")\n"); 2831 (void) WriteBlobString(image,buffer); 2832 utf16=(wchar_t *) RelinquishMagickMemory(utf16); 2833 } 2834 seconds=time((time_t *) NULL); 2835 #if defined(MAGICKCORE_HAVE_LOCALTIME_R) 2836 (void) localtime_r(&seconds,&local_time); 2837 #else 2838 (void) memcpy(&local_time,localtime(&seconds),sizeof(local_time)); 2839 #endif 2840 (void) FormatLocaleString(date,MagickPathExtent,"D:%04d%02d%02d%02d%02d%02d", 2841 local_time.tm_year+1900,local_time.tm_mon+1,local_time.tm_mday, 2842 local_time.tm_hour,local_time.tm_min,local_time.tm_sec); 2843 (void) FormatLocaleString(buffer,MagickPathExtent,"/CreationDate (%s)\n", 2844 date); 2845 (void) WriteBlobString(image,buffer); 2846 (void) FormatLocaleString(buffer,MagickPathExtent,"/ModDate (%s)\n",date); 2847 (void) WriteBlobString(image,buffer); 2848 (void) FormatLocaleString(buffer,MagickPathExtent,"/Producer (%s)\n", 2849 EscapeParenthesis(GetMagickVersion((size_t *) NULL))); 2850 (void) WriteBlobString(image,buffer); 2851 (void) WriteBlobString(image,">>\n"); 2852 (void) WriteBlobString(image,"endobj\n"); 2853 /* 2854 Write Xref object. 2855 */ 2856 offset=TellBlob(image)-xref[0]+ 2857 (LocaleCompare(image_info->magick,"PDFA") == 0 ? 6 : 0)+10; 2858 (void) WriteBlobString(image,"xref\n"); 2859 (void) FormatLocaleString(buffer,MagickPathExtent,"0 %.20g\n",(double) 2860 object+1); 2861 (void) WriteBlobString(image,buffer); 2862 (void) WriteBlobString(image,"0000000000 65535 f \n"); 2863 for (i=0; i < (ssize_t) object; i++) 2864 { 2865 (void) FormatLocaleString(buffer,MagickPathExtent,"%010lu 00000 n \n", 2866 (unsigned long) xref[i]); 2867 (void) WriteBlobString(image,buffer); 2868 } 2869 (void) WriteBlobString(image,"trailer\n"); 2870 (void) WriteBlobString(image,"<<\n"); 2871 (void) FormatLocaleString(buffer,MagickPathExtent,"/Size %.20g\n",(double) 2872 object+1); 2873 (void) WriteBlobString(image,buffer); 2874 (void) FormatLocaleString(buffer,MagickPathExtent,"/Info %.20g 0 R\n",(double) 2875 info_id); 2876 (void) WriteBlobString(image,buffer); 2877 (void) FormatLocaleString(buffer,MagickPathExtent,"/Root %.20g 0 R\n",(double) 2878 root_id); 2879 (void) WriteBlobString(image,buffer); 2880 (void) SignatureImage(image,exception); 2881 (void) FormatLocaleString(buffer,MagickPathExtent,"/ID [<%s> <%s>]\n", 2882 GetImageProperty(image,"signature",exception), 2883 GetImageProperty(image,"signature",exception)); 2884 (void) WriteBlobString(image,buffer); 2885 (void) WriteBlobString(image,">>\n"); 2886 (void) WriteBlobString(image,"startxref\n"); 2887 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double) offset); 2888 (void) WriteBlobString(image,buffer); 2889 (void) WriteBlobString(image,"%%EOF\n"); 2890 xref=(MagickOffsetType *) RelinquishMagickMemory(xref); 2891 (void) CloseBlob(image); 2892 return(MagickTrue); 2893 } 2894