1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #include "Debug/BsBitmapWriter.h" |
4 | |
5 | namespace bs |
6 | { |
7 | #pragma pack(push, 2) // Align to 2byte boundary so we don't get extra 2 bytes for this struct |
8 | |
9 | struct |
10 | { |
11 | UINT16 ; |
12 | UINT32 ; |
13 | UINT32 ; |
14 | UINT32 ; |
15 | UINT32 ; |
16 | UINT32 ; |
17 | UINT32 ; |
18 | UINT16 ; |
19 | UINT16 ; |
20 | UINT32 ; |
21 | UINT32 ; |
22 | UINT32 ; |
23 | UINT32 ; |
24 | UINT32 ; |
25 | UINT32 ; |
26 | |
27 | }; |
28 | |
29 | #pragma pack(pop) |
30 | |
31 | void BitmapWriter::rawPixelsToBMP(const UINT8* input, UINT8* output, UINT32 width, UINT32 height, UINT32 bytesPerPixel) |
32 | { |
33 | UINT16 bmpBytesPerPixel = 3; |
34 | if(bytesPerPixel >= 4) |
35 | bmpBytesPerPixel = 4; |
36 | |
37 | UINT32 padding = (width * bmpBytesPerPixel) % 4; |
38 | if(padding != 0) |
39 | padding = 4 - padding; |
40 | |
41 | UINT32 rowPitch = (width * bmpBytesPerPixel) + padding; |
42 | UINT32 dataSize = height * rowPitch; |
43 | |
44 | BMP_HEADER ; |
45 | header.BM = 0x4d42; |
46 | header.size_of_file = sizeof(header) + dataSize; |
47 | header.reserve = 0000; |
48 | header.offset_of_pixel_data = 54; |
49 | header.size_of_header = 40; |
50 | header.width = width; |
51 | header.hight = height; |
52 | header.num_of_color_plane = 1; |
53 | header.num_of_bit_per_pix = bmpBytesPerPixel * 8; |
54 | header.compression = 0; |
55 | header.size_of_pix_data = dataSize; |
56 | header.h_resolution = 2835; |
57 | header.v_resolution = 2835; |
58 | header.num_of_color_in_palette = 0; |
59 | header.important_colors = 0; |
60 | |
61 | // Write header |
62 | memcpy(output, &header, sizeof(header)); |
63 | output += sizeof(header); |
64 | |
65 | // Write bytes |
66 | UINT32 widthBytes = width * bytesPerPixel; |
67 | |
68 | // BPP matches so we can just copy directly |
69 | if(bmpBytesPerPixel == bytesPerPixel) |
70 | { |
71 | for(INT32 y = height - 1; y >= 0 ; y--) |
72 | { |
73 | UINT8* outputPtr = output + y * rowPitch; |
74 | |
75 | memcpy(outputPtr, input, widthBytes); |
76 | memset(outputPtr + widthBytes, 0, padding); |
77 | |
78 | input += widthBytes; |
79 | } |
80 | } |
81 | else if(bmpBytesPerPixel < bytesPerPixel) // More bytes in source than supported in BMP, just truncate excess data |
82 | { |
83 | for(INT32 y = height - 1; y >= 0 ; y--) |
84 | { |
85 | UINT8* outputPtr = output + y * rowPitch; |
86 | |
87 | for(UINT32 x = 0; x < width; x++) |
88 | { |
89 | memcpy(outputPtr, input, bmpBytesPerPixel); |
90 | outputPtr += bmpBytesPerPixel; |
91 | input += bytesPerPixel; |
92 | } |
93 | |
94 | memset(outputPtr, 0, padding); |
95 | } |
96 | } |
97 | else // More bytes in BMP than in source (BMP must be 24bit minimum) |
98 | { |
99 | for(INT32 y = height - 1; y >= 0 ; y--) |
100 | { |
101 | UINT8* outputPtr = output + y * rowPitch; |
102 | |
103 | for(UINT32 x = 0; x < width; x++) |
104 | { |
105 | memcpy(outputPtr, input, bytesPerPixel); |
106 | |
107 | // Fill the empty bytes with the last available byte from input |
108 | UINT32 remainingBytes = bmpBytesPerPixel - bytesPerPixel; |
109 | while(remainingBytes > 0) |
110 | { |
111 | memcpy(outputPtr + (bmpBytesPerPixel - remainingBytes), input, 1); |
112 | remainingBytes--; |
113 | } |
114 | |
115 | outputPtr += bmpBytesPerPixel; |
116 | input += bytesPerPixel; |
117 | } |
118 | |
119 | memset(outputPtr, 0, padding); |
120 | } |
121 | } |
122 | } |
123 | |
124 | UINT32 BitmapWriter::getBMPSize(UINT32 width, UINT32 height, UINT32 bytesPerPixel) |
125 | { |
126 | UINT16 bmpBytesPerPixel = 3; |
127 | if(bytesPerPixel >= 4) |
128 | bmpBytesPerPixel = 4; |
129 | |
130 | UINT32 padding = (width * bmpBytesPerPixel) % 4; |
131 | if(padding != 0) |
132 | padding = 4 - padding; |
133 | |
134 | UINT32 rowPitch = (width * bmpBytesPerPixel) + padding; |
135 | UINT32 dataSize = height * rowPitch; |
136 | |
137 | return sizeof(BMP_HEADER) + dataSize; |
138 | } |
139 | } |