Adding data to IPTC field using Perl

2020-04-21 03:50发布

问题:

I want to set custom text to the IPTC field "Special instructions" in Perl.

How can this be done without the usage of a modul?

回答1:

Updated Again

Ok, in the light of your new requirement to actually read, modify and then re-write the IPTC information, you could use the following to read the IPTC information until we find something better:

print $image->Identify();

which gives this:

stuff ..
...
Profiles:
  Profile-8bim: 44 bytes
  Profile-iptc: 32 bytes
    Special Instructions[2,40]: Handle with care.
    Credit[2,110]: Mark
...
...

Mmm... it appears that that information gets written to stdout, and I don't know how to capture it. So I have investigated further and can get the IPTC information like this too:

$profile=$image->Get('IPTC');

which gives this:

0000000      021c    0028    4811    6e61    6c64    2065    6977    6874
         034 002   (  \0 021   H   a   n   d   l   e       w   i   t   h
0000020      6320    7261    2e65    021c    006e    4d04    7261    006b
               c   a   r   e   . 034 002   n  \0 004   M   a   r   k  \0

So it looks like individual IPTC fields are separated by:

1c - a single byte marker
byte - IPTC page
byte - IPTC field number
2 bytes - length of following field
<FIELD> - the actual data

So, you can read them and create your IPTC.txt file like this:

#!/usr/bin/perl
use strict;
use warnings;
use Image::Magick;

my ($image,$x,$profile,$id);
$image=Image::Magick->new(size=>'256x128');
$image->ReadImage('out.jpg');

$profile=$image->Get('IPTC');
my @items=split /\x1c/,$profile;
shift @items; # Discard emptiness before first separator
foreach (@items) {
   my $page=ord(substr($_,0,1));
   my $field=ord(substr($_,1,1));
   my $value=substr($_,4); # rest
   print "$page#$field=\"$value\"\n";
}

With my test file I get the following output from this:

2#110="CREDITCREDITCREDITCREDIT"
2#5="OBJECT"
2#115="SOURCE"
2#116="COPYRIGHT"
2#118="CONTACT"
2#120="CAPTION"

Then you can set IPTC data using the Perl API, as follows using the file IPTC.txt further down:

$image->Mogrify("profile",'8BIMTEXT:IPTC.txt');

The following is not a sensible, complete program in itself but it shows how to use the techniques I am suggesting:

#!/usr/bin/perl
use strict;
use warnings;
use Image::Magick;

my ($image,$x,$profile);
$image=Image::Magick->new(size=>'256x128');
$image->ReadImage('out.jpg');
print $image->Identify();                          # Get IPTC info - to screen but you can put it in a variable obviously
$image->Mogrify("profile",'8BIMTEXT:IPTC.txt');    # Write IPTC info
$image->Write('out.jpg');                          # Output image with new IPTC info

Updated

I have made a little progress... I can read the IPTC attributes from an image using the Perl API. For example, the following will read the IPTC Credit:

$credit=$image->Get('IPTC:2:110');

Original Answer

I am working on this, but the following may be enough to get you started anyway before I finish!

If I create a file like this, and call it IPTC.txt

2#40#Special Instructions="Handle with care."
2#110#Credit="Mark"

and then use ImageMagick convert like this:

convert out.jpg -profile 8BIMTEXT:IPTC.txt out.jpg

I can insert the IPTC information. I can then test this using jhead as follows:

jhead out.jpg
File name    : out.jpg
File size    : 18899 bytes
File date    : 2014:09:24 11:41:23
Resolution   : 1024 x 768
Color/bw     : Black and white
JPEG Quality : 86
======= IPTC data: =======
Spec. Instr.  : Handle with care.
Credit        : Mark

I know you don't want to shell out, but this will hopefully get us started on how to do it using the CPAN module you have. Which one do you have, by the way?