source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/CanonRaw.pm@ 24626

Last change on this file since 24626 was 24626, checked in by jmt12, 13 years ago

An (almost) complete copy of the perllib directory from a (circa SEP2011) head checkout from Greenstone 2 trunk - in order to try and make merging in this extension a little easier later on (as there have been some major changes to buildcol.pl commited in the main trunk but not in the x64 branch)

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