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