File Coverage

blib/lib/Image/Imlib2/Thumbnail/Scaled.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Image::Imlib2::Thumbnail::Scaled;
2              
3 1     1   21271 use strict;
  1         4  
  1         45  
4 1     1   4 use warnings;
  1         2  
  1         36  
5 1     1   865 use Object::Tiny::RW::XS qw/sizes include_original delete_original original_width original_height move_original/;
  1         4146  
  1         6  
6 1     1   495 use File::Basename qw/fileparse basename dirname/;
  1         1  
  1         74  
7 1     1   941 use File::Copy qw/move/;
  1         5477  
  1         72  
8 1     1   447 use Image::Imlib2;
  0            
  0            
9             use MIME::Types;
10             use Path::Class;
11              
12             =head1 NAME
13              
14             Image::Imlib2::Thumbnail::Scaled - Create scaled thumbnails while keeping the aspect ratio
15              
16             =head1 VERSION
17              
18             Version 0.05
19              
20             =cut
21              
22             our $VERSION = '0.05';
23              
24             =head1 SYNOPSIS
25              
26             use Image::Imlib2::Thumbnail::Scaled;
27             my $thumbnail = Image::Imlib2::Thumbnail::Scaled->new;
28            
29             # generates a set of thumbnails for $source image in $directory
30             my $thumbnails = $thumbnail->generate( $source, $directory );
31              
32             =head1 DESCRIPTION
33              
34             This module creates a series of thumbnails using L.
35              
36             This module is essentially L, except it respects the aspect ratio
37             of the original image when scaling, and there are some minor differences in terms of what
38             functions take in and return.
39              
40             It is possible using L to keep the aspect ratio of the image, however
41             you have to decide whether to scale based on height or width, whereas L
42             figures this out for you based on the dimensions of the image.
43              
44             This module by default generates sizes very similar to L:
45              
46             Name Width Height
47             Square 75 75
48             Thumbnail 100 75
49             Small 240 180
50             Medium 500 375
51             Large 1024 768
52              
53             =head1 SUBROUTINES/METHODS
54              
55             =head2 new
56              
57             my $thumbnail = Image::Imlib2::Thumbnail::Scaled->new;
58              
59             Returns a new L object. Can take in any of the subroutines as options (except L). For example:
60              
61             my $thumbnail = Image::Imlib2::Thumbnail::Scaled->new(
62             sizes => [
63             {
64             name => 'my_image',
65             width => 180,
66             height => 180,
67             },
68             {
69             name => 'my_other_image',
70             width => 240,
71             height => 240,
72             }
73             ]
74             );
75              
76             my $thumbnail = Image::Imlib2::Thumbnail::Scaled->new(include_original => 1);
77              
78             #or multiple
79             my $thumbnail = Image::Imlib2::Thumbnail::Scaled->new(include_original => 1, delete_original => 1);
80              
81             =cut
82              
83             sub _set_default_sizes {
84             my ($self) = @_;
85             $self->sizes(
86             [
87             {
88             name => 'square',
89             width => 75,
90             height => 75
91             },
92             {
93             name => 'thumbnail',
94             width => 100,
95             height => 75
96             },
97             {
98             name => 'small',
99             width => 240,
100             height => 180
101             },
102             {
103             name => 'medium',
104             width => 500,
105             height => 375
106             },
107             {
108             name => 'large',
109             width => 1024,
110             height => 768
111             },
112             ]
113             );
114             }
115              
116             =head2 sizes
117              
118             my $thumbnail = Image::Imlib2::Thumbnail::Scaled->new(
119             sizes => [
120             {
121             name => 'my_image',
122             width => 180,
123             height => 180,
124             },
125             {
126             name => 'my_other_image',
127             width => 240,
128             height => 240,
129             }
130             ]
131             );
132              
133             L allows you to override the default sizes that are provided.
134              
135             =head2 include_original
136              
137             $thumbnail->include_original(1);
138              
139             If set to 1, L will return the original image along with
140             the created thumbnails in the returned arrayref. Default is false.
141              
142             =cut
143              
144             =head2 delete_original
145              
146             $thumbnail->delete_original(1);
147              
148             If set to 1, the original image will be deleted once all resized images are made.
149             Default is false.
150              
151             =cut
152              
153             =head2 move_original
154              
155             $thumbnail->move_original(1);
156              
157             If set to 1, the original image will be moved to the directory that is passed into L along
158             with all of the other resized images.
159             Default is false.
160              
161             =cut
162              
163             =head2 add_size
164              
165             Add an extra size:
166              
167             $thumbnail->add_size(
168             {
169             name => 'header',
170             width => 350,
171             height => 200,
172             quality => 80,
173             }
174             );
175            
176             The quality is the JPEG quality compression ratio. This defaults to 75.
177              
178             =cut
179              
180             sub add_size {
181             my ( $self, $size ) = @_;
182             push @{ $self->sizes }, $size;
183             }
184              
185             =head2 generate
186              
187             Returns an arrayref a set of thumbnails for $source image in $directory.
188             Will include the original image if L
189             is set to 1.
190              
191             my $thumbnails = $thumbnail->generate( $source, $directory );
192             for my $thumbnail (@$thumbnails) {
193             my $name = $thumbnail->{name};
194             my $width = $thumbnail->{width};
195             my $requested_width = $thumbnail->{requested_width};
196             my $height = $thumbnail->{height};
197             my $requested_height = $thumbnail->{requested_height};
198             my $filename = $thumbnail->{filename};
199             my $mime_type = $thumbnail->{mime_type};
200             print "$name $mime_type is $width x $height at $filename with requested width $requested_width requested height $requested_height\n";
201             }
202              
203             Since the aspect ratio is kept, width and height will hold the resulting width and height after resizing,
204             while requested_width and requested_height will hold the width and height that the image was
205             requested to be resized to.
206              
207             You can also pass in an optional third argument to L, which if set to true will return a hash of hashes
208             for all of the resized images, where the key is the name provided in L.
209              
210             my $thumbnails = $thumbnail->generate( $source, $directory, 1 );
211             while(my ($name, $thumbnail) = each %$thumbnails) {
212             my $name = $thumbnail->{name};
213             my $width = $thumbnail->{width};
214             my $requested_width = $thumbnail->{requested_width};
215             my $height = $thumbnail->{height};
216             my $requested_height = $thumbnail->{requested_height};
217             my $filename = $thumbnail->{filename};
218             my $mime_type = $thumbnail->{mime_type};
219             print "$name $mime_type is $width x $height at $filename with requested width $requested_width requested height $requested_height\n";
220             }
221              
222             =cut
223              
224             sub generate {
225             my ($self, $filename, $directory, $return_hash) = @_;
226             my $image = Image::Imlib2->load($filename);
227             my $return_obj;
228              
229             my ( $o_width, $o_height )
230             = ( $image->width, $image->height );
231             $self->original_width($o_width);
232             $self->original_height($o_height);
233             my $original_extension = [ fileparse( $filename, qr/\.[^.]*?$/ ) ]->[2]
234             || '.jpg';
235             $original_extension =~ s/^\.//;
236              
237             my $mime_type = MIME::Types->new->mimeTypeOf($original_extension);
238              
239             if($self->include_original) {
240             my $orig_file = {
241             filename => $filename,
242             name => 'original',
243             width => $o_width,
244             height => $o_height,
245             requested_width => $o_width,
246             requested_height => $o_height,
247             };
248              
249             if($return_hash) {
250             $return_obj->{original} = $orig_file;
251             }
252             else { push @$return_obj, $orig_file }
253             }
254              
255             #set defaults if they do not exist!
256             $self->_set_default_sizes unless $self->sizes;
257              
258             foreach my $size ( @{ $self->sizes } ) {
259             my ( $name, $width, $height) = ( $size->{name}, $size->{width}, $size->{height} );
260              
261             # add quality from the size definition if provided
262             my $quality = $size->{quality} || 75;
263              
264             my $scaled_image;
265              
266             #SCALING CODE
267             my ($t_width, $t_height) = ($width,$height);
268              
269             if ( $o_width * $height - $width * $o_height >= 0 ) {
270             $t_height = ( $width / $o_width ) * $o_height;
271             }
272             else {
273             $t_width = ( $height / $o_height ) * $o_width;
274             }
275              
276             $t_width = int($t_width);
277             $t_height = int($t_height);
278             $scaled_image = $image->create_scaled_image( $t_width, $t_height );
279             my $destination
280             = file( $directory, $name . '.' . $original_extension )
281             ->stringify;
282             $scaled_image->set_quality($quality);
283             $scaled_image->save($destination);
284              
285             my $resized_image = {
286             filename => $destination,
287             name => $name,
288             requested_width => $width,
289             requested_height => $height,
290             width => $t_width,
291             height => $t_height,
292             mime_type => $mime_type,
293             };
294              
295             if($return_hash) {
296             $return_obj->{$name} = $resized_image;
297             }
298             else { push @$return_obj, $resized_image }
299             }
300              
301             if($self->move_original) {
302             my $base_filename = basename($filename);
303             move($filename, file($directory, $base_filename)->stringify);
304             }
305             unlink $filename if $self->delete_original;
306              
307             return $return_obj;
308             }
309              
310             =head2 original_width
311              
312             my $original_width = $thumbnail->original_width;
313              
314             This subroutine returns the width of the original image. (Can only be called after L).
315              
316             =cut
317              
318             =head2 original_height
319              
320             my $original_height = $thumbnail->original_height;
321              
322             This subroutine returns the height of the original image. (Can only be called after L).
323              
324             =cut
325              
326             =head1 AUTHOR
327              
328             Adam Hopkins, C<< >>
329              
330             =head1 BUGS
331              
332             Please report any bugs or feature requests to C, or through
333             the web interface at L. I will be notified, and then you'll
334             automatically be notified of progress on your bug as I make changes.
335              
336              
337              
338              
339             =head1 SUPPORT
340              
341             You can find documentation for this module with the perldoc command.
342              
343             perldoc Image::Imlib2::Thumbnail::Scaled
344              
345              
346             You can also look for information at:
347              
348             =over 4
349              
350             =item * RT: CPAN's request tracker (report bugs here)
351              
352             L
353              
354             =item * AnnoCPAN: Annotated CPAN documentation
355              
356             L
357              
358             =item * CPAN Ratings
359              
360             L
361              
362             =item * Search CPAN
363              
364             L
365              
366             =back
367              
368              
369             =head1 ACKNOWLEDGEMENTS
370              
371              
372             =head1 LICENSE AND COPYRIGHT
373              
374             Copyright 2013 Adam Hopkins.
375              
376             This program is free software; you can redistribute it and/or modify it
377             under the terms of the the Artistic License (2.0). You may obtain a
378             copy of the full license at:
379              
380             L
381              
382             Any use, modification, and distribution of the Standard or Modified
383             Versions is governed by this Artistic License. By using, modifying or
384             distributing the Package, you accept this license. Do not use, modify,
385             or distribute the Package, if you do not accept this license.
386              
387             If your Modified Version has been derived from a Modified Version made
388             by someone other than you, you are nevertheless required to ensure that
389             your Modified Version complies with the requirements of this license.
390              
391             This license does not grant you the right to use any trademark, service
392             mark, tradename, or logo of the Copyright Holder.
393              
394             This license includes the non-exclusive, worldwide, free-of-charge
395             patent license to make, have made, use, offer to sell, sell, import and
396             otherwise transfer the Package with respect to any patent claims
397             licensable by the Copyright Holder that are necessarily infringed by the
398             Package. If you institute patent litigation (including a cross-claim or
399             counterclaim) against any party alleging that the Package constitutes
400             direct or contributory patent infringement, then this Artistic License
401             to you shall terminate on the date that such litigation is filed.
402              
403             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
404             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
405             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
406             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
407             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
408             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
409             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
410             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
411              
412              
413             =cut
414              
415             1; # End of Image::Imlib2::Thumbnail::Scaled