]> granicus.if.org Git - imagemagick/blob - coders/dps.c
(no commit message)
[imagemagick] / coders / dps.c
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 %                                John Cristy                                  %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2011 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 \f
39 /*
40   Include declarations.
41 */
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>
65 #endif
66 \f
67 #if defined(MAGICKCORE_DPS_DELEGATE)
68 /*
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 %                                                                             %
71 %                                                                             %
72 %                                                                             %
73 %   R e a d D P S I m a g e                                                   %
74 %                                                                             %
75 %                                                                             %
76 %                                                                             %
77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 %
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.
82 %
83 %  The format of the ReadDPSImage method is:
84 %
85 %      Image *ReadDPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
86 %
87 %  A description of each parameter follows:
88 %
89 %    o image_info: the image info.
90 %
91 %    o exception: return any errors or warnings in this structure.
92 %
93 */
94
95 static inline double MagickMin(const double x,const double y)
96 {
97   if (x < y)
98     return(x);
99   return(y);
100 }
101
102 static Image *ReadDPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
103 {
104   const char
105     *client_name;
106
107   Display
108     *display;
109
110   float
111     pixels_per_point;
112
113   Image
114     *image;
115
116   int
117     sans,
118     status;
119
120   Pixmap
121     pixmap;
122
123   register IndexPacket
124     *indexes;
125
126   register ssize_t
127     i;
128
129   register PixelPacket
130     *q;
131
132   register size_t
133     pixel;
134
135   Screen
136     *screen;
137
138   ssize_t
139     x,
140     y;
141
142   XColor
143     *colors;
144
145   XImage
146     *dps_image;
147
148   XRectangle
149     page,
150     bits_per_pixel;
151
152   XResourceInfo
153     resource_info;
154
155   XrmDatabase
156     resource_database;
157
158   XStandardColormap
159     *map_info;
160
161   XVisualInfo
162     *visual_info;
163
164   /*
165     Open X server connection.
166   */
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);
177   /*
178     Set our forgiving exception handler.
179   */
180   (void) XSetErrorHandler(XError);
181   /*
182     Open image file.
183   */
184   image=AcquireImage(image_info);
185   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
186   if (status == MagickFalse)
187     return((Image *) NULL);
188   /*
189     Get user defaults from X resource database.
190   */
191   client_name=GetClientName();
192   resource_database=XGetResourceDatabase(display,client_name);
193   XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
194   /*
195     Allocate standard colormap.
196   */
197   map_info=XAllocStandardColormap();
198   visual_info=(XVisualInfo *) NULL;
199   if (map_info == (XStandardColormap *) NULL)
200     ThrowReaderException(ResourceLimitError,"UnableToCreateStandardColormap")
201   else
202     {
203       /*
204         Initialize visual info.
205       */
206       (void) CloneString(&resource_info.visual_type,"default");
207       visual_info=XBestVisualInfo(display,map_info,&resource_info);
208       map_info->colormap=(Colormap) NULL;
209     }
210   if ((map_info == (XStandardColormap *) NULL) ||
211       (visual_info == (XVisualInfo *) NULL))
212     {
213       image=DestroyImage(image);
214       XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
215         (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
216       return((Image *) NULL);
217     }
218   /*
219     Create a pixmap the appropriate size for the image.
220   */
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)/
225       DefaultResolution;
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))
230     {
231       image=DestroyImage(image);
232       XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
233         (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
234       return((Image *) NULL);
235     }
236   /*
237     Rasterize the file into the pixmap.
238   */
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,
242     &sans);
243   if (status != dps_status_success)
244     {
245       image=DestroyImage(image);
246       XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
247         (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
248       return((Image *) NULL);
249     }
250   /*
251     Initialize DPS X image.
252   */
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)
257     {
258       image=DestroyImage(image);
259       XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
260         (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
261       return((Image *) NULL);
262     }
263   /*
264     Get the colormap colors.
265   */
266   colors=(XColor *) AcquireQuantumMemory(visual_info->colormap_size,
267     sizeof(*colors));
268   if (colors == (XColor *) NULL)
269     {
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);
275     }
276   if ((visual_info->klass != DirectColor) && (visual_info->klass != TrueColor))
277     for (i=0; i < visual_info->colormap_size; i++)
278     {
279       colors[i].pixel=(size_t) i;
280       colors[i].pad=0;
281     }
282   else
283     {
284       size_t
285         blue,
286         blue_bit,
287         green,
288         green_bit,
289         red,
290         red_bit;
291
292       /*
293         DirectColor or TrueColor visual.
294       */
295       red=0;
296       green=0;
297       blue=0;
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++)
302       {
303         colors[i].pixel=red | green | blue;
304         colors[i].pad=0;
305         red+=red_bit;
306         if (red > visual_info->red_mask)
307           red=0;
308         green+=green_bit;
309         if (green > visual_info->green_mask)
310           green=0;
311         blue+=blue_bit;
312         if (blue > visual_info->blue_mask)
313           blue=0;
314       }
315     }
316   (void) XQueryColors(display,XDefaultColormap(display,visual_info->screen),
317     colors,visual_info->colormap_size);
318   /*
319     Convert X image to MIFF format.
320   */
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)
326     {
327       (void) CloseBlob(image);
328       return(GetFirstImageInList(image));
329     }
330   switch (image->storage_class)
331   {
332     case DirectClass:
333     default:
334     {
335       register size_t
336         color,
337         index;
338
339       size_t
340         blue_mask,
341         blue_shift,
342         green_mask,
343         green_shift,
344         red_mask,
345         red_shift;
346
347       /*
348         Determine shift and mask for red, green, and blue.
349       */
350       red_mask=visual_info->red_mask;
351       red_shift=0;
352       while ((red_mask != 0) && ((red_mask & 0x01) == 0))
353       {
354         red_mask>>=1;
355         red_shift++;
356       }
357       green_mask=visual_info->green_mask;
358       green_shift=0;
359       while ((green_mask != 0) && ((green_mask & 0x01) == 0))
360       {
361         green_mask>>=1;
362         green_shift++;
363       }
364       blue_mask=visual_info->blue_mask;
365       blue_shift=0;
366       while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
367       {
368         blue_mask>>=1;
369         blue_shift++;
370       }
371       /*
372         Convert X image to DirectClass packets.
373       */
374       if ((visual_info->colormap_size > 0) &&
375           (visual_info->klass == DirectColor))
376         for (y=0; y < (ssize_t) image->rows; y++)
377         {
378           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
379           if (q == (PixelPacket *) NULL)
380             break;
381           for (x=0; x < (ssize_t) image->columns; x++)
382           {
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));
390             q++;
391           }
392           if (SyncAuthenticPixels(image,exception) == MagickFalse)
393             break;
394           if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
395             break;
396         }
397       else
398         for (y=0; y < (ssize_t) image->rows; y++)
399         {
400           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
401           if (q == (PixelPacket *) NULL)
402             break;
403           for (x=0; x < (ssize_t) image->columns; x++)
404           {
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)
412               color));
413             color=(pixel >> blue_shift) & blue_mask;
414             color=(color*65535L)/blue_mask;
415             SetBluePixelComponent(q,ScaleShortToQuantum((unsigned short)
416               color));
417             q++;
418           }
419           if (SyncAuthenticPixels(image,exception) == MagickFalse)
420             break;
421           if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
422             break;
423         }
424       break;
425     }
426     case PseudoClass:
427     {
428       /*
429         Create colormap.
430       */
431       if (AcquireImageColormap(image,(size_t) visual_info->colormap_size) == MagickFalse)
432         {
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);
439         }
440       for (i=0; i < (ssize_t) image->colors; i++)
441       {
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);
447       }
448       /*
449         Convert X image to PseudoClass packets.
450       */
451       for (y=0; y < (ssize_t) image->rows; y++)
452       {
453         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
454         if (q == (PixelPacket *) NULL)
455           break;
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)
461           break;
462         if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
463           break;
464       }
465       break;
466     }
467   }
468   colors=(XColor *) RelinquishMagickMemory(colors);
469   XDestroyImage(dps_image);
470   if (image->storage_class == PseudoClass)
471     (void) SyncImage(image);
472   /*
473     Rasterize matte image.
474   */
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))
478     {
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)
483         {
484           XImage
485             *matte_image;
486
487           /*
488             Initialize image matte.
489           */
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)
494             {
495               image->storage_class=DirectClass;
496               image->matte=MagickTrue;
497               for (y=0; y < (ssize_t) image->rows; y++)
498               {
499                 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
500                 if (q == (PixelPacket *) NULL)
501                   break;
502                 for (x=0; x < (ssize_t) image->columns; x++)
503                 {
504                   SetOpacityPixelComponent(q,OpaqueOpacity);
505                   if (XGetPixel(matte_image,x,y) == 0)
506                     SetOpacityPixelComponent(q,TransparentOpacity);
507                   q++;
508                 }
509                 if (SyncAuthenticPixels(image,exception) == MagickFalse)
510                   break;
511               }
512               XDestroyImage(matte_image);
513             }
514         }
515     }
516   /*
517     Relinquish resources.
518   */
519   XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
520     (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
521   (void) CloseBlob(image);
522   return(GetFirstImageInList(image));
523 }
524 #endif
525 \f
526 /*
527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528 %                                                                             %
529 %                                                                             %
530 %                                                                             %
531 %   R e g i s t e r D P S I m a g e                                           %
532 %                                                                             %
533 %                                                                             %
534 %                                                                             %
535 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
536 %
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.
543 %
544 %  The format of the RegisterDPSImage method is:
545 %
546 %      size_t RegisterDPSImage(void)
547 %
548 */
549 ModuleExport size_t RegisterDPSImage(void)
550 {
551   MagickInfo
552     *entry;
553
554   entry=SetMagickInfo("DPS");
555 #if defined(MAGICKCORE_DPS_DELEGATE)
556   entry->decoder=(DecodeImageHandler *) ReadDPSImage;
557 #endif
558   entry->blob_support=MagickFalse;
559   entry->description=ConstantString("Display Postscript Interpreter");
560   entry->module=ConstantString("DPS");
561   (void) RegisterMagickInfo(entry);
562   return(MagickImageCoderSignature);
563 }
564 \f
565 /*
566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 %                                                                             %
568 %                                                                             %
569 %                                                                             %
570 %   U n r e g i s t e r D P S I m a g e                                       %
571 %                                                                             %
572 %                                                                             %
573 %                                                                             %
574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575 %
576 %  UnregisterDPSImage() removes format registrations made by the
577 %  DPS module from the list of supported formats.
578 %
579 %  The format of the UnregisterDPSImage method is:
580 %
581 %      UnregisterDPSImage(void)
582 %
583 */
584 ModuleExport void UnregisterDPSImage(void)
585 {
586   (void) UnregisterMagickInfo("DPS");
587 }