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
|
package main
import (
"encoding/binary"
"os"
)
func WriteBMP24(width, height int, pixels []byte, filename string) error {
rowSize := ((24*width + 31) / 32) * 4
imgSize := rowSize * height
fileSize := 14 + 40 + imgSize
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
// BITMAPFILEHEADER
f.Write([]byte{'B', 'M'})
binary.Write(f, binary.LittleEndian, uint32(fileSize))
binary.Write(f, binary.LittleEndian, uint16(0))
binary.Write(f, binary.LittleEndian, uint16(0))
binary.Write(f, binary.LittleEndian, uint32(54)) // offset
// BITMAPINFOHEADER
binary.Write(f, binary.LittleEndian, uint32(40)) // DIB header size
binary.Write(f, binary.LittleEndian, int32(width))
binary.Write(f, binary.LittleEndian, int32(height))
binary.Write(f, binary.LittleEndian, uint16(1)) // planes
binary.Write(f, binary.LittleEndian, uint16(24)) // bits per pixel
binary.Write(f, binary.LittleEndian, uint32(0)) // compression
binary.Write(f, binary.LittleEndian, uint32(imgSize))
binary.Write(f, binary.LittleEndian, int32(0)) // xppm
binary.Write(f, binary.LittleEndian, int32(0)) // yppm
binary.Write(f, binary.LittleEndian, uint32(0)) // clr used
binary.Write(f, binary.LittleEndian, uint32(0)) // clr important
// Pixel data
padding := make([]byte, rowSize-width*3)
// BMP stores bottom to top
for y := height - 1; y >= 0; y-- {
row := pixels[y*width*3 : (y+1)*width*3]
f.Write(row)
f.Write(padding)
}
return nil
}
|