Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
ioBMP.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #include "ioBMP.hpp"
35 #include <vlCore/FileSystem.hpp>
36 #include <vlCore/VirtualFile.hpp>
37 #include <vlCore/Image.hpp>
38 
39 using namespace vl;
40 
41 #include <vlCore/ImageTools.hpp>
42 
43 //-----------------------------------------------------------------------------
44 // BMP loader
45 //-----------------------------------------------------------------------------
46 namespace
47 {
48  typedef struct
49  {
50  char mType[2];
51  char mSize[4];
52  char mReserved1[2];
53  char mReserved2[2];
54  char mOffBits[4];
55 
56  unsigned short Type() const { return *(const unsigned short*)mType; }
57  unsigned int Size() const { return *(const unsigned int*)mSize; }
58  unsigned short Reserved1() const { return *(const unsigned short*)mReserved1; }
59  unsigned short Reserved2() const { return *(const unsigned short*)mReserved2; }
60  unsigned int OffBits() const { return *(const unsigned int*)mOffBits; }
61  } BitmapFileHeader;
62 
63  typedef struct
64  {
65  unsigned int Size() { return *(unsigned int*)mSize; }
66  int Width() { return *(int*)mWidth; }
67  int Height() { return *(int*)mHeight; }
68  unsigned short Planes() { return *(unsigned short*)mPlanes; }
69  unsigned short BitCount() { return *(unsigned short*)mBitCount; }
70  unsigned int Compression() { return *(unsigned int*)mCompression; }
71  unsigned int SizeImage() { return *(unsigned int*)mSizeImage; }
72  int XPelsPerMeter() { return *(int*)mXPelsPerMeter; }
73  int YPelsPerMeter() { return *(int*)mYPelsPerMeter; }
74  unsigned int ClrUsed() { return *(unsigned int*)mClrUsed; }
75  unsigned int ClrImportant() { return *(unsigned int*)mClrImportant; }
76 
77  char mSize[4];
78  char mWidth[4];
79  char mHeight[4];
80  char mPlanes[2];
81  char mBitCount[2];
82  char mCompression[4];
83  char mSizeImage[4];
84  char mXPelsPerMeter[4];
85  char mYPelsPerMeter[4];
86  char mClrUsed[4];
87  char mClrImportant[4];
88  } BitmapInfoHeader;
89 
90  const unsigned int BMP_NoCompression = 0;
91  const unsigned int BMP_XRGB = 3;
92  // RLE8 = 1L;
93  // RLE4 = 2L;
94  // JPEG = 4L;
95  // PNG = 5L;
96 }
97 //-----------------------------------------------------------------------------
105 {
106  ref<VirtualFile> file = defFileSystem()->locateFile(path);
107  if ( !file )
108  {
109  Log::error( Say("File '%s' not found.\n") << path );
110  return NULL;
111  }
112 
113  return loadBMP(file.get());
114 }
115 //-----------------------------------------------------------------------------
117 {
118  if ( !file->open(OM_ReadOnly) )
119  {
120  Log::error( Say("loadBMP: error opening file: '%s'\n") << file->path() );
121  return NULL;
122  }
123 
124  ref<Image> img = new Image;
125  img->setObjectName(file->path().toStdString().c_str());
126 
127  BitmapFileHeader bfh;
128  memset(&bfh, 0, sizeof(bfh));
129  BitmapInfoHeader bih;
130  memset(&bih, 0, sizeof(bih));
131 
132  file->read(&bfh, sizeof(bfh));
133  if (bfh.Type() != 0x4D42)
134  {
135  file->close();
136  Log::error( Say("The file '%s' is not a BMP file.\n") << file->path() );
137  return NULL;
138  }
139 
140  int head = (int)file->position();
141 
142  file->read(&bih, sizeof(bih));
143 
144  bool flip = false;
145  if ( bih.Height() < 0 )
146  {
147  int *h = (int*)bih.mHeight;
148  *h = -*h;
149  flip = true;
150  }
151  VL_CHECK( bih.Height() * bih.Width() );
152 
153  // TODO: support bih.Compression() == BMP_Type_RLE8 e BMP_XRGB meglio
154  if ( bih.Compression() != BMP_NoCompression && bih.Compression() != BMP_XRGB )
155  {
156  Log::error( Say("Compression %n unsupported for %s\n") << bih.Compression() << file->path() );
157  file->close();
158  return NULL;
159  }
160 
161  switch( bih.BitCount() )
162  {
163  // 8 bit palettized
164  case 8:
165  {
166  img->allocate2D(bih.Width(), bih.Height(), 4, IF_BGRA, IT_UNSIGNED_BYTE);
167 
168  TPalette4x256 palette;
169  memset(palette, 0, 256*4);
170 
171  int br;
172  file->seekSet( (int)head + bih.Size() );
173  int palette_bytes = (bih.ClrUsed() ? bih.ClrUsed() : 256)*4;
174  br = (int)file->read(palette, palette_bytes);
175  /*// set alpha to 0xFF
176  for(int i=0; i<palette_bytes; i+=4)
177  palette[i+3] = 0xFF;*/
178  if(br != palette_bytes)
179  {
180  file->close();
181  Log::error( Say("File %s truncated: %n < %n.\n") << file->path() << br << palette_bytes );
182  return NULL;
183  }
184 
185  int pad_bytes = (4 - (img->width() * 1) % 4) % 4;
186  int datasize = (img->width() * 1 + pad_bytes) * img->height();
187 
188  // 8bpp uncompressed
189 
190  if ( bih.Compression() == BMP_NoCompression )
191  {
192  br = (int)file->read(img->pixels(), datasize);
193  if(br != datasize)
194  {
195  // fclose(fin);
196  file->close();
197  Log::error( Say("file %s truncated.\n") << file->path() );
198  return NULL;
199  }
200  }
201  // BMP_Type_RLE8 not supported yet
202  else
203  {
204  // TODO
205  }
206 
207  convert8ToRGBA( palette, img->pixels(), img->width(), img->height(), 4 );
208  } break;
209 
210  case 32:
211  case 24:
212  {
213  img->allocate2D(bih.Width(), bih.Height(), 4, IF_BGRA, IT_UNSIGNED_BYTE);
214  file->seekSet(bfh.OffBits());
215 
216  // usato solo se 24 bits.
217  int pad_bytes = (4 - (img->width() * 3) % 4) % 4;
218  // fa prima se lo si legge tutto insieme.
219  int datasize = bih.BitCount() == 32 ? img->width() * img->height() * 4 : (img->width() * 3 + pad_bytes) * img->height();
220  int rd = (int)file->read(img->pixels(), datasize);
221  if( rd < datasize )
222  {
223  file->close();
224  Log::error( Say("File %s truncated.\n") << file->path() );
225  return NULL;
226  }
227 
228  // convert the buffer from 24 to 32bpp running from the end to the begining.
229  if (bih.BitCount() == 24)
230  convertRGBToRGBA(img->pixels(), img->width(), img->height(), 0xFF, 4);
231 
232  } break;
233 
234  default:
235  {
236  file->close();
237  Log::error( Say("BitCount %n unsupported for %s\n") << (int)bih.BitCount() << file->path() );
238  return NULL;
239  }
240  }
241 
242  file->close();
243 
244  // convert BGRA to RGBA
245  img = img->convertFormat(IF_RGBA);
246 
247  // set alpha channel to 0xFF
248  for(int h=0; h<img->height(); ++h)
249  {
250  unsigned char* px = img->pixels() + img->pitch()*h;
251  for(int x=0; x<img->width()*4; x+=4)
252  px[x+3] = 0xFF;
253  }
254 
255  // flip the image
256  if (flip)
257  img->flipVertically();
258 
259  return img;
260 }
261 //-----------------------------------------------------------------------------
263 {
264  if (!file->open(OM_ReadOnly))
265  return false;
266 
267  BitmapFileHeader bfh;
268  memset(&bfh, 0, sizeof(bfh));
269  BitmapInfoHeader bih;
270  memset(&bih, 0, sizeof(bih));
271 
272  file->read(&bfh, sizeof(bfh));
273  file->read(&bih, sizeof(bih));
274  file->close();
275 
276  if (bfh.Type() != 0x4D42)
277  {
278  return false;
279  }
280 
281  // check bit count
282  switch( bih.BitCount() )
283  {
284  case 1:
285  case 4:
286  case 8:
287  case 16:
288  case 24:
289  case 32:
290  break;
291  default:
292  return false;
293  }
294 
295  // check compression
296  switch( bih.Compression() )
297  {
298  case 0:
299  case 1:
300  case 2:
301  case 3:
302  case 4:
303  case 5:
304  break;
305  default:
306  return false;
307  }
308 
309  return true;
310 }
311 //-----------------------------------------------------------------------------
long long read(void *buffer, long long byte_count)
Reads byte_count bytes from a file. Returns the number of bytes actually read.
Definition: VirtualFile.cpp:82
VLCORE_EXPORT FileSystem * defFileSystem()
Returns the default FileSystem used by VisualizationLibrary.
Definition: pimpl.cpp:97
VLCORE_EXPORT ref< Image > loadBMP(VirtualFile *file)
Definition: ioBMP.cpp:116
const T * get() const
Definition: Object.hpp:128
An abstract class representing a file.
Definition: VirtualFile.hpp:60
void convert8ToRGBA(const TPalette3x256 &palette, void *buf, int w, int h, unsigned char alpha, int bytealign=1)
Definition: ImageTools.hpp:117
A simple String formatting class.
Definition: Say.hpp:124
const unsigned char * pixels() const
Raw pointer to pixels.
Definition: Image.hpp:170
void setObjectName(const char *name)
The name of the object, by default set to the object&#39;s class name in debug builds.
Definition: Object.hpp:220
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
virtual ref< VirtualFile > locateFile(const String &full_path, const String &alternate_path=String()) const
Looks for a VirtualFile on the disk and in the currently active FileSystem.
Definition: FileSystem.cpp:61
virtual void close()=0
Closes the file.
const String & path() const
Returns the path of the file.
Definition: VirtualFile.hpp:98
Visualization Library main namespace.
void convertRGBToRGBA(void *buf, int w, int h, unsigned char alpha, int bytealign=1)
Definition: ImageTools.hpp:43
int height() const
Definition: Image.hpp:209
int width() const
Definition: Image.hpp:207
virtual bool open(EOpenMode mode)=0
Opens the file in the specified mode.
int pitch() const
Definition: Image.hpp:213
#define NULL
Definition: OpenGLDefs.hpp:81
bool seekSet(long long offset)
Changes the current read/write position of a file.
ref< Image > convertFormat(EImageFormat new_format) const
Converts the format() of an image.
Definition: Image.cpp:1719
VLCORE_EXPORT bool isBMP(VirtualFile *file)
Definition: ioBMP.cpp:262
Implements a generic 1d, 2d, 3d and cubemap image that can have mipmaps.
Definition: Image.hpp:54
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
void allocate2D(int x, int y, int bytealign, EImageFormat format, EImageType type)
Definition: Image.cpp:608
std::string toStdString() const
Returns a UTF8 encoded std::string.
Definition: String.cpp:1156
long long position() const
Returns the current position in the file.
Definition: VirtualFile.cpp:98
#define VL_CHECK(expr)
Definition: checks.hpp:73
void flipVertically()
Definition: Image.cpp:942
unsigned char TPalette4x256[256 *4]
Definition: ImageTools.hpp:41