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