1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % DDDD PPPP SSSSS % 7 % D D P P SS % 8 % D D PPPP SSS % 9 % D D P SS % 10 % DDDD P SSSSS % 11 % % 12 % % 13 % Read Postscript Using the Display Postscript System. % 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/blob.h" 45 #include "MagickCore/blob-private.h" 46 #include "MagickCore/client.h" 47 #include "MagickCore/colormap.h" 48 #include "MagickCore/exception.h" 49 #include "MagickCore/exception-private.h" 50 #include "MagickCore/image.h" 51 #include "MagickCore/image-private.h" 52 #include "MagickCore/list.h" 53 #include "MagickCore/magick.h" 54 #include "MagickCore/memory_.h" 55 #include "MagickCore/monitor.h" 56 #include "MagickCore/monitor-private.h" 57 #include "MagickCore/pixel-accessor.h" 58 #include "MagickCore/quantum-private.h" 59 #include "MagickCore/static.h" 60 #include "MagickCore/string_.h" 61 #include "MagickCore/module.h" 62 #include "MagickCore/utility.h" 63 #include "MagickCore/xwindow-private.h" 64 #if defined(MAGICKCORE_DPS_DELEGATE) 65 #include <DPS/dpsXclient.h> 66 #include <DPS/dpsXpreview.h> 67 #endif 68 69 #if defined(MAGICKCORE_DPS_DELEGATE) 71 /* 72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 73 % % 74 % % 75 % % 76 % R e a d D P S I m a g e % 77 % % 78 % % 79 % % 80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 81 % 82 % ReadDPSImage() reads a Adobe Postscript image file and returns it. It 83 % allocates the memory necessary for the new Image structure and returns a 84 % pointer to the new image. 85 % 86 % The format of the ReadDPSImage method is: 87 % 88 % Image *ReadDPSImage(const ImageInfo *image_info,ExceptionInfo *exception) 89 % 90 % A description of each parameter follows: 91 % 92 % o image_info: the image info. 93 % 94 % o exception: return any errors or warnings in this structure. 95 % 96 */ 97 static Image *ReadDPSImage(const ImageInfo *image_info,ExceptionInfo *exception) 98 { 99 const char 100 *client_name; 101 102 Display 103 *display; 104 105 float 106 pixels_per_point; 107 108 Image 109 *image; 110 111 int 112 sans, 113 status; 114 115 Pixmap 116 pixmap; 117 118 register ssize_t 119 i; 120 121 register Quantum 122 *q; 123 124 register size_t 125 pixel; 126 127 Screen 128 *screen; 129 130 ssize_t 131 x, 132 y; 133 134 XColor 135 *colors; 136 137 XImage 138 *dps_image; 139 140 XRectangle 141 page, 142 bits_per_pixel; 143 144 XResourceInfo 145 resource_info; 146 147 XrmDatabase 148 resource_database; 149 150 XStandardColormap 151 *map_info; 152 153 XVisualInfo 154 *visual_info; 155 156 /* 157 Open X server connection. 158 */ 159 assert(image_info != (const ImageInfo *) NULL); 160 assert(image_info->signature == MagickCoreSignature); 161 if (image_info->debug != MagickFalse) 162 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 163 image_info->filename); 164 assert(exception != (ExceptionInfo *) NULL); 165 assert(exception->signature == MagickCoreSignature); 166 display=XOpenDisplay(image_info->server_name); 167 if (display == (Display *) NULL) 168 return((Image *) NULL); 169 /* 170 Set our forgiving exception handler. 171 */ 172 (void) XSetErrorHandler(XError); 173 /* 174 Open image file. 175 */ 176 image=AcquireImage(image_info,exception); 177 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 178 if (status == MagickFalse) 179 return((Image *) NULL); 180 /* 181 Get user defaults from X resource database. 182 */ 183 client_name=GetClientName(); 184 resource_database=XGetResourceDatabase(display,client_name); 185 XGetResourceInfo(image_info,resource_database,client_name,&resource_info); 186 /* 187 Allocate standard colormap. 188 */ 189 map_info=XAllocStandardColormap(); 190 visual_info=(XVisualInfo *) NULL; 191 if (map_info == (XStandardColormap *) NULL) 192 ThrowReaderException(ResourceLimitError,"UnableToCreateStandardColormap") 193 else 194 { 195 /* 196 Initialize visual info. 197 */ 198 (void) CloneString(&resource_info.visual_type,"default"); 199 visual_info=XBestVisualInfo(display,map_info,&resource_info); 200 map_info->colormap=(Colormap) NULL; 201 } 202 if ((map_info == (XStandardColormap *) NULL) || 203 (visual_info == (XVisualInfo *) NULL)) 204 { 205 image=DestroyImage(image); 206 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, 207 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); 208 return((Image *) NULL); 209 } 210 /* 211 Create a pixmap the appropriate size for the image. 212 */ 213 screen=ScreenOfDisplay(display,visual_info->screen); 214 pixels_per_point=XDPSPixelsPerPoint(screen); 215 if ((image->resolution.x != 0.0) && (image->resolution.y != 0.0)) 216 pixels_per_point=MagickMin(image->resolution.x,image->resolution.y)/ 217 DefaultResolution; 218 status=XDPSCreatePixmapForEPSF((DPSContext) NULL,screen, 219 GetBlobFileHandle(image),visual_info->depth,pixels_per_point,&pixmap, 220 &bits_per_pixel,&page); 221 if ((status == dps_status_failure) || (status == dps_status_no_extension)) 222 { 223 image=DestroyImage(image); 224 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, 225 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); 226 return((Image *) NULL); 227 } 228 /* 229 Rasterize the file into the pixmap. 230 */ 231 status=XDPSImageFileIntoDrawable((DPSContext) NULL,screen,pixmap, 232 GetBlobFileHandle(image),(int) bits_per_pixel.height,visual_info->depth, 233 &page,-page.x,-page.y,pixels_per_point,MagickTrue,MagickFalse,MagickTrue, 234 &sans); 235 if (status != dps_status_success) 236 { 237 image=DestroyImage(image); 238 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, 239 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); 240 return((Image *) NULL); 241 } 242 /* 243 Initialize DPS X image. 244 */ 245 dps_image=XGetImage(display,pixmap,0,0,bits_per_pixel.width, 246 bits_per_pixel.height,AllPlanes,ZPixmap); 247 (void) XFreePixmap(display,pixmap); 248 if (dps_image == (XImage *) NULL) 249 { 250 image=DestroyImage(image); 251 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, 252 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); 253 return((Image *) NULL); 254 } 255 /* 256 Get the colormap colors. 257 */ 258 colors=(XColor *) AcquireQuantumMemory(visual_info->colormap_size, 259 sizeof(*colors)); 260 if (colors == (XColor *) NULL) 261 { 262 image=DestroyImage(image); 263 XDestroyImage(dps_image); 264 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, 265 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); 266 return((Image *) NULL); 267 } 268 if ((visual_info->klass != DirectColor) && (visual_info->klass != TrueColor)) 269 for (i=0; i < visual_info->colormap_size; i++) 270 { 271 colors[i].pixel=(size_t) i; 272 colors[i].pad=0; 273 } 274 else 275 { 276 size_t 277 blue, 278 blue_bit, 279 green, 280 green_bit, 281 red, 282 red_bit; 283 284 /* 285 DirectColor or TrueColor visual. 286 */ 287 red=0; 288 green=0; 289 blue=0; 290 red_bit=visual_info->red_mask & (~(visual_info->red_mask)+1); 291 green_bit=visual_info->green_mask & (~(visual_info->green_mask)+1); 292 blue_bit=visual_info->blue_mask & (~(visual_info->blue_mask)+1); 293 for (i=0; i < visual_info->colormap_size; i++) 294 { 295 colors[i].pixel=red | green | blue; 296 colors[i].pad=0; 297 red+=red_bit; 298 if (red > visual_info->red_mask) 299 red=0; 300 green+=green_bit; 301 if (green > visual_info->green_mask) 302 green=0; 303 blue+=blue_bit; 304 if (blue > visual_info->blue_mask) 305 blue=0; 306 } 307 } 308 (void) XQueryColors(display,XDefaultColormap(display,visual_info->screen), 309 colors,visual_info->colormap_size); 310 /* 311 Convert X image to MIFF format. 312 */ 313 if ((visual_info->klass != TrueColor) && (visual_info->klass != DirectColor)) 314 image->storage_class=PseudoClass; 315 image->columns=(size_t) dps_image->width; 316 image->rows=(size_t) dps_image->height; 317 if (image_info->ping != MagickFalse) 318 { 319 (void) CloseBlob(image); 320 return(GetFirstImageInList(image)); 321 } 322 status=SetImageExtent(image,image->columns,image->rows,exception); 323 if (status == MagickFalse) 324 return(DestroyImageList(image)); 325 switch (image->storage_class) 326 { 327 case DirectClass: 328 default: 329 { 330 register size_t 331 color, 332 index; 333 334 size_t 335 blue_mask, 336 blue_shift, 337 green_mask, 338 green_shift, 339 red_mask, 340 red_shift; 341 342 /* 343 Determine shift and mask for red, green, and blue. 344 */ 345 red_mask=visual_info->red_mask; 346 red_shift=0; 347 while ((red_mask != 0) && ((red_mask & 0x01) == 0)) 348 { 349 red_mask>>=1; 350 red_shift++; 351 } 352 green_mask=visual_info->green_mask; 353 green_shift=0; 354 while ((green_mask != 0) && ((green_mask & 0x01) == 0)) 355 { 356 green_mask>>=1; 357 green_shift++; 358 } 359 blue_mask=visual_info->blue_mask; 360 blue_shift=0; 361 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0)) 362 { 363 blue_mask>>=1; 364 blue_shift++; 365 } 366 /* 367 Convert X image to DirectClass packets. 368 */ 369 if ((visual_info->colormap_size > 0) && 370 (visual_info->klass == DirectColor)) 371 for (y=0; y < (ssize_t) image->rows; y++) 372 { 373 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 374 if (q == (Quantum *) NULL) 375 break; 376 for (x=0; x < (ssize_t) image->columns; x++) 377 { 378 pixel=XGetPixel(dps_image,x,y); 379 index=(pixel >> red_shift) & red_mask; 380 SetPixelRed(image,ScaleShortToQuantum(colors[index].red),q); 381 index=(pixel >> green_shift) & green_mask; 382 SetPixelGreen(image,ScaleShortToQuantum(colors[index].green),q); 383 index=(pixel >> blue_shift) & blue_mask; 384 SetPixelBlue(image,ScaleShortToQuantum(colors[index].blue),q); 385 q+=GetPixelChannels(image); 386 } 387 if (SyncAuthenticPixels(image,exception) == MagickFalse) 388 break; 389 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse) 390 break; 391 } 392 else 393 for (y=0; y < (ssize_t) image->rows; y++) 394 { 395 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 396 if (q == (Quantum *) NULL) 397 break; 398 for (x=0; x < (ssize_t) image->columns; x++) 399 { 400 pixel=XGetPixel(dps_image,x,y); 401 color=(pixel >> red_shift) & red_mask; 402 color=(color*65535L)/red_mask; 403 SetPixelRed(image,ScaleShortToQuantum((unsigned short) color),q); 404 color=(pixel >> green_shift) & green_mask; 405 color=(color*65535L)/green_mask; 406 SetPixelGreen(image,ScaleShortToQuantum((unsigned short) color),q); 407 color=(pixel >> blue_shift) & blue_mask; 408 color=(color*65535L)/blue_mask; 409 SetPixelBlue(image,ScaleShortToQuantum((unsigned short) color),q); 410 q+=GetPixelChannels(image); 411 } 412 if (SyncAuthenticPixels(image,exception) == MagickFalse) 413 break; 414 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse) 415 break; 416 } 417 break; 418 } 419 case PseudoClass: 420 { 421 /* 422 Create colormap. 423 */ 424 if (AcquireImageColormap(image,(size_t) visual_info->colormap_size,exception) == MagickFalse) 425 { 426 image=DestroyImage(image); 427 colors=(XColor *) RelinquishMagickMemory(colors); 428 XDestroyImage(dps_image); 429 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, 430 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); 431 return((Image *) NULL); 432 } 433 for (i=0; i < (ssize_t) image->colors; i++) 434 { 435 image->colormap[colors[i].pixel].red=ScaleShortToQuantum(colors[i].red); 436 image->colormap[colors[i].pixel].green= 437 ScaleShortToQuantum(colors[i].green); 438 image->colormap[colors[i].pixel].blue= 439 ScaleShortToQuantum(colors[i].blue); 440 } 441 /* 442 Convert X image to PseudoClass packets. 443 */ 444 for (y=0; y < (ssize_t) image->rows; y++) 445 { 446 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 447 if (q == (Quantum *) NULL) 448 break; 449 for (x=0; x < (ssize_t) image->columns; x++) 450 { 451 SetPixelIndex(image,(unsigned short) XGetPixel(dps_image,x,y),q); 452 q+=GetPixelChannels(image); 453 } 454 if (SyncAuthenticPixels(image,exception) == MagickFalse) 455 break; 456 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse) 457 break; 458 } 459 break; 460 } 461 } 462 colors=(XColor *) RelinquishMagickMemory(colors); 463 XDestroyImage(dps_image); 464 if (image->storage_class == PseudoClass) 465 (void) SyncImage(image,exception); 466 /* 467 Rasterize matte image. 468 */ 469 status=XDPSCreatePixmapForEPSF((DPSContext) NULL,screen, 470 GetBlobFileHandle(image),1,pixels_per_point,&pixmap,&bits_per_pixel,&page); 471 if ((status != dps_status_failure) && (status != dps_status_no_extension)) 472 { 473 status=XDPSImageFileIntoDrawable((DPSContext) NULL,screen,pixmap, 474 GetBlobFileHandle(image),(int) bits_per_pixel.height,1,&page,-page.x, 475 -page.y,pixels_per_point,MagickTrue,MagickTrue,MagickTrue,&sans); 476 if (status == dps_status_success) 477 { 478 XImage 479 *matte_image; 480 481 /* 482 Initialize image matte. 483 */ 484 matte_image=XGetImage(display,pixmap,0,0,bits_per_pixel.width, 485 bits_per_pixel.height,AllPlanes,ZPixmap); 486 (void) XFreePixmap(display,pixmap); 487 if (matte_image != (XImage *) NULL) 488 { 489 image->storage_class=DirectClass; 490 image->alpha_trait=BlendPixelTrait; 491 for (y=0; y < (ssize_t) image->rows; y++) 492 { 493 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 494 if (q == (Quantum *) NULL) 495 break; 496 for (x=0; x < (ssize_t) image->columns; x++) 497 { 498 SetPixelAlpha(image,OpaqueAlpha,q); 499 if (XGetPixel(matte_image,x,y) == 0) 500 SetPixelAlpha(image,TransparentAlpha,q); 501 q+=GetPixelChannels(image); 502 } 503 if (SyncAuthenticPixels(image,exception) == MagickFalse) 504 break; 505 } 506 XDestroyImage(matte_image); 507 } 508 } 509 } 510 /* 511 Relinquish resources. 512 */ 513 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, 514 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); 515 (void) CloseBlob(image); 516 return(GetFirstImageInList(image)); 517 } 518 #endif 519 520 /* 522 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 523 % % 524 % % 525 % % 526 % R e g i s t e r D P S I m a g e % 527 % % 528 % % 529 % % 530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 531 % 532 % RegisterDPSImage() adds attributes for the Display Postscript image 533 % format to the list of supported formats. The attributes include the image 534 % format tag, a method to read and/or write the format, whether the format 535 % supports the saving of more than one frame to the same file or blob, 536 % whether the format supports native in-memory I/O, and a brief 537 % description of the format. 538 % 539 % The format of the RegisterDPSImage method is: 540 % 541 % size_t RegisterDPSImage(void) 542 % 543 */ 544 ModuleExport size_t RegisterDPSImage(void) 545 { 546 MagickInfo 547 *entry; 548 549 entry=AcquireMagickInfo("DPS","DPS","Display Postscript Interpreter"); 550 #if defined(MAGICKCORE_DPS_DELEGATE) 551 entry->decoder=(DecodeImageHandler *) ReadDPSImage; 552 #endif 553 entry->flags^=CoderBlobSupportFlag; 554 (void) RegisterMagickInfo(entry); 555 return(MagickImageCoderSignature); 556 } 557 558 /* 560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 561 % % 562 % % 563 % % 564 % U n r e g i s t e r D P S I m a g e % 565 % % 566 % % 567 % % 568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 569 % 570 % UnregisterDPSImage() removes format registrations made by the 571 % DPS module from the list of supported formats. 572 % 573 % The format of the UnregisterDPSImage method is: 574 % 575 % UnregisterDPSImage(void) 576 % 577 */ 578 ModuleExport void UnregisterDPSImage(void) 579 { 580 (void) UnregisterMagickInfo("DPS"); 581 } 582