diff options
author | Daniel Friesel <derf@finalrewind.org> | 2018-06-26 17:36:20 +0200 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2018-06-26 17:36:20 +0200 |
commit | d4c4fb3208caa6a12a54f670afa7b0e2d96aa3ad (patch) | |
tree | 0a3c7a4a47eb73945575c87bff7911961b1a8a9a | |
parent | 770f2780491afe8d69f9daf12d60d73f2acf16d2 (diff) |
support recursive thumbnail generation on directory trees
-rwxr-xr-x | bin/dthumb | 5 | ||||
-rwxr-xr-x | lib/App/Dthumb.pm | 106 | ||||
-rw-r--r-- | share/html_start.dthumb | 10 | ||||
-rwxr-xr-x | t/20-app-dthumb.t | 4 | ||||
-rwxr-xr-x | t/21-app-dthumb.files.t | 23 | ||||
-rw-r--r-- | t/cmp/index.names | 4 | ||||
-rw-r--r-- | t/cmp/index.no-names | 4 | ||||
-rw-r--r-- | t/out/.thumbnails/invalid.png (renamed from t/imgdir/.thumbs/invalid.png) | 0 | ||||
-rw-r--r-- | t/out/no_image (renamed from t/imgdir/no_image) | 0 | ||||
-rw-r--r-- | t/out/one.png (renamed from t/imgdir/one.png) | bin | 6525 -> 6525 bytes | |||
-rw-r--r-- | t/out/two.png (renamed from t/imgdir/two.png) | bin | 13552 -> 13552 bytes |
11 files changed, 92 insertions, 64 deletions
@@ -96,8 +96,6 @@ current directory. It uses a javascript lightbox (see L<http://fancyapps.com/fancybox/>) to display images. To view them without the lightbox, open images by clicking on the filename instead of the thumbnail. -Note that recursion is not yet supported. - During operation, B<dthumb> will show its progress on STDERR. =head1 OPTIONS @@ -118,7 +116,8 @@ Recreate all thumbnails =item B<-R>, B<--recursive> -Also include directories in the file listing +Include directories in file listing and recurnsively generate thumbnails +for their contents. =item B<-d>, B<--size> I<maxsize> (default: 200) diff --git a/lib/App/Dthumb.pm b/lib/App/Dthumb.pm index 0223016..3d999bc 100755 --- a/lib/App/Dthumb.pm +++ b/lib/App/Dthumb.pm @@ -26,8 +26,8 @@ sub new { $conf{file_index} //= 'index.html'; $conf{dir_images} //= q{.}; - $conf{dir_data} = "$conf{dir_images}/.dthumb"; - $conf{dir_thumbs} = "$conf{dir_images}/.thumbs"; + $conf{dir_data} = "$conf{dir_images}/.dthumb"; + $conf{suffix_thumbs} = '.thumbnails'; $conf{names} //= ( $conf{'no-names'} ? 0 : 1 ); @@ -43,45 +43,53 @@ sub new { height => $conf{size} * $conf{spacing} . 'px', ); - $ref->{html} = $ref->{data}->get('html_start.dthumb'); - return bless( $ref, $obj ); } sub read_directories { my ($self) = @_; - my $thumbdir = $self->{config}->{dir_thumbs}; + my $thumbdir = $self->{config}->{suffix_thumbs}; my $imgdir = $self->{config}->{dir_images}; my ( @files, @old_thumbs ); - for my $file ( read_dir($imgdir) ) { + my @queue = read_dir( $imgdir, prefix => 1 ); + my @paths = ($imgdir); + + for my $path (@queue) { + my ( $basedir, $file ) = ( $path =~ m{ ^ (.*) / ([^/]*) $ }x ); if ( $file =~ m{ ^ [.] }x ) { next; } if ( $file eq 'index.html' ) { next; } - if ( -f "${imgdir}/${file}" + if ( -f $path and ( $self->{config}{all} or $file =~ m{ [.] (png | jp e? g) $ }ix ) ) { - push( @files, $file ); + push( @files, $path ); } - elsif ( $self->{config}{recursive} and -d "${imgdir}/${file}" ) { - push( @files, $file ); + elsif ( $self->{config}{recursive} and -d $path ) { + push( @files, $path ); + push( @queue, read_dir( $path, prefix => 1 ) ); + push( @paths, $path ); } } - if ( -d $thumbdir ) { - for my $file ( read_dir($thumbdir) ) { - if ( $file =~ m{^ [^.] }ox and not -f "${imgdir}/${file}" ) { - push( @old_thumbs, $file ); + for my $path (@paths) { + if ( -d "${path}/${thumbdir}" ) { + for my $file ( read_dir("${path}/${thumbdir}") ) { + if ( $file =~ m{^ [^.] }ox and not -f "${path}/${file}" ) { + push( @old_thumbs, "${path}/$file" ); + } } } + $self->{html}->{$path} = $self->{data}->get('html_start.dthumb'); } @{ $self->{files} } = sort { lc($a) cmp lc($b) } @files; + @{ $self->{paths} } = sort { lc($a) cmp lc($b) } @paths; @{ $self->{old_thumbnails} } = @old_thumbs; return; @@ -90,7 +98,7 @@ sub read_directories { sub create_files { my ($self) = @_; - my $thumbdir = $self->{config}->{dir_thumbs}; + my $thumbdir = $self->{config}->{suffix_thumbs}; my $datadir = $self->{config}->{dir_data}; my @files = $self->{data}->list_archived; my @icons; @@ -102,12 +110,18 @@ sub create_files { push( @icons, 'places/folder-blue.png' ); } - for my $dir ( $thumbdir, $datadir, "${datadir}/css", "${datadir}/js" ) { + for my $dir ( $datadir, "${datadir}/css", "${datadir}/js" ) { if ( not -d $dir ) { mkdir($dir); } } + for my $path ( @{ $self->{paths} } ) { + if ( not -d "${path}/${thumbdir}" ) { + mkdir("${path}/${thumbdir}"); + } + } + for my $file (@files) { write_file( "${datadir}/${file}", $self->{data}->get($file) ); } @@ -124,10 +138,8 @@ sub create_files { sub delete_old_thumbnails { my ($self) = @_; - my $thumbdir = $self->{config}->{dir_thumbs}; - for my $file ( @{ $self->{old_thumbnails} } ) { - unlink("${thumbdir}/${file}"); + unlink($file); } return; @@ -140,70 +152,77 @@ sub get_files { } sub create_thumbnail_html { - my ( $self, $file ) = @_; + my ( $self, $path ) = @_; my $div_width = $self->{config}->{size} * $self->{config}->{spacing}; my $div_height = $div_width + ( $self->{config}->{names} ? 10 : 0 ); - $self->{html} .= "<div class=\"image-container\">\n"; + my ( $basedir, $file ) = ( $path =~ m{ ^ (.*) / ([^/]*) $ }x ); - if ( -d $file ) { - $self->{html} .= sprintf( + my $html = \$self->{html}->{$basedir}; + + $$html .= "<div class=\"image-container\">\n"; + + if ( -d $path ) { + $$html .= sprintf( "\t<a href=\"%s\" title=\"%s\">\n" - . "\t\t<img src=\".dthumb/folder-blue.png\" alt=\"%s\" /></a>\n", + . "\t\t<img src=\"<!--BASE-->.dthumb/folder-blue.png\" alt=\"%s\" /></a>\n", ($file) x 3, ); } elsif ( $file =~ m{ [.] (png | jp e? g) $ }ix ) { - $self->{html} .= sprintf( + $$html .= sprintf( "\t<a class=\"fancybox\" href=\"%s\" title=\"%s\" data-fancybox-group=\"gallery\">\n" . "\t\t<img src=\"%s/%s\" alt=\"%s\" /></a>\n", ($file) x 2, - $self->{config}->{dir_thumbs}, + $self->{config}->{suffix_thumbs}, ($file) x 2, ); } else { - $self->{html} .= sprintf( + $$html .= sprintf( "\t<a href=\"%s\" title=\"%s\">\n" - . "\t\t<img src=\".dthumb/unknown.png\" alt=\"%s\" /></a>\n", + . "\t\t<img src=\"<!--BASE-->.dthumb/unknown.png\" alt=\"%s\" /></a>\n", ($file) x 3, ); } if ( $self->{config}->{names} or -d $file ) { - $self->{html} .= sprintf( + $$html .= sprintf( "\t<br />\n" . "\t<a style=\"%s;\" href=\"%s\">%s</a>\n", 'text-decoration: none', ($file) x 2, ); } - $self->{html} .= "</div>\n"; + $$html .= "</div>\n"; return; } sub create_thumbnail_image { - my ( $self, $file ) = @_; + my ( $self, $path ) = @_; - my $thumbdir = $self->{config}->{dir_thumbs}; + my $thumbdir = $self->{config}->{suffix_thumbs}; my $thumb_dim = $self->{config}->{size}; - if ( -e "${thumbdir}/${file}" + my ( $basedir, $file ) = ( $path =~ m{ ^ (.*) / ([^/]*) $ }x ); + + if ( -e "${basedir}/${thumbdir}/${file}" and not $self->{config}->{recreate} - and ( stat($file) )[9] <= ( stat("${thumbdir}/${file}") )[9] ) + and ( stat($path) )[9] + <= ( stat("${basedir}/${thumbdir}/${file}") )[9] ) { return; } - if ( -d $file + if ( -d $path or $self->{config}{all} and not( $file =~ m{ [.] (png | jp e? g) $ }ix ) ) { return; } - my $image = Image::Imlib2->load($file); + my $image = Image::Imlib2->load($path); my ( $dx, $dy ) = ( $image->width, $image->height ); my $thumb = $image; @@ -217,7 +236,7 @@ sub create_thumbnail_image { } $thumb->set_quality( $self->{config}->{quality} ); - $thumb->save("${thumbdir}/${file}"); + $thumb->save("${basedir}/${thumbdir}/${file}"); return; } @@ -225,9 +244,18 @@ sub create_thumbnail_image { sub write_out_html { my ($self) = @_; - $self->{html} .= $self->{data}->get('html_end.dthumb'); + my $index_name = $self->{config}->{file_index}; - write_file( $self->{config}->{file_index}, $self->{html} ); + for my $path ( @{ $self->{paths} } ) { + my $diff = substr( $path, length( $self->{config}->{dir_images} ) ); + my $path_to_base = q{}; + if ( length($diff) ) { + $path_to_base = '../' x ( scalar split( qr{/}, $diff ) - 1 ); + } + $self->{html}->{$path} .= $self->{data}->get('html_end.dthumb'); + $self->{html}->{$path} =~ s{<!--BASE-->}{$path_to_base}g; + write_file( "${path}/${index_name}", $self->{html}->{$path} ); + } return; } diff --git a/share/html_start.dthumb b/share/html_start.dthumb index e6ac830..0cdf5cc 100644 --- a/share/html_start.dthumb +++ b/share/html_start.dthumb @@ -4,11 +4,11 @@ <title><!-- $title --></title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <script type="text/javascript" src=".dthumb/js/jquery-1.10.2.min.js"></script> - <script type="text/javascript" src=".dthumb/js/jquery.mousewheel-3.0.6.pack.js"></script> - <script type="text/javascript" src=".dthumb/js/jquery.fancybox.pack.js"></script> - <link rel="stylesheet" type="text/css" href=".dthumb/css/jquery.fancybox.css" media="screen" /> - <link rel="stylesheet" type="text/css" href=".dthumb/css/main.css"/> + <script type="text/javascript" src="<!--BASE-->.dthumb/js/jquery-1.10.2.min.js"></script> + <script type="text/javascript" src="<!--BASE-->.dthumb/js/jquery.mousewheel-3.0.6.pack.js"></script> + <script type="text/javascript" src="<!--BASE-->.dthumb/js/jquery.fancybox.pack.js"></script> + <link rel="stylesheet" type="text/css" href="<!--BASE-->.dthumb/css/jquery.fancybox.css" media="screen" /> + <link rel="stylesheet" type="text/css" href="<!--BASE-->.dthumb/css/main.css"/> <script type="text/javascript">//<![CDATA[ $(document).ready(function() { $('.fancybox').fancybox(); diff --git a/t/20-app-dthumb.t b/t/20-app-dthumb.t index 9be60de..74288a8 100755 --- a/t/20-app-dthumb.t +++ b/t/20-app-dthumb.t @@ -16,8 +16,8 @@ isa_ok($dthumb->{data}, 'App::Dthumb::Data'); is($dthumb->{config}->{dir_data}, './.dthumb', 'Data directory is .dthumb'); is($dthumb->{config}->{dir_images}, '.', 'Image directory is .'); -is($dthumb->{config}->{dir_thumbs}, './.thumbs', - 'Thumbnail directory is dthumbs'); +is($dthumb->{config}->{suffix_thumbs}, '.thumbnails', + 'Thumbnail suffix is .thumbnails'); is($dthumb->{config}->{file_index}, 'index.html', 'index is index.html'); is($dthumb->{config}->{names} , 1, 'Show image names'); diff --git a/t/21-app-dthumb.files.t b/t/21-app-dthumb.files.t index 7c91580..60283a6 100755 --- a/t/21-app-dthumb.files.t +++ b/t/21-app-dthumb.files.t @@ -14,8 +14,8 @@ plan tests => 9; use_ok('App::Dthumb'); my %conf = ( - file_index => 't/out/index', - dir_images => 't/imgdir', + file_index => 'index', + dir_images => 't/out', ); my @created_files; my @indep_files = ('main.css'); @@ -23,10 +23,10 @@ my @indep_files = ('main.css'); my $dthumb = App::Dthumb->new(%conf); isa_ok($dthumb, 'App::Dthumb'); -mkdir('t/out'); +$dthumb->read_directories; for my $file (qw(one.png two.png)) { - $dthumb->create_thumbnail_html($file); + $dthumb->create_thumbnail_html("t/out/$file"); } $dthumb->write_out_html(); @@ -40,8 +40,10 @@ unlink('t/out/index'); $conf{names} = 0; $dthumb = App::Dthumb->new(%conf); +$dthumb->read_directories; + for my $file (qw(one.png two.png)) { - $dthumb->create_thumbnail_html($file); + $dthumb->create_thumbnail_html("t/out/$file"); } $dthumb->write_out_html(); @@ -53,9 +55,10 @@ unlink('t/out/index'); $dthumb = App::Dthumb->new(dir_images => 't/out'); -$dthumb->create_files(); +$dthumb->read_directories; +$dthumb->create_files; -ok(-d 't/out/.thumbs', 'create_files: Creates thumb dir'); +ok(-d 't/out/.thumbnails', 'create_files: Creates thumb dir'); ok(-d 't/out/.dthumb', 'create_files: Creates data dir'); for my $file ($dthumb->{data}->list_archived()) { @@ -64,11 +67,9 @@ for my $file ($dthumb->{data}->list_archived()) { unlink("t/out/.dthumb/${file}"); } } -rmdir('t/out/.thumbs'); rmdir('t/out/.dthumb/css'); rmdir('t/out/.dthumb/js'); rmdir('t/out/.dthumb'); -rmdir('t/out'); is_deeply([sort $dthumb->{data}->list_archived()], [sort @created_files], 'create_files: All files created'); @@ -78,5 +79,5 @@ $dthumb = App::Dthumb->new(%conf); $dthumb->read_directories(); -is_deeply($dthumb->{old_thumbnails}, ['invalid.png'], '{old_thumbnails}'); -is_deeply($dthumb->{files}, ['one.png', 'two.png'], '{files}'); +is_deeply($dthumb->{old_thumbnails}, ['t/out/invalid.png'], '{old_thumbnails}'); +is_deeply($dthumb->{files}, ['t/out/one.png', 't/out/two.png'], '{files}'); diff --git a/t/cmp/index.names b/t/cmp/index.names index d714ab5..fcfb547 100644 --- a/t/cmp/index.names +++ b/t/cmp/index.names @@ -18,13 +18,13 @@ <body><div> <div class="image-container"> <a class="fancybox" href="one.png" title="one.png" data-fancybox-group="gallery"> - <img src="t/imgdir/.thumbs/one.png" alt="one.png" /></a> + <img src=".thumbnails/one.png" alt="one.png" /></a> <br /> <a style="text-decoration: none;" href="one.png">one.png</a> </div> <div class="image-container"> <a class="fancybox" href="two.png" title="two.png" data-fancybox-group="gallery"> - <img src="t/imgdir/.thumbs/two.png" alt="two.png" /></a> + <img src=".thumbnails/two.png" alt="two.png" /></a> <br /> <a style="text-decoration: none;" href="two.png">two.png</a> </div> diff --git a/t/cmp/index.no-names b/t/cmp/index.no-names index e1e9e2c..9689b00 100644 --- a/t/cmp/index.no-names +++ b/t/cmp/index.no-names @@ -18,11 +18,11 @@ <body><div> <div class="image-container"> <a class="fancybox" href="one.png" title="one.png" data-fancybox-group="gallery"> - <img src="t/imgdir/.thumbs/one.png" alt="one.png" /></a> + <img src=".thumbnails/one.png" alt="one.png" /></a> </div> <div class="image-container"> <a class="fancybox" href="two.png" title="two.png" data-fancybox-group="gallery"> - <img src="t/imgdir/.thumbs/two.png" alt="two.png" /></a> + <img src=".thumbnails/two.png" alt="two.png" /></a> </div> </div> </body> diff --git a/t/imgdir/.thumbs/invalid.png b/t/out/.thumbnails/invalid.png index e69de29..e69de29 100644 --- a/t/imgdir/.thumbs/invalid.png +++ b/t/out/.thumbnails/invalid.png diff --git a/t/imgdir/no_image b/t/out/no_image index e69de29..e69de29 100644 --- a/t/imgdir/no_image +++ b/t/out/no_image diff --git a/t/imgdir/one.png b/t/out/one.png Binary files differindex 5903c34..5903c34 100644 --- a/t/imgdir/one.png +++ b/t/out/one.png diff --git a/t/imgdir/two.png b/t/out/two.png Binary files differindex f16d150..f16d150 100644 --- a/t/imgdir/two.png +++ b/t/out/two.png |