]> granicus.if.org Git - imagemagick/blob - coders/emf.c
695effcacb53efb72f321cb1bb40c7741cae3a75
[imagemagick] / coders / emf.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                            EEEEE  M   M  FFFFF                              %
7 %                            E      MM MM  F                                  %
8 %                            EEE    M M M  FFF                                %
9 %                            E      M   M  F                                  %
10 %                            EEEEE  M   M  F                                  %
11 %                                                                             %
12 %                                                                             %
13 %                  Read Windows Enahanced Metafile Format                     %
14 %                                                                             %
15 %                              Software Design                                %
16 %                              Bill Radcliffe                                 %
17 %                                   2001                                      %
18 %                                                                             %
19 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
20 %  dedicated to making software imaging solutions freely available.           %
21 %                                                                             %
22 %  You may not use this file except in compliance with the License.  You may  %
23 %  obtain a copy of the License at                                            %
24 %                                                                             %
25 %    http://www.imagemagick.org/script/license.php                            %
26 %                                                                             %
27 %  Unless required by applicable law or agreed to in writing, software        %
28 %  distributed under the License is distributed on an "AS IS" BASIS,          %
29 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
30 %  See the License for the specific language governing permissions and        %
31 %  limitations under the License.                                             %
32 %                                                                             %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 */
35 \f
36 /*
37  * Include declarations.
38  */
39
40 #include "MagickCore/studio.h"
41 #if defined(MAGICKCORE_WINGDI32_DELEGATE) && defined(__CYGWIN__)
42 #  define MAGICKCORE_EMF_DELEGATE
43 #endif
44 #if defined(MAGICKCORE_EMF_DELEGATE)
45 #  if defined(__CYGWIN__)
46 #    include <windows.h>
47 #  else
48 #    include "MagickCore/nt-base-private.h"
49 #    include <wingdi.h>
50 #  endif
51 #endif
52 #include "MagickCore/blob.h"
53 #include "MagickCore/blob-private.h"
54 #include "MagickCore/cache.h"
55 #include "MagickCore/exception.h"
56 #include "MagickCore/exception-private.h"
57 #include "MagickCore/geometry.h"
58 #include "MagickCore/image.h"
59 #include "MagickCore/image-private.h"
60 #include "MagickCore/list.h"
61 #include "MagickCore/magick.h"
62 #include "MagickCore/memory_.h"
63 #include "MagickCore/pixel.h"
64 #include "MagickCore/pixel-accessor.h"
65 #include "MagickCore/quantum-private.h"
66 #include "MagickCore/static.h"
67 #include "MagickCore/string_.h"
68 #include "MagickCore/module.h"
69 \f
70 /*
71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 %                                                                             %
73 %                                                                             %
74 %                                                                             %
75 %   I s E F M                                                                 %
76 %                                                                             %
77 %                                                                             %
78 %                                                                             %
79 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80 %
81 %  IsEMF() returns MagickTrue if the image format type, identified by the
82 %  magick string, is a Microsoft Windows Enhanced MetaFile (EMF) file.
83 %
84 %  The format of the ReadEMFImage method is:
85 %
86 %      MagickBooleanType IsEMF(const unsigned char *magick,const size_t length)
87 %
88 %  A description of each parameter follows:
89 %
90 %    o magick: compare image format pattern against these bytes.
91 %
92 %    o length: Specifies the length of the magick string.
93 %
94 */
95 static MagickBooleanType IsEMF(const unsigned char *magick,const size_t length)
96 {
97   if (length < 48)
98     return(MagickFalse);
99   if (memcmp(magick+40,"\040\105\115\106\000\000\001\000",8) == 0)
100     return(MagickTrue);
101   return(MagickFalse);
102 }
103 \f
104 /*
105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 %                                                                             %
107 %                                                                             %
108 %                                                                             %
109 %   I s W M F                                                                 %
110 %                                                                             %
111 %                                                                             %
112 %                                                                             %
113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114 %
115 %  IsWMF() returns MagickTrue if the image format type, identified by the
116 %  magick string, is a Windows MetaFile (WMF) file.
117 %
118 %  The format of the ReadEMFImage method is:
119 %
120 %      MagickBooleanType IsEMF(const unsigned char *magick,const size_t length)
121 %
122 %  A description of each parameter follows:
123 %
124 %    o magick: compare image format pattern against these bytes.
125 %
126 %    o length: Specifies the length of the magick string.
127 %
128 */
129 static MagickBooleanType IsWMF(const unsigned char *magick,const size_t length)
130 {
131   if (length < 4)
132     return(MagickFalse);
133   if (memcmp(magick,"\327\315\306\232",4) == 0)
134     return(MagickTrue);
135   if (memcmp(magick,"\001\000\011\000",4) == 0)
136     return(MagickTrue);
137   return(MagickFalse);
138 }
139 \f
140 /*
141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 %                                                                             %
143 %                                                                             %
144 %                                                                             %
145 %  R e a d E M F I m a g e                                                    %
146 %                                                                             %
147 %                                                                             %
148 %                                                                             %
149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150 %
151 %  ReadEMFImage() reads an Microsoft Windows Enhanced MetaFile (EMF) or
152 %  Windows MetaFile (WMF) file using the Windows API and returns it.  It
153 %  allocates the memory necessary for the new Image structure and returns a
154 %  pointer to the new image.
155 %
156 %  The format of the ReadEMFImage method is:
157 %
158 %      Image *ReadEMFImage(const ImageInfo *image_info,
159 %        ExceptionInfo *exception)
160 %
161 %  A description of each parameter follows:
162 %
163 %    o image_info: the image info..
164 %
165 %    o exception: return any errors or warnings in this structure.
166 %
167 */
168
169
170 #if defined(MAGICKCORE_HAVE__WFOPEN)
171 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
172 {
173   register const unsigned char
174     *p;
175
176   if (utf16 != (wchar_t *) NULL)
177     {
178       register wchar_t
179         *q;
180
181       wchar_t
182         c;
183
184       /*
185         Convert UTF-8 to UTF-16.
186       */
187       q=utf16;
188       for (p=utf8; *p != '\0'; p++)
189       {
190         if ((*p & 0x80) == 0)
191           *q=(*p);
192         else
193           if ((*p & 0xE0) == 0xC0)
194             {
195               c=(*p);
196               *q=(c & 0x1F) << 6;
197               p++;
198               if ((*p & 0xC0) != 0x80)
199                 return(0);
200               *q|=(*p & 0x3F);
201             }
202           else
203             if ((*p & 0xF0) == 0xE0)
204               {
205                 c=(*p);
206                 *q=c << 12;
207                 p++;
208                 if ((*p & 0xC0) != 0x80)
209                   return(0);
210                 c=(*p);
211                 *q|=(c & 0x3F) << 6;
212                 p++;
213                 if ((*p & 0xC0) != 0x80)
214                   return(0);
215                 *q|=(*p & 0x3F);
216               }
217             else
218               return(0);
219         q++;
220       }
221       *q++='\0';
222       return(q-utf16);
223     }
224   /*
225     Compute UTF-16 string length.
226   */
227   for (p=utf8; *p != '\0'; p++)
228   {
229     if ((*p & 0x80) == 0)
230       ;
231     else
232       if ((*p & 0xE0) == 0xC0)
233         {
234           p++;
235           if ((*p & 0xC0) != 0x80)
236             return(0);
237         }
238       else
239         if ((*p & 0xF0) == 0xE0)
240           {
241             p++;
242             if ((*p & 0xC0) != 0x80)
243               return(0);
244             p++;
245             if ((*p & 0xC0) != 0x80)
246               return(0);
247          }
248        else
249          return(0);
250   }
251   return(p-utf8);
252 }
253
254 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source)
255 {
256   size_t
257     length;
258
259   wchar_t
260     *utf16;
261
262   length=UTF8ToUTF16(source,(wchar_t *) NULL);
263   if (length == 0)
264     {
265       register ssize_t
266         i;
267
268       /*
269         Not UTF-8, just copy.
270       */
271       length=strlen((char *) source);
272       utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
273       if (utf16 == (wchar_t *) NULL)
274         return((wchar_t *) NULL);
275       for (i=0; i <= (ssize_t) length; i++)
276         utf16[i]=source[i];
277       return(utf16);
278     }
279   utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
280   if (utf16 == (wchar_t *) NULL)
281     return((wchar_t *) NULL);
282   length=UTF8ToUTF16(source,utf16);
283   return(utf16);
284 }
285 #endif
286
287 /*
288   This method reads either an enhanced metafile, a regular 16bit Windows
289   metafile, or an Aldus Placeable metafile and converts it into an enhanced
290   metafile.  Width and height are returned in .01mm units.
291 */
292 #if defined(MAGICKCORE_EMF_DELEGATE)
293 static HENHMETAFILE ReadEnhMetaFile(const char *path,ssize_t *width,
294   ssize_t *height)
295 {
296 #pragma pack( push, 2 )
297   typedef struct
298   {
299     DWORD dwKey;
300     WORD hmf;
301     SMALL_RECT bbox;
302     WORD wInch;
303     DWORD dwReserved;
304     WORD wCheckSum;
305   } APMHEADER, *PAPMHEADER;
306 #pragma pack( pop )
307
308   DWORD
309     dwSize;
310
311   ENHMETAHEADER
312     emfh;
313
314   HANDLE
315     hFile;
316
317   HDC
318     hDC;
319
320   HENHMETAFILE
321     hTemp;
322
323   LPBYTE
324     pBits;
325
326   METAFILEPICT
327     mp;
328
329   HMETAFILE
330     hOld;
331
332   *width=512;
333   *height=512;
334   hTemp=GetEnhMetaFile(path);
335 #if defined(MAGICKCORE_HAVE__WFOPEN)
336   if (hTemp == (HENHMETAFILE) NULL)
337     {
338       wchar_t
339         *unicode_path;
340
341       unicode_path=ConvertUTF8ToUTF16((const unsigned char *) path);
342       if (unicode_path != (wchar_t *) NULL)
343         {
344           hTemp=GetEnhMetaFileW(unicode_path);
345           unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
346         }
347     }
348 #endif
349   if (hTemp != (HENHMETAFILE) NULL)
350     {
351       /*
352         Enhanced metafile.
353       */
354       GetEnhMetaFileHeader(hTemp,sizeof(ENHMETAHEADER),&emfh);
355       *width=emfh.rclFrame.right-emfh.rclFrame.left;
356       *height=emfh.rclFrame.bottom-emfh.rclFrame.top;
357       return(hTemp);
358     }
359   hOld=GetMetaFile(path);
360   if (hOld != (HMETAFILE) NULL)
361     {
362       /*
363         16bit windows metafile.
364       */
365       dwSize=GetMetaFileBitsEx(hOld,0,NULL);
366       if (dwSize == 0)
367         {
368           DeleteMetaFile(hOld);
369           return((HENHMETAFILE) NULL);
370         }
371       pBits=(LPBYTE) AcquireQuantumMemory(dwSize,sizeof(*pBits));
372       if (pBits == (LPBYTE) NULL)
373         {
374           DeleteMetaFile(hOld);
375           return((HENHMETAFILE) NULL);
376         }
377       if (GetMetaFileBitsEx(hOld,dwSize,pBits) == 0)
378         {
379           pBits=(BYTE *) DestroyString((char *) pBits);
380           DeleteMetaFile(hOld);
381           return((HENHMETAFILE) NULL);
382         }
383       /*
384         Make an enhanced metafile from the windows metafile.
385       */
386       mp.mm=MM_ANISOTROPIC;
387       mp.xExt=1000;
388       mp.yExt=1000;
389       mp.hMF=NULL;
390       hDC=GetDC(NULL);
391       hTemp=SetWinMetaFileBits(dwSize,pBits,hDC,&mp);
392       ReleaseDC(NULL,hDC);
393       DeleteMetaFile(hOld);
394       pBits=(BYTE *) DestroyString((char *) pBits);
395       GetEnhMetaFileHeader(hTemp,sizeof(ENHMETAHEADER),&emfh);
396       *width=emfh.rclFrame.right-emfh.rclFrame.left;
397       *height=emfh.rclFrame.bottom-emfh.rclFrame.top;
398       return(hTemp);
399     }
400   /*
401     Aldus Placeable metafile.
402   */
403   hFile=CreateFile(path,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,
404     NULL);
405   if (hFile == INVALID_HANDLE_VALUE)
406     return(NULL);
407   dwSize=GetFileSize(hFile,NULL);
408   pBits=(LPBYTE) AcquireQuantumMemory(dwSize,sizeof(*pBits));
409   ReadFile(hFile,pBits,dwSize,&dwSize,NULL);
410   CloseHandle(hFile);
411   if (((PAPMHEADER) pBits)->dwKey != 0x9ac6cdd7l)
412     {
413       pBits=(BYTE *) DestroyString((char *) pBits);
414       return((HENHMETAFILE) NULL);
415     }
416   /*
417     Make an enhanced metafile from the placable metafile.
418   */
419   mp.mm=MM_ANISOTROPIC;
420   mp.xExt=((PAPMHEADER) pBits)->bbox.Right-((PAPMHEADER) pBits)->bbox.Left;
421   *width=mp.xExt;
422   mp.xExt=(mp.xExt*2540l)/(DWORD) (((PAPMHEADER) pBits)->wInch);
423   mp.yExt=((PAPMHEADER)pBits)->bbox.Bottom-((PAPMHEADER) pBits)->bbox.Top;
424   *height=mp.yExt;
425   mp.yExt=(mp.yExt*2540l)/(DWORD) (((PAPMHEADER) pBits)->wInch);
426   mp.hMF=NULL;
427   hDC=GetDC(NULL);
428   hTemp=SetWinMetaFileBits(dwSize,&(pBits[sizeof(APMHEADER)]),hDC,&mp);
429   ReleaseDC(NULL,hDC);
430   pBits=(BYTE *) DestroyString((char *) pBits);
431   return(hTemp);
432 }
433
434 #define CENTIMETERS_INCH 2.54
435
436 static Image *ReadEMFImage(const ImageInfo *image_info,
437   ExceptionInfo *exception)
438 {
439   BITMAPINFO
440     DIBinfo;
441
442   HBITMAP
443     hBitmap,
444     hOldBitmap;
445
446   HDC
447     hDC;
448
449   HENHMETAFILE
450     hemf;
451
452   Image
453     *image;
454
455   RECT
456     rect;
457
458   register ssize_t
459     x;
460
461   register Quantum
462     *q;
463
464   RGBQUAD
465     *pBits,
466     *ppBits;
467
468   ssize_t
469     height,
470     width,
471     y;
472
473   image=AcquireImage(image_info,exception);
474   hemf=ReadEnhMetaFile(image_info->filename,&width,&height);
475   if (hemf == (HENHMETAFILE) NULL)
476     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
477   if ((image->columns == 0) || (image->rows == 0))
478     {
479       double
480         y_resolution,
481         x_resolution;
482
483       y_resolution=DefaultResolution;
484       x_resolution=DefaultResolution;
485       if (image->resolution.y > 0)
486         {
487           y_resolution=image->resolution.y;
488           if (image->units == PixelsPerCentimeterResolution)
489             y_resolution*=CENTIMETERS_INCH;
490         }
491       if (image->resolution.x > 0)
492         {
493           x_resolution=image->resolution.x;
494           if (image->units == PixelsPerCentimeterResolution)
495             x_resolution*=CENTIMETERS_INCH;
496         }
497       image->rows=(size_t) ((height/1000.0/CENTIMETERS_INCH)*y_resolution+0.5);
498       image->columns=(size_t) ((width/1000.0/CENTIMETERS_INCH)*
499         x_resolution+0.5);
500     }
501   if (image_info->size != (char *) NULL)
502     {
503       ssize_t
504         x;
505
506       image->columns=width;
507       image->rows=height;
508       x=0;
509       y=0;
510       (void) GetGeometry(image_info->size,&x,&y,&image->columns,&image->rows);
511     }
512   if (image_info->page != (char *) NULL)
513     {
514       char
515         *geometry;
516
517       register char
518         *p;
519
520       MagickStatusType
521         flags;
522
523       ssize_t
524         sans;
525
526       geometry=GetPageGeometry(image_info->page);
527       p=strchr(geometry,'>');
528       if (p == (char *) NULL)
529         {
530           flags=ParseMetaGeometry(geometry,&sans,&sans,&image->columns,
531             &image->rows);
532           if (image->resolution.x != 0.0)
533             image->columns=(size_t) floor((image->columns*image->resolution.x)+
534               0.5);
535           if (image->resolution.y != 0.0)
536             image->rows=(size_t) floor((image->rows*image->resolution.y)+0.5);
537         }
538       else
539         {
540           *p='\0';
541           flags=ParseMetaGeometry(geometry,&sans,&sans,&image->columns,
542             &image->rows);
543           if (image->resolution.x != 0.0)
544             image->columns=(size_t) floor(((image->columns*image->resolution.x)/
545               DefaultResolution)+0.5);
546           if (image->resolution.y != 0.0)
547             image->rows=(size_t) floor(((image->rows*image->resolution.y)/
548               DefaultResolution)+0.5);
549         }
550       (void) flags;
551       geometry=DestroyString(geometry);
552     }
553   hDC=GetDC(NULL);
554   if (hDC == (HDC) NULL)
555     {
556       DeleteEnhMetaFile(hemf);
557       ThrowReaderException(ResourceLimitError,"UnableToCreateADC");
558     }
559   /*
560     Initialize the bitmap header info.
561   */
562   (void) ResetMagickMemory(&DIBinfo,0,sizeof(BITMAPINFO));
563   DIBinfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
564   DIBinfo.bmiHeader.biWidth=(LONG) image->columns;
565   DIBinfo.bmiHeader.biHeight=(-1)*(LONG) image->rows;
566   DIBinfo.bmiHeader.biPlanes=1;
567   DIBinfo.bmiHeader.biBitCount=32;
568   DIBinfo.bmiHeader.biCompression=BI_RGB;
569   hBitmap=CreateDIBSection(hDC,&DIBinfo,DIB_RGB_COLORS,(void **) &ppBits,NULL,
570     0);
571   ReleaseDC(NULL,hDC);
572   if (hBitmap == (HBITMAP) NULL)
573     {
574       DeleteEnhMetaFile(hemf);
575       ThrowReaderException(ResourceLimitError,"UnableToCreateBitmap");
576     }
577   hDC=CreateCompatibleDC(NULL);
578   if (hDC == (HDC) NULL)
579     {
580       DeleteEnhMetaFile(hemf);
581       DeleteObject(hBitmap);
582       ThrowReaderException(ResourceLimitError,"UnableToCreateADC");
583     }
584   hOldBitmap=(HBITMAP) SelectObject(hDC,hBitmap);
585   if (hOldBitmap == (HBITMAP) NULL)
586     {
587       DeleteEnhMetaFile(hemf);
588       DeleteDC(hDC);
589       DeleteObject(hBitmap);
590       ThrowReaderException(ResourceLimitError,"UnableToCreateBitmap");
591     }
592   /*
593     Initialize the bitmap to the image background color.
594   */
595   pBits=ppBits;
596   for (y=0; y < (ssize_t) image->rows; y++)
597   {
598     for (x=0; x < (ssize_t) image->columns; x++)
599     {
600       pBits->rgbRed=ScaleQuantumToChar(image->background_color.red);
601       pBits->rgbGreen=ScaleQuantumToChar(image->background_color.green);
602       pBits->rgbBlue=ScaleQuantumToChar(image->background_color.blue);
603       pBits++;
604     }
605   }
606   rect.top=0;
607   rect.left=0;
608   rect.right=(LONG) image->columns;
609   rect.bottom=(LONG) image->rows;
610   /*
611     Convert metafile pixels.
612   */
613   PlayEnhMetaFile(hDC,hemf,&rect);
614   pBits=ppBits;
615   for (y=0; y < (ssize_t) image->rows; y++)
616   {
617     q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
618     if (q == (Quantum *) NULL)
619       break;
620     for (x=0; x < (ssize_t) image->columns; x++)
621     {
622       SetPixelRed(image,ScaleCharToQuantum(pBits->rgbRed),q);
623       SetPixelGreen(image,ScaleCharToQuantum(pBits->rgbGreen),q);
624       SetPixelBlue(image,ScaleCharToQuantum(pBits->rgbBlue),q);
625       SetPixelAlpha(image,OpaqueAlpha,q);
626       pBits++;
627       q+=GetPixelChannels(image);
628     }
629     if (SyncAuthenticPixels(image,exception) == MagickFalse)
630       break;
631   }
632   DeleteEnhMetaFile(hemf);
633   SelectObject(hDC,hOldBitmap);
634   DeleteDC(hDC);
635   DeleteObject(hBitmap);
636   return(GetFirstImageInList(image));
637 }
638 #endif /* MAGICKCORE_EMF_DELEGATE */
639 \f
640 /*
641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
642 %                                                                             %
643 %                                                                             %
644 %                                                                             %
645 %   R e g i s t e r E M F I m a g e                                           %
646 %                                                                             %
647 %                                                                             %
648 %                                                                             %
649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
650 %
651 %  RegisterEMFImage() adds attributes for the EMF image format to
652 %  the list of supported formats.  The attributes include the image format
653 %  tag, a method to read and/or write the format, whether the format
654 %  supports the saving of more than one frame to the same file or blob,
655 %  whether the format supports native in-memory I/O, and a brief
656 %  description of the format.
657 %
658 %  The format of the RegisterEMFImage method is:
659 %
660 %      size_t RegisterEMFImage(void)
661 %
662 */
663 ModuleExport size_t RegisterEMFImage(void)
664 {
665   MagickInfo
666     *entry;
667
668   entry=SetMagickInfo("EMF");
669 #if defined(MAGICKCORE_EMF_DELEGATE)
670   entry->decoder=ReadEMFImage;
671 #endif
672   entry->description=ConstantString(
673     "Windows WIN32 API rendered Enhanced Meta File");
674   entry->magick=(IsImageFormatHandler *) IsEMF;
675   entry->blob_support=MagickFalse;
676   entry->module=ConstantString("WMF");
677   (void) RegisterMagickInfo(entry);
678   entry=SetMagickInfo("WMFWIN32");
679 #if defined(MAGICKCORE_EMF_DELEGATE)
680   entry->decoder=ReadEMFImage;
681 #endif
682   entry->description=ConstantString("Windows WIN32 API rendered Meta File");
683   entry->magick=(IsImageFormatHandler *) IsWMF;
684   entry->blob_support=MagickFalse;
685   entry->module=ConstantString("WMFWIN32");
686   (void) RegisterMagickInfo(entry);
687   return(MagickImageCoderSignature);
688 }
689 \f
690 /*
691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
692 %                                                                             %
693 %                                                                             %
694 %                                                                             %
695 %   U n r e g i s t e r E M F I m a g e                                       %
696 %                                                                             %
697 %                                                                             %
698 %                                                                             %
699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
700 %
701 %  UnregisterEMFImage() removes format registrations made by the
702 %  EMF module from the list of supported formats.
703 %
704 %  The format of the UnregisterEMFImage method is:
705 %
706 %      UnregisterEMFImage(void)
707 %
708 */
709 ModuleExport void UnregisterEMFImage(void)
710 {
711   (void) UnregisterMagickInfo("EMF");
712   (void) UnregisterMagickInfo("WMFWIN32");
713 }