• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                                                                             %
7 %                                 N   N  TTTTT                                %
8 %                                 NN  N    T                                  %
9 %                                 N N N    T                                  %
10 %                                 N  NN    T                                  %
11 %                                 N   N    T                                  %
12 %                                                                             %
13 %                                                                             %
14 %                   Windows NT Feature Methods for MagickCore                 %
15 %                                                                             %
16 %                               Software Design                               %
17 %                                    Cristy                                   %
18 %                                December 1996                                %
19 %                                                                             %
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 
40 /*
41   Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
45 #define WIN32_LEAN_AND_MEAN
46 #define VC_EXTRALEAN
47 #include <windows.h>
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/monitor.h"
57 #include "MagickCore/monitor-private.h"
58 #include "MagickCore/nt-base.h"
59 #include "MagickCore/nt-base-private.h"
60 #include "MagickCore/pixel-accessor.h"
61 #include "MagickCore/quantum.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/token.h"
64 #include "MagickCore/splay-tree.h"
65 #include "MagickCore/utility.h"
66 
67 /*
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 %                                                                             %
70 %                                                                             %
71 %                                                                             %
72 %   C r o p I m a g e T o H B i t m a p                                       %
73 %                                                                             %
74 %                                                                             %
75 %                                                                             %
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 %
78 %  CropImageToHBITMAP() extracts a specified region of the image and returns
79 %  it as a Windows HBITMAP. While the same functionality can be accomplished by
80 %  invoking CropImage() followed by ImageToHBITMAP(), this method is more
81 %  efficient since it copies pixels directly to the HBITMAP.
82 %
83 %  The format of the CropImageToHBITMAP method is:
84 %
85 %      HBITMAP CropImageToHBITMAP(Image* image,const RectangleInfo *geometry,
86 %        ExceptionInfo *exception)
87 %
88 %  A description of each parameter follows:
89 %
90 %    o image: the image.
91 %
92 %    o geometry: Define the region of the image to crop with members
93 %      x, y, width, and height.
94 %
95 %    o exception: return any errors or warnings in this structure.
96 %
97 */
CropImageToHBITMAP(Image * image,const RectangleInfo * geometry,ExceptionInfo * exception)98 MagickExport void *CropImageToHBITMAP(Image *image,
99   const RectangleInfo *geometry,ExceptionInfo *exception)
100 {
101 #define CropImageTag  "Crop/Image"
102 
103   BITMAP
104     bitmap;
105 
106   HBITMAP
107     bitmapH;
108 
109   HANDLE
110     bitmap_bitsH;
111 
112   MagickBooleanType
113     proceed;
114 
115   RectangleInfo
116     page;
117 
118   register const Quantum
119     *p;
120 
121   register RGBQUAD
122     *q;
123 
124   RGBQUAD
125     *bitmap_bits;
126 
127   ssize_t
128     y;
129 
130   /*
131     Check crop geometry.
132   */
133   assert(image != (const Image *) NULL);
134   assert(image->signature == MagickCoreSignature);
135   if (image->debug != MagickFalse)
136     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
137   assert(geometry != (const RectangleInfo *) NULL);
138   assert(exception != (ExceptionInfo *) NULL);
139   assert(exception->signature == MagickCoreSignature);
140   if (((geometry->x+(ssize_t) geometry->width) < 0) ||
141       ((geometry->y+(ssize_t) geometry->height) < 0) ||
142       (geometry->x >= (ssize_t) image->columns) ||
143       (geometry->y >= (ssize_t) image->rows))
144     ThrowImageException(OptionError,"GeometryDoesNotContainImage");
145   page=(*geometry);
146   if ((page.x+(ssize_t) page.width) > (ssize_t) image->columns)
147     page.width=image->columns-page.x;
148   if ((page.y+(ssize_t) page.height) > (ssize_t) image->rows)
149     page.height=image->rows-page.y;
150   if (page.x < 0)
151     {
152       page.width+=page.x;
153       page.x=0;
154     }
155   if (page.y < 0)
156     {
157       page.height+=page.y;
158       page.y=0;
159     }
160 
161   if ((page.width == 0) || (page.height == 0))
162     ThrowImageException(OptionError,"GeometryDimensionsAreZero");
163   /*
164     Initialize crop image attributes.
165   */
166   bitmap.bmType         = 0;
167   bitmap.bmWidth        = (LONG) page.width;
168   bitmap.bmHeight       = (LONG) page.height;
169   bitmap.bmWidthBytes   = bitmap.bmWidth * 4;
170   bitmap.bmPlanes       = 1;
171   bitmap.bmBitsPixel    = 32;
172   bitmap.bmBits         = NULL;
173 
174   bitmap_bitsH=(HANDLE) GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,page.width*
175     page.height*bitmap.bmBitsPixel);
176   if (bitmap_bitsH == NULL)
177     return(NULL);
178   bitmap_bits=(RGBQUAD *) GlobalLock((HGLOBAL) bitmap_bitsH);
179   if ( bitmap.bmBits == NULL )
180     bitmap.bmBits = bitmap_bits;
181   if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
182     SetImageColorspace(image,sRGBColorspace,exception);
183   /*
184     Extract crop image.
185   */
186   q=bitmap_bits;
187   for (y=0; y < (ssize_t) page.height; y++)
188   {
189     register ssize_t
190       x;
191 
192     p=GetVirtualPixels(image,page.x,page.y+y,page.width,1,exception);
193     if (p == (const Quantum *) NULL)
194       break;
195 
196     /* Transfer pixels, scaling to Quantum */
197     for( x=(ssize_t) page.width ; x> 0 ; x-- )
198     {
199       q->rgbRed = ScaleQuantumToChar(GetPixelRed(image,p));
200       q->rgbGreen = ScaleQuantumToChar(GetPixelGreen(image,p));
201       q->rgbBlue = ScaleQuantumToChar(GetPixelBlue(image,p));
202       q->rgbReserved = 0;
203       p+=GetPixelChannels(image);
204       q++;
205     }
206     proceed=SetImageProgress(image,CropImageTag,y,page.height);
207     if (proceed == MagickFalse)
208       break;
209   }
210   if (y < (ssize_t) page.height)
211     {
212       GlobalUnlock((HGLOBAL) bitmap_bitsH);
213       GlobalFree((HGLOBAL) bitmap_bitsH);
214       return((void *) NULL);
215     }
216   bitmap.bmBits=bitmap_bits;
217   bitmapH=CreateBitmapIndirect(&bitmap);
218   GlobalUnlock((HGLOBAL) bitmap_bitsH);
219   GlobalFree((HGLOBAL) bitmap_bitsH);
220   return((void *) bitmapH);
221 }
222 
223 /*
224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225 %                                                                             %
226 %                                                                             %
227 %                                                                             %
228 %   I s M a g i c k C o n f l i c t                                           %
229 %                                                                             %
230 %                                                                             %
231 %                                                                             %
232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233 %
234 %  IsMagickConflict() returns true if the image format conflicts with a logical
235 %  drive (.e.g. X:).
236 %
237 %  The format of the IsMagickConflict method is:
238 %
239 %      MagickBooleanType IsMagickConflict(const char *magick)
240 %
241 %  A description of each parameter follows:
242 %
243 %    o magick: Specifies the image format.
244 %
245 */
NTIsMagickConflict(const char * magick)246 MagickExport MagickBooleanType NTIsMagickConflict(const char *magick)
247 {
248   MagickBooleanType
249     status;
250 
251   assert(magick != (char *) NULL);
252   if (strlen(magick) > 1)
253     return(MagickFalse);
254   status=(GetLogicalDrives() & (1 << ((toupper((int) (*magick)))-'A'))) != 0 ?
255     MagickTrue : MagickFalse;
256   return(status);
257 }
258 
259 /*
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 %                                                                             %
262 %                                                                             %
263 %                                                                             %
264 %   N T A c q u i r e T y p e C a c h e                                       %
265 %                                                                             %
266 %                                                                             %
267 %                                                                             %
268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269 %
270 %  NTAcquireTypeCache() loads a Windows TrueType fonts.
271 %
272 %  The format of the NTAcquireTypeCache method is:
273 %
274 %      MagickBooleanType NTAcquireTypeCache(SplayTreeInfo *type_cache)
275 %
276 %  A description of each parameter follows:
277 %
278 %    o type_cache: A linked list of fonts.
279 %
280 */
NTAcquireTypeCache(SplayTreeInfo * type_cache,ExceptionInfo * exception)281 MagickExport MagickBooleanType NTAcquireTypeCache(SplayTreeInfo *type_cache,
282   ExceptionInfo *exception)
283 {
284   HKEY
285     reg_key = (HKEY) INVALID_HANDLE_VALUE;
286 
287   LONG
288     res;
289 
290   int
291     list_entries = 0;
292 
293   char
294     buffer[MagickPathExtent],
295     system_root[MagickPathExtent],
296     font_root[MagickPathExtent];
297 
298   DWORD
299     type,
300     system_root_length;
301 
302   MagickBooleanType
303     status;
304 
305   /*
306     Try to find the right Windows*\CurrentVersion key, the SystemRoot and
307     then the Fonts key
308   */
309   res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
310     "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &reg_key);
311   if (res == ERROR_SUCCESS) {
312     system_root_length=sizeof(system_root)-1;
313     res = RegQueryValueExA(reg_key,"SystemRoot",NULL, &type,
314       (BYTE*) system_root, &system_root_length);
315   }
316   if (res != ERROR_SUCCESS) {
317     res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
318       "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, &reg_key);
319     if (res == ERROR_SUCCESS) {
320       system_root_length=sizeof(system_root)-1;
321       res = RegQueryValueExA(reg_key,"SystemRoot",NULL, &type,
322         (BYTE*)system_root, &system_root_length);
323     }
324   }
325   if (res == ERROR_SUCCESS)
326     res = RegOpenKeyExA (reg_key, "Fonts",0, KEY_READ, &reg_key);
327   if (res != ERROR_SUCCESS)
328     return(MagickFalse);
329   *font_root='\0';
330   (void) CopyMagickString(buffer,system_root,MagickPathExtent);
331   (void) ConcatenateMagickString(buffer,"\\fonts\\arial.ttf",MagickPathExtent);
332   if (IsPathAccessible(buffer) != MagickFalse)
333     {
334       (void) CopyMagickString(font_root,system_root,MagickPathExtent);
335       (void) ConcatenateMagickString(font_root,"\\fonts\\",MagickPathExtent);
336     }
337   else
338     {
339       (void) CopyMagickString(font_root,system_root,MagickPathExtent);
340       (void) ConcatenateMagickString(font_root,"\\",MagickPathExtent);
341     }
342 
343   {
344     TypeInfo
345       *type_info;
346 
347     DWORD
348       registry_index = 0,
349       type,
350       value_data_size,
351       value_name_length;
352 
353     char
354       value_data[MagickPathExtent],
355       value_name[MagickPathExtent];
356 
357     res = ERROR_SUCCESS;
358 
359     while (res != ERROR_NO_MORE_ITEMS)
360       {
361         char
362           *family_extent,
363           token[MagickPathExtent],
364           *pos,
365           *q;
366 
367         value_name_length = sizeof(value_name) - 1;
368         value_data_size = sizeof(value_data) - 1;
369         res = RegEnumValueA ( reg_key, registry_index, value_name,
370           &value_name_length, 0, &type, (BYTE*)value_data, &value_data_size);
371         registry_index++;
372         if (res != ERROR_SUCCESS)
373           continue;
374         if ( (pos = strstr(value_name, " (TrueType)")) == (char*) NULL )
375           continue;
376         *pos='\0'; /* Remove (TrueType) from string */
377 
378         type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
379         if (type_info == (TypeInfo *) NULL)
380           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
381         (void) ResetMagickMemory(type_info,0,sizeof(TypeInfo));
382 
383         type_info->path=ConstantString("Windows Fonts");
384         type_info->signature=MagickCoreSignature;
385 
386         /* Name */
387         (void) CopyMagickString(buffer,value_name,MagickPathExtent);
388         for(pos = buffer; *pos != 0 ; pos++)
389           if (*pos == ' ')
390             *pos = '-';
391         type_info->name=ConstantString(buffer);
392 
393         /* Fullname */
394         type_info->description=ConstantString(value_name);
395 
396         /* Format */
397         type_info->format=ConstantString("truetype");
398 
399         /* Glyphs */
400         if (strchr(value_data,'\\') != (char *) NULL)
401           (void) CopyMagickString(buffer,value_data,MagickPathExtent);
402         else
403           {
404             (void) CopyMagickString(buffer,font_root,MagickPathExtent);
405             (void) ConcatenateMagickString(buffer,value_data,MagickPathExtent);
406           }
407 
408         LocaleLower(buffer);
409         type_info->glyphs=ConstantString(buffer);
410 
411         type_info->stretch=NormalStretch;
412         type_info->style=NormalStyle;
413         type_info->weight=400;
414 
415         /* Some fonts are known to require special encodings */
416         if ( (LocaleCompare(type_info->name, "Symbol") == 0 ) ||
417              (LocaleCompare(type_info->name, "Wingdings") == 0 ) ||
418              (LocaleCompare(type_info->name, "Wingdings-2") == 0 ) ||
419              (LocaleCompare(type_info->name, "Wingdings-3") == 0 ) )
420           type_info->encoding=ConstantString("AppleRoman");
421 
422         family_extent=value_name;
423 
424         for (q=value_name; *q != '\0'; )
425           {
426             GetNextToken(q,(const char **) &q,MagickPathExtent,token);
427             if (*token == '\0')
428               break;
429 
430             if (LocaleCompare(token,"Italic") == 0)
431               {
432                 type_info->style=ItalicStyle;
433               }
434 
435             else if (LocaleCompare(token,"Oblique") == 0)
436               {
437                 type_info->style=ObliqueStyle;
438               }
439 
440             else if (LocaleCompare(token,"Bold") == 0)
441               {
442                 type_info->weight=700;
443               }
444 
445             else if (LocaleCompare(token,"Thin") == 0)
446               {
447                 type_info->weight=100;
448               }
449 
450             else if ( (LocaleCompare(token,"ExtraLight") == 0) ||
451                       (LocaleCompare(token,"UltraLight") == 0) )
452               {
453                 type_info->weight=200;
454               }
455 
456             else if (LocaleCompare(token,"Light") == 0)
457               {
458                 type_info->weight=300;
459               }
460 
461             else if ( (LocaleCompare(token,"Normal") == 0) ||
462                       (LocaleCompare(token,"Regular") == 0) )
463               {
464                 type_info->weight=400;
465               }
466 
467             else if (LocaleCompare(token,"Medium") == 0)
468               {
469                 type_info->weight=500;
470               }
471 
472             else if ( (LocaleCompare(token,"SemiBold") == 0) ||
473                       (LocaleCompare(token,"DemiBold") == 0) )
474               {
475                 type_info->weight=600;
476               }
477 
478             else if ( (LocaleCompare(token,"ExtraBold") == 0) ||
479                       (LocaleCompare(token,"UltraBold") == 0) )
480               {
481                 type_info->weight=800;
482               }
483 
484             else if ( (LocaleCompare(token,"Heavy") == 0) ||
485                       (LocaleCompare(token,"Black") == 0) )
486               {
487                 type_info->weight=900;
488               }
489 
490             else if (LocaleCompare(token,"Condensed") == 0)
491               {
492                 type_info->stretch = CondensedStretch;
493               }
494 
495             else if (LocaleCompare(token,"Expanded") == 0)
496               {
497                 type_info->stretch = ExpandedStretch;
498               }
499 
500             else if (LocaleCompare(token,"ExtraCondensed") == 0)
501               {
502                 type_info->stretch = ExtraCondensedStretch;
503               }
504 
505             else if (LocaleCompare(token,"ExtraExpanded") == 0)
506               {
507                 type_info->stretch = ExtraExpandedStretch;
508               }
509 
510             else if (LocaleCompare(token,"SemiCondensed") == 0)
511               {
512                 type_info->stretch = SemiCondensedStretch;
513               }
514 
515             else if (LocaleCompare(token,"SemiExpanded") == 0)
516               {
517                 type_info->stretch = SemiExpandedStretch;
518               }
519 
520             else if (LocaleCompare(token,"UltraCondensed") == 0)
521               {
522                 type_info->stretch = UltraCondensedStretch;
523               }
524 
525             else if (LocaleCompare(token,"UltraExpanded") == 0)
526               {
527                 type_info->stretch = UltraExpandedStretch;
528               }
529 
530             else
531               {
532                 family_extent=q;
533               }
534           }
535 
536         (void) CopyMagickString(buffer,value_name,family_extent-value_name+1);
537         StripString(buffer);
538         type_info->family=ConstantString(buffer);
539 
540         list_entries++;
541         status=AddValueToSplayTree(type_cache,type_info->name,type_info);
542         if (status == MagickFalse)
543           (void) ThrowMagickException(exception,GetMagickModule(),
544             ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name);
545       }
546   }
547   RegCloseKey ( reg_key );
548   return(MagickTrue);
549 }
550 
551 /*
552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
553 %                                                                             %
554 %                                                                             %
555 %                                                                             %
556 %   I m a g e T o H B i t m a p                                               %
557 %                                                                             %
558 %                                                                             %
559 %                                                                             %
560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561 %
562 %  ImageToHBITMAP() creates a Windows HBITMAP from an image.
563 %
564 %  The format of the ImageToHBITMAP method is:
565 %
566 %      HBITMAP ImageToHBITMAP(Image *image,Exceptioninfo *exception)
567 %
568 %  A description of each parameter follows:
569 %
570 %    o image: the image to convert.
571 %
572 */
ImageToHBITMAP(Image * image,ExceptionInfo * exception)573 MagickExport void *ImageToHBITMAP(Image *image,ExceptionInfo *exception)
574 {
575   BITMAP
576     bitmap;
577 
578   HANDLE
579     bitmap_bitsH;
580 
581   HBITMAP
582     bitmapH;
583 
584   register ssize_t
585     x;
586 
587   register const Quantum
588     *p;
589 
590   register RGBQUAD
591     *q;
592 
593   RGBQUAD
594     *bitmap_bits;
595 
596   size_t
597     length;
598 
599   ssize_t
600     y;
601 
602   (void) ResetMagickMemory(&bitmap,0,sizeof(bitmap));
603   bitmap.bmType=0;
604   bitmap.bmWidth=(LONG) image->columns;
605   bitmap.bmHeight=(LONG) image->rows;
606   bitmap.bmWidthBytes=4*bitmap.bmWidth;
607   bitmap.bmPlanes=1;
608   bitmap.bmBitsPixel=32;
609   bitmap.bmBits=NULL;
610   length=bitmap.bmWidthBytes*bitmap.bmHeight;
611   bitmap_bitsH=(HANDLE) GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,length);
612   if (bitmap_bitsH == NULL)
613     {
614       char
615         *message;
616 
617       message=GetExceptionMessage(errno);
618       (void) ThrowMagickException(exception,GetMagickModule(),
619         ResourceLimitError,"MemoryAllocationFailed","`%s'",message);
620       message=DestroyString(message);
621       return(NULL);
622     }
623   bitmap_bits=(RGBQUAD *) GlobalLock((HGLOBAL) bitmap_bitsH);
624   q=bitmap_bits;
625   if (bitmap.bmBits == NULL)
626     bitmap.bmBits=bitmap_bits;
627   (void) SetImageColorspace(image,sRGBColorspace,exception);
628   for (y=0; y < (ssize_t) image->rows; y++)
629   {
630     p=GetVirtualPixels(image,0,y,image->columns,1,exception);
631     if (p == (const Quantum *) NULL)
632       break;
633     for (x=0; x < (ssize_t) image->columns; x++)
634     {
635       q->rgbRed=ScaleQuantumToChar(GetPixelRed(image,p));
636       q->rgbGreen=ScaleQuantumToChar(GetPixelGreen(image,p));
637       q->rgbBlue=ScaleQuantumToChar(GetPixelBlue(image,p));
638       q->rgbReserved=0;
639       p+=GetPixelChannels(image);
640       q++;
641     }
642   }
643   bitmap.bmBits=bitmap_bits;
644   bitmapH=CreateBitmapIndirect(&bitmap);
645   if (bitmapH == NULL)
646     {
647       char
648         *message;
649 
650       message=GetExceptionMessage(errno);
651       (void) ThrowMagickException(exception,GetMagickModule(),
652         ResourceLimitError,"MemoryAllocationFailed","`%s'",message);
653       message=DestroyString(message);
654     }
655   GlobalUnlock((HGLOBAL) bitmap_bitsH);
656   GlobalFree((HGLOBAL) bitmap_bitsH);
657   return((void *) bitmapH);
658 }
659 
660 #endif
661