libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
Load n Save BMPs.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2002 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 // DESCRIPTION:
19 // This bit of code was copied from an article called:
20 // "Bitmap & Palette - Drawing a bitmap from a BMP file" by
21 // Zafir Anjum (05/97). I found it at <a href="http://www.dsp.net/zafir/bitmap/draw_bmp.html"/>
22 // e-mail zafir@dsp.com .
23 //
24 // Variations on the BitBlt theme.
25 //
26 
27 // This file uses the MFC.
28 
29 #include "stdafx.h"
30 
32 
33 #include <boost/scoped_array.hpp>
34 
35 /////////////////////////////////////////////////////////////////////////////
36 
37 const WORD current_version=0x300;
38 const unsigned short max_entries=256;
39 const WORD bitmap_type_id=((WORD)('M'<<8)|'B');
40 
41 /////////////////////////////////////////////////////////////////////////////
42 
43 using namespace libjmmcg;
44 using namespace NTUtils;
45 
46 // LoadBMP - Loads a BMP file and creates a logical palette for it..
47 // Returns - TRUE for success.
48 // BMPFile - Full path of the BMP file.
49 // hDIB - Pointer to a HGLOBAL variable to hold the loaded bitmap.
50 // Pal - Will hold the logical palette.
51 
52 bool
53 NTUtils::LoadBMP(const tstring &BMPFile,BitMapInfoWrapper &hDIB,std::auto_ptr<CPalette> &Pal) {
54  register CFile file_t(BMPFile.c_str(),CFile::modeRead|CFile::shareDenyWrite);
55  return LoadBMP(file_t,hDIB,Pal);
56 }
57 
58 bool
59 NTUtils::LoadBMP(CFile &file_t,BitMapInfoWrapper &hDIB,std::auto_ptr<CPalette> &Pal) {
60  BITMAPFILEHEADER bmfHeader;
61  // Read file header
62  if (file_t.Read(reinterpret_cast<char *>(&bmfHeader), sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER)) {
63  return true;
64  }
65  // File type should be 'BM'
66  if (bmfHeader.bfType!=bitmap_type_id) {
67  return true;
68  }
69  BitMapInfoWrapper biw(bmfHeader.bfSize);
70  hDIB=biw;
71  // Read the remainder of the bitmap file.
72  if (file_t.Read(reinterpret_cast<char *>(hDIB.Info()),bmfHeader.bfSize-sizeof(BITMAPFILEHEADER))!=(bmfHeader.bfSize-sizeof(BITMAPFILEHEADER))) {
73  return true;
74  }
75  register DWORD tmp=(hDIB.Info()->bmiHeader.biClrUsed ? hDIB.Info()->bmiHeader.biClrUsed : (1 << (hDIB.Info()->bmiHeader.biBitCount-1)));
76  if (tmp>USHRT_MAX) {
77  Pal=std::auto_ptr<CPalette>();
78  return false;
79  }
80  Pal=std::auto_ptr<CPalette>(new CPalette);
81  WORD nColors;
82  // Create the palette
83  if ((nColors=static_cast<WORD>(tmp))<=max_entries && nColors) {
84  const std::auto_ptr<BYTE> buff(new BYTE[sizeof(LOGPALETTE)+(sizeof(PALETTEENTRY)*nColors)]);
85  register LOGPALETTE * const pLP=reinterpret_cast<LOGPALETTE *>(buff.get());
86  if (!pLP) {
87  Pal=std::auto_ptr<CPalette>();
88  return true;
89  }
90  pLP->palVersion = current_version;
91  pLP->palNumEntries = nColors;
92  for (register unsigned int i=0;i<nColors;++i) {
93  pLP->palPalEntry[i].peRed=hDIB.Info()->bmiColors[i].rgbRed;
94  pLP->palPalEntry[i].peGreen=hDIB.Info()->bmiColors[i].rgbGreen;
95  pLP->palPalEntry[i].peBlue=hDIB.Info()->bmiColors[i].rgbBlue;
96  pLP->palPalEntry[i].peFlags=0;
97  }
98  Pal->CreatePalette(pLP);
99  }
100  return false;
101 }
102 
103 NTUtils::BitMapInfoWrapper
104 NTUtils::CreateBitmapInfoStruct(const CBitmap &Bmp) {
105  BITMAP bmp;
106  /* Retrieve the bitmap's color format, width, and height. */
107  if (!Bmp.GetObject(sizeof(BITMAP),reinterpret_cast<void *>(&bmp))) {
108  // Gak, choke, splutter....!
109  return *reinterpret_cast<NTUtils::BitMapInfoWrapper *>(NULL);
110  }
111  /* Convert the color format to a count of bits. */
112  WORD cClrBits=static_cast<WORD>(bmp.bmPlanes*bmp.bmBitsPixel);
113  if (cClrBits==1) {
114  cClrBits=1;
115  } else if (cClrBits<=4) {
116  cClrBits=4;
117  } else if (cClrBits<=8) {
118  cClrBits=8;
119  } else if (cClrBits<=16) {
120  cClrBits=16;
121  } else if (cClrBits<=24) {
122  cClrBits=24;
123  } else {
124  cClrBits=32;
125  }
126  /*
127  * Allocate memory for the BITMAPINFO structure. (This structure
128  * contains a BITMAPINFOHEADER structure and an array of RGBQUAD data
129  * structures.)
130  */
131  BitMapInfoWrapper bmi;
132  if (cClrBits!=24) {
133  BitMapInfoWrapper biw(sizeof(RGBQUAD)*(2^cClrBits));
134  bmi=biw;
135  /*
136  * There is no RGBQUAD array for the 24-bit-per-pixel format.
137  */
138  }
139  /* Initialize the fields in the BITMAPINFO structure. */
140  bmi.Info()->bmiHeader.biWidth=bmp.bmWidth;
141  bmi.Info()->bmiHeader.biHeight=bmp.bmHeight;
142  bmi.Info()->bmiHeader.biPlanes=bmp.bmPlanes;
143  bmi.Info()->bmiHeader.biBitCount=bmp.bmBitsPixel;
144  if (cClrBits<24) {
145  bmi.Info()->bmiHeader.biClrUsed=2^cClrBits;
146  }
147  /*
148  * Compute the number of bytes in the array of color
149  * indices and store the result in biSizeImage.
150  */
151  bmi.Info()->bmiHeader.biSizeImage=(bmi.Info()->bmiHeader.biWidth+7)/8*bmi.Info()->bmiHeader.biHeight*cClrBits;
152  return bmi;
153 }
154 
155 bool
156 NTUtils::CreateBMPFile(const tstring &pszFile,const CBitmap &BMP,const CDC &DC) {
157  register CFile file_t(pszFile.c_str(),CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite);
158  register bool ret=CreateBMPFile(file_t,BMP,DC);
159  file_t.Close();
160  return ret;
161 }
162 
163 bool
164 NTUtils::CreateBMPFile(CFile &File,const CBitmap &BMP,const CDC &DC) {
165  BitMapInfoWrapper pbi(NTUtils::CreateBitmapInfoStruct(BMP));
166  const boost::scoped_array<BYTE> lpBits(new BYTE[pbi.Header()->biSizeImage]); /* memory pointer */
167  if (!lpBits.get())
168  return false;
169  /*
170  * Retrieve the color table (RGBQUAD array) and the bits
171  * (array of palette indices) from the DIB. */
172  if (!GetDIBits(DC.GetSafeHdc(),static_cast<const HBITMAP>(BMP),0,static_cast<WORD>(pbi.Header()->biHeight),lpBits.get(),pbi.Info(),DIB_RGB_COLORS))
173  return false;
174  BITMAPFILEHEADER hdr; /* bitmap file-header */
175  hdr.bfType=bitmap_type_id;
176  /* Compute the size of the entire file. */
177  hdr.bfSize=static_cast<DWORD>(sizeof(BITMAPFILEHEADER)+pbi.Header()->biSize+pbi.Header()->biClrUsed*sizeof(RGBQUAD)+pbi.Header()->biSizeImage);
178  hdr.bfReserved1=0;
179  hdr.bfReserved2=0;
180  /* Compute the offset to the array of color indices. */
181  hdr.bfOffBits=static_cast<DWORD>(sizeof(BITMAPFILEHEADER))+pbi.Header()->biSize+pbi.Header()->biClrUsed*sizeof(RGBQUAD);
182  /* Copy the BITMAPFILEHEADER into the .BMP file. */
183  File.Write(reinterpret_cast<const void *>(&hdr),sizeof(BITMAPFILEHEADER));
184  /* Copy the BITMAPINFOHEADER and RGBQUAD array into the file. */
185  File.Write(reinterpret_cast<const void *>(pbi.Header()),sizeof(BITMAPINFOHEADER)+pbi.Header()->biClrUsed*sizeof(RGBQUAD));
186  /* Copy the array of color indices into the .BMP file. */
187  File.Write(reinterpret_cast<const void *>(lpBits.get()),static_cast<unsigned int>(pbi.Header()->biSizeImage));
188  return true;
189 }