smntc
an in-memory multimodal graph database
Loading...
Searching...
No Matches
Bmp.c
Go to the documentation of this file.
1// Adapted https://github.com/vallentin/LoadBMP
2#include <stdlib.h>
3#include <string.h>
4#include <stdio.h>
5#include "errors.h"
6
7#define RGB_COLOR_LENGTH 3
8#define FILE_HEADER_LENGTH 14
9#define INFO_HEADER_LENGTH 40
10#define PAD_LENGTH 3
11
13struct Bmp {
14 unsigned int width;
15 unsigned int height;
16 unsigned long length;
17 unsigned char *reds;
18 unsigned char *greens;
19 unsigned char *blues;
20};
21
22struct Bmp *Bmp_destruct(struct Bmp *this)
23{
24 if (0 != this) {
25 free(this->reds);
26 free(this->greens);
27 free(this->blues);
28 free(this);
29 }
30
31 return 0;
32}
33
34unsigned int Bmp_getWidth(struct Bmp *this)
35{
36 return this->width;
37}
38
39unsigned int Bmp_getHeight(struct Bmp *this)
40{
41 return this->height;
42}
43
44unsigned long Bmp_getLength(struct Bmp *this)
45{
46 return this->length;
47}
48
49void Bmp_getPixelOfRaster(struct Bmp *this, int horizontal, int vertical, unsigned char *red, unsigned char *green, unsigned char *blue, int *error)
50{
51 unsigned long offset = this->width * vertical + horizontal;
52
53 *red = this->reds[offset];
54 *green = this->greens[offset];
55 *blue = this->blues[offset];
56}
57
58void Bmp_getPixelOfLine(struct Bmp *this, int index, unsigned char *red, unsigned char *green, unsigned char *blue, int *error)
59{
60 *red = this->reds[index];
61 *green = this->greens[index];
62 *blue = this->blues[index];
63}
64
65struct Bmp *Bmp_readFile(const char *filename, int *error)
66{
67 FILE *file = fopen(filename, "rb");
68
69 if (!file)
70 {
71 *error = ERROR_IN_FILE;
72 return 0;
73 }
74
75 unsigned char fileHeader[FILE_HEADER_LENGTH];
76 unsigned char infoHeader[INFO_HEADER_LENGTH];
77 unsigned char pad[PAD_LENGTH];
78 unsigned int width = 0;
79 unsigned int height = 0;
80 unsigned long length = 0;
81 unsigned char *reds = 0;
82 unsigned char *greens = 0;
83 unsigned char *blues = 0;
84 unsigned int x = 0;
85 unsigned int y = 0;
86 unsigned int i = 0;
87 unsigned int padding = 0;
88
89 memset(fileHeader, 0, sizeof(fileHeader));
90 memset(infoHeader, 0, sizeof(infoHeader));
91
92 if (fread(fileHeader, sizeof(fileHeader), 1, file) == 0)
93 {
94 // invalid file format
95 fclose(file);
96
97 *error = ERROR_IN_FILE;
98 return 0;
99 }
100
101 if (fread(infoHeader, sizeof(infoHeader), 1, file) == 0)
102 {
103 // invalid file format
104 fclose(file);
105
106 *error = ERROR_IN_FILE;
107 return 0;
108 }
109
110 if ((fileHeader[0] != 'B') || (fileHeader[1] != 'M'))
111 {
112 // invalid signatue
113 fclose(file);
114
115 *error = ERROR_IN_FILE;
116 return 0;
117 }
118
119 if ((infoHeader[14] != 24) && (infoHeader[14] != 32))
120 {
121 // invalid bits per pixel
122 fclose(file);
123
124 *error = ERROR_IN_FILE;
125 return 0;
126 }
127
128 width = (infoHeader[4] + (infoHeader[5] << 8) + (infoHeader[6] << 16) + (infoHeader[7] << 24));
129 height = (infoHeader[8] + (infoHeader[9] << 8) + (infoHeader[10] << 16) + (infoHeader[11] << 24));
130
131 if ((width > 0) && (height > 0))
132 {
133 length = width * height;
134
135 reds = (unsigned char*)malloc(length);
136
137 if (!reds)
138 {
139 fclose(file);
140 *error = ERROR_NO_MEMORY;
141 return 0;
142 }
143
144 greens = (unsigned char*)malloc(length);
145
146 if (!greens)
147 {
148 fclose(file);
149 *error = ERROR_NO_MEMORY;
150 return 0;
151 }
152
153 blues = (unsigned char*)malloc(length);
154
155 if (!blues)
156 {
157 fclose(file);
158 *error = ERROR_NO_MEMORY;
159 return 0;
160 }
161
162 for (y = (height - 1); y != -1; y--)
163 {
164 for (x = 0; x < width; x++)
165 {
166 i = x + y * width;
167
168 // BGR -> RGB
169
170 if (fread(blues + i, 1, 1, file) == 0)
171 {
172 // invalid file format
173 free(reds);
174 free(blues);
175 free(greens);
176 fclose(file);
177
178 *error = ERROR_IN_FILE;
179 return 0;
180 }
181
182 if (fread(greens + i, 1, 1, file) == 0)
183 {
184 // invalid file format
185 free(reds);
186 free(blues);
187 free(greens);
188 fclose(file);
189
190 *error = ERROR_IN_FILE;
191 return 0;
192 }
193
194 if (fread(reds + i, 1, 1, file) == 0)
195 {
196 // invalid file format
197 free(reds);
198 free(blues);
199 free(greens);
200 fclose(file);
201
202 *error = ERROR_IN_FILE;
203 return 0;
204 }
205 }
206
207 padding = ((4 - (width * 3) % 4) % 4);
208
209 if (fread(pad, 1, padding, file) != padding)
210 {
211 // invalid file format
212 free(reds);
213 free(blues);
214 free(greens);
215 fclose(file);
216
217 *error = ERROR_IN_FILE;
218 return 0;
219 }
220 }
221 }
222
223 fclose(file);
224
225 struct Bmp * this = malloc(sizeof(struct Bmp));
226
227 if (!this) {
228 *error = ERROR_NO_MEMORY;
229 return 0;
230 }
231
232 this->width = width;
233 this->height = height;
234 this->length = length;
235 this->reds = reds;
236 this->greens = greens;
237 this->blues = blues;
238
239 return this;
240}
241
242void Bmp_writeFile(struct Bmp *this, const char *filename, int *error)
243{
244 FILE *file = fopen(filename, "wb");
245
246 if (!file)
247 {
248 *error = ERROR_IN_FILE;
249 return;
250 }
251
252 unsigned char fileHeader[FILE_HEADER_LENGTH] = { 'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0 };
253 unsigned char infoHeader[INFO_HEADER_LENGTH] = { 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0 };
254 const unsigned char pad[PAD_LENGTH] = { 0, 0, 0 };
255
256 const unsigned int size = (FILE_HEADER_LENGTH + INFO_HEADER_LENGTH) + this->width * this->height * RGB_COLOR_LENGTH; // 3 as the BMP format uses 3 channels (red, green, blue and NO alpha)
257
258 unsigned int x = 0;
259 unsigned int y = 0;
260 unsigned int i = 0;
261 unsigned int padding = 0;
262
263 fileHeader[2] = (unsigned char)(size);
264 fileHeader[3] = (unsigned char)(size >> 8);
265 fileHeader[4] = (unsigned char)(size >> 16);
266 fileHeader[5] = (unsigned char)(size >> 24);
267
268 infoHeader[4] = (unsigned char)(this->width);
269 infoHeader[5] = (unsigned char)(this->width >> 8);
270 infoHeader[6] = (unsigned char)(this->width >> 16);
271 infoHeader[7] = (unsigned char)(this->width >> 24);
272
273 infoHeader[8] = (unsigned char)(this->height);
274 infoHeader[9] = (unsigned char)(this->height >> 8);
275 infoHeader[10] = (unsigned char)(this->height >> 16);
276 infoHeader[11] = (unsigned char)(this->height >> 24);
277
278 if (fwrite(fileHeader, FILE_HEADER_LENGTH, 1, file) == 0)
279 {
280 fclose(file);
281
282 *error = ERROR_IN_FILE;
283 return;
284 }
285
286 if (fwrite(infoHeader, INFO_HEADER_LENGTH, 1, file) == 0)
287 {
288 fclose(file);
289
290 *error = ERROR_IN_FILE;
291 return;
292 }
293
294 for (y = (this->height - 1); y != -1; y--)
295 {
296 for (x = 0; x < this->width; x++)
297 {
298 i = (x + y * this->width) * RGB_COLOR_LENGTH;
299
300 // RGB -> BGR
301
302 if (fwrite(&this->blues[i], 1, 1, file) == 0)
303 {
304 fclose(file);
305 *error = ERROR_IN_FILE;
306 return;
307 }
308
309 if (fwrite(&this->greens[i], 1, 1, file) == 0)
310 {
311 fclose(file);
312 *error = ERROR_IN_FILE;
313 return;
314 }
315
316 if (fwrite(&this->reds[i], 1, 1, file) == 0)
317 {
318 fclose(file);
319 *error = ERROR_IN_FILE;
320 return;
321 }
322 }
323
324 padding = ((4 - (this->width * 3) % 4) % 4);
325
326 if (fwrite(pad, 1, padding, file) != padding)
327 {
328 fclose(file);
329 *error = ERROR_IN_FILE;
330 return;
331 }
332 }
333
334 fclose(file);
335}
struct Bmp * Bmp_readFile(const char *filename, int *error)
It loads an image file with the bmp format into memory.
Definition Bmp.c:65
unsigned long Bmp_getLength(struct Bmp *this)
It supplies the number of pixels.
Definition Bmp.c:44
#define FILE_HEADER_LENGTH
Definition Bmp.c:8
void Bmp_getPixelOfLine(struct Bmp *this, int index, unsigned char *red, unsigned char *green, unsigned char *blue, int *error)
It supplies three colors of a pixel when the horizontal and vertical positions of a raster are provid...
Definition Bmp.c:58
#define INFO_HEADER_LENGTH
Definition Bmp.c:9
unsigned int Bmp_getWidth(struct Bmp *this)
Definition Bmp.c:34
unsigned int Bmp_getHeight(struct Bmp *this)
It supplies the height of an image.
Definition Bmp.c:39
struct Bmp * Bmp_destruct(struct Bmp *this)
It destructs a managing object for one image.
Definition Bmp.c:22
#define PAD_LENGTH
Definition Bmp.c:10
#define RGB_COLOR_LENGTH
Definition Bmp.c:7
void Bmp_writeFile(struct Bmp *this, const char *filename, int *error)
It writes an image in a file in bmp format.
Definition Bmp.c:242
void Bmp_getPixelOfRaster(struct Bmp *this, int horizontal, int vertical, unsigned char *red, unsigned char *green, unsigned char *blue, int *error)
It supplies three colors of a pixel when the horizontal and vertical positions of a raster are provid...
Definition Bmp.c:49
#define ERROR_NO_MEMORY
Definition errors.h:5
#define ERROR_IN_FILE
Definition errors.h:16
It stores an image in memory.
Definition Bmp.c:13
unsigned long length
the length of each color channel
Definition Bmp.c:16
unsigned char * blues
the blue channel as an array of bytes
Definition Bmp.c:19
unsigned char * reds
the red channel as an array of bytes
Definition Bmp.c:17
unsigned char * greens
the green channel as an array of bytes
Definition Bmp.c:18
unsigned int height
the height of an image
Definition Bmp.c:15
unsigned int width
the width of an image
Definition Bmp.c:14