#------------------------------------------------------------------------------ # File: Rawzor.pm # # Description: Read meta information from Rawzor compressed images # # Revisions: 09/09/2008 - P. Harvey Created # # References: 1) http://www.rawzor.com/ #------------------------------------------------------------------------------ package Image::ExifTool::Rawzor; use strict; use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); $VERSION = '1.05'; # currently support this version Rawzor images my $implementedRawzorVersion = 199; # (up to version 1.99) # Rawzor-specific tags %Image::ExifTool::Rawzor::Main = ( GROUPS => { 2 => 'Other' }, VARS => { NO_ID => 1 }, NOTES => q{ Rawzor files store compressed images of other formats. As well as the information listed below, exiftool uncompresses and extracts the meta information from the original image. }, OriginalFileType => { }, OriginalFileSize => { PrintConv => $Image::ExifTool::Extra{FileSize}->{PrintConv}, }, RawzorRequiredVersion => { ValueConv => '$val / 100', PrintConv => 'sprintf("%.2f", $val)', }, RawzorCreatorVersion => { ValueConv => '$val / 100', PrintConv => 'sprintf("%.2f", $val)', }, # compression factor is originalSize/compressedSize (and compression # ratio is the inverse - ref "Data Compression" by David Salomon) CompressionFactor => { PrintConv => 'sprintf("%.2f", $val)' }, ); #------------------------------------------------------------------------------ # Extract information from a Rawzor file # Inputs: 0) ExifTool object reference, 1) dirInfo reference # Returns: 1 on success, 0 if this wasn't a valid Rawzor file sub ProcessRWZ($$) { my ($et, $dirInfo) = @_; my $raf = $$dirInfo{RAF}; my ($buff, $buf2); # read the Rawzor file header: # 0 string - "rawzor" signature # 6 int16u - Required SDK version # 8 int16u - Creator SDK version # 10 int64u - RWZ file size # 18 int64u - original raw file size # 26 undef[12] - reserved # 38 int64u - metadata offset $raf->Read($buff, 46) == 46 and $buff =~ /^rawzor/ or return 0; SetByteOrder('II'); my $reqVers = Get16u(\$buff, 6); my $creatorVers = Get16u(\$buff, 8); my $rwzSize = Get64u(\$buff, 10); my $origSize = Get64u(\$buff, 18); my $tagTablePtr = GetTagTable('Image::ExifTool::Rawzor::Main'); $et->HandleTag($tagTablePtr, RawzorRequiredVersion => $reqVers); $et->HandleTag($tagTablePtr, RawzorCreatorVersion => $creatorVers); $et->HandleTag($tagTablePtr, OriginalFileSize => $origSize); $et->HandleTag($tagTablePtr, CompressionFactor => $origSize/$rwzSize) if $rwzSize; # check version numbers if ($reqVers > $implementedRawzorVersion) { $et->Warn("Version $reqVers Rawzor images not yet supported"); return 1; } my $metaOffset = Get64u(\$buff, 38); if ($metaOffset > 0x7fffffff) { $et->Warn('Bad metadata offset'); return 1; } # check for the ability to uncompress the information unless (eval { require IO::Uncompress::Bunzip2 }) { $et->Warn('Install IO::Compress::Bzip2 to decode Rawzor bzip2 compression'); return 1; } # read the metadata header: # 0 int64u - metadata section 0 end (offset in original file) # 8 int64u - metadata section 1 start # 16 int64u - metadata section 1 end # 24 int64u - metadata section 2 start # 32 undef[4] - reserved # 36 int32u - original metadata size # 40 int32u - compressed metadata size unless ($raf->Seek($metaOffset, 0) and $raf->Read($buff, 44) == 44) { $et->Warn('Error reading metadata header'); return 1; } my $metaSize = Get32u(\$buff, 36); if ($metaSize) { $$et{DontValidateImageData} = 1; # validate the metadata header and read the compressed metadata my $end0 = Get64u(\$buff, 0); my $pos1 = Get64u(\$buff, 8); my $end1 = Get64u(\$buff, 16); my $pos2 = Get64u(\$buff, 24); my $len = Get32u(\$buff, 40); unless ($raf->Read($buff, $len) == $len and $end0 + ($end1 - $pos1) + ($origSize - $pos2) == $metaSize and $end0 <= $pos1 and $pos1 <= $end1 and $end1 <= $pos2) { $et->Warn('Error reading image metadata'); return 1; } # uncompress the metadata unless (IO::Uncompress::Bunzip2::bunzip2(\$buff, \$buf2) and length($buf2) eq $metaSize) { $et->Warn('Error uncompressing image metadata'); return 1; } # re-assemble the original file (sans image data) undef $buff; # (can't hurt to free memory as soon as possible) $buff = substr($buf2, 0, $end0) . ("\0" x ($pos1 - $end0)) . substr($buf2, $end0, $end1 - $pos1) . ("\0" x ($pos2 - $end1)) . substr($buf2, $end0 + $end1 - $pos1, $origSize - $pos2); undef $buf2; # extract original information by calling ExtractInfo recursively $et->ExtractInfo(\$buff, { ReEntry => 1 }); undef $buff; } # set OriginalFileType from FileType of original file # then change FileType and MIMEType to indicate a Rawzor image my $origFileType = $$et{VALUE}{FileType}; if ($origFileType) { $et->HandleTag($tagTablePtr, OriginalFileType => $origFileType); $et->OverrideFileType('RWZ'); } else { $et->HandleTag($tagTablePtr, OriginalFileType => 'Unknown'); $et->SetFileType(); } return 1; } 1; # end __END__ =head1 NAME Image::ExifTool::Rawzor - Read meta information from Rawzor compressed images =head1 SYNOPSIS This module is used by Image::ExifTool =head1 DESCRIPTION This module contains definitions required by Image::ExifTool to extract meta information from Rawzor compressed images. =head1 AUTHOR Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com) This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 REFERENCES =over 4 =item L =back =head1 SEE ALSO L, L =cut