File Coverage

blib/lib/Imager/Search/Driver/BMP24.pm
Criterion Covered Total %
statement 59 63 93.6
branch 6 12 50.0
condition n/a
subroutine 11 11 100.0
pod 4 4 100.0
total 80 90 88.8


line stmt bran cond sub pod time code
1             package Imager::Search::Driver::BMP24;
2              
3             # Basic search driver implemented in terms of 8-bit
4             # HTML-style strings ( #003399 )
5              
6 2     2   1879 use 5.006;
  2         7  
  2         80  
7 2     2   11 use strict;
  2         4  
  2         56  
8 2     2   9 use Imager::Search::Match ();
  2         5  
  2         27  
9 2     2   10 use Imager::Search::Driver ();
  2         3  
  2         37  
10              
11 2     2   9 use vars qw{$VERSION @ISA};
  2         3  
  2         175  
12             BEGIN {
13 2     2   4 $VERSION = '1.01';
14 2         71 @ISA = 'Imager::Search::Driver';
15             }
16              
17 2     2   11 use constant HEADER => 54;
  2         4  
  2         1261  
18              
19              
20              
21              
22              
23             #####################################################################
24             # Imager::Search::Driver Methods
25              
26             sub image_string {
27 1     1 1 2 my $self = shift;
28 1         2 my $imager = shift;
29 1         3 my $data = '';
30 1 50       4 $imager->write(
31             data => \$data,
32             type => 'bmp',
33             ) or die "Failed to generate image string";
34 1         199 return \$data;
35             }
36              
37             sub pattern_lines {
38 1     1 1 3 my $self = shift;
39 1         3 my $imager = shift;
40 1         2 my $data = '';
41 1 50       7 $imager->write(
42             data => \$data,
43             type => 'bmp',
44             ) or die "Failed to generate bmp image";
45              
46             # The bmp will contain the raw scanline data we want in
47             # a series of byte ranges. Capture each range and quotemeta
48             # the raw bytes.
49 1         261 my $pixels = $imager->getwidth;
50 1         14 my $range = $pixels * 3;
51 1         9 my $width = $range + (-$range % 4);
52             return [
53 2         9 map { quotemeta substr( $data, $_, $range ) }
  2         16  
54 1         6 map { HEADER + $_ * $width }
55             ( 0 .. $imager->getheight - 1 )
56             ];
57             }
58              
59             sub pattern_regexp {
60 2     2 1 39 my $self = shift;
61 2         3 my $pattern = shift;
62 2         3 my $width = shift;
63              
64             # Each BMP scan line comes in groups of 4-byte dwords.
65             # As a result, each line contains an amount of useless extra
66             # bytes needed to round it up to a multiple of 4 bytes.
67 2         4 my $junk = ($width * -3) % 4;
68 2         6 my $pixels = $width - $pattern->width;
69 2         5 my $newline = '.{' . ($pixels * 3 + $junk) . '}';
70              
71             # Assemble the regexp
72 2         4 my $lines = $pattern->lines;
73 2         5 my $string = join( $newline, @$lines );
74              
75 2         21 return qr/$string/s;
76             }
77              
78             sub match_object {
79 3     3 1 4 my $self = shift;
80 3         3 my $image = shift;
81 3         5 my $pattern = shift;
82 3         3 my $byte = shift;
83              
84             # Remove the delta from the header
85 3         4 $byte -= HEADER;
86              
87             # If we accidentally matched somewhere in header, we need
88             # to discard the match. Shortcut to fail.
89 3 50       8 unless ( $byte >= 0 ) {
90 0         0 return; # undef or null list
91             }
92              
93             # The bytewidth of a line is pixel width
94             # multiplied by three, plus one for the newline.
95 3         6 my $pixel_width = $image->width;
96 3         4 my $byte_junk = ($pixel_width * -3) % 4;
97 3         4 my $byte_width = $pixel_width * 3 + $byte_junk;
98              
99             # Find the column for the match.
100             # If the column isn't an integer we matched at a position that is
101             # not a pixel boundary, and thus this match is a false positive.
102             # Shortcut to fail.
103 3         7 my $pixel_left = ($byte % $byte_width) / 3;
104 3 50       7 unless ( $pixel_left == int($pixel_left) ) {
105 0         0 return; # undef or null list
106             }
107              
108             # If the match overlaps the newline boundary this is also a
109             # false positive. Shortcut to fail.
110 3 50       13 if ( $pixel_left > $image->width - $pattern->width ) {
111 0         0 return; # undef or null list
112             }
113              
114             # The match position represents the bottom row.
115             # If the match falls off the top of the image this is also
116             # a false positive. Shortcut to fail.
117 3         9 my $pixel_bottom = $image->height - int($byte / $byte_width) - 1;
118 3 50       9 if ( $pixel_bottom < $pattern->height - 1 ) {
119 0         0 return; # undef or null list
120             }
121              
122             # This is a legitimate match.
123             # Convert to a match object and return.
124 3         34 return Imager::Search::Match->new(
125             name => $pattern->name,
126             top => $pixel_bottom - $pattern->height + 1,
127             left => $pixel_left,
128             height => $pattern->height,
129             width => $pattern->width,
130             );
131             }
132              
133             1;
134              
135             =pod
136              
137             =head1 NAME
138              
139             Imager::Search::Driver::BMP24 - Imager::Search driver based on 24-bit BMP
140              
141             =head1 DESCRIPTION
142              
143             B is a simple default driver for L.
144              
145             It generates a search regular expression that can scan a Windows BMP
146             directly, taking advantage of fast underlying C code that generates these
147             files.
148              
149             For a 1024x768 screen grab, the result is that the BMP24 driver is 50-100
150             times faster to generate a search image compated to the HTML24 driver.
151              
152             =head1 SUPPORT
153              
154             See the SUPPORT section of the main L module.
155              
156             =head1 AUTHOR
157              
158             Adam Kennedy Eadamk@cpan.orgE
159              
160             =head1 COPYRIGHT
161              
162             Copyright 2007 - 2011 Adam Kennedy.
163              
164             This program is free software; you can redistribute
165             it and/or modify it under the same terms as Perl itself.
166              
167             The full text of the license can be found in the
168             LICENSE file included with this module.
169              
170             =cut