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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
# File 'lib/fileshunter/Decoders/BMP.rb', line 15
def decode(offset)
ending_offset = nil
cursor = offset + 14
= BinData::Uint32le.read(@data[cursor..cursor+3])
width = nil
height = nil
bpp = nil
= nil
bitmap_size = nil
compression = 0
if ( == 12)
= 2
width = BinData::Sint16le.read(@data[cursor+4..cursor+5])
height = BinData::Sint16le.read(@data[cursor+6..cursor+7])
nbr_planes = BinData::Uint16le.read(@data[cursor+8..cursor+9])
invalid_data("@#{cursor} - Number of planes (#{nbr_planes}) should always be 1") if (nbr_planes != 1)
bpp = BinData::Uint16le.read(@data[cursor+10..cursor+11])
invalid_data("@#{cursor} - Invalid BPP: #{bpp}") if (![1,4,8,16,24,32].include?(bpp))
cursor +=
cursor += 3*(1 << bpp) if (bpp != 24)
else
= 3
width = BinData::Uint32le.read(@data[cursor+4..cursor+7])
height = BinData::Uint32le.read(@data[cursor+8..cursor+11])
nbr_planes = BinData::Uint16le.read(@data[cursor+12..cursor+13])
invalid_data("@#{cursor} - Number of planes (#{nbr_planes}) should always be 1") if (nbr_planes != 1)
bpp = BinData::Uint16le.read(@data[cursor+14..cursor+15])
invalid_data("@#{cursor} - Invalid BPP: #{bpp}") if (![1,4,8,16,24,32].include?(bpp))
compression = BinData::Uint32le.read(@data[cursor+16..cursor+19])
invalid_data("@#{cursor} - Invalid compression method: #{compression}") if (compression > 3)
invalid_data("@#{cursor} - Invalid compression method: #{compression} for given bpp (#{bpp})") if ((compression != 3) and (bpp == 16))
bitmap_size = BinData::Uint32le.read(@data[cursor+20..cursor+23])
invalid_data("@#{cursor} - Empty bitmap size for compression method: #{compression}") if ((bitmap_size == 0) and ((compression == 1) or (compression == 2)))
nbr_colors_used = BinData::Uint32le.read(@data[cursor+32..cursor+35])
invalid_data("@#{cursor} - Number of colors used specified (#{nbr_colors_used} whereas bpp is >= 16 (#{bpp})") if ((bpp >= 16) and (nbr_colors_used > 0))
if ( == 56)
= 56
elsif ( == 108)
= 4
cstype = BinData::Uint32le.read(@data[cursor+56..cursor+59])
invalid_data("@#{cursor} - Invalid cstype: #{cstype}") if (cstype > 2)
end
cursor +=
cursor += 4*(1 << bpp) if (bpp < 16)
cursor += 12 if (((bpp == 16) or (bpp == 32)) and (compression == 3) and ( == 3))
end
progress(cursor)
found_relevant_data(:bmp)
metadata(
:width => width,
:height => height,
:bpp => bpp,
:header_version => ,
:bitmap_size => bitmap_size,
:compression => compression
)
log_debug "@#{cursor} - Decoding bitmap data: header_version=#{} width=#{width} height=#{height} bpp=#{bpp} compression=#{compression} bitmap_size=#{bitmap_size}"
if ((compression == 0) or
(compression == 3))
scanline_size = nil
case bpp.to_i
when 1, 4, 8
scanline_size, = width.divmod(8/bpp)
scanline_size += 1 if ( > 0)
when 16, 24, 32
scanline_size = width * (bpp/8)
scanline_size *= 2 if ((bpp == 16) and ( == 4))
end
rest = scanline_size % 4
scanline_size += 4 - rest if (rest > 0)
computed_bitmap_size = scanline_size * height
cursor += computed_bitmap_size
else
cursor += bitmap_size
end
progress(cursor)
rest = (cursor - offset) % 4
if (rest > 0)
possible_padding_size = 4 - rest
cursor += possible_padding_size if ((cursor + possible_padding_size <= @end_offset) and (@data[cursor..cursor + possible_padding_size - 1] == PADDING_CHAR * possible_padding_size))
end
ending_offset = cursor
return ending_offset
end
|