File Coverage

blib/lib/Music/Image/Chord.pm
Criterion Covered Total %
statement 111 125 88.8
branch 21 42 50.0
condition 16 33 48.4
subroutine 20 20 100.0
pod 10 10 100.0
total 178 230 77.3


line stmt bran cond sub pod time code
1             package Music::Image::Chord;
2              
3 1     1   29878 use strict;
  1         2  
  1         36  
4 1     1   4 use warnings;
  1         1  
  1         25  
5 1     1   4 use vars qw($VERSION);
  1         5  
  1         57  
6              
7             $VERSION = '0.006';
8              
9 1     1   3919 use Imager;
  1         58311  
  1         7  
10              
11             my $standard_6 =
12             {
13             c => 'x32010',
14             d => 'xxO232',
15             e => '022100',
16             g => '210002',
17             a => 'x02220',
18             f => 'xx3211',
19             b => 'xx4442',
20              
21             cm => 'xx5543',
22             dm => 'xx0231',
23             em => '022000',
24             gm => 'xx5333',
25             am => 'x02210',
26             fm => 'xx3111',
27             bm => 'xx4432',
28              
29             c7 => 'x32310',
30             d7 => 'xx0212',
31             e7 => '020100',
32             g7 => '320001',
33             a7 => 'x02020',
34             f7 => 'xx1211',
35             b7 => 'x21202',
36             };
37              
38             my $black = Imager::Color->new(0,0,0);
39             my $white = Imager::Color->new(255,255,255);
40              
41             sub new
42             {
43 1     1 1 14 my $class = shift;
44 1         5 bless {}, $class;
45             }
46              
47 3   66 3 1 13758 sub bar_thickness { shift->{bar_thickness} ||= shift; }
48 4   66 4 1 59 sub crop_width { shift->{crop_width} ||= shift; }
49 3   66 3 1 29 sub debug { shift->{debug} ||= shift; }
50 2   66 2 1 22 sub font { shift->{font} ||= shift; }
51 2   66 2 1 24 sub file { shift->{file} ||= shift; }
52 1   33 1 1 8 sub fret { shift->{fret} ||= shift; }
53              
54             sub bounds
55             {
56 6     6 1 14 my $self = shift;
57 6 100       16 if(@_>0)
58             {
59 1 50       6 if($_[0]=~/\D/)
60             {
61 0         0 while(@_)
62             {
63 0         0 $_ = shift;
64 0 0       0 if(/^w/i)
    0          
    0          
    0          
    0          
    0          
65 0         0 { $self->{bounds}->{w} = shift; }
66             elsif(/^h/i)
67 0         0 { $self->{bounds}->{h} = shift; }
68             elsif(/^xmin/i)
69 0         0 { $self->{bounds}->{xmin} = shift; }
70             elsif(/^xmax/i)
71 0         0 { $self->{bounds}->{xmax} = shift; }
72             elsif(/^ymin/i)
73 0         0 { $self->{bounds}->{ymin} = shift; }
74             elsif(/^ymax/i)
75 0         0 { $self->{bounds}->{ymax} = shift; }
76             }
77             }
78             else
79             {
80 1         5 $self->{bounds}->{w} = shift;
81 1         3 $self->{bounds}->{h} = shift;
82             }
83 1   33     6 $self->{bounds}->{w} ||=
84             $self->{bounds}->{xmax} - $self->{bounds}->{xmin};
85 1   33     4 $self->{bounds}->{h} ||=
86             $self->{bounds}->{ymax} - $self->{bounds}->{ymin};
87             }
88 6         33 return $self->{bounds};
89             }
90              
91             sub grid
92             {
93 1     1 1 9 my $self = shift;
94 1 50       5 if(@_>0)
95             {
96 1 50       7 if($_[0]=~/\D/)
97             {
98 1         4 while(@_)
99             {
100 4         8 $_ = shift;
101 4 100       26 if(/^w/i) { $self->{grid}->{w} = shift; }
  1 100       4  
    100          
    50          
102 1         5 elsif(/^h/i) { $self->{grid}->{h} = shift; }
103 1         7 elsif(/^x/i) { $self->{grid}->{x} = shift; }
104 1         5 elsif(/^y/i) { $self->{grid}->{y} = shift; }
105             }
106             }
107             else
108             {
109 0         0 $self->{grid}->{x} = shift;
110 0         0 $self->{grid}->{y} = shift;
111 0         0 $self->{grid}->{w} = shift;
112 0         0 $self->{grid}->{h} = shift;
113             }
114             }
115 1         2 return %{$self->{grid}};
  1         3  
116             }
117              
118             sub draw
119             {
120 1     1 1 7 my $self = shift;
121 1         4 while(@_)
122             {
123 3         16 my ($k,$v)=(shift(),shift());
124 3         12 $self->{$k}=$v;
125             }
126 1   33     10 $self->{chord} ||= $standard_6->{lc $self->{name}};
127              
128 1 50       5 if(length($self->{chord})<6)
129             {
130 0         0 $self->{chord} .= 'x' x 6-length($self->{chord});
131             }
132              
133 1         3 my $i = 0;
134              
135 1         9 for(split //,lc $self->{chord})
136             {
137 6 100       28 if(/x/i)
    100          
138             {
139 2         4 push @{$self->{closed}},$i;
  2         13  
140             }
141             elsif(/[o0]/i)
142             {
143 1         2 push @{$self->{open}},$i;
  1         4  
144             }
145             else
146             {
147 3 50 33     20 push @{$self->{fingering}->[$_-1]},$i if $_>0 and $_<5;
  3         10  
148             }
149 6         10 $i++;
150             }
151              
152 1         8 $self->{open_r}=($self->{grid}->{w}/2)-1;
153 1         4 $self->{image} = Imager->new
154             (
155             xsize => $self->bounds()->{w},
156             ysize => $self->bounds()->{h},
157             channels => 1,
158             );
159 1 50       151 $self->{image}->{DEBUG}=1 if $self->debug();
160 1         4 $self->{image}->box
161             (
162             color => $white,
163             xmin => 0,
164             ymin => 0,
165             xmax => $self->bounds()->{w},
166             ymax => $self->bounds()->{h},
167             filled => 1,
168             );
169              
170 1 50       124 $self->_cropmarks() if $self->crop_width() > 0;
171 1         93 $self->_grid();
172 1         59 $self->_open_strings();
173 1         87 $self->_closed_strings();
174 1         49 $self->_fingering();
175 1         4 $self->_top_label();
176              
177 1         32 $self->file()=~/\.(.*)$/;
178 1         6 $self->{type} = $1;
179 1         7 $self->{image}->write(file=>$self->{file},type=>$self->{type});
180             }
181              
182             sub _top_label
183             {
184 1     1   2 my $self = shift;
185 1   33     6 my $text = $self->{name} || $self->{labels}{top};
186 1         4 my $font = new Imager::Font(file => $self->font());
187 1         2953 $self->{image}->string
188             (
189             font => $font,
190             text => $text,
191             x => 0,
192             y => 20,
193             size => 20,
194             color => $black
195             );
196             }
197              
198             sub _cropmarks
199             {
200 1     1   3 my $self = shift;
201 1         2 my $bounds = $self->bounds();
202 1         4 my $crop_width = $self->crop_width();
203 1         10 $self->{image}->polyline
204             (
205             points=>
206             [
207             [0,$crop_width],
208             [0,0],
209             [$crop_width,0]
210             ],
211             color=>$black
212             );
213 1         139 $self->{image}->polyline
214             (
215             points=>
216             [
217             [$bounds->{w}-$crop_width-1,$bounds->{h}-1],
218             [$bounds->{w}-1,$bounds->{h}-1],
219             [$bounds->{w}-1,$bounds->{h}-$crop_width-1]
220             ],
221             color=>$black
222             );
223             }
224              
225             sub _closed_strings
226             {
227 1     1   2 my $self = shift;
228 1         6 my $y = $self->{grid}->{y}+$self->{grid}->{h}-$self->{grid}->{w};
229              
230 1         2 for(@{$self->{closed}})
  1         3  
231             {
232 2         56 my $x = $self->{grid}->{x}+$self->{open_r}+($self->{grid}->{w}*$_);
233 2         13 $self->{image}->polyline
234             (
235             points=>
236             [
237             [$x-$self->{open_r},$y-$self->{open_r}],
238             [$x+$self->{open_r},$y+$self->{open_r}-1],
239             ],
240             color => $black
241             );
242 2         131 $self->{image}->polyline
243             (
244             points=>
245             [
246             [$x+$self->{open_r},$y-$self->{open_r}],
247             [$x-$self->{open_r},$y+$self->{open_r}],
248             ],
249             color => $black
250             );
251             }
252             }
253              
254             sub _open_strings
255             {
256 1     1   11 my $self = shift;
257 1         5 my $y = $self->{grid}->{y}+$self->{grid}->{h}-$self->{grid}->{w};
258              
259 1         2 for(@{$self->{open}})
  1         4  
260             {
261 1         4 my $x = $self->{grid}->{x}+$self->{open_r}+($self->{grid}->{w}*$_);
262 1         6 $self->{image}->circle
263             (
264             r => $self->{open_r},
265             x => $x,
266             y => $y,
267             color => $black,
268             filled => 0
269             );
270 1         102 $self->{image}->circle
271             (
272             r => $self->{open_r} - 1,
273             x => $x,
274             y => $y,
275             color => $white,
276             filled => 0
277             );
278             }
279             }
280              
281             sub _fingering
282             {
283 1     1   2 my $self = shift;
284 1         1 my $row = 0;
285 1         6 my $grid_y = $self->{grid}->{y}+$self->{grid}->{h}+
286             ($self->{grid}->{h}/2)+($self->{open_r}/2)-$self->{open_r};
287              
288 1         2 for my $fret_ref(@{$self->{fingering}})
  1         4  
289             {
290 3         3 for(@{$fret_ref})
  3         9  
291             {
292 3         87 $self->{image}->circle
293             (
294             r => $self->{open_r},
295             x => $self->{grid}->{x}+$self->{open_r}+($self->{grid}->{w}*($_)),
296             y => $grid_y+($row*($self->{grid}->{h}+2)),
297             color => $black,
298             filled => 0
299             );
300             }
301 3         139 $row++;
302             }
303             }
304              
305             sub _grid
306             {
307 1     1   3 my $self = shift;
308              
309 1         4 for(0..5)
310             {
311 6         306 my $x = $self->{grid}->{x}+$self->{open_r}+($self->{grid}->{w}*$_);
312              
313 6         45 $self->{image}->polyline
314             (
315             points=>
316             [
317             [$x,$self->{grid}->{y}+$self->{grid}->{h}],
318             [$x,$self->{grid}->{y}+$self->{grid}->{h}+($self->{grid}->{h}*5)],
319             ],
320             color=>$black
321             );
322             }
323 1         53 for(0..4)
324             {
325 5         218 my $y = $self->{grid}->{y}+($self->{grid}->{h}*($_+1));
326 5         162 $self->{image}->polyline
327             (
328             points=>
329             [
330             [$self->{grid}->{x}+$self->{open_r},$y],
331             [$self->{grid}->{x}+$self->{open_r}+($self->{grid}->{w}*5),$y],
332             ],
333             color=>$black
334             );
335             }
336              
337 1 50       69 if ($self->fret() == 1)
338             {
339 1         6 $self->{image}->box
340             (
341             color => $black,
342             xmin => $self->{grid}->{x}+$self->{open_r},
343             ymin => $self->{grid}->{y}+$self->{grid}->{h}-$self->bar_thickness(),
344             xmax => $self->{grid}->{x}+$self->{open_r}+(5*$self->{grid}->{w}),
345             ymax => $self->{grid}->{y}+$self->{grid}->{h},
346             filled => 1,
347             );
348             }
349              
350 1         42 $self->{image}->polyline
351             (
352             points=>
353             [
354             [$self->{grid}->{x}+$self->{open_r},
355             $self->{grid}->{y}+$self->{grid}->{h}+($self->{grid}->{h}*5)],
356             [$self->{grid}->{x}+$self->{open_r}+(5*$self->{grid}->{w}),
357             $self->{grid}->{y}+$self->{grid}->{h}+($self->{grid}->{h}*5)],
358             ],
359             color=>$black
360             );
361             }
362              
363             1;
364             __END__