]> 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-2011 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       geometry=DestroyString(geometry);
548     }
549   hDC=GetDC(NULL);
550   if (hDC == (HDC) NULL)
551     {
552       DeleteEnhMetaFile(hemf);
553       ThrowReaderException(ResourceLimitError,"UnableToCreateADC");
554     }
555   /*
556     Initialize the bitmap header info.
557   */
558   (void) ResetMagickMemory(&DIBinfo,0,sizeof(BITMAPINFO));
559   DIBinfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
560   DIBinfo.bmiHeader.biWidth=(LONG) image->columns;
561   DIBinfo.bmiHeader.biHeight=(-1)*(LONG) image->rows;
562   DIBinfo.bmiHeader.biPlanes=1;
563   DIBinfo.bmiHeader.biBitCount=32;
564   DIBinfo.bmiHeader.biCompression=BI_RGB;
565   hBitmap=CreateDIBSection(hDC,&DIBinfo,DIB_RGB_COLORS,(void **) &ppBits,NULL,
566     0);
567   ReleaseDC(NULL,hDC);
568   if (hBitmap == (HBITMAP) NULL)
569     {
570       DeleteEnhMetaFile(hemf);
571       ThrowReaderException(ResourceLimitError,"UnableToCreateBitmap");
572     }
573   hDC=CreateCompatibleDC(NULL);
574   if (hDC == (HDC) NULL)
575     {
576       DeleteEnhMetaFile(hemf);
577       DeleteObject(hBitmap);
578       ThrowReaderException(ResourceLimitError,"UnableToCreateADC");
579     }
580   hOldBitmap=(HBITMAP) SelectObject(hDC,hBitmap);
581   if (hOldBitmap == (HBITMAP) NULL)
582     {
583       DeleteEnhMetaFile(hemf);
584       DeleteDC(hDC);
585       DeleteObject(hBitmap);
586       ThrowReaderException(ResourceLimitError,"UnableToCreateBitmap");
587     }
588   /*
589     Initialize the bitmap to the image background color.
590   */
591   pBits=ppBits;
592   for (y=0; y < (ssize_t) image->rows; y++)
593   {
594     for (x=0; x < (ssize_t) image->columns; x++)
595     {
596       pBits->rgbRed=ScaleQuantumToChar(image->background_color.red);
597       pBits->rgbGreen=ScaleQuantumToChar(image->background_color.green);
598       pBits->rgbBlue=ScaleQuantumToChar(image->background_color.blue);
599       pBits++;
600     }
601   }
602   rect.top=0;
603   rect.left=0;
604   rect.right=(LONG) image->columns;
605   rect.bottom=(LONG) image->rows;
606   /*
607     Convert metafile pixels.
608   */
609   PlayEnhMetaFile(hDC,hemf,&rect);
610   pBits=ppBits;
611   for (y=0; y < (ssize_t) image->rows; y++)
612   {
613     q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
614     if (q == (Quantum *) NULL)
615       break;
616     for (x=0; x < (ssize_t) image->columns; x++)
617     {
618       SetPixelRed(image,ScaleCharToQuantum(pBits->rgbRed),q);
619       SetPixelGreen(image,ScaleCharToQuantum(pBits->rgbGreen),q);
620       SetPixelBlue(image,ScaleCharToQuantum(pBits->rgbBlue),q);
621       SetPixelAlpha(image,OpaqueAlpha,q);
622       pBits++;
623       q+=GetPixelChannels(image);
624     }
625     if (SyncAuthenticPixels(image,exception) == MagickFalse)
626       break;
627   }
628   DeleteEnhMetaFile(hemf);
629   SelectObject(hDC,hOldBitmap);
630   DeleteDC(hDC);
631   DeleteObject(hBitmap);
632   return(GetFirstImageInList(image));
633 }
634 #endif /* MAGICKCORE_WINGDI32_DELEGATE */
635 \f
636 /*
637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
638 %                                                                             %
639 %                                                                             %
640 %                                                                             %
641 %   R e g i s t e r E M F I m a g e                                           %
642 %                                                                             %
643 %                                                                             %
644 %                                                                             %
645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646 %
647 %  RegisterEMFImage() adds attributes for the EMF image format to
648 %  the list of supported formats.  The attributes include the image format
649 %  tag, a method to read and/or write the format, whether the format
650 %  supports the saving of more than one frame to the same file or blob,
651 %  whether the format supports native in-memory I/O, and a brief
652 %  description of the format.
653 %
654 %  The format of the RegisterEMFImage method is:
655 %
656 %      size_t RegisterEMFImage(void)
657 %
658 */
659 ModuleExport size_t RegisterEMFImage(void)
660 {
661   MagickInfo
662     *entry;
663
664   entry=SetMagickInfo("EMF");
665 #if defined(MAGICKCORE_WINGDI32_DELEGATE)
666   entry->decoder=ReadEMFImage;
667 #endif
668   entry->description=ConstantString(
669     "Windows WIN32 API rendered Enhanced Meta File");
670   entry->magick=(IsImageFormatHandler *) IsEMF;
671   entry->blob_support=MagickFalse;
672   entry->module=ConstantString("WMF");
673   (void) RegisterMagickInfo(entry);
674   entry=SetMagickInfo("WMFWIN32");
675 #if defined(MAGICKCORE_WINGDI32_DELEGATE)
676   entry->decoder=ReadEMFImage;
677 #endif
678   entry->description=ConstantString("Windows WIN32 API rendered Meta File");
679   entry->magick=(IsImageFormatHandler *) IsWMF;
680   entry->blob_support=MagickFalse;
681   entry->module=ConstantString("WMFWIN32");
682   (void) RegisterMagickInfo(entry);
683   return(MagickImageCoderSignature);
684 }
685 \f
686 /*
687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
688 %                                                                             %
689 %                                                                             %
690 %                                                                             %
691 %   U n r e g i s t e r E M F I m a g e                                       %
692 %                                                                             %
693 %                                                                             %
694 %                                                                             %
695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
696 %
697 %  UnregisterEMFImage() removes format registrations made by the
698 %  EMF module from the list of supported formats.
699 %
700 %  The format of the UnregisterEMFImage method is:
701 %
702 %      UnregisterEMFImage(void)
703 %
704 */
705 ModuleExport void UnregisterEMFImage(void)
706 {
707   (void) UnregisterMagickInfo("EMF");
708   (void) UnregisterMagickInfo("WMFWIN32");
709 }