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% Dirk Lemstra % 19% January 2014 % 20% % 21% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 22% dedicated to making software imaging solutions freely available. % 23% % 24% You may not use this file except in compliance with the License. You may % 25% obtain a copy of the License at % 26% % 27% http://www.imagemagick.org/script/license.php % 28% % 29% Unless required by applicable law or agreed to in writing, software % 30% distributed under the License is distributed on an "AS IS" BASIS, % 31% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 32% See the License for the specific language governing permissions and % 33% limitations under the License. % 34% % 35%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36*/ 37 38/* 39 * Include declarations. 40 */ 41 42#include "MagickCore/studio.h" 43#if defined(MAGICKCORE_WINGDI32_DELEGATE) 44# if !defined(_MSC_VER) 45# if defined(__CYGWIN__) 46# include <windows.h> 47# else 48# include <wingdi.h> 49# endif 50# else 51#pragma warning(disable: 4457) 52#pragma warning(disable: 4458) 53# include <gdiplus.h> 54#pragma warning(default: 4457) 55#pragma warning(default: 4458) 56# pragma comment(lib, "gdiplus.lib") 57# endif 58#endif 59#include "MagickCore/blob.h" 60#include "MagickCore/blob-private.h" 61#include "MagickCore/cache.h" 62#include "MagickCore/exception.h" 63#include "MagickCore/exception-private.h" 64#include "MagickCore/geometry.h" 65#include "MagickCore/image.h" 66#include "MagickCore/image-private.h" 67#include "MagickCore/list.h" 68#include "MagickCore/magick.h" 69#include "MagickCore/memory_.h" 70#include "MagickCore/pixel.h" 71#include "MagickCore/pixel-accessor.h" 72#include "MagickCore/quantum-private.h" 73#include "MagickCore/static.h" 74#include "MagickCore/string_.h" 75#include "MagickCore/module.h" 76 77/* 78%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 79% % 80% % 81% % 82% I s E F M % 83% % 84% % 85% % 86%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 87% 88% IsEMF() returns MagickTrue if the image format type, identified by the 89% magick string, is a Microsoft Windows Enhanced MetaFile (EMF) file. 90% 91% The format of the ReadEMFImage method is: 92% 93% MagickBooleanType IsEMF(const unsigned char *magick,const size_t length) 94% 95% A description of each parameter follows: 96% 97% o magick: compare image format pattern against these bytes. 98% 99% o length: Specifies the length of the magick string. 100% 101*/ 102static MagickBooleanType IsEMF(const unsigned char *magick,const size_t length) 103{ 104 if (length < 48) 105 return(MagickFalse); 106 if (memcmp(magick+40,"\040\105\115\106\000\000\001\000",8) == 0) 107 return(MagickTrue); 108 return(MagickFalse); 109} 110 111/* 112%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 113% % 114% % 115% % 116% I s W M F % 117% % 118% % 119% % 120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 121% 122% IsWMF() returns MagickTrue if the image format type, identified by the 123% magick string, is a Windows MetaFile (WMF) file. 124% 125% The format of the ReadEMFImage method is: 126% 127% MagickBooleanType IsEMF(const unsigned char *magick,const size_t length) 128% 129% A description of each parameter follows: 130% 131% o magick: compare image format pattern against these bytes. 132% 133% o length: Specifies the length of the magick string. 134% 135*/ 136static MagickBooleanType IsWMF(const unsigned char *magick,const size_t length) 137{ 138 if (length < 4) 139 return(MagickFalse); 140 if (memcmp(magick,"\327\315\306\232",4) == 0) 141 return(MagickTrue); 142 if (memcmp(magick,"\001\000\011\000",4) == 0) 143 return(MagickTrue); 144 return(MagickFalse); 145} 146 147/* 148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 149% % 150% % 151% % 152% R e a d E M F I m a g e % 153% % 154% % 155% % 156%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 157% 158% ReadEMFImage() reads an Microsoft Windows Enhanced MetaFile (EMF) or 159% Windows MetaFile (WMF) file using the Windows API and returns it. It 160% allocates the memory necessary for the new Image structure and returns a 161% pointer to the new image. 162% 163% The format of the ReadEMFImage method is: 164% 165% Image *ReadEMFImage(const ImageInfo *image_info, 166% ExceptionInfo *exception) 167% 168% A description of each parameter follows: 169% 170% o image_info: the image info.. 171% 172% o exception: return any errors or warnings in this structure. 173% 174*/ 175 176#if defined(MAGICKCORE_WINGDI32_DELEGATE) 177# if !defined(_MSC_VER) 178# if defined(MAGICKCORE_HAVE__WFOPEN) 179static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16) 180{ 181 register const unsigned char 182 *p; 183 184 if (utf16 != (wchar_t *) NULL) 185 { 186 register wchar_t 187 *q; 188 189 wchar_t 190 c; 191 192 /* 193 Convert UTF-8 to UTF-16. 194 */ 195 q=utf16; 196 for (p=utf8; *p != '\0'; p++) 197 { 198 if ((*p & 0x80) == 0) 199 *q=(*p); 200 else 201 if ((*p & 0xE0) == 0xC0) 202 { 203 c=(*p); 204 *q=(c & 0x1F) << 6; 205 p++; 206 if ((*p & 0xC0) != 0x80) 207 return(0); 208 *q|=(*p & 0x3F); 209 } 210 else 211 if ((*p & 0xF0) == 0xE0) 212 { 213 c=(*p); 214 *q=c << 12; 215 p++; 216 if ((*p & 0xC0) != 0x80) 217 return(0); 218 c=(*p); 219 *q|=(c & 0x3F) << 6; 220 p++; 221 if ((*p & 0xC0) != 0x80) 222 return(0); 223 *q|=(*p & 0x3F); 224 } 225 else 226 return(0); 227 q++; 228 } 229 *q++='\0'; 230 return(q-utf16); 231 } 232 /* 233 Compute UTF-16 string length. 234 */ 235 for (p=utf8; *p != '\0'; p++) 236 { 237 if ((*p & 0x80) == 0) 238 ; 239 else 240 if ((*p & 0xE0) == 0xC0) 241 { 242 p++; 243 if ((*p & 0xC0) != 0x80) 244 return(0); 245 } 246 else 247 if ((*p & 0xF0) == 0xE0) 248 { 249 p++; 250 if ((*p & 0xC0) != 0x80) 251 return(0); 252 p++; 253 if ((*p & 0xC0) != 0x80) 254 return(0); 255 } 256 else 257 return(0); 258 } 259 return(p-utf8); 260} 261 262static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source) 263{ 264 size_t 265 length; 266 267 wchar_t 268 *utf16; 269 270 length=UTF8ToUTF16(source,(wchar_t *) NULL); 271 if (length == 0) 272 { 273 register ssize_t 274 i; 275 276 /* 277 Not UTF-8, just copy. 278 */ 279 length=strlen((char *) source); 280 utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16)); 281 if (utf16 == (wchar_t *) NULL) 282 return((wchar_t *) NULL); 283 for (i=0; i <= (ssize_t) length; i++) 284 utf16[i]=source[i]; 285 return(utf16); 286 } 287 utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16)); 288 if (utf16 == (wchar_t *) NULL) 289 return((wchar_t *) NULL); 290 length=UTF8ToUTF16(source,utf16); 291 return(utf16); 292} 293# endif /* MAGICKCORE_HAVE__WFOPEN */ 294 295static HENHMETAFILE ReadEnhMetaFile(const char *path,ssize_t *width, 296 ssize_t *height) 297{ 298#pragma pack( push, 2 ) 299 typedef struct 300 { 301 DWORD dwKey; 302 WORD hmf; 303 SMALL_RECT bbox; 304 WORD wInch; 305 DWORD dwReserved; 306 WORD wCheckSum; 307 } APMHEADER, *PAPMHEADER; 308#pragma pack( pop ) 309 310 DWORD 311 dwSize; 312 313 ENHMETAHEADER 314 emfh; 315 316 HANDLE 317 hFile; 318 319 HDC 320 hDC; 321 322 HENHMETAFILE 323 hTemp; 324 325 LPBYTE 326 pBits; 327 328 METAFILEPICT 329 mp; 330 331 HMETAFILE 332 hOld; 333 334 *width=512; 335 *height=512; 336 hTemp=GetEnhMetaFile(path); 337#if defined(MAGICKCORE_HAVE__WFOPEN) 338 if (hTemp == (HENHMETAFILE) NULL) 339 { 340 wchar_t 341 *unicode_path; 342 343 unicode_path=ConvertUTF8ToUTF16((const unsigned char *) path); 344 if (unicode_path != (wchar_t *) NULL) 345 { 346 hTemp=GetEnhMetaFileW(unicode_path); 347 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path); 348 } 349 } 350#endif 351 if (hTemp != (HENHMETAFILE) NULL) 352 { 353 /* 354 Enhanced metafile. 355 */ 356 GetEnhMetaFileHeader(hTemp,sizeof(ENHMETAHEADER),&emfh); 357 *width=emfh.rclFrame.right-emfh.rclFrame.left; 358 *height=emfh.rclFrame.bottom-emfh.rclFrame.top; 359 return(hTemp); 360 } 361 hOld=GetMetaFile(path); 362 if (hOld != (HMETAFILE) NULL) 363 { 364 /* 365 16bit windows metafile. 366 */ 367 dwSize=GetMetaFileBitsEx(hOld,0,NULL); 368 if (dwSize == 0) 369 { 370 DeleteMetaFile(hOld); 371 return((HENHMETAFILE) NULL); 372 } 373 pBits=(LPBYTE) AcquireQuantumMemory(dwSize,sizeof(*pBits)); 374 if (pBits == (LPBYTE) NULL) 375 { 376 DeleteMetaFile(hOld); 377 return((HENHMETAFILE) NULL); 378 } 379 if (GetMetaFileBitsEx(hOld,dwSize,pBits) == 0) 380 { 381 pBits=(BYTE *) DestroyString((char *) pBits); 382 DeleteMetaFile(hOld); 383 return((HENHMETAFILE) NULL); 384 } 385 /* 386 Make an enhanced metafile from the windows metafile. 387 */ 388 mp.mm=MM_ANISOTROPIC; 389 mp.xExt=1000; 390 mp.yExt=1000; 391 mp.hMF=NULL; 392 hDC=GetDC(NULL); 393 hTemp=SetWinMetaFileBits(dwSize,pBits,hDC,&mp); 394 ReleaseDC(NULL,hDC); 395 DeleteMetaFile(hOld); 396 pBits=(BYTE *) DestroyString((char *) pBits); 397 GetEnhMetaFileHeader(hTemp,sizeof(ENHMETAHEADER),&emfh); 398 *width=emfh.rclFrame.right-emfh.rclFrame.left; 399 *height=emfh.rclFrame.bottom-emfh.rclFrame.top; 400 return(hTemp); 401 } 402 /* 403 Aldus Placeable metafile. 404 */ 405 hFile=CreateFile(path,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 406 NULL); 407 if (hFile == INVALID_HANDLE_VALUE) 408 return(NULL); 409 dwSize=GetFileSize(hFile,NULL); 410 pBits=(LPBYTE) AcquireQuantumMemory(dwSize,sizeof(*pBits)); 411 ReadFile(hFile,pBits,dwSize,&dwSize,NULL); 412 CloseHandle(hFile); 413 if (((PAPMHEADER) pBits)->dwKey != 0x9ac6cdd7l) 414 { 415 pBits=(BYTE *) DestroyString((char *) pBits); 416 return((HENHMETAFILE) NULL); 417 } 418 /* 419 Make an enhanced metafile from the placable metafile. 420 */ 421 mp.mm=MM_ANISOTROPIC; 422 mp.xExt=((PAPMHEADER) pBits)->bbox.Right-((PAPMHEADER) pBits)->bbox.Left; 423 *width=mp.xExt; 424 mp.xExt=(mp.xExt*2540l)/(DWORD) (((PAPMHEADER) pBits)->wInch); 425 mp.yExt=((PAPMHEADER)pBits)->bbox.Bottom-((PAPMHEADER) pBits)->bbox.Top; 426 *height=mp.yExt; 427 mp.yExt=(mp.yExt*2540l)/(DWORD) (((PAPMHEADER) pBits)->wInch); 428 mp.hMF=NULL; 429 hDC=GetDC(NULL); 430 hTemp=SetWinMetaFileBits(dwSize,&(pBits[sizeof(APMHEADER)]),hDC,&mp); 431 ReleaseDC(NULL,hDC); 432 pBits=(BYTE *) DestroyString((char *) pBits); 433 return(hTemp); 434} 435 436#define CENTIMETERS_INCH 2.54 437 438static Image *ReadEMFImage(const ImageInfo *image_info,ExceptionInfo *exception) 439{ 440 BITMAPINFO 441 DIBinfo; 442 443 HBITMAP 444 hBitmap, 445 hOldBitmap; 446 447 HDC 448 hDC; 449 450 HENHMETAFILE 451 hemf; 452 453 Image 454 *image; 455 456 MagickBooleanType 457 status; 458 459 RECT 460 rect; 461 462 register ssize_t 463 x; 464 465 register Quantum 466 *q; 467 468 RGBQUAD 469 *pBits, 470 *ppBits; 471 472 ssize_t 473 height, 474 width, 475 y; 476 477 image=AcquireImage(image_info,exception); 478 hemf=ReadEnhMetaFile(image_info->filename,&width,&height); 479 if (hemf == (HENHMETAFILE) NULL) 480 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 481 if ((image->columns == 0) || (image->rows == 0)) 482 { 483 double 484 y_resolution, 485 x_resolution; 486 487 y_resolution=DefaultResolution; 488 x_resolution=DefaultResolution; 489 if (image->resolution.y > 0) 490 { 491 y_resolution=image->resolution.y; 492 if (image->units == PixelsPerCentimeterResolution) 493 y_resolution*=CENTIMETERS_INCH; 494 } 495 if (image->resolution.x > 0) 496 { 497 x_resolution=image->resolution.x; 498 if (image->units == PixelsPerCentimeterResolution) 499 x_resolution*=CENTIMETERS_INCH; 500 } 501 image->rows=(size_t) ((height/1000.0/CENTIMETERS_INCH)*y_resolution+0.5); 502 image->columns=(size_t) ((width/1000.0/CENTIMETERS_INCH)* 503 x_resolution+0.5); 504 } 505 if (image_info->size != (char *) NULL) 506 { 507 image->columns=width; 508 image->rows=height; 509 (void) GetGeometry(image_info->size,(ssize_t *) NULL,(ssize_t *) NULL, 510 &image->columns,&image->rows); 511 } 512 status=SetImageExtent(image,image->columns,image->rows,exception); 513 if (status == MagickFalse) 514 return(DestroyImageList(image)); 515 if (image_info->page != (char *) NULL) 516 { 517 char 518 *geometry; 519 520 register char 521 *p; 522 523 MagickStatusType 524 flags; 525 526 ssize_t 527 sans; 528 529 geometry=GetPageGeometry(image_info->page); 530 p=strchr(geometry,'>'); 531 if (p == (char *) NULL) 532 { 533 flags=ParseMetaGeometry(geometry,&sans,&sans,&image->columns, 534 &image->rows); 535 if (image->resolution.x != 0.0) 536 image->columns=(size_t) floor((image->columns*image->resolution.x)+ 537 0.5); 538 if (image->resolution.y != 0.0) 539 image->rows=(size_t) floor((image->rows*image->resolution.y)+0.5); 540 } 541 else 542 { 543 *p='\0'; 544 flags=ParseMetaGeometry(geometry,&sans,&sans,&image->columns, 545 &image->rows); 546 if (image->resolution.x != 0.0) 547 image->columns=(size_t) floor(((image->columns*image->resolution.x)/ 548 DefaultResolution)+0.5); 549 if (image->resolution.y != 0.0) 550 image->rows=(size_t) floor(((image->rows*image->resolution.y)/ 551 DefaultResolution)+0.5); 552 } 553 (void) flags; 554 geometry=DestroyString(geometry); 555 } 556 hDC=GetDC(NULL); 557 if (hDC == (HDC) NULL) 558 { 559 DeleteEnhMetaFile(hemf); 560 ThrowReaderException(ResourceLimitError,"UnableToCreateADC"); 561 } 562 /* 563 Initialize the bitmap header info. 564 */ 565 (void) ResetMagickMemory(&DIBinfo,0,sizeof(BITMAPINFO)); 566 DIBinfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); 567 DIBinfo.bmiHeader.biWidth=(LONG) image->columns; 568 DIBinfo.bmiHeader.biHeight=(-1)*(LONG) image->rows; 569 DIBinfo.bmiHeader.biPlanes=1; 570 DIBinfo.bmiHeader.biBitCount=32; 571 DIBinfo.bmiHeader.biCompression=BI_RGB; 572 hBitmap=CreateDIBSection(hDC,&DIBinfo,DIB_RGB_COLORS,(void **) &ppBits,NULL, 573 0); 574 ReleaseDC(NULL,hDC); 575 if (hBitmap == (HBITMAP) NULL) 576 { 577 DeleteEnhMetaFile(hemf); 578 ThrowReaderException(ResourceLimitError,"UnableToCreateBitmap"); 579 } 580 hDC=CreateCompatibleDC(NULL); 581 if (hDC == (HDC) NULL) 582 { 583 DeleteEnhMetaFile(hemf); 584 DeleteObject(hBitmap); 585 ThrowReaderException(ResourceLimitError,"UnableToCreateADC"); 586 } 587 hOldBitmap=(HBITMAP) SelectObject(hDC,hBitmap); 588 if (hOldBitmap == (HBITMAP) NULL) 589 { 590 DeleteEnhMetaFile(hemf); 591 DeleteDC(hDC); 592 DeleteObject(hBitmap); 593 ThrowReaderException(ResourceLimitError,"UnableToCreateBitmap"); 594 } 595 /* 596 Initialize the bitmap to the image background color. 597 */ 598 pBits=ppBits; 599 for (y=0; y < (ssize_t) image->rows; y++) 600 { 601 for (x=0; x < (ssize_t) image->columns; x++) 602 { 603 pBits->rgbRed=ScaleQuantumToChar(image->background_color.red); 604 pBits->rgbGreen=ScaleQuantumToChar(image->background_color.green); 605 pBits->rgbBlue=ScaleQuantumToChar(image->background_color.blue); 606 pBits++; 607 } 608 } 609 rect.top=0; 610 rect.left=0; 611 rect.right=(LONG) image->columns; 612 rect.bottom=(LONG) image->rows; 613 /* 614 Convert metafile pixels. 615 */ 616 PlayEnhMetaFile(hDC,hemf,&rect); 617 pBits=ppBits; 618 for (y=0; y < (ssize_t) image->rows; y++) 619 { 620 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 621 if (q == (Quantum *) NULL) 622 break; 623 for (x=0; x < (ssize_t) image->columns; x++) 624 { 625 SetPixelRed(image,ScaleCharToQuantum(pBits->rgbRed),q); 626 SetPixelGreen(image,ScaleCharToQuantum(pBits->rgbGreen),q); 627 SetPixelBlue(image,ScaleCharToQuantum(pBits->rgbBlue),q); 628 SetPixelAlpha(image,OpaqueAlpha,q); 629 pBits++; 630 q+=GetPixelChannels(image); 631 } 632 if (SyncAuthenticPixels(image,exception) == MagickFalse) 633 break; 634 } 635 DeleteEnhMetaFile(hemf); 636 SelectObject(hDC,hOldBitmap); 637 DeleteDC(hDC); 638 DeleteObject(hBitmap); 639 return(GetFirstImageInList(image)); 640} 641# else 642 643static inline void EMFSetDimensions(Image * image,Gdiplus::Image *source) 644{ 645 if ((image->resolution.x <= 0.0) || (image->resolution.y <= 0.0)) 646 return; 647 648 image->columns=(size_t) floor((Gdiplus::REAL) source->GetWidth()/ 649 source->GetHorizontalResolution()*image->resolution.x+0.5); 650 image->rows=(size_t)floor((Gdiplus::REAL) source->GetHeight()/ 651 source->GetVerticalResolution()*image->resolution.y+0.5); 652} 653 654static Image *ReadEMFImage(const ImageInfo *image_info, 655 ExceptionInfo *exception) 656{ 657 Gdiplus::Bitmap 658 *bitmap; 659 660 Gdiplus::BitmapData 661 bitmap_data; 662 663 Gdiplus::GdiplusStartupInput 664 startup_input; 665 666 Gdiplus::Graphics 667 *graphics; 668 669 Gdiplus::Image 670 *source; 671 672 Gdiplus::Rect 673 rect; 674 675 GeometryInfo 676 geometry_info; 677 678 Image 679 *image; 680 681 MagickStatusType 682 flags; 683 684 register Quantum 685 *q; 686 687 register ssize_t 688 x; 689 690 ssize_t 691 y; 692 693 ULONG_PTR 694 token; 695 696 unsigned char 697 *p; 698 699 wchar_t 700 fileName[MagickPathExtent]; 701 702 assert(image_info != (const ImageInfo *) NULL); 703 assert(image_info->signature == MagickCoreSignature); 704 if (image_info->debug != MagickFalse) 705 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 706 image_info->filename); 707 assert(exception != (ExceptionInfo *) NULL); 708 709 image=AcquireImage(image_info,exception); 710 if (Gdiplus::GdiplusStartup(&token,&startup_input,NULL) != 711 Gdiplus::Status::Ok) 712 ThrowReaderException(CoderError, "GdiplusStartupFailed"); 713 MultiByteToWideChar(CP_UTF8,0,image->filename,-1,fileName,MagickPathExtent); 714 source=Gdiplus::Image::FromFile(fileName); 715 if (source == (Gdiplus::Image *) NULL) 716 { 717 Gdiplus::GdiplusShutdown(token); 718 ThrowReaderException(FileOpenError,"UnableToOpenFile"); 719 } 720 721 image->resolution.x=source->GetHorizontalResolution(); 722 image->resolution.y=source->GetVerticalResolution(); 723 image->columns=(size_t) source->GetWidth(); 724 image->rows=(size_t) source->GetHeight(); 725 if (image_info->size != (char *) NULL) 726 { 727 (void) GetGeometry(image_info->size,(ssize_t *) NULL,(ssize_t *) NULL, 728 &image->columns,&image->rows); 729 image->resolution.x=source->GetHorizontalResolution()*image->columns/ 730 source->GetWidth(); 731 image->resolution.y=source->GetVerticalResolution()*image->rows/ 732 source->GetHeight(); 733 if (image->resolution.x == 0) 734 image->resolution.x=image->resolution.y; 735 else if (image->resolution.y == 0) 736 image->resolution.y=image->resolution.x; 737 else 738 image->resolution.x=image->resolution.y=MagickMin( 739 image->resolution.x,image->resolution.y); 740 EMFSetDimensions(image,source); 741 } 742 else if (image_info->density != (char *) NULL) 743 { 744 flags=ParseGeometry(image_info->density,&geometry_info); 745 image->resolution.x=geometry_info.rho; 746 image->resolution.y=geometry_info.sigma; 747 if ((flags & SigmaValue) == 0) 748 image->resolution.y=image->resolution.x; 749 EMFSetDimensions(image,source); 750 } 751 if (SetImageExtent(image,image->columns,image->rows,exception) == MagickFalse) 752 { 753 delete source; 754 Gdiplus::GdiplusShutdown(token); 755 return(DestroyImageList(image)); 756 } 757 image->alpha_trait=BlendPixelTrait; 758 if (image->ping != MagickFalse) 759 { 760 delete source; 761 Gdiplus::GdiplusShutdown(token); 762 return(image); 763 } 764 765 bitmap=new Gdiplus::Bitmap((INT) image->columns,(INT) image->rows, 766 PixelFormat32bppARGB); 767 graphics=Gdiplus::Graphics::FromImage(bitmap); 768 graphics->SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic); 769 graphics->SetSmoothingMode(Gdiplus::SmoothingModeHighQuality); 770 graphics->SetTextRenderingHint(Gdiplus::TextRenderingHintClearTypeGridFit); 771 graphics->Clear(Gdiplus::Color((BYTE) ScaleQuantumToChar( 772 image->background_color.alpha),(BYTE) ScaleQuantumToChar( 773 image->background_color.red),(BYTE) ScaleQuantumToChar( 774 image->background_color.green),(BYTE) ScaleQuantumToChar( 775 image->background_color.blue))); 776 graphics->DrawImage(source,0,0,(INT) image->columns,(INT) image->rows); 777 delete graphics; 778 delete source; 779 780 rect=Gdiplus::Rect(0,0,(INT) image->columns,(INT) image->rows); 781 if (bitmap->LockBits(&rect,Gdiplus::ImageLockModeRead,PixelFormat32bppARGB, 782 &bitmap_data) != Gdiplus::Ok) 783 { 784 delete bitmap; 785 Gdiplus::GdiplusShutdown(token); 786 ThrowReaderException(FileOpenError,"UnableToReadImageData"); 787 } 788 789 for (y=0; y < (ssize_t) image->rows; y++) 790 { 791 p=(unsigned char *) bitmap_data.Scan0+(y*abs(bitmap_data.Stride)); 792 if (bitmap_data.Stride < 0) 793 q=GetAuthenticPixels(image,0,image->rows-y-1,image->columns,1,exception); 794 else 795 q=GetAuthenticPixels(image,0,y,image->columns,1,exception); 796 if (q == (Quantum *) NULL) 797 break; 798 799 for (x=0; x < (ssize_t) image->columns; x++) 800 { 801 SetPixelBlue(image,ScaleCharToQuantum(*p++),q); 802 SetPixelGreen(image,ScaleCharToQuantum(*p++),q); 803 SetPixelRed(image,ScaleCharToQuantum(*p++),q); 804 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q); 805 q+=GetPixelChannels(image); 806 } 807 808 if (SyncAuthenticPixels(image,exception) == MagickFalse) 809 break; 810 } 811 812 bitmap->UnlockBits(&bitmap_data); 813 delete bitmap; 814 Gdiplus::GdiplusShutdown(token); 815 return(image); 816} 817# endif /* _MSC_VER */ 818#endif /* MAGICKCORE_EMF_DELEGATE */ 819 820/* 821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 822% % 823% % 824% % 825% R e g i s t e r E M F I m a g e % 826% % 827% % 828% % 829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 830% 831% RegisterEMFImage() adds attributes for the EMF image format to 832% the list of supported formats. The attributes include the image format 833% tag, a method to read and/or write the format, whether the format 834% supports the saving of more than one frame to the same file or blob, 835% whether the format supports native in-memory I/O, and a brief 836% description of the format. 837% 838% The format of the RegisterEMFImage method is: 839% 840% size_t RegisterEMFImage(void) 841% 842*/ 843ModuleExport size_t RegisterEMFImage(void) 844{ 845 MagickInfo 846 *entry; 847 848 entry=AcquireMagickInfo("EMF","EMF","Windows Enhanced Meta File"); 849#if defined(MAGICKCORE_WINGDI32_DELEGATE) 850 entry->decoder=ReadEMFImage; 851#endif 852 entry->magick=(IsImageFormatHandler *) IsEMF; 853 entry->flags^=CoderBlobSupportFlag; 854 (void) RegisterMagickInfo(entry); 855 entry=AcquireMagickInfo("EMF","WMF","Windows Meta File"); 856#if defined(MAGICKCORE_WINGDI32_DELEGATE) 857 entry->decoder=ReadEMFImage; 858#endif 859 entry->magick=(IsImageFormatHandler *) IsWMF; 860 entry->flags^=CoderBlobSupportFlag; 861 (void) RegisterMagickInfo(entry); 862 return(MagickImageCoderSignature); 863} 864 865/* 866%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 867% % 868% % 869% % 870% U n r e g i s t e r E M F I m a g e % 871% % 872% % 873% % 874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 875% 876% UnregisterEMFImage() removes format registrations made by the 877% EMF module from the list of supported formats. 878% 879% The format of the UnregisterEMFImage method is: 880% 881% UnregisterEMFImage(void) 882% 883*/ 884ModuleExport void UnregisterEMFImage(void) 885{ 886 (void) UnregisterMagickInfo("EMF"); 887 (void) UnregisterMagickInfo("WMF"); 888} 889