2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read Postscript Using the Display Postscript System. %
20 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/blob-private.h"
45 #include "magick/client.h"
46 #include "magick/colormap.h"
47 #include "magick/exception.h"
48 #include "magick/exception-private.h"
49 #include "magick/image.h"
50 #include "magick/image-private.h"
51 #include "magick/list.h"
52 #include "magick/magick.h"
53 #include "magick/memory_.h"
54 #include "magick/monitor.h"
55 #include "magick/monitor-private.h"
56 #include "magick/quantum-private.h"
57 #include "magick/static.h"
58 #include "magick/string_.h"
59 #include "magick/module.h"
60 #include "magick/utility.h"
61 #include "magick/xwindow-private.h"
62 #if defined(MAGICKCORE_DPS_DELEGATE)
63 #include <DPS/dpsXclient.h>
64 #include <DPS/dpsXpreview.h>
67 #if defined(MAGICKCORE_DPS_DELEGATE)
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 % R e a d D P S I m a g e %
77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 % ReadDPSImage() reads a Adobe Postscript image file and returns it. It
80 % allocates the memory necessary for the new Image structure and returns a
81 % pointer to the new image.
83 % The format of the ReadDPSImage method is:
85 % Image *ReadDPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
87 % A description of each parameter follows:
89 % o image_info: the image info.
91 % o exception: return any errors or warnings in this structure.
95 static inline double MagickMin(const double x,const double y)
102 static Image *ReadDPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
165 Open X server connection.
167 assert(image_info != (const ImageInfo *) NULL);
168 assert(image_info->signature == MagickSignature);
169 if (image_info->debug != MagickFalse)
170 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
171 image_info->filename);
172 assert(exception != (ExceptionInfo *) NULL);
173 assert(exception->signature == MagickSignature);
174 display=XOpenDisplay(image_info->server_name);
175 if (display == (Display *) NULL)
176 return((Image *) NULL);
178 Set our forgiving exception handler.
180 (void) XSetErrorHandler(XError);
184 image=AcquireImage(image_info);
185 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
186 if (status == MagickFalse)
187 return((Image *) NULL);
189 Get user defaults from X resource database.
191 client_name=GetClientName();
192 resource_database=XGetResourceDatabase(display,client_name);
193 XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
195 Allocate standard colormap.
197 map_info=XAllocStandardColormap();
198 visual_info=(XVisualInfo *) NULL;
199 if (map_info == (XStandardColormap *) NULL)
200 ThrowReaderException(ResourceLimitError,"UnableToCreateStandardColormap")
204 Initialize visual info.
206 (void) CloneString(&resource_info.visual_type,"default");
207 visual_info=XBestVisualInfo(display,map_info,&resource_info);
208 map_info->colormap=(Colormap) NULL;
210 if ((map_info == (XStandardColormap *) NULL) ||
211 (visual_info == (XVisualInfo *) NULL))
213 image=DestroyImage(image);
214 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
215 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
216 return((Image *) NULL);
219 Create a pixmap the appropriate size for the image.
221 screen=ScreenOfDisplay(display,visual_info->screen);
222 pixels_per_point=XDPSPixelsPerPoint(screen);
223 if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
224 pixels_per_point=MagickMin(image->x_resolution,image->y_resolution)/
226 status=XDPSCreatePixmapForEPSF((DPSContext) NULL,screen,
227 GetBlobFileHandle(image),visual_info->depth,pixels_per_point,&pixmap,
228 &bits_per_pixel,&page);
229 if ((status == dps_status_failure) || (status == dps_status_no_extension))
231 image=DestroyImage(image);
232 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
233 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
234 return((Image *) NULL);
237 Rasterize the file into the pixmap.
239 status=XDPSImageFileIntoDrawable((DPSContext) NULL,screen,pixmap,
240 GetBlobFileHandle(image),(int) bits_per_pixel.height,visual_info->depth,
241 &page,-page.x,-page.y,pixels_per_point,MagickTrue,MagickFalse,MagickTrue,
243 if (status != dps_status_success)
245 image=DestroyImage(image);
246 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
247 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
248 return((Image *) NULL);
251 Initialize DPS X image.
253 dps_image=XGetImage(display,pixmap,0,0,bits_per_pixel.width,
254 bits_per_pixel.height,AllPlanes,ZPixmap);
255 (void) XFreePixmap(display,pixmap);
256 if (dps_image == (XImage *) NULL)
258 image=DestroyImage(image);
259 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
260 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
261 return((Image *) NULL);
264 Get the colormap colors.
266 colors=(XColor *) AcquireQuantumMemory(visual_info->colormap_size,
268 if (colors == (XColor *) NULL)
270 image=DestroyImage(image);
271 XDestroyImage(dps_image);
272 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
273 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
274 return((Image *) NULL);
276 if ((visual_info->klass != DirectColor) && (visual_info->klass != TrueColor))
277 for (i=0; i < visual_info->colormap_size; i++)
279 colors[i].pixel=(size_t) i;
293 DirectColor or TrueColor visual.
298 red_bit=visual_info->red_mask & (~(visual_info->red_mask)+1);
299 green_bit=visual_info->green_mask & (~(visual_info->green_mask)+1);
300 blue_bit=visual_info->blue_mask & (~(visual_info->blue_mask)+1);
301 for (i=0; i < visual_info->colormap_size; i++)
303 colors[i].pixel=red | green | blue;
306 if (red > visual_info->red_mask)
309 if (green > visual_info->green_mask)
312 if (blue > visual_info->blue_mask)
316 (void) XQueryColors(display,XDefaultColormap(display,visual_info->screen),
317 colors,visual_info->colormap_size);
319 Convert X image to MIFF format.
321 if ((visual_info->klass != TrueColor) && (visual_info->klass != DirectColor))
322 image->storage_class=PseudoClass;
323 image->columns=(size_t) dps_image->width;
324 image->rows=(size_t) dps_image->height;
325 if (image_info->ping != MagickFalse)
327 (void) CloseBlob(image);
328 return(GetFirstImageInList(image));
330 switch (image->storage_class)
348 Determine shift and mask for red, green, and blue.
350 red_mask=visual_info->red_mask;
352 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
357 green_mask=visual_info->green_mask;
359 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
364 blue_mask=visual_info->blue_mask;
366 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
372 Convert X image to DirectClass packets.
374 if ((visual_info->colormap_size > 0) &&
375 (visual_info->klass == DirectColor))
376 for (y=0; y < (ssize_t) image->rows; y++)
378 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
379 if (q == (PixelPacket *) NULL)
381 for (x=0; x < (ssize_t) image->columns; x++)
383 pixel=XGetPixel(dps_image,x,y);
384 index=(pixel >> red_shift) & red_mask;
385 SetRedPixelComponent(q,ScaleShortToQuantum(colors[index].red));
386 index=(pixel >> green_shift) & green_mask;
387 SetGreenPixelComponent(q,ScaleShortToQuantum(colors[index].green));
388 index=(pixel >> blue_shift) & blue_mask;
389 SetBluePixelComponent(q,ScaleShortToQuantum(colors[index].blue));
392 if (SyncAuthenticPixels(image,exception) == MagickFalse)
394 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
398 for (y=0; y < (ssize_t) image->rows; y++)
400 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
401 if (q == (PixelPacket *) NULL)
403 for (x=0; x < (ssize_t) image->columns; x++)
405 pixel=XGetPixel(dps_image,x,y);
406 color=(pixel >> red_shift) & red_mask;
407 color=(color*65535L)/red_mask;
408 SetRedPixelComponent(q,ScaleShortToQuantum((unsigned short) color));
409 color=(pixel >> green_shift) & green_mask;
410 color=(color*65535L)/green_mask;
411 SetGreenPixelComponent(q,ScaleShortToQuantum((unsigned short)
413 color=(pixel >> blue_shift) & blue_mask;
414 color=(color*65535L)/blue_mask;
415 SetBluePixelComponent(q,ScaleShortToQuantum((unsigned short)
419 if (SyncAuthenticPixels(image,exception) == MagickFalse)
421 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
431 if (AcquireImageColormap(image,(size_t) visual_info->colormap_size) == MagickFalse)
433 image=DestroyImage(image);
434 colors=(XColor *) RelinquishMagickMemory(colors);
435 XDestroyImage(dps_image);
436 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
437 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
438 return((Image *) NULL);
440 for (i=0; i < (ssize_t) image->colors; i++)
442 image->colormap[colors[i].pixel].red=ScaleShortToQuantum(colors[i].red);
443 image->colormap[colors[i].pixel].green=
444 ScaleShortToQuantum(colors[i].green);
445 image->colormap[colors[i].pixel].blue=
446 ScaleShortToQuantum(colors[i].blue);
449 Convert X image to PseudoClass packets.
451 for (y=0; y < (ssize_t) image->rows; y++)
453 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
454 if (q == (PixelPacket *) NULL)
456 indexes=GetAuthenticIndexQueue(image);
457 for (x=0; x < (ssize_t) image->columns; x++)
458 SetIndexPixelComponent(indexes+x,(unsigned short)
459 XGetPixel(dps_image,x,y));
460 if (SyncAuthenticPixels(image,exception) == MagickFalse)
462 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
468 colors=(XColor *) RelinquishMagickMemory(colors);
469 XDestroyImage(dps_image);
470 if (image->storage_class == PseudoClass)
471 (void) SyncImage(image);
473 Rasterize matte image.
475 status=XDPSCreatePixmapForEPSF((DPSContext) NULL,screen,
476 GetBlobFileHandle(image),1,pixels_per_point,&pixmap,&bits_per_pixel,&page);
477 if ((status != dps_status_failure) && (status != dps_status_no_extension))
479 status=XDPSImageFileIntoDrawable((DPSContext) NULL,screen,pixmap,
480 GetBlobFileHandle(image),(int) bits_per_pixel.height,1,&page,-page.x,
481 -page.y,pixels_per_point,MagickTrue,MagickTrue,MagickTrue,&sans);
482 if (status == dps_status_success)
488 Initialize image matte.
490 matte_image=XGetImage(display,pixmap,0,0,bits_per_pixel.width,
491 bits_per_pixel.height,AllPlanes,ZPixmap);
492 (void) XFreePixmap(display,pixmap);
493 if (matte_image != (XImage *) NULL)
495 image->storage_class=DirectClass;
496 image->matte=MagickTrue;
497 for (y=0; y < (ssize_t) image->rows; y++)
499 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
500 if (q == (PixelPacket *) NULL)
502 for (x=0; x < (ssize_t) image->columns; x++)
504 SetOpacityPixelComponent(q,OpaqueOpacity);
505 if (XGetPixel(matte_image,x,y) == 0)
506 SetOpacityPixelComponent(q,TransparentOpacity);
509 if (SyncAuthenticPixels(image,exception) == MagickFalse)
512 XDestroyImage(matte_image);
517 Relinquish resources.
519 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
520 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
521 (void) CloseBlob(image);
522 return(GetFirstImageInList(image));
527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
531 % R e g i s t e r D P S I m a g e %
535 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
537 % RegisterDPSImage() adds attributes for the Display Postscript image
538 % format to the list of supported formats. The attributes include the image
539 % format tag, a method to read and/or write the format, whether the format
540 % supports the saving of more than one frame to the same file or blob,
541 % whether the format supports native in-memory I/O, and a brief
542 % description of the format.
544 % The format of the RegisterDPSImage method is:
546 % size_t RegisterDPSImage(void)
549 ModuleExport size_t RegisterDPSImage(void)
554 entry=SetMagickInfo("DPS");
555 #if defined(MAGICKCORE_DPS_DELEGATE)
556 entry->decoder=(DecodeImageHandler *) ReadDPSImage;
558 entry->blob_support=MagickFalse;
559 entry->description=ConstantString("Display Postscript Interpreter");
560 entry->module=ConstantString("DPS");
561 (void) RegisterMagickInfo(entry);
562 return(MagickImageCoderSignature);
566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 % U n r e g i s t e r D P S I m a g e %
574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
576 % UnregisterDPSImage() removes format registrations made by the
577 % DPS module from the list of supported formats.
579 % The format of the UnregisterDPSImage method is:
581 % UnregisterDPSImage(void)
584 ModuleExport void UnregisterDPSImage(void)
586 (void) UnregisterMagickInfo("DPS");