File Coverage

blib/lib/Data/ParseBinary/Graphics/BMP.pm
Criterion Covered Total %
statement 18 18 100.0
branch 2 2 100.0
condition n/a
subroutine 7 7 100.0
pod 0 1 0.0
total 27 28 96.4


line stmt bran cond sub pod time code
1             package Data::ParseBinary::Graphics::BMP;
2 1     1   626 use strict;
  1         1  
  1         28  
3 1     1   6 use warnings;
  1         1  
  1         23  
4 1     1   5 use Data::ParseBinary;
  1         1  
  1         1037  
5            
6             # Windows/OS2 Bitmap (BMP)
7            
8             #===============================================================================
9             # pixels: uncompressed
10             #===============================================================================
11             sub UncompressedRows {
12 4     4 0 4 my ($subcon, $align_to_byte) = @_;
13             # argh! lines must be aligned to a 4-byte boundary, and bit-pixel
14             # lines must be aligned to full bytes...
15 4         5 my $line_pixels;
16 4 100       8 if ($align_to_byte) {
17 2     28   7 $line_pixels = Bitwise(Array(sub { $_->ctx(2)->{width} }, $subcon));
  28         67  
18             } else {
19 2     28   7 $line_pixels = Array(sub { $_->ctx(2)->{width} }, $subcon);
  28         80  
20             }
21 4     8   79 return Array(sub { $_->ctx->{height} }, Aligned($line_pixels, 4));
  8         29  
22             }
23            
24             my $uncompressed_pixels = Switch("uncompressed", sub { $_->ctx->{bpp} },
25             {
26             1 => UncompressedRows(Bit("index"), 1),
27             4 => UncompressedRows(Nibble("index"), 1),
28             8 => UncompressedRows(Byte("index")),
29             24 => UncompressedRows(Sequence("rgb", Byte("red"), Byte("green"), Byte("blue"))),
30             }
31             );
32            
33             #===============================================================================
34             # file structure
35             #===============================================================================
36             our $bmp_parser = Struct("bitmap_file",
37             # header
38             Const(String("signature", 2), "BM"),
39             ULInt32("file_size"),
40             Padding(4),
41             ULInt32("data_offset"),
42             ULInt32("header_size"),
43             Enum(Alias("version", "header_size"),
44             v2 => 12,
45             v3 => 40,
46             v4 => 108,
47             ),
48             ULInt32("width"),
49             ULInt32("height"),
50             Value("number_of_pixels", sub { $_->ctx->{width} * $_->ctx->{height} }),
51             ULInt16("planes"),
52             ULInt16("bpp"), # bits per pixel
53             Enum(ULInt32("compression"),
54             Uncompressed => 0,
55             RLE8 => 1,
56             RLE4 => 2,
57             Bitfields => 3,
58             JPEG => 4,
59             PNG => 5,
60             ),
61             ULInt32("image_data_size"), # in bytes
62             ULInt32("horizontal_dpi"),
63             ULInt32("vertical_dpi"),
64             ULInt32("colors_used"),
65             ULInt32("important_colors"),
66            
67             # palette (24 bit has no palette)
68             If( sub { $_->ctx->{bpp} <= 8 },
69             Array( sub { 2 ** $_->ctx->{bpp} },
70             Struct("palette",
71             Byte("blue"),
72             Byte("green"),
73             Byte("red"),
74             Padding(1),
75             )
76             )
77             ),
78            
79             # pixels
80             Pointer( sub { $_->ctx->{data_offset} },
81             Switch("pixels", sub { $_->ctx->{compression} },
82             {
83             "Uncompressed" => $uncompressed_pixels,
84             }
85             ),
86             ),
87             );
88            
89             require Exporter;
90             our @ISA = qw(Exporter);
91             our @EXPORT = qw($bmp_parser);
92            
93             1;
94            
95            
96             __END__