10
10
11
11
namespace Gfx {
12
12
13
- constexpr int bytes_per_pixel = 3 ;
14
-
15
- #define FILE_HEADER_SIZE 14
16
- #define IMAGE_INFORMATION_SIZE 40
17
- #define PIXEL_DATA_OFFSET FILE_HEADER_SIZE + IMAGE_INFORMATION_SIZE
18
-
19
13
class OutputStreamer {
20
14
public:
21
15
OutputStreamer (u8 * data)
@@ -49,7 +43,7 @@ class OutputStreamer {
49
43
u8 * m_data;
50
44
};
51
45
52
- static ByteBuffer write_pixel_data (const RefPtr<Bitmap> bitmap, int pixel_row_data_size)
46
+ static ByteBuffer write_pixel_data (const RefPtr<Bitmap> bitmap, int pixel_row_data_size, int bytes_per_pixel, bool include_alpha_channel )
53
47
{
54
48
int image_size = pixel_row_data_size * bitmap->height ();
55
49
auto buffer = ByteBuffer::create_uninitialized (image_size);
@@ -62,6 +56,8 @@ static ByteBuffer write_pixel_data(const RefPtr<Bitmap> bitmap, int pixel_row_da
62
56
row[x * bytes_per_pixel + 0 ] = pixel.blue ();
63
57
row[x * bytes_per_pixel + 1 ] = pixel.green ();
64
58
row[x * bytes_per_pixel + 2 ] = pixel.red ();
59
+ if (include_alpha_channel)
60
+ row[x * bytes_per_pixel + 3 ] = pixel.alpha ();
65
61
}
66
62
}
67
63
@@ -71,41 +67,74 @@ static ByteBuffer write_pixel_data(const RefPtr<Bitmap> bitmap, int pixel_row_da
71
67
static ByteBuffer compress_pixel_data (const ByteBuffer& pixel_data, BMPWriter::Compression compression)
72
68
{
73
69
switch (compression) {
74
- case BMPWriter::Compression::RGB:
70
+ case BMPWriter::Compression::BI_BITFIELDS:
71
+ case BMPWriter::Compression::BI_RGB:
75
72
return pixel_data;
76
73
}
77
74
78
75
VERIFY_NOT_REACHED ();
79
76
}
80
77
81
- ByteBuffer BMPWriter::dump (const RefPtr<Bitmap> bitmap)
78
+ ByteBuffer BMPWriter::dump (const RefPtr<Bitmap> bitmap, DibHeader dib_header )
82
79
{
83
- int pixel_row_data_size = (bytes_per_pixel * 8 * bitmap->width () + 31 ) / 32 * 4 ;
80
+
81
+ switch (dib_header) {
82
+ case DibHeader::Info:
83
+ m_compression = Compression::BI_RGB;
84
+ m_bytes_per_pixel = 3 ;
85
+ m_include_alpha_channel = false ;
86
+ break ;
87
+ case DibHeader::V3:
88
+ case DibHeader::V4:
89
+ m_compression = Compression::BI_BITFIELDS;
90
+ m_bytes_per_pixel = 4 ;
91
+ m_include_alpha_channel = true ;
92
+ }
93
+
94
+ const size_t file_header_size = 14 ;
95
+ size_t pixel_data_offset = file_header_size + (u32 )dib_header;
96
+
97
+ int pixel_row_data_size = (m_bytes_per_pixel * 8 * bitmap->width () + 31 ) / 32 * 4 ;
84
98
int image_size = pixel_row_data_size * bitmap->height ();
85
- auto buffer = ByteBuffer::create_uninitialized (PIXEL_DATA_OFFSET );
99
+ auto buffer = ByteBuffer::create_uninitialized (pixel_data_offset );
86
100
87
- auto pixel_data = write_pixel_data (bitmap, pixel_row_data_size);
101
+ auto pixel_data = write_pixel_data (bitmap, pixel_row_data_size, m_bytes_per_pixel, m_include_alpha_channel );
88
102
pixel_data = compress_pixel_data (pixel_data, m_compression);
89
103
90
- int file_size = PIXEL_DATA_OFFSET + pixel_data.size ();
104
+ size_t file_size = pixel_data_offset + pixel_data.size ();
91
105
OutputStreamer streamer (buffer.data ());
92
106
streamer.write_u8 (' B' );
93
107
streamer.write_u8 (' M' );
94
108
streamer.write_u32 (file_size);
95
109
streamer.write_u32 (0 );
96
- streamer.write_u32 (PIXEL_DATA_OFFSET);
97
-
98
- streamer.write_u32 (IMAGE_INFORMATION_SIZE); // Header size
99
- streamer.write_i32 (bitmap->width ()); // ImageWidth
100
- streamer.write_i32 (bitmap->height ()); // ImageHeight
101
- streamer.write_u16 (1 ); // Planes
102
- streamer.write_u16 (bytes_per_pixel * 8 ); // BitsPerPixel
103
- streamer.write_u32 ((u32 )m_compression); // Compression
104
- streamer.write_u32 (image_size); // ImageSize
105
- streamer.write_i32 (0 ); // XpixelsPerMeter
106
- streamer.write_i32 (0 ); // YpixelsPerMeter
107
- streamer.write_u32 (0 ); // TotalColors
108
- streamer.write_u32 (0 ); // ImportantColors
110
+ streamer.write_u32 (pixel_data_offset);
111
+
112
+ streamer.write_u32 ((u32 )dib_header); // Header size
113
+ streamer.write_i32 (bitmap->width ()); // ImageWidth
114
+ streamer.write_i32 (bitmap->height ()); // ImageHeight
115
+ streamer.write_u16 (1 ); // Planes
116
+ streamer.write_u16 (m_bytes_per_pixel * 8 ); // BitsPerPixel
117
+ streamer.write_u32 ((u32 )m_compression); // Compression
118
+ streamer.write_u32 (image_size); // ImageSize
119
+ streamer.write_i32 (0 ); // XpixelsPerMeter
120
+ streamer.write_i32 (0 ); // YpixelsPerMeter
121
+ streamer.write_u32 (0 ); // TotalColors
122
+ streamer.write_u32 (0 ); // ImportantColors
123
+
124
+ if (dib_header == DibHeader::V3 || dib_header == DibHeader::V4) {
125
+ streamer.write_u32 (0x00ff0000 ); // Red bitmask
126
+ streamer.write_u32 (0x0000ff00 ); // Green bitmask
127
+ streamer.write_u32 (0x000000ff ); // Blue bitmask
128
+ streamer.write_u32 (0xff000000 ); // Alpha bitmask
129
+ }
130
+
131
+ if (dib_header == DibHeader::V4) {
132
+ streamer.write_u32 (0 ); // Colorspace
133
+
134
+ for (int i = 0 ; i < 12 ; i++) {
135
+ streamer.write_u32 (0 ); // Endpoints
136
+ }
137
+ }
109
138
110
139
buffer.append (pixel_data.data (), pixel_data.size ());
111
140
return buffer;
0 commit comments