-
Notifications
You must be signed in to change notification settings - Fork 0
/
bmpload.cpp
92 lines (72 loc) · 2.53 KB
/
bmpload.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
#include <stdio.h>
#include <string.h>
#include "bmpload.h"
int bmp_load8_header(const char * fname, BITMAPV5HEADER * head)
{
FILE *f;
if (head == NULL) return 1;
memset(head, 0, sizeof(BITMAPV5HEADER));
// open file
f = fopen(fname, "rb");
if (!f) return 1;
// read file header
BITMAPFILEHEADER bmfile;
if ((fread(&bmfile, sizeof(bmfile), 1, f) != 1) ||
(bmfile.bfType != 0x4D42) ||
(bmfile.bfOffBits > bmfile.bfSize)) {
fclose(f); return 1;
}
// read info header size (to determine header size)
uint32_t infoHeaderSize;
if (fread(&infoHeaderSize, sizeof(infoHeaderSize), 1, f) != 1) {
fclose(f); return 1;
}
// step back and read header
fseek(f, -sizeof(infoHeaderSize), SEEK_CUR);
if ((fread(head, sizeof(BITMAPV5HEADER), 1, f) != 1) ||
(head->bV5Width <= 0) || (head->bV5Planes != 1) || (head->bV5BitCount != 8) || (head->bV5Compression != BI_RGB)) {
fclose(f); return 1;
}
fclose(f);
return 0;
}
// TODO - fix duplicated BITMAPFILEHEADER reading
int bmp_load8_data(const char * fname, BITMAPV5HEADER * head, uint8_t * buf, uint32_t * pal, int order, size_t pitch)
{
if (head == NULL) return 1;
FILE *f;
// open file
f = fopen(fname, "rb");
if (!f) return 1;
// read file header (yes, again)
BITMAPFILEHEADER bmfile;
if ((fread(&bmfile, sizeof(bmfile), 1, f) != 1) ||
(bmfile.bfType != 0x4D42) ||
(bmfile.bfOffBits > bmfile.bfSize)) {
fclose(f); return 1;
}
// skip header
fseek(f, head->bV5Size, SEEK_CUR);
// read palette
if (pal != NULL) {
fseek(f, 0, SEEK_CUR);
// palette is stored as ARGB8888 (except of A = 0), load it as-is
fread(pal, head->bV5Size < sizeof(BITMAPV5HEADER) ? 256 : head->bV5ClrUsed, sizeof(uint32_t), f);
if (ferror(f)) { fclose(f); return 1; }
}
// read pixel data
fseek(f, bmfile.bfOffBits, SEEK_SET);
int raworder = order ^ (head->bV5Height < 0 ? -1 : 0);
if (pitch == 0) pitch = head->bV5Width;
uint8_t *p = (raworder ? buf + pitch * (head->bV5Height - 1) : buf);
signed long srcFixup = (4 - (head->bV5Width & 3) & 3);
for (int i = 0; i < head->bV5Height; i++) {
if (fread(p, head->bV5Width, 1, f) != 1) { fclose(f); return 1; }
if (raworder) p -= pitch; else p += pitch;
// dword alignment fixup
fseek(f, srcFixup, SEEK_CUR);
}
// fix height sign
if (head->bV5Height < 0) head->bV5Height = -head->bV5Height;
return 0;
}