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