root / ImageMagick / trunk / coders / dps.c

Revision 12033, 19.4 kB (checked in by cristy, 7 days 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-2008 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  Display
104    *display;
105
106  float
107    pixels_per_point;
108
109  Image
110    *image;
111
112  int
113    sans,
114    status;
115
116  long
117    x,
118    y;
119
120  Pixmap
121    pixmap;
122
123  register IndexPacket
124    *indexes;
125
126  register long
127    i;
128
129  register PixelPacket
130    *q;
131
132  register unsigned long
133    pixel;
134
135  Screen
136    *screen;
137
138  XColor
139    *colors;
140
141  XImage
142    *dps_image;
143
144  XRectangle
145    page,
146    bits_per_pixel;
147
148  XResourceInfo
149    resource_info;
150
151  XrmDatabase
152    resource_database;
153
154  XStandardColormap
155    *map_info;
156
157  XVisualInfo
158    *visual_info;
159
160  /*
161    Open X server connection.
162  */
163  assert(image_info != (const ImageInfo *) NULL);
164  assert(image_info->signature == MagickSignature);
165  if (image_info->debug != MagickFalse)
166    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
167      image_info->filename);
168  assert(exception != (ExceptionInfo *) NULL);
169  assert(exception->signature == MagickSignature);
170  display=XOpenDisplay(image_info->server_name);
171  if (display == (Display *) NULL)
172    return((Image *) NULL);
173  /*
174    Set our forgiving exception handler.
175  */
176  (void) XSetErrorHandler(XError);
177  /*
178    Open image file.
179  */
180  image=AcquireImage(image_info);
181  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
182  if (status == MagickFalse)
183    return((Image *) NULL);
184  /*
185    Get user defaults from X resource database.
186  */
187  resource_database=XGetResourceDatabase(display,GetClientName());
188  XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
189  /*
190    Allocate standard colormap.
191  */
192  map_info=XAllocStandardColormap();
193  visual_info=(XVisualInfo *) NULL;
194  if (map_info == (XStandardColormap *) NULL)
195    ThrowReaderException(ResourceLimitError,"UnableToCreateStandardColormap")
196  else
197    {
198      /*
199        Initialize visual info.
200      */
201      (void) CloneString(&resource_info.visual_type,"default");
202      visual_info=XBestVisualInfo(display,map_info,&resource_info);
203      map_info->colormap=(Colormap) NULL;
204    }
205  if ((map_info == (XStandardColormap *) NULL) ||
206      (visual_info == (XVisualInfo *) NULL))
207    {
208      image=DestroyImage(image);
209      XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
210        (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
211      return((Image *) NULL);
212    }
213  /*
214    Create a pixmap the appropriate size for the image.
215  */
216  screen=ScreenOfDisplay(display,visual_info->screen);
217  pixels_per_point=XDPSPixelsPerPoint(screen);
218  if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
219    pixels_per_point=MagickMin(image->x_resolution,image->y_resolution)/
220      DefaultResolution;
221  status=XDPSCreatePixmapForEPSF((DPSContext) NULL,screen,
222    GetBlobFileHandle(image),visual_info->depth,pixels_per_point,&pixmap,
223    &bits_per_pixel,&page);
224  if ((status == dps_status_failure) || (status == dps_status_no_extension))
225    {
226      image=DestroyImage(image);
227      XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
228        (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
229      return((Image *) NULL);
230    }
231  /*
232    Rasterize the file into the pixmap.
233  */
234  status=XDPSImageFileIntoDrawable((DPSContext) NULL,screen,pixmap,
235    GetBlobFileHandle(image),(int) bits_per_pixel.height,visual_info->depth,
236    &page,-page.x,-page.y,pixels_per_point,MagickTrue,MagickFalse,MagickTrue,
237    &sans);
238  if (status != dps_status_success)
239    {
240      image=DestroyImage(image);
241      XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
242        (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
243      return((Image *) NULL);
244    }
245  /*
246    Initialize DPS X image.
247  */
248  dps_image=XGetImage(display,pixmap,0,0,bits_per_pixel.width,
249    bits_per_pixel.height,AllPlanes,ZPixmap);
250  (void) XFreePixmap(display,pixmap);
251  if (dps_image == (XImage *) NULL)
252    {
253      image=DestroyImage(image);
254      XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
255        (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
256      return((Image *) NULL);
257    }
258  /*
259    Get the colormap colors.
260  */
261  colors=(XColor *) AcquireQuantumMemory(visual_info->colormap_size,
262    sizeof(*colors));
263  if (colors == (XColor *) NULL)
264    {
265      image=DestroyImage(image);
266      XDestroyImage(dps_image);
267      XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
268        (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
269      return((Image *) NULL);
270    }
271  if ((visual_info->klass != DirectColor) && (visual_info->klass != TrueColor))
272    for (i=0; i < visual_info->colormap_size; i++)
273    {
274      colors[i].pixel=(unsigned long) i;
275      colors[i].pad=0;
276    }
277  else
278    {
279      unsigned long
280        blue,
281        blue_bit,
282        green,
283        green_bit,
284        red,
285        red_bit;
286
287      /*
288        DirectColor or TrueColor visual.
289      */
290      red=0;
291      green=0;
292      blue=0;
293      red_bit=visual_info->red_mask & (~(visual_info->red_mask)+1);
294      green_bit=visual_info->green_mask & (~(visual_info->green_mask)+1);
295      blue_bit=visual_info->blue_mask & (~(visual_info->blue_mask)+1);
296      for (i=0; i < visual_info->colormap_size; i++)
297      {
298        colors[i].pixel=red | green | blue;
299        colors[i].pad=0;
300        red+=red_bit;
301        if (red > visual_info->red_mask)
302          red=0;
303        green+=green_bit;
304        if (green > visual_info->green_mask)
305          green=0;
306        blue+=blue_bit;
307        if (blue > visual_info->blue_mask)
308          blue=0;
309      }
310    }
311  (void) XQueryColors(display,XDefaultColormap(display,visual_info->screen),
312    colors,visual_info->colormap_size);
313  /*
314    Convert X image to MIFF format.
315  */
316  if ((visual_info->klass != TrueColor) && (visual_info->klass != DirectColor))
317    image->storage_class=PseudoClass;
318  image->columns=(unsigned long) dps_image->width;
319  image->rows=(unsigned long) dps_image->height;
320  if (image_info->ping != MagickFalse)
321    {
322      (void) CloseBlob(image);
323      return(GetFirstImageInList(image));
324    }
325  if (SetImageExtent(image,0,0) == MagickFalse)
326    {
327      InheritException(exception,&image->exception);
328      return(DestroyImageList(image));
329    }
330  switch (image->storage_class)
331  {
332    case DirectClass:
333    default:
334    {
335      register unsigned long
336        color,
337        index;
338
339      unsigned long
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 < (long) image->rows; y++)
377        {
378          q=SetImagePixels(image,0,y,image->columns,1);
379          if (q == (PixelPacket *) NULL)
380            break;
381          for (x=0; x < (long) image->columns; x++)
382          {
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);
390            q++;
391          }
392          if (SyncImagePixels(image) == MagickFalse)
393            break;
394          if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
395            break;
396        }
397      else
398        for (y=0; y < (long) image->rows; y++)
399        {
400          q=SetImagePixels(image,0,y,image->columns,1);
401          if (q == (PixelPacket *) NULL)
402            break;
403          for (x=0; x < (long) 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            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);
415            q++;
416          }
417          if (SyncImagePixels(image) == MagickFalse)
418            break;
419          if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
420            break;
421        }
422      break;
423    }
424    case PseudoClass:
425    {
426      /*
427        Create colormap.
428      */
429      if (AcquireImageColormap(image,(unsigned long) visual_info->colormap_size) == MagickFalse)
430        {
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);
437        }
438      for (i=0; i < (long) image->colors; i++)
439      {
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);
445      }
446      /*
447        Convert X image to PseudoClass packets.
448      */
449      for (y=0; y < (long) image->rows; y++)
450      {
451        q=SetImagePixels(image,0,y,image->columns,1);
452        if (q == (PixelPacket *) NULL)
453          break;
454        indexes=GetIndexes(image);
455        for (x=0; x < (long) image->columns; x++)
456          indexes[x]=(unsigned short) XGetPixel(dps_image,x,y);
457        if (SyncImagePixels(image) == MagickFalse)
458          break;
459        if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
460          break;
461      }
462      break;
463    }
464  }
465  colors=(XColor *) RelinquishMagickMemory(colors);
466  XDestroyImage(dps_image);
467  if (image->storage_class == PseudoClass)
468    (void) SyncImage(image);
469  /*
470    Rasterize matte image.
471  */
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))
475    {
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)
480        {
481          XImage
482            *matte_image;
483
484          /*
485            Initialize image matte.
486          */
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)
491            {
492              image->storage_class=DirectClass;
493              image->matte=MagickTrue;
494              for (y=0; y < (long) image->rows; y++)
495              {
496                q=SetImagePixels(image,0,y,image->columns,1);
497                if (q == (PixelPacket *) NULL)
498                  break;
499                for (x=0; x < (long) image->columns; x++)
500                {
501                  q->opacity=OpaqueOpacity;
502                  if (XGetPixel(matte_image,x,y) == 0)
503                    q->opacity=TransparentOpacity;
504                  q++;
505                }
506                if (SyncImagePixels(image) == MagickFalse)
507                  break;
508              }
509              XDestroyImage(matte_image);
510            }
511        }
512    }
513  /*
514    Relinquish resources.
515  */
516  XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
517    (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
518  (void) CloseBlob(image);
519  return(GetFirstImageInList(image));
520}
521#endif
522
523/*
524%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
525%                                                                             %
526%                                                                             %
527%                                                                             %
528%   R e g i s t e r D P S I m a g e                                           %
529%                                                                             %
530%                                                                             %
531%                                                                             %
532%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533%
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.
540%
541%  The format of the RegisterDPSImage method is:
542%
543%      unsigned long RegisterDPSImage(void)
544%
545*/
546ModuleExport unsigned long RegisterDPSImage(void)
547{
548  MagickInfo
549    *entry;
550
551  entry=SetMagickInfo("DPS");
552#if defined(MAGICKCORE_DPS_DELEGATE)
553  entry->decoder=(DecodeImageHandler *) ReadDPSImage;
554#endif
555  entry->blob_support=MagickFalse;
556  entry->description=ConstantString("Display Postscript Interpreter");
557  entry->module=ConstantString("DPS");
558  (void) RegisterMagickInfo(entry);
559  return(MagickImageCoderSignature);
560}
561
562/*
563%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
564%                                                                             %
565%                                                                             %
566%                                                                             %
567%   U n r e g i s t e r D P S I m a g e                                       %
568%                                                                             %
569%                                                                             %
570%                                                                             %
571%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
572%
573%  UnregisterDPSImage() removes format registrations made by the
574%  DPS module from the list of supported formats.
575%
576%  The format of the UnregisterDPSImage method is:
577%
578%      UnregisterDPSImage(void)
579%
580*/
581ModuleExport void UnregisterDPSImage(void)
582{
583  (void) UnregisterMagickInfo("DPS");
584}
Note: See TracBrowser for help on using the browser.