blob: 638d306158452412fb91fc1d89e0c7ace75d16cf [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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% %
cristy45ef08f2012-12-07 13:13:34 +000019% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000020% 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
36/*
37 * Include declarations.
38 */
39
cristy4c08aed2011-07-01 19:47:50 +000040#include "MagickCore/studio.h"
cristy2dfb1df2012-02-25 14:16:09 +000041#if defined(MAGICKCORE_WINGDI32_DELEGATE) && defined(__CYGWIN__)
42# define MAGICKCORE_EMF_DELEGATE
43#endif
44#if defined(MAGICKCORE_EMF_DELEGATE)
cristy3ed852e2009-09-05 21:47:34 +000045# if defined(__CYGWIN__)
46# include <windows.h>
47# else
cristyb5ae05b2012-10-02 18:17:25 +000048# include "MagickCore/nt-base-private.h"
cristy3ed852e2009-09-05 21:47:34 +000049# include <wingdi.h>
50# endif
51#endif
cristy4c08aed2011-07-01 19:47:50 +000052#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"
cristy6c9c9e82011-08-05 14:27:57 +000064#include "MagickCore/pixel-accessor.h"
cristy4c08aed2011-07-01 19:47:50 +000065#include "MagickCore/quantum-private.h"
66#include "MagickCore/static.h"
67#include "MagickCore/string_.h"
68#include "MagickCore/module.h"
cristy3ed852e2009-09-05 21:47:34 +000069
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*/
95static 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
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*/
129static 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
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
cristy0bd2bc52011-08-10 02:47:13 +0000169
170#if defined(MAGICKCORE_HAVE__WFOPEN)
171static 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
254static 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
cristy3ed852e2009-09-05 21:47:34 +0000287/*
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*/
cristy2dfb1df2012-02-25 14:16:09 +0000292#if defined(MAGICKCORE_EMF_DELEGATE)
cristybb503372010-05-27 20:51:26 +0000293static HENHMETAFILE ReadEnhMetaFile(const char *path,ssize_t *width,
294 ssize_t *height)
cristy3ed852e2009-09-05 21:47:34 +0000295{
cristy1f9e1ed2009-11-18 04:09:38 +0000296#pragma pack( push, 2 )
cristy3ed852e2009-09-05 21:47:34 +0000297 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
cristy0bd2bc52011-08-10 02:47:13 +0000341 unicode_path=ConvertUTF8ToUTF16((const unsigned char *) path);
cristy3ed852e2009-09-05 21:47:34 +0000342 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
436static 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
cristy3ed852e2009-09-05 21:47:34 +0000455 RECT
456 rect;
457
cristybb503372010-05-27 20:51:26 +0000458 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000459 x;
460
cristy4c08aed2011-07-01 19:47:50 +0000461 register Quantum
cristy3ed852e2009-09-05 21:47:34 +0000462 *q;
463
464 RGBQUAD
465 *pBits,
466 *ppBits;
467
cristy202de442011-04-24 18:19:07 +0000468 ssize_t
469 height,
470 width,
471 y;
472
cristy9950d572011-10-01 18:22:35 +0000473 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000474 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;
cristy2a11bef2011-10-28 18:33:11 +0000485 if (image->resolution.y > 0)
cristy3ed852e2009-09-05 21:47:34 +0000486 {
cristy2a11bef2011-10-28 18:33:11 +0000487 y_resolution=image->resolution.y;
cristy3ed852e2009-09-05 21:47:34 +0000488 if (image->units == PixelsPerCentimeterResolution)
489 y_resolution*=CENTIMETERS_INCH;
490 }
cristy2a11bef2011-10-28 18:33:11 +0000491 if (image->resolution.x > 0)
cristy3ed852e2009-09-05 21:47:34 +0000492 {
cristy2a11bef2011-10-28 18:33:11 +0000493 x_resolution=image->resolution.x;
cristy3ed852e2009-09-05 21:47:34 +0000494 if (image->units == PixelsPerCentimeterResolution)
495 x_resolution*=CENTIMETERS_INCH;
496 }
cristy202de442011-04-24 18:19:07 +0000497 image->rows=(size_t) ((height/1000.0/CENTIMETERS_INCH)*y_resolution+0.5);
cristybb503372010-05-27 20:51:26 +0000498 image->columns=(size_t) ((width/1000.0/CENTIMETERS_INCH)*
cristy3ed852e2009-09-05 21:47:34 +0000499 x_resolution+0.5);
500 }
501 if (image_info->size != (char *) NULL)
502 {
cristybb503372010-05-27 20:51:26 +0000503 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000504 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
cristy3ed852e2009-09-05 21:47:34 +0000517 register char
518 *p;
519
520 MagickStatusType
521 flags;
522
cristy202de442011-04-24 18:19:07 +0000523 ssize_t
524 sans;
525
cristy3ed852e2009-09-05 21:47:34 +0000526 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);
cristy2a11bef2011-10-28 18:33:11 +0000532 if (image->resolution.x != 0.0)
533 image->columns=(size_t) floor((image->columns*image->resolution.x)+
cristy06609ee2010-03-17 20:21:27 +0000534 0.5);
cristy2a11bef2011-10-28 18:33:11 +0000535 if (image->resolution.y != 0.0)
536 image->rows=(size_t) floor((image->rows*image->resolution.y)+0.5);
cristy3ed852e2009-09-05 21:47:34 +0000537 }
538 else
539 {
540 *p='\0';
541 flags=ParseMetaGeometry(geometry,&sans,&sans,&image->columns,
542 &image->rows);
cristy2a11bef2011-10-28 18:33:11 +0000543 if (image->resolution.x != 0.0)
544 image->columns=(size_t) floor(((image->columns*image->resolution.x)/
cristy202de442011-04-24 18:19:07 +0000545 DefaultResolution)+0.5);
cristy2a11bef2011-10-28 18:33:11 +0000546 if (image->resolution.y != 0.0)
547 image->rows=(size_t) floor(((image->rows*image->resolution.y)/
cristy202de442011-04-24 18:19:07 +0000548 DefaultResolution)+0.5);
cristy3ed852e2009-09-05 21:47:34 +0000549 }
cristy32cacff2011-12-31 03:36:27 +0000550 (void) flags;
cristy3ed852e2009-09-05 21:47:34 +0000551 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);
cristyeaedf062010-05-29 22:36:02 +0000564 DIBinfo.bmiHeader.biWidth=(LONG) image->columns;
565 DIBinfo.bmiHeader.biHeight=(-1)*(LONG) image->rows;
cristy3ed852e2009-09-05 21:47:34 +0000566 DIBinfo.bmiHeader.biPlanes=1;
567 DIBinfo.bmiHeader.biBitCount=32;
568 DIBinfo.bmiHeader.biCompression=BI_RGB;
cristy202de442011-04-24 18:19:07 +0000569 hBitmap=CreateDIBSection(hDC,&DIBinfo,DIB_RGB_COLORS,(void **) &ppBits,NULL,
570 0);
cristy3ed852e2009-09-05 21:47:34 +0000571 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;
cristybb503372010-05-27 20:51:26 +0000596 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000597 {
cristybb503372010-05-27 20:51:26 +0000598 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000599 {
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;
cristyeaedf062010-05-29 22:36:02 +0000608 rect.right=(LONG) image->columns;
609 rect.bottom=(LONG) image->rows;
cristy3ed852e2009-09-05 21:47:34 +0000610 /*
611 Convert metafile pixels.
612 */
613 PlayEnhMetaFile(hDC,hemf,&rect);
614 pBits=ppBits;
cristybb503372010-05-27 20:51:26 +0000615 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000616 {
617 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000618 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000619 break;
cristybb503372010-05-27 20:51:26 +0000620 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000621 {
cristy4c08aed2011-07-01 19:47:50 +0000622 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);
cristy3ed852e2009-09-05 21:47:34 +0000626 pBits++;
cristyed231572011-07-14 02:18:59 +0000627 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000628 }
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}
cristy2dfb1df2012-02-25 14:16:09 +0000638#endif /* MAGICKCORE_EMF_DELEGATE */
cristy3ed852e2009-09-05 21:47:34 +0000639
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%
cristybb503372010-05-27 20:51:26 +0000660% size_t RegisterEMFImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000661%
662*/
cristybb503372010-05-27 20:51:26 +0000663ModuleExport size_t RegisterEMFImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000664{
665 MagickInfo
666 *entry;
667
668 entry=SetMagickInfo("EMF");
cristy2dfb1df2012-02-25 14:16:09 +0000669#if defined(MAGICKCORE_EMF_DELEGATE)
cristy3ed852e2009-09-05 21:47:34 +0000670 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");
cristy2dfb1df2012-02-25 14:16:09 +0000679#if defined(MAGICKCORE_EMF_DELEGATE)
cristy3ed852e2009-09-05 21:47:34 +0000680 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
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*/
709ModuleExport void UnregisterEMFImage(void)
710{
711 (void) UnregisterMagickInfo("EMF");
712 (void) UnregisterMagickInfo("WMFWIN32");
713}