-
Notifications
You must be signed in to change notification settings - Fork 0
/
BMP.fs
64 lines (56 loc) · 2.47 KB
/
BMP.fs
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
/// The code in this module is attempting to replicate the specification here:
/// https://en.wikipedia.org/wiki/BMP_file_format
/// and here:
/// http://www.ece.ualberta.ca/~elliott/ee552/studentAppNotes/2003_w/misc/bmp_file_format/bmp_file_format.htm
module BMP
open System
let grayscale array =
let width, height = Array2D.length1 array, Array2D.length2 array
// each line width must be divisible by 4.
// as each pixel is three bytes, we need padding bytes
let padding =
let off = (width * 3) % 4
if off = 0 then 0 else 4 - off
let byteSize = ((width * 3) + padding) * height
let as4bytes n = BitConverter.GetBytes (uint32 n)
let as2bytes n = BitConverter.GetBytes (uint16 n)
let zeroIn4bytes = [|0uy;0uy;0uy;0uy|]
// Format is header, dib, pixel data
let header =
[|
"BM" |> Seq.map byte |> Seq.toArray // standard header for BMP
as4bytes (14 + 40 + byteSize) // header is 14, dib is 40, then pixels
zeroIn4bytes // reserved/unused
as4bytes (14 + 40) // offset to byte data
|] |> Array.concat
let dib =
[|
as4bytes 40 // dib size. just a count of all the bytes in this array (including the bytes for the count)
as4bytes width
as4bytes height
as2bytes 1 // planes (=1)
as2bytes 24 // bpp (24bit)
zeroIn4bytes // BI_RGB, no pixel array compression used
as4bytes byteSize // Size of the raw bitmap data (including padding)
as4bytes 2835 // 72dpi horizontal (calc in wiki article)
as4bytes 2835 // 72dpi vertical
zeroIn4bytes // palette colours (0, not using a palette)
zeroIn4bytes // important colours (0=all)
|] |> Array.concat
let pixels =
[| height-1..-1..0 |]
|> Array.map (fun y ->
let row =
[|0..width-1|]
|> Array.collect (fun x ->
let v = array.[x, y]
let gs = int (v * 255.) |> byte
[| gs; gs; gs |]) // this where it is made grayscale. if the array contained multi data you would set it here
let padding = Array.zeroCreate<byte> padding
Array.append row padding)
|> Array.concat
[|
header
dib
pixels
|] |> Array.concat