-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibbmp.cpp
196 lines (159 loc) · 3.97 KB
/
libbmp.cpp
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/* Copyright 2016 - 2017 Marc Volker Dickmann
* Project: LibBMP
*/
#include <fstream>
#include <cmath>
#include "libbmp.h"
//
// BmpPixbuf
//
BmpPixbuf::BmpPixbuf (void)
{
}
BmpPixbuf::BmpPixbuf (const int width,
const int height)
{
init (width, height);
}
BmpPixbuf::~BmpPixbuf (void)
{
data.clear ();
}
void
BmpPixbuf::init (const int width,
const int height)
{
len_row = width * len_pixel;
data.resize (height * len_row);
}
void
BmpPixbuf::set_pixel (const int x,
const int y,
const unsigned char r,
const unsigned char g,
const unsigned char b)
{
const size_t index = (x * len_pixel) + (y * len_row);
data[index] = b;
data[index + 1] = g;
data[index + 2] = r;
}
unsigned char
BmpPixbuf::red_at (const int x,
const int y)
{
return data[(x * len_pixel) + (y * len_row) + 2];
}
unsigned char
BmpPixbuf::green_at (const int x,
const int y)
{
return data[(x * len_pixel) + (y * len_row) + 1];
}
unsigned char
BmpPixbuf::blue_at (const int x,
const int y)
{
return data[(x * len_pixel) + (y * len_row)];
}
void
BmpPixbuf::write (const int row,
std::ofstream& f)
{
f.write (reinterpret_cast<char*> (&data[row * len_row]), len_row);
}
void
BmpPixbuf::read (const int row,
std::ifstream& f)
{
f.read (reinterpret_cast<char*> (&data[row * len_row]), len_row);
}
//
// BmpImg
//
BmpImg::BmpImg (void)
{
}
BmpImg::BmpImg (const int width,
const int height) : BmpPixbuf (width, std::abs (height))
{
// INIT the header with default values
header.bfSize = (3 * width + BMP_GET_PADDING (width))
* std::abs (height);
header.biWidth = width;
header.biHeight = height;
}
BmpImg::~BmpImg (void)
{
}
int
BmpImg::get_width (void)
{
return header.biWidth;
}
int
BmpImg::get_height (void)
{
return header.biHeight;
}
enum BmpError
BmpImg::write (const std::string& filename)
{
// Open the image file in binary mode
std::ofstream f_img (filename.c_str (), std::ios::binary);
if (!f_img.is_open ())
return BMP_FILE_NOT_OPENED;
// Since an adress must be passed to fwrite, create a variable!
const unsigned short magic = BMP_MAGIC;
f_img.write (reinterpret_cast<const char*>(&magic), sizeof (magic));
f_img.write (reinterpret_cast<const char*>(&header), sizeof (header));
// Select the mode (bottom-up or top-down)
const int h = std::abs (header.biHeight);
const int offset = (header.biHeight > 0 ? 0 : h - 1);
const int padding = BMP_GET_PADDING (header.biWidth);
for (int y = h - 1; y >= 0; y--)
{
// Write a whole row of pixels into the file
BmpPixbuf::write ((int)std::abs (y - offset), f_img);
// Write the padding
f_img.write ("\0\0\0", padding);
}
// NOTE: All good
f_img.close ();
return BMP_OK;
}
enum BmpError
BmpImg::read (const std::string& filename)
{
// Open the image file in binary mode
std::ifstream f_img (filename.c_str (), std::ios::binary);
if (!f_img.is_open ())
return BMP_FILE_NOT_OPENED;
// Since an adress must be passed to fread, create a variable!
unsigned short magic;
// Check if its an bmp file by comparing the magic nbr
f_img.read(reinterpret_cast<char*>(&magic), sizeof (magic));
if (magic != BMP_MAGIC)
{
f_img.close ();
return BMP_INVALID_FILE;
}
// Read the header structure into header
f_img.read (reinterpret_cast<char*>(&header), sizeof (header));
// Select the mode (bottom-up or top-down)
const int h = std::abs (header.biHeight);
const int offset = (header.biHeight > 0 ? 0 : h - 1);
const int padding = BMP_GET_PADDING (header.biWidth);
// Allocate the pixel buffer
BmpPixbuf::init (header.biWidth, h);
for (int y = h - 1; y >= 0; y--)
{
// Read a whole row of pixels from the file
BmpPixbuf::read ((int)std::abs (y - offset), f_img);
// Skip the padding
f_img.seekg (padding, std::ios::cur);
}
// NOTE: All good
f_img.close ();
return BMP_OK;
}