Mercurial > bins
changeset 2:c44d020e5f8a 1.1.29-extended
Importing extended patched version from http://www.uli-eckhardt.de/bins/index.en.html
author | Peter Gervai <grin@grin.hu> |
---|---|
date | Wed, 15 Oct 2008 23:31:54 +0200 |
parents | 178fed916ebe |
children | 66beb7e16b22 |
files | bins |
diffstat | 1 files changed, 181 insertions(+), 68 deletions(-) [+] |
line wrap: on
line diff
--- a/bins Wed Oct 15 23:29:18 2008 +0200 +++ b/bins Wed Oct 15 23:31:54 2008 +0200 @@ -2,7 +2,7 @@ # -*- cperl-indent-level: 4 -*- # BINS Photo Album version 1.1.29 -# Copyright (C) 2001-2005 Jérôme Sautret (Jerome@Sautret.org) +# Copyright (C) 2001-2005 Jerome Sautret (Jerome@Sautret.org) # # Original SWIGS code : # Copyright (C) 2000 Brendan McMahan (mcmahahb@whitman.edu) @@ -50,8 +50,8 @@ # Image manipulation use Image::Size; -use Image::Info qw(image_info); use Image::Magick; +use Image::ExifTool; # HTML manipulation use URI::Escape; @@ -237,7 +237,7 @@ previewMaxWidth => 150, # Max Thumbnail Width. - thumbPrevNext => 1, # If set to 1, display thumbnails close + thumbPrevNext => 1, # If set to 1, display thumbnails close # to the previous and next link at the # bottom of the image page. @@ -377,9 +377,9 @@ # anywhere. You can also use the -n command line # option. - colorStyle => "blue", # name of the color style to use - - templateStyle => "swigs", # name of the template style to use + colorStyle => "blue", # name of the color style to use + + templateStyle => "swigs", # name of the template style to use # The following parameters cannot be set in config files for now : globalConfigDir => "/etc/bins", # System wide configuration directory @@ -399,6 +399,10 @@ # strings on console and to # convert strings from .po # files. + + injectDir => '', # directory to be injected + # without rebuilding complete + # album ); my $codeset; @@ -417,7 +421,7 @@ $local2htmlConverter = Text::Iconv->new($defaultConfig{defaultEncoding}, $defaultConfig{htmlEncoding}); -# Here are set number, name and size of scaled images. +# Here are set number, name and size of scaled images. # This can be changed in the binsrc or album.xml files. # By default, there is three sizes, but you can remove or add some new # by editing the @scaledWidths, @scaledHeights, @sizeNames and @@ -449,17 +453,20 @@ $defaultConfig{fileActiveSizeNames} = \@fileActiveSizeNames; # Fields to display (in the list order) under the picture. These -# fields are defined in the getFields function below. +# fields are defined in the %fields hash below. my @mainFields = ("description", "people", "location", "date", - "event", "comment"); + "event", "comment", "usercomment"); # Fields to display (in the list order) in the details page. These -# fields are in the getFields function below. +# fields are defined in the %fields hash below. my @secondaryFields = ( # DigiCam _("BINS-SECTION DigiCam Info"), - "make", "model", "owner", "firmware", + "model", + "lensid", + "owner", + "firmware", # DigiCam settings for the image _("BINS-SECTION DigiCam settings for the image"), "artist", @@ -473,6 +480,8 @@ "CanonSharpness", # DigiCam settings for the photo _("BINS-SECTION DigiCam settings for the photo"), + "lens", + "focallength35efl", "canon_easy_shooting_mode", "canon_macro", "lightsource", @@ -481,6 +490,8 @@ "flashenergy", "CanonISO", "iso", + "aperture_value", + "fnumber", "exposure_time", "exposure_prog", "canon_digital_zoom", @@ -488,12 +499,8 @@ "CanonFocusType", "subject_distance", "metering_mode", - "focal_length", "shutter_speed_value", "brightness", - "aperture_value", - "max_aperture_value", - "fnumber", "canon_timer_length", "canon_continuous_drive_mode", "focal_plane_x_resolution", @@ -511,15 +518,11 @@ "bits_per_sample", "resolution", "compression", - "usercomment", - "exif_version", "image_width", "image_length", - "compressed_bits", "BINS-SECTION end", # close the last section ); -sub getFields { # The key is the string used as the name in the picture # description file. # Name corresponds to the string displayed under the picture. @@ -527,9 +530,8 @@ # found in some JPEG images. # The value of the EXIF structure is only used if no value # is present in the picture description file. - # Transform is a Perl operator used to convert an exif value - # to the desired format to display. It is evaluated as - # normal Perl code and the result has to be in $_. + # Note: See also postProcessHashArrays() for dateString related + # items my %fields = ( "title" => @@ -547,12 +549,6 @@ "date" => { Name => _("Date"), EXIF => "DateTimeOriginal", - Transform => '$_ = local2html(strftime $configHash->{dateString}, gmtime str2time "$_") if str2time "$_"', - # Alternatively, you could use regex substitution: - # English version is yyyy:mm:dd hh:mm:ss to yyyy/mm/dd hh:mm:ss : - # Transform => 's%^(\\d+):(\\d+):(\\d+) (.*)$%\$1/\$2/\$3 \$4%', - # French version is yyyy:mm:dd hh:mm:ss to dd/mm/yyyy hh:mm:ss : - # Transform => 's%^(\d+):(\d+):(\d+) (.*)$%$3/$2/$1 $4%', }, "event" => @@ -821,9 +817,22 @@ EXIF => "SensingMethod", Tip => _("Indicates the image sensor type on the camera or input device."), }, + "lens" => + { Name => _("Lens"), + EXIF => "LensSpec", + Tip => _("Indicates the used lens."), + }, + "focallength35efl" => + { Name => _("Focal Length 35mm equivalent"), + EXIF => "FocalLength35efl", + Tip => _("Indicates the focal length for 35mm .") + }, + "lensid" => + { Name => _("Lens"), + EXIF => "LensID", + Tip => _("Indicates the used lens."), + } ); - return \%fields; -} my @priorityExifTags = (); # the field in this list are taken from # the desc file, even if they are present @@ -847,10 +856,10 @@ }); $defaultConfig{colorsSubs} = \%colorsSubs; -sub getIntlSubs{ - my $configHash = shift; - # Strings to translate in the HTML template pages (if I18N is used) - my %intlSubs = ( STRING_THUMBNAILS => _("thumbnails"), +# Strings to translate in the HTML template pages (if I18N is used) +# Note: See also postProcessHashArrays() for dateString related +# items +my %intlSubs = ( STRING_THUMBNAILS => _("thumbnails"), STRING_IMAGELIST => _("Image List"), STRING_HOME => _("Home"), STRING_ALBUM => _("Album"), @@ -882,13 +891,11 @@ BINS_VERSION => "1.1.29", ENCODING => $defaultConfig{htmlEncoding}, GENERATED_DATE => _("on "). - local2html(strftime($configHash->{dateString}, + local2html(strftime($defaultConfig{dateString}, localtime)), BINS_ID => '<!--$Id: bins,v 1.182 2005/08/22 23:52:33 jerome Exp $-->', ); - return \%intlSubs; -} # @knownImageExtentions defines file extensions that BINS can handle as # input image. BINS _should_ handle all input format of ImageMagick @@ -910,7 +917,7 @@ # formats will be converted # to JPEG). -my @filesToLinkExtensions = ( "avi", "mpg", "mpeg", "mov" ); +my @filesToLinkExtensions = ( "avi", "mpg", "mpeg", "mov", "mp4" ); ############################################################################ # End of Configuration Section # @@ -925,6 +932,7 @@ sub beVerboseN; sub min; sub readConfigFile; +sub postProcessHashArrays; sub fileSize; sub generateAlbumPages; sub filenameToPreviewName; @@ -942,8 +950,6 @@ sub trimWhiteSpace; sub stringToBool; sub ignoreSet; -sub getFields; -sub getIntlSubs; sub generateThumbnailPages; sub generateThumbEntry; @@ -953,10 +959,10 @@ sub write_htaccess; print "\nBINS Photo Album 1.1.29 (http://bins.sautret.org/)\n"; -print "Copyright © 2001-2004 Jérôme Sautret (Jerome\@Sautret.org)\n"; +print "Copyright (C) 2001-2004 Jerome Sautret (Jerome\@Sautret.org)\n"; print "Some parts of code:\n"; -print "Copyright © 2000 Brendan McMahan (mcmahahb\@whitman.edu)\n"; -print "Copyright © John Moose (moosejc\@muohio.edu)\n\n"; +print "Copyright (C) 2000 Brendan McMahan (mcmahahb\@whitman.edu)\n"; +print "Copyright (C) John Moose (moosejc\@muohio.edu)\n\n"; print "This is free software with ABSOLUTELY NO WARRANTY.\n"; print "See COPYING file for details.\n\n"; @@ -988,7 +994,7 @@ Getopt::Long::Configure("bundling"); die "Invalid options\n" if (!GetOptions(\%option, "h", "p", "r:s", "e", "o:s", "t=s", "d=s", "s=s", - "c=s", "v:i", "i=s", "n=s", "f=s")); + "c=s", "v:i", "i=s", "n=s", "f=s", "j=s")); if (defined($option{v})) { $verbose = $option{v}; @@ -1005,6 +1011,27 @@ return \%option; } +# process hash arrays after reading config file +# a non-default value of dateString might have been read from the +# configuration file, so the proper values must be inserted into the +# %fields and %intlSubs hash arrays +sub postProcessHashArrays { + my $configHash = shift; + + # Transform is a Perl operator used to convert an exif value + # to the desired format to display. It is evaluated as + # normal Perl code and the result has to be in $_. + $fields{date}{Transform} = + '$_ = local2html(strftime $configHash->{dateString}, gmtime str2time "$_")'; + # Alternatively, you could use regex substitution: + # English version is yyyy:mm:dd hh:mm:ss to yyyy/mm/dd hh:mm:ss : + # Transform => 's%^(\\d+):(\\d+):(\\d+) (.*)$%\$1/\$2/\$3 \$4%', + # French version is yyyy:mm:dd hh:mm:ss to dd/mm/yyyy hh:mm:ss : + # Transform => 's%^(\d+):(\d+):(\d+) (.*)$%$3/$2/$1 $4%', + $intlSubs{GENERATED_DATE} = _("on "). + local2html(strftime($configHash->{dateString}, localtime)), +} + # process command line arguments after reading config file sub postProcessArgs { my $option = shift; @@ -1123,6 +1150,25 @@ die "albumdir_dir ($albumdir) can't be a subdirectory of picdir_dir ($picdir)" if ($albumdir2 =~ m/^$picdir2\//); + + if( defined $option{j} ) { + my $injectDir = $option{j}; + my $injectExists = 1; + + chdir $injectDir or warn "Can't chdir $injectDir: $!" and $injectExists = 0; + + if( $injectExists ) { + $injectDir = File::Spec->rel2abs(".") unless -l $option{j}; + chdir $pwd; + } + + die "inject_dir (specified via -j parameter) $option{j} must be a subdirectory of pic_dir ($picdir)" + unless $injectDir =~ m#^$picdir2/.*#; + + $configHash->{injectDir} + = File::Spec->rel2abs(File::Spec->canonpath($injectDir)); + $configHash->{injectDir} .= '/'; # add trailing slash + } } $picdir = File::Spec->rel2abs(File::Spec->canonpath($picdir)); @@ -1254,9 +1300,12 @@ # pre process command line args before reading config files my $options = preProcessArgs(\%defaultConfig); - # read configurations files + # read configurations files my $defaultConfig = readConfigFile(\%defaultConfig); + # post process %fields and %intlSubs hash arrays + postProcessHashArrays($defaultConfig); + # post process command line args after reading config files postProcessArgs($options, $defaultConfig); @@ -2151,6 +2200,16 @@ sub generateImageListPage{ my ($album, $albumHashRef, $imageDataRef, $xlinksRef, $configHash) = @_; + if( $configHash->{injectDir} ne '' ) { + my $injectDir = $configHash->{injectDir}; + my $oneDirUp; + # drop the last subdirectory + ( $oneDirUp = $configHash->{injectDir} ) =~ s#(.*/).*?/$#$1#o; + my $dir = $picdir . $album; + # Only generate imagelist page during injection + # for 1-level-up or injected album itself + return unless $dir =~ m#($oneDirUp|$injectDir)$#; + } my %albumHash = %{$albumHashRef}; my @imageData = @{$imageDataRef}; my $pwd; @@ -2361,6 +2420,18 @@ sub generateLongSubAlbumPage{ my ($album, $albumHashRef, $configHash) = @_; + if( $configHash->{injectDir} ne '' ) { + my $injectDir = $configHash->{injectDir}; + my( $oneDirUp, $twoDirUp ); + # drop the last subdirectory + ( $oneDirUp = $configHash->{injectDir} ) =~ s#(.*/).*?/$#$1#o; + # drop the last subdirectory + ( $twoDirUp = $oneDirUp ) =~ s#(.*/).*?/$#$1#o; + my $dir = $picdir . $album; + # Only generate subalbum page during injection for + # 1-level-up or 2-level-up or injected album itself + return unless $dir =~ m#($oneDirUp|$twoDirUp|$injectDir)$#; + } my %albumHash = %{$albumHashRef}; # hash for final subsitutions @@ -2641,6 +2712,18 @@ my ($album, $albumHashRef, $firstIsIndex, $configHash, $xlinkListRef, @imageData) = @_; + + if( $configHash->{injectDir} ne '' ) { + my $injectDir = $configHash->{injectDir}; + my $oneDirUp; + # drop the last subdirectory + ( $oneDirUp = $configHash->{injectDir} ) =~ s#(.*/).*?/$#$1#o; + my $dir = $picdir . $album; + # Only generate thumbnail page during injection for + # 1-level-up or injected album itself + return unless $dir =~ m#($oneDirUp|$injectDir)$#; + } + my @xlinkList=@$xlinkListRef; my %albumHash = %{$albumHashRef}; my $numImages = scalar(@imageData); #element count @@ -2667,7 +2750,7 @@ for($crntPage=0; $crntPage < $numPages; $crntPage++) { #calculate prev, next thumb page # we set prev and next equal to the empty string - # if we have only 1 page to + # if we have only 1 page to # to indicate prev and next buttons should not be displayed. my ($prev, $next); if ($numPages == 1) { @@ -2765,6 +2848,7 @@ # set up all the substitutions, first with subs for header my %subsHash; + $subsHash{PREVIEW_MAX_WIDTH} = $configHash->{previewMaxWidth}; $subsHash{THUMBS_TABLE} = \@thumbTable; $subsHash{PRELOAD_IMAGES} = $preloadImages; $subsHash{THUMB_NUMBER_LINKS} = $numberLinks; @@ -2879,6 +2963,8 @@ $configHash->{colorsSubs}{$configHash->{colorStyle}}{SUBBAR_BACKCOLOR}; } + $thumb{IMAGE_COMMENT} = $$imageHashRef{comment}; + $thumb{USER_COMMENT} = $$imageHashRef{usercomment}; #print 'for image'.$imageHashRef->{'filename'}.'we have #$imageHashRef->{\'maxSize\'} = '.$imageHashRef->{'maxSize'}."\n"; @@ -2934,7 +3020,7 @@ $sectionTitle = $tagName; $sectionTitle =~ s/^BINS-SECTION //; }else{ - $tagValue = getFields($configHash)->{$tagName}; + $tagValue = $fields{$tagName}; if ($imageInfo->{$tagName}) { my %row = (FIELD_NAME => $tagValue->{'Name'}, FIELD_VALUE => local2html($imageInfo->{$tagName}) @@ -2989,7 +3075,7 @@ $subs_hash{CUSTOM_CSS} = $configHash->{customStyleSheet}; my @array; - push @array, {NAV_NAME => getIntlSubs($configHash)->{STRING_BACKTOTHEIMAGE}, + push @array, {NAV_NAME => $intlSubs{STRING_BACKTOTHEIMAGE}, NAV_LINK => "javascript:history.back();", NAV_ICON => "back.png", NAV_ID => "back"}; @@ -3056,6 +3142,13 @@ my ($album, $albumHashRef, $firstIsIndex, $configHash, @imagesToDisplay) = @_; + my $skipDueToInjection = 0; + + if( $configHash->{injectDir} ne '' ) { + # skip processing of images unless processing injected directory + $skipDueToInjection = 1 unless $picdir . $album eq $configHash->{injectDir}; + } + # an array of references to hashes storing information about each image my @imageData; @@ -3096,7 +3189,7 @@ $imageData[$i]{'type'} = $crntImageType; # don't escape the / character #$imageData[$i]{'imagepath'} = $album; - #print "imagepath : «$imagePath»\n"; + #print "imagepath : �$imagePath�\n"; #$imageData[$i]{'imageurl'} = $url; # to handle virtual images, make sure the images album exists @@ -3311,10 +3404,12 @@ $imageData[$i]{'detailsLink'} = generateSecondaryFieldsPage($imageData[$i], $album, $albumHashRef, $crntImageBase.$crntImageType, - $configHash); + $configHash) + unless $skipDueToInjection; if ( $configHash->{searchEngine}) { writeSearchString($imageData[$i], $configHash, $albumHashRef, - $album); + $album) + unless $skipDueToInjection; } } @@ -3322,6 +3417,7 @@ # now generate html for ($i=0; $i<$numImages; $i++) { + last if $skipDueToInjection; for (my $j=0; $j <= $imageData[$i]->{maxSize}; $j++) { my $lastImageURL = getHTMLImagePageLink($imageData[$numImages-1], $j, $numImages-1); @@ -3440,13 +3536,14 @@ $newpath = "$picdir$origName"; } beVerboseN("Linking from $albumdir$newName to $newpath... ", 2); - system("ln", "-sf", $newpath, "$albumdir$newName") == 0 + unlink("$albumdir$newName"); + symlink($newpath, "$albumdir$newName") == 1 or die("\nCannot link $albumdir$newName to $newpath: $?"); # the original file may be r/o but we don't have to modify it # but it must be readable by the http deamon if ($configHash->{updateOriginalPerms}) { - system("chmod", "a+r", "$picdir$origName") == 0 + chmod(0644, "$picdir$origName") == 1 or die("\nCannot set read permission on $albumdir$newName: $?"); } beVerboseN("done.", 2); @@ -3457,7 +3554,7 @@ system("cp", "-p", "$picdir$origName", "$albumdir$newName") == 0 or die("\nCannot copy $picdir$origName to $albumdir$newName: $?"); # make it writable in case $origName was r/o - system("chmod", "u+w,a+r", "$albumdir$newName") == 0 + chmod(0644, "$albumdir$newName") == 1 or die("\nCannot set write permission on $albumdir$newName: $?"); beVerboseN("done.", 2); return 1; @@ -3496,6 +3593,13 @@ my ($origName, $newName, $newWidth, $newHeight, $imageRef, $configHash) = @_; + if (-e "$albumdir$newName"){ + if (((lstat("$albumdir$newName"))[9]) >= ((stat("$picdir$origName"))[9])){ + beVerboseN("\n image already exists and is newer, skipping.", 2); + ($newWidth, $newHeight) = imgsize($albumdir.$newName); + return ($newWidth, $newHeight); + } + } if (writeScaledVersion($origName, $newName, $newWidth, $newHeight, $imageRef, $configHash)){ if ($configHash->{rotateImages} eq 'destination'){ @@ -3609,7 +3713,7 @@ $subs_hash{FIRST_IMAGE} = $firstImage; $subs_hash{LAST_IMAGE} = $lastImage; $subs_hash{IMAGE_COMMENT} = $imageHashRef->{comment}; - + $subs_hash{USER_COMMENT} = $imageHashRef->{usercomment}; renderTemplate("image", $albumdir.$album.$imageHashRef->{$size}{htmlFileName}, \%subs_hash, $configHash); @@ -3646,7 +3750,7 @@ if (${%$hashref}{$tagName}) { my $value=${%$hashref}{$tagName}; $value =~ s/'/'/g ; # in case it's used in javascript code - push @descTable, {DESC_FIELD_NAME => getFields($configHash)->{$tagName}->{'Name'}, + push @descTable, {DESC_FIELD_NAME => $fields{$tagName}->{'Name'}, DESC_FIELD_VALUE => $value, }; } @@ -3791,7 +3895,7 @@ %{$templateParameters} = (%{$templateParameters}, %{$configHash->{colorsSubs}{$configHash->{colorStyle}}}, - %{getIntlSubs($configHash)}, + %intlSubs, ); # open the html template @@ -3919,7 +4023,7 @@ && $element->{Name} eq "field") { $fieldName = $element->{Attributes}{'name'}; $fieldValue = ""; - if (grep (/^$fieldName$/, keys(%{getFields($configHash)}))) { + if (grep (/^$fieldName$/, keys(%fields))) { beVerbose(" Reading field '$fieldName':", 3); foreach my $characters (@{$element->{Contents}}) { #if (UNIVERSAL::isa($characters, 'XML::Grove::Characters')) { @@ -4021,6 +4125,10 @@ if ($tagName eq "Canon-Tag-0x0009"){ return addExif("Owner", $tagValue, $exifHash, $priorityList); } + if ($tagName eq "UserComment") { + $tagValue = local2html ($tagValue); + return addExif($tagName, $tagValue, $exifHash, $priorityList);; + } } elsif (UNIVERSAL::isa($tagValue, 'ARRAY')) { if ($tagValue->[1] eq 0) { return 0; @@ -4317,7 +4425,12 @@ beVerboseN(" Reading Exif info from picture file $crntImage...", 2); my $pictureFile = $picdir.$dir.$base.$type; - my($camerainfo) = image_info($pictureFile); + my $exifTool = new Image::ExifTool; + + $exifTool->Options(Unknown => 1, + Charset => $defaultConfig{defaultEncoding} ); + my($camerainfo) = $exifTool->ImageInfo($pictureFile); + if (exists $camerainfo->{"error"}) { beVerboseN(" Can't read info from picture file $crntImage: ". $camerainfo->{"error"}."\n", 2); @@ -4345,13 +4458,13 @@ } # add value to desc Hash if field is void - foreach my $field (keys(%{getFields($configHash)})) { - my $fieldExif = getFields($configHash)->{$field}->{'EXIF'}; + foreach my $field (keys(%fields)) { + my $fieldExif = $fields{$field}->{'EXIF'}; if ((! $descHash->{$field}) && $fieldExif && $exifHash->{$fieldExif}) { beVerboseN(" Using '$field' from EXIF data: ". $exifHash->{$fieldExif}, 3); - my $func = getFields($configHash)->{$field}->{'Transform'}; + my $func = $fields{$field}->{'Transform'}; if ($func) { $_ = $exifHash->{$fieldExif}; beVerbose(" Evaluating '$func' from '$_'", 4); @@ -4668,8 +4781,8 @@ # (<bins> tag) merged with current hash. sub getConfigXML{ my $document = shift(@_); # Grove document - my $path = shift(@_); # path of the <bins> tag in the document - my $currentConfigHash = shift(@_); # hash ref to the current configuration + my $path = shift(@_); # path of the <bins> tag in the document + my $currentConfigHash = shift(@_); # hash ref to the current configuration #my $fieldNb; my $fieldName; my $fieldValue; @@ -4828,18 +4941,18 @@ beVerboseN(" Orientation for picture is '$orientation'", 3); - if ($orientation eq "top_left"){ + if ($orientation eq "Horizontal (normal)"){ return 0; } if ($imageName =~ m/$configHash->{noRotation}/) { return 0; } my $degrees; - if ($orientation eq "right_top"){ + if ($orientation eq "Rotate 90 CW"){ $degrees = 90; - }elsif ($orientation eq "left_bot"){ + }elsif ($orientation eq "Rotate 270 CW"){ $degrees = 270; - }elsif ($orientation eq "bot_right"){ + }elsif ($orientation eq "Rotate 180"){ $degrees = 180; } else { print "Warning, Orientation field has an unknown value '$orientation'.\n";