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 q->red=ScaleShortToQuantum(colors[index].red);
386 index=(pixel >> green_shift) & green_mask;
387 q->green=ScaleShortToQuantum(colors[index].green);
388 index=(pixel >> blue_shift) & blue_mask;
389 q->blue=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 q->red=ScaleShortToQuantum((unsigned short) color);
409 color=(pixel >> green_shift) & green_mask;
410 color=(color*65535L)/green_mask;
411 q->green=ScaleShortToQuantum((unsigned short) color);
412 color=(pixel >> blue_shift) & blue_mask;
413 color=(color*65535L)/blue_mask;
414 q->blue=ScaleShortToQuantum((unsigned short) color);
417 if (SyncAuthenticPixels(image,exception) == MagickFalse)
419 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
429 if (AcquireImageColormap(image,(size_t) visual_info->colormap_size) == MagickFalse)
431 image=DestroyImage(image);
432 colors=(XColor *) RelinquishMagickMemory(colors);
433 XDestroyImage(dps_image);
434 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
435 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
436 return((Image *) NULL);
438 for (i=0; i < (ssize_t) image->colors; i++)
440 image->colormap[colors[i].pixel].red=ScaleShortToQuantum(colors[i].red);
441 image->colormap[colors[i].pixel].green=
442 ScaleShortToQuantum(colors[i].green);
443 image->colormap[colors[i].pixel].blue=
444 ScaleShortToQuantum(colors[i].blue);
447 Convert X image to PseudoClass packets.
449 for (y=0; y < (ssize_t) image->rows; y++)
451 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
452 if (q == (PixelPacket *) NULL)
454 indexes=GetAuthenticIndexQueue(image);
455 for (x=0; x < (ssize_t) image->columns; x++)
456 indexes[x]=(unsigned short) XGetPixel(dps_image,x,y);
457 if (SyncAuthenticPixels(image,exception) == MagickFalse)
459 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
465 colors=(XColor *) RelinquishMagickMemory(colors);
466 XDestroyImage(dps_image);
467 if (image->storage_class == PseudoClass)
468 (void) SyncImage(image);
470 Rasterize matte image.
472 status=XDPSCreatePixmapForEPSF((DPSContext) NULL,screen,
473 GetBlobFileHandle(image),1,pixels_per_point,&pixmap,&bits_per_pixel,&page);
474 if ((status != dps_status_failure) && (status != dps_status_no_extension))
476 status=XDPSImageFileIntoDrawable((DPSContext) NULL,screen,pixmap,
477 GetBlobFileHandle(image),(int) bits_per_pixel.height,1,&page,-page.x,
478 -page.y,pixels_per_point,MagickTrue,MagickTrue,MagickTrue,&sans);
479 if (status == dps_status_success)
485 Initialize image matte.
487 matte_image=XGetImage(display,pixmap,0,0,bits_per_pixel.width,
488 bits_per_pixel.height,AllPlanes,ZPixmap);
489 (void) XFreePixmap(display,pixmap);
490 if (matte_image != (XImage *) NULL)
492 image->storage_class=DirectClass;
493 image->matte=MagickTrue;
494 for (y=0; y < (ssize_t) image->rows; y++)
496 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
497 if (q == (PixelPacket *) NULL)
499 for (x=0; x < (ssize_t) image->columns; x++)
501 SetOpacityPixelComponent(q,OpaqueOpacity);
502 if (XGetPixel(matte_image,x,y) == 0)
503 q->opacity=TransparentOpacity;
506 if (SyncAuthenticPixels(image,exception) == MagickFalse)
509 XDestroyImage(matte_image);
514 Relinquish resources.
516 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
517 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
518 (void) CloseBlob(image);
519 return(GetFirstImageInList(image));
524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528 % R e g i s t e r D P S I m a g e %
532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534 % RegisterDPSImage() adds attributes for the Display Postscript image
535 % format to the list of supported formats. The attributes include the image
536 % format tag, a method to read and/or write the format, whether the format
537 % supports the saving of more than one frame to the same file or blob,
538 % whether the format supports native in-memory I/O, and a brief
539 % description of the format.
541 % The format of the RegisterDPSImage method is:
543 % size_t RegisterDPSImage(void)
546 ModuleExport size_t RegisterDPSImage(void)
551 entry=SetMagickInfo("DPS");
552 #if defined(MAGICKCORE_DPS_DELEGATE)
553 entry->decoder=(DecodeImageHandler *) ReadDPSImage;
555 entry->blob_support=MagickFalse;
556 entry->description=ConstantString("Display Postscript Interpreter");
557 entry->module=ConstantString("DPS");
558 (void) RegisterMagickInfo(entry);
559 return(MagickImageCoderSignature);
563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 % U n r e g i s t e r D P S I m a g e %
571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
573 % UnregisterDPSImage() removes format registrations made by the
574 % DPS module from the list of supported formats.
576 % The format of the UnregisterDPSImage method is:
578 % UnregisterDPSImage(void)
581 ModuleExport void UnregisterDPSImage(void)
583 (void) UnregisterMagickInfo("DPS");