diff options
author | Daniel Friesel <derf@finalrewind.org> | 2011-02-27 13:43:07 +0100 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2011-02-27 13:43:07 +0100 |
commit | 9011214ddb1834875be28cbb8bf666f62d85cbb4 (patch) | |
tree | 6a8080d7290a6d4d1559dbe812878e967ade4dc0 | |
parent | 7fad3f17eb256fb25402fe4a4481a4b077502594 (diff) |
Create App::Dthumb
-rw-r--r-- | Build.PL | 6 | ||||
-rwxr-xr-x | bin/dthumb | 700 | ||||
-rwxr-xr-x | lib/App/Dthumb.pm | 198 | ||||
-rw-r--r-- | lib/App/Dthumb/Data.pm | 534 |
4 files changed, 753 insertions, 685 deletions
@@ -11,14 +11,16 @@ my $build = Module::Build->new( 'Test::Pod' => 0, }, dist_name => 'dthumb', - dist_version_from => 'bin/dthumb', + module_name => 'App::Dthumb', license => 'unrestricted', requires => { 'perl' => '5.10.0', 'autodie' => 0, 'Archive::Tar' => 0, + 'Cwd' => 0, + 'Data::Section' => 0, + 'Getopt::Long' => 0, 'Image::Imlib2' => 0, }, - script_files => 'bin/', ); $build->create_build_script(); @@ -5,242 +5,27 @@ use strict; use warnings; use autodie; -use constant { - DEFAULT_FILEMODE => oct(644), -}; - -use Archive::Tar; -use Cwd; -use Getopt::Long; -use Image::Imlib2; - - -my $thumbdir = '.thumbs'; -my $file_index = 'index.xhtml'; -my $file_lightbox = 'lightbox.js'; -my $title = q{}; -my $css_line = q{}; -my $thumb_dim = 200; -my $thumb_quality = 75; -my $thumb_spacing = 1.1; -my $thumb_no_names = 0; -my $css_source; -my @files; -my $number = 0; -my $create_archive = 0; -my $tar = Archive::Tar->new(); -local $| = 1; - -sub print_progress { - if (($number % 60) == 0) { - if ($number) { - printf(" %4d/%d\n", $number, scalar(@files)); - } - printf('[%3d%%] ', $number * 100 / @files); - } elsif (($number % 10) == 0) { - print ' '; - } - return; -} +use App::Dthumb; +use Getopt::Long qw(:config no_ignore_case); + +my $opt = {}; GetOptions( - 'c|css=s' => \$css_source, - 'd|size=i' => \$thumb_dim, - 's|spacing=f' => \$thumb_spacing, - 'n|no-names' => \$thumb_no_names, - 't|title=s' => \$title, - 'q|quality=i' => \$thumb_quality, - 'x|archive' => \$create_archive, -); - -if (defined($css_source)) { - $css_line = "<link rel=\"stylesheet\" type=\"text/css\" href=\"$css_source\"/>"; -} - -open(my $lightbox, '>', $file_lightbox); -while (my $line = <DATA>) { - print {$lightbox} $line; -} -close($lightbox); - -if (-d $thumbdir) { - opendir(my $thumb_dh, $thumbdir); - for my $file (readdir($thumb_dh)) { - if ($file =~ qr{^\.}) { - next; - } - - if (not -e $file) { - unlink("${thumbdir}/${file}"); - } - } - closedir($thumb_dh); -} - -open(my $index, '>', $file_index); - -print $index <<"EOD"; -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" - "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> -<head> - <title>$title</title> - <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> - $css_line - <script type="text/javascript" src="lightbox.js"></script> - <style type="text/css"> - -#lightbox { - background-color:#eee; - padding: 10px; - border-bottom: 2px solid #666; - border-right: 2px solid #666; -} - -#lightboxDetails { - font-size: 0.8em; - padding-top: 0.4em; -} - -#lightboxCaption { - float: left; -} - -#keyboardMsg { - float: right; -} - -#closeButton { - top: 5px; - right: 5px; -} - -#lightbox img { - border: none; - clear: both; -} - -#overlay img { - border: none; -} - -#overlay { - color: transparent; -/* background-image: url(overlay.png); */ -} - - </style> -</head> -<body><div> -EOD - -if (! -d $thumbdir) { - mkdir($thumbdir); -} - -opendir(my $dirhandle, '.'); - -foreach my $file (readdir($dirhandle)) { - if ($file =~ / \. ( png | jp e? g ) $ /ix) { - push(@files, $file); - } -} - -closedir($dirhandle); - -@files = sort { lc($a) cmp lc($b) } @files; - -if ($create_archive) { - print "Adding files to tar archive\n"; - $tar->add_files(@files); -} - -print "Generating thumbnails [ - cached | + generated ]\n"; - -foreach my $file (@files) { - my $thumb; - - if (defined($css_source)) { - print {$index} '<div class="imgbox">'; - } - else { - printf {$index} ( - '<div style="%s; %s; %s; width: %dpx; height: %dpx">', - 'text-align: center', - 'font-size: 80%', - 'float: left', - $thumb_dim * $thumb_spacing, - ($thumb_dim * $thumb_spacing) + ($thumb_no_names ? 0 : 10), - ); - } - - print {$index} "<a rel=\"lightbox\" href=\"$file\"><img src=\".thumbs/$file\" alt=\"$file\" /></a>\n"; - - if (not $thumb_no_names) { - print {$index} "<br />\n"; - - if ($css_source) { - print {$index} - "<a class=\"textlink\" href=\"${file}\">${file}</a>"; - } - else { - printf {$index} ( - '<a style="%s" href="%s">%s</a>', - 'text-decoration: none;', - $file, - $file, - ); - } - } - - print {$index} "</div>\n"; - print_progress; - $number++; - - if (-e "$thumbdir/$file") { - print '-'; - next; - } - - my $image = Image::Imlib2->load($file); - my ($dx, $dy) = ($image->width, $image->height); - - if ($dx > $thumb_dim or $dy > $thumb_dim) { - if ($dx > $dy) { - $thumb = $image->create_scaled_image($thumb_dim, 0); - } - else { - $thumb = $image->create_scaled_image(0, $thumb_dim); - } - } - else { - $thumb = $image; - } - - $thumb->set_quality($thumb_quality); - $thumb->save("$thumbdir/$file"); - - chmod(DEFAULT_FILEMODE, "$thumbdir/$file"); - print '+'; -} -print "\n"; - -if ($create_archive) { - print "Writing tar archive to disk\n"; - $tar->write('images.tar', undef, (split(qr{/}, getcwd))[-1]); - - print $index "</div><div style=\"clear: left;\"><a href=\"images.tar\">archive</a>\n"; -} - -print $index <<'EOD'; -</div></body> -</html> -EOD - -close($index); -chmod(DEFAULT_FILEMODE, $file_index); + $opt, + qw{ + size|d=i + spacing|s=f + no-names|n + quality|q=i + archive|x + }, +) or die("Please see perldoc -F $0\n"); + +my $dthumb = App::Dthumb->new($opt); +$dthumb->run(); +__END__ =head1 NAME @@ -272,10 +57,6 @@ All but the last directories in the files' path are stripped, besides that the directory structure is preserved. So, if you run dthumb -x in .../mydir/, the archive will contain mydir/1.jpg, mydir/2.jpg etc. -=item B<-c>, B<--css> I<file> - -Use I<file> for css definitions - =item B<-n>, B<--no-names> Do not show image names below thumbnails @@ -292,10 +73,6 @@ number of pixels (see --size) times I<float>. So for B<1.1> you have a small border around each image, for B<1.0> you have no border at all, etc. -=item B<-t>, B<--title> I<title> - -Use I<title> as <title> for the XHTML output - =item B<-q>, B<--quality> I<int> Set thumbnail quality. @@ -341,446 +118,3 @@ CC-BY-2.5 =head1 LICENSE 0. You just DO WHAT THE FUCK YOU WANT TO - - -=cut - -__DATA__ -/* - Lightbox JS: Fullsize Image Overlays - by Lokesh Dhakar - http://www.huddletogether.com - - For more information on this script, visit: - http://huddletogether.com/projects/lightbox/ - - Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/ - (basically, do anything you want, just leave my name and link) - - Table of Contents - ----------------- - Configuration - - Functions - - getPageScroll() - - getPageSize() - - pause() - - getKey() - - listenKey() - - showLightbox() - - hideLightbox() - - initLightbox() - - addLoadEvent() - - Function Calls - - addLoadEvent(initLightbox) - -*/ - - - -// -// Configuration -// - -// If you would like to use a custom loading image or close button reference them in the next two lines. -var loadingImage = 'loading.gif'; -var closeButton = 'close.gif'; - - - - - -// -// getPageScroll() -// Returns array with x,y page scroll values. -// Core code from - quirksmode.org -// -function getPageScroll(){ - - var yScroll; - - if (self.pageYOffset) { - yScroll = self.pageYOffset; - } else if (document.documentElement && document.documentElement.scrollTop){ // Explorer 6 Strict - yScroll = document.documentElement.scrollTop; - } else if (document.body) {// all other Explorers - yScroll = document.body.scrollTop; - } - - arrayPageScroll = new Array('',yScroll) - return arrayPageScroll; -} - - - -// -// getPageSize() -// Returns array with page width, height and window width, height -// Core code from - quirksmode.org -// Edit for Firefox by pHaez -// -function getPageSize(){ - - var xScroll, yScroll; - - if (window.innerHeight && window.scrollMaxY) { - xScroll = document.body.scrollWidth; - yScroll = window.innerHeight + window.scrollMaxY; - } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac - xScroll = document.body.scrollWidth; - yScroll = document.body.scrollHeight; - } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari - xScroll = document.body.offsetWidth; - yScroll = document.body.offsetHeight; - } - - var windowWidth, windowHeight; - if (self.innerHeight) { // all except Explorer - windowWidth = self.innerWidth; - windowHeight = self.innerHeight; - } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode - windowWidth = document.documentElement.clientWidth; - windowHeight = document.documentElement.clientHeight; - } else if (document.body) { // other Explorers - windowWidth = document.body.clientWidth; - windowHeight = document.body.clientHeight; - } - - // for small pages with total height less then height of the viewport - if(yScroll < windowHeight){ - pageHeight = windowHeight; - } else { - pageHeight = yScroll; - } - - // for small pages with total width less then width of the viewport - if(xScroll < windowWidth){ - pageWidth = windowWidth; - } else { - pageWidth = xScroll; - } - - - arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight) - return arrayPageSize; -} - - -// -// pause(numberMillis) -// Pauses code execution for specified time. Uses busy code, not good. -// Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602 -// -function pause(numberMillis) { - var now = new Date(); - var exitTime = now.getTime() + numberMillis; - while (true) { - now = new Date(); - if (now.getTime() > exitTime) - return; - } -} - -// -// getKey(key) -// Gets keycode. If 'x' is pressed then it hides the lightbox. -// - -function getKey(e){ - if (e == null) { // ie - keycode = event.keyCode; - } else { // mozilla - keycode = e.which; - } - key = String.fromCharCode(keycode).toLowerCase(); - - if(key == 'x'){ hideLightbox(); } -} - - -// -// listenKey() -// -function listenKey () { document.onkeypress = getKey; } - - -// -// showLightbox() -// Preloads images. Pleaces new image in lightbox then centers and displays. -// -function showLightbox(objLink) -{ - // prep objects - var objOverlay = document.getElementById('overlay'); - var objLightbox = document.getElementById('lightbox'); - var objCaption = document.getElementById('lightboxCaption'); - var objImage = document.getElementById('lightboxImage'); - var objLoadingImage = document.getElementById('loadingImage'); - var objLightboxDetails = document.getElementById('lightboxDetails'); - - - var arrayPageSize = getPageSize(); - var arrayPageScroll = getPageScroll(); - - // center loadingImage if it exists - if (objLoadingImage) { - objLoadingImage.style.top = (arrayPageScroll[1] + ((arrayPageSize[3] - 35 - objLoadingImage.height) / 2) + 'px'); - objLoadingImage.style.left = (((arrayPageSize[0] - 20 - objLoadingImage.width) / 2) + 'px'); - objLoadingImage.style.display = 'block'; - } - - // set height of Overlay to take up whole page and show - objOverlay.style.height = (arrayPageSize[1] + 'px'); - objOverlay.style.display = 'block'; - - // preload image - imgPreload = new Image(); - - imgPreload.onload=function(){ - objImage.src = objLink.href; - - // center lightbox and make sure that the top and left values are not negative - // and the image placed outside the viewport - var lightboxTop = arrayPageScroll[1] + ((arrayPageSize[3] - 35 - imgPreload.height) / 2); - var lightboxLeft = ((arrayPageSize[0] - 20 - imgPreload.width) / 2); - - objLightbox.style.top = (lightboxTop < 0) ? "0px" : lightboxTop + "px"; - objLightbox.style.left = (lightboxLeft < 0) ? "0px" : lightboxLeft + "px"; - - - objLightboxDetails.style.width = imgPreload.width + 'px'; - - if(objLink.getAttribute('title')){ - objCaption.style.display = 'block'; - //objCaption.style.width = imgPreload.width + 'px'; - objCaption.innerHTML = objLink.getAttribute('title'); - } else { - objCaption.style.display = 'none'; - } - - // A small pause between the image loading and displaying is required with IE, - // this prevents the previous image displaying for a short burst causing flicker. - if (navigator.appVersion.indexOf("MSIE")!=-1){ - pause(250); - } - - if (objLoadingImage) { objLoadingImage.style.display = 'none'; } - - // Hide select boxes as they will 'peek' through the image in IE - selects = document.getElementsByTagName("select"); - for (i = 0; i != selects.length; i++) { - selects[i].style.visibility = "hidden"; - } - - - objLightbox.style.display = 'block'; - - // After image is loaded, update the overlay height as the new image might have - // increased the overall page height. - arrayPageSize = getPageSize(); - objOverlay.style.height = (arrayPageSize[1] + 'px'); - - // Check for 'x' keypress - listenKey(); - - return false; - } - - imgPreload.src = objLink.href; - -} - - - - - -// -// hideLightbox() -// -function hideLightbox() -{ - // get objects - objOverlay = document.getElementById('overlay'); - objLightbox = document.getElementById('lightbox'); - - // hide lightbox and overlay - objOverlay.style.display = 'none'; - objLightbox.style.display = 'none'; - - // make select boxes visible - selects = document.getElementsByTagName("select"); - for (i = 0; i != selects.length; i++) { - selects[i].style.visibility = "visible"; - } - - // disable keypress listener - document.onkeypress = ''; -} - - - - -// -// initLightbox() -// Function runs on window load, going through link tags looking for rel="lightbox". -// These links receive onclick events that enable the lightbox display for their targets. -// The function also inserts html markup at the top of the page which will be used as a -// container for the overlay pattern and the inline image. -// -function initLightbox() -{ - - if (!document.getElementsByTagName){ return; } - var anchors = document.getElementsByTagName("a"); - - // loop through all anchor tags - for (var i=0; i<anchors.length; i++){ - var anchor = anchors[i]; - - if (anchor.getAttribute("href") && (anchor.getAttribute("rel") == "lightbox")){ - anchor.onclick = function () {showLightbox(this); return false;} - } - } - - // the rest of this code inserts html at the top of the page that looks like this: - // - // <div id="overlay"> - // <a href="#" onclick="hideLightbox(); return false;"><img id="loadingImage" /></a> - // </div> - // <div id="lightbox"> - // <a href="#" onclick="hideLightbox(); return false;" title="Click anywhere to close image"> - // <img id="closeButton" /> - // <img id="lightboxImage" /> - // </a> - // <div id="lightboxDetails"> - // <div id="lightboxCaption"></div> - // <div id="keyboardMsg"></div> - // </div> - // </div> - - var objBody = document.getElementsByTagName("body").item(0); - - // create overlay div and hardcode some functional styles (aesthetic styles are in CSS file) - var objOverlay = document.createElement("div"); - objOverlay.setAttribute('id','overlay'); - objOverlay.onclick = function () {hideLightbox(); return false;} - objOverlay.style.display = 'none'; - objOverlay.style.position = 'absolute'; - objOverlay.style.top = '0'; - objOverlay.style.left = '0'; - objOverlay.style.zIndex = '90'; - objOverlay.style.width = '100%'; - objBody.insertBefore(objOverlay, objBody.firstChild); - - var arrayPageSize = getPageSize(); - var arrayPageScroll = getPageScroll(); - - // preload and create loader image - var imgPreloader = new Image(); - - // if loader image found, create link to hide lightbox and create loadingimage - imgPreloader.onload=function(){ - - var objLoadingImageLink = document.createElement("a"); - objLoadingImageLink.setAttribute('href','#'); - objLoadingImageLink.onclick = function () {hideLightbox(); return false;} - objOverlay.appendChild(objLoadingImageLink); - - var objLoadingImage = document.createElement("img"); - objLoadingImage.src = loadingImage; - objLoadingImage.setAttribute('id','loadingImage'); - objLoadingImage.style.position = 'absolute'; - objLoadingImage.style.zIndex = '150'; - objLoadingImageLink.appendChild(objLoadingImage); - - imgPreloader.onload=function(){}; // clear onLoad, as IE will flip out w/animated gifs - - return false; - } - - imgPreloader.src = loadingImage; - - // create lightbox div, same note about styles as above - var objLightbox = document.createElement("div"); - objLightbox.setAttribute('id','lightbox'); - objLightbox.style.display = 'none'; - objLightbox.style.position = 'absolute'; - objLightbox.style.zIndex = '100'; - objBody.insertBefore(objLightbox, objOverlay.nextSibling); - - // create link - var objLink = document.createElement("a"); - objLink.setAttribute('href','#'); - objLink.setAttribute('title','Click to close'); - objLink.onclick = function () {hideLightbox(); return false;} - objLightbox.appendChild(objLink); - - // preload and create close button image - var imgPreloadCloseButton = new Image(); - - // if close button image found, - imgPreloadCloseButton.onload=function(){ - - var objCloseButton = document.createElement("img"); - objCloseButton.src = closeButton; - objCloseButton.setAttribute('id','closeButton'); - objCloseButton.style.position = 'absolute'; - objCloseButton.style.zIndex = '200'; - objLink.appendChild(objCloseButton); - - return false; - } - - imgPreloadCloseButton.src = closeButton; - - // create image - var objImage = document.createElement("img"); - objImage.setAttribute('id','lightboxImage'); - objLink.appendChild(objImage); - - // create details div, a container for the caption and keyboard message - var objLightboxDetails = document.createElement("div"); - objLightboxDetails.setAttribute('id','lightboxDetails'); - objLightbox.appendChild(objLightboxDetails); - - // create caption - var objCaption = document.createElement("div"); - objCaption.setAttribute('id','lightboxCaption'); - objCaption.style.display = 'none'; - objLightboxDetails.appendChild(objCaption); - - // create keyboard message - var objKeyboardMsg = document.createElement("div"); - objKeyboardMsg.setAttribute('id','keyboardMsg'); - objKeyboardMsg.innerHTML = 'press <a href="#" onclick="hideLightbox(); return false;"><kbd>x</kbd></a> to close'; - objLightboxDetails.appendChild(objKeyboardMsg); - - -} - - - - -// -// addLoadEvent() -// Adds event to window.onload without overwriting currently assigned onload functions. -// Function found at Simon Willison's weblog - http://simon.incutio.com/ -// -function addLoadEvent(func) -{ - var oldonload = window.onload; - if (typeof window.onload != 'function'){ - window.onload = func; - } else { - window.onload = function(){ - oldonload(); - func(); - } - } - -} - - - -addLoadEvent(initLightbox); // run initLightbox onLoad - diff --git a/lib/App/Dthumb.pm b/lib/App/Dthumb.pm new file mode 100755 index 0000000..2425800 --- /dev/null +++ b/lib/App/Dthumb.pm @@ -0,0 +1,198 @@ +package App::Dthumb; + +use strict; +use warnings; +use autodie; +use 5.010; + +use base 'Exporter'; + +use App::Dthumb::Data; +use Archive::Tar; +use Cwd; +use Image::Imlib2; + +our @EXPORT_OK = (); +our $VERSION = '0.1'; + +local $| = 1; + +sub new { + my ($obj, $conf) = @_; + my $ref = {}; + + $conf->{size} //= 200; + $conf->{spacing} //= 1.1; + $conf->{quality} //= 75; + + $ref->{config} = $conf; + + $ref->{data} = App::Dthumb::Data->new(); + $ref->{tar} = Archive::Tar->new(); + + $ref->{html} = $ref->{data}->html_start(); + + $ref->{current_file_id} = 0; + + $ref->{config}->{file_index} = 'index.xhtml'; + $ref->{config}->{file_lightbox} = 'lightbox.js'; + $ref->{config}->{dir_thumbs} = '.thumbs'; + + return bless($ref, $obj); +} + +sub run { + my ($self) = @_; + + $self->read_directories(); + $self->create_files(); + $self->delete_old_thumbnails(); + $self->create_thumbnails(); + $self->write_out_html(); +} + +sub read_directories { + my ($self) = @_; + my $thumbdir = $self->{config}->{dir_thumbs}; + my $imgdir = '.'; + my $dh; + my (@files, @old_thumbs); + + opendir($dh, $imgdir); + + for my $file (readdir($dh)) { + if (-f $file and $file =~ qr{ \. (png | jp e? g | gif | tif) $ }iox) { + push(@files, $file); + } + } + closedir($dh); + + if (-d $thumbdir) { + opendir($dh, $thumbdir); + for my $file (readdir($dh)) { + if ($file =~ qr{^ [^.] }ox and not -f $file) { + push(@old_thumbs, $file); + } + } + closedir($dh); + } + + @{$self->{files}} = sort { lc($a) cmp lc($b) } @files; + @{$self->{old_thumbnails}} = @old_thumbs; +} + +sub create_files { + my ($self) = @_; + my $thumbdir = $self->{config}->{dir_thumbs}; + my $fh; + + if (not -d $thumbdir) { + mkdir($thumbdir); + } + + open($fh, '>', 'lightbox.js'); + print {$fh} $self->{data}->lightbox(); + close($fh); +} + +sub delete_old_thumbnails { + my ($self) = @_; + my $thumbdir = $self->{config}->{dir_thumbs}; + + for my $file (@{$self->{old_thumbnails}}) { + unlink("${thumbdir}/${file}"); + } +} + +sub create_thumbnails { + my ($self) = @_; + + for my $file (@{$self->{files}}) { + $self->create_thumbnail_html($file); + $self->create_thumbnail_image($file); + } +} + +sub create_thumbnail_html { + my ($self, $file) = @_; + my $div_width = $self->{config}->{size} * $self->{config}->{spacing}; + my $div_height = $div_width + ($self->{config}->{no_names} ? 0 : 10); + + $self->{html} .= sprintf( + "<div style=\"%s; %s; %s; width: %dpx; height: %dpx\">\n", + 'text-align: center', + 'font-size: 80%', + 'float: left', + $div_width, + $div_height, + ); + $self->{html} .= sprintf( + "\t<a rel=\"lightbox\" href=\"%s\">\n" + . "\t\t<img src=\"%s/%s\" alt=\"%s\" />\n" + . "\t</a>\n", + $file, + $self->{config}->{dir_thumbs}, + ($file) x 2, + ); + if (not $self->{config}->{no_names}) { + $self->{html} .= sprintf( + "\t<br />\n" + . "\t<a style=\"%s;\" href=\"%s\">%s</a>\n", + 'text-decoration: none', + ($file) x 2, + ); + } + $self->{html} .= "</div>\n"; +} + +sub create_thumbnail_image { + my ($self, $file) = @_; + my $thumbdir = $self->{config}->{dir_thumbs}; + my $thumb_dim = $self->{config}->{size}; + + if (-e "${thumbdir}/${file}") { + return; + } + + my $image = Image::Imlib2->load($file); + my ($dx, $dy) = ($image->width(), $image->height()); + my $thumb = $image; + + if ($dx > $thumb_dim or $dy > $thumb_dim) { + if ($dx > $dy) { + $thumb = $image->create_scaled_image($thumb_dim, 0); + } + else { + $thumb = $image->create_scaled_image(0, $thumb_dim); + } + } + + $thumb->set_quality($self->{config}->{quality}); + $thumb->save("${thumbdir}/${file}"); +} + +sub write_out_html { + my ($self) = @_; + + $self->{html} .= $self->{data}->html_end(); + + open(my $fh, '>', $self->{config}->{file_index}); + print {$fh} $self->{html}; + close($fh); +} + +#sub print_progress { +# my ($self) = @_; +# my $num = $self->{current_file_id}; +# my $name = $self->{current_file_name}; +# +# if (($num % 60) == 0) { +# if ($number) { +# printf(" %4d/%d\n", $number, scalar(@files)); +# } +# printf('[%3d%%] ', $number * 100 / @files); +# } elsif (($number % 10) == 0) { +# print ' '; +# } +# return; +#} diff --git a/lib/App/Dthumb/Data.pm b/lib/App/Dthumb/Data.pm new file mode 100644 index 0000000..85ab1d2 --- /dev/null +++ b/lib/App/Dthumb/Data.pm @@ -0,0 +1,534 @@ +package App::Dthumb::Data; + +use strict; +use warnings; +use base 'Exporter'; + +use Data::Section -setup; + +our @EXPORT_OK = (); + +sub new { + my ($obj) = @_; + my $ref = {}; + return bless($ref, $obj); +} + +sub html_start { + my ($self) = @_; + return ${$self->section_data('html_and_css')}; +} + +sub html_end { + my ($self) = @_; + return ${$self->section_data('html_end')}; +} + +sub lightbox { + my ($self) = @_; + return ${$self->section_data('lightbox.js')}; +} + +1; + +__DATA__ + +______[ html_and_css ]______ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> +<head> + <title>dthumb</title> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> + <script type="text/javascript" src="lightbox.js"></script> + <style type="text/css"> + +#lightbox { + background-color:#eee; + padding: 10px; + border-bottom: 2px solid #666; + border-right: 2px solid #666; +} + +#lightboxDetails { + font-size: 0.8em; + padding-top: 0.4em; +} + +#lightboxCaption { + float: left; +} + +#keyboardMsg { + float: right; +} + +#closeButton { + top: 5px; + right: 5px; +} + +#lightbox img { + border: none; + clear: both; +} + +#overlay img { + border: none; +} + +#overlay { + color: transparent; +/* background-image: url(overlay.png); */ +} + + </style> +</head> +<body><div> + +______[ html_end ]______ + +</div> +</body> +</html> + +______[ lightbox.js ]______ + +/* + Lightbox JS: Fullsize Image Overlays + by Lokesh Dhakar - http://www.huddletogether.com + + For more information on this script, visit: + http://huddletogether.com/projects/lightbox/ + + Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/ + (basically, do anything you want, just leave my name and link) + + Table of Contents + ----------------- + Configuration + + Functions + - getPageScroll() + - getPageSize() + - pause() + - getKey() + - listenKey() + - showLightbox() + - hideLightbox() + - initLightbox() + - addLoadEvent() + + Function Calls + - addLoadEvent(initLightbox) + +*/ + + + +// +// Configuration +// + +// If you would like to use a custom loading image or close button reference them in the next two lines. +var loadingImage = 'loading.gif'; +var closeButton = 'close.gif'; + + + + + +// +// getPageScroll() +// Returns array with x,y page scroll values. +// Core code from - quirksmode.org +// +function getPageScroll(){ + + var yScroll; + + if (self.pageYOffset) { + yScroll = self.pageYOffset; + } else if (document.documentElement && document.documentElement.scrollTop){ // Explorer 6 Strict + yScroll = document.documentElement.scrollTop; + } else if (document.body) {// all other Explorers + yScroll = document.body.scrollTop; + } + + arrayPageScroll = new Array('',yScroll) + return arrayPageScroll; +} + + + +// +// getPageSize() +// Returns array with page width, height and window width, height +// Core code from - quirksmode.org +// Edit for Firefox by pHaez +// +function getPageSize(){ + + var xScroll, yScroll; + + if (window.innerHeight && window.scrollMaxY) { + xScroll = document.body.scrollWidth; + yScroll = window.innerHeight + window.scrollMaxY; + } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac + xScroll = document.body.scrollWidth; + yScroll = document.body.scrollHeight; + } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari + xScroll = document.body.offsetWidth; + yScroll = document.body.offsetHeight; + } + + var windowWidth, windowHeight; + if (self.innerHeight) { // all except Explorer + windowWidth = self.innerWidth; + windowHeight = self.innerHeight; + } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode + windowWidth = document.documentElement.clientWidth; + windowHeight = document.documentElement.clientHeight; + } else if (document.body) { // other Explorers + windowWidth = document.body.clientWidth; + windowHeight = document.body.clientHeight; + } + + // for small pages with total height less then height of the viewport + if(yScroll < windowHeight){ + pageHeight = windowHeight; + } else { + pageHeight = yScroll; + } + + // for small pages with total width less then width of the viewport + if(xScroll < windowWidth){ + pageWidth = windowWidth; + } else { + pageWidth = xScroll; + } + + + arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight) + return arrayPageSize; +} + + +// +// pause(numberMillis) +// Pauses code execution for specified time. Uses busy code, not good. +// Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602 +// +function pause(numberMillis) { + var now = new Date(); + var exitTime = now.getTime() + numberMillis; + while (true) { + now = new Date(); + if (now.getTime() > exitTime) + return; + } +} + +// +// getKey(key) +// Gets keycode. If 'x' is pressed then it hides the lightbox. +// + +function getKey(e){ + if (e == null) { // ie + keycode = event.keyCode; + } else { // mozilla + keycode = e.which; + } + key = String.fromCharCode(keycode).toLowerCase(); + + if(key == 'x'){ hideLightbox(); } +} + + +// +// listenKey() +// +function listenKey () { document.onkeypress = getKey; } + + +// +// showLightbox() +// Preloads images. Pleaces new image in lightbox then centers and displays. +// +function showLightbox(objLink) +{ + // prep objects + var objOverlay = document.getElementById('overlay'); + var objLightbox = document.getElementById('lightbox'); + var objCaption = document.getElementById('lightboxCaption'); + var objImage = document.getElementById('lightboxImage'); + var objLoadingImage = document.getElementById('loadingImage'); + var objLightboxDetails = document.getElementById('lightboxDetails'); + + + var arrayPageSize = getPageSize(); + var arrayPageScroll = getPageScroll(); + + // center loadingImage if it exists + if (objLoadingImage) { + objLoadingImage.style.top = (arrayPageScroll[1] + ((arrayPageSize[3] - 35 - objLoadingImage.height) / 2) + 'px'); + objLoadingImage.style.left = (((arrayPageSize[0] - 20 - objLoadingImage.width) / 2) + 'px'); + objLoadingImage.style.display = 'block'; + } + + // set height of Overlay to take up whole page and show + objOverlay.style.height = (arrayPageSize[1] + 'px'); + objOverlay.style.display = 'block'; + + // preload image + imgPreload = new Image(); + + imgPreload.onload=function(){ + objImage.src = objLink.href; + + // center lightbox and make sure that the top and left values are not negative + // and the image placed outside the viewport + var lightboxTop = arrayPageScroll[1] + ((arrayPageSize[3] - 35 - imgPreload.height) / 2); + var lightboxLeft = ((arrayPageSize[0] - 20 - imgPreload.width) / 2); + + objLightbox.style.top = (lightboxTop < 0) ? "0px" : lightboxTop + "px"; + objLightbox.style.left = (lightboxLeft < 0) ? "0px" : lightboxLeft + "px"; + + + objLightboxDetails.style.width = imgPreload.width + 'px'; + + if(objLink.getAttribute('title')){ + objCaption.style.display = 'block'; + //objCaption.style.width = imgPreload.width + 'px'; + objCaption.innerHTML = objLink.getAttribute('title'); + } else { + objCaption.style.display = 'none'; + } + + // A small pause between the image loading and displaying is required with IE, + // this prevents the previous image displaying for a short burst causing flicker. + if (navigator.appVersion.indexOf("MSIE")!=-1){ + pause(250); + } + + if (objLoadingImage) { objLoadingImage.style.display = 'none'; } + + // Hide select boxes as they will 'peek' through the image in IE + selects = document.getElementsByTagName("select"); + for (i = 0; i != selects.length; i++) { + selects[i].style.visibility = "hidden"; + } + + + objLightbox.style.display = 'block'; + + // After image is loaded, update the overlay height as the new image might have + // increased the overall page height. + arrayPageSize = getPageSize(); + objOverlay.style.height = (arrayPageSize[1] + 'px'); + + // Check for 'x' keypress + listenKey(); + + return false; + } + + imgPreload.src = objLink.href; + +} + + + + + +// +// hideLightbox() +// +function hideLightbox() +{ + // get objects + objOverlay = document.getElementById('overlay'); + objLightbox = document.getElementById('lightbox'); + + // hide lightbox and overlay + objOverlay.style.display = 'none'; + objLightbox.style.display = 'none'; + + // make select boxes visible + selects = document.getElementsByTagName("select"); + for (i = 0; i != selects.length; i++) { + selects[i].style.visibility = "visible"; + } + + // disable keypress listener + document.onkeypress = ''; +} + + + + +// +// initLightbox() +// Function runs on window load, going through link tags looking for rel="lightbox". +// These links receive onclick events that enable the lightbox display for their targets. +// The function also inserts html markup at the top of the page which will be used as a +// container for the overlay pattern and the inline image. +// +function initLightbox() +{ + + if (!document.getElementsByTagName){ return; } + var anchors = document.getElementsByTagName("a"); + + // loop through all anchor tags + for (var i=0; i<anchors.length; i++){ + var anchor = anchors[i]; + + if (anchor.getAttribute("href") && (anchor.getAttribute("rel") == "lightbox")){ + anchor.onclick = function () {showLightbox(this); return false;} + } + } + + // the rest of this code inserts html at the top of the page that looks like this: + // + // <div id="overlay"> + // <a href="#" onclick="hideLightbox(); return false;"><img id="loadingImage" /></a> + // </div> + // <div id="lightbox"> + // <a href="#" onclick="hideLightbox(); return false;" title="Click anywhere to close image"> + // <img id="closeButton" /> + // <img id="lightboxImage" /> + // </a> + // <div id="lightboxDetails"> + // <div id="lightboxCaption"></div> + // <div id="keyboardMsg"></div> + // </div> + // </div> + + var objBody = document.getElementsByTagName("body").item(0); + + // create overlay div and hardcode some functional styles (aesthetic styles are in CSS file) + var objOverlay = document.createElement("div"); + objOverlay.setAttribute('id','overlay'); + objOverlay.onclick = function () {hideLightbox(); return false;} + objOverlay.style.display = 'none'; + objOverlay.style.position = 'absolute'; + objOverlay.style.top = '0'; + objOverlay.style.left = '0'; + objOverlay.style.zIndex = '90'; + objOverlay.style.width = '100%'; + objBody.insertBefore(objOverlay, objBody.firstChild); + + var arrayPageSize = getPageSize(); + var arrayPageScroll = getPageScroll(); + + // preload and create loader image + var imgPreloader = new Image(); + + // if loader image found, create link to hide lightbox and create loadingimage + imgPreloader.onload=function(){ + + var objLoadingImageLink = document.createElement("a"); + objLoadingImageLink.setAttribute('href','#'); + objLoadingImageLink.onclick = function () {hideLightbox(); return false;} + objOverlay.appendChild(objLoadingImageLink); + + var objLoadingImage = document.createElement("img"); + objLoadingImage.src = loadingImage; + objLoadingImage.setAttribute('id','loadingImage'); + objLoadingImage.style.position = 'absolute'; + objLoadingImage.style.zIndex = '150'; + objLoadingImageLink.appendChild(objLoadingImage); + + imgPreloader.onload=function(){}; // clear onLoad, as IE will flip out w/animated gifs + + return false; + } + + imgPreloader.src = loadingImage; + + // create lightbox div, same note about styles as above + var objLightbox = document.createElement("div"); + objLightbox.setAttribute('id','lightbox'); + objLightbox.style.display = 'none'; + objLightbox.style.position = 'absolute'; + objLightbox.style.zIndex = '100'; + objBody.insertBefore(objLightbox, objOverlay.nextSibling); + + // create link + var objLink = document.createElement("a"); + objLink.setAttribute('href','#'); + objLink.setAttribute('title','Click to close'); + objLink.onclick = function () {hideLightbox(); return false;} + objLightbox.appendChild(objLink); + + // preload and create close button image + var imgPreloadCloseButton = new Image(); + + // if close button image found, + imgPreloadCloseButton.onload=function(){ + + var objCloseButton = document.createElement("img"); + objCloseButton.src = closeButton; + objCloseButton.setAttribute('id','closeButton'); + objCloseButton.style.position = 'absolute'; + objCloseButton.style.zIndex = '200'; + objLink.appendChild(objCloseButton); + + return false; + } + + imgPreloadCloseButton.src = closeButton; + + // create image + var objImage = document.createElement("img"); + objImage.setAttribute('id','lightboxImage'); + objLink.appendChild(objImage); + + // create details div, a container for the caption and keyboard message + var objLightboxDetails = document.createElement("div"); + objLightboxDetails.setAttribute('id','lightboxDetails'); + objLightbox.appendChild(objLightboxDetails); + + // create caption + var objCaption = document.createElement("div"); + objCaption.setAttribute('id','lightboxCaption'); + objCaption.style.display = 'none'; + objLightboxDetails.appendChild(objCaption); + + // create keyboard message + var objKeyboardMsg = document.createElement("div"); + objKeyboardMsg.setAttribute('id','keyboardMsg'); + objKeyboardMsg.innerHTML = 'press <a href="#" onclick="hideLightbox(); return false;"><kbd>x</kbd></a> to close'; + objLightboxDetails.appendChild(objKeyboardMsg); + + +} + + + + +// +// addLoadEvent() +// Adds event to window.onload without overwriting currently assigned onload functions. +// Function found at Simon Willison's weblog - http://simon.incutio.com/ +// +function addLoadEvent(func) +{ + var oldonload = window.onload; + if (typeof window.onload != 'function'){ + window.onload = func; + } else { + window.onload = function(){ + oldonload(); + func(); + } + } + +} + + + +addLoadEvent(initLightbox); // run initLightbox onLoad |