2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14 % Windows NT Feature Methods for MagickCore %
21 % Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization %
22 % dedicated to making software imaging solutions freely available. %
24 % You may not use this file except in compliance with the License. You may %
25 % obtain a copy of the License at %
27 % https://www.imagemagick.org/script/license.php %
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. %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
45 #define WIN32_LEAN_AND_MEAN
48 #include "MagickCore/cache.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/colorspace-private.h"
51 #include "MagickCore/draw.h"
52 #include "MagickCore/exception.h"
53 #include "MagickCore/exception-private.h"
54 #include "MagickCore/image-private.h"
55 #include "MagickCore/memory_.h"
56 #include "MagickCore/memory-private.h"
57 #include "MagickCore/monitor.h"
58 #include "MagickCore/monitor-private.h"
59 #include "MagickCore/nt-base.h"
60 #include "MagickCore/nt-base-private.h"
61 #include "MagickCore/pixel-accessor.h"
62 #include "MagickCore/quantum.h"
63 #include "MagickCore/string_.h"
64 #include "MagickCore/token.h"
65 #include "MagickCore/splay-tree.h"
66 #include "MagickCore/utility.h"
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 % C r o p I m a g e T o H B i t m a p %
77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 % CropImageToHBITMAP() extracts a specified region of the image and returns
80 % it as a Windows HBITMAP. While the same functionality can be accomplished by
81 % invoking CropImage() followed by ImageToHBITMAP(), this method is more
82 % efficient since it copies pixels directly to the HBITMAP.
84 % The format of the CropImageToHBITMAP method is:
86 % HBITMAP CropImageToHBITMAP(Image* image,const RectangleInfo *geometry,
87 % ExceptionInfo *exception)
89 % A description of each parameter follows:
93 % o geometry: Define the region of the image to crop with members
94 % x, y, width, and height.
96 % o exception: return any errors or warnings in this structure.
99 MagickExport void *CropImageToHBITMAP(Image *image,
100 const RectangleInfo *geometry,ExceptionInfo *exception)
102 #define CropImageTag "Crop/Image"
119 register const Quantum
134 assert(image != (const Image *) NULL);
135 assert(image->signature == MagickCoreSignature);
136 if (image->debug != MagickFalse)
137 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
138 assert(geometry != (const RectangleInfo *) NULL);
139 assert(exception != (ExceptionInfo *) NULL);
140 assert(exception->signature == MagickCoreSignature);
141 if (((geometry->x+(ssize_t) geometry->width) < 0) ||
142 ((geometry->y+(ssize_t) geometry->height) < 0) ||
143 (geometry->x >= (ssize_t) image->columns) ||
144 (geometry->y >= (ssize_t) image->rows))
145 ThrowImageException(OptionError,"GeometryDoesNotContainImage");
147 if ((page.x+(ssize_t) page.width) > (ssize_t) image->columns)
148 page.width=image->columns-page.x;
149 if ((page.y+(ssize_t) page.height) > (ssize_t) image->rows)
150 page.height=image->rows-page.y;
162 if ((page.width == 0) || (page.height == 0))
163 ThrowImageException(OptionError,"GeometryDimensionsAreZero");
165 Initialize crop image attributes.
168 bitmap.bmWidth = (LONG) page.width;
169 bitmap.bmHeight = (LONG) page.height;
170 bitmap.bmWidthBytes = bitmap.bmWidth * 4;
172 bitmap.bmBitsPixel = 32;
173 bitmap.bmBits = NULL;
175 bitmap_bitsH=(HANDLE) GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,page.width*
176 page.height*bitmap.bmBitsPixel);
177 if (bitmap_bitsH == NULL)
179 bitmap_bits=(RGBQUAD *) GlobalLock((HGLOBAL) bitmap_bitsH);
180 if ( bitmap.bmBits == NULL )
181 bitmap.bmBits = bitmap_bits;
182 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
183 SetImageColorspace(image,sRGBColorspace,exception);
188 for (y=0; y < (ssize_t) page.height; y++)
193 p=GetVirtualPixels(image,page.x,page.y+y,page.width,1,exception);
194 if (p == (const Quantum *) NULL)
197 /* Transfer pixels, scaling to Quantum */
198 for( x=(ssize_t) page.width ; x> 0 ; x-- )
200 q->rgbRed = ScaleQuantumToChar(GetPixelRed(image,p));
201 q->rgbGreen = ScaleQuantumToChar(GetPixelGreen(image,p));
202 q->rgbBlue = ScaleQuantumToChar(GetPixelBlue(image,p));
204 p+=GetPixelChannels(image);
207 proceed=SetImageProgress(image,CropImageTag,y,page.height);
208 if (proceed == MagickFalse)
211 if (y < (ssize_t) page.height)
213 GlobalUnlock((HGLOBAL) bitmap_bitsH);
214 GlobalFree((HGLOBAL) bitmap_bitsH);
215 return((void *) NULL);
217 bitmap.bmBits=bitmap_bits;
218 bitmapH=CreateBitmapIndirect(&bitmap);
219 GlobalUnlock((HGLOBAL) bitmap_bitsH);
220 GlobalFree((HGLOBAL) bitmap_bitsH);
221 return((void *) bitmapH);
225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229 % I s M a g i c k C o n f l i c t %
233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235 % IsMagickConflict() returns true if the image format conflicts with a logical
238 % The format of the IsMagickConflict method is:
240 % MagickBooleanType IsMagickConflict(const char *magick)
242 % A description of each parameter follows:
244 % o magick: Specifies the image format.
247 MagickExport MagickBooleanType NTIsMagickConflict(const char *magick)
252 assert(magick != (char *) NULL);
253 if (strlen(magick) > 1)
255 status=(GetLogicalDrives() & (1 << ((toupper((int) (*magick)))-'A'))) != 0 ?
256 MagickTrue : MagickFalse;
261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265 % N T A c q u i r e T y p e C a c h e %
269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 % NTAcquireTypeCache() loads a Windows TrueType fonts.
273 % The format of the NTAcquireTypeCache method is:
275 % MagickBooleanType NTAcquireTypeCache(SplayTreeInfo *type_cache)
277 % A description of each parameter follows:
279 % o type_cache: A linked list of fonts.
282 MagickExport MagickBooleanType NTAcquireTypeCache(SplayTreeInfo *type_cache,
283 ExceptionInfo *exception)
286 reg_key = (HKEY) INVALID_HANDLE_VALUE;
295 buffer[MagickPathExtent],
296 system_root[MagickPathExtent],
297 font_root[MagickPathExtent];
307 Try to find the right Windows*\CurrentVersion key, the SystemRoot and
310 res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
311 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, ®_key);
312 if (res == ERROR_SUCCESS) {
313 system_root_length=sizeof(system_root)-1;
314 res = RegQueryValueExA(reg_key,"SystemRoot",NULL, &type,
315 (BYTE*) system_root, &system_root_length);
317 if (res != ERROR_SUCCESS) {
318 res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
319 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, ®_key);
320 if (res == ERROR_SUCCESS) {
321 system_root_length=sizeof(system_root)-1;
322 res = RegQueryValueExA(reg_key,"SystemRoot",NULL, &type,
323 (BYTE*)system_root, &system_root_length);
326 if (res == ERROR_SUCCESS)
327 res = RegOpenKeyExA (reg_key, "Fonts",0, KEY_READ, ®_key);
328 if (res != ERROR_SUCCESS)
331 (void) CopyMagickString(buffer,system_root,MagickPathExtent);
332 (void) ConcatenateMagickString(buffer,"\\fonts\\arial.ttf",MagickPathExtent);
333 if (IsPathAccessible(buffer) != MagickFalse)
335 (void) CopyMagickString(font_root,system_root,MagickPathExtent);
336 (void) ConcatenateMagickString(font_root,"\\fonts\\",MagickPathExtent);
340 (void) CopyMagickString(font_root,system_root,MagickPathExtent);
341 (void) ConcatenateMagickString(font_root,"\\",MagickPathExtent);
355 value_data[MagickPathExtent],
356 value_name[MagickPathExtent];
360 while (res != ERROR_NO_MORE_ITEMS)
364 token[MagickPathExtent],
368 value_name_length = sizeof(value_name) - 1;
369 value_data_size = sizeof(value_data) - 1;
370 res = RegEnumValueA ( reg_key, registry_index, value_name,
371 &value_name_length, 0, &type, (BYTE*)value_data, &value_data_size);
373 if (res != ERROR_SUCCESS)
375 if ( (pos = strstr(value_name, " (TrueType)")) == (char*) NULL )
377 *pos='\0'; /* Remove (TrueType) from string */
379 type_info=(TypeInfo *) AcquireCriticalMemory(sizeof(*type_info));
380 (void) ResetMagickMemory(type_info,0,sizeof(TypeInfo));
382 type_info->path=ConstantString("Windows Fonts");
383 type_info->signature=MagickCoreSignature;
386 (void) CopyMagickString(buffer,value_name,MagickPathExtent);
387 for(pos = buffer; *pos != 0 ; pos++)
390 type_info->name=ConstantString(buffer);
393 type_info->description=ConstantString(value_name);
396 type_info->format=ConstantString("truetype");
399 if (strchr(value_data,'\\') != (char *) NULL)
400 (void) CopyMagickString(buffer,value_data,MagickPathExtent);
403 (void) CopyMagickString(buffer,font_root,MagickPathExtent);
404 (void) ConcatenateMagickString(buffer,value_data,MagickPathExtent);
408 type_info->glyphs=ConstantString(buffer);
410 type_info->stretch=NormalStretch;
411 type_info->style=NormalStyle;
412 type_info->weight=400;
414 /* Some fonts are known to require special encodings */
415 if ( (LocaleCompare(type_info->name, "Symbol") == 0 ) ||
416 (LocaleCompare(type_info->name, "Wingdings") == 0 ) ||
417 (LocaleCompare(type_info->name, "Wingdings-2") == 0 ) ||
418 (LocaleCompare(type_info->name, "Wingdings-3") == 0 ) )
419 type_info->encoding=ConstantString("AppleRoman");
421 family_extent=value_name;
423 for (q=value_name; *q != '\0'; )
425 GetNextToken(q,(const char **) &q,MagickPathExtent,token);
429 if (LocaleCompare(token,"Italic") == 0)
431 type_info->style=ItalicStyle;
434 else if (LocaleCompare(token,"Oblique") == 0)
436 type_info->style=ObliqueStyle;
439 else if (LocaleCompare(token,"Bold") == 0)
441 type_info->weight=700;
444 else if (LocaleCompare(token,"Thin") == 0)
446 type_info->weight=100;
449 else if ( (LocaleCompare(token,"ExtraLight") == 0) ||
450 (LocaleCompare(token,"UltraLight") == 0) )
452 type_info->weight=200;
455 else if (LocaleCompare(token,"Light") == 0)
457 type_info->weight=300;
460 else if ( (LocaleCompare(token,"Normal") == 0) ||
461 (LocaleCompare(token,"Regular") == 0) )
463 type_info->weight=400;
466 else if (LocaleCompare(token,"Medium") == 0)
468 type_info->weight=500;
471 else if ( (LocaleCompare(token,"SemiBold") == 0) ||
472 (LocaleCompare(token,"DemiBold") == 0) )
474 type_info->weight=600;
477 else if ( (LocaleCompare(token,"ExtraBold") == 0) ||
478 (LocaleCompare(token,"UltraBold") == 0) )
480 type_info->weight=800;
483 else if ( (LocaleCompare(token,"Heavy") == 0) ||
484 (LocaleCompare(token,"Black") == 0) )
486 type_info->weight=900;
489 else if (LocaleCompare(token,"Condensed") == 0)
491 type_info->stretch = CondensedStretch;
494 else if (LocaleCompare(token,"Expanded") == 0)
496 type_info->stretch = ExpandedStretch;
499 else if (LocaleCompare(token,"ExtraCondensed") == 0)
501 type_info->stretch = ExtraCondensedStretch;
504 else if (LocaleCompare(token,"ExtraExpanded") == 0)
506 type_info->stretch = ExtraExpandedStretch;
509 else if (LocaleCompare(token,"SemiCondensed") == 0)
511 type_info->stretch = SemiCondensedStretch;
514 else if (LocaleCompare(token,"SemiExpanded") == 0)
516 type_info->stretch = SemiExpandedStretch;
519 else if (LocaleCompare(token,"UltraCondensed") == 0)
521 type_info->stretch = UltraCondensedStretch;
524 else if (LocaleCompare(token,"UltraExpanded") == 0)
526 type_info->stretch = UltraExpandedStretch;
535 (void) CopyMagickString(buffer,value_name,family_extent-value_name+1);
537 type_info->family=ConstantString(buffer);
540 status=AddValueToSplayTree(type_cache,type_info->name,type_info);
541 if (status == MagickFalse)
542 (void) ThrowMagickException(exception,GetMagickModule(),
543 ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name);
546 RegCloseKey ( reg_key );
551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
555 % I m a g e T o H B i t m a p %
559 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561 % ImageToHBITMAP() creates a Windows HBITMAP from an image.
563 % The format of the ImageToHBITMAP method is:
565 % HBITMAP ImageToHBITMAP(Image *image,Exceptioninfo *exception)
567 % A description of each parameter follows:
569 % o image: the image to convert.
572 MagickExport void *ImageToHBITMAP(Image *image,ExceptionInfo *exception)
586 register const Quantum
601 (void) ResetMagickMemory(&bitmap,0,sizeof(bitmap));
603 bitmap.bmWidth=(LONG) image->columns;
604 bitmap.bmHeight=(LONG) image->rows;
605 bitmap.bmWidthBytes=4*bitmap.bmWidth;
607 bitmap.bmBitsPixel=32;
609 length=bitmap.bmWidthBytes*bitmap.bmHeight;
610 bitmap_bitsH=(HANDLE) GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,length);
611 if (bitmap_bitsH == NULL)
616 message=GetExceptionMessage(errno);
617 (void) ThrowMagickException(exception,GetMagickModule(),
618 ResourceLimitError,"MemoryAllocationFailed","`%s'",message);
619 message=DestroyString(message);
622 bitmap_bits=(RGBQUAD *) GlobalLock((HGLOBAL) bitmap_bitsH);
624 if (bitmap.bmBits == NULL)
625 bitmap.bmBits=bitmap_bits;
626 (void) SetImageColorspace(image,sRGBColorspace,exception);
627 for (y=0; y < (ssize_t) image->rows; y++)
629 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
630 if (p == (const Quantum *) NULL)
632 for (x=0; x < (ssize_t) image->columns; x++)
634 q->rgbRed=ScaleQuantumToChar(GetPixelRed(image,p));
635 q->rgbGreen=ScaleQuantumToChar(GetPixelGreen(image,p));
636 q->rgbBlue=ScaleQuantumToChar(GetPixelBlue(image,p));
638 p+=GetPixelChannels(image);
642 bitmap.bmBits=bitmap_bits;
643 bitmapH=CreateBitmapIndirect(&bitmap);
649 message=GetExceptionMessage(errno);
650 (void) ThrowMagickException(exception,GetMagickModule(),
651 ResourceLimitError,"MemoryAllocationFailed","`%s'",message);
652 message=DestroyString(message);
654 GlobalUnlock((HGLOBAL) bitmap_bitsH);
655 GlobalFree((HGLOBAL) bitmap_bitsH);
656 return((void *) bitmapH);