1 /*
2 * Copyright (c) 2001-2007, Eric M. Johnston <emj@postal.net>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Eric M. Johnston.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: canon.c,v 1.54 2007/12/16 03:06:13 ejohnst Exp $
33 */
34
35 /*
36 * Exif tag definitions for Canon maker notes.
37 * Developed from http://www.burren.cx/david/canon.html.
38 * EOS 1D and 1Ds contributions from Stan Jirman <stanj@phototrek.org>.
39 * EOS 10D contributions from Jason Montojo <jason.montojo@rogers.com>.
40 * EOS 20D contributions from Per Kristian Hove <Per.Hove@math.ntnu.no>.
41 * EOS 5D contributions from Albert Max Lai <amlai@columbia.edu>.
42 *
43 */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <math.h>
49
50 #include "makers.h"
51
52
53 /*
54 * Calculate and format an exposure value ("-n.nn EV").
55 */
56 static float
calcev(char * c,int l,int16_t v)57 calcev(char *c, int l, int16_t v)
58 {
59 #if 0 /* Adjustment seems silly. If someone complains, I'll reconsider. */
60 int16_t n;
61
62 /*
63 * XXX 1/3 and 2/3 values seem to be a bit off. This makes a
64 * slight adjustment; may want to revisit.
65 */
66 n = (abs(v) - 32) * (v & 0x8000 ? -1 : 1);
67 if (n == 20 || n == -12) v++;
68 else if (n == -20 || n == 12) v--;
69 #endif
70
71 if (c) snprintf(c, l, "%.2f EV", (float)v / 32);
72 return ((float)v / 32);
73 }
74
75
76 /* Macro mode. */
77
78 static struct descrip canon_macro[] = {
79 { 1, "Macro" },
80 { 2, "Normal" },
81 { -1, "Unknown" },
82 };
83
84
85 /* Focus type. */
86
87 static struct descrip canon_focustype[] = {
88 { 0, "Manual" },
89 { 1, "Auto" },
90 { 2, "Auto" },
91 { 3, "Close-Up (Macro Mode)" },
92 { 7, "Infinity Mode" },
93 { 8, "Locked (Pan Mode)" },
94 { -1, "Unknown" },
95 };
96
97
98 /* Quality. */
99
100 static struct descrip canon_quality[] = {
101 { 2, "Normal" },
102 { 3, "Fine" },
103 { 5, "Superfine" },
104 { -1, "Unknown" },
105 };
106
107
108 /* Flash mode. */
109
110 static struct descrip canon_flash[] = {
111 { 0, "Off" },
112 { 1, "Auto" },
113 { 2, "On" },
114 { 3, "Red-Eye Reduction" },
115 { 4, "Slow-Synchro" },
116 { 5, "Red-Eye Reduction (Auto)" },
117 { 6, "Red-Eye Reduction (On)" },
118 { 16, "External Flash" },
119 { -1, "Unknown" },
120 };
121
122
123 /* Drive mode. */
124
125 static struct descrip canon_drive[] = {
126 { 0, "Single" }, /* "Timed" when field 2 is > 0. */
127 { 1, "Continuous" },
128 { -1, "Unknown" },
129 };
130
131
132 /* Focus mode. */
133
134 static struct descrip canon_focus1[] = {
135 { 0, "One-Shot" },
136 { 1, "AI Servo" },
137 { 2, "AI Focus" },
138 { 3, "Manual" },
139 { 4, "Single" },
140 { 5, "Continuous" },
141 { 6, "Manual" },
142 { -1, "Unknown" },
143 };
144
145
146 /* Image size. */
147
148 static struct descrip canon_imagesz[] = {
149 { 0, "Large" },
150 { 1, "Medium" },
151 { 2, "Small" },
152 { -1, "Unknown" },
153 };
154
155
156 /* Shooting mode. */
157
158 static struct descrip canon_shoot[] = {
159 { 0, "Full Auto" },
160 { 1, "Manual" },
161 { 2, "Landscape" },
162 { 3, "Fast Shutter" },
163 { 4, "Slow Shutter" },
164 { 5, "Night" },
165 { 6, "Black & White" },
166 { 7, "Sepia" },
167 { 8, "Portrait" },
168 { 9, "Sports" },
169 { 10, "Macro/Close-Up" },
170 { 11, "Pan Focus" },
171 { 19, "Indoor" },
172 { 22, "Underwater" },
173 { 24, "Kids & Pets" },
174 { 25, "Night Snapshot" },
175 { -1, "Unknown" },
176 };
177
178
179 /* Digital zoom. */
180
181 static struct descrip canon_dzoom[] = {
182 { 0, "None" },
183 { 1, "x2" },
184 { 2, "x4" },
185 { -1, "Unknown" },
186 };
187
188
189 /* Contrast, saturation, & sharpness. */
190
191 static struct descrip canon_range[] = {
192 { 0, "Normal" },
193 { 1, "High" },
194 { 0xffff, "Low" },
195 { -1, "Unknown" },
196 };
197
198
199 /* ISO speed rating. */
200
201 static struct descrip canon_iso[] = {
202 { 15, "Auto" },
203 { 16, "50" },
204 { 17, "100" },
205 { 18, "200" },
206 { 19, "400" },
207 { -1, "Unknown" },
208 };
209
210
211 /* Metering mode. */
212
213 static struct descrip canon_meter[] = {
214 { 0, "Default" },
215 { 1, "Spot" },
216 { 3, "Evaluative" },
217 { 4, "Partial" },
218 { 5, "Center-Weighted" },
219 { -1, "Unknown" },
220 };
221
222
223 /* Exposure mode. */
224
225 static struct descrip canon_expmode[] = {
226 { 0, "Easy Shooting" },
227 { 1, "Program" },
228 { 2, "Tv-Priority" },
229 { 3, "Av-Priority" },
230 { 4, "Manual" },
231 { 5, "A-DEP" },
232 { 6, "DEP" },
233 { -1, "Unknown" },
234 };
235
236
237 /* White balance. */
238
239 static struct descrip canon_whitebal[] = {
240 { 0, "Auto" },
241 { 1, "Daylight" },
242 { 2, "Cloudy" },
243 { 3, "Tungsten" },
244 { 4, "Fluorescent" },
245 { 5, "Flash" },
246 { 6, "Custom" },
247 { 7, "Black & White" },
248 { 8, "Shade" },
249 { 9, "Manual Temperature" },
250 { 14, "Daylight Fluorescent" },
251 { 15, "Custom 1" },
252 { 16, "Custom 2" },
253 { 17, "Underwater" },
254 { -1, "Unknown" },
255 };
256
257
258 /* Maker note IFD tags. */
259
260 static struct exiftag canon_tags[] = {
261 { 0x0001, TIFF_SHORT, 0, ED_UNK, "Canon1Tag",
262 "Canon Tag1 Offset", NULL },
263 { 0x0004, TIFF_SHORT, 0, ED_UNK, "Canon4Tag",
264 "Canon Tag4 Offset", NULL },
265 { 0x0006, TIFF_ASCII, 32, ED_VRB, "ImageType",
266 "Image Type", NULL },
267 { 0x0007, TIFF_ASCII, 24, ED_CAM, "FirmwareVer",
268 "Firmware Version", NULL },
269 { 0x0008, TIFF_LONG, 1, ED_IMG, "ImgNum",
270 "Image Number", NULL },
271 { 0x0009, TIFF_ASCII, 32, ED_CAM, "OwnerName",
272 "Owner Name", NULL },
273 { 0x000c, TIFF_LONG, 1, ED_CAM, "Serial",
274 "Serial Number", NULL },
275 { 0x000f, TIFF_SHORT, 0, ED_UNK, "CustomFunc",
276 "Custom Function", NULL },
277 { 0x0090, TIFF_SHORT, 0, ED_UNK, "CustomFunc",
278 "Custom Function", NULL },
279 { 0x0093, TIFF_SHORT, 0, ED_UNK, "Canon93Tag",
280 "Canon Tag93 Offset", NULL },
281 { 0x0095, TIFF_ASCII, 64, ED_PAS, "LensName",
282 "Lens Name", NULL },
283 { 0x00a0, TIFF_SHORT, 0, ED_UNK, "CanonA0Tag",
284 "Canon TagA0 Offset", NULL },
285 { 0xffff, TIFF_UNKN, 0, ED_UNK, "CanonUnknown",
286 "Canon Unknown", NULL },
287 };
288
289
290 /* Fields under tag 0x0001 (camera settings). */
291
292 static struct exiftag canon_tags01[] = {
293 { 0, TIFF_SHORT, 0, ED_VRB, "Canon1Len",
294 "Canon Tag1 Length", NULL },
295 { 1, TIFF_SHORT, 0, ED_IMG, "CanonMacroMode",
296 "Macro Mode", canon_macro },
297 { 2, TIFF_SHORT, 0, ED_VRB, "CanonTimerLen",
298 "Self-Timer Length", NULL },
299 { 3, TIFF_SHORT, 0, ED_IMG, "CanonQuality",
300 "Compression Setting", canon_quality },
301 { 4, TIFF_SHORT, 0, ED_IMG, "CanonFlashMode",
302 "Flash Mode", canon_flash },
303 { 5, TIFF_SHORT, 0, ED_IMG, "CanonDriveMode",
304 "Drive Mode", canon_drive },
305 { 7, TIFF_SHORT, 0, ED_IMG, "CanonFocusMode",
306 "Focus Mode", canon_focus1 },
307 { 10, TIFF_SHORT, 0, ED_IMG, "CanonImageSize",
308 "Image Size", canon_imagesz },
309 { 11, TIFF_SHORT, 0, ED_IMG, "CanonShootMode",
310 "Shooting Mode", canon_shoot },
311 { 12, TIFF_SHORT, 0, ED_VRB, "CanonDigiZoom",
312 "Digital Zoom", NULL },
313 { 13, TIFF_SHORT, 0, ED_IMG, "CanonContrast",
314 "Contrast", canon_range },
315 { 14, TIFF_SHORT, 0, ED_IMG, "CanonSaturate",
316 "Saturation", canon_range },
317 { 15, TIFF_SHORT, 0, ED_IMG, "CanonSharpness",
318 "Sharpness", canon_range },
319 { 16, TIFF_SHORT, 0, ED_IMG, "CanonISO",
320 "ISO Speed Rating", canon_iso },
321 { 17, TIFF_SHORT, 0, ED_IMG, "CanonMeterMode",
322 "Metering Mode", canon_meter },
323 { 18, TIFF_SHORT, 0, ED_IMG, "CanonFocusType",
324 "Focus Type", canon_focustype },
325 { 19, TIFF_SHORT, 0, ED_UNK, "CanonAFPoint",
326 "Autofocus Point", NULL },
327 { 20, TIFF_SHORT, 0, ED_IMG, "CanonExpMode",
328 "Exposure Mode", canon_expmode },
329 { 23, TIFF_SHORT, 0, ED_UNK, "CanonMaxFocal",
330 "Max Focal Length", NULL },
331 { 24, TIFF_SHORT, 0, ED_UNK, "CanonMinFocal",
332 "Min Focal Length", NULL },
333 { 25, TIFF_SHORT, 0, ED_UNK, "CanonFocalUnits",
334 "Focal Units/mm", NULL },
335 { 28, TIFF_SHORT, 0, ED_UNK, "CanonFlashAct",
336 "Flash Activity", NULL },
337 { 29, TIFF_SHORT, 0, ED_UNK, "CanonFlashDet",
338 "Flash Details", NULL },
339 { 36, TIFF_SHORT, 0, ED_VRB, "CanonDZoomRes",
340 "Zoomed Resolution", NULL },
341 { 37, TIFF_SHORT, 0, ED_VRB, "CanonBZoomRes",
342 "Base Zoom Resolution", NULL },
343 { 0xffff, TIFF_SHORT, 0, ED_UNK, "Canon01Unknown",
344 "Canon Tag1 Unknown", NULL },
345 };
346
347
348 /* Fields under tag 0x0004 (shot info). */
349
350 static struct exiftag canon_tags04[] = {
351 { 0, TIFF_SHORT, 0, ED_VRB, "Canon4Len",
352 "Canon Tag4 Length", NULL },
353 { 2, TIFF_SHORT, 0, ED_IMG, "CanonSensorSpeed",
354 "Sensor ISO Speed", NULL },
355 { 6, TIFF_SHORT, 0, ED_IMG, "CanonExpComp",
356 "Exposure Compensation", NULL },
357 { 7, TIFF_SHORT, 0, ED_IMG, "CanonWhiteB",
358 "White Balance", canon_whitebal },
359 { 9, TIFF_SHORT, 0, ED_IMG, "CanonSequence",
360 "Sequence Number", NULL },
361 { 14, TIFF_SHORT, 0, ED_UNK, "CanonAFPoint2",
362 "Autofocus Point", NULL },
363 { 15, TIFF_SHORT, 0, ED_IMG, "CanonFlashBias",
364 "Flash Bias", NULL },
365 { 19, TIFF_SHORT, 0, ED_IMG, "CanonSubjDst",
366 "Subject Distance", NULL },
367 { 0xffff, TIFF_SHORT, 0, ED_UNK, "Canon04Unknown",
368 "Canon Tag4 Unknown", NULL },
369 };
370
371
372 /* Fields under tag 0x00a0 (EOS 1D, 1Ds). */
373
374 static struct exiftag canon_tagsA0[] = {
375 { 0, TIFF_SHORT, 0, ED_VRB, "CanonA0Len",
376 "Canon TagA0 Length", NULL },
377 { 9, TIFF_SHORT, 0, ED_IMG, "CanonColorTemp",
378 "Color Temperature", NULL },
379 { 10, TIFF_SHORT, 0, ED_IMG, "CanonColorMatrix",
380 "Color Matrix", NULL },
381 { 0xffff, TIFF_SHORT, 0, ED_UNK, "CanonA0Unknown",
382 "Canon TagA0 Unknown", NULL },
383 };
384
385
386 /* Fields under tag 0x0093 (counter on EOS 1D, 1Ds). */
387
388 static struct exiftag canon_tags93[] = {
389 { 0, TIFF_SHORT, 0, ED_VRB, "Canon93Len",
390 "Canon Tag93 Length", NULL },
391 { 1, TIFF_SHORT, 0, ED_VRB, "CanonActuateMult",
392 "Actuation Multiplier", NULL },
393 { 2, TIFF_SHORT, 0, ED_VRB, "CanonActuateCount",
394 "Actuation Counter", NULL },
395 { 0xffff, TIFF_SHORT, 0, ED_UNK, "Canon93Unknown",
396 "Canon Tag93 Unknown", NULL },
397 };
398
399
400 /* Placeholder for unknown fields. */
401
402 static struct exiftag canon_tagsunk[] = {
403 { 0xffff, TIFF_SHORT, 0, ED_UNK, "CanonUnknown",
404 "Canon Unknown", NULL },
405 };
406
407
408 /* Value descriptions for custom functions. */
409
410 static struct descrip ccstm_offon[] = {
411 { 0, "Off" },
412 { 1, "On" },
413 { -1, "Unknown" },
414 };
415
416 static struct descrip ccstm_shutter[] = {
417 { 0, "AF/AE Lock" },
418 { 1, "AE Lock/AF" },
419 { 2, "AF/AF Lock" },
420 { 3, "AE+Release/AE+AF" },
421 { -1, "Unknown" },
422 };
423
424 static struct descrip ccstm_disen[] = {
425 { 0, "Disabled" },
426 { 1, "Enabled" },
427 { -1, "Unknown" },
428 };
429
430 static struct descrip ccstm_explvl[] = {
431 { 0, "1/2 Stop" },
432 { 1, "1/3 Stop" },
433 { -1, "Unknown" },
434 };
435
436 static struct descrip ccstm_autooff[] = {
437 { 0, "Auto" },
438 { 1, "Off" },
439 { -1, "Unknown" },
440 };
441
442 static struct descrip ccstm_shutspd[] = {
443 { 0, "Auto" },
444 { 1, "1/200 (Fixed)" },
445 { -1, "Unknown" },
446 };
447
448 static struct descrip ccstm_aebseq[] = {
449 { 0, "0,-,+/Enabled" },
450 { 1, "0,-,+/Disabled" },
451 { 2, "-,0,+/Enabled" },
452 { 3, "-,0,+/Disabled" },
453 { -1, "Unknown" },
454 };
455
456 static struct descrip ccstm_shutsync[] = {
457 { 0, "1st-Curtain Sync" },
458 { 1, "2nd-Curtain Sync" },
459 { -1, "Unknown" },
460 };
461
462 static struct descrip ccstm_lensaf[] = {
463 { 0, "AF Stop" },
464 { 1, "Operate AF" },
465 { 2, "Lock AE & Start Timer" },
466 { -1, "Unknown" },
467 };
468
469 static struct descrip ccstm_endis[] = {
470 { 0, "Enabled" },
471 { 1, "Disabled" },
472 { -1, "Unknown" },
473 };
474
475 static struct descrip ccstm_menubut[] = {
476 { 0, "Top" },
477 { 1, "Previous (Volatile)" },
478 { 2, "Previous" },
479 { -1, "Unknown" },
480 };
481
482 static struct descrip ccstm_setbut[] = {
483 { 0, "Not Assigned" },
484 { 1, "Change Quality" },
485 { 2, "Change ISO Speed" },
486 { 3, "Select Parameters" },
487 { -1, "Unknown" },
488 };
489
490 static struct descrip ccstm_yesno[] = {
491 { 0, "Yes" },
492 { 1, "No" },
493 { -1, "Unknown" },
494 };
495
496 static struct descrip ccstm_noyes[] = {
497 { 0, "No" },
498 { 1, "Yes" },
499 { -1, "Unknown" },
500 };
501
502 static struct descrip ccstm_onoff[] = {
503 { 0, "On" },
504 { 1, "Off" },
505 { -1, "Unknown" },
506 };
507
508 static struct descrip ccstm_afsel[] = {
509 { 0, "H=AF+Main/V=AF+Command" },
510 { 1, "H=Comp+Main/V=Comp+Command" },
511 { 2, "H=Command Only/V=Assist+Main" },
512 { 3, "H=FEL+Main/V=FEL+Command" },
513 { -1, "Unknown" },
514 };
515
516 static struct descrip ccstm_afill[] = {
517 { 0, "On" },
518 { 1, "Off" },
519 { 2, "On Without Dimming" },
520 { 3, "Brighter" },
521 { -1, "Unknown" },
522 };
523
524 static struct descrip ccstm_lcdpanels[] = {
525 { 0, "Remain. Shots/File No." },
526 { 1, "ISO/Remain. Shots" },
527 { 2, "ISO/File No." },
528 { 3, "Shots In Folder/Remain. Shots" },
529 { -1, "Unknown" },
530 };
531
532 static struct descrip ccstm_usmmf[] = {
533 { 0, "Turns On After One-Shot AF" },
534 { 1, "Turns Off After One-Shot AF" },
535 { 2, "Always Turned Off" },
536 { -1, "Unknown" },
537 };
538
539 static struct descrip ccstm_explvlinc[] = {
540 { 0, "1/3-Stop Set, 1/3-Stop Comp" },
541 { 1, "1-Stop Set, 1/3-Stop Comp" },
542 { 2, "1/2-Stop Set, 1/2-Stop Comp" },
543 { -1, "Unknown" },
544 };
545
546 static struct descrip ccstm_tvavform[] = {
547 { 0, "Tv=Main/Av=Control" },
548 { 1, "Tv=Control/Av=Main" },
549 { 2, "Tv=Main/Av=Main w/o Lens" },
550 { 3, "Tv=Control/Av=Main w/o Lens" },
551 { -1, "Unknown" },
552 };
553
554 static struct descrip ccstm_shutterael[] = {
555 { 0, "AF/AE Lock Stop" },
556 { 1, "AE Lock/AF" },
557 { 2, "AF/AF Lock, No AE Lock" },
558 { 3, "AE/AF, No AE Lock" },
559 { -1, "Unknown" },
560 };
561
562 static struct descrip ccstm_afspot[] = {
563 { 0, "45/Center AF Point" },
564 { 1, "11/Active AF Point" },
565 { 2, "11/Center AF Point" },
566 { 3, "9/Active AF Point" },
567 { -1, "Unknown" },
568 };
569
570 static struct descrip ccstm_afact[] = {
571 { 0, "Single AF Point" },
572 { 1, "Expanded (TTL. of 7 AF Points)" },
573 { 2, "Automatic Expanded (Max. 13)" },
574 { -1, "Unknown" },
575 };
576
577 static struct descrip ccstm_regaf[] = {
578 { 0, "Assist + AF" },
579 { 1, "Assist" },
580 { 2, "Only While Pressing Assist" },
581 { -1, "Unknown" },
582 };
583
584 static struct descrip ccstm_lensaf1[] = {
585 { 0, "AF Stop" },
586 { 1, "AF Start" },
587 { 2, "AE Lock While Metering" },
588 { 3, "AF Point: M->Auto/Auto->Ctr" },
589 { 4, "AF Mode: ONESHOT<->SERVO" },
590 { 5, "IS Start" },
591 { -1, "Unknown" },
592 };
593
594 static struct descrip ccstm_aisens[] = {
595 { 0, "Standard" },
596 { 1, "Slow" },
597 { 2, "Moderately Slow" },
598 { 3, "Moderately Fast" },
599 { 4, "Fast" },
600 { -1, "Unknown" },
601 };
602
603 static struct descrip ccstm_fscr[] = {
604 { 0, "Ec-N, R" },
605 { 1, "Ec-A,B,C,CII,CIII,D,H,I,L" },
606 { -1, "Unknown" },
607 };
608
609 static struct descrip ccstm_10dsetbut[] = {
610 { 0, "Not Assigned" },
611 { 1, "Change Quality" },
612 { 2, "Change Parameters" },
613 { 3, "Menu Display" },
614 { 4, "Image Replay" },
615 { -1, "Unknown" },
616 };
617
618 static struct descrip ccstm_10dshutter[] = {
619 { 0, "AF/AE Lock" },
620 { 1, "AE Lock/AF" },
621 { 2, "AF/AF Lock, No AE Lock" },
622 { 3, "AE/AF, No AE Lock" },
623 { -1, "Unknown" },
624 };
625
626 static struct descrip ccstm_assistflash[] = {
627 { 0, "Emits/Fires" },
628 { 1, "Does Not Emit/Fires" },
629 { 2, "Only Ext. Flash Emits/Fires" },
630 { 3, "Emits/Does Not Fire" },
631 { -1, "Unknown" },
632 };
633
634 static struct descrip ccstm_afptreg[] = {
635 { 0, "Center" },
636 { 1, "Bottom" },
637 { 2, "Right" },
638 { 3, "Extreme Right" },
639 { 4, "Automatic" },
640 { 5, "Extreme Left" },
641 { 6, "Left" },
642 { 7, "Top" },
643 { -1, "Unknown" },
644 };
645
646 static struct descrip ccstm_rawjpeg[] = {
647 { 0, "RAW+Small/Normal" },
648 { 1, "RAW+Small/Fine" },
649 { 2, "RAW+Medium/Normal" },
650 { 3, "RAW+Medium/Fine" },
651 { 4, "RAW+Large/Normal" },
652 { 5, "RAW+Large/Fine" },
653 { -1, "Unknown" },
654 };
655
656 static struct descrip ccstm_10dmenubut[] = {
657 { 0, "Previous (Volatile)" },
658 { 1, "Previous" },
659 { 2, "Top" },
660 { -1, "Unknown" },
661 };
662
663 static struct descrip ccstm_assistbut[] = {
664 { 0, "Normal" },
665 { 1, "Select Home Position" },
666 { 2, "Select HP (while pressing)" },
667 { 3, "Av+/- (AF point by QCD)" },
668 { 4, "FE lock" },
669 { -1, "Unknown" },
670 };
671
672 static struct descrip ccstm_20dexplvl[] = {
673 { 0, "1/3 Stop" },
674 { 1, "1/2 Stop" },
675 { -1, "Unknown" },
676 };
677
678 static struct descrip ccstm_20dflashsync[] = {
679 { 0, "Auto" },
680 { 1, "1/250 (Fixed)" },
681 { -1, "Unknown" },
682 };
683
684 static struct descrip ccstm_20dflash[] = {
685 { 0, "Fires" },
686 { 1, "Does Not Fire" },
687 { -1, "Unknown" },
688 };
689
690 static struct descrip ccstm_20dafpsel[] = {
691 { 0, "Normal" },
692 { 1, "Multi-Controller Direct" },
693 { 2, "Quick Control Dial Direct" },
694 { -1, "Unknown" },
695 };
696
697 static struct descrip ccstm_20dettl[] = {
698 { 0, "Evaluative" },
699 { 1, "Average" },
700 { -1, "Unknown" },
701 };
702
703 static struct descrip ccstm_5dflashsync[] = {
704 { 0, "Auto" },
705 { 1, "1/200 (Fixed)" },
706 { -1, "Unknown" },
707 };
708
709 static struct descrip ccstm_5dfscr[] = {
710 { 0, "Ee-A" },
711 { 1, "Ee-D" },
712 { 2, "Ee-S" },
713 { -1, "Unknown" },
714 };
715
716
717 /* D30/D60 custom functions. */
718
719 static struct exiftag canon_d30custom[] = {
720 { 1, TIFF_SHORT, 0, ED_VRB, "D30Custom",
721 "Long exposure noise reduction", ccstm_offon },
722 { 2, TIFF_SHORT, 0, ED_VRB, "D30Custom",
723 "Shutter/AE lock buttons", ccstm_shutter },
724 { 3, TIFF_SHORT, 0, ED_VRB, "D30Custom",
725 "Mirror lockup", ccstm_disen },
726 { 4, TIFF_SHORT, 0, ED_VRB, "D30Custom",
727 "Tv/Av and exposure level", ccstm_explvl },
728 { 5, TIFF_SHORT, 0, ED_VRB, "D30Custom",
729 "AF-assist light", ccstm_autooff },
730 { 6, TIFF_SHORT, 0, ED_VRB, "D30Custom",
731 "Av mode shutter speed", ccstm_shutspd },
732 { 7, TIFF_SHORT, 0, ED_VRB, "D30Custom",
733 "AEB sequence/auto cancellation", ccstm_aebseq },
734 { 8, TIFF_SHORT, 0, ED_VRB, "D30Custom",
735 "Shutter curtain sync", ccstm_shutsync },
736 { 9, TIFF_SHORT, 0, ED_VRB, "D30Custom",
737 "Lens AF stop button", ccstm_lensaf },
738 { 10, TIFF_SHORT, 0, ED_VRB, "D30Custom",
739 "Fill flash auto reduction", ccstm_endis },
740 { 11, TIFF_SHORT, 0, ED_VRB, "D30Custom",
741 "Menu button return position", ccstm_menubut },
742 { 12, TIFF_SHORT, 0, ED_VRB, "D30Custom",
743 "Shooting Set button function", ccstm_setbut },
744 { 13, TIFF_SHORT, 0, ED_VRB, "D30Custom",
745 "Sensor cleaning", ccstm_disen },
746 { 14, TIFF_SHORT, 0, ED_VRB, "D30Custom",
747 "Superimposed display", ccstm_onoff },
748 { 15, TIFF_SHORT, 0, ED_VRB, "D30Custom",
749 "Shutter release w/o CF card", ccstm_yesno },
750 { 0xffff, TIFF_SHORT, 0, ED_UNK, "D30CustomUnknown",
751 "Canon D30/D60 Custom Unknown", NULL },
752 };
753
754
755 /* EOS-1D/1Ds custom functions. */
756
757 static struct exiftag canon_1dcustom[] = {
758 { 0, TIFF_SHORT, 0, ED_VRB, "1DCustom",
759 "Focusing screen", ccstm_fscr },
760 { 1, TIFF_SHORT, 0, ED_VRB, "1DCustom",
761 "Finder display during exposure", ccstm_offon },
762 { 2, TIFF_SHORT, 0, ED_VRB, "1DCustom",
763 "Shutter release w/o CF card", ccstm_yesno },
764 { 3, TIFF_SHORT, 0, ED_VRB, "1DCustom",
765 "ISO speed expansion", ccstm_noyes },
766 { 4, TIFF_SHORT, 0, ED_VRB, "1DCustom",
767 "Shutter button/AEL button", ccstm_shutterael },
768 { 5, TIFF_SHORT, 0, ED_VRB, "1DCustom",
769 "Manual Tv/Av for M", ccstm_tvavform },
770 { 6, TIFF_SHORT, 0, ED_VRB, "1DCustom",
771 "Exposure level increments", ccstm_explvlinc },
772 { 7, TIFF_SHORT, 0, ED_VRB, "1DCustom",
773 "USM lens electronic MF", ccstm_usmmf },
774 { 8, TIFF_SHORT, 0, ED_VRB, "1DCustom",
775 "Top/back LCD panels", ccstm_lcdpanels },
776 { 9, TIFF_SHORT, 0, ED_VRB, "1DCustom",
777 "AEB sequence/auto cancellation", ccstm_aebseq },
778 { 10, TIFF_SHORT, 0, ED_VRB, "1DCustom",
779 "AF point illumination", ccstm_afill },
780 { 11, TIFF_SHORT, 0, ED_VRB, "1DCustom",
781 "AF point selection", ccstm_afsel },
782 { 12, TIFF_SHORT, 0, ED_VRB, "1DCustom",
783 "Mirror lockup", ccstm_disen },
784 { 13, TIFF_SHORT, 0, ED_VRB, "1DCustom",
785 "# AF points/spot metering", ccstm_afspot },
786 { 14, TIFF_SHORT, 0, ED_VRB, "1DCustom",
787 "Fill flash auto reduction", ccstm_endis },
788 { 15, TIFF_SHORT, 0, ED_VRB, "1DCustom",
789 "Shutter curtain sync", ccstm_shutsync },
790 { 16, TIFF_SHORT, 0, ED_VRB, "1DCustom",
791 "Safety shift in Av or Tv", ccstm_disen },
792 { 17, TIFF_SHORT, 0, ED_VRB, "1DCustom",
793 "AF point activation area", ccstm_afact },
794 { 18, TIFF_SHORT, 0, ED_VRB, "1DCustom",
795 "Switch to registered AF point", ccstm_regaf },
796 { 19, TIFF_SHORT, 0, ED_VRB, "1DCustom",
797 "Lens AF stop button", ccstm_lensaf1 },
798 { 20, TIFF_SHORT, 0, ED_VRB, "1DCustom",
799 "AI servo tracking sensitivity", ccstm_aisens },
800 { 0xffff, TIFF_SHORT, 0, ED_UNK, "1DCustomUnknown",
801 "Canon 1D/1Ds Custom Unknown", NULL },
802 };
803
804 /* 5D custom functions. */
805
806 static struct exiftag canon_5dcustom[] = {
807 { 0, TIFF_SHORT, 0, ED_VRB, "5DCustom",
808 "Focusing Screen", ccstm_5dfscr },
809 { 1, TIFF_SHORT, 0, ED_VRB, "5DCustom",
810 "SET button function when shooting", ccstm_10dsetbut },
811 { 2, TIFF_SHORT, 0, ED_VRB, "5DCustom",
812 "Long exposure noise reduction", ccstm_offon },
813 { 3, TIFF_SHORT, 0, ED_VRB, "5DCustom",
814 "Flash sync speed in Av mode", ccstm_5dflashsync },
815 { 4, TIFF_SHORT, 0, ED_VRB, "5DCustom",
816 "Shutter button/AE lock button", ccstm_10dshutter },
817 { 5, TIFF_SHORT, 0, ED_VRB, "5DCustom",
818 "AF-assist beam", ccstm_assistflash },
819 { 6, TIFF_SHORT, 0, ED_VRB, "5DCustom",
820 "Exposure level increments", ccstm_20dexplvl },
821 { 7, TIFF_SHORT, 0, ED_VRB, "5DCustom",
822 "Flash firing", ccstm_20dflash },
823 { 8, TIFF_SHORT, 0, ED_VRB, "5DCustom",
824 "ISO expansion", ccstm_offon },
825 { 9, TIFF_SHORT, 0, ED_VRB, "5DCustom",
826 "AEB sequence/auto cancellation", ccstm_aebseq },
827 { 10, TIFF_SHORT, 0, ED_VRB, "5DCustom",
828 "Superimposed display", ccstm_onoff },
829 { 11, TIFF_SHORT, 0, ED_VRB, "5DCustom",
830 "Menu button display position", ccstm_10dmenubut },
831 { 12, TIFF_SHORT, 0, ED_VRB, "5DCustom",
832 "Mirror lockup", ccstm_disen },
833 { 13, TIFF_SHORT, 0, ED_VRB, "5DCustom",
834 "AF point selection method", ccstm_20dafpsel },
835 { 14, TIFF_SHORT, 0, ED_VRB, "5DCustom",
836 "E-TTL II", ccstm_20dettl },
837 { 15, TIFF_SHORT, 0, ED_VRB, "5DCustom",
838 "Shutter curtain sync", ccstm_shutsync },
839 { 16, TIFF_SHORT, 0, ED_VRB, "5DCustom",
840 "Safety shift in Av or Tv", ccstm_disen },
841 { 17, TIFF_SHORT, 0, ED_VRB, "5DCustom",
842 "Lens AF stop button", ccstm_lensaf1 },
843 { 18, TIFF_SHORT, 0, ED_VRB, "5DCustom",
844 "Add original decision data", ccstm_offon },
845 { 0xffff, TIFF_SHORT, 0, ED_UNK, "5DCustomUnknown",
846 "Canon 5D Custom Unknown", NULL },
847 };
848
849 /* 10D custom functions. */
850
851 static struct exiftag canon_10dcustom[] = {
852 { 1, TIFF_SHORT, 0, ED_VRB, "10DCustom",
853 "SET button function when shooting", ccstm_10dsetbut },
854 { 2, TIFF_SHORT, 0, ED_VRB, "10DCustom",
855 "Shutter release w/o CF card", ccstm_yesno },
856 { 3, TIFF_SHORT, 0, ED_VRB, "10DCustom",
857 "Flash sync speed in Av mode", ccstm_shutspd },
858 { 4, TIFF_SHORT, 0, ED_VRB, "10DCustom",
859 "Shutter button/AE lock button", ccstm_10dshutter },
860 { 5, TIFF_SHORT, 0, ED_VRB, "10DCustom",
861 "AF-assist beam/Flash firing", ccstm_assistflash },
862 { 6, TIFF_SHORT, 0, ED_VRB, "10DCustom",
863 "Exposure level increments", ccstm_explvl },
864 { 7, TIFF_SHORT, 0, ED_VRB, "10DCustom",
865 "AF point registration", ccstm_afptreg },
866 { 8, TIFF_SHORT, 0, ED_VRB, "10DCustom",
867 "RAW+JPEG recording", ccstm_rawjpeg },
868 { 9, TIFF_SHORT, 0, ED_VRB, "10DCustom",
869 "AEB sequence/auto cancellation", ccstm_aebseq },
870 { 10, TIFF_SHORT, 0, ED_VRB, "10DCustom",
871 "Superimposed display", ccstm_onoff },
872 { 11, TIFF_SHORT, 0, ED_VRB, "10DCustom",
873 "Menu button display position", ccstm_10dmenubut },
874 { 12, TIFF_SHORT, 0, ED_VRB, "10DCustom",
875 "Mirror lockup", ccstm_disen },
876 { 13, TIFF_SHORT, 0, ED_VRB, "10DCustom",
877 "Assist button function", ccstm_assistbut },
878 { 14, TIFF_SHORT, 0, ED_VRB, "10DCustom",
879 "Fill flash auto reduction", ccstm_endis },
880 { 15, TIFF_SHORT, 0, ED_VRB, "10DCustom",
881 "Shutter curtain sync", ccstm_shutsync },
882 { 16, TIFF_SHORT, 0, ED_VRB, "10DCustom",
883 "Safety shift in Av or Tv", ccstm_disen },
884 { 17, TIFF_SHORT, 0, ED_VRB, "10DCustom",
885 "Lens AF stop button", ccstm_lensaf },
886 { 0xffff, TIFF_SHORT, 0, ED_UNK, "10DCustomUnknown",
887 "Canon 10D Custom Unknown", NULL },
888 };
889
890 /* 20D custom functions. */
891
892 static struct exiftag canon_20dcustom[] = {
893 { 0, TIFF_SHORT, 0, ED_VRB, "20DCustom",
894 "SET button function when shooting", ccstm_10dsetbut },
895 { 1, TIFF_SHORT, 0, ED_VRB, "20DCustom",
896 "Long exposure noise reduction", ccstm_offon },
897 { 2, TIFF_SHORT, 0, ED_VRB, "20DCustom",
898 "Flash sync speed in Av mode", ccstm_20dflashsync },
899 { 3, TIFF_SHORT, 0, ED_VRB, "20DCustom",
900 "Shutter button/AE lock button", ccstm_10dshutter },
901 { 4, TIFF_SHORT, 0, ED_VRB, "20DCustom",
902 "AF-assist beam", ccstm_assistflash },
903 { 5, TIFF_SHORT, 0, ED_VRB, "20DCustom",
904 "Exposure level increments", ccstm_20dexplvl },
905 { 6, TIFF_SHORT, 0, ED_VRB, "20DCustom",
906 "Flash firing", ccstm_20dflash },
907 { 7, TIFF_SHORT, 0, ED_VRB, "20DCustom",
908 "ISO expansion", ccstm_offon },
909 { 8, TIFF_SHORT, 0, ED_VRB, "20DCustom",
910 "AEB sequence/auto cancellation", ccstm_aebseq },
911 { 9, TIFF_SHORT, 0, ED_VRB, "20DCustom",
912 "Superimposed display", ccstm_onoff },
913 { 10, TIFF_SHORT, 0, ED_VRB, "20DCustom",
914 "Menu button display position", ccstm_10dmenubut },
915 { 11, TIFF_SHORT, 0, ED_VRB, "20DCustom",
916 "Mirror lockup", ccstm_disen },
917 { 12, TIFF_SHORT, 0, ED_VRB, "20DCustom",
918 "AF point selection method", ccstm_20dafpsel },
919 { 13, TIFF_SHORT, 0, ED_VRB, "20DCustom",
920 "E-TTL II", ccstm_20dettl },
921 { 14, TIFF_SHORT, 0, ED_VRB, "20DCustom",
922 "Shutter curtain sync", ccstm_shutsync },
923 { 15, TIFF_SHORT, 0, ED_VRB, "20DCustom",
924 "Safety shift in Av or Tv", ccstm_disen },
925 { 16, TIFF_SHORT, 0, ED_VRB, "20DCustom",
926 "Lens AF stop button", ccstm_lensaf1 },
927 { 17, TIFF_SHORT, 0, ED_VRB, "20DCustom",
928 "Add original decision data", ccstm_offon },
929 { 0xffff, TIFF_SHORT, 0, ED_UNK, "20DCustomUnknown",
930 "Canon 20D Custom Unknown", NULL },
931 };
932
933
934 /*
935 * Process maker note tag 0x0001 values.
936 */
937 static int
canon_prop01(struct exifprop * aprop,struct exifprop * prop,unsigned char * off,struct exiftags * t)938 canon_prop01(struct exifprop *aprop, struct exifprop *prop,
939 unsigned char *off, struct exiftags *t)
940 {
941 u_int16_t v = (u_int16_t)aprop->value;
942
943 switch (aprop->tag) {
944 case 2:
945 aprop->lvl = v ? ED_IMG : ED_VRB;
946 exifstralloc(&aprop->str, 32);
947 snprintf(aprop->str, 31, "%d sec", v / 10);
948 break;
949 case 5:
950 /* Change "Single" to "Timed" if #2 > 0. */
951
952 if (!v && exif2byte(off + 2 * 2, t->mkrmd.order))
953 strcpy(aprop->str, "Timed");
954 break;
955 case 12:
956 aprop->lvl = v ? ED_IMG : ED_VRB;
957
958 /*
959 * Looks like we can calculate zoom level when value
960 * is 3 (ref S110). Calculation is (2 * #37 / #36).
961 */
962
963 if (v == 3 && prop->count >= 37) {
964 exifstralloc(&aprop->str, 32);
965 snprintf(aprop->str, 31, "x%.1f", 2 *
966 (float)exif2byte(off + 37 * 2, t->mkrmd.order) /
967 (float)exif2byte(off + 36 * 2, t->mkrmd.order));
968 } else
969 aprop->str = finddescr(canon_dzoom, v);
970 break;
971 case 16:
972 /* ISO overrides standard one if known. */
973 if (!strcmp(aprop->str, "Unknown")) {
974 aprop->lvl = ED_VRB;
975 break;
976 }
977 aprop->override = EXIF_T_ISOSPEED;
978 break;
979 case 17:
980 /* Maker meter mode overrides standard one if known. */
981 if (!strcmp(aprop->str, "Unknown")) {
982 aprop->lvl = ED_VRB;
983 break;
984 }
985 aprop->override = EXIF_T_METERMODE;
986 break;
987 case 20:
988 /* With "Easy Shooting", shooting mode is all that matters. */
989 aprop->lvl = v ? ED_IMG : ED_VRB;
990 break;
991 default:
992 return (FALSE);
993 }
994
995 return (TRUE);
996 }
997
998
999 /*
1000 * Process maker note tag 0x0004 values.
1001 */
1002 static int
canon_prop04(struct exifprop * aprop,struct exifprop * prop,unsigned char * off,struct exiftags * t)1003 canon_prop04(struct exifprop *aprop, struct exifprop *prop,
1004 unsigned char *off, struct exiftags *t)
1005 {
1006 struct exifprop *tmpprop;
1007 u_int16_t v = (u_int16_t)aprop->value;
1008 int d;
1009
1010 switch (aprop->tag) {
1011 case 6:
1012 /* Calculate sensor speed (ISO units). */
1013 exifstralloc(&aprop->str, 32);
1014 snprintf(aprop->str, 31, "%d", (int)(exp(calcev(NULL, 0, v) *
1015 log(2)) * 100.0 / 32.0 + 0.5));
1016 break;
1017
1018 case 7:
1019 aprop->override = EXIF_T_WHITEBAL;
1020 break;
1021 case 9:
1022 aprop->lvl = v ? ED_IMG : ED_VRB;
1023 break;
1024 case 15:
1025 exifstralloc(&aprop->str, 16);
1026 if (calcev(aprop->str, 15, v) == 0.0)
1027 aprop->lvl = ED_VRB;
1028 break;
1029
1030 /*
1031 * Sigh. Some cameras have a standard Exif subject distance tag,
1032 * some do not. Some express this in mm, some in cm. (I cannot
1033 * for the life of me figure out how to tell what the units are.)
1034 * It looks like maybe some of the newer models stick to cm; we'll
1035 * assume cm and consider mm by exception. In any case, we'll only
1036 * display the value in the absence of the standard Exif value.
1037 * Needless to say, this is pretty ugly.
1038 */
1039
1040 case 19:
1041 exifstralloc(&aprop->str, 32);
1042
1043 if (!v) {
1044 aprop->lvl = ED_VRB;
1045 strcpy(aprop->str, "Unknown");
1046 break;
1047 }
1048
1049 if (t->model && (!strcmp(t->model, "Canon PowerShot A10") ||
1050 !strcmp(t->model, "Canon PowerShot S110") ||
1051 !strcmp(t->model, "Canon PowerShot S30") ||
1052 !strcmp(t->model, "Canon PowerShot S40") ||
1053 !strcmp(t->model, "Canon EOS 10D")))
1054 d = 1000;
1055 else
1056 d = 100;
1057
1058 if (v == 0xffff)
1059 strcpy(aprop->str, "Infinity");
1060 else
1061 snprintf(aprop->str, 31, "%.3f m",
1062 (float)v / (float)d);
1063
1064 if ((tmpprop = findprop(t->props, tags, EXIF_T_DISTANCE))) {
1065 if (strcmp(tmpprop->str, "Unknown"))
1066 aprop->lvl = ED_VRB;
1067 else
1068 aprop->override = EXIF_T_DISTANCE;
1069 }
1070 break;
1071
1072 default:
1073 return (FALSE);
1074 }
1075
1076 return (TRUE);
1077 }
1078
1079
1080 /*
1081 * Process maker note tag 0x00a0 values.
1082 */
1083 static int
canon_propA0(struct exifprop * aprop,struct exifprop * prop,unsigned char * off,struct exiftags * t)1084 canon_propA0(struct exifprop *aprop, struct exifprop *prop,
1085 unsigned char *off, struct exiftags *t)
1086 {
1087
1088 switch (aprop->tag) {
1089 case 9:
1090 exifstralloc(&aprop->str, 32);
1091 snprintf(aprop->str, 31, "%d K", aprop->value);
1092 break;
1093 default:
1094 return (FALSE);
1095 }
1096
1097 return (TRUE);
1098 }
1099
1100
1101 /*
1102 * Common function for a tag's child values. Pass in the list of tags
1103 * and a function to process them.
1104 */
1105 static int
canon_subval(struct exifprop * prop,struct exiftags * t,struct exiftag * subtags,int (* valfun)())1106 canon_subval(struct exifprop *prop, struct exiftags *t,
1107 struct exiftag *subtags, int (*valfun)())
1108 {
1109 int i, j;
1110 u_int16_t v;
1111 struct exifprop *aprop;
1112 unsigned char *off = t->mkrmd.btiff + prop->value;
1113
1114 /* Check size of tag (first value) if we're not debugging. */
1115
1116 if (valfun && exif2byte(off, t->mkrmd.order) != 2 * prop->count) {
1117 exifwarn("Canon maker tag appears corrupt");
1118 return (FALSE);
1119 }
1120
1121 if (debug)
1122 printf("Processing %s (0x%04X) directory, %d entries\n",
1123 prop->name, prop->tag, prop->count);
1124
1125 for (i = 0; i < (int)prop->count; i++) {
1126 v = exif2byte(off + i * 2, t->mkrmd.order);
1127
1128 aprop = childprop(prop);
1129 aprop->value = (u_int32_t)v;
1130 aprop->tag = i;
1131 aprop->tagset = subtags;
1132
1133 /* Lookup property name and description. */
1134
1135 for (j = 0; subtags[j].tag < EXIF_T_UNKNOWN &&
1136 subtags[j].tag != i; j++);
1137 aprop->name = subtags[j].name;
1138 aprop->descr = subtags[j].descr;
1139 aprop->lvl = subtags[j].lvl;
1140 if (subtags[j].table)
1141 aprop->str = finddescr(subtags[j].table, v);
1142
1143 dumpprop(aprop, NULL);
1144
1145 /* Process individual values. Returns false if unknown. */
1146
1147 if (valfun && !valfun(aprop, prop, off, t)) {
1148 if (aprop->lvl != ED_UNK)
1149 continue;
1150 exifstralloc(&aprop->str, 32);
1151 snprintf(aprop->str, 31, "num %02d, val 0x%04X", i, v);
1152 }
1153 }
1154
1155 if (debug)
1156 printf("\n");
1157 return (TRUE);
1158 }
1159
1160
1161 /*
1162 * Process custom function tag values.
1163 */
1164 static void
canon_custom(struct exifprop * prop,unsigned char * off,enum byteorder o,struct exiftag * table)1165 canon_custom(struct exifprop *prop, unsigned char *off, enum byteorder o,
1166 struct exiftag *table)
1167 {
1168 int i, j = -1;
1169 const char *cn;
1170 char *cv = NULL;
1171 u_int16_t v;
1172 struct exifprop *aprop;
1173
1174 /*
1175 * Check size of tag (first value).
1176 * XXX There seems to be a problem with the D60 where it reports the
1177 * wrong size, hence the 2nd clause in the if(). Could be related
1178 * to the second value being zero?
1179 */
1180
1181 if (exif2byte(off, o) != 2 * prop->count &&
1182 exif2byte(off, o) != 2 * (prop->count - 1)) {
1183 exifwarn("Canon custom tag appears corrupt");
1184 return;
1185 }
1186
1187 if (debug)
1188 printf("Processing %s directory, %d entries\n", prop->name,
1189 prop->count);
1190
1191 for (i = 1; i < (int)prop->count; i++) {
1192 v = exif2byte(off + i * 2, o);
1193
1194 aprop = childprop(prop);
1195 aprop->value = v & 0xff;
1196 aprop->tag = v >> 8 & 0xff;
1197 aprop->tagset = table;
1198
1199 /*
1200 * Lookup function name and value. First byte is function
1201 * number; second is function value.
1202 */
1203
1204 for (j = 0; table[j].tag != EXIF_T_UNKNOWN &&
1205 table[j].tag != (v >> 8 & 0xff); j++);
1206 aprop->name = table[j].name;
1207 aprop->descr = prop->descr;
1208 aprop->lvl = table[j].lvl;
1209 if (table[j].table)
1210 cv = finddescr(table[j].table,
1211 (u_int16_t)(v & 0xff));
1212 cn = table[j].descr;
1213
1214
1215 dumpprop(aprop, NULL);
1216
1217 exifstralloc(&aprop->str, 4 + strlen(cn) +
1218 (cv ? strlen(cv) : 10));
1219
1220 if (cv && j != -1) {
1221 snprintf(aprop->str, 4 + strlen(cn) + strlen(cv),
1222 "%s - %s", cn, cv);
1223 free(cv);
1224 cv = NULL;
1225 } else {
1226 snprintf(aprop->str, 4 + strlen(cn) + 10, "%s %d - %d",
1227 cn, v >> 8 & 0xff, v & 0xff);
1228 aprop->str[3 + strlen(cn) + 10] = '\0';
1229 aprop->lvl = ED_UNK;
1230 }
1231 }
1232
1233 if (debug)
1234 printf("\n");
1235 }
1236
1237
1238 /*
1239 * Process Canon maker note tags.
1240 */
1241 void
canon_prop(struct exifprop * prop,struct exiftags * t)1242 canon_prop(struct exifprop *prop, struct exiftags *t)
1243 {
1244 unsigned char *offset;
1245 u_int16_t flmin = 0, flmax = 0, flunit = 0;
1246 u_int32_t v, w;
1247 struct exifprop *tmpprop;
1248
1249 switch (prop->tag) {
1250
1251 /* Various image data. */
1252
1253 case 0x0001:
1254 if (!canon_subval(prop, t, canon_tags01, canon_prop01))
1255 break;
1256
1257 /*
1258 * Create a new value for the lens' focal length range. If
1259 * it's not a zoom lens, we'll make it verbose (it should
1260 * match the existing focal length Exif tag).
1261 */
1262
1263 if (prop->count >= 25) {
1264 offset = t->mkrmd.btiff + prop->value;
1265 flmax = exif2byte(offset + 23 * 2, t->mkrmd.order);
1266 flmin = exif2byte(offset + 24 * 2, t->mkrmd.order);
1267 flunit = exif2byte(offset + 25 * 2, t->mkrmd.order);
1268 }
1269
1270 if (flunit && (flmin || flmax)) {
1271 tmpprop = childprop(prop);
1272 tmpprop->name = "CanonLensSz";
1273 tmpprop->descr = "Lens Size";
1274 exifstralloc(&tmpprop->str, 32);
1275
1276 if (flmin == flmax) {
1277 snprintf(tmpprop->str, 31, "%.2f mm",
1278 (float)flmax / (float)flunit);
1279 tmpprop->lvl = ED_VRB;
1280 } else {
1281 snprintf(tmpprop->str, 31, "%.2f - %.2f mm",
1282 (float)flmin / (float)flunit,
1283 (float)flmax / (float)flunit);
1284 tmpprop->lvl = ED_PAS;
1285 }
1286 }
1287 break;
1288
1289 case 0x0004:
1290 canon_subval(prop, t, canon_tags04, canon_prop04);
1291 break;
1292
1293 case 0x00a0:
1294 if (!canon_subval(prop, t, canon_tagsA0, canon_propA0))
1295 break;
1296
1297 /* Color temp is bad if white balance isn't manual. */
1298
1299 if ((tmpprop = findprop(t->props, canon_tags04, 7)))
1300 if (tmpprop->value != 9) {
1301 if ((tmpprop = findprop(prop, canon_tagsA0, 9)))
1302 tmpprop->lvl = ED_BAD;
1303 }
1304 break;
1305
1306 /* Number of actuations. */
1307
1308 case 0x0093:
1309 /*
1310 * Alas, meanings of these fields seem to differ according
1311 * to camera model. For the 1D, 1Ds, and 1D2, they are total
1312 * number of actuations. For the 20D, they're the image
1313 * number. For now, we'll make the former behavior default
1314 * and the latter an exception.
1315 */
1316
1317 if (!t->model) {
1318 exifwarn("Canon model unset; please report to author");
1319 break;
1320 }
1321
1322 if (!canon_subval(prop, t, canon_tags93, NULL))
1323 break;
1324 v = 0;
1325
1326 if (strstr(t->model, "20D")) {
1327
1328 /* Image number is in two shorts... */
1329
1330 if ((tmpprop = findprop(t->props, canon_tags93, 1))) {
1331 v = tmpprop->value >> 6;
1332 w = (tmpprop->value & 0x3f) << 8;
1333
1334 if ((tmpprop = findprop(prop, canon_tags93, 2)))
1335 w += tmpprop->value;
1336 else {
1337 v = 0;
1338 w = 0;
1339 }
1340 }
1341
1342 if (v) {
1343 tmpprop = childprop(prop);
1344 tmpprop->name = "ImgNum";
1345 tmpprop->descr = "Image Number";
1346 tmpprop->lvl = ED_IMG;
1347 exifstralloc(&tmpprop->str, 32);
1348 snprintf(tmpprop->str, 31, "%03d-%04d", v, w);
1349 }
1350 break;
1351 }
1352
1353 /* Number of acuations is in two shorts... */
1354
1355 if ((tmpprop = findprop(t->props, canon_tags93, 1))) {
1356 v = tmpprop->value * 65536;
1357
1358 if ((tmpprop = findprop(prop, canon_tags93, 2)))
1359 v += tmpprop->value;
1360 else
1361 v = 0;
1362 }
1363
1364 if (v) {
1365 tmpprop = childprop(prop);
1366 tmpprop->name = "CanonActuations";
1367 tmpprop->descr = "Camera Actuations";
1368 tmpprop->lvl = ED_IMG;
1369 tmpprop->value = v;
1370 }
1371 break;
1372
1373 /* Image number. */
1374
1375 case 0x0008:
1376 if (!prop->value)
1377 prop->lvl = ED_VRB;
1378 exifstralloc(&prop->str, 32);
1379 snprintf(prop->str, 31, "%03d-%04d", prop->value / 10000,
1380 prop->value % 10000);
1381 break;
1382
1383 /* Serial number. */
1384
1385 case 0x000c:
1386 exifstralloc(&prop->str, 11);
1387 snprintf(prop->str, 11, "%010d", prop->value);
1388 break;
1389
1390 /* Custom functions. */
1391
1392 case 0x000f:
1393 /*
1394 * Canon annoyingly reuses this tag value for different sets
1395 * of custom functions (e.g., D30/60, 10D). Therefore, we
1396 * won't try to interpret them unless we know for sure that
1397 * the camera model is supported.
1398 */
1399
1400 if (!t->model) {
1401 exifwarn("Canon model unset; please report to author");
1402 break;
1403 }
1404
1405 if (strstr(t->model, "10D"))
1406 canon_custom(prop, t->mkrmd.btiff + prop->value,
1407 t->mkrmd.order, canon_10dcustom);
1408 else if (strstr(t->model, "D30") || strstr(t->model, "D60"))
1409 canon_custom(prop, t->mkrmd.btiff + prop->value,
1410 t->mkrmd.order, canon_d30custom);
1411 else if (strstr(t->model, "20D"))
1412 canon_custom(prop, t->mkrmd.btiff + prop->value,
1413 t->mkrmd.order, canon_20dcustom);
1414 else if (strstr(t->model, "5D"))
1415 canon_custom(prop, t->mkrmd.btiff + prop->value,
1416 t->mkrmd.order, canon_5dcustom);
1417 else
1418 exifwarn2("Custom function unsupported; please "
1419 "report to author", t->model);
1420 break;
1421
1422 case 0x0090:
1423 canon_custom(prop, t->mkrmd.btiff + prop->value, t->mkrmd.order,
1424 canon_1dcustom);
1425 break;
1426
1427 /* Dump debug for tags of type short w/count > 1. */
1428
1429 default:
1430 if (prop->type == TIFF_SHORT && prop->count > 1 && debug)
1431 canon_subval(prop, t, canon_tagsunk, NULL);
1432 break;
1433 }
1434 }
1435
1436
1437 /*
1438 * Try to read Canon maker note IFDs.
1439 */
1440 struct ifd *
canon_ifd(u_int32_t offset,struct tiffmeta * md)1441 canon_ifd(u_int32_t offset, struct tiffmeta *md)
1442 {
1443
1444 return (readifds(offset, canon_tags, md));
1445 }
1446