File Coverage

blib/lib/GD/Image/Scale2x.pm
Criterion Covered Total %
statement 15 54 27.7
branch 0 12 0.0
condition 0 4 0.0
subroutine 5 9 55.5
pod n/a
total 20 79 25.3


line stmt bran cond sub pod time code
1             package GD::Image::Scale2x;
2              
3             =head1 NAME
4              
5             GD::Image::Scale2x - Implementation of the Scale2x algorithm for the GD library
6              
7             =head1 SYNOPSIS
8              
9             use GD;
10             use GD::Image::Scale2x;
11              
12             # load an image
13             my $image = GD::Image->new( 'file.png' );
14              
15             # scale2x, 3x, and 4x
16             my $scaled2x = $image->scale2x;
17             my $scaled3x = $image->scale3x;
18             my $scaled4x = $image->scale4x;
19              
20             # scale a certain area
21             # (10, 10) to (30, 30)
22             my $scaled = $image->scale2x( 10, 10, 20, 20 );
23              
24             =head1 DESCRIPTION
25              
26             This module implements the Scale2x algorithm (as well as 3x and 4x). From the Scale2x web site:
27              
28             Scale2x is real-time graphics effect able to increase the size of small bitmaps
29             guessing the missing pixels without interpolating pixels and blurring the images.
30              
31             The algorithm itself is explained at http://scale2x.sourceforge.net/algorithm.html. You can see
32             some example results by looking through the test directory.
33              
34             =cut
35              
36 1     1   53844 use strict;
  1         3  
  1         27  
37 1     1   4 use warnings;
  1         2  
  1         45  
38              
39             our $VERSION = '0.07';
40              
41             =head1 METHODS
42              
43             =head2 scale2x( [ $source_x, $source_y, $width, $height ] )
44              
45             Takes an image and produces one twice a big. From the Scale2x web site:
46              
47             The effect works repeating a computation pattern for every pixel of the
48             original image. The pattern starts from a square of 9 pixels and expands
49             the central pixel computing 4 new pixels.
50              
51             You can specify a portion of the original image by specifying a source x and y plus
52             a width and height.
53              
54             =head2 scale3x( [ $source_x, $source_y, $width, $height ] )
55              
56             A similar algorithm to scale2x, except that it produces a 9-pixel result.
57              
58             =head2 scale4x( [ $source_x, $source_y, $width, $height ] )
59              
60             Same as scale2x done twice over.
61              
62             =head1 SEE ALSO
63              
64             =over 4
65              
66             =item * Algorithm::Scale2x
67              
68             =item * GD
69              
70             =item * http://scale2x.sourceforge.net/
71              
72             =back
73              
74             =head1 AUTHOR
75              
76             Brian Cassidy Ebricas@cpan.orgE
77              
78             =head1 COPYRIGHT AND LICENSE
79              
80             Copyright 2005-2009 by Brian Cassidy
81              
82             This library is free software; you can redistribute it and/or modify
83             it under the same terms as Perl itself.
84              
85             =cut
86              
87             package GD::Image;
88              
89 1     1   4 use strict;
  1         6  
  1         25  
90 1     1   9 use warnings;
  1         1  
  1         22  
91              
92 1     1   939 use Algorithm::Scale2x ();
  1         633  
  1         465  
93              
94             sub scale2x {
95 0     0     my $self = shift;
96              
97 0           return $self->_scale( 2, @_ );
98             }
99              
100             sub scale3x {
101 0     0     my $self = shift;
102              
103 0           return $self->_scale( 3, @_ );
104             }
105              
106             sub scale4x {
107 0     0     my $self = shift;
108              
109 0           my $image = $self->scale2x( @_ );
110 0           return $image->scale2x;
111             }
112              
113             sub _scale {
114 0     0     my $self = shift;
115 0           my $scale = shift;
116 0   0       my $source_x = shift || 0;
117 0   0       my $source_y = shift || 0;
118 0           my $source_w = shift;
119 0           my $source_h = shift;
120              
121 0 0         unless( $source_w ) {
122 0           ( $source_w, $source_h ) = $self->getBounds;
123 0           $source_w -= $source_x;
124 0           $source_h -= $source_y;
125             }
126              
127 0           my $image = GD::Image->new( $source_w * $scale, $source_h * $scale );
128 0           my $code = Algorithm::Scale2x->can( "scale${scale}x" );
129              
130 0           my $bound_x = $source_w - 1;
131 0           my $bound_y = $source_h - 1;
132              
133 0           my @palette;
134              
135 0           for my $y ( $source_y..$bound_y ) {
136 0           for my $x ( $source_x..$bound_x ) {
137 0 0         my $x_plus = ( $x + 1 > $bound_x ? $x : $x + 1 );
138 0 0         my $x_minus = ( $x - 1 < $source_x ? $x : $x - 1 );
139 0 0         my $y_plus = ( $y + 1 > $bound_y ? $y : $y + 1 );
140 0 0         my $y_minus = ( $y - 1 < $source_y ? $y : $y - 1 );
141              
142             # 0 1 2 #
143             # 3 4 5 # 4 => x, y
144             # 6 7 8 #
145              
146 0           my @pixels = (
147             $self->getPixel( $x_minus, $y_minus ),
148             $self->getPixel( $x, $y_minus ),
149             $self->getPixel( $x_plus, $y_minus ),
150             $self->getPixel( $x_minus, $y ),
151             $self->getPixel( $x, $y ),
152             $self->getPixel( $x_plus, $y ),
153             $self->getPixel( $x_minus, $y_plus ),
154             $self->getPixel( $x, $y_plus ),
155             $self->getPixel( $x_plus, $y_plus )
156             );
157              
158 0           my @E = $code->( @pixels );
159              
160 0           my $scaledx = $x * $scale;
161 0           my $scaledy = $y * $scale;
162              
163 0           for my $y ( 0..$scale - 1 ) {
164 0           for my $x ( 0..$scale - 1 ) {
165 0           my $E = shift @E;
166 0 0         unless( $palette[ $E ] ) {
167 0           $palette[ $E ] = $image->colorAllocate( $self->rgb( $E ) );
168             }
169              
170 0           $image->setPixel( $scaledx + $x, $scaledy + $y, $palette[ $E ] );
171             }
172             }
173             }
174             }
175              
176 0           return $image;
177             }
178              
179             1;