$File::Sticker::Scribe::Exif::VERSION
=
'4.0101'
;
BEGIN {
%Image::ExifTool::UserDefined::sticker
= (
GROUPS
=> {
0
=>
'XMP'
,
1
=>
'XMP-sticker'
,
2
=>
'Image'
},
WRITABLE
=>
'string'
,
FreeFields
=> { },
);
%Image::ExifTool::UserDefined
= (
'Image::ExifTool::XMP::Main'
=> {
sticker
=> {
SubDirectory
=> {
TagTable
=>
'Image::ExifTool::UserDefined::sticker'
},
},
}
);
Image::ExifTool::XMP::RegisterNamespace(\
%Image::ExifTool::UserDefined::sticker
);
}
sub
whoami { (
caller
(1) )[3] }
sub
init {
my
$self
=
shift
;
my
%parameters
=
@_
;
$self
->SUPER::init(
%parameters
);
}
sub
priority {
my
$class
=
shift
;
return
1;
}
sub
allowed_file {
my
$self
=
shift
;
my
$file
=
shift
;
say
STDERR whoami(),
" file=$file"
if
$self
->{verbose} > 2;
$file
=
$self
->_get_the_real_file(
filename
=>
$file
);
my
$ft
=
$self
->{file_magic}->info_from_filename(
$file
);
if
(
$ft
->{mime_type} =~ /(image|pdf)/
and
$ft
->{mime_type} !~ /gif/)
{
return
1;
}
return
0;
}
sub
known_fields {
my
$self
=
shift
;
return
{
title
=>
'TEXT'
,
creator
=>
'TEXT'
,
description
=>
'TEXT'
,
location
=>
'TEXT'
,
tags
=>
'MULTI'
,
%{
$self
->{wanted_fields}},
};
}
sub
readonly_fields {
my
$self
=
shift
;
return
{
date
=>
'TEXT'
,
copyright
=>
'TEXT'
,
flash
=>
'TEXT'
,
filesize
=>
'NUMBER'
,
imagesize
=>
'TEXT'
,
imageheight
=>
'NUMBER'
,
imagewidth
=>
'NUMBER'
,
megapixels
=>
'NUMBER'
};
}
sub
read_meta {
my
$self
=
shift
;
my
$filename
=
shift
;
say
STDERR whoami(),
" filename=$filename"
if
$self
->{verbose} > 2;
$filename
=
$self
->_get_the_real_file(
filename
=>
$filename
);
my
$exif_options
= {
DateFormat
=>
"%Y-%m-%d %H:%M:%S"
};
my
$info
= ImageInfo(
$filename
,
$exif_options
);
my
%meta
= ();
my
$is_gutenberg_book
= 0;
if
(
exists
$info
->{Identifier}
{
$is_gutenberg_book
= 1;
$meta
{
'url'
} =
$info
->{
'Identifier'
};
}
my
$description
=
''
;
foreach
my
$field
(
qw(Caption-Abstract Comment UserComment ImageDescription Description)
)
{
if
(
exists
$info
->{
$field
}
and
$info
->{
$field
}
and
$info
->{
$field
} !~ /^---/
and !
$description
)
{
$description
=
$info
->{
$field
};
$description
=~ s/\n$//;
}
}
$meta
{description} =
$description
if
$description
;
my
$creator
=
''
;
foreach
my
$field
(
qw(Author Artist Creator)
)
{
if
(
exists
$info
->{
$field
} and
$info
->{
$field
} and !
$creator
)
{
$creator
=
$info
->{
$field
};
}
}
$meta
{creator} =
$creator
if
$creator
;
my
$copyright
=
''
;
foreach
my
$field
(
qw(License Rights)
)
{
if
(
exists
$info
->{
$field
} and
$info
->{
$field
} and !
$copyright
)
{
$copyright
=
$info
->{
$field
};
}
}
$meta
{copyright} =
$copyright
if
$copyright
;
my
$date
=
''
;
foreach
my
$field
(
qw(CreateDate DateTimeOriginal Date PublishedDate PublicationDate)
)
{
if
(
exists
$info
->{
$field
} and
$info
->{
$field
} and !
$date
)
{
$date
=
$info
->{
$field
};
}
}
$meta
{date} =
$date
if
$date
;
my
@tags
= ();
foreach
my
$field
(
qw(Keywords Subject)
)
{
if
(
exists
$info
->{
$field
} and
$info
->{
$field
})
{
my
$val
=
$info
->{
$field
};
my
@these_tags
;
if
(
$is_gutenberg_book
)
{
$val
=~ s/\(//g;
$val
=~ s/\)//g;
$val
=~ s/\s--\s/,/g;
@these_tags
=
split
(/,\s?/,
$val
);
}
else
{
@these_tags
=
split
(/,\s*/,
$val
);
}
foreach
my
$t
(
@these_tags
)
{
$t
=~ s/ - / /g;
$t
=~ s/[^\w\s,-]//g;
push
@tags
,
$t
;
}
}
}
if
(
@tags
)
{
$meta
{tags} = [uniq
@tags
];
}
else
{
delete
$meta
{tags};
}
foreach
my
$field
(
qw(
Flash
ImageHeight
ImageSize
ImageWidth
Megapixels
PageCount
Location
Title
)
)
{
if
(
exists
$info
->{
$field
} and
$info
->{
$field
})
{
$meta
{
lc
(
$field
)} =
$info
->{
$field
};
}
}
if
(
exists
$info
->{FreeFields}
and
$info
->{FreeFields}
and
$info
->{FreeFields} =~ /^---/)
{
say
STDERR
sprintf
(
"FreeFields='%s'"
,
$info
->{FreeFields})
if
$self
->{verbose} > 2;
my
$data
;
eval
{
$data
= Load(
$info
->{FreeFields});};
if
($@)
{
warn
__PACKAGE__,
" Load of YAML data failed: $@"
;
}
elsif
(!
$data
)
{
warn
__PACKAGE__,
" no legal YAML"
if
$self
->{verbose} > 2;
}
else
{
foreach
my
$field
(
sort
keys
%{
$data
})
{
$meta
{
$field
} =
$data
->{
$field
};
}
}
}
elsif
(
exists
$info
->{Description}
and
$info
->{Description}
and
$info
->{Description} =~ /^---/)
{
say
STDERR
sprintf
(
"Description='%s'"
,
$info
->{Description})
if
$self
->{verbose} > 2;
my
$data
;
eval
{
$data
= Load(
$info
->{Description});};
if
($@)
{
warn
__PACKAGE__,
" Load of YAML data failed: $@"
;
}
elsif
(!
$data
)
{
warn
__PACKAGE__,
" no legal YAML"
if
$self
->{verbose} > 2;
}
else
{
foreach
my
$field
(
sort
keys
%{
$data
})
{
$meta
{
$field
} =
$data
->{
$field
};
}
}
}
elsif
(
exists
$info
->{ImageDescription}
and
$info
->{ImageDescription}
and
$info
->{ImageDescription} =~ /^---/)
{
say
STDERR
sprintf
(
"ImageDescription='%s'"
,
$info
->{ImageDescription})
if
$self
->{verbose} > 2;
my
$data
;
eval
{
$data
= Load(
$info
->{ImageDescription});};
if
($@)
{
warn
__PACKAGE__,
" Load of YAML data failed: $@"
;
}
elsif
(!
$data
)
{
warn
__PACKAGE__,
" no legal YAML"
if
$self
->{verbose} > 2;
}
else
{
foreach
my
$field
(
sort
keys
%{
$data
})
{
$meta
{
$field
} =
$data
->{
$field
};
}
}
}
elsif
(
exists
$info
->{UserComment}
and
$info
->{UserComment}
and
$info
->{UserComment} =~ /^---/)
{
say
STDERR
sprintf
(
"UserComment='%s'"
,
$info
->{UserComment})
if
$self
->{verbose} > 2;
my
$data
;
eval
{
$data
= Load(
$info
->{UserComment});};
if
($@)
{
warn
__PACKAGE__,
" Load of YAML data failed: $@"
;
}
elsif
(!
$data
)
{
warn
__PACKAGE__,
" no legal YAML"
if
$self
->{verbose} > 2;
}
else
{
foreach
my
$field
(
sort
keys
%{
$data
})
{
$meta
{
$field
} =
$data
->{
$field
};
}
}
}
return
\
%meta
;
}
sub
replace_one_field {
my
$self
=
shift
;
my
%args
=
@_
;
say
STDERR whoami(),
" field=$args{field},value=$args{value}"
if
$self
->{verbose} > 2;
my
$filename
=
$self
->_get_the_real_file(
filename
=>
$args
{filename});
my
$field
=
$args
{field};
my
$value
=
$args
{value};
my
$ft
=
$self
->{file_magic}->info_from_filename(
$filename
);
my
$et
= new Image::ExifTool;
$et
->Options(
ListSep
=>
','
,
ListSplit
=>
','
);
$et
->ExtractInfo(
$filename
);
my
$success
;
if
(
$field
eq
'creator'
)
{
$success
=
$et
->SetNewValue(
'Creator'
,
$value
);
}
elsif
(
$field
eq
'copyright'
)
{
$success
=
$et
->SetNewValue(
'License'
,
$value
);
}
elsif
(
$field
eq
'title'
)
{
$success
=
$et
->SetNewValue(
'Title'
,
$value
);
}
elsif
(
$field
eq
'location'
)
{
$success
=
$et
->SetNewValue(
'Location'
,
$value
);
}
elsif
(
$field
eq
'description'
)
{
$self
->_convert_freeform_data(
exif
=>
$et
);
$success
=
$et
->SetNewValue(
'UserComment'
,
$value
);
$success
=
$et
->SetNewValue(
'ImageDescription'
,
$value
);
if
(
$ft
->{mime_type} =~ /image\/jpeg/)
{
$success
=
$et
->SetNewValue(
'Comment'
,
$value
);
}
}
elsif
(
$field
eq
'tags'
)
{
if
(
ref
$value
eq
'ARRAY'
)
{
$success
=
$et
->SetNewValue(
'Keywords'
,
$value
);
$success
=
$et
->SetNewValue(
'Subject'
,
$value
);
}
else
{
my
@tags
=
split
(/,/,
$value
);
$success
=
$et
->SetNewValue(
'Keywords'
, \
@tags
);
$success
=
$et
->SetNewValue(
'Subject'
, \
@tags
);
}
}
else
{
my
$fdata
=
$self
->_read_freeform_data(
exif
=>
$et
);
$fdata
->{
$field
} =
$value
;
$success
=
$self
->_write_freeform_data(
newdata
=>
$fdata
,
exif
=>
$et
);
}
if
(
$success
)
{
$et
->WriteInfo(
$filename
);
}
return
$success
;
}
sub
delete_field_from_file {
my
$self
=
shift
;
my
%args
=
@_
;
say
STDERR whoami(),
" field=$args{field}"
if
$self
->{verbose} > 2;
my
$filename
=
$self
->_get_the_real_file(
filename
=>
$args
{filename});
my
$field
=
$args
{field};
my
$ft
=
$self
->{file_magic}->info_from_filename(
$filename
);
my
$et
= new Image::ExifTool;
$et
->Options(
ListSep
=>
','
,
ListSplit
=>
','
);
$et
->ExtractInfo(
$filename
);
my
$success
;
if
(
$field
eq
'creator'
)
{
$success
=
$et
->SetNewValue(
'Creator'
)
}
elsif
(
$field
eq
'title'
)
{
$success
=
$et
->SetNewValue(
'Title'
)
}
elsif
(
$field
eq
'description'
)
{
if
(
$ft
->{mime_type} =~ /image\/jpeg/)
{
$success
=
$et
->SetNewValue(
'Comment'
);
}
$success
=
$et
->SetNewValue(
'ImageDescription'
);
$success
=
$et
->SetNewValue(
'UserComment'
);
}
elsif
(
$field
eq
'tags'
)
{
$success
=
$et
->SetNewValue(
'Keywords'
);
$success
=
$et
->SetNewValue(
'Subject'
);
}
else
{
my
$fdata
=
$self
->_read_freeform_data(
exif
=>
$et
);
if
(
exists
$fdata
->{
$field
})
{
delete
$fdata
->{
$field
};
$success
=
$self
->_write_freeform_data(
newdata
=>
$fdata
,
exif
=>
$et
);
}
}
if
(
$success
)
{
$et
->WriteInfo(
$filename
);
}
return
$success
;
}
sub
_get_the_real_file {
my
$self
=
shift
;
my
%args
=
@_
;
say
STDERR whoami(),
" filename=$args{filename}"
if
$self
->{verbose} > 2;
my
$filename
=
$args
{filename};
if
(-d
$filename
)
{
my
$cover_file
= (
$self
->{cover_file} ?
$self
->{cover_file} :
'cover.jpg'
);
$cover_file
= File::Spec->catfile(
$filename
,
$cover_file
);
if
(-f
$cover_file
)
{
$filename
=
$cover_file
;
}
else
{
croak
"$args{filename} is directory, cannot find $cover_file"
;
}
}
while
(-l
$filename
)
{
my
$realfile
=
readlink
$filename
;
if
(-f
$realfile
)
{
$filename
=
$realfile
;
}
else
{
croak
"$args{filename} is soft link, cannot find $realfile"
;
}
}
return
$filename
;
}
sub
_read_freeform_data {
my
$self
=
shift
;
my
%args
=
@_
;
say
STDERR whoami()
if
$self
->{verbose} > 2;
$self
->_convert_freeform_data(
%args
);
my
$ydata
;
my
$et
=
$args
{exif};
my
$ystring
=
$et
->GetValue(
'FreeFields'
);
$ystring
=
$et
->GetNewValue(
'FreeFields'
)
if
!
$ystring
;
say
STDERR
"ystring=$ystring"
if
$self
->{verbose} > 2;
if
(
$ystring
and
$ystring
=~ /^---/)
{
eval
{
$ydata
= Load(
$ystring
);};
if
($@)
{
warn
__PACKAGE__,
" Load of YAML data failed: $@ // '$ystring'"
;
}
elsif
(!
$ydata
)
{
warn
__PACKAGE__,
" no legal YAML"
if
$self
->{verbose} > 1;
}
}
say
STDERR Dump(
$ydata
)
if
$self
->{verbose} > 2;
return
$ydata
;
}
sub
_write_freeform_data {
my
$self
=
shift
;
my
%args
=
@_
;
say
STDERR whoami()
if
$self
->{verbose} > 2;
my
$newdata
=
$args
{newdata};
my
$et
=
$args
{exif};
foreach
my
$fn
(
keys
%{
$self
->{wanted_fields}})
{
if
(
$self
->{wanted_fields}->{
$fn
} eq
'MULTI'
and
exists
$newdata
->{
$fn
}
and
defined
$newdata
->{
$fn
}
and
$newdata
->{
$fn
} =~ /,/)
{
my
@vals
=
split
(/,/,
$newdata
->{
$fn
});
$newdata
->{
$fn
} = \
@vals
;
}
}
my
$ystring
= Dump(
$newdata
);
say
STDERR
"ystring=$ystring"
if
$self
->{verbose} > 2;
my
$success
=
$et
->SetNewValue(
'XMP-sticker:FreeFields'
,
$ystring
);
return
$success
;
}
sub
_convert_freeform_data {
my
$self
=
shift
;
my
%args
=
@_
;
say
STDERR whoami()
if
$self
->{verbose} > 2;
my
$et
=
$args
{exif};
my
$ystring
=
$et
->GetValue(
'XMP-sticker:FreeFields'
);
$ystring
=
$et
->GetNewValue(
'XMP-sticker:FreeFields'
)
if
!
$ystring
;
if
(
$ystring
and
$ystring
=~ /^---/)
{
return
1;
}
$ystring
=
$et
->GetValue(
'Description'
);
$ystring
=
$et
->GetNewValue(
'Description'
)
if
!
$ystring
;
if
(!
$ystring
or
$ystring
!~ /^---/)
{
$ystring
=
$et
->GetValue(
'ImageDescription'
);
$ystring
=
$et
->GetNewValue(
'ImageDescription'
)
if
!
$ystring
;
}
if
(!
$ystring
or
$ystring
!~ /^---/)
{
$ystring
=
$et
->GetValue(
'UserComment'
);
$ystring
=
$et
->GetNewValue(
'UserComment'
)
if
!
$ystring
;
}
my
$ydata
;
my
$success
= 0;
if
(
$ystring
and
$ystring
=~ /^---/)
{
eval
{
$ydata
= Load(
$ystring
);};
if
($@)
{
warn
__PACKAGE__,
" Load of YAML data failed: $@ ## '$ystring'"
;
}
elsif
(!
$ydata
)
{
warn
__PACKAGE__,
" no legal YAML"
if
$self
->{verbose} > 1;
}
else
{
$success
=
$et
->SetNewValue(
'XMP-sticker:FreeFields'
,
$ystring
);
if
(
$success
)
{
$et
->SetNewValue(
'XMP:Description'
);
my
$desc
=
$et
->GetValue(
'Comment'
);
$desc
=
$et
->GetNewValue(
'Comment'
)
if
!
$desc
;
$desc
=
$et
->GetValue(
'Caption-Abstract'
)
if
!
$desc
;
if
(
$desc
)
{
$et
->SetNewValue(
'UserComment'
,
$desc
);
$et
->SetNewValue(
'ImageDescription'
,
$desc
);
}
else
{
$et
->SetNewValue(
'ImageDescription'
);
$et
->SetNewValue(
'UserComment'
);
}
}
}
}
else
{
my
%newdata
= ();
my
$nystring
= Dump(\
%newdata
);
$success
=
$et
->SetNewValue(
'XMP-sticker:FreeFields'
,
$nystring
);
}
return
$success
;
}
1;