# Album Plugin: captions/db/digikam
# Author : Kevin Barter
# Description : Reads an SQLite database to provide the caption, and optionally the tags
# : The database is created with the program Digikam
# : This plugin has only been tested with the database created by version 0.8.1
# : of Digikam. It should work with all versions of Digikam that create an SQLite 3
# : database, as long as the schema remains the same.
# Use : Copy the top level digikam album with all of its subdirectories to a directory
# : on your webserver. Also copy the digikam3.db file to where the script can
# : read it. It can be in the same directory as your digikam photo album, but it
# : does not have to be.
# : Here is what I used as command line:
# : album -plugin captions/db/digikam
# : -digikam:db='/mnt/photos/digikam3.db' /var/www/localhost/htdocs/photos/
# Required : Two additional perl modules are required for this plugin to function.
# : DBI - the generic database interface
# : DBD::SQLite - the database driver for SQLite 3
# : I do not have much experience with perl, and am not familiar with what is or
# : isn't proper naming conventions, practices, etc. Any pointers/guidance on
# : improving the code is appreciated.
# License : This code is licensed under the terms of the LGPL. If a copy of the license
# : is not available with this source, it can be viewed at
# : http://www.gnu.org/licenses/lgpl.html
# For info : album -plugin_info captions/db/digikam
# For usage : album -plugin_usage captions/db/digikam
use strict;
# My webhost does not have DBD:SQLite install, so I have installed it locally
# If you have the same problem, change to where you have installed the db driver
# use lib qw(/path/to/web/root/local/local/lib/perl/5.6.1);
my $DBI = album::attempt_require('DBI');
my $DBD_SQLITE = album::attempt_require('DBD::SQLite');
# Standard module, should be in all base PERL installations
use File::Basename;
sub start_plugin {
my ( $opt, $plugin, $path ) = @_;
my $ret = {
author => 'Kevin Barter',
href => 'http://digikam.TheBarters.com/',
version => '1.0',
description => "Get the image caption from the Digikam description.
Options:
-digikam:db REQUIRED Location of the digikam3.db file. If this
file is at /home/user/digikam3.db, then use
-digikam:db /home/user/digikam3.db
-digikam:usetags OPTIONAL Value can be X or nothing. If set to X,
the caption will contain the description of the
photo, as well as all of the tags for the photo
",
};
unless ($DBI) {
my $err = "DBI is required and not installed!\n";
print STDERR "\n[Plugin: $plugin] $err\n";
$ret->{description} .= "\n$err";
return $ret;
}
unless ($DBD_SQLITE) {
my $err = "DBD::SQLite is required and not installed!\n";
print STDERR "\n[Plugin: $plugin] $err\n";
$ret->{description} .= "\n$err";
return $ret;
}
# Setup my hooks
# Get photo caption from digikam
album::hook( $opt, 'modify_caption', \&modify_caption );
album::add_option( 1, 'db', $album::OPTION_STR,
usage => "Location of the digikam database (with path)" );
album::add_option( 1, 'usetags', $album::OPTION_BOOL,
usage => "Show the tags for a photo as part of the caption" );
# Get album caption from digikam
album::hook( $opt, 'modify_dir_caption', \&modify_dir_caption );
$ret;
}
sub modify_caption {
my ( $opt, $data, $hookname, $dir, $pic, $cap ) = @_;
my ( $caption, $image_id, $tag_name, $albumroot, $database );
# Check for the required options
album::fatal( $opt,
"Need to specify the full path to the digikam database (eg. /media/photos/digikam3.db) with -digikam:db"
)
unless album::option($opt,'db');
# TODO Does this need to be done? Perhaps only do it if there is a new caption?
album::new_html( $opt, $data, $pic );
$database = album::option($opt,'db');
# Get the top directory (where the Digikam Album is stored)
$albumroot = dirname($database);
# Remove the part of the path from directory to make it relative to where the
# Digikam Album is located
$dir =~ s/($albumroot)//;
( $caption, $image_id ) =
get_image_description( $dir, $pic, $database );
if ( album::option($opt,'usetags') == 'X' ) {
my @tags = get_image_tags( $image_id, $database );
my $tags = join( "
", @tags );
if ($caption) {
$caption = $caption . "
" . $tags;
}
else {
$caption = $tags;
}
}
return $caption;
}
sub modify_dir_caption {
my ( $opt, $data, $hookname, $dir, $pic, $cap ) = @_;
my $albumroot = album::option($opt,'topdir');
$dir =~ s/($albumroot)//;
my $database = album::option($opt,'db');
my $caption = get_album_caption( $dir, $database );
if ($caption) {
return $caption;
}
else {
return $cap;
}
}
my $dbh;
sub get_album_caption {
my ( $dir, $database ) = @_;
my ($caption);
# Open the database
unless ($dbh) { $dbh =
DBI->connect( "dbi:SQLite:$database", "", "",
{ RaiseError => 1, AutoCommit => 1 } ) };
my $sth = $dbh->prepare(q{select caption from Albums where url = ? });
$sth->execute($dir);
$sth->bind_columns( \$caption );
while ( $sth->fetch() ) {
}
#$sth->finish();
#$dbh->disconnect();
return ($caption);
}
sub get_image_description {
my ( $dir, $pic, $database ) = @_;
my ( $caption, $image_id, $query );
# Open the database
unless ($dbh) { $dbh =
DBI->connect( "dbi:SQLite:$database", "", "",
{ RaiseError => 1, AutoCommit => 1 } ) };
$query = q{
SELECT Images.caption, Images.id
FROM Albums, Images
WHERE albums.url = ?
AND Images.dirid = Albums.id
AND Images.name = ?
};
my $sth = $dbh->prepare($query);
$sth->execute( $dir, $pic );
$sth->bind_columns( \$caption, \$image_id );
while ( $sth->fetch() ) {
}
#$sth->finish();
#$dbh->disconnect();
return ( $caption, $image_id );
}
sub get_image_tags {
my ( $image_id, $database ) = @_;
my ( $tag_name, @tags );
# Open the database
unless ($dbh) { $dbh =
DBI->connect( "dbi:SQLite:$database", "", "",
{ RaiseError => 1, AutoCommit => 1 } ) };
# Get the tags for the image
my $sth = $dbh->prepare(
q{
SELECT Tags.name
FROM ImageTags, Tags, Images
WHERE Images.id = ?
AND Images.id = ImageTags.imageid
AND Tags.id = ImageTags.tagid
}
);
$sth->execute($image_id);
$sth->bind_columns( \$tag_name );
while ( $sth->fetch() ) {
push( @tags, $tag_name );
}
$sth->finish();
#$dbh->disconnect();
return @tags;
}
# Plugins always end with:
1;