CanonRaw.pm 30 KB

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