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
|
import gleam/int
pub type ImageDimensions {
ImageDimensions(width: Int, height: Int)
}
pub fn get_image_dimensions(image) {
case image {
<<0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, _:bits>> ->
parse_png_chunks(image, 8)
<<
0x47,
0x49,
0x46,
_:16,
_:unsigned,
width_0:8,
width_1:8,
height_0:8,
height_1:8,
_rest:bits,
>> ->
Ok(ImageDimensions(
width_0
|> int.bitwise_or(
width_1
|> int.bitwise_shift_left(8),
),
height_0
|> int.bitwise_or(
height_1
|> int.bitwise_shift_left(8),
),
))
_ -> Error("Invalid PNG signature")
}
}
fn parse_png_chunks(image, offset) {
let offset_bits = offset * 8
case image {
<<
_:size(offset_bits),
_length:32,
"IHDR":utf8,
width:32,
height:32,
_:bits,
>> -> Ok(ImageDimensions(width, height))
<<_:size(offset), length:32, _:4, _:bits>> ->
parse_png_chunks(image, offset + length + 12)
_ -> Error("Invalid PNG chunk")
}
}
|