Image-ExifTool
view release on metacpan or search on metacpan
lib/Image/ExifTool/Jpeg2000.pm view on Meta::CPAN
# not sure why, but EXIF box is padded with leading 0's in my sample
my $pad = $dirName eq 'Exif' ? "\0\0\0\0" : '';
if ($$et{IsJXL} and $compress) {
# create as Brotli-compressed metadata
if (eval { require IO::Compress::Brotli }) {
my $compressed;
eval { $compressed = IO::Compress::Brotli::bro($pad . $newdir) };
if ($@ or not $compressed) {
BrotliWarn($et, $dirName);
} else {
$et->VPrint(0, " Writing Brotli-compressed $dir\n");
$newdir = $compressed;
$pad = $tag;
$tag = 'brob';
}
} else {
$et->Warn('Install IO::Compress::Brotli to create Brotli-compressed metadata');
}
}
my $boxhdr = pack('N', length($newdir) + length($pad) + 8) . $tag;
Write($outfile, $boxhdr, $pad, $newdir) or return 0;
next;
}
}
next unless $uuid{$dirName};
my $tagInfo;
foreach $tagInfo (@{$Image::ExifTool::Jpeg2000::Main{uuid}}) {
next unless $$tagInfo{Name} eq $dirName;
my $subdir = $$tagInfo{SubDirectory};
my $tagTable = GetTagTable($$subdir{TagTable});
my %dirInfo = (
DirName => $$subdir{DirName} || $dirName,
Parent => 'JP2',
);
# remove "UUID-" from start of directory name to allow appropriate
# directories to be written as a block
$dirInfo{DirName} =~ s/^UUID-//;
my $newdir = $et->WriteDirectory(\%dirInfo, $tagTable, $$subdir{WriteProc});
if (defined $newdir and length $newdir) {
my $boxhdr = pack('N', length($newdir) + 24) . 'uuid' . $uuid{$dirName};
Write($outfile, $boxhdr, $newdir) or return 0;
last;
}
}
}
return 1;
}
#------------------------------------------------------------------------------
# Create Color Specification Box
# Inputs: 0) ExifTool object ref, 1) Output file or scalar ref
# Returns: 1 on success
sub CreateColorSpec($$)
{
my ($et, $outfile) = @_;
my $meth = $et->GetNewValue('Jpeg2000:ColorSpecMethod');
my $prec = $et->GetNewValue('Jpeg2000:ColorSpecPrecedence') || 0;
my $approx = $et->GetNewValue('Jpeg2000:ColorSpecApproximation') || 0;
my $icc = $et->GetNewValue('ICC_Profile');
my $space = $et->GetNewValue('Jpeg2000:ColorSpace');
my $cdata = $et->GetNewValue('Jpeg2000:ColorSpecData');
unless ($meth) {
if ($icc) {
$meth = 2;
} elsif (defined $space) {
$meth = 1;
} elsif (defined $cdata) {
$meth = 4;
} else {
$et->Warn('Color space not defined'), return 0;
}
}
if ($meth eq '1') {
defined $space or $et->Warn('Must specify ColorSpace'), return 0;
$cdata = pack('N', $space);
} elsif ($meth eq '2' or $meth eq '3') {
defined $icc or $et->Warn('Must specify ICC_Profile'), return 0;
$cdata = $icc;
} elsif ($meth eq '4') {
defined $cdata or $et->Warn('Must specify ColorSpecData'), return 0;
} else {
$et->Warn('Unknown ColorSpecMethod'), return 0;
}
my $boxhdr = pack('N', length($cdata) + 11) . 'colr';
Write($outfile, $boxhdr, pack('CCC',$meth,$prec,$approx), $cdata) or return 0;
++$$et{CHANGED};
$et->VPrint(1, " + Jpeg2000:ColorSpec\n");
return 1;
}
#------------------------------------------------------------------------------
# Process JPEG 2000 box
# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) Pointer to tag table
# Returns: 1 on success when reading, or -1 on write error
# (or JP2 box or undef when writing from buffer)
sub ProcessJpeg2000Box($$$)
{
my ($et, $dirInfo, $tagTablePtr) = @_;
my $dataPt = $$dirInfo{DataPt};
my $dataLen = $$dirInfo{DataLen};
my $dataPos = $$dirInfo{DataPos} || 0;
my $dirLen = $$dirInfo{DirLen} || 0;
my $dirStart = $$dirInfo{DirStart} || 0;
my $base = $$dirInfo{Base} || 0;
my $outfile = $$dirInfo{OutFile};
my $dirName = $$dirInfo{DirName} || '';
my $dirEnd = $dirStart + $dirLen;
my ($err, $outBuff, $verbose, $doColour, $hash, $raf);
if ($dataPt) {
# save C2PA JUMBF as a block if requested
if ($dirName eq 'JUMBF' and $$et{REQ_TAG_LOOKUP}{jumbf} and not $$dirInfo{NoBlockSave}) {
if ($dirStart or $dirLen ne length($$dataPt)) {
my $dat = substr($$dataPt, $dirStart, $dirLen);
$et->FoundTag(JUMBF => \$dat);
} else {
$et->FoundTag(JUMBF => $dataPt);
}
}
} else {
$raf = $$dirInfo{RAF}; # read from RAF
}
if ($outfile) {
unless ($raf) {
# buffer output to be used for return value
$outBuff = '';
$outfile = \$outBuff;
}
# determine if we will be writing colr box
if ($dirName eq 'JP2Header') {
$doColour = 2 if defined $et->GetNewValue('ColorSpecMethod') or $et->GetNewValue('ICC_Profile') or
defined $et->GetNewValue('ColorSpecPrecedence') or defined $et->GetNewValue('ColorSpace') or
defined $et->GetNewValue('ColorSpecApproximation') or defined $et->GetNewValue('ColorSpecData');
}
} else {
# (must not set verbose flag when writing!)
$verbose = $$et{OPTIONS}{Verbose};
$et->VerboseDir($dirName) if $verbose;
# do hash if requested, but only for top-level image data
$hash = $$et{ImageDataHash} if $raf;
}
# loop through all contained boxes
my ($pos, $boxLen, $lastBox);
for ($pos=$dirStart; ; $pos+=$boxLen) {
( run in 1.206 second using v1.01-cache-2.11-cpan-5b529ec07f3 )