summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Build.PL6
-rwxr-xr-xbin/dthumb700
-rwxr-xr-xlib/App/Dthumb.pm198
-rw-r--r--lib/App/Dthumb/Data.pm534
4 files changed, 753 insertions, 685 deletions
diff --git a/Build.PL b/Build.PL
index 002b5bd..2158460 100644
--- a/Build.PL
+++ b/Build.PL
@@ -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();
diff --git a/bin/dthumb b/bin/dthumb
index 06b7451..012b911 100755
--- a/bin/dthumb
+++ b/bin/dthumb
@@ -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