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