ProShell v2.0
Dashboard
Server Info
Server: 127.0.0.80
PHP: 8.3.31
home
clients
08ce2314c3c7e396ea36e41d2a860c5e
sites
filmerletravail.org
wp-content
mu-plugins
2026-08-13 09:53:47
Editing: TIFF.pm
Cancel
Save Changes
package Image::TIFF; # Copyright 1999-2001, Gisle Aas. # Copyright 2006, 2007 Tels # # This library is free software; you can redistribute it and/or # modify it under the same terms as Perl v5.8.8 itself. use strict; use vars qw($VERSION); $VERSION = '1.10'; my @types = ( [ "BYTE", "C1", 1], [ "ASCII", "A1", 1], [ "SHORT", "n1", 2], [ "LONG", "N1", 4], [ "RATIONAL", "N2", 8], [ "SBYTE", "c1", 1], [ "UNDEFINED", "a1", 1], [ "BINARY", "a1", 1], # treat binary data as UNDEFINED [ "SSHORT", "n1", 2], [ "SLONG", "N1", 4], [ "SRATIONAL", "N2", 8], [ "FLOAT", "f1", 4], # XXX 4-byte IEEE format [ "DOUBLE", "d1", 8], # XXX 8-byte IEEE format # XXX TODO: # [ "IFD", "??", ?], # See ExifTool ); my %nikon1_tags = ( 0x0003 => "Quality", 0x0004 => "ColorMode", 0x0005 => "ImageAdjustment", 0x0006 => "CCDSensitivity", 0x0007 => "Whitebalance", 0x0008 => "Focus", 0x000A => "DigitalZoom", 0x000B => "Converter", ); my %nikon2_tags = ( 0x0001 => "NikonVersion", 0x0002 => "ISOSetting", 0x0003 => "ColorMode", 0x0004 => "Quality", 0x0005 => "Whitebalance", 0x0006 => "ImageSharpening", 0x0007 => "FocusMode", 0x0008 => "FlashSetting", 0x0009 => "FlashMetering", 0x000B => "WBAdjustment", 0x000F => "ISOSelection", 0x0080 => "ImageAdjustment", 0x0082 => "AuxiliaryLens", 0x0084 => "Lens", 0x0085 => "ManualFocusDistance", 0x0086 => "DigitalZoom", 0x0088 => { __TAG__ => "AFFocusPosition", pack("xCxx",0) => "Center", pack("xCxx",1) => "Top", pack("xCxx",2) => "Bottom", pack("xCxx",3) => "Left", pack("xCxx",4) => "Right", }, 0x008d => "ColorMode", 0x0090 => "FlashType", 0x0095 => "NoiseReduction", 0x0010 => "DataDump", ); my %olympus_tags = ( 0x0200 => "SpecialMode", 0x0201 => { __TAG__ => "JpegQual", 0 => "SQ", 1 => "HQ", 2 => "SHQ" }, 0x0202 => { __TAG__ => "Macro", 0 => "Normal", 1 => "Macro" }, 0x0204 => "DigiZoom", 0x0207 => "SoftwareRelease", 0x0208 => "PictInfo", 0x0209 => "CameraID", 0x0f00 => "DataDump", ); my %fujifilm_tags = ( 0x0000 => "Version", 0x1000 => "Quality", 0x1001 => { __TAG__ => "Sharpness", 1 => "Very Soft", 2 => "Soft", 3 => "Normal", 4 => "Hard", 5 => "Very Hard", }, 0x1002 => { __TAG__ => "WhiteBalance", 0 => "Auto", 256 => "Daylight", 512 => "Cloudy", 768 => "DaylightColor-fluorescence", 769 => "DaywhiteColor-fluorescence", 770 => "White-fluorescence", 1024 => "Incandenscense", 3840 => "Custom white balance", }, 0x1003 => { __TAG__ => "Color", 0 => "Normal", 256 => "High", 512 => "Low" }, 0x1004 => { __TAG__ => "Tone" , 0 => "Normal", 256 => "High", 512 => "Low" }, 0x1010 => { __TAG__ => "FlashMode", 0 => "Auto", 1 => "On", 2 => "Off", 3 => "Red-eye reduction" }, 0x1011 => "FlashStrength", 0x1020 => { __TAG__ => "Macro", 0 => "Off", 1 => "On"}, 0x1021 => { __TAG__ => "FocusMode", 0 => "Auto", 1 => "Manual" }, 0x1030 => { __TAG__ => "SlowSync", 0 => "Off", 1 => "On"}, 0x1031 => { __TAG__ => "PictureMode", 0 => "Auto", 1 => "Portrait", 2 => "Landscape", 4 => "Sports", 5 => "Night", 6 => "Program AE", 256 => "Aperture priority", 512 => "Shutter priority", 768 => "Manual", }, 0x1100 => { __TAG__ => "AutoBracketing", 0 => "Off", 1 => "On"}, 0x1300 => { __TAG__ => "BlurWarning", 0 => "No", 1 => "Yes"}, 0x1301 => { __TAG__ => "FocusWarning", 0 => "No", 1 => "Yes"}, 0x1302 => { __TAG__ => "AEWarning", 0 => "No", 1 => "Yes"}, ); my %casio_tags = ( 0x0001 => { __TAG__ => "RecordingMode", 1 => "SingleShutter", 2 => "Panorama", 3 => "Night scene", 4 => "Portrait", 5 => "Landscape", }, 0x0002 => { __TAG__ => "Quality", 1 => "Economy", 2 => "Normal", 3 => "Fine" }, 0x0003 => { __TAG__ => "FocusingMode", 2 => "Macro", 3 => "Auto", 4 => "Manual", 5 => "Infinity", }, 0x0004 => { __TAG__ => "FlashMode", 1 => "Auto", 2 => "On", 3 => "Off", 4 => "Red-eye reduction" }, 0x0005 => { __TAG__ => "FlashIntensity", 11 => "Weak", 13 => "Normal", 15 => "Strong" }, 0x0006 => "ObjectDistance", 0x0007 => { __TAG__ => "WhiteBalance", 1 => "Auto", 2 => "Tungsten", 3 => "Daylight", 4 => "Fluorescent", 5 => "Shade", 129 => "Manual", }, 0x000a => { __TAG__ => "DigitalZoom", 65536 => "Off", 65537 => "2X" }, 0x000b => { __TAG__ => "Sharpness", 0 => "Normal", 1 => "Soft", 2 => "Hard" }, 0x000c => { __TAG__ => "Contrast" , 0 => "Normal", 1 => "Low", 2 => "High" }, 0x000d => { __TAG__ => "Saturation", 0 => "Normal", 1 => "Low", 2 => "High" }, 0x0014 => { __TAG__ => "CCDSensitivity", 64 => "Normal", 125 => "+1.0", 250 => "+2.0", 244 => "+3.0", 80 => "Normal", 100 => "High", }, ); my %canon_0x0001_tags = ( 0 => { __TAG__ => "MacroMode", 1 => "Macro", 2 => "Normal" }, 1 => "SelfTimer", 2 => { __TAG__ => "Quality", 2 => "Normal", 3 => "Fine", 5 => "SuperFine" }, 3 => 'Tag-0x0001-03', 4 => { __TAG__ => 'FlashMode', 0 => 'Flash Not Fired', 1 => 'Auto', 2 => 'On', 3 => 'Red-Eye Reduction', 4 => 'Slow Synchro', 5 => 'Auto + Red-Eye Reduction', 6 => 'On + Red-Eye Reduction', 16 => 'External Flash' }, 5 => { __TAG__ => 'ContinuousDriveMode', 0 => 'Single Or Timer', 1 => 'Continuous' }, 6 => 'Tag-0x0001-06', 7 => { __TAG__ => 'FocusMode', 0 => 'One-Shot', 1 => 'AI Servo', 2 => 'AI Focus', 3 => 'MF', 4 => 'Single', 5 => 'Continuous', 6 => 'MF' }, 8 => 'Tag-0x0001-08', 9 => 'Tag-0x0001-09', 10 => { __TAG__ => 'ImageSize', 0 => 'Large', 1 => 'Medium', 2 => 'Small' }, 11 => { __TAG__ => 'EasyShootingMode', 0 => 'Full Auto', 1 => 'Manual', 2 => 'Landscape', 3 => 'Fast Shutter', 4 => 'Slow Shutter', 5 => 'Night', 6 => 'B&W', 7 => 'Sepia', 8 => 'Portrait', 9 => 'Sports', 10 => 'Macro/Close-Up', 11 => 'Pan Focus' }, 12 => { __TAG__ => 'DigitalZoom', 0 => 'None', 1 => '2x', 2 => '4x' }, 13 => { __TAG__ => 'Contrast', 0xFFFF => 'Low', 0 => 'Normal', 1 => 'High' }, 14 => { __TAG__ => 'Saturation', 0xFFFF => 'Low', 0 => 'Normal', 1 => 'High' }, 15 => { __TAG__ => 'Sharpness', 0xFFFF => 'Low', 0 => 'Normal', 1 => 'High' }, 16 => { __TAG__ => 'ISO', 0 => 'See ISOSpeedRatings Tag', 15 => 'Auto', 16 => '50', 17 => '100', 18 => '200', 19 => '400' }, 17 => { __TAG__ => 'MeteringMode', 3 => 'Evaluative', 4 => 'Partial', 5 => 'Center-Weighted' }, 18 => { __TAG__ => 'FocusType', 0 => 'Manual', 1 => 'Auto', 3 => 'Close-Up (Macro)', 8 => 'Locked (Pan Mode)' }, 19 => { __TAG__ => 'AFPointSelected', 0x3000 => 'None { __TAG__ => MF)', 0x3001 => 'Auto-Selected', 0x3002 => 'Right', 0x3003 => 'Center', 0x3004 => 'Left' }, 20 => { __TAG__ => 'ExposureMode', 0 => 'Easy Shooting', 1 => 'Program', 2 => 'Tv-priority', 3 => 'Av-priority', 4 => 'Manual', 5 => 'A-DEP' }, 21 => 'Tag-0x0001-21', 22 => 'Tag-0x0001-22', 23 => 'LongFocalLengthOfLensInFocalUnits', 24 => 'ShortFocalLengthOfLensInFocalUnits', 25 => 'FocalUnitsPerMM', 26 => 'Tag-0x0001-26', 27 => 'Tag-0x0001-27', 28 => { __TAG__ => 'FlashActivity', 0 => 'Did Not Fire', 1 => 'Fired' }, 29 => { __TAG__ => 'FlashDetails', 14 => 'External E-TTL', 13 => 'Internal Flash', 11 => 'FP Sync Used', 7 => '2nd ("Rear")-Curtain Sync Used', 4 => 'FP Sync Enabled' }, 30 => 'Tag-0x0001-30', 31 => 'Tag-0x0001-31', 32 => { __TAG__ => 'FocusMode', 0 => 'Single', 1 => 'Continuous' }, ); my %canon_0x0004_tags = ( 7 => { __TAG__ => 'WhiteBalance', 0 => 'Auto', 1 => 'Sunny', 2 => 'Cloudy', 3 => 'Tungsten', 4 => 'Fluorescent', 5 => 'Flash', 6 => 'Custom' }, 9 => 'SequenceNumber', 14 => 'AFPointUsed', 15 => { __TAG__ => 'FlashBias', 0xFFC0 => '-2 EV', 0xFFCC => '-1.67 EV', 0xFFD0 => '-1.50 EV', 0xFFD4 => '-1.33 EV', 0xFFE0 => '-1 EV', 0xFFEC => '-0.67 EV', 0xFFF0 => '-0.50 EV', 0xFFF4 => '-0.33 EV', 0x0000 => '0 EV', 0x000C => '0.33 EV', 0x0010 => '0.50 EV', 0x0014 => '0.67 EV', 0x0020 => '1 EV', 0x002C => '1.33 EV', 0x0030 => '1.50 EV', 0x0034 => '1.67 EV', 0x0040 => '2 EV', }, 19 => 'SubjectDistance' ); my %canon_tags = ( 0x0001 => { __TAG__ => "Custom_0x0001", __ARRAYOFFSET__ => \%canon_0x0001_tags }, 0x0004 => { __TAG__ => "Custom_0x0004", __ARRAYOFFSET__ => \%canon_0x0004_tags }, 0x0006 => "ImageType", 0x0007 => "FirmwareVersion", 0x0008 => "ImageNumber", 0x0009 => "OwnerName", 0x000c => "SerialNumber", ); # see http://www.compton.nu/panasonic.html my %panasonic_tags = ( 0x0001 => { __TAG__ => "ImageQuality", 2 => 'High', 3 => 'Normal', 6 => 'Very High', #3 (Leica) 7 => 'Raw', #3 (Leica) }, 0x0002 => "FirmwareVersion", 0x0003 => { __TAG__ => "WhiteBalance", 1 => 'Auto', 2 => 'Daylight', 3 => 'Cloudy', 4 => 'Halogen', 5 => 'Manual', 8 => 'Flash', 10 => 'Black & White', #3 (Leica) }, 0x0007 => { __TAG__ => "FocusMode", 1 => 'Auto', 2 => 'Manual', 5 => 'Auto, Continuous', 4 => 'Auto, Focus button', }, 0x000f => { __TAG__ => "SpotMode", # XXX TODO: does not decode properly "0,1" => 'On', "0,16" => 'Off', }, 0x001a => { __TAG__ => "ImageStabilizer", 2 => 'On, Mode 1', 3 => 'Off', 4 => 'On, Mode 2', }, 0x001c => { __TAG__ => "MacroMode", 1 => 'On', 2 => 'Off', }, 0x001f => { __TAG__ => "ShootingMode", 1 => 'Normal', 2 => 'Portrait', 3 => 'Scenery', 4 => 'Sports', 5 => 'Night Portrait', 6 => 'Program', 7 => 'Aperture Priority', 8 => 'Shutter Priority', 9 => 'Macro', 11 => 'Manual', 13 => 'Panning', 18 => 'Fireworks', 19 => 'Party', 20 => 'Snow', 21 => 'Night Scenery', }, 0x0020 => { __TAG__ => "Audio", 1 => 'Yes', 2 => 'No', }, 0x0021 => "DataDump", 0x0022 => "Panasonic 0x0022", 0x0023 => "WhiteBalanceBias", 0x0024 => "FlashBias", 0x0025 => "SerialNumber", 0x0026 => "Panasonic 0x0026", 0x0027 => "Panasonic 0x0027", 0x0028 => { __TAG__ => "ColorEffect", 1 => 'Off', 2 => 'Warm', 3 => 'Cool', 4 => 'Black & White', 5 => 'Sepia', }, 0x0029 => "Panasonic 0x0029", 0x002a => { __TAG__ => "BurstMode", 0 => 'Off', 1 => 'Low/High Quality', 2 => 'Infinite', }, 0x002b => "ImageSequenceNumber", 0x002c => { __TAG__ => "Contrast", 0 => 'Normal', 1 => 'Low', 2 => 'High', 0x100 => 'Low', # Leica 0x110 => 'Normal', # Leica 0x120 => 'High', # Leica }, 0x002d => { __TAG__ => "NoiseReduction", 0 => 'Standard', 1 => 'Low', 2 => 'High', }, 0x002e => { __TAG__ => "SelfTimer", 1 => 'Off', 2 => '10s', 3 => '2s', }, 0x002f => "Panasonic 0x002f", 0x0030 => "Panasonic 0x0030", 0x0031 => "Panasonic 0x0031", 0x0032 => "Panasonic 0x0032", ); # format: # "Make Model" => [ Offset, 'Tag_prefix', ptr to tags ] # Offset is either 0, or a positive number of Bytes. # Offset -1 or -2 means a kludge for Fuji or Nikon my %makernotes = ( "NIKON CORPORATION NIKON D1" => [0, 'NikonD1', \%nikon2_tags], "NIKON CORPORATION NIKON D70" => [-2, 'NikonD1', \%nikon2_tags], "NIKON CORPORATION NIKON D100" => [-2, 'NikonD1', \%nikon2_tags], # For the following manufacturers we simple discard the model and always # decode the MakerNote in the same manner. This makes it work with all # models, even yet unreleased ones. (That's better than the very limited # list of models we previously had) "CANON" => [0, 'Canon', \%canon_tags], 'PANASONIC' => [12, 'Panasonic', \%panasonic_tags], "FUJIFILM" => [-1, 'FinePix', \%fujifilm_tags], "CASIO" => [0, 'Casio', \%casio_tags], "OLYMPUS" => [8, 'Olympus', \%olympus_tags], ); BEGIN { # add some Nikon cameras for my $model (qw/E700 E800 E900 E900S E910 E950/) { $makernotes{'NIKON ' . $model} = [8, 'CoolPix', \%nikon1_tags]; } for my $model (qw/E880 E990 E995/) { $makernotes{'NIKON ' . $model} = [0, 'CoolPix', \%nikon2_tags]; } } my %exif_intr_tags = ( 0x1 => "InteroperabilityIndex", 0x2 => "InteroperabilityVersion", 0x1000 => "RelatedImageFileFormat", 0x1001 => "RelatedImageWidth", 0x1002 => "RelatedImageLength", ); # Tag decode helpers sub components_configuration_decoder; sub file_source_decoder; sub scene_type_decoder; my %exif_tags = ( 0x828D => "CFARepeatPatternDim", 0x828E => "CFAPattern", 0x828F => "BatteryLevel", 0x8298 => "Copyright", 0x829A => "ExposureTime", 0x829D => "FNumber", 0x83BB => "IPTC/NAA", 0x8769 => "ExifOffset", 0x8773 => "InterColorProfile", 0x8822 => { __TAG__ => "ExposureProgram", 0 => "unknown", 1 => "Manual", 2 => "Program", 3 => "Aperture priority", 4 => "Shutter priority", 5 => "Program creative", 6 => "Program action", 7 => "Portrait", 8 => "Landscape", # 9 .. 255 reserved }, 0x8824 => "SpectralSensitivity", 0x8827 => "ISOSpeedRatings", 0x8828 => "OECF", 0x9000 => "ExifVersion", 0x9003 => "DateTimeOriginal", 0x9004 => "DateTimeDigitized", 0x9101 => { __TAG__ => "ComponentsConfiguration", DECODER => \&components_configuration_decoder, }, 0x9102 => "CompressedBitsPerPixel", 0x9201 => "ShutterSpeedValue", 0x9202 => "ApertureValue", 0x9203 => "BrightnessValue", 0x9204 => "ExposureBiasValue", 0x9205 => "MaxApertureValue", 0x9206 => "SubjectDistance", 0x9207 => { __TAG__ => "MeteringMode", 0 => "unknown", 1 => "Average", 2 => "CenterWeightedAverage", 3 => "Spot", 4 => "MultiSpot", 5 => "Pattern", 6 => "Partial", # 7 .. 254 reserved in EXIF 1.2 255 => "other", }, 0x9208 => { __TAG__ => "LightSource", 0 => "unknown", 1 => "Daylight", 2 => "Fluorescent", 3 => "Tungsten", 4 => "Flash", # 5 .. 8 reserved in EXIF 2.2 9 => "Fine weather", 10 => "Cloudy weather", 11 => "Shade", 12 => "Daylight fluorescent (D 5700-7100K)", 13 => "Day white fluorescent (N 4600-5400K)", 14 => "Cool white fluorescent (W 3900-4500K)", 15 => "White fluorescent (WW 3200-3700K)", 17 => "Standard light A", 18 => "Standard light B", 19 => "Standard light C", 20 => "D55", 21 => "D65", 22 => "D75", 23 => "D50", 24 => "ISO studio tungesten", # 25 .. 254 reserved in EXIF 2.2 255 => "other light source", }, 0x9209 => { __TAG__ => "Flash", 0x0000 => "Flash did not fire", 0x0001 => "Flash fired", 0x0005 => "Strobe return light not detected", 0x0007 => "Strobe return light detected", 0x0009 => "Flash fired, compulsory flash mode", 0x000D => "Flash fired, compulsory flash mode, return light not detected", 0x000F => "Flash fired, compulsory flash mode, return light detected", 0x0010 => "Flash did not fire, compulsory flash mode", 0x0018 => "Flash did not fire, auto mode", 0x0019 => "Flash fired, auto mode", 0x001D => "Flash fired, auto mode, return light not detected", 0x001F => "Flash fired, auto mode, return light detected", 0x0020 => "No flash function", 0x0041 => "Flash fired, red-eye reduction mode", 0x0045 => "Flash fired, red-eye reduction mode, return light not detected", 0x0047 => "Flash fired, red-eye reduction mode, return light detected", 0x0049 => "Flash fired, compulsory flash mode, red-eye reduction mode", 0x004D => "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected", 0x004F => "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected", 0x0059 => "Flash fired, auto mode, red-eye reduction mode", 0x005D => "Flash fired, auto mode, return light not detected, red-eye reduction mode", 0x005F => "Flash fired, auto mode, return light detected, red-eye reduction mode" }, 0x920A => "FocalLength", 0x9214 => "SubjectArea", 0x927C => "MakerNote", 0x9286 => "UserComment", 0x9290 => "SubSecTime", 0x9291 => "SubSecTimeOriginal", 0x9292 => "SubSecTimeDigitized", 0xA000 => "FlashPixVersion", 0xA001 => "ColorSpace", 0xA002 => "ExifImageWidth", 0xA003 => "ExifImageLength", 0xA004 => "RelatedAudioFile", 0xA005 => {__TAG__ => "InteroperabilityOffset", __SUBIFD__ => \%exif_intr_tags, }, 0xA20B => "FlashEnergy", # 0x920B in TIFF/EP 0xA20C => "SpatialFrequencyResponse", # 0x920C - - 0xA20E => "FocalPlaneXResolution", # 0x920E - - 0xA20F => "FocalPlaneYResolution", # 0x920F - - 0xA210 => { __TAG__ => "FocalPlaneResolutionUnit", # 0x9210 - - 1 => "pixels", 2 => "dpi", 3 => "dpcm", }, 0xA214 => "SubjectLocation", # 0x9214 - - 0xA215 => "ExposureIndex", # 0x9215 - - 0xA217 => {__TAG__ => "SensingMethod", 1 => "Not defined", 2 => "One-chip color area sensor", 3 => "Two-chip color area sensor", 4 => "Three-chip color area sensor", 5 => "Color sequential area sensor", 7 => "Trilinear sensor", 8 => "Color sequential linear sensor" }, 0xA300 => {__TAG__ => "FileSource", DECODER => \&file_source_decoder, }, 0xA301 => {__TAG__ => "SceneType", DECODER => \&scene_type_decoder, }, 0xA302 => "CFAPattern", 0xA401 => {__TAG__ => "CustomRendered", 0 => "Normal process", 1 => "Custom process" }, 0xA402 => {__TAG__ => "ExposureMode", 0 => "Auto exposure", 1 => "Manual exposure", 2 => "Auto bracket" }, 0xA403 => {__TAG__ => "WhiteBalance", 0 => "Auto white balance", 1 => "Manual white balance" }, 0xA404 => "DigitalZoomRatio", 0xA405 => "FocalLengthIn35mmFilm", 0xA406 => {__TAG__ => "SceneCaptureType", 0 => "Standard", 1 => "Landscape", 2 => "Portrait", 3 => "Night Scene" }, 0xA407 => {__TAG__ => "GainControl", 0 => "None", 1 => "Low gain up", 2 => "High gain up", 3 => "Low gain down", 4 => "High gain down" }, 0xA408 => {__TAG__ => "Contrast", 0 => "Normal", 1 => "Soft", 2 => "Hard" }, 0xA409 => {__TAG__ => "Saturation", 0 => "Normal", 1 => "Low saturation", 2 => "High saturation" }, 0xA40A => {__TAG__ => "Sharpness", 0 => "Normal", 1 => "Soft", 2 => "Hard" }, 0xA40B => "DeviceSettingDescription", 0xA40C => {__TAG__ => "SubjectDistanceRange", 0 => "Unknown", 1 => "Macro", 2 => "Close view", 3 => "Distant view" }, 0xA420 => "ImageUniqueID", ); my %gps_tags = ( 0x0000 => 'GPSVersionID', 0x0001 => 'GPSLatitudeRef', 0x0002 => 'GPSLatitude', 0x0003 => 'GPSLongitudeRef', 0x0004 => 'GPSLongitude', 0x0005 => 'GPSAltitudeRef', 0x0006 => 'GPSAltitude', 0x0007 => 'GPSTimeStamp', 0x0008 => 'GPSSatellites', 0x0009 => 'GPSStatus', 0x000A => 'GPSMeasureMode', 0x000B => 'GPSDOP', 0x000C => 'GPSSpeedRef', 0x000D => 'GPSSpeed', 0x000E => 'GPSTrackRef', 0x000F => 'GPSTrack', 0x0010 => 'GPSImgDirectionRef', 0x0011 => 'GPSImgDirection', 0x0012 => 'GPSMapDatum', 0x0013 => 'GPSDestLatitudeRef', 0x0014 => 'GPSDestLatitude', 0x0015 => 'GPSDestLongitudeRef', 0x0016 => 'GPSDestLongitude', 0x0017 => 'GPSDestBearingRef', 0x0018 => 'GPSDestBearing', 0x0019 => 'GPSDestDistanceRef', 0x001A => 'GPSDestDistance', 0x001B => 'GPSProcessingMethod', 0x001C => 'GPSAreaInformation', 0x001D => 'GPSDateStamp', 0x001E => 'GPSDifferential', ); my %tiff_tags = ( 254 => { __TAG__ => "NewSubfileType", 1 => "ReducedResolution", 2 => "SinglePage", 4 => "TransparencyMask", }, 255 => { __TAG__ => "SubfileType", 1 => "FullResolution", 2 => "ReducedResolution", 3 => "SinglePage", }, 256 => "width", 257 => "height", 258 => "BitsPerSample", 259 => { __TAG__ => "Compression", 1 => "PackBytes", 2 => "CCITT Group3", 3 => "CCITT T4", 4 => "CCITT T6", 5 => "LZW", 6 => "JPEG", 7 => "JPEG DCT", 8 => "Deflate (Adobe)", 32766 => "NeXT 2-bit RLE", 32771 => "#1 w/ word alignment", 32773 => "PackBits (Macintosh RLE)", 32809 => "ThunderScan RLE", 32895 => "IT8 CT w/padding", 32896 => "IT8 Linework RLE", 32897 => "IT8 Monochrome picture", 32898 => "IT8 Binary line art", 32908 => "Pixar companded 10bit LZW", 32909 => "Pixar companded 11bit ZIP", 32946 => "Deflate", }, 262 => { __TAG__ => "PhotometricInterpretation", 0 => "WhiteIsZero", 1 => "BlackIsZero", 2 => "RGB", 3 => "RGB Palette", 4 => "Transparency Mask", 5 => "CMYK", 6 => "YCbCr", 8 => "CIELab", }, 263 => { __TAG__ => "Threshholding", 1 => "NoDithering", 2 => "OrderedDither", 3 => "Randomized", }, 266 => { __TAG__ => "FillOrder", 1 => "LowInHigh", 2 => "HighInLow", }, 269 => "DocumentName", 270 => "ImageDescription", 271 => "Make", 272 => "Model", 273 => "StripOffsets", 274 => { __TAG__ => "Orientation", 1 => "top_left", 2 => "top_right", 3 => "bot_right", 4 => "bot_left", 5 => "left_top", 6 => "right_top", 7 => "right_bot", 8 => "left_bot", }, 277 => "SamplesPerPixel", 278 => "RowsPerStrip", 279 => "StripByteCounts", 282 => "XResolution", 283 => "YResolution", 284 => {__TAG__ => "PlanarConfiguration", 1 => "Chunky", 2 => "Planar", }, 296 => {__TAG__ => "ResolutionUnit", 1 => "pixels", 2 => "dpi", 3 => "dpcm", }, 297 => "PageNumber", 301 => "TransferFunction", 305 => "Software", 306 => "DateTime", 315 => "Artist", 316 => "Host", 318 => "WhitePoint", 319 => "PrimaryChromaticities", 320 => "ColorMap", 513 => "JPEGInterchangeFormat", 514 => "JPEGInterchangeFormatLength", 529 => "YCbCrCoefficients", 530 => "YCbCrSubSampling", 531 => "YCbCrPositioning", 532 => "ReferenceBlackWhite", 33432 => "Copyright", 34665 => { __TAG__ => "ExifOffset", __SUBIFD__ => \%exif_tags, }, 34853 => { __TAG__ => "GPSInfo", __SUBIFD__ => \%gps_tags, }, ); sub new { my $class = shift; my $source = shift; if (!ref($source)) { local(*F); open(F, $source) || return; binmode(F); $source = \*F; } if (ref($source) ne "SCALAR") { # XXX should really only read the file on demand local($/); # slurp mode my $data = <$source>; $source = \$data; } my $self = bless { source => $source }, $class; for ($$source) { my $byte_order = substr($_, 0, 2); $self->{little_endian} = ($byte_order eq "II"); $self->{version} = $self->unpack("n", substr($_, 2, 2)); my $ifd = $self->unpack("N", substr($_, 4, 4)); while ($ifd) { push(@{$self->{ifd}}, $ifd); my($num_fields) = $self->unpack("x$ifd n", $_); my $substr_ifd = substr($_, $ifd + 2 + $num_fields*12, 4); last unless defined $substr_ifd; # bad TIFF header, eg: substr idx > length($substr_ifd) my $next_ifd = $self->unpack("N", $substr_ifd); # guard against (bug #26127) $next_ifd = 0 if $next_ifd > length($_); # guard against looping ifd (bug #26130) if ($next_ifd <= $ifd) { # bad TIFF header - would cause a loop or strange results last; } $ifd = $next_ifd; } } $self; } sub unpack { my $self = shift; my $template = shift; if ($self->{little_endian}) { $template =~ tr/nN/vV/; } #print "UNPACK $template\n"; CORE::unpack($template, $_[0]); } sub num_ifds { my $self = shift; scalar @{$self->{ifd}}; } sub ifd { my $self = shift; my $num = shift || 0; my @ifd; $self->add_fields($self->{ifd}[$num], \@ifd); } sub tagname { $tiff_tags{$_[1]} || sprintf "Tag-0x%04x",$_[1]; } sub exif_tagname { $tiff_tags{$_[1]} || $exif_tags{$_[1]} || sprintf "Tag-0x%04x",$_[1]; } sub add_fields { my($self, $offset, $ifds, $tags, $voff_plus) = @_; return unless $offset; # guard against finding the same offset twice (bug #29088) return if $self->{seen_offset}{$offset}++; $tags ||= \%tiff_tags; for (${$self->{source}}) { # alias as $_ last if $offset > length($_) - 2; # bad offset my $entries = $self->unpack("x$offset n", $_); my $max_entries = int((length($_) - $offset - 2) / 12); # print "ENTRIES $entries $max_entries\n"; if ($entries > $max_entries) { # Hmmm, something smells bad here... parsing garbage $entries = $max_entries; last; } FIELD: for my $i (0 .. $entries-1) { my $entry_offset = 2 + $offset + $i*12; my($tag, $type, $count, $voff) = $self->unpack("nnNN", substr($_, $entry_offset, 12)); #print STDERR "TAG $tag $type $count $voff\n"; if ($type == 0 || $type > @types) { # unknown type code might indicate that we are parsing garbage print STDERR "# Ignoring unknown type code $type\n"; next; } # extract type information my($tmpl, $vlen); ($type, $tmpl, $vlen) = @{$types[$type-1]}; die "Undefined type while parsing" unless $type; if ($count * $vlen <= 4) { $voff = $entry_offset + 8; } elsif ($voff + $count * $vlen > length($_)) { # offset points outside of string, corrupt entry ignore print STDERR "# ignoring offset pointer outside of string\n"; next; } else { $voff += $voff_plus || 0; } $tmpl =~ s/(\d+)$/$count*$1/e; my @v = $self->unpack("x$voff $tmpl", $_); if ($type =~ /^S(SHORT|LONG|RATIONAL)/) { my $max = 2 ** ($1 eq "SHORT" ? 15 : 31); $v[0] -= ($max * 2) if $v[0] >= $max; } my $val = (@v > 1) ? \@v : $v[0]; bless $val, "Image::TIFF::Rational" if $type =~ /^S?RATIONAL$/; if ($type eq 'ASCII' || $type eq 'UNDEFINED') { if ($val =~ /\0[^\0]+\z/) { # cut out the first "ASCII\0" and take the remaining text # (fix bug #29243 parsing of UserComment) # XXX TODO: this needs to handle UNICODE, too: $val =~ /\0([^\0]+)/; $val = '' . ($1 || ''); } else { # avoid things like "Foo\x00\x00\x00" by removing trailing nulls # this needs to handle UNICODE, too: $val =~ /^([^\0]*)/; $val = '' . ($1 || ''); } } $tag = $tags->{$tag} || $self->tagname($tag); if ($tag eq 'MakerNote') { my $maker = uc($self->{Make} || ''); $maker =~ /^([A-Z]+)/; $maker = $1 || ''; # "OLYMPUS ..." > "OLYMPUS" # if 'Panasonic' doesn't exist, try 'Panasonic DMC-FZ5' $maker = join " " => grep m/\S/ => $self->{Make}, $self->{Model} unless exists $makernotes{$maker}; if (exists $makernotes{$maker}) { my ($ifd_off, $tag_prefix, $sub) = @{$makernotes{$maker}}; #print STDERR "# Decoding Makernotes from $maker\n"; $self->{tag_prefix} = $tag_prefix; if ($ifd_off == -1 && length($val) >= 12) { # fuji kludge - http://www.butaman.ne.jp/~tsuruzoh/Computer/Digicams/exif-e.html#APP4 my $save_endian = $self->{little_endian}; $self->{little_endian} = 1; $ifd_off = $self->unpack("N", substr($val, 8, 4)); $self->add_fields($voff+$ifd_off, $ifds, $sub, $voff); $self->{little_endian} = $save_endian; } elsif ($ifd_off == -2) { # Nikon D70/D100 kludge -- word "Nikon" and 5 # bytes of data is tacked to the front of MakerNote; # all EXIF offsets are relative to MakerNote section my ($nikon_voff); $nikon_voff = 0; if (substr($val, 0, 5) eq 'Nikon') { $nikon_voff = $voff+10; } #print "IFD_OFF $ifd_off NIKON_VOFF $nikon_voff\n"; $self->add_fields($voff+18, $ifds, $sub, $nikon_voff); } else { $self->add_fields($voff+$ifd_off, $ifds, $sub) } delete $self->{tag_prefix}; next FIELD; } } if (ref($tag)) { die "Assert" unless ref($tag) eq "HASH"; if (my $sub = $tag->{__SUBIFD__}) { next if $val < 0 || $val > length($_); #print "SUBIFD $tag->{__TAG__} $val ", length($_), "\n"; $self->add_fields($val, $ifds, $sub); next FIELD; } if (my $sub = $tag->{__ARRAYOFFSET__}) { my $prefix; $prefix = $tag = $self->{tag_prefix} . '-' if $self->{tag_prefix}; for (my $i=0; $i < @$val; $i++) { if ( exists($sub->{$i}) ) { if ( ref($sub->{$i}) eq "HASH" && exists($sub->{$i}->{__TAG__}) ) { if ( exists($sub->{$i}->{$val->[$i]}) ) { push @$ifds, [ $prefix . $sub->{$i}->{__TAG__}, $type, $count, $sub->{$i}->{$val->[$i]} ]; } else { push @$ifds, [ $prefix . $sub->{$i}->{__TAG__}, $type, $count, "Unknown (" . $val->[$i] . ")" ]; } } else { push @$ifds, [ $prefix . $sub->{$i}, $type, $count, $val->[$i] ]; } } } next FIELD; } #hack for UNDEFINED values, they all have different #meanings depending on tag $val = &{$tag->{DECODER}}($self,$val) if defined($tag->{DECODER}); $val = $tag->{$val} if exists $tag->{$val}; $tag = $tag->{__TAG__}; } $tag = $self->{tag_prefix} . '-' . $tag if $self->{tag_prefix}; #if ( $val =~ m/ARRAY/ ) { $val = join(', ',@$val); } push @$ifds, [ $tag, $type, $count, $val ]; $self->{$tag} = $val if ($tag eq 'Make' or $tag eq 'Model'); } } $ifds; } sub components_configuration_decoder { my $self = shift; my $val = shift; my $rv = ""; my %v = ( 0 => undef, 1 => 'Y', 2 => 'Cb', 3 => 'Cr', 4 => 'R', 5 => 'G', 6 => 'B', ); return join ( '', map { $v{$_} if defined($v{$_}) } $self->unpack('c4',$val) ); } sub file_source_decoder { my $self = shift; my $val = shift; my %v = ( 3 => "(DSC) Digital Still Camera", ); $val = $self->unpack('c',$val); return $v{$val} if $v{$val}; "Other"; } sub scene_type_decoder { my $self = shift; my $val = shift; my %v = ( 1 => "Directly Photographed Image", ); $val = $self->unpack('c',$val); return $v{$val} if $v{$val}; "Other"; } package Image::TIFF::Rational; use overload '""' => \&as_string, '0+' => \&as_float, fallback => 1; sub new { my($class, $a, $b) = @_; bless [$a, $b], $class; } sub as_string { my $self = shift; #warn "@$self"; "$self->[0]/$self->[1]"; } sub as_float { my $self = shift; # We check here because some stupid cameras (Samsung Digimax 200) # use rationals with 0 denominator (found in thumbnail resolution spec). if ($self->[1]) { return $self->[0] / $self->[1]; } else { return $self->[0]; } } 1;
Upload Files
Cancel
Upload
Create New
Cancel
Create
Change Permissions
Cancel
Save
Change Date
Cancel
Save
Rename Item
Cancel
Save
Confirm Delete
Are you sure you want to delete the selected items?
Cancel
Delete