17 bool saveToBitmap(
string filename,
int width,
int height,
const unsigned char* imageData)
20 fstream imageFile(filename.c_str(), ios::out);
21 if(!imageFile.is_open())
23 cerr <<
"Unable to open " << filename <<
". " << __FILE__ <<
":"<< __LINE__ << endl;
37 int paddedWidth = width * 3;
38 while((paddedWidth % 4) != 0)
44 header.
fileSize =
sizeof(magic) +
sizeof(header) +
sizeof(informationHeader) + paddedWidth * height;
47 header.
offset =
sizeof(magic) +
sizeof(header) +
sizeof(informationHeader);
50 informationHeader.
size =
sizeof(informationHeader);
63 if(imageFile.write((
char*)&magic,
sizeof(magic)).bad() ||
64 imageFile.write((
char*)&header,
sizeof(header)).bad() ||
65 imageFile.write((
char*)&informationHeader,
sizeof(informationHeader)).bad())
67 cerr <<
"Failed to write bitmap header. " << __FILE__ <<
":"<< __LINE__ << endl;
68 if (imageFile.is_open())
75 for (
int y = height - 1; y >= 0; y--)
77 for (
int x = 0; x <
width; x++)
81 rgb[2] = imageData[3 * (y * informationHeader.
width + x) + 0];
82 rgb[1] = imageData[3 * (y * informationHeader.
width + x) + 1];
83 rgb[0] = imageData[3 * (y * informationHeader.
width + x) + 2];
85 if(imageFile.write((
char*)&rgb, 3).bad())
87 if (imageFile.is_open())
98 for (
int x = width * 3; x < paddedWidth; x++)
101 if(imageFile.write(&b, 1).bad())
103 if (imageFile.is_open())
118 ifstream imageFile(filename.c_str(), ios::in);
119 if(!imageFile.is_open())
121 cerr <<
"Unable to open " << filename <<
". " << __FILE__ <<
":"<< __LINE__ << endl;
132 if (imageFile.read((
char*)&magic,
sizeof(magic)).bad() || magic.
magic[0] != 0x42 || magic.
magic[1] != 0x4d)
135 cerr <<
"Not a valid BMP file header. " << __FILE__ <<
":"<< __LINE__ << endl;
136 if (imageFile.is_open())
144 if (imageFile.read((
char*)&header,
sizeof(header)).bad() || header.
offset != 54)
147 cerr <<
"Not a supported BMP format. " << __FILE__ <<
":"<< __LINE__ << endl;
148 if (imageFile.is_open())
155 if (imageFile.read((
char*)&informationHeader,
sizeof(informationHeader)).bad() || informationHeader.
compressionType != 0 || informationHeader.
bitsPerPixel != 24)
158 cerr <<
"We only support uncompressed 24-bits per pixel RGB. " << __FILE__ <<
":"<< __LINE__ << endl;
159 if (imageFile.is_open())
169 if (informationHeader.
height > 0)
173 first_row = informationHeader.
height - 1;
181 after_last_row = informationHeader.
height;
185 int paddedWidth = informationHeader.
width * 3;
186 while((paddedWidth % 4) != 0)
192 int size = 3 * paddedWidth * informationHeader.
height;
193 *imageData =
new unsigned char[
size];
194 unsigned char* readBuffer =
new unsigned char[
size];
197 if (imageFile.read((
char*)readBuffer, size).bad())
199 cerr <<
"Error reading main image data. " << __FILE__ <<
":"<< __LINE__ << endl;
200 if (imageFile.is_open())
204 if (readBuffer != NULL)
206 delete [] readBuffer;
211 int readBufferIndex = 0;
213 for (
int y = first_row; y != after_last_row; y += row_delta)
215 for (
int x = 0; x < informationHeader.
width; x++)
218 (*imageData)[3 * (y * informationHeader.
width + x) + 0] = readBuffer[readBufferIndex + 2];
219 (*imageData)[3 * (y * informationHeader.
width + x) + 1] = readBuffer[readBufferIndex + 1];
220 (*imageData)[3 * (y * informationHeader.
width + x) + 2] = readBuffer[readBufferIndex + 0];
222 readBufferIndex += 3;
225 readBufferIndex += paddedWidth - (informationHeader.
width * 3);
228 *width = informationHeader.
width;
229 *height = informationHeader.
height;
231 if (imageFile.is_open())
235 if (readBuffer != NULL)
237 delete [] readBuffer;
245 if (luminanceData == NULL)
247 cerr <<
"luminanceData cannot be NULL. " << __FILE__ <<
":"<< __LINE__ << endl;
253 cerr <<
"rgbData cannot be NULL. " << __FILE__ <<
":"<< __LINE__ << endl;
257 for (
int n = width * height - 1; n >= 0; --n)
259 unsigned char d = luminanceData[n];
260 rgbData[3 * n + 0] = d;
261 rgbData[3 * n + 1] = d;
262 rgbData[3 * n + 2] = d;
271 cerr <<
"rgbData cannot be NULL. " << __FILE__ <<
":"<< __LINE__ << endl;
275 if (luminanceData == NULL)
277 cerr <<
"luminanceData cannot be NULL. " << __FILE__ <<
":"<< __LINE__ << endl;
281 for (
int n = width * height - 1; n >= 0; --n)
283 float r = rgbData[3 * n + 0];
284 float g = rgbData[3 * n + 1];
285 float b = rgbData[3 * n + 2];
286 luminanceData[n] = (
unsigned char) (0.2126f * r + 0.7152f * g + 0.0722f * b);
295 cerr <<
"rgbData cannot be NULL. " << __FILE__ <<
":"<< __LINE__ << endl;
299 if (rgbaData == NULL)
301 cerr <<
"rgbaData cannot be NULL. " << __FILE__ <<
":"<< __LINE__ << endl;
305 for (
int n = 0; n < width *
height; n++)
308 rgbaData[4 * n + 0] = rgbData[3 * n + 0];
309 rgbaData[4 * n + 1] = rgbData[3 * n + 1];
310 rgbaData[4 * n + 2] = rgbData[3 * n + 2];
313 rgbaData[4 * n + 3] = (
unsigned char)255;
320 if (rgbaData == NULL)
322 cerr <<
"rgbaData cannot be NULL. " << __FILE__ <<
":"<< __LINE__ << endl;
328 cerr <<
"rgbData cannot be NULL. " << __FILE__ <<
":"<< __LINE__ << endl;
332 for (
int n = 0; n < width *
height; n++)
335 rgbData[3 * n + 0] = rgbaData[4 * n + 0];
336 rgbData[3 * n + 1] = rgbaData[4 * n + 1];
337 rgbData[3 * n + 2] = rgbaData[4 * n + 2];