[16842] | 1 | #------------------------------------------------------------------------------
|
---|
| 2 | # File: CanonRaw.pm
|
---|
| 3 | #
|
---|
| 4 | # Description: Read Canon RAW (CRW) meta information
|
---|
| 5 | #
|
---|
| 6 | # Revisions: 11/25/2003 - P. Harvey Created
|
---|
| 7 | # 12/02/2003 - P. Harvey Completely reworked and figured out many
|
---|
| 8 | # more tags
|
---|
| 9 | #
|
---|
| 10 | # References: 1) http://www.cybercom.net/~dcoffin/dcraw/
|
---|
| 11 | # 2) http://www.wonderland.org/crw/
|
---|
| 12 | # 3) http://xyrion.org/ciff/CIFFspecV1R04.pdf
|
---|
[24107] | 13 | # 4) Dave Nicholson private communication (PowerShot S30)
|
---|
[16842] | 14 | #------------------------------------------------------------------------------
|
---|
| 15 |
|
---|
| 16 | package Image::ExifTool::CanonRaw;
|
---|
| 17 |
|
---|
| 18 | use strict;
|
---|
| 19 | use vars qw($VERSION $AUTOLOAD %crwTagFormat);
|
---|
[24107] | 20 | use Image::ExifTool qw(:DataAccess :Utils);
|
---|
[16842] | 21 | use Image::ExifTool::Exif;
|
---|
| 22 | use Image::ExifTool::Canon;
|
---|
| 23 |
|
---|
[34921] | 24 | $VERSION = '1.58';
|
---|
[16842] | 25 |
|
---|
| 26 | sub WriteCRW($$);
|
---|
| 27 | sub ProcessCanonRaw($$$);
|
---|
| 28 | sub WriteCanonRaw($$$);
|
---|
| 29 | sub CheckCanonRaw($$$);
|
---|
| 30 | sub InitMakerNotes($);
|
---|
| 31 | sub SaveMakerNotes($);
|
---|
| 32 | sub BuildMakerNotes($$$$$$);
|
---|
| 33 |
|
---|
| 34 | # formats for CRW tag types (($tag >> 8) & 0x38)
|
---|
| 35 | # Note: don't define format for undefined types
|
---|
| 36 | %crwTagFormat = (
|
---|
| 37 | 0x00 => 'int8u',
|
---|
| 38 | 0x08 => 'string',
|
---|
| 39 | 0x10 => 'int16u',
|
---|
| 40 | 0x18 => 'int32u',
|
---|
| 41 | # 0x20 => 'undef',
|
---|
| 42 | # 0x28 => 'undef',
|
---|
| 43 | # 0x30 => 'undef',
|
---|
| 44 | );
|
---|
| 45 |
|
---|
| 46 | # Canon raw file tag table
|
---|
| 47 | # Note: Tag ID's have upper 2 bits set to zero, since these 2 bits
|
---|
| 48 | # just specify the location of the information
|
---|
| 49 | %Image::ExifTool::CanonRaw::Main = (
|
---|
| 50 | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
---|
| 51 | PROCESS_PROC => \&ProcessCanonRaw,
|
---|
| 52 | WRITE_PROC => \&WriteCanonRaw,
|
---|
| 53 | CHECK_PROC => \&CheckCanonRaw,
|
---|
| 54 | WRITABLE => 1,
|
---|
| 55 | 0x0000 => { Name => 'NullRecord', Writable => 'undef' }, #3
|
---|
| 56 | 0x0001 => { #3
|
---|
| 57 | Name => 'FreeBytes',
|
---|
| 58 | Format => 'undef',
|
---|
| 59 | Binary => 1,
|
---|
| 60 | },
|
---|
| 61 | 0x0032 => { Name => 'CanonColorInfo1', Writable => 0 },
|
---|
| 62 | 0x0805 => [
|
---|
| 63 | # this tag is found in more than one directory...
|
---|
| 64 | {
|
---|
| 65 | Condition => '$self->{DIR_NAME} eq "ImageDescription"',
|
---|
| 66 | Name => 'CanonFileDescription',
|
---|
| 67 | Writable => 'string[32]',
|
---|
| 68 | },
|
---|
| 69 | {
|
---|
| 70 | Name => 'UserComment',
|
---|
| 71 | Writable => 'string[256]',
|
---|
| 72 | },
|
---|
| 73 | ],
|
---|
| 74 | 0x080a => {
|
---|
| 75 | Name => 'CanonRawMakeModel',
|
---|
| 76 | Writable => 0,
|
---|
[34921] | 77 | SubDirectory => { TagTable => 'Image::ExifTool::CanonRaw::MakeModel' },
|
---|
[16842] | 78 | },
|
---|
| 79 | 0x080b => { Name => 'CanonFirmwareVersion', Writable => 'string[32]' },
|
---|
| 80 | 0x080c => { Name => 'ComponentVersion', Writable => 'string' }, #3
|
---|
| 81 | 0x080d => { Name => 'ROMOperationMode', Writable => 'string[8]' }, #3
|
---|
| 82 | 0x0810 => { Name => 'OwnerName', Writable => 'string[32]' },
|
---|
| 83 | 0x0815 => { Name => 'CanonImageType', Writable => 'string[32]' },
|
---|
| 84 | 0x0816 => { Name => 'OriginalFileName', Writable => 'string[32]' },
|
---|
| 85 | 0x0817 => { Name => 'ThumbnailFileName', Writable => 'string[32]' },
|
---|
| 86 | 0x100a => { #3
|
---|
| 87 | Name => 'TargetImageType',
|
---|
| 88 | Writable => 'int16u',
|
---|
| 89 | PrintConv => {
|
---|
| 90 | 0 => 'Real-world Subject',
|
---|
| 91 | 1 => 'Written Document',
|
---|
| 92 | },
|
---|
| 93 | },
|
---|
| 94 | 0x1010 => { #3
|
---|
| 95 | Name => 'ShutterReleaseMethod',
|
---|
| 96 | Writable => 'int16u',
|
---|
| 97 | PrintConv => {
|
---|
| 98 | 0 => 'Single Shot',
|
---|
| 99 | 2 => 'Continuous Shooting',
|
---|
| 100 | },
|
---|
| 101 | },
|
---|
| 102 | 0x1011 => { #3
|
---|
| 103 | Name => 'ShutterReleaseTiming',
|
---|
| 104 | Writable => 'int16u',
|
---|
| 105 | PrintConv => {
|
---|
| 106 | 0 => 'Priority on shutter',
|
---|
| 107 | 1 => 'Priority on focus',
|
---|
| 108 | },
|
---|
| 109 | },
|
---|
| 110 | 0x1016 => { Name => 'ReleaseSetting', Writable => 'int16u' }, #3
|
---|
| 111 | 0x101c => { Name => 'BaseISO', Writable => 'int16u' }, #3
|
---|
| 112 | 0x1028=> { #PH
|
---|
| 113 | Name => 'CanonFlashInfo',
|
---|
| 114 | Writable => 'int16u',
|
---|
| 115 | Count => 4,
|
---|
| 116 | Unknown => 1,
|
---|
| 117 | },
|
---|
| 118 | 0x1029 => {
|
---|
| 119 | Name => 'CanonFocalLength',
|
---|
| 120 | Writable => 0,
|
---|
[34921] | 121 | SubDirectory => { TagTable => 'Image::ExifTool::Canon::FocalLength' },
|
---|
[16842] | 122 | },
|
---|
| 123 | 0x102a => {
|
---|
| 124 | Name => 'CanonShotInfo',
|
---|
| 125 | Writable => 0,
|
---|
[34921] | 126 | SubDirectory => { TagTable => 'Image::ExifTool::Canon::ShotInfo' },
|
---|
[16842] | 127 | },
|
---|
[24107] | 128 | 0x102c => {
|
---|
| 129 | Name => 'CanonColorInfo2',
|
---|
| 130 | Writable => 0,
|
---|
| 131 | # for the S30, the following information has been decoded: (ref 4)
|
---|
| 132 | # offset 66: int32u - shutter half press time in ms
|
---|
| 133 | # offset 70: int32u - image capture time in ms
|
---|
| 134 | # offset 74: int16u - custom white balance flag (0=Off, 512=On)
|
---|
| 135 | },
|
---|
[16842] | 136 | 0x102d => {
|
---|
| 137 | Name => 'CanonCameraSettings',
|
---|
| 138 | Writable => 0,
|
---|
[34921] | 139 | SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraSettings' },
|
---|
[16842] | 140 | },
|
---|
[24107] | 141 | 0x1030 => { #4
|
---|
| 142 | Name => 'WhiteSample',
|
---|
| 143 | Writable => 0,
|
---|
| 144 | SubDirectory => {
|
---|
| 145 | Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)',
|
---|
| 146 | TagTable => 'Image::ExifTool::CanonRaw::WhiteSample',
|
---|
| 147 | },
|
---|
| 148 | },
|
---|
[16842] | 149 | 0x1031 => {
|
---|
| 150 | Name => 'SensorInfo',
|
---|
| 151 | Writable => 0,
|
---|
[34921] | 152 | SubDirectory => { TagTable => 'Image::ExifTool::Canon::SensorInfo' },
|
---|
[16842] | 153 | },
|
---|
| 154 | # this tag has only be verified for the 10D in CRW files, but the D30 and D60
|
---|
| 155 | # also produce CRW images and have CustomFunction information in their JPEG's
|
---|
| 156 | 0x1033 => [
|
---|
| 157 | {
|
---|
| 158 | Name => 'CustomFunctions10D',
|
---|
[24107] | 159 | Condition => '$self->{Model} =~ /EOS 10D/',
|
---|
[16842] | 160 | SubDirectory => {
|
---|
| 161 | Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)',
|
---|
| 162 | TagTable => 'Image::ExifTool::CanonCustom::Functions10D',
|
---|
| 163 | },
|
---|
| 164 | },
|
---|
| 165 | {
|
---|
| 166 | Name => 'CustomFunctionsD30',
|
---|
[24107] | 167 | Condition => '$self->{Model} =~ /EOS D30\b/',
|
---|
[16842] | 168 | SubDirectory => {
|
---|
| 169 | Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)',
|
---|
| 170 | TagTable => 'Image::ExifTool::CanonCustom::FunctionsD30',
|
---|
| 171 | },
|
---|
| 172 | },
|
---|
| 173 | {
|
---|
| 174 | Name => 'CustomFunctionsD60',
|
---|
[24107] | 175 | Condition => '$self->{Model} =~ /EOS D60\b/',
|
---|
[16842] | 176 | SubDirectory => {
|
---|
| 177 | # the stored size in the D60 apparently doesn't include the size word:
|
---|
| 178 | Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size-2,$size)',
|
---|
| 179 | # (D60 custom functions are basically the same as D30)
|
---|
| 180 | TagTable => 'Image::ExifTool::CanonCustom::FunctionsD30',
|
---|
| 181 | },
|
---|
| 182 | },
|
---|
| 183 | {
|
---|
| 184 | Name => 'CustomFunctionsUnknown',
|
---|
| 185 | SubDirectory => {
|
---|
| 186 | Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)',
|
---|
| 187 | TagTable => 'Image::ExifTool::CanonCustom::FuncsUnknown',
|
---|
| 188 | },
|
---|
| 189 | },
|
---|
| 190 | ],
|
---|
| 191 | 0x1038 => {
|
---|
| 192 | Name => 'CanonAFInfo',
|
---|
| 193 | Writable => 0,
|
---|
[34921] | 194 | SubDirectory => { TagTable => 'Image::ExifTool::Canon::AFInfo' },
|
---|
[16842] | 195 | },
|
---|
| 196 | 0x1093 => {
|
---|
| 197 | Name => 'CanonFileInfo',
|
---|
| 198 | SubDirectory => {
|
---|
| 199 | Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)',
|
---|
| 200 | TagTable => 'Image::ExifTool::Canon::FileInfo',
|
---|
| 201 | },
|
---|
| 202 | },
|
---|
| 203 | 0x10a9 => {
|
---|
| 204 | Name => 'ColorBalance',
|
---|
| 205 | Writable => 0,
|
---|
[34921] | 206 | SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorBalance' },
|
---|
[16842] | 207 | },
|
---|
| 208 | 0x10b5 => { #PH
|
---|
| 209 | Name => 'RawJpgInfo',
|
---|
| 210 | SubDirectory => {
|
---|
| 211 | Validate => 'Image::ExifTool::Canon::Validate($dirData,$subdirStart,$size)',
|
---|
| 212 | TagTable => 'Image::ExifTool::CanonRaw::RawJpgInfo',
|
---|
| 213 | },
|
---|
| 214 | },
|
---|
| 215 | 0x10ae => {
|
---|
| 216 | Name => 'ColorTemperature',
|
---|
| 217 | Writable => 'int16u',
|
---|
| 218 | },
|
---|
| 219 | 0x10b4 => {
|
---|
| 220 | Name => 'ColorSpace',
|
---|
| 221 | Writable => 'int16u',
|
---|
| 222 | PrintConv => {
|
---|
| 223 | 1 => 'sRGB',
|
---|
| 224 | 2 => 'Adobe RGB',
|
---|
| 225 | 0xffff => 'Uncalibrated',
|
---|
| 226 | },
|
---|
| 227 | },
|
---|
| 228 | 0x1803 => { #3
|
---|
| 229 | Name => 'ImageFormat',
|
---|
| 230 | Writable => 0,
|
---|
[34921] | 231 | SubDirectory => { TagTable => 'Image::ExifTool::CanonRaw::ImageFormat' },
|
---|
[16842] | 232 | },
|
---|
| 233 | 0x1804 => { Name => 'RecordID', Writable => 'int32u' }, #3
|
---|
| 234 | 0x1806 => { #3
|
---|
| 235 | Name => 'SelfTimerTime',
|
---|
| 236 | Writable => 'int32u',
|
---|
| 237 | ValueConv => '$val / 1000',
|
---|
| 238 | ValueConvInv => '$val * 1000',
|
---|
[24107] | 239 | PrintConv => '"$val s"',
|
---|
| 240 | PrintConvInv => '$val=~s/\s*s.*//;$val',
|
---|
[16842] | 241 | },
|
---|
| 242 | 0x1807 => {
|
---|
| 243 | Name => 'TargetDistanceSetting',
|
---|
| 244 | Format => 'float',
|
---|
| 245 | PrintConv => '"$val mm"',
|
---|
| 246 | PrintConvInv => '$val=~s/\s*mm$//;$val',
|
---|
| 247 | },
|
---|
[24107] | 248 | 0x180b => [
|
---|
| 249 | {
|
---|
| 250 | # D30
|
---|
| 251 | Name => 'SerialNumber',
|
---|
| 252 | Condition => '$$self{Model} =~ /EOS D30\b/',
|
---|
| 253 | Writable => 'int32u',
|
---|
| 254 | PrintConv => 'sprintf("%x-%.5d",$val>>16,$val&0xffff)',
|
---|
| 255 | PrintConvInv => '$val=~/(.*)-(\d+)/ ? (hex($1)<<16)+$2 : undef',
|
---|
| 256 | },
|
---|
| 257 | {
|
---|
| 258 | # all EOS models (D30, 10D, 300D)
|
---|
| 259 | Name => 'SerialNumber',
|
---|
| 260 | Condition => '$$self{Model} =~ /EOS/',
|
---|
| 261 | Writable => 'int32u',
|
---|
| 262 | PrintConv => 'sprintf("%.10d",$val)',
|
---|
| 263 | PrintConvInv => '$val',
|
---|
| 264 | },
|
---|
| 265 | {
|
---|
| 266 | # this is not SerialNumber for PowerShot models (but what is it?) - PH
|
---|
| 267 | Name => 'UnknownNumber',
|
---|
| 268 | Unknown => 1,
|
---|
| 269 | },
|
---|
| 270 | ],
|
---|
[16842] | 271 | 0x180e => {
|
---|
| 272 | Name => 'TimeStamp',
|
---|
| 273 | Writable => 0,
|
---|
| 274 | SubDirectory => {
|
---|
| 275 | TagTable => 'Image::ExifTool::CanonRaw::TimeStamp',
|
---|
| 276 | },
|
---|
| 277 | },
|
---|
| 278 | 0x1810 => {
|
---|
| 279 | Name => 'ImageInfo',
|
---|
| 280 | Writable => 0,
|
---|
| 281 | SubDirectory => {
|
---|
| 282 | TagTable => 'Image::ExifTool::CanonRaw::ImageInfo',
|
---|
| 283 | },
|
---|
| 284 | },
|
---|
| 285 | 0x1813 => { #3
|
---|
| 286 | Name => 'FlashInfo',
|
---|
| 287 | Writable => 0,
|
---|
| 288 | SubDirectory => {
|
---|
| 289 | TagTable => 'Image::ExifTool::CanonRaw::FlashInfo',
|
---|
| 290 | },
|
---|
| 291 | },
|
---|
| 292 | 0x1814 => { #3
|
---|
| 293 | Name => 'MeasuredEV',
|
---|
| 294 | Notes => q{
|
---|
[24107] | 295 | this is the Canon name for what could better be called MeasuredLV, and
|
---|
| 296 | should be close to the calculated LightValue for a proper exposure with most
|
---|
| 297 | models
|
---|
[16842] | 298 | },
|
---|
| 299 | Format => 'float',
|
---|
[24107] | 300 | ValueConv => '$val + 5',
|
---|
| 301 | ValueConvInv => '$val - 5',
|
---|
[16842] | 302 | },
|
---|
| 303 | 0x1817 => {
|
---|
| 304 | Name => 'FileNumber',
|
---|
| 305 | Writable => 'int32u',
|
---|
| 306 | Groups => { 2 => 'Image' },
|
---|
| 307 | PrintConv => '$_=$val;s/(\d+)(\d{4})/$1-$2/;$_',
|
---|
| 308 | PrintConvInv => '$_=$val;s/-//;$_',
|
---|
| 309 | },
|
---|
| 310 | 0x1818 => { #3
|
---|
| 311 | Name => 'ExposureInfo',
|
---|
[24107] | 312 | Groups => { 1 => 'CIFF' }, # (only so CIFF shows up in group lists)
|
---|
[16842] | 313 | Writable => 0,
|
---|
[34921] | 314 | SubDirectory => { TagTable => 'Image::ExifTool::CanonRaw::ExposureInfo' },
|
---|
[16842] | 315 | },
|
---|
| 316 | 0x1834 => { #PH
|
---|
| 317 | Name => 'CanonModelID',
|
---|
| 318 | Writable => 'int32u',
|
---|
| 319 | PrintHex => 1,
|
---|
| 320 | Notes => q{
|
---|
| 321 | this is the complete list of model ID numbers, but note that many of these
|
---|
| 322 | models do not produce CRW images
|
---|
| 323 | },
|
---|
| 324 | SeparateTable => 'Canon CanonModelID',
|
---|
| 325 | PrintConv => \%Image::ExifTool::Canon::canonModelID,
|
---|
| 326 | },
|
---|
| 327 | 0x1835 => {
|
---|
| 328 | Name => 'DecoderTable',
|
---|
| 329 | Writable => 0,
|
---|
[34921] | 330 | SubDirectory => { TagTable => 'Image::ExifTool::CanonRaw::DecoderTable' },
|
---|
[16842] | 331 | },
|
---|
| 332 | 0x183b => { #PH
|
---|
| 333 | # display format for serial number
|
---|
| 334 | Name => 'SerialNumberFormat',
|
---|
| 335 | Writable => 'int32u',
|
---|
| 336 | PrintHex => 1,
|
---|
| 337 | PrintConv => {
|
---|
| 338 | 0x90000000 => 'Format 1',
|
---|
| 339 | 0xa0000000 => 'Format 2',
|
---|
| 340 | },
|
---|
| 341 | },
|
---|
| 342 | 0x2005 => {
|
---|
| 343 | Name => 'RawData',
|
---|
| 344 | Writable => 0,
|
---|
| 345 | Binary => 1,
|
---|
| 346 | },
|
---|
| 347 | 0x2007 => {
|
---|
| 348 | Name => 'JpgFromRaw',
|
---|
[34921] | 349 | Groups => { 2 => 'Preview' },
|
---|
[16842] | 350 | Writable => 'resize', # 'resize' allows this value to change size
|
---|
| 351 | Permanent => 0,
|
---|
[24107] | 352 | RawConv => '$self->ValidateImage(\$val,$tag)',
|
---|
[16842] | 353 | },
|
---|
| 354 | 0x2008 => {
|
---|
| 355 | Name => 'ThumbnailImage',
|
---|
[34921] | 356 | Groups => { 2 => 'Preview' },
|
---|
[16842] | 357 | Writable => 'resize', # 'resize' allows this value to change size
|
---|
| 358 | WriteCheck => '$self->CheckImage(\$val)',
|
---|
| 359 | Permanent => 0,
|
---|
[24107] | 360 | RawConv => '$self->ValidateImage(\$val,$tag)',
|
---|
[16842] | 361 | },
|
---|
| 362 | # the following entries are subdirectories
|
---|
| 363 | # (any 0x28 and 0x30 tag types are handled automatically by the decoding logic)
|
---|
| 364 | 0x2804 => {
|
---|
| 365 | Name => 'ImageDescription',
|
---|
| 366 | SubDirectory => { },
|
---|
| 367 | Writable => 0,
|
---|
| 368 | },
|
---|
| 369 | 0x2807 => { #3
|
---|
| 370 | Name => 'CameraObject',
|
---|
| 371 | SubDirectory => { },
|
---|
| 372 | Writable => 0,
|
---|
| 373 | },
|
---|
| 374 | 0x3002 => { #3
|
---|
| 375 | Name => 'ShootingRecord',
|
---|
| 376 | SubDirectory => { },
|
---|
| 377 | Writable => 0,
|
---|
| 378 | },
|
---|
| 379 | 0x3003 => { #3
|
---|
| 380 | Name => 'MeasuredInfo',
|
---|
| 381 | SubDirectory => { },
|
---|
| 382 | Writable => 0,
|
---|
| 383 | },
|
---|
| 384 | 0x3004 => { #3
|
---|
| 385 | Name => 'CameraSpecification',
|
---|
| 386 | SubDirectory => { },
|
---|
| 387 | Writable => 0,
|
---|
| 388 | },
|
---|
| 389 | 0x300a => { #3
|
---|
| 390 | Name => 'ImageProps',
|
---|
| 391 | SubDirectory => { },
|
---|
| 392 | Writable => 0,
|
---|
| 393 | },
|
---|
| 394 | 0x300b => {
|
---|
| 395 | Name => 'ExifInformation',
|
---|
| 396 | SubDirectory => { },
|
---|
| 397 | Writable => 0,
|
---|
| 398 | },
|
---|
| 399 | );
|
---|
| 400 |
|
---|
| 401 | # Canon binary data blocks
|
---|
| 402 | %Image::ExifTool::CanonRaw::MakeModel = (
|
---|
| 403 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
| 404 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
| 405 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
| 406 | DATAMEMBER => [ 0, 6 ], # indices of data members to extract when writing
|
---|
| 407 | WRITABLE => 1,
|
---|
| 408 | FORMAT => 'string',
|
---|
| 409 | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
---|
| 410 | # (can't specify a first entry because this isn't
|
---|
| 411 | # a simple binary table with fixed offsets)
|
---|
| 412 | 0 => {
|
---|
| 413 | Name => 'Make',
|
---|
| 414 | Format => 'string[6]', # "Canon\0"
|
---|
[24107] | 415 | DataMember => 'Make',
|
---|
| 416 | RawConv => '$self->{Make} = $val',
|
---|
[16842] | 417 | },
|
---|
| 418 | 6 => {
|
---|
| 419 | Name => 'Model',
|
---|
[24107] | 420 | Format => 'string', # no size = to the end of the data
|
---|
[16842] | 421 | Description => 'Camera Model Name',
|
---|
[24107] | 422 | DataMember => 'Model',
|
---|
| 423 | RawConv => '$self->{Model} = $val',
|
---|
[16842] | 424 | },
|
---|
| 425 | );
|
---|
| 426 |
|
---|
| 427 | %Image::ExifTool::CanonRaw::TimeStamp = (
|
---|
| 428 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
| 429 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
| 430 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
| 431 | WRITABLE => 1,
|
---|
| 432 | FORMAT => 'int32u',
|
---|
| 433 | FIRST_ENTRY => 0,
|
---|
| 434 | GROUPS => { 0 => 'MakerNotes', 2 => 'Time' },
|
---|
| 435 | 0 => {
|
---|
| 436 | Name => 'DateTimeOriginal',
|
---|
| 437 | Description => 'Date/Time Original',
|
---|
| 438 | Shift => 'Time',
|
---|
| 439 | ValueConv => 'ConvertUnixTime($val)',
|
---|
| 440 | ValueConvInv => 'GetUnixTime($val)',
|
---|
| 441 | PrintConv => '$self->ConvertDateTime($val)',
|
---|
[24107] | 442 | PrintConvInv => '$self->InverseDateTime($val)',
|
---|
[16842] | 443 | },
|
---|
| 444 | 1 => { #3
|
---|
| 445 | Name => 'TimeZoneCode',
|
---|
| 446 | Format => 'int32s',
|
---|
| 447 | ValueConv => '$val / 3600',
|
---|
| 448 | ValueConvInv => '$val * 3600',
|
---|
| 449 | },
|
---|
| 450 | 2 => { #3
|
---|
| 451 | Name => 'TimeZoneInfo',
|
---|
| 452 | Notes => 'set to 0x80000000 if TimeZoneCode is valid',
|
---|
| 453 | },
|
---|
| 454 | );
|
---|
| 455 |
|
---|
| 456 | %Image::ExifTool::CanonRaw::ImageFormat = (
|
---|
| 457 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
| 458 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
| 459 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
| 460 | WRITABLE => 1,
|
---|
| 461 | FORMAT => 'int32u',
|
---|
| 462 | FIRST_ENTRY => 0,
|
---|
| 463 | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
---|
| 464 | 0 => {
|
---|
| 465 | Name => 'FileFormat',
|
---|
| 466 | Flags => 'PrintHex',
|
---|
| 467 | PrintConv => {
|
---|
| 468 | 0x00010000 => 'JPEG (lossy)',
|
---|
| 469 | 0x00010002 => 'JPEG (non-quantization)',
|
---|
| 470 | 0x00010003 => 'JPEG (lossy/non-quantization toggled)',
|
---|
| 471 | 0x00020001 => 'CRW',
|
---|
| 472 | },
|
---|
| 473 | },
|
---|
| 474 | 1 => {
|
---|
| 475 | Name => 'TargetCompressionRatio',
|
---|
| 476 | Format => 'float',
|
---|
| 477 | },
|
---|
| 478 | );
|
---|
| 479 |
|
---|
| 480 | %Image::ExifTool::CanonRaw::RawJpgInfo = (
|
---|
| 481 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
| 482 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
| 483 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
| 484 | WRITABLE => 1,
|
---|
| 485 | FORMAT => 'int16u',
|
---|
| 486 | FIRST_ENTRY => 1,
|
---|
| 487 | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
---|
| 488 | # 0 => 'RawJpgInfoSize',
|
---|
| 489 | 1 => { #PH
|
---|
| 490 | Name => 'RawJpgQuality',
|
---|
| 491 | PrintConv => {
|
---|
| 492 | 1 => 'Economy',
|
---|
| 493 | 2 => 'Normal',
|
---|
| 494 | 3 => 'Fine',
|
---|
| 495 | 5 => 'Superfine',
|
---|
| 496 | },
|
---|
| 497 | },
|
---|
| 498 | 2 => { #PH
|
---|
| 499 | Name => 'RawJpgSize',
|
---|
| 500 | PrintConv => {
|
---|
| 501 | 0 => 'Large',
|
---|
| 502 | 1 => 'Medium',
|
---|
| 503 | 2 => 'Small',
|
---|
| 504 | },
|
---|
| 505 | },
|
---|
| 506 | 3 => 'RawJpgWidth', #PH
|
---|
| 507 | 4 => 'RawJpgHeight', #PH
|
---|
| 508 | );
|
---|
| 509 |
|
---|
| 510 | %Image::ExifTool::CanonRaw::FlashInfo = (
|
---|
| 511 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
| 512 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
| 513 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
| 514 | WRITABLE => 1,
|
---|
| 515 | FORMAT => 'float',
|
---|
| 516 | FIRST_ENTRY => 0,
|
---|
| 517 | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
---|
| 518 | 0 => 'FlashGuideNumber',
|
---|
| 519 | 1 => 'FlashThreshold',
|
---|
| 520 | );
|
---|
| 521 |
|
---|
| 522 | %Image::ExifTool::CanonRaw::ExposureInfo = (
|
---|
| 523 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
| 524 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
| 525 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
| 526 | WRITABLE => 1,
|
---|
| 527 | FORMAT => 'float',
|
---|
| 528 | FIRST_ENTRY => 0,
|
---|
| 529 | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
---|
| 530 | 0 => 'ExposureCompensation',
|
---|
[24107] | 531 | 1 => {
|
---|
| 532 | Name => 'ShutterSpeedValue',
|
---|
| 533 | ValueConv => 'abs($val)<100 ? 1/(2**$val) : 0',
|
---|
| 534 | ValueConvInv => '$val>0 ? -log($val)/log(2) : -100',
|
---|
| 535 | PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
|
---|
| 536 | PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
|
---|
| 537 | },
|
---|
| 538 | 2 => {
|
---|
| 539 | Name => 'ApertureValue',
|
---|
| 540 | ValueConv => '2 ** ($val / 2)',
|
---|
| 541 | ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0',
|
---|
| 542 | PrintConv => 'sprintf("%.1f",$val)',
|
---|
| 543 | PrintConvInv => '$val',
|
---|
| 544 | },
|
---|
[16842] | 545 | );
|
---|
| 546 |
|
---|
| 547 | %Image::ExifTool::CanonRaw::ImageInfo = (
|
---|
| 548 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
| 549 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
| 550 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
| 551 | FORMAT => 'int32u',
|
---|
[24107] | 552 | FIRST_ENTRY => 0,
|
---|
[16842] | 553 | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
---|
| 554 | # Note: Don't make these writable (except rotation) because it confuses
|
---|
| 555 | # Canon decoding software if the are changed
|
---|
| 556 | 0 => 'ImageWidth', #3
|
---|
| 557 | 1 => 'ImageHeight', #3
|
---|
| 558 | 2 => { #3
|
---|
| 559 | Name => 'PixelAspectRatio',
|
---|
| 560 | Format => 'float',
|
---|
| 561 | },
|
---|
| 562 | 3 => {
|
---|
| 563 | Name => 'Rotation',
|
---|
| 564 | Format => 'int32s',
|
---|
| 565 | Writable => 'int32s',
|
---|
| 566 | },
|
---|
| 567 | 4 => 'ComponentBitDepth', #3
|
---|
| 568 | 5 => 'ColorBitDepth', #3
|
---|
| 569 | 6 => 'ColorBW', #3
|
---|
| 570 | );
|
---|
| 571 |
|
---|
[24107] | 572 | # ref 4
|
---|
| 573 | %Image::ExifTool::CanonRaw::DecoderTable = (
|
---|
| 574 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
| 575 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
| 576 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
| 577 | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
---|
| 578 | FORMAT => 'int32u',
|
---|
| 579 | FIRST_ENTRY => 0,
|
---|
| 580 | 0 => 'DecoderTableNumber',
|
---|
| 581 | 2 => 'CompressedDataOffset',
|
---|
| 582 | 3 => 'CompressedDataLength',
|
---|
| 583 | );
|
---|
| 584 |
|
---|
| 585 | # ref 1/4
|
---|
| 586 | %Image::ExifTool::CanonRaw::WhiteSample = (
|
---|
| 587 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
| 588 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
| 589 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
| 590 | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
---|
| 591 | FORMAT => 'int16u',
|
---|
| 592 | FIRST_ENTRY => 1,
|
---|
| 593 | 1 => 'WhiteSampleWidth',
|
---|
| 594 | 2 => 'WhiteSampleHeight',
|
---|
| 595 | 3 => 'WhiteSampleLeftBorder',
|
---|
| 596 | 4 => 'WhiteSampleTopBorder',
|
---|
| 597 | 5 => 'WhiteSampleBits',
|
---|
| 598 | # this is followed by the encrypted white sample values (ref 1)
|
---|
| 599 | );
|
---|
| 600 |
|
---|
[16842] | 601 | #------------------------------------------------------------------------------
|
---|
| 602 | # AutoLoad our writer routines when necessary
|
---|
| 603 | #
|
---|
| 604 | sub AUTOLOAD
|
---|
| 605 | {
|
---|
| 606 | return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_);
|
---|
| 607 | }
|
---|
| 608 |
|
---|
| 609 | #------------------------------------------------------------------------------
|
---|
| 610 | # Process Raw file directory
|
---|
| 611 | # Inputs: 0) ExifTool object reference
|
---|
| 612 | # 1) directory information reference, 2) tag table reference
|
---|
| 613 | # Returns: 1 on success
|
---|
| 614 | sub ProcessCanonRaw($$$)
|
---|
| 615 | {
|
---|
[34921] | 616 | my ($et, $dirInfo, $rawTagTable) = @_;
|
---|
[16842] | 617 | my $blockStart = $$dirInfo{DirStart};
|
---|
| 618 | my $blockSize = $$dirInfo{DirLen};
|
---|
| 619 | my $raf = $$dirInfo{RAF} or return 0;
|
---|
| 620 | my $buff;
|
---|
[34921] | 621 | my $verbose = $et->Options('Verbose');
|
---|
| 622 | my $buildMakerNotes = $et->Options('MakerNotes');
|
---|
[16842] | 623 |
|
---|
| 624 | # 4 bytes at end of block give directory position within block
|
---|
| 625 | $raf->Seek($blockStart+$blockSize-4, 0) or return 0;
|
---|
| 626 | $raf->Read($buff, 4) == 4 or return 0;
|
---|
| 627 | my $dirOffset = Get32u(\$buff,0) + $blockStart;
|
---|
| 628 | $raf->Seek($dirOffset, 0) or return 0;
|
---|
| 629 | $raf->Read($buff, 2) == 2 or return 0;
|
---|
| 630 | my $entries = Get16u(\$buff,0); # get number of entries in directory
|
---|
| 631 | # read the directory (10 bytes per entry)
|
---|
| 632 | $raf->Read($buff, 10 * $entries) == 10 * $entries or return 0;
|
---|
| 633 |
|
---|
[34921] | 634 | $verbose and $et->VerboseDir('CIFF', $entries);
|
---|
[16842] | 635 | my $index;
|
---|
| 636 | for ($index=0; $index<$entries; ++$index) {
|
---|
| 637 | my $pt = 10 * $index;
|
---|
| 638 | my $tag = Get16u(\$buff, $pt);
|
---|
| 639 | my $size = Get32u(\$buff, $pt+2);
|
---|
| 640 | my $valuePtr = Get32u(\$buff, $pt+6);
|
---|
| 641 | my $ptr = $valuePtr + $blockStart; # all pointers relative to block start
|
---|
| 642 | if ($tag & 0x8000) {
|
---|
[34921] | 643 | $et->Warn('Bad CRW directory entry');
|
---|
[16842] | 644 | return 1;
|
---|
| 645 | }
|
---|
| 646 | my $tagID = $tag & 0x3fff; # get tag ID
|
---|
| 647 | my $tagType = ($tag >> 8) & 0x38; # get tag type
|
---|
| 648 | my $valueInDir = ($tag & 0x4000); # flag for value in directory
|
---|
[34921] | 649 | my $tagInfo = $et->GetTagInfo($rawTagTable, $tagID);
|
---|
[16842] | 650 | if (($tagType==0x28 or $tagType==0x30) and not $valueInDir) {
|
---|
| 651 | # this type of tag specifies a raw subdirectory
|
---|
| 652 | my $name;
|
---|
| 653 | $tagInfo and $name = $$tagInfo{Name};
|
---|
| 654 | $name or $name = sprintf("CanonRaw_0x%.4x", $tag);
|
---|
| 655 | my %subdirInfo = (
|
---|
| 656 | DirName => $name,
|
---|
| 657 | DataLen => 0,
|
---|
| 658 | DirStart => $ptr,
|
---|
| 659 | DirLen => $size,
|
---|
| 660 | Nesting => $$dirInfo{Nesting} + 1,
|
---|
| 661 | RAF => $raf,
|
---|
| 662 | Parent => $$dirInfo{DirName},
|
---|
| 663 | );
|
---|
| 664 | if ($verbose) {
|
---|
| 665 | my $fakeInfo = { Name => $name, SubDirectory => { } };
|
---|
[34921] | 666 | $et->VerboseInfo($tagID, $fakeInfo,
|
---|
[16842] | 667 | 'Index' => $index,
|
---|
| 668 | 'Size' => $size,
|
---|
| 669 | 'Start' => $ptr,
|
---|
| 670 | );
|
---|
| 671 | }
|
---|
[34921] | 672 | $et->ProcessDirectory(\%subdirInfo, $rawTagTable);
|
---|
[16842] | 673 | next;
|
---|
| 674 | }
|
---|
| 675 | my ($valueDataPos, $count, $subdir);
|
---|
| 676 | my $format = $crwTagFormat{$tagType};
|
---|
| 677 | if ($tagInfo) {
|
---|
| 678 | $subdir = $$tagInfo{SubDirectory};
|
---|
| 679 | $format = $$tagInfo{Format} if $$tagInfo{Format};
|
---|
| 680 | $count = $$tagInfo{Count};
|
---|
| 681 | }
|
---|
| 682 | # get value data
|
---|
| 683 | my ($value, $delRawConv);
|
---|
| 684 | if ($valueInDir) { # is the value data in the directory?
|
---|
| 685 | # this type of tag stores the value in the 'size' and 'ptr' fields
|
---|
[34921] | 686 | $valueDataPos = $dirOffset + $pt + 4; # (remember, +2 for the entry count)
|
---|
[16842] | 687 | $size = 8;
|
---|
| 688 | $value = substr($buff, $pt+2, $size);
|
---|
| 689 | # set count to 1 by default for normal values in directory
|
---|
| 690 | $count = 1 if not defined $count and $format and
|
---|
| 691 | $format ne 'string' and not $subdir;
|
---|
| 692 | } else {
|
---|
| 693 | $valueDataPos = $ptr;
|
---|
| 694 | if ($size <= 512 or ($verbose > 2 and $size <= 65536)
|
---|
| 695 | or ($tagInfo and ($$tagInfo{SubDirectory}
|
---|
[34921] | 696 | or grep(/^$$tagInfo{Name}$/i, $et->GetRequestedTags()) )))
|
---|
[16842] | 697 | {
|
---|
| 698 | # read value if size is small or specifically requested
|
---|
| 699 | # or if this is a SubDirectory
|
---|
| 700 | unless ($raf->Seek($ptr, 0) and $raf->Read($value, $size) == $size) {
|
---|
[34921] | 701 | $et->Warn(sprintf("Error reading %d bytes from 0x%x",$size,$ptr));
|
---|
[16842] | 702 | next;
|
---|
| 703 | }
|
---|
| 704 | } else {
|
---|
| 705 | $value = "Binary data $size bytes";
|
---|
| 706 | if ($tagInfo) {
|
---|
[34921] | 707 | if ($et->Options('Binary') or $verbose) {
|
---|
[16842] | 708 | # read the value anyway
|
---|
| 709 | unless ($raf->Seek($ptr, 0) and $raf->Read($value, $size) == $size) {
|
---|
[34921] | 710 | $et->Warn(sprintf("Error reading %d bytes from 0x%x",$size,$ptr));
|
---|
[16842] | 711 | next;
|
---|
| 712 | }
|
---|
| 713 | }
|
---|
| 714 | # force this to be a binary (scalar reference)
|
---|
| 715 | $$tagInfo{RawConv} = '\$val';
|
---|
| 716 | $delRawConv = 1;
|
---|
| 717 | }
|
---|
| 718 | $size = length $value;
|
---|
| 719 | undef $format;
|
---|
| 720 | }
|
---|
| 721 | }
|
---|
| 722 | # set count from tagInfo count if necessary
|
---|
| 723 | if ($format and not $count) {
|
---|
| 724 | # set count according to format and size
|
---|
| 725 | my $fnum = $Image::ExifTool::Exif::formatNumber{$format};
|
---|
| 726 | my $fsiz = $Image::ExifTool::Exif::formatSize[$fnum];
|
---|
| 727 | $count = int($size / $fsiz);
|
---|
| 728 | }
|
---|
| 729 | if ($verbose) {
|
---|
| 730 | my $val = $value;
|
---|
| 731 | $format and $val = ReadValue(\$val, 0, $format, $count, $size);
|
---|
[34921] | 732 | $et->VerboseInfo($tagID, $tagInfo,
|
---|
[16842] | 733 | Table => $rawTagTable,
|
---|
| 734 | Index => $index,
|
---|
| 735 | Value => $val,
|
---|
| 736 | DataPt => \$value,
|
---|
| 737 | DataPos => $valueDataPos,
|
---|
| 738 | Size => $size,
|
---|
| 739 | Format => $format,
|
---|
| 740 | Count => $count,
|
---|
| 741 | );
|
---|
| 742 | }
|
---|
| 743 | if ($buildMakerNotes) {
|
---|
| 744 | # build maker notes information if requested
|
---|
[34921] | 745 | BuildMakerNotes($et, $tagID, $tagInfo, \$value, $format, $count);
|
---|
[16842] | 746 | }
|
---|
| 747 | next unless defined $tagInfo;
|
---|
| 748 |
|
---|
| 749 | if ($subdir) {
|
---|
| 750 | my $name = $$tagInfo{Name};
|
---|
| 751 | my $newTagTable;
|
---|
| 752 | if ($$subdir{TagTable}) {
|
---|
[24107] | 753 | $newTagTable = GetTagTable($$subdir{TagTable});
|
---|
[16842] | 754 | unless ($newTagTable) {
|
---|
| 755 | warn "Unknown tag table $$subdir{TagTable}\n";
|
---|
| 756 | next;
|
---|
| 757 | }
|
---|
| 758 | } else {
|
---|
| 759 | warn "Must specify TagTable for SubDirectory $name\n";
|
---|
| 760 | next;
|
---|
| 761 | }
|
---|
| 762 | my $subdirStart = 0;
|
---|
| 763 | #### eval Start ()
|
---|
| 764 | $subdirStart = eval $$subdir{Start} if $$subdir{Start};
|
---|
| 765 | my $dirData = \$value;
|
---|
| 766 | my %subdirInfo = (
|
---|
| 767 | Name => $name,
|
---|
| 768 | DataPt => $dirData,
|
---|
| 769 | DataLen => $size,
|
---|
| 770 | DataPos => $valueDataPos,
|
---|
| 771 | DirStart => $subdirStart,
|
---|
| 772 | DirLen => $size - $subdirStart,
|
---|
| 773 | Nesting => $$dirInfo{Nesting} + 1,
|
---|
| 774 | RAF => $raf,
|
---|
[34921] | 775 | DirName => $name,
|
---|
[16842] | 776 | Parent => $$dirInfo{DirName},
|
---|
| 777 | );
|
---|
| 778 | #### eval Validate ($dirData, $subdirStart, $size)
|
---|
| 779 | if (defined $$subdir{Validate} and not eval $$subdir{Validate}) {
|
---|
[34921] | 780 | $et->Warn("Invalid $name data");
|
---|
[16842] | 781 | } else {
|
---|
[34921] | 782 | $et->ProcessDirectory(\%subdirInfo, $newTagTable, $$subdir{ProcessProc});
|
---|
[16842] | 783 | }
|
---|
| 784 | } else {
|
---|
| 785 | # convert to specified format if necessary
|
---|
| 786 | $format and $value = ReadValue(\$value, 0, $format, $count, $size);
|
---|
| 787 | # save the information
|
---|
[34921] | 788 | $et->FoundTag($tagInfo, $value);
|
---|
[16842] | 789 | delete $$tagInfo{RawConv} if $delRawConv;
|
---|
| 790 | }
|
---|
| 791 | }
|
---|
| 792 | return 1;
|
---|
| 793 | }
|
---|
| 794 |
|
---|
| 795 | #------------------------------------------------------------------------------
|
---|
| 796 | # get information from raw file
|
---|
| 797 | # Inputs: 0) ExifTool object reference, 1) dirInfo reference
|
---|
| 798 | # Returns: 1 if this was a valid Canon RAW file
|
---|
| 799 | sub ProcessCRW($$)
|
---|
| 800 | {
|
---|
[34921] | 801 | my ($et, $dirInfo) = @_;
|
---|
[16842] | 802 | my ($buff, $sig);
|
---|
| 803 | my $raf = $$dirInfo{RAF};
|
---|
[34921] | 804 | my $buildMakerNotes = $et->Options('MakerNotes');
|
---|
[16842] | 805 |
|
---|
| 806 | $raf->Read($buff,2) == 2 or return 0;
|
---|
| 807 | SetByteOrder($buff) or return 0;
|
---|
| 808 | $raf->Read($buff,4) == 4 or return 0;
|
---|
| 809 | $raf->Read($sig,8) == 8 or return 0; # get file signature
|
---|
| 810 | $sig =~ /^HEAP(CCDR|JPGM)/ or return 0; # validate signature
|
---|
| 811 | my $hlen = Get32u(\$buff, 0);
|
---|
| 812 |
|
---|
| 813 | $raf->Seek(0, 2) or return 0; # seek to end of file
|
---|
| 814 | my $filesize = $raf->Tell() or return 0;
|
---|
| 815 |
|
---|
| 816 | # initialize maker note data if building maker notes
|
---|
[34921] | 817 | $buildMakerNotes and InitMakerNotes($et);
|
---|
[16842] | 818 |
|
---|
[34921] | 819 | # set the FileType tag unless already done (eg. APP0 CIFF record in JPEG image)
|
---|
| 820 | $et->SetFileType();
|
---|
[16842] | 821 |
|
---|
| 822 | # build directory information for main raw directory
|
---|
| 823 | my %dirInfo = (
|
---|
| 824 | DataLen => 0,
|
---|
| 825 | DirStart => $hlen,
|
---|
| 826 | DirLen => $filesize - $hlen,
|
---|
| 827 | Nesting => 0,
|
---|
| 828 | RAF => $raf,
|
---|
| 829 | Parent => 'CRW',
|
---|
| 830 | );
|
---|
| 831 |
|
---|
| 832 | # process the raw directory
|
---|
[24107] | 833 | my $rawTagTable = GetTagTable('Image::ExifTool::CanonRaw::Main');
|
---|
[34921] | 834 | my $oldIndent = $$et{INDENT};
|
---|
| 835 | $$et{INDENT} .= '| ';
|
---|
| 836 | unless (ProcessCanonRaw($et, \%dirInfo, $rawTagTable)) {
|
---|
| 837 | $et->Warn('CRW file format error');
|
---|
[16842] | 838 | }
|
---|
[34921] | 839 | $$et{INDENT} = $oldIndent;
|
---|
[16842] | 840 |
|
---|
| 841 | # finish building maker notes if necessary
|
---|
[34921] | 842 | $buildMakerNotes and SaveMakerNotes($et);
|
---|
[16842] | 843 |
|
---|
[24107] | 844 | # process trailers if they exist in CRW file (not in CIFF information!)
|
---|
[34921] | 845 | if ($$et{FILE_TYPE} eq 'CRW') {
|
---|
[24107] | 846 | my $trailInfo = Image::ExifTool::IdentifyTrailer($raf);
|
---|
[34921] | 847 | $et->ProcessTrailers($trailInfo) if $trailInfo;
|
---|
[24107] | 848 | }
|
---|
[16842] | 849 |
|
---|
| 850 | return 1;
|
---|
| 851 | }
|
---|
| 852 |
|
---|
| 853 | 1; # end
|
---|
| 854 |
|
---|
| 855 | __END__
|
---|
| 856 |
|
---|
| 857 | =head1 NAME
|
---|
| 858 |
|
---|
| 859 | Image::ExifTool::CanonRaw - Read Canon RAW (CRW) meta information
|
---|
| 860 |
|
---|
| 861 | =head1 SYNOPSIS
|
---|
| 862 |
|
---|
| 863 | This module is loaded automatically by Image::ExifTool when required.
|
---|
| 864 |
|
---|
| 865 | =head1 DESCRIPTION
|
---|
| 866 |
|
---|
| 867 | This module contains definitions required by Image::ExifTool to interpret
|
---|
| 868 | meta information from Canon CRW raw files. These files are written directly
|
---|
| 869 | by some Canon cameras, and contain meta information similar to that found in
|
---|
| 870 | the EXIF Canon maker notes.
|
---|
| 871 |
|
---|
| 872 | =head1 NOTES
|
---|
| 873 |
|
---|
| 874 | The CR2 format written by some Canon cameras is very different the CRW
|
---|
| 875 | format processed by this module. (CR2 is TIFF-based and uses standard EXIF
|
---|
| 876 | tags.)
|
---|
| 877 |
|
---|
| 878 | =head1 AUTHOR
|
---|
| 879 |
|
---|
[34921] | 880 | Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
|
---|
[16842] | 881 |
|
---|
| 882 | This library is free software; you can redistribute it and/or modify it
|
---|
| 883 | under the same terms as Perl itself.
|
---|
| 884 |
|
---|
| 885 | =head1 REFERENCES
|
---|
| 886 |
|
---|
| 887 | =over 4
|
---|
| 888 |
|
---|
| 889 | =item L<http://www.cybercom.net/~dcoffin/dcraw/>
|
---|
| 890 |
|
---|
| 891 | =item L<http://www.wonderland.org/crw/>
|
---|
| 892 |
|
---|
| 893 | =item L<http://xyrion.org/ciff/>
|
---|
| 894 |
|
---|
[34921] | 895 | =item L<https://exiftool.org/canon_raw.html>
|
---|
[16842] | 896 |
|
---|
| 897 | =back
|
---|
| 898 |
|
---|
[24107] | 899 | =head1 ACKNOWLEDGEMENTS
|
---|
| 900 |
|
---|
| 901 | Thanks to Dave Nicholson for decoding a number of new tags.
|
---|
| 902 |
|
---|
[16842] | 903 | =head1 SEE ALSO
|
---|
| 904 |
|
---|
| 905 | L<Image::ExifTool::TagNames/CanonRaw Tags>,
|
---|
| 906 | L<Image::ExifTool::Canon(3pm)|Image::ExifTool::Canon>,
|
---|
| 907 | L<Image::ExifTool(3pm)|Image::ExifTool>
|
---|
| 908 |
|
---|
| 909 | =cut
|
---|
| 910 |
|
---|