root/ImageMagick/trunk/coders/dps.c

Revision 448, 19.5 KB (checked in by cristy, 4 weeks ago)
Line 
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-2009 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
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
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
94static inline double MagickMin(const double x,const double y)
95{
96  if (x < y)
97    return(x);
98  return(y);
99}
100
101static 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
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*/
545ModuleExport 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
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*/
580ModuleExport void UnregisterDPSImage(void)
581{
582  (void) UnregisterMagickInfo("DPS");
583}
Note: See TracBrowser for help on using the browser.