Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/nall/bmp.hpp
2 views
1
#ifndef NALL_BMP_HPP
2
#define NALL_BMP_HPP
3
4
#include <nall/file.hpp>
5
6
//BMP reader / writer
7
//author: byuu
8
//note: only 24-bit RGB and 32-bit ARGB uncompressed images supported
9
10
namespace nall {
11
12
struct bmp {
13
inline static bool read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height);
14
inline static bool write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha = false);
15
};
16
17
bool bmp::read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height) {
18
file fp;
19
if(fp.open(filename, file::mode::read) == false) return false;
20
if(fp.size() < 0x36) return false;
21
22
if(fp.readm(2) != 0x424d) return false;
23
fp.seek(0x000a);
24
unsigned offset = fp.readl(4);
25
unsigned dibsize = fp.readl(4);
26
if(dibsize != 40) return false;
27
signed headerWidth = fp.readl(4);
28
if(headerWidth < 0) return false;
29
signed headerHeight = fp.readl(4);
30
fp.readl(2);
31
unsigned bitsPerPixel = fp.readl(2);
32
if(bitsPerPixel != 24 && bitsPerPixel != 32) return false;
33
unsigned compression = fp.readl(4);
34
if(compression != 0) return false;
35
fp.seek(offset);
36
37
bool noFlip = headerHeight < 0;
38
width = headerWidth, height = abs(headerHeight);
39
data = new uint32_t[width * height];
40
41
unsigned bytesPerPixel = bitsPerPixel / 8;
42
unsigned alignedWidth = width * bytesPerPixel;
43
unsigned paddingLength = 0;
44
while(alignedWidth % 4) alignedWidth++, paddingLength++;
45
46
for(unsigned y = 0; y < height; y++) {
47
uint32_t *p = noFlip ? data + y * width : data + (height - 1 - y) * width;
48
for(unsigned x = 0; x < width; x++, p++) {
49
*p = fp.readl(bytesPerPixel);
50
if(bytesPerPixel == 3) *p |= 255 << 24;
51
}
52
if(paddingLength) fp.readl(paddingLength);
53
}
54
55
fp.close();
56
return true;
57
}
58
59
bool bmp::write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha) {
60
file fp;
61
if(fp.open(filename, file::mode::write) == false) return false;
62
63
unsigned bitsPerPixel = alpha ? 32 : 24;
64
unsigned bytesPerPixel = bitsPerPixel / 8;
65
unsigned alignedWidth = width * bytesPerPixel;
66
unsigned paddingLength = 0;
67
unsigned imageSize = alignedWidth * height;
68
unsigned fileSize = 0x36 + imageSize;
69
while(alignedWidth % 4) alignedWidth++, paddingLength++;
70
71
fp.writem(0x424d, 2); //signature
72
fp.writel(fileSize, 4); //file size
73
fp.writel(0, 2); //reserved
74
fp.writel(0, 2); //reserved
75
fp.writel(0x36, 4); //offset
76
77
fp.writel(40, 4); //DIB size
78
fp.writel(width, 4); //width
79
fp.writel(-height, 4); //height
80
fp.writel(1, 2); //color planes
81
fp.writel(bitsPerPixel, 2); //bits per pixel
82
fp.writel(0, 4); //compression method (BI_RGB)
83
fp.writel(imageSize, 4); //image data size
84
fp.writel(3780, 4); //horizontal resolution
85
fp.writel(3780, 4); //vertical resolution
86
fp.writel(0, 4); //palette size
87
fp.writel(0, 4); //important color count
88
89
for(unsigned y = 0; y < height; y++) {
90
const uint32_t *p = (const uint32_t*)((const uint8_t*)data + y * pitch);
91
for(unsigned x = 0; x < width; x++) fp.writel(*p++, bytesPerPixel);
92
if(paddingLength) fp.writel(0, paddingLength);
93
}
94
95
fp.close();
96
return true;
97
}
98
99
}
100
101
#endif
102
103