1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
/**
* @module cwindowsbitmap
* @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
* @brief Implementation of CBitmap handling Windows Bitmaps.
* @date 17.04.2009
*/
#include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <assert.h>
#ifdef DEBUG
# include <iostream>
#endif
#include "cwindowsbitmap.h"
#include "cpixelformat_bgr24.h"
#include "cpixelformat_bgr555.h"
using namespace std;
CWindowsBitmap::CWindowsBitmap()
{
m_types.insert("BMP");
/* add our handlers */
m_handlers.insert(new CPixelFormat_BGR24(this));
m_handlers.insert(new CPixelFormat_BGR555(this));
}
/*----------------------------------------------------------------------------*/
void CWindowsBitmap::read(std::ifstream& in)
{
/* read and check file header */
in.read(reinterpret_cast<char *>(&m_fileheader), sizeof(m_fileheader));
if (m_fileheader.bfType[0] != 'B' || m_fileheader.bfType[1] != 'M')
throw FileError("Imagefile has invalid Bitmap header.");
/* bfSize is unreliable (http://de.wikipedia.org/wiki/Windows_Bitmap) */
if (m_fileheader.bfSize < 0)
throw FileError("Bitmap filesize is less than zero?");
/* read and check info header */
in.read(reinterpret_cast<char *>(&m_infoheader), sizeof(m_infoheader));
if (m_infoheader.biSize != 40)
throw FileError("Bitmap info header size is invalid.");
if (m_infoheader.biPlanes != 1)
throw FileError("Bitmap color planes is not set to 1.");
if (m_infoheader.biCompression != 0)
throw FileError("Bitmap compression is set but not supported.");
if (m_infoheader.biSizeImage < 0)
throw FileError("Bitmap image size is less than zero?");
if (m_infoheader.biClrUsed != 0 || m_infoheader.biClrImportant != 0)
throw FileError("Bitmap colortable is used but not supported.");
/* read pixel data using separate class */
if (m_infoheader.biSizeImage > 0)
{
if (m_pixeldata != NULL)
delete[] m_pixeldata;
m_pixeldata = new uint8_t[m_infoheader.biSizeImage];
assert(m_fileheader.bfOffBits > 0);
in.seekg(m_fileheader.bfOffBits);
in.read(reinterpret_cast<char *>(m_pixeldata), m_infoheader.biSizeImage);
}
/* get pixelformat instance */
m_pixelformat = NULL;
set<CPixelFormat *>::iterator it;
for (it = m_handlers.begin(); it != m_handlers.end(); it++)
{
if (m_infoheader.biBitCount == (*it)->getBitCount())
{
m_pixelformat = *it;
break;
}
}
if (m_pixelformat == NULL)
throw FileError("Bitmap bitcount is not supported.");
/* calc rowsize - boundary is 32 */
m_rowsize = 4 * static_cast<uint32_t>(
((m_pixelformat->getBitCount() * m_infoheader.biWidth) + 31) / 32
);
}
/*----------------------------------------------------------------------------*/
void CWindowsBitmap::write(std::ofstream& out)
{
/* set header values */
m_fileheader.bfSize = m_infoheader.biSizeImage + sizeof(m_infoheader) + sizeof(m_fileheader);
/* write file header */
out.write(reinterpret_cast<char *>(&m_fileheader), sizeof(m_fileheader));
/* write info header */
out.write(reinterpret_cast<char *>(&m_infoheader), sizeof(m_infoheader));
/* write pixel data */
if (m_pixeldata != NULL)
out.write(reinterpret_cast<char *>(m_pixeldata), m_infoheader.biSizeImage);
}
/*----------------------------------------------------------------------------*/
#ifdef DEBUG
void CWindowsBitmap::dump(std::ostream& out)
{
out
<< "Bitmap File Header:" << endl
<< " bfType=" << m_fileheader.bfType[0] << m_fileheader.bfType[1]
<< ", bfSize=" << m_fileheader.bfSize
<< ", bfReserved=" << m_fileheader.bfReserved
<< ", bfOffBits=" << m_fileheader.bfOffBits
<< endl;
out
<< "Bitmap Info Header:" << endl
<< " biSize=" << m_infoheader.biSize
<< ", biWidth=" << m_infoheader.biWidth
<< ", biHeight=" << m_infoheader.biHeight
<< ", biPlanes=" << m_infoheader.biPlanes
<< endl
<< " biBitCount=" << m_infoheader.biBitCount
<< ", biCompression=" << m_infoheader.biCompression
<< ", biSizeImage=" << m_infoheader.biSizeImage
<< endl
<< " biXPelsPerMeter=" << m_infoheader.biXPelsPerMeter
<< ", biYPelsPerMeter=" << m_infoheader.biYPelsPerMeter
<< ", biClrUsed=" << m_infoheader.biClrUsed
<< ", biClrImportant=" << m_infoheader.biClrImportant
<< endl;
}
#endif
/* vim: set et sw=2 ts=2: */
|