Ricoh.pm 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148
  1. #------------------------------------------------------------------------------
  2. # File: Ricoh.pm
  3. #
  4. # Description: Ricoh EXIF maker notes tags
  5. #
  6. # Revisions: 03/28/2005 - P. Harvey Created
  7. #
  8. # References: 1) http://www.ozhiker.com/electronics/pjmt/jpeg_info/ricoh_mn.html
  9. # 2) http://homepage3.nifty.com/kamisaka/makernote/makernote_ricoh.htm
  10. # 3) Tim Gray private communication (GR)
  11. # 4) https://github.com/atotto/ricoh-theta-tools/
  12. # 5) Iliah Borg private communication (LibRaw)
  13. #------------------------------------------------------------------------------
  14. package Image::ExifTool::Ricoh;
  15. use strict;
  16. use vars qw($VERSION);
  17. use Image::ExifTool qw(:DataAccess :Utils);
  18. use Image::ExifTool::Exif;
  19. $VERSION = '1.31';
  20. sub ProcessRicohText($$$);
  21. sub ProcessRicohRMETA($$$);
  22. # lens types for Ricoh GXR
  23. my %ricohLensIDs = (
  24. Notes => q{
  25. Lens units available for the GXR, used by the Ricoh Composite LensID tag. Note
  26. that unlike lenses for all other makes of cameras, the focal lengths in these
  27. model names have already been scaled to include the 35mm crop factor.
  28. },
  29. # (the exact lens model names used by Ricoh, except for a change in case)
  30. 'RL1' => 'GR Lens A12 50mm F2.5 Macro',
  31. 'RL2' => 'Ricoh Lens S10 24-70mm F2.5-4.4 VC',
  32. 'RL3' => 'Ricoh Lens P10 28-300mm F3.5-5.6 VC',
  33. 'RL5' => 'GR Lens A12 28mm F2.5',
  34. 'RL8' => 'Mount A12',
  35. 'RL6' => 'Ricoh Lens A16 24-85mm F3.5-5.5',
  36. );
  37. %Image::ExifTool::Ricoh::Main = (
  38. GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
  39. WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
  40. CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
  41. WRITABLE => 1,
  42. 0x0001 => { Name => 'MakerNoteType', Writable => 'string' },
  43. 0x0002 => { #PH
  44. Name => 'FirmwareVersion',
  45. Writable => 'string',
  46. # eg. "Rev0113" is firmware version 1.13
  47. PrintConv => '$val=~/^Rev(\d+)$/ ? sprintf("%.2f",$1/100) : $val',
  48. PrintConvInv => '$val=~/^(\d+)\.(\d+)$/ ? sprintf("Rev%.2d%.2d",$1,$2) : $val',
  49. },
  50. 0x0005 => [ #PH
  51. {
  52. Condition => '$$valPt =~ /^[-\w ]+$/',
  53. Name => 'SerialNumber', # (verified for GXR)
  54. Writable => 'undef',
  55. Count => 16,
  56. Notes => q{
  57. the serial number stamped on the camera begins with 2 model-specific letters
  58. followed by the last 8 digits of this value. For the GXR, this is the
  59. serial number of the lens unit
  60. },
  61. PrintConv => '$val=~s/^(.*)(.{8})$/($1)$2/; $val',
  62. PrintConvInv => '$val=~tr/()//d; $val',
  63. },{
  64. Name => 'InternalSerialNumber',
  65. Writable => 'undef',
  66. Count => 16,
  67. ValueConv => 'unpack("H*", $val)',
  68. ValueConvInv => 'pack("H*", $val)',
  69. },
  70. ],
  71. 0x0e00 => {
  72. Name => 'PrintIM',
  73. Writable => 0,
  74. Description => 'Print Image Matching',
  75. SubDirectory => { TagTable => 'Image::ExifTool::PrintIM::Main' },
  76. },
  77. 0x1000 => { #3
  78. Name => 'RecordingFormat',
  79. Writable => 'int16u',
  80. PrintConv => {
  81. 2 => 'JPEG',
  82. 3 => 'DNG',
  83. },
  84. },
  85. 0x1001 => [{
  86. Name => 'ImageInfo',
  87. Condition => '$format ne "int16u"',
  88. SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::ImageInfo' },
  89. },{ #3
  90. Name => 'ExposureProgram',
  91. Writable => 'int16u',
  92. Notes => 'GR',
  93. PrintConv => {
  94. 1 => 'Auto',
  95. 2 => 'Program AE',
  96. 3 => 'Aperture-priority AE',
  97. 4 => 'Shutter speed priority AE',
  98. 5 => 'Shutter/aperture priority AE', # TAv
  99. 6 => 'Manual',
  100. 7 => 'Movie', #PH
  101. },
  102. }],
  103. 0x1002 => { #3
  104. Name => 'DriveMode',
  105. Condition => '$format eq "int16u"',
  106. Notes => 'valid only for some models',
  107. Writable => 'int16u',
  108. PrintConv => {
  109. 0 => 'Single-frame',
  110. 1 => 'Continuous',
  111. 8 => 'AF-priority Continuous',
  112. },
  113. },
  114. 0x1003 => [{
  115. Name => 'Sharpness',
  116. Condition => '$format ne "int16u"',
  117. Writable => 'int32u',
  118. PrintConv => {
  119. 0 => 'Sharp',
  120. 1 => 'Normal',
  121. 2 => 'Soft',
  122. },
  123. },{ #3
  124. Name => 'WhiteBalance',
  125. Writable => 'int16u',
  126. Notes => 'GR',
  127. PrintConv => {
  128. 0 => 'Auto',
  129. 1 => 'Multi-P Auto',
  130. 2 => 'Daylight',
  131. 3 => 'Cloudy',
  132. 4 => 'Incandescent 1',
  133. 5 => 'Incandescent 2',
  134. 6 => 'Daylight Fluorescent',
  135. 7 => 'Neutral White Fluorescent',
  136. 8 => 'Cool White Fluorescent',
  137. 9 => 'Warm White Fluorescent',
  138. 10 => 'Manual',
  139. 11 => 'Kelvin',
  140. 12 => 'Shade', #5
  141. },
  142. }],
  143. 0x1004 => { #3
  144. Name => 'WhiteBalanceFineTune',
  145. Condition => '$format eq "int16u"',
  146. Format => 'int16s',
  147. Writable => 'int16u',
  148. Notes => q{
  149. 2 numbers: amount of adjustment towards Amber and Green. Not valid for all
  150. models
  151. },
  152. },
  153. # 0x1005 int16u - 5
  154. 0x1006 => { #3
  155. Name => 'FocusMode',
  156. Writable => 'int16u',
  157. PrintConv => {
  158. 1 => 'Manual',
  159. 2 => 'Multi AF',
  160. 3 => 'Spot AF',
  161. 4 => 'Snap',
  162. 5 => 'Infinity',
  163. 7 => 'Face Detect', #PH
  164. 8 => 'Subject Tracking',
  165. 9 => 'Pinpoint AF',
  166. 10 => 'Movie', #PH
  167. },
  168. },
  169. 0x1007 => { #3
  170. Name => 'AutoBracketing',
  171. Writable => 'int16u',
  172. PrintConv => {
  173. 0 => 'Off',
  174. 9 => 'AE',
  175. 11 => 'WB',
  176. 16 => 'DR', # (dynamic range)
  177. 17 => 'Contrast',
  178. 18 => 'WB2', # (selects two different WB presets besides normal)
  179. 19 => 'Effect',
  180. },
  181. },
  182. 0x1009 => { #3
  183. Name => 'MacroMode',
  184. Writable => 'int16u',
  185. PrintConv => { 0 => 'Off', 1 => 'On' },
  186. },
  187. 0x100a => { #3
  188. Name => 'FlashMode',
  189. Writable => 'int16u',
  190. PrintConv => {
  191. 0 => 'Off',
  192. 1 => 'Auto, Fired',
  193. 2 => 'On',
  194. 3 => 'Auto, Fired, Red-eye reduction',
  195. 4 => 'Slow Sync',
  196. 5 => 'Manual',
  197. 6 => 'On, Red-eye reduction',
  198. 7 => 'Synchro, Red-eye reduction',
  199. 8 => 'Auto, Did not fire',
  200. },
  201. },
  202. 0x100b => { #3
  203. Name => 'FlashExposureComp',
  204. Writable => 'rational64s',
  205. PrintConv => '$val ? sprintf("%+.1f",$val) : $val',
  206. PrintConvInv => '$val',
  207. },
  208. 0x100c => { #3
  209. Name => 'ManualFlashOutput',
  210. Writable => 'rational64s',
  211. PrintConv => {
  212. 0 => 'Full',
  213. -24 => '1/1.4',
  214. -48 => '1/2',
  215. -72 => '1/2.8',
  216. -96 => '1/4',
  217. -120 => '1/5.6',
  218. -144 => '1/8',
  219. -168 => '1/11',
  220. -192 => '1/16',
  221. -216 => '1/22',
  222. -240 => '1/32',
  223. -288 => '1/64',
  224. },
  225. },
  226. 0x100d => { #3
  227. Name => 'FullPressSnap',
  228. Writable => 'int16u',
  229. PrintConv => { 0 => 'Off', 1 => 'On' },
  230. },
  231. 0x100e => { #3
  232. Name => 'DynamicRangeExpansion',
  233. Writable => 'int16u',
  234. PrintConv => {
  235. 0 => 'Off',
  236. 3 => 'Weak',
  237. 4 => 'Medium',
  238. 5 => 'Strong',
  239. },
  240. },
  241. 0x100f => { #3
  242. Name => 'NoiseReduction',
  243. Writable => 'int16u',
  244. PrintConv => {
  245. 0 => 'Off',
  246. 1 => 'Weak',
  247. 2 => 'Medium',
  248. 3 => 'Strong',
  249. },
  250. },
  251. 0x1010 => { #3
  252. Name => 'ImageEffects',
  253. Writable => 'int16u',
  254. PrintConv => {
  255. 0 => 'Standard',
  256. 1 => 'Vivid',
  257. 3 => 'Black & White',
  258. 5 => 'B&W Toning Effect',
  259. 6 => 'Setting 1',
  260. 7 => 'Setting 2',
  261. 9 => 'High-contrast B&W',
  262. 10 => 'Cross Process',
  263. 11 => 'Positive Film',
  264. 12 => 'Bleach Bypass',
  265. 13 => 'Retro',
  266. 15 => 'Miniature',
  267. 17 => 'High Key',
  268. },
  269. },
  270. 0x1011 => { #3
  271. Name => 'Vignetting',
  272. Writable => 'int16u',
  273. PrintConv => {
  274. 0 => 'Off',
  275. 1 => 'Low',
  276. 2 => 'Medium',
  277. 3 => 'High',
  278. },
  279. },
  280. 0x1012 => { #PH
  281. Name => 'Contrast',
  282. Writable => 'int32u',
  283. Format => 'int32s', #3 (high-contrast B&W also has -1 and -2 settings)
  284. PrintConv => {
  285. OTHER => sub { shift },
  286. 2147483647 => 'MAX', #3 (high-contrast B&W effect MAX setting)
  287. },
  288. },
  289. 0x1013 => { Name => 'Saturation', Writable => 'int32u' }, #PH
  290. 0x1014 => { Name => 'Sharpness', Writable => 'int32u' }, #3
  291. 0x1015 => { #3
  292. Name => 'ToningEffect',
  293. Writable => 'int16u',
  294. PrintConv => {
  295. 0 => 'Off',
  296. 1 => 'Sepia',
  297. 2 => 'Red',
  298. 3 => 'Green',
  299. 4 => 'Blue',
  300. 5 => 'Purple',
  301. 6 => 'B&W',
  302. 7 => 'Color',
  303. },
  304. },
  305. 0x1016 => { #3
  306. Name => 'HueAdjust',
  307. Writable => 'int16u',
  308. PrintConv => {
  309. 0 => 'Off',
  310. 1 => 'Basic',
  311. 2 => 'Magenta',
  312. 3 => 'Yellow',
  313. 4 => 'Normal',
  314. 5 => 'Warm',
  315. 6 => 'Cool',
  316. },
  317. },
  318. 0x1017 => { #3
  319. Name => 'WideAdapter',
  320. Writable => 'int16u',
  321. PrintConv => {
  322. 0 => 'Not Attached',
  323. 2 => 'Attached', # (21mm)
  324. },
  325. },
  326. 0x1018 => { #3
  327. Name => 'CropMode35mm',
  328. Writable => 'int16u',
  329. PrintConv => { 0 => 'Off', 1 => 'On' },
  330. },
  331. 0x1019 => { #3
  332. Name => 'NDFilter',
  333. Writable => 'int16u',
  334. PrintConv => { 0 => 'Off', 1 => 'On' },
  335. },
  336. 0x101a => { Name => 'WBBracketShotNumber', Writable => 'int16u' }, #3
  337. # 0x1100 - related to DR correction (ref 3)
  338. 0x1307 => { Name => 'ColorTempKelvin', Writable => 'int32u' }, #3
  339. 0x1308 => { Name => 'ColorTemperature', Writable => 'int32u' }, #3
  340. 0x1500 => { #3
  341. Name => 'FocalLength',
  342. Writable => 'rational64u',
  343. PrintConv => 'sprintf("%.1f mm",$val)',
  344. PrintConvInv => '$val=~s/\s*mm$//;$val',
  345. },
  346. 0x1200 => { #3
  347. Name => 'AFStatus',
  348. Writable => 'int16u',
  349. PrintConv => {
  350. 0 => 'Out of Focus',
  351. 1 => 'In Focus',
  352. },
  353. },
  354. # 0x1201-0x1204 - related to focus points (ref 3)
  355. 0x1201 => { #PH (NC)
  356. Name => 'AFAreaXPosition1',
  357. Writable => 'int32u',
  358. Notes => 'manual AF area position in a 1280x864 image',
  359. },
  360. 0x1202 => { Name => 'AFAreaYPosition1', Writable => 'int32u' }, #PH (NC)
  361. 0x1203 => { #PH (NC)
  362. Name => 'AFAreaXPosition',
  363. Writable => 'int32u',
  364. Notes => 'manual AF area position in the full image',
  365. # (coordinates change to correspond with smaller image
  366. # when recording reduced-size JPEG)
  367. },
  368. 0x1204 => { Name => 'AFAreaYPosition', Writable => 'int32u' }, #PH (NC)
  369. 0x1205 => { #3
  370. Name => 'AFAreaMode',
  371. Writable => 'int16u',
  372. PrintConv => {
  373. 0 => 'Auto',
  374. 2 => 'Manual',
  375. },
  376. },
  377. 0x1601 => { Name => 'SensorWidth', Writable => 'int32u' }, #3
  378. 0x1602 => { Name => 'SensorHeight', Writable => 'int32u' }, #3
  379. 0x1603 => { Name => 'CroppedImageWidth', Writable => 'int32u' }, #3
  380. 0x1604 => { Name => 'CroppedImageHeight', Writable => 'int32u' }, #3
  381. # 0x1700 - Composite? (0=normal image, 1=interval composite, 2=multi-exposure composite) (ref 3)
  382. # 0x1703 - 0=normal, 1=final composite (ref 3)
  383. # 0x1704 - 0=normal, 2=final composite (ref 3)
  384. 0x2001 => [
  385. {
  386. Name => 'RicohSubdir',
  387. Condition => q{
  388. $self->{Model} !~ /^Caplio RR1\b/ and
  389. ($format ne 'int32u' or $count != 1)
  390. },
  391. SubDirectory => {
  392. Validate => '$val =~ /^\[Ricoh Camera Info\]/',
  393. TagTable => 'Image::ExifTool::Ricoh::Subdir',
  394. Start => '$valuePtr + 20',
  395. ByteOrder => 'BigEndian',
  396. },
  397. },
  398. {
  399. Name => 'RicohSubdirIFD',
  400. # the CX6 and GR Digital 4 write an int32u pointer in AVI videos -- doh!
  401. Condition => '$self->{Model} !~ /^Caplio RR1\b/',
  402. Flags => 'SubIFD',
  403. SubDirectory => {
  404. TagTable => 'Image::ExifTool::Ricoh::Subdir',
  405. Start => '$val + 20', # (skip over "[Ricoh Camera Info]\0" header)
  406. ByteOrder => 'BigEndian',
  407. },
  408. },
  409. {
  410. Name => 'RicohRR1Subdir',
  411. SubDirectory => {
  412. Validate => '$val =~ /^\[Ricoh Camera Info\]/',
  413. TagTable => 'Image::ExifTool::Ricoh::Subdir',
  414. Start => '$valuePtr + 20',
  415. ByteOrder => 'BigEndian',
  416. # the Caplio RR1 uses a different base address -- doh!
  417. Base => '$start-20',
  418. },
  419. },
  420. ],
  421. 0x4001 => {
  422. Name => 'ThetaSubdir',
  423. Groups => { 1 => 'MakerNotes' }, # SubIFD needs group 1 set
  424. Flags => 'SubIFD',
  425. SubDirectory => {
  426. TagTable => 'Image::ExifTool::Ricoh::ThetaSubdir',
  427. Start => '$val',
  428. },
  429. },
  430. );
  431. # Ricoh type 2 maker notes (ref PH)
  432. # (similar to Kodak::Type11 and GE::Main)
  433. %Image::ExifTool::Ricoh::Type2 = (
  434. GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
  435. NOTES => q{
  436. Tags written by models such as the Ricoh HZ15 and the Pentax XG-1. These
  437. are not writable due to numerous formatting errors as written by these
  438. cameras.
  439. },
  440. # 0x104 - int32u: 1
  441. # 0x200 - int32u[3]: 0 0 0
  442. # 0x202 - int16u: 0 (GE Macro?)
  443. # 0x203 - int16u: 0,3 (Kodak PictureEffect?)
  444. # 0x204 - rational64u: 0/10
  445. # 0x205 - rational64u: 150/1
  446. # 0x206 - float[6]: (not really float because size should be 2 bytes)
  447. 0x207 => {
  448. Name => 'RicohModel',
  449. Writable => 'string',
  450. },
  451. 0x300 => {
  452. # brutal. There are lots of errors in the XG-1 maker notes. For the XG-1,
  453. # 0x300 has a value of "XG-1Pentax". The "XG-1" part is likely an improperly
  454. # stored 0x207 RicohModel, resulting in an erroneous 4-byte offset for this tag
  455. Name => 'RicohMake',
  456. Writable => 'undef',
  457. ValueConv => '$val =~ s/ *$//; $val',
  458. },
  459. # 0x306 - int16u: 1
  460. # 0x500 - int16u: 0,1
  461. # 0x501 - int16u: 0
  462. # 0x502 - int16u: 0
  463. # 0x9c9c - int8u[6]: ?
  464. # 0xadad - int8u[20480]: ?
  465. );
  466. # Ricoh image info (ref 2)
  467. %Image::ExifTool::Ricoh::ImageInfo = (
  468. GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
  469. PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
  470. WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
  471. CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
  472. WRITABLE => 1,
  473. PRIORITY => 0,
  474. FORMAT => 'int8u',
  475. FIRST_ENTRY => 0,
  476. IS_OFFSET => [ 28 ], # tag 28 is 'IsOffset'
  477. 0 => {
  478. Name => 'RicohImageWidth',
  479. Format => 'int16u',
  480. },
  481. 2 => {
  482. Name => 'RicohImageHeight',
  483. Format => 'int16u',
  484. },
  485. 6 => {
  486. Name => 'RicohDate',
  487. Groups => { 2 => 'Time' },
  488. Format => 'int8u[7]',
  489. # (what an insane way to encode the date)
  490. ValueConv => q{
  491. sprintf("%.2x%.2x:%.2x:%.2x %.2x:%.2x:%.2x",
  492. split(' ', $val));
  493. },
  494. ValueConvInv => q{
  495. my @vals = ($val =~ /(\d{1,2})/g);
  496. push @vals, 0 if @vals < 7;
  497. join(' ', map(hex, @vals));
  498. },
  499. },
  500. 28 => {
  501. Name => 'PreviewImageStart',
  502. Format => 'int16u', # ha! (only the lower 16 bits, even if > 0xffff)
  503. Flags => 'IsOffset',
  504. OffsetPair => 30, # associated byte count tagID
  505. DataTag => 'PreviewImage',
  506. Protected => 2,
  507. # prevent preview from being written to MakerNotes of DNG images
  508. RawConvInv => q{
  509. return $val if $$self{FILE_TYPE} eq "JPEG";
  510. warn "\n"; # suppress warning
  511. return undef;
  512. },
  513. },
  514. 30 => {
  515. Name => 'PreviewImageLength',
  516. Format => 'int16u',
  517. OffsetPair => 28, # point to associated offset
  518. DataTag => 'PreviewImage',
  519. Protected => 2,
  520. RawConvInv => q{
  521. return $val if $$self{FILE_TYPE} eq "JPEG";
  522. warn "\n"; # suppress warning
  523. return undef;
  524. },
  525. },
  526. 32 => {
  527. Name => 'FlashMode',
  528. PrintConv => {
  529. 0 => 'Off',
  530. 1 => 'Auto', #PH
  531. 2 => 'On',
  532. },
  533. },
  534. 33 => {
  535. Name => 'Macro',
  536. PrintConv => { 0 => 'Off', 1 => 'On' },
  537. },
  538. 34 => {
  539. Name => 'Sharpness',
  540. PrintConv => {
  541. 0 => 'Sharp',
  542. 1 => 'Normal',
  543. 2 => 'Soft',
  544. },
  545. },
  546. 38 => {
  547. Name => 'WhiteBalance',
  548. PrintConv => {
  549. 0 => 'Auto',
  550. 1 => 'Daylight',
  551. 2 => 'Cloudy',
  552. 3 => 'Tungsten',
  553. 4 => 'Fluorescent',
  554. 5 => 'Manual', #PH (GXR)
  555. 7 => 'Detail',
  556. 9 => 'Multi-pattern Auto', #PH (GXR)
  557. },
  558. },
  559. 39 => {
  560. Name => 'ISOSetting',
  561. PrintConv => {
  562. 0 => 'Auto',
  563. 1 => 64,
  564. 2 => 100,
  565. 4 => 200,
  566. 6 => 400,
  567. 7 => 800,
  568. 8 => 1600,
  569. 9 => 'Auto', #PH (? CX3)
  570. 10 => 3200, #PH (A16)
  571. 11 => '100 (Low)', #PH (A16)
  572. },
  573. },
  574. 40 => {
  575. Name => 'Saturation',
  576. PrintConv => {
  577. 0 => 'High',
  578. 1 => 'Normal',
  579. 2 => 'Low',
  580. 3 => 'B&W',
  581. 6 => 'Toning Effect', #PH (GXR Sepia,Red,Green,Blue,Purple)
  582. 9 => 'Vivid', #PH (GXR)
  583. 10 => 'Natural', #PH (GXR)
  584. },
  585. },
  586. );
  587. # Ricoh subdirectory tags (ref PH)
  588. # NOTE: this subdir is currently not writable because the offsets would require
  589. # special code to handle the funny start location and base offset
  590. %Image::ExifTool::Ricoh::Subdir = (
  591. GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
  592. WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
  593. CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
  594. # the significance of the following 2 dates is not known. They are usually
  595. # within a month of each other, but I have seen differences of nearly a year.
  596. # Sometimes the first is more recent, and sometimes the second.
  597. # 0x0003 - int32u[1]
  598. 0x0004 => { # (NC)
  599. Name => 'ManufactureDate1',
  600. Groups => { 2 => 'Time' },
  601. Writable => 'string',
  602. Count => 20,
  603. },
  604. 0x0005 => { # (NC)
  605. Name => 'ManufactureDate2',
  606. Groups => { 2 => 'Time' },
  607. Writable => 'string',
  608. Count => 20,
  609. },
  610. # 0x0006 - undef[16] ?
  611. # 0x0007 - int32u[1] ?
  612. # 0x000c - int32u[2] 1st number is a counter (file number? shutter count?) - PH
  613. # 0x0014 - int8u[338] could contain some data related to face detection? - PH
  614. # 0x0015 - int8u[2]: related to noise reduction?
  615. 0x001a => { #PH
  616. Name => 'FaceInfo',
  617. SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::FaceInfo' },
  618. },
  619. 0x0029 => {
  620. Name => 'FirmwareInfo',
  621. SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::FirmwareInfo' },
  622. },
  623. 0x002a => {
  624. Name => 'NoiseReduction',
  625. # this is the applied value if NR is set to "Auto"
  626. Writable => 'int32u',
  627. PrintConv => {
  628. 0 => 'Off',
  629. 1 => 'Weak',
  630. 2 => 'Strong',
  631. 3 => 'Max',
  632. },
  633. },
  634. 0x002c => { # (GXR)
  635. Name => 'SerialInfo',
  636. SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::SerialInfo' },
  637. }
  638. # 0x000E ProductionNumber? (ref 2) [no. zero for most models - PH]
  639. );
  640. # Ricoh Theta subdirectory tags - Contains orientation information (ref 4)
  641. %Image::ExifTool::Ricoh::ThetaSubdir = (
  642. GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
  643. WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
  644. CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
  645. # 0x0001 - int16u[1] ?
  646. # 0x0002 - int16u[1] ?
  647. 0x0003 => {
  648. Name => 'Accelerometer',
  649. Writable => 'rational64s',
  650. Count => 2,
  651. },
  652. 0x0004 => {
  653. Name => 'Compass',
  654. Writable => 'rational64u',
  655. },
  656. # 0x0005 - int16u[1] ?
  657. # 0x0006 - int16u[1] ?
  658. # 0x0007 - int16u[1] ?
  659. # 0x0008 - int16u[1] ?
  660. # 0x0009 - int16u[1] ?
  661. 0x000a => {
  662. Name => 'TimeZone',
  663. Writable => 'string',
  664. },
  665. # 0x0101 - int16u[4] ISO (why 4 values?)
  666. # 0x0102 - rational64s[2] FNumber (why 2 values?)
  667. # 0x0103 - rational64u[2] ExposureTime (why 2 values?)
  668. # 0x0104 - string[9] SerialNumber?
  669. # 0x0105 - string[9] SerialNumber?
  670. );
  671. # face detection information (ref PH, CX4)
  672. %Image::ExifTool::Ricoh::FaceInfo = (
  673. GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
  674. PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
  675. WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
  676. CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
  677. WRITABLE => 1,
  678. FIRST_ENTRY => 0,
  679. DATAMEMBER => [ 181 ],
  680. 0xb5 => { # (should be int16u at 0xb4?)
  681. Name => 'FacesDetected',
  682. DataMember => 'FacesDetected',
  683. RawConv => '$$self{FacesDetected} = $val',
  684. },
  685. 0xb6 => {
  686. Name => 'FaceDetectFrameSize',
  687. Format => 'int16u[2]',
  688. },
  689. 0xbc => {
  690. Name => 'Face1Position',
  691. Condition => '$$self{FacesDetected} >= 1',
  692. Format => 'int16u[4]',
  693. Notes => q{
  694. left, top, width and height of detected face in coordinates of
  695. FaceDetectFrameSize with increasing Y downwards
  696. },
  697. },
  698. 0xc8 => {
  699. Name => 'Face2Position',
  700. Condition => '$$self{FacesDetected} >= 2',
  701. Format => 'int16u[4]',
  702. },
  703. 0xd4 => {
  704. Name => 'Face3Position',
  705. Condition => '$$self{FacesDetected} >= 3',
  706. Format => 'int16u[4]',
  707. },
  708. 0xe0 => {
  709. Name => 'Face4Position',
  710. Condition => '$$self{FacesDetected} >= 4',
  711. Format => 'int16u[4]',
  712. },
  713. 0xec => {
  714. Name => 'Face5Position',
  715. Condition => '$$self{FacesDetected} >= 5',
  716. Format => 'int16u[4]',
  717. },
  718. 0xf8 => {
  719. Name => 'Face6Position',
  720. Condition => '$$self{FacesDetected} >= 6',
  721. Format => 'int16u[4]',
  722. },
  723. 0x104 => {
  724. Name => 'Face7Position',
  725. Condition => '$$self{FacesDetected} >= 7',
  726. Format => 'int16u[4]',
  727. },
  728. 0x110 => {
  729. Name => 'Face8Position',
  730. Condition => '$$self{FacesDetected} >= 8',
  731. Format => 'int16u[4]',
  732. },
  733. );
  734. # firmware version information (ref PH)
  735. %Image::ExifTool::Ricoh::FirmwareInfo = (
  736. GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
  737. PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
  738. WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
  739. CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
  740. WRITABLE => 1,
  741. 0x00 => {
  742. Name => 'FirmwareRevision',
  743. Format => 'string[12]',
  744. },
  745. 0x0c => {
  746. Name => 'FirmwareRevision2',
  747. Format => 'string[12]',
  748. },
  749. );
  750. # serial/version number information written by GXR (ref PH)
  751. %Image::ExifTool::Ricoh::SerialInfo = (
  752. GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
  753. PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
  754. WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
  755. CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
  756. WRITABLE => 1,
  757. NOTES => 'This information is found in images from the GXR.',
  758. 0 => {
  759. Name => 'BodyFirmware', #(NC)
  760. Format => 'string[16]',
  761. # observed: "RS1 :V00560000" --> FirmwareVersion "Rev0056"
  762. # "RS1 :V01020200" --> FirmwareVersion "Rev0102"
  763. },
  764. 16 => {
  765. Name => 'BodySerialNumber',
  766. Format => 'string[16]',
  767. # observed: "SID:00100056" --> "WD00100056" on plate
  768. },
  769. 32 => {
  770. Name => 'LensFirmware', #(NC)
  771. Format => 'string[16]',
  772. # observed: "RL1 :V00560000", "RL1 :V01020200" - A12 50mm F2.5 Macro
  773. # "RL2 :V00560000", "RL2 :V01020300" - S10 24-70mm F2.5-4.4 VC
  774. # --> used in a Composite tag to determine LensType
  775. },
  776. 48 => {
  777. Name => 'LensSerialNumber',
  778. Format => 'string[16]',
  779. # observed: (S10) "LID:00010024" --> "WF00010024" on plate
  780. # (A12) "LID:00010054" --> "WE00010029" on plate??
  781. },
  782. );
  783. # Ricoh text-type maker notes (PH)
  784. %Image::ExifTool::Ricoh::Text = (
  785. GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
  786. PROCESS_PROC => \&ProcessRicohText,
  787. NOTES => q{
  788. Some Ricoh DC and RDC models use a text-based format for their maker notes
  789. instead of the IFD format used by the Caplio models. Below is a list of known
  790. tags in this information.
  791. },
  792. Rev => {
  793. Name => 'FirmwareVersion',
  794. PrintConv => '$val=~/^\d+$/ ? sprintf("%.2f",$val/100) : $val',
  795. PrintConvInv => '$val=~/^(\d+)\.(\d+)$/ ? sprintf("%.2d%.2d",$1,$2) : $val',
  796. },
  797. Rv => {
  798. Name => 'FirmwareVersion',
  799. PrintConv => '$val=~/^\d+$/ ? sprintf("%.2f",$val/100) : $val',
  800. PrintConvInv => '$val=~/^(\d+)\.(\d+)$/ ? sprintf("%.2d%.2d",$1,$2) : $val',
  801. },
  802. Rg => 'RedGain',
  803. Gg => 'GreenGain',
  804. Bg => 'BlueGain',
  805. );
  806. %Image::ExifTool::Ricoh::RMETA = (
  807. GROUPS => { 0 => 'APP5', 1 => 'RMETA', 2 => 'Image' },
  808. PROCESS_PROC => \&Image::ExifTool::Ricoh::ProcessRicohRMETA,
  809. NOTES => q{
  810. The Ricoh Caplio Pro G3 has the ability to add custom fields to the APP5
  811. "RMETA" segment of JPEG images. While only a few observed tags have been
  812. defined below, ExifTool will extract any information found here.
  813. },
  814. 'Sign type' => { Name => 'SignType', PrintConv => {
  815. 1 => 'Directional',
  816. 2 => 'Warning',
  817. 3 => 'Information',
  818. } },
  819. Location => { PrintConv => {
  820. 1 => 'Verge',
  821. 2 => 'Gantry',
  822. 3 => 'Central reservation',
  823. 4 => 'Roundabout',
  824. } },
  825. Lit => { PrintConv => {
  826. 1 => 'Yes',
  827. 2 => 'No',
  828. } },
  829. Condition => { PrintConv => {
  830. 1 => 'Good',
  831. 2 => 'Fair',
  832. 3 => 'Poor',
  833. 4 => 'Damaged',
  834. } },
  835. Azimuth => { PrintConv => {
  836. 1 => 'N',
  837. 2 => 'NNE',
  838. 3 => 'NE',
  839. 4 => 'ENE',
  840. 5 => 'E',
  841. 6 => 'ESE',
  842. 7 => 'SE',
  843. 8 => 'SSE',
  844. 9 => 'S',
  845. 10 => 'SSW',
  846. 11 => 'SW',
  847. 12 => 'WSW',
  848. 13 => 'W',
  849. 14 => 'WNW',
  850. 15 => 'NW',
  851. 16 => 'NNW',
  852. } },
  853. _audio => {
  854. Name => 'SoundFile',
  855. Notes => 'audio data recorded in JPEG images by the G700SE',
  856. },
  857. );
  858. # information stored in Ricoh AVI images (ref PH)
  859. %Image::ExifTool::Ricoh::AVI = (
  860. GROUPS => { 0 => 'MakerNotes', 2 => 'Video' },
  861. ucmt => {
  862. Name => 'Comment',
  863. # Ricoh writes a "Unicode" header even when text is ASCII (spaces anyway)
  864. ValueConv => '$_=$val; s/^(Unicode\0|ASCII\0\0\0)//; tr/\0//d; s/\s+$//; $_',
  865. },
  866. mnrt => {
  867. Name => 'MakerNoteRicoh',
  868. SubDirectory => {
  869. TagTable => 'Image::ExifTool::Ricoh::Main',
  870. Start => '$valuePtr + 8',
  871. ByteOrder => 'BigEndian',
  872. Base => '8',
  873. },
  874. },
  875. rdc2 => {
  876. Name => 'RicohRDC2',
  877. Unknown => 1,
  878. ValueConv => 'unpack("H*",$val)',
  879. # have seen values like 0a000444 and 00000000 - PH
  880. },
  881. thum => {
  882. Name => 'ThumbnailImage',
  883. Groups => { 2 => 'Preview' },
  884. Binary => 1,
  885. },
  886. );
  887. # Ricoh composite tags
  888. %Image::ExifTool::Ricoh::Composite = (
  889. GROUPS => { 2 => 'Camera' },
  890. LensID => {
  891. SeparateTable => 'Ricoh LensID',
  892. Require => 'Ricoh:LensFirmware',
  893. RawConv => '$val[0] ? $val[0] : undef',
  894. ValueConv => '$val=~s/\s*:.*//; $val',
  895. PrintConv => \%ricohLensIDs,
  896. },
  897. RicohPitch => {
  898. Require => 'Ricoh:Accelerometer',
  899. ValueConv => 'my @v = split(" ",$val); $v[1]',
  900. },
  901. RicohRoll => {
  902. Require => 'Ricoh:Accelerometer',
  903. ValueConv => 'my @v = split(" ",$val); $v[0] <= 180 ? $v[0] : $v[0] - 360',
  904. },
  905. );
  906. # add our composite tags
  907. Image::ExifTool::AddCompositeTags('Image::ExifTool::Ricoh');
  908. #------------------------------------------------------------------------------
  909. # Process Ricoh text-based maker notes
  910. # Inputs: 0) ExifTool object reference
  911. # 1) Reference to directory information hash
  912. # 2) Pointer to tag table for this directory
  913. # Returns: 1 on success, otherwise returns 0 and sets a Warning
  914. sub ProcessRicohText($$$)
  915. {
  916. my ($et, $dirInfo, $tagTablePtr) = @_;
  917. my $dataPt = $$dirInfo{DataPt};
  918. my $dataLen = $$dirInfo{DataLen};
  919. my $dirStart = $$dirInfo{DirStart} || 0;
  920. my $dirLen = $$dirInfo{DirLen} || $dataLen - $dirStart;
  921. my $verbose = $et->Options('Verbose');
  922. my $data = substr($$dataPt, $dirStart, $dirLen);
  923. return 1 if $data =~ /^\0/; # blank Ricoh maker notes
  924. # validate text maker notes
  925. unless ($data =~ /^(Rev|Rv)/) {
  926. $et->Warn('Bad Ricoh maker notes');
  927. return 0;
  928. }
  929. while ($data =~ m/([A-Z][a-z]{1,2})([0-9A-F]+);/sg) {
  930. my $tag = $1;
  931. my $val = $2;
  932. my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
  933. if ($verbose) {
  934. $et->VerboseInfo($tag, $tagInfo,
  935. Table => $tagTablePtr,
  936. Value => $val,
  937. );
  938. }
  939. unless ($tagInfo) {
  940. next unless $$et{OPTIONS}{Unknown};
  941. $tagInfo = {
  942. Name => "Ricoh_Text_$tag",
  943. Unknown => 1,
  944. PrintConv => 'length($val) > 60 ? substr($val,0,55) . "[...]" : $val',
  945. };
  946. # add tag information to table
  947. AddTagToTable($tagTablePtr, $tag, $tagInfo);
  948. }
  949. $et->FoundTag($tagInfo, $val);
  950. }
  951. return 1;
  952. }
  953. #------------------------------------------------------------------------------
  954. # Process Ricoh APP5 RMETA information
  955. # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
  956. # Returns: 1 on success, otherwise returns 0 and sets a Warning
  957. sub ProcessRicohRMETA($$$)
  958. {
  959. my ($et, $dirInfo, $tagTablePtr) = @_;
  960. my $dataPt = $$dirInfo{DataPt};
  961. my $dirStart = $$dirInfo{DirStart};
  962. my $dataLen = length($$dataPt);
  963. my $dirLen = $dataLen - $dirStart;
  964. my $verbose = $et->Options('Verbose');
  965. $et->VerboseDir('Ricoh RMETA') if $verbose;
  966. $dirLen < 20 and $et->Warn('Truncated Ricoh RMETA data', 1), return 0;
  967. my $byteOrder = substr($$dataPt, $dirStart, 2);
  968. $byteOrder = GetByteOrder() if $byteOrder eq "\0\0"; # (same order as container)
  969. SetByteOrder($byteOrder) or $et->Warn('Bad Ricoh RMETA data', 1), return 0;
  970. # get the RMETA segment number
  971. my $rmetaNum = Get16u($dataPt, $dirStart+4);
  972. if ($rmetaNum != 0) {
  973. # not sure how to recognize audio, so do it by checking for "RIFF" header
  974. # and assume all subsequent RMETA segments are part of the audio data
  975. # (but it looks like the int16u at $dirStart+6 is the next block number
  976. # if the data is continued, or 0 for the last block)
  977. $dirLen < 14 and $et->Warn('Short Ricoh RMETA block', 1), return 0;
  978. my $audioLen = Get16u($dataPt, $dirStart+12);
  979. $audioLen + 14 > $dirLen and $et->Warn('Truncated Ricoh RMETA audio data', 1), return 0;
  980. my $buff = substr($$dataPt, $dirStart + 14, $audioLen);
  981. if ($audioLen >= 4 and substr($buff, 0, 4) eq 'RIFF') {
  982. $et->HandleTag($tagTablePtr, '_audio', \$buff);
  983. } elsif ($$et{VALUE}{SoundFile}) {
  984. ${$$et{VALUE}{SoundFile}} .= $buff;
  985. } else {
  986. $et->Warn('Unknown Ricoh RMETA type', 1);
  987. return 0;
  988. }
  989. return 1;
  990. }
  991. # decode standard RMETA tag directory
  992. my (@tags, @vals, @nums, $valPos, $numPos);
  993. my $pos = $dirStart + Get16u($dataPt, $dirStart+8);
  994. my $numEntries = Get16u($dataPt, $pos);
  995. $numEntries > 100 and $et->Warn('Bad RMETA entry count'), return 0;
  996. $pos += 10; # start of first RMETA section
  997. # loop through RMETA sections
  998. while ($pos <= $dataLen - 4) {
  999. my $type = Get16u($dataPt, $pos);
  1000. my $size = Get16u($dataPt, $pos + 2);
  1001. last unless $size;
  1002. $pos += 4;
  1003. $size -= 2;
  1004. if ($size < 0 or $pos + $size > $dataLen) {
  1005. $et->Warn('Corrupted Ricoh RMETA data', 1);
  1006. last;
  1007. }
  1008. my $dat = substr($$dataPt, $pos, $size);
  1009. if ($verbose) {
  1010. $et->VPrint(2, "$$et{INDENT}RMETA section type=$type size=$size\n");
  1011. if ($verbose > 2) {
  1012. my %dumpParms = ( Addr => $$dirInfo{DataPos} + $pos, Prefix => $$et{INDENT} );
  1013. $dumpParms{MaxLen} = 96 if $verbose == 3;
  1014. Image::ExifTool::HexDump(\$dat, undef, %dumpParms);
  1015. }
  1016. }
  1017. if ($type == 1) { # section 1: tag names
  1018. # save the tag names
  1019. @tags = split /\0/, $dat, $numEntries+1;
  1020. } elsif ($type == 2 || $type == 18) { # section 2/18: string values (G800 uses type 18)
  1021. # save the tag values (assume "ASCII\0" encoding since others never seen)
  1022. @vals = split /\0/, $dat, $numEntries+1;
  1023. $valPos = $pos; # save position of first string value
  1024. } elsif ($type == 3) { # section 3: numerical values
  1025. if ($size < $numEntries * 2) {
  1026. $et->Warn('Truncated RMETA section 3');
  1027. } else {
  1028. # save the numerical tag values
  1029. # (0=empty, 0xffff=text input, otherwise menu item number)
  1030. @nums = unpack(($byteOrder eq 'MM' ? 'n' : 'v').$numEntries, $dat);
  1031. $numPos = $pos; # save position of numerical values
  1032. }
  1033. } elsif ($type != 16) {
  1034. $et->Warn("Unrecognized RMETA section (type $type, len $size)");
  1035. }
  1036. $pos += $size;
  1037. }
  1038. return 1 unless @tags or @vals;
  1039. $valPos or $valPos = 0; # (just in case there was no value section)
  1040. # find next tag in null-delimited list
  1041. # unpack numerical values from block of int16u values
  1042. my ($i, $name);
  1043. for ($i=0; $i<$numEntries; ++$i) {
  1044. my $tag = $tags[$i];
  1045. my $val = $vals[$i];
  1046. $val = '' unless defined $val;
  1047. unless (defined $tag and length $tag) {
  1048. length $val or ++$valPos, next; # (skip empty entries)
  1049. $tag = '';
  1050. }
  1051. ($name = $tag) =~ s/\b([a-z])/\U$1/gs; # capitalize all words
  1052. $name =~ s/ (\w)/\U$1/g; # remove special characters
  1053. $name = 'RMETA_Unknown' unless length($name);
  1054. my $num = $nums[$i];
  1055. my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
  1056. if ($tagInfo) {
  1057. # make sure print conversion is defined
  1058. $$tagInfo{PrintConv} = { } unless ref $$tagInfo{PrintConv} eq 'HASH';
  1059. } else {
  1060. # create tagInfo hash
  1061. $tagInfo = { Name => $name, PrintConv => { } };
  1062. AddTagToTable($tagTablePtr, $tag, $tagInfo);
  1063. }
  1064. # use string value directly if no numerical value
  1065. $num = $val unless defined $num;
  1066. # add conversion for this value (replacing any existing entry)
  1067. $tagInfo->{PrintConv}->{$num} = length $val ? $val : $num;
  1068. if ($verbose) {
  1069. my %datParms;
  1070. if (length $val) {
  1071. %datParms = ( Start => $valPos, Size => length($val), Format => 'string' );
  1072. } elsif ($numPos) {
  1073. %datParms = ( Start => $numPos + $i * 2, Size => 2, Format => 'int16u' );
  1074. }
  1075. %datParms and $datParms{DataPt} = $dataPt, $datParms{DataPos} = $$dirInfo{DataPos};
  1076. $et->VerboseInfo($tag, $tagInfo, Table=>$tagTablePtr, Value=>$num, %datParms);
  1077. }
  1078. $et->FoundTag($tagInfo, $num);
  1079. $valPos += length($val) + 1;
  1080. }
  1081. return 1;
  1082. }
  1083. 1; # end
  1084. __END__
  1085. =head1 NAME
  1086. Image::ExifTool::Ricoh - Ricoh EXIF maker notes tags
  1087. =head1 SYNOPSIS
  1088. This module is loaded automatically by Image::ExifTool when required.
  1089. =head1 DESCRIPTION
  1090. This module contains definitions required by Image::ExifTool to
  1091. interpret Ricoh maker notes EXIF meta information.
  1092. =head1 AUTHOR
  1093. Copyright 2003-2016, Phil Harvey (phil at owl.phy.queensu.ca)
  1094. This library is free software; you can redistribute it and/or modify it
  1095. under the same terms as Perl itself.
  1096. =head1 REFERENCES
  1097. =over 4
  1098. =item L<http://www.ozhiker.com/electronics/pjmt/jpeg_info/ricoh_mn.html>
  1099. =back
  1100. =head1 ACKNOWLEDGEMENTS
  1101. Thanks to Tim Gray for his help decoding a number of tags for the Ricoh GR.
  1102. =head1 SEE ALSO
  1103. L<Image::ExifTool::TagNames/Ricoh Tags>,
  1104. L<Image::ExifTool(3pm)|Image::ExifTool>
  1105. =cut