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