2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read Postscript Using the Display Postscript System. %
20 % Copyright 1999-2013 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 "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>
68 #if defined(MAGICKCORE_DPS_DELEGATE)
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74 % R e a d D P S I m a g e %
78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
84 % The format of the ReadDPSImage method is:
86 % Image *ReadDPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
88 % A description of each parameter follows:
90 % o image_info: the image info.
92 % o exception: return any errors or warnings in this structure.
96 static inline double MagickMin(const double x,const double y)
103 static Image *ReadDPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
163 Open X server connection.
165 assert(image_info != (const ImageInfo *) NULL);
166 assert(image_info->signature == MagickSignature);
167 if (image_info->debug != MagickFalse)
168 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
169 image_info->filename);
170 assert(exception != (ExceptionInfo *) NULL);
171 assert(exception->signature == MagickSignature);
172 display=XOpenDisplay(image_info->server_name);
173 if (display == (Display *) NULL)
174 return((Image *) NULL);
176 Set our forgiving exception handler.
178 (void) XSetErrorHandler(XError);
182 image=AcquireImage(image_info,exception);
183 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
184 if (status == MagickFalse)
185 return((Image *) NULL);
187 Get user defaults from X resource database.
189 client_name=GetClientName();
190 resource_database=XGetResourceDatabase(display,client_name);
191 XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
193 Allocate standard colormap.
195 map_info=XAllocStandardColormap();
196 visual_info=(XVisualInfo *) NULL;
197 if (map_info == (XStandardColormap *) NULL)
198 ThrowReaderException(ResourceLimitError,"UnableToCreateStandardColormap")
202 Initialize visual info.
204 (void) CloneString(&resource_info.visual_type,"default");
205 visual_info=XBestVisualInfo(display,map_info,&resource_info);
206 map_info->colormap=(Colormap) NULL;
208 if ((map_info == (XStandardColormap *) NULL) ||
209 (visual_info == (XVisualInfo *) NULL))
211 image=DestroyImage(image);
212 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
213 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
214 return((Image *) NULL);
217 Create a pixmap the appropriate size for the image.
219 screen=ScreenOfDisplay(display,visual_info->screen);
220 pixels_per_point=XDPSPixelsPerPoint(screen);
221 if ((image->resolution.x != 0.0) && (image->resolution.y != 0.0))
222 pixels_per_point=MagickMin(image->resolution.x,image->resolution.y)/
224 status=XDPSCreatePixmapForEPSF((DPSContext) NULL,screen,
225 GetBlobFileHandle(image),visual_info->depth,pixels_per_point,&pixmap,
226 &bits_per_pixel,&page);
227 if ((status == dps_status_failure) || (status == dps_status_no_extension))
229 image=DestroyImage(image);
230 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
231 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
232 return((Image *) NULL);
235 Rasterize the file into the pixmap.
237 status=XDPSImageFileIntoDrawable((DPSContext) NULL,screen,pixmap,
238 GetBlobFileHandle(image),(int) bits_per_pixel.height,visual_info->depth,
239 &page,-page.x,-page.y,pixels_per_point,MagickTrue,MagickFalse,MagickTrue,
241 if (status != dps_status_success)
243 image=DestroyImage(image);
244 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
245 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
246 return((Image *) NULL);
249 Initialize DPS X image.
251 dps_image=XGetImage(display,pixmap,0,0,bits_per_pixel.width,
252 bits_per_pixel.height,AllPlanes,ZPixmap);
253 (void) XFreePixmap(display,pixmap);
254 if (dps_image == (XImage *) NULL)
256 image=DestroyImage(image);
257 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
258 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
259 return((Image *) NULL);
262 Get the colormap colors.
264 colors=(XColor *) AcquireQuantumMemory(visual_info->colormap_size,
266 if (colors == (XColor *) NULL)
268 image=DestroyImage(image);
269 XDestroyImage(dps_image);
270 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
271 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
272 return((Image *) NULL);
274 if ((visual_info->klass != DirectColor) && (visual_info->klass != TrueColor))
275 for (i=0; i < visual_info->colormap_size; i++)
277 colors[i].pixel=(size_t) i;
291 DirectColor or TrueColor visual.
296 red_bit=visual_info->red_mask & (~(visual_info->red_mask)+1);
297 green_bit=visual_info->green_mask & (~(visual_info->green_mask)+1);
298 blue_bit=visual_info->blue_mask & (~(visual_info->blue_mask)+1);
299 for (i=0; i < visual_info->colormap_size; i++)
301 colors[i].pixel=red | green | blue;
304 if (red > visual_info->red_mask)
307 if (green > visual_info->green_mask)
310 if (blue > visual_info->blue_mask)
314 (void) XQueryColors(display,XDefaultColormap(display,visual_info->screen),
315 colors,visual_info->colormap_size);
317 Convert X image to MIFF format.
319 if ((visual_info->klass != TrueColor) && (visual_info->klass != DirectColor))
320 image->storage_class=PseudoClass;
321 image->columns=(size_t) dps_image->width;
322 image->rows=(size_t) dps_image->height;
323 if (image_info->ping != MagickFalse)
325 (void) CloseBlob(image);
326 return(GetFirstImageInList(image));
328 switch (image->storage_class)
346 Determine shift and mask for red, green, and blue.
348 red_mask=visual_info->red_mask;
350 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
355 green_mask=visual_info->green_mask;
357 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
362 blue_mask=visual_info->blue_mask;
364 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
370 Convert X image to DirectClass packets.
372 if ((visual_info->colormap_size > 0) &&
373 (visual_info->klass == DirectColor))
374 for (y=0; y < (ssize_t) image->rows; y++)
376 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
377 if (q == (Quantum *) NULL)
379 for (x=0; x < (ssize_t) image->columns; x++)
381 pixel=XGetPixel(dps_image,x,y);
382 index=(pixel >> red_shift) & red_mask;
383 SetPixelRed(image,ScaleShortToQuantum(colors[index].red),q);
384 index=(pixel >> green_shift) & green_mask;
385 SetPixelGreen(image,ScaleShortToQuantum(colors[index].green),q);
386 index=(pixel >> blue_shift) & blue_mask;
387 SetPixelBlue(image,ScaleShortToQuantum(colors[index].blue),q);
388 q+=GetPixelChannels(image);
390 if (SyncAuthenticPixels(image,exception) == MagickFalse)
392 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
396 for (y=0; y < (ssize_t) image->rows; y++)
398 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
399 if (q == (Quantum *) NULL)
401 for (x=0; x < (ssize_t) image->columns; x++)
403 pixel=XGetPixel(dps_image,x,y);
404 color=(pixel >> red_shift) & red_mask;
405 color=(color*65535L)/red_mask;
406 SetPixelRed(image,ScaleShortToQuantum((unsigned short) color),q);
407 color=(pixel >> green_shift) & green_mask;
408 color=(color*65535L)/green_mask;
409 SetPixelGreen(image,ScaleShortToQuantum((unsigned short) color),q);
410 color=(pixel >> blue_shift) & blue_mask;
411 color=(color*65535L)/blue_mask;
412 SetPixelBlue(image,ScaleShortToQuantum((unsigned short) color),q);
413 q+=GetPixelChannels(image);
415 if (SyncAuthenticPixels(image,exception) == MagickFalse)
417 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
427 if (AcquireImageColormap(image,(size_t) visual_info->colormap_size,exception) == MagickFalse)
429 image=DestroyImage(image);
430 colors=(XColor *) RelinquishMagickMemory(colors);
431 XDestroyImage(dps_image);
432 XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
433 (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
434 return((Image *) NULL);
436 for (i=0; i < (ssize_t) image->colors; i++)
438 image->colormap[colors[i].pixel].red=ScaleShortToQuantum(colors[i].red);
439 image->colormap[colors[i].pixel].green=
440 ScaleShortToQuantum(colors[i].green);
441 image->colormap[colors[i].pixel].blue=
442 ScaleShortToQuantum(colors[i].blue);
445 Convert X image to PseudoClass packets.
447 for (y=0; y < (ssize_t) image->rows; y++)
449 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
450 if (q == (Quantum *) NULL)
452 for (x=0; x < (ssize_t) image->columns; x++)
454 SetPixelIndex(image,(unsigned short) XGetPixel(dps_image,x,y),q);
455 q+=GetPixelChannels(image);
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,exception);
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->alpha_trait=BlendPixelTrait;
494 for (y=0; y < (ssize_t) image->rows; y++)
496 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
497 if (q == (Quantum *) NULL)
499 for (x=0; x < (ssize_t) image->columns; x++)
501 SetPixelAlpha(image,OpaqueAlpha,q);
502 if (XGetPixel(matte_image,x,y) == 0)
503 SetPixelAlpha(image,TransparentAlpha,q);
504 q+=GetPixelChannels(image);
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");