-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlibbmp.c
More file actions
181 lines (166 loc) · 4.34 KB
/
libbmp.c
File metadata and controls
181 lines (166 loc) · 4.34 KB
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
//Created by Ben Myshkowec
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "libbmp.h"
int is_host_le()
{
volatile uint32_t x = 1;
volatile uint8_t *y = (volatile char *) &x;
return *y;
}
uint32_t my_htole32(uint32_t i)
{
if (!is_host_le())
{
uint8_t *x = (uint8_t *) &i;
uint8_t t = x[3];
x[3] = x[0];
x[0] = t;
t = x[2];
x[2] = x[1];
x[1] = t;
}
return i;
}
uint16_t my_htole16(uint16_t i)
{
if (!is_host_le())
{
uint8_t *x = (uint8_t *) &i;
uint8_t t = x[1];
x[1] = x[0];
x[0] = t;
}
return i;
}
int bmp_write(const char *path, bmp_info_t *info)
{
FILE *f = fopen(path, "wb");
if (!f)
{
return -1;
}
int i, j;
uint32_t header_size = 14;
uint32_t dib_header_size = 108;
uint32_t offset_pixel_array = header_size + dib_header_size;
// unsigned 1 byte
uint8_t b1;
// unsigned 2 bytes
uint16_t b2;
// unsigned 4 bytes
uint32_t b4;
// header
// ASCII 'B'
b1 = 0x42;
fwrite(&b1, 1, 1, f);
// ASCII 'M'
b1 = 0x4D;
fwrite(&b1, 1, 1, f);
// file size
b4 = htole32(offset_pixel_array + info->width * info->height);
fwrite(&b4, 4, 1, f);
// reserved 1
b2 = 0;
fwrite(&b2, 2, 1, f);
// reserved 2
b2 = 0;
fwrite(&b2, 2, 1, f);
// offset of pixel array
b4 = htole32(offset_pixel_array);
fwrite(&b4, 4, 1, f);
// DIB header
// using version BITMAPV4HEADER
// size of header
b4 = htole32(dib_header_size);
fwrite(&b4, 4, 1, f);
// bitmap width
b4 = htole32(info->width);
fwrite(&b4, 4, 1, f);
// bitmap height
b4 = htole32(info->height);
fwrite(&b4, 4, 1, f);
// number of color panes
b2 = htole16(1);
fwrite(&b2, 2, 1, f);
// color depth - 32bpp is the only depth supported by this implementation
b2 = htole16(32);
fwrite(&b2, 2, 1, f);
// compression method - BI_BITFIELDS is the only one supported by this implementation
b4 = htole32(3);
fwrite(&b4, 4, 1, f);
// image size in bytes
b4 = htole32(info->width * info->height * 4);
fwrite(&b4, 4, 1, f);
// horizontal resolution in pixel per meter - 72 DPI
b4 = htole32(2835);
fwrite(&b4, 4, 1, f);
// vertical resolution in pixel per meter - 72 DPI
b4 = htole32(2835);
fwrite(&b4, 4, 1, f);
// number of colors in the color palatte - 0 means default to 2^n
b4 = 0;
fwrite(&b4, 4, 1, f);
// number of important colors used - 0 means every color is important
b4 = 0;
fwrite(&b4, 4, 1, f);
// red mask - only valid for BI_BITFIELDS
b4 = htole32(0x00FF0000);
fwrite(&b4, 4, 1, f);
// green mask - only valid for BI_BITFIELDS
b4 = htole32(0x0000FF00);
fwrite(&b4, 4, 1, f);
// blue mask - only valid for BI_BITFIELDS
b4 = htole32(0x000000FF);
fwrite(&b4, 4, 1, f);
// alpha mask - required
b4 = htole32(0xFF000000);
fwrite(&b4, 4, 1, f);
// DIB color space
b4 = htole32(0x73524742); // ASCII "sRGB"
fwrite(&b4, 4, 1, f);
// CIEXYZTRIPLE Color Space endpoints - unused for sRGB, Wikipedia says this is 36 bytes
for (i = 0; i < 36; i++)
{
b1 = 0;
fwrite(&b1, 1, 1, f);
}
// red gamma - unused for sRGB
b4 = 0;
fwrite(&b4, 4, 1, f);
// green gamma - unused for sRGB
b4 = 0;
fwrite(&b4, 4, 1, f);
// blue gamma - unused for sRGB
b4 = 0;
fwrite(&b4, 4, 1, f);
// pixel array
for (i = info->height - 1; i >= 0; i--)
{
for (j = 0; j < info->width; j++)
{
// write one pixel in format ARGB (BGRA little-endian)
// what this line does: pixel = &((*(info->pixels))[i][j])
bmp_pixel_t *pixel = bmp_pixels(info, i, j);
// array length 4 of unsigned 1 byte
uint8_t b1_4[4];
b1_4[0] = pixel->blue;
b1_4[1] = pixel->green;
b1_4[2] = pixel->red;
b1_4[3] = pixel->alpha;
fwrite(b1_4, 1, 4, f);
}
}
fclose(f);
return 0;
}
bmp_pixel_t get_bmp_pixel(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
{
bmp_pixel_t pixel;
pixel.alpha = alpha;
pixel.red = red;
pixel.green = green;
pixel.blue = blue;
return pixel;
}