1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "bitmap.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
37 #include "wx/palette.h"
38 #include "wx/dcmemory.h"
39 #include "wx/bitmap.h"
43 #include "wx/msw/private.h"
46 #include "wx/msw/dib.h"
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 #if !USE_SHARED_LIBRARIES
53 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
54 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
57 // ============================================================================
59 // ============================================================================
61 // ----------------------------------------------------------------------------
63 // ----------------------------------------------------------------------------
65 wxBitmapRefData::wxBitmapRefData()
73 m_selectedInto
= NULL
;
78 wxBitmapRefData::~wxBitmapRefData()
80 wxASSERT_MSG( !m_selectedInto
,
81 wxT("deleting bitmap still selected into wxMemoryDC") );
84 DeleteObject((HBITMAP
) m_hBitmap
);
90 // ----------------------------------------------------------------------------
92 // ----------------------------------------------------------------------------
94 wxList
wxBitmap::sm_handlers
;
96 // this function should be called from all wxBitmap ctors
99 // m_refData = NULL; done in the base class ctor
101 if ( wxTheBitmapList
)
102 wxTheBitmapList
->AddBitmap(this);
105 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
)
112 int width
= icon
.GetWidth(),
113 height
= icon
.GetHeight();
115 HICON hicon
= (HICON
) icon
.GetHICON();
117 // GetIconInfo() doesn't exist under Win16 and I don't know any other way
118 // to create a bitmap from icon there - but using this way we won't have
121 // copy the icon to the bitmap
122 HDC hdcScreen
= ::GetDC((HWND
)NULL
);
123 HDC hdc
= ::CreateCompatibleDC(hdcScreen
);
124 HBITMAP hbitmap
= ::CreateCompatibleBitmap(hdcScreen
, width
, height
);
125 HBITMAP hbmpOld
= (HBITMAP
)::SelectObject(hdc
, hbitmap
);
127 ::DrawIcon(hdc
, 0, 0, hicon
);
129 ::SelectObject(hdc
, hbmpOld
);
131 ::ReleaseDC((HWND
)NULL
, hdcScreen
);
134 if ( !GetIconInfo(hicon
, &iconInfo
) )
136 wxLogLastError("GetIconInfo");
141 HBITMAP hbitmap
= iconInfo
.hbmColor
;
143 wxMask
*mask
= new wxMask
;
144 mask
->SetMaskBitmap((WXHBITMAP
)iconInfo
.hbmMask
);
147 m_refData
= new wxBitmapRefData
;
149 M_BITMAPDATA
->m_width
= width
;
150 M_BITMAPDATA
->m_height
= height
;
151 M_BITMAPDATA
->m_depth
= wxDisplayDepth();
153 M_BITMAPDATA
->m_hBitmap
= (WXHBITMAP
)hbitmap
;
154 M_BITMAPDATA
->m_ok
= TRUE
;
163 wxBitmap::~wxBitmap()
166 wxTheBitmapList
->DeleteObject(this);
169 bool wxBitmap::FreeResource(bool WXUNUSED(force
))
174 wxASSERT_MSG( !M_BITMAPDATA
->m_selectedInto
,
175 wxT("freeing bitmap still selected into wxMemoryDC") );
177 if (M_BITMAPDATA
->m_hBitmap
)
179 DeleteObject((HBITMAP
) M_BITMAPDATA
->m_hBitmap
);
181 M_BITMAPDATA
->m_hBitmap
= 0 ;
184 if (M_BITMAPDATA->m_bitmapPalette)
185 delete M_BITMAPDATA->m_bitmapPalette;
187 M_BITMAPDATA->m_bitmapPalette = NULL ;
194 wxBitmap::wxBitmap(const char bits
[], int the_width
, int the_height
, int no_bits
)
198 m_refData
= new wxBitmapRefData
;
200 M_BITMAPDATA
->m_width
= the_width
;
201 M_BITMAPDATA
->m_height
= the_height
;
202 M_BITMAPDATA
->m_depth
= no_bits
;
203 M_BITMAPDATA
->m_numColors
= 0;
205 M_BITMAPDATA
->m_hBitmap
= (WXHBITMAP
) CreateBitmap(the_width
, the_height
, 1, no_bits
, bits
);
207 if (M_BITMAPDATA
->m_hBitmap
)
208 M_BITMAPDATA
->m_ok
= TRUE
;
210 M_BITMAPDATA
->m_ok
= FALSE
;
212 M_BITMAPDATA
->m_selectedInto
= NULL
;
215 // Create from XPM data
216 wxBitmap::wxBitmap(char **data
, wxControl
*WXUNUSED(anItem
))
220 (void)Create((void *)data
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
223 wxBitmap::wxBitmap(int w
, int h
, int d
)
227 (void)Create(w
, h
, d
);
230 wxBitmap::wxBitmap(void *data
, long type
, int width
, int height
, int depth
)
234 (void) Create(data
, type
, width
, height
, depth
);
237 wxBitmap::wxBitmap(const wxString
& filename
, long type
)
241 LoadFile(filename
, (int)type
);
244 bool wxBitmap::Create(int w
, int h
, int d
)
248 m_refData
= new wxBitmapRefData
;
250 M_BITMAPDATA
->m_width
= w
;
251 M_BITMAPDATA
->m_height
= h
;
252 M_BITMAPDATA
->m_depth
= d
;
256 M_BITMAPDATA
->m_hBitmap
= (WXHBITMAP
) CreateBitmap(w
, h
, 1, d
, NULL
);
260 HDC dc
= GetDC((HWND
) NULL
);
261 M_BITMAPDATA
->m_hBitmap
= (WXHBITMAP
) CreateCompatibleBitmap(dc
, w
, h
);
262 ReleaseDC((HWND
) NULL
, dc
);
263 M_BITMAPDATA
->m_depth
= wxDisplayDepth();
265 if (M_BITMAPDATA
->m_hBitmap
)
266 M_BITMAPDATA
->m_ok
= TRUE
;
268 M_BITMAPDATA
->m_ok
= FALSE
;
269 return M_BITMAPDATA
->m_ok
;
272 bool wxBitmap::LoadFile(const wxString
& filename
, long type
)
276 m_refData
= new wxBitmapRefData
;
278 wxBitmapHandler
*handler
= FindHandler(type
);
280 if ( handler
== NULL
) {
281 wxLogWarning(wxT("no bitmap handler for type %d defined."), type
);
286 return handler
->LoadFile(this, filename
, type
, -1, -1);
289 bool wxBitmap::Create(void *data
, long type
, int width
, int height
, int depth
)
293 m_refData
= new wxBitmapRefData
;
295 wxBitmapHandler
*handler
= FindHandler(type
);
297 if ( handler
== NULL
) {
298 wxLogWarning(wxT("no bitmap handler for type %d defined."), type
);
303 return handler
->Create(this, data
, type
, width
, height
, depth
);
306 bool wxBitmap::SaveFile(const wxString
& filename
, int type
, const wxPalette
*palette
)
308 wxBitmapHandler
*handler
= FindHandler(type
);
310 if ( handler
== NULL
) {
311 wxLogWarning(wxT("no bitmap handler for type %d defined."), type
);
316 return handler
->SaveFile(this, filename
, type
, palette
);
319 void wxBitmap::SetWidth(int w
)
322 m_refData
= new wxBitmapRefData
;
324 M_BITMAPDATA
->m_width
= w
;
327 void wxBitmap::SetHeight(int h
)
330 m_refData
= new wxBitmapRefData
;
332 M_BITMAPDATA
->m_height
= h
;
335 void wxBitmap::SetDepth(int d
)
338 m_refData
= new wxBitmapRefData
;
340 M_BITMAPDATA
->m_depth
= d
;
343 void wxBitmap::SetQuality(int q
)
346 m_refData
= new wxBitmapRefData
;
348 M_BITMAPDATA
->m_quality
= q
;
351 void wxBitmap::SetOk(bool isOk
)
354 m_refData
= new wxBitmapRefData
;
356 M_BITMAPDATA
->m_ok
= isOk
;
359 void wxBitmap::SetPalette(const wxPalette
& palette
)
362 m_refData
= new wxBitmapRefData
;
364 M_BITMAPDATA
->m_bitmapPalette
= palette
;
367 void wxBitmap::SetMask(wxMask
*mask
)
370 m_refData
= new wxBitmapRefData
;
372 M_BITMAPDATA
->m_bitmapMask
= mask
;
375 void wxBitmap::SetHBITMAP(WXHBITMAP bmp
)
378 m_refData
= new wxBitmapRefData
;
380 M_BITMAPDATA
->m_hBitmap
= bmp
;
381 M_BITMAPDATA
->m_ok
= bmp
!= 0;
384 void wxBitmap::AddHandler(wxBitmapHandler
*handler
)
386 sm_handlers
.Append(handler
);
389 void wxBitmap::InsertHandler(wxBitmapHandler
*handler
)
391 sm_handlers
.Insert(handler
);
394 bool wxBitmap::RemoveHandler(const wxString
& name
)
396 wxBitmapHandler
*handler
= FindHandler(name
);
399 sm_handlers
.DeleteObject(handler
);
406 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& name
)
408 wxNode
*node
= sm_handlers
.First();
411 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
412 if ( (handler
->GetName().Cmp(name
) == 0) )
419 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& extension
, long bitmapType
)
421 wxNode
*node
= sm_handlers
.First();
424 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
425 if ( (handler
->GetExtension().Cmp(extension
) == 0) &&
426 (bitmapType
== -1 || (handler
->GetType() == bitmapType
)) )
433 wxBitmapHandler
*wxBitmap::FindHandler(long bitmapType
)
435 wxNode
*node
= sm_handlers
.First();
438 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
439 if (handler
->GetType() == bitmapType
)
446 // New Create/FreeDIB functions since ones in dibutils.cpp are confusing
447 static long createDIB(long xSize
, long ySize
, long bitsPerPixel
,
448 HPALETTE hPal
, LPBITMAPINFO
* lpDIBHeader
);
449 static long freeDIB(LPBITMAPINFO lpDIBHeader
);
451 // Creates a bitmap that matches the device context, from
452 // an arbitray bitmap. At present, the original bitmap must have an
453 // associated palette. TODO: use a default palette if no palette exists.
454 // Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com>
455 wxBitmap
wxBitmap::GetBitmapForDC(wxDC
& dc
) const
458 wxBitmap
tmpBitmap(this->GetWidth(), this->GetHeight(), dc
.GetDepth());
459 HPALETTE hPal
= (HPALETTE
) NULL
;
461 void *lpBits
= (void*) NULL
;
464 wxASSERT( this->GetPalette() && this->GetPalette()->Ok() && (this->GetPalette()->GetHPALETTE() != 0) );
466 tmpBitmap.SetPalette(this->GetPalette());
467 memDC.SelectObject(tmpBitmap);
468 memDC.SetPalette(this->GetPalette());
470 hPal = (HPALETTE) this->GetPalette()->GetHPALETTE();
472 if( this->GetPalette() && this->GetPalette()->Ok() && (this->GetPalette()->GetHPALETTE() != 0) )
474 tmpBitmap
.SetPalette(* this->GetPalette());
475 memDC
.SelectObject(tmpBitmap
);
476 memDC
.SetPalette(* this->GetPalette());
477 hPal
= (HPALETTE
) this->GetPalette()->GetHPALETTE();
481 hPal
= (HPALETTE
) ::GetStockObject(DEFAULT_PALETTE
);
483 palette
.SetHPALETTE( (WXHPALETTE
)hPal
);
484 tmpBitmap
.SetPalette( palette
);
485 memDC
.SelectObject(tmpBitmap
);
486 memDC
.SetPalette( palette
);
489 // set the height negative because in a DIB the order of the lines is reversed
490 createDIB(this->GetWidth(), -this->GetHeight(), this->GetDepth(), hPal
, &lpDib
);
492 lpBits
= malloc(lpDib
->bmiHeader
.biSizeImage
);
494 ::GetBitmapBits((HBITMAP
)GetHBITMAP(), lpDib
->bmiHeader
.biSizeImage
, lpBits
);
496 ::SetDIBitsToDevice((HDC
) memDC
.GetHDC(), 0, 0, this->GetWidth(), this->GetHeight(),
497 0, 0, 0, this->GetHeight(), lpBits
, lpDib
, DIB_RGB_COLORS
);
514 // Construct a mask from a bitmap and a colour indicating
515 // the transparent area
516 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
519 Create(bitmap
, colour
);
522 // Construct a mask from a bitmap and a palette index indicating
523 // the transparent area
524 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
527 Create(bitmap
, paletteIndex
);
530 // Construct a mask from a mono bitmap (copies the bitmap).
531 wxMask::wxMask(const wxBitmap
& bitmap
)
540 ::DeleteObject((HBITMAP
) m_maskBitmap
);
543 // Create a mask from a mono bitmap (copies the bitmap).
544 bool wxMask::Create(const wxBitmap
& bitmap
)
548 ::DeleteObject((HBITMAP
) m_maskBitmap
);
551 if (!bitmap
.Ok() || bitmap
.GetDepth() != 1)
555 m_maskBitmap
= (WXHBITMAP
) CreateBitmap(
560 HDC srcDC
= CreateCompatibleDC(0);
561 SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
562 HDC destDC
= CreateCompatibleDC(0);
563 SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
564 BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
);
565 SelectObject(srcDC
, 0);
567 SelectObject(destDC
, 0);
572 // Create a mask from a bitmap and a palette index indicating
573 // the transparent area
574 bool wxMask::Create(const wxBitmap
& bitmap
, int paletteIndex
)
578 ::DeleteObject((HBITMAP
) m_maskBitmap
);
581 if (bitmap
.Ok() && bitmap
.GetPalette()->Ok())
583 unsigned char red
, green
, blue
;
584 if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
))
586 wxColour
transparentColour(red
, green
, blue
);
587 return Create(bitmap
, transparentColour
);
593 // Create a mask from a bitmap and a colour indicating
594 // the transparent area
595 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
)
599 ::DeleteObject((HBITMAP
) m_maskBitmap
);
607 // scan the bitmap for the transparent colour and set
608 // the corresponding pixels in the mask to BLACK and
610 COLORREF maskColour
= RGB(colour
.Red(), colour
.Green(), colour
.Blue());
611 m_maskBitmap
= (WXHBITMAP
) ::CreateBitmap(
616 HDC srcDC
= ::CreateCompatibleDC(0);
617 ::SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
618 HDC destDC
= ::CreateCompatibleDC(0);
619 ::SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
621 // this is not very efficient, but I can't think
622 // of a better way of doing it
623 for (int w
= 0; w
< bitmap
.GetWidth(); w
++)
625 for (int h
= 0; h
< bitmap
.GetHeight(); h
++)
627 COLORREF col
= GetPixel(srcDC
, w
, h
);
628 if (col
== maskColour
)
630 ::SetPixel(destDC
, w
, h
, RGB(0, 0, 0));
634 ::SetPixel(destDC
, w
, h
, RGB(255, 255, 255));
638 ::SelectObject(srcDC
, 0);
640 ::SelectObject(destDC
, 0);
649 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
651 bool wxBitmapHandler::Create(wxBitmap
*WXUNUSED(bitmap
), void *WXUNUSED(data
), long WXUNUSED(type
), int WXUNUSED(width
), int WXUNUSED(height
), int WXUNUSED(depth
))
656 bool wxBitmapHandler::LoadFile(wxBitmap
*WXUNUSED(bitmap
), const wxString
& WXUNUSED(name
), long WXUNUSED(type
),
657 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
))
662 bool wxBitmapHandler::SaveFile(wxBitmap
*WXUNUSED(bitmap
), const wxString
& WXUNUSED(name
), int WXUNUSED(type
), const wxPalette
*WXUNUSED(palette
))
671 class WXDLLEXPORT wxBMPResourceHandler
: public wxBitmapHandler
673 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler
)
675 inline wxBMPResourceHandler()
677 m_name
= "Windows bitmap resource";
679 m_type
= wxBITMAP_TYPE_BMP_RESOURCE
;
682 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
683 int desiredWidth
, int desiredHeight
);
685 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler
, wxBitmapHandler
)
687 bool wxBMPResourceHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long WXUNUSED(flags
),
688 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
))
690 // TODO: load colourmap.
691 M_BITMAPHANDLERDATA
->m_hBitmap
= (WXHBITMAP
) ::LoadBitmap(wxGetInstance(), name
);
692 if (M_BITMAPHANDLERDATA
->m_hBitmap
)
694 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
696 GetObject((HBITMAP
) M_BITMAPHANDLERDATA
->m_hBitmap
, sizeof(BITMAP
), (LPSTR
) &bm
);
697 M_BITMAPHANDLERDATA
->m_width
= bm
.bmWidth
;
698 M_BITMAPHANDLERDATA
->m_height
= bm
.bmHeight
;
699 M_BITMAPHANDLERDATA
->m_depth
= bm
.bmBitsPixel
;
701 if ( bitmap
->IsKindOf(CLASSINFO(wxIcon
)) )
708 // it's probably not found
709 wxLogError(wxT("Can't load bitmap '%s' from resources! Check .rc file."), name
.c_str());
714 class WXDLLEXPORT wxBMPFileHandler
: public wxBitmapHandler
716 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler
)
718 inline wxBMPFileHandler()
720 m_name
= "Windows bitmap file";
722 m_type
= wxBITMAP_TYPE_BMP
;
725 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
726 int desiredWidth
, int desiredHeight
);
727 virtual bool SaveFile(wxBitmap
*bitmap
, const wxString
& name
, int type
, const wxPalette
*palette
= NULL
);
729 IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler
, wxBitmapHandler
)
731 bool wxBMPFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long WXUNUSED(flags
),
732 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
))
734 #if wxUSE_IMAGE_LOADING_IN_MSW
735 wxPalette
*palette
= NULL
;
736 bool success
= FALSE
;
738 if (type & wxBITMAP_DISCARD_COLOURMAP)
739 success = wxLoadIntoBitmap(WXSTRINGCAST name, bitmap);
742 success
= (wxLoadIntoBitmap(WXSTRINGCAST name
, bitmap
, &palette
) != 0);
743 if (!success
&& palette
)
750 M_BITMAPHANDLERDATA
->m_bitmapPalette
= *palette
;
759 bool wxBMPFileHandler::SaveFile(wxBitmap
*bitmap
, const wxString
& name
, int WXUNUSED(type
), const wxPalette
*pal
)
761 #if wxUSE_IMAGE_LOADING_IN_MSW
762 wxPalette
*actualPalette
= (wxPalette
*)pal
;
763 if (!actualPalette
&& (!M_BITMAPHANDLERDATA
->m_bitmapPalette
.IsNull()))
764 actualPalette
= & (M_BITMAPHANDLERDATA
->m_bitmapPalette
);
765 return (wxSaveBitmap(WXSTRINGCAST name
, bitmap
, actualPalette
) != 0);
771 void wxBitmap::CleanUpHandlers()
773 wxNode
*node
= sm_handlers
.First();
776 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
777 wxNode
*next
= node
->Next();
784 void wxBitmap::InitStandardHandlers()
786 AddHandler(new wxBMPResourceHandler
);
787 AddHandler(new wxBMPFileHandler
);
789 // Not added by default: include xpmhand.h in your app
790 // and call these in your wxApp::OnInit.
791 // AddHandler(new wxXPMFileHandler);
792 // AddHandler(new wxXPMDataHandler);
794 AddHandler(new wxICOResourceHandler
);
795 AddHandler(new wxICOFileHandler
);
798 static long createDIB(long xSize
, long ySize
, long bitsPerPixel
,
799 HPALETTE hPal
, LPBITMAPINFO
* lpDIBHeader
)
801 unsigned long i
, headerSize
;
802 LPBITMAPINFO lpDIBheader
= NULL
;
803 LPPALETTEENTRY lpPe
= NULL
;
806 // Allocate space for a DIB header
807 headerSize
= (sizeof(BITMAPINFOHEADER
) + (256 * sizeof(PALETTEENTRY
)));
808 lpDIBheader
= (BITMAPINFO
*) malloc(headerSize
);
809 lpPe
= (PALETTEENTRY
*)((BYTE
*)lpDIBheader
+ sizeof(BITMAPINFOHEADER
));
811 GetPaletteEntries(hPal
, 0, 256, lpPe
);
814 memset(lpDIBheader
, 0x00, sizeof(BITMAPINFOHEADER
));
817 // Fill in the static parts of the DIB header
818 lpDIBheader
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
819 lpDIBheader
->bmiHeader
.biWidth
= xSize
;
820 lpDIBheader
->bmiHeader
.biHeight
= ySize
;
821 lpDIBheader
->bmiHeader
.biPlanes
= 1;
823 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
824 lpDIBheader
->bmiHeader
.biBitCount
= (WORD
)(bitsPerPixel
);
825 lpDIBheader
->bmiHeader
.biCompression
= BI_RGB
;
826 lpDIBheader
->bmiHeader
.biSizeImage
= xSize
* abs(ySize
) * bitsPerPixel
>>
828 lpDIBheader
->bmiHeader
.biClrUsed
= 256;
831 // Initialize the DIB palette
832 for (i
= 0; i
< 256; i
++) {
833 lpDIBheader
->bmiColors
[i
].rgbReserved
= lpPe
[i
].peFlags
;
834 lpDIBheader
->bmiColors
[i
].rgbRed
= lpPe
[i
].peRed
;
835 lpDIBheader
->bmiColors
[i
].rgbGreen
= lpPe
[i
].peGreen
;
836 lpDIBheader
->bmiColors
[i
].rgbBlue
= lpPe
[i
].peBlue
;
839 *lpDIBHeader
= lpDIBheader
;
848 static long freeDIB(LPBITMAPINFO lpDIBHeader
)
851 if (lpDIBHeader
!= NULL
) {