| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Math::FitRect; |
|
2
|
|
|
|
|
|
|
BEGIN { |
|
3
|
1
|
|
|
1
|
|
59883
|
$Math::FitRect::VERSION = '0.04'; |
|
4
|
|
|
|
|
|
|
} |
|
5
|
1
|
|
|
1
|
|
10
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
39
|
|
|
6
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
125
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
Math::FitRect - Resize one rect in to another while preserving aspect ratio. |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
use Math::FitRect; |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# This will return: {w=>40, h=>20, x=>0, y=>10} |
|
17
|
|
|
|
|
|
|
my $rect = fit_rect( [80,40] => 40 ); |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# This will return: {w=>80, h=>40, x=>-19, y=>0} |
|
20
|
|
|
|
|
|
|
my $rect = crop_rect( [80,40] => 40 ); |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
This module is very simple in its content but can save much time, much like |
|
25
|
|
|
|
|
|
|
other simplistic modules like L. This module is useful for |
|
26
|
|
|
|
|
|
|
calculating what size you should resize images as for such things as |
|
27
|
|
|
|
|
|
|
thumbnails. |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=cut |
|
30
|
|
|
|
|
|
|
|
|
31
|
1
|
|
|
1
|
|
5
|
use Carp qw( croak ); |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
532
|
|
|
32
|
|
|
|
|
|
|
|
|
33
|
1
|
|
|
1
|
|
7
|
use Exporter qw( import ); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
627
|
|
|
34
|
|
|
|
|
|
|
our @EXPORT_OK = qw( |
|
35
|
|
|
|
|
|
|
fit_rect |
|
36
|
|
|
|
|
|
|
crop_rect |
|
37
|
|
|
|
|
|
|
); |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=head1 RECTANGLES |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
Rectangles may be specified in several different forms to fit your needs. |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=over |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=item A simple scalar integer containg the pixel width/height of a square. |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=item An array ref containing the width and height of a rectangle: [$width,$height] |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=item A hash ref containg a w (width) and h (height) key: {w=>$width,h=>$height} |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=back |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head1 FUNCTIONS |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head2 fit_rect |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# This will return: {w=>40, h=>20, x=>0, y=>10} |
|
58
|
|
|
|
|
|
|
my $rect = fit_rect( [80,40] => 40 ); |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
Takes two rectangles and fits the first one inside the second one. The rectangle |
|
61
|
|
|
|
|
|
|
that will be returned will be a hash ref with a 'w' and 'h' parameter as well |
|
62
|
|
|
|
|
|
|
as 'x' and 'y' parameters which will specify any offset. |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=cut |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub fit_rect { |
|
67
|
4
|
|
|
4
|
1
|
20
|
return _calc_rect('fit',@_); |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=head2 crop_rect |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# This will return: {w=>80, h=>40, x=>-19, y=>0} |
|
73
|
|
|
|
|
|
|
my $rect = crop_rect( [80,40] => 40 ); |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
Like the fit_rect function, crop_rect takes two rectangles as a parameter and it |
|
76
|
|
|
|
|
|
|
makes $rect1 completely fill $rect2. This can mean that the top and bottom or |
|
77
|
|
|
|
|
|
|
the left and right get chopped off (cropped). This method returns a hash ref just |
|
78
|
|
|
|
|
|
|
like fit_rect. |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=cut |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub crop_rect { |
|
83
|
4
|
|
|
4
|
1
|
10
|
return _calc_rect('crop',@_); |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub _calc_rect { |
|
87
|
8
|
|
|
8
|
|
14
|
my($type,$from,$to) = @_; |
|
88
|
8
|
|
|
|
|
16
|
$from = _normalize($from); |
|
89
|
8
|
|
|
|
|
15
|
$to = _normalize($to); |
|
90
|
8
|
|
|
|
|
13
|
my($w,$h,$x,$y); |
|
91
|
8
|
100
|
|
|
|
20
|
if($type eq 'crop'){ ($to->{r},$from->{r}) = ($from->{r},$to->{r}); } |
|
|
4
|
|
|
|
|
12
|
|
|
92
|
|
|
|
|
|
|
|
|
93
|
8
|
100
|
|
|
|
35
|
if($from->{r} < $to->{r}){ |
|
94
|
2
|
|
|
|
|
6
|
$w = $from->{w} * ($to->{h}/$from->{h}); |
|
95
|
2
|
|
|
|
|
3
|
$h = $to->{h}; |
|
96
|
2
|
|
|
|
|
4
|
$x = ($to->{w}-$w)/2; |
|
97
|
2
|
|
|
|
|
3
|
$y = 0; |
|
98
|
|
|
|
|
|
|
}else{ |
|
99
|
6
|
|
|
|
|
13
|
$h = $from->{h} * ($to->{w}/$from->{w}); |
|
100
|
6
|
|
|
|
|
10
|
$w = $to->{w}; |
|
101
|
6
|
|
|
|
|
13
|
$y = ($to->{h}-$h)/2; |
|
102
|
6
|
|
|
|
|
7
|
$x = 0; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
8
|
|
|
|
|
104
|
return {w=>int($w+0.5),h=>int($h+0.5),x=>int($x+0.5),y=>int($y+0.5)}; |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub _normalize { |
|
109
|
16
|
|
|
16
|
|
19
|
my $rect = shift; |
|
110
|
16
|
|
|
|
|
20
|
my($w,$h,$r); |
|
111
|
16
|
100
|
|
|
|
49
|
if(!ref($rect)){ # square |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
112
|
8
|
|
|
|
|
10
|
$w = $h = $rect; |
|
113
|
|
|
|
|
|
|
}elsif(ref($rect) eq 'HASH'){ # rect hash ref |
|
114
|
0
|
|
|
|
|
0
|
$w = $rect->{w}; |
|
115
|
0
|
|
|
|
|
0
|
$h = $rect->{h}; |
|
116
|
|
|
|
|
|
|
}elsif(@$rect==2){ # width, height |
|
117
|
8
|
|
|
|
|
13
|
$w = $rect->[0]; |
|
118
|
8
|
|
|
|
|
40
|
$h = $rect->[1]; |
|
119
|
|
|
|
|
|
|
}elsif(@$rect==4){ # x1, y1, x2, y2 |
|
120
|
0
|
0
|
|
|
|
0
|
if($rect->[0]<$rect->[2]){ $w=($rect->[2]-$rect->[0])+1; } |
|
|
0
|
|
|
|
|
0
|
|
|
121
|
0
|
|
|
|
|
0
|
else{ $w=($rect->[0]-$rect->[2])+1; } |
|
122
|
0
|
0
|
|
|
|
0
|
if($rect->[1]<$rect->[3]){ $h=($rect->[3]-$rect->[1])+1; } |
|
|
0
|
|
|
|
|
0
|
|
|
123
|
0
|
|
|
|
|
0
|
else{ $h=($rect->[1]-$rect->[3])+1; } |
|
124
|
|
|
|
|
|
|
}else{ |
|
125
|
0
|
|
|
|
|
0
|
croak('Invalid rectangle parameter'); |
|
126
|
|
|
|
|
|
|
} |
|
127
|
16
|
|
|
|
|
21
|
$r = $w/$h; |
|
128
|
16
|
|
|
|
|
67
|
return {w=>$w,h=>$h,r=>$r}; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
1; |
|
132
|
|
|
|
|
|
|
__END__ |