1 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
2 /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */
3 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
4 /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */
5 /* */
6 /* See the file LICENSE.EXIFPROBE for terms of use. */
7 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
8
9 #ifndef lint
10 static char *ModuleId = "@(#) $Id: maker_panasonic.c,v 1.5 2005/07/24 22:56:27 alex Exp $";
11 #endif
12
13 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14 /* panasonic camera maker-specific routines */
15 /* panasonic support contributed by Tom Hughes <tom@compton.nu> */
16 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
17 /* The information coded here is derived from experimentation with */
18 /* a Panasonic DMC-FZ10 and from looking at a few images from other */
19 /* cameras found on various web sites. */
20 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include "defs.h"
26 #include "datadefs.h"
27 #include "maker_datadefs.h"
28 #include "summary.h"
29 #include "maker.h"
30 #include "misc.h"
31 #include "tags.h"
32 #include "maker_extern.h"
33 #include "extern.h"
34
35 extern struct camera_id panasonic_model_id[];
36
37 /* Find the identifying number assigned to known Panasonic camera */
38 /* models. This number is used to dispatch print and interpret */
39 /* routines approopriate to the current image. */
40
41 int
panasonic_model_number(char * model,char * software)42 panasonic_model_number(char *model,char *software)
43 {
44 struct camera_id *model_id;
45 int number = NO_MODEL;
46
47 for(model_id = &panasonic_model_id[0]; model_id && model_id->name; ++model_id)
48 {
49 if(strncasecmp(model,model_id->name,model_id->namelen) == 0)
50 {
51 number = model_id->id;
52 setnoteversion(model_id->noteversion);
53 setnotetagset(model_id->notetagset); /* info only */
54 break;
55 }
56 }
57 return(number);
58 }
59
60
61 /* Dispatch a print routine for direct values in Panasonic cameras, */
62 /* based upon model */
63
64 void
print_panasonic_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)65 print_panasonic_makervalue(struct ifd_entry *entry_ptr,int make,int model,
66 char *prefix)
67 {
68 int noteversion = 0;
69
70 noteversion = getnoteversion();
71
72 if(entry_ptr && (PRINT_VALUE))
73 {
74 switch(noteversion)
75 {
76 case 1:
77 print_panasonic1_makervalue(entry_ptr,make,model,prefix);
78 panasonic1_interpret_value(entry_ptr);
79 break;
80 default:
81 print_value(entry_ptr,PREFIX);
82 break;
83 }
84 }
85 }
86
87 /* Model-specific print routine for Panasonic cameras. This routine */
88 /* is responsible for picking off any direct entry tags which are */
89 /* peculiar and will not be handled properly by print_value() */
90 /* (usually UNDEFINED values which fit in the 4-byte entry value). If */
91 /* there are no such entries, this function simply calls */
92 /* print_value(). */
93
94 void
print_panasonic1_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)95 print_panasonic1_makervalue(struct ifd_entry *entry_ptr,int make,int model,
96 char *prefix)
97 {
98 if(entry_ptr && (PRINT_VALUE))
99 {
100 switch(entry_ptr->tag)
101 {
102 default:
103 print_value(entry_ptr,PREFIX);
104 break;
105 }
106 }
107 }
108
109
110 /* Dispatch a routine to decode and print offset values for Panasonic */
111 /* cameras. */
112
113 void
print_panasonic_offset_makervalue(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)114 print_panasonic_offset_makervalue(FILE *inptr,unsigned short byteorder,
115 struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
116 struct image_summary *summary_entry,char *parent_name,char *prefix,
117 int indent,int make,int model,int at_offset)
118 {
119 int noteversion = 0;
120
121 noteversion = getnoteversion();
122
123 if(entry_ptr)
124 {
125 switch(noteversion)
126 {
127 case 1:
128 panasonic1_offset_makervalue(inptr,byteorder,entry_ptr,
129 fileoffset_base,summary_entry,
130 parent_name,prefix,indent,
131 make,model,at_offset);
132
133 break;
134 default:
135 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
136 fileoffset_base,parent_name,prefix,indent,
137 make,model,at_offset);
138 break;
139 }
140 }
141 }
142
143 /* Model-specific routine to print UNDEFINED values found at offsets */
144 /* in Panasonic makernotes. */
145
146 void
panasonic1_offset_makervalue(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)147 panasonic1_offset_makervalue(FILE *inptr,unsigned short byteorder,
148 struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
149 struct image_summary *summary_entry,char *parent_name,char *prefix,
150 int indent,int make,int model,int at_offset)
151 {
152 unsigned long value_offset,count;
153 char *nameoftag;
154 char *fulldirname = NULL;
155 int chpr = 0;
156
157 if(entry_ptr)
158 {
159 nameoftag = maker_tagname(entry_ptr->tag,make,model);
160 fulldirname = splice(parent_name,".",nameoftag);
161 value_offset = fileoffset_base + entry_ptr->value;
162 count = entry_ptr->count;
163 switch(entry_ptr->tag)
164 {
165 case 0x0e00: /* PrintIM (Epson Print Image matching) */
166 if(!at_offset && (PRINT_VALUE))
167 {
168 if(!(PRINT_OFFSET))
169 {
170 chpr += printf("@%lu:%lu",value_offset,count);
171 chpr = newline(chpr);
172 }
173 }
174 process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base,
175 count,nameoftag,parent_name,prefix,indent);
176 break;
177 default:
178 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
179 fileoffset_base,parent_name,prefix,indent,
180 make,model,at_offset);
181 break;
182 }
183 if(fulldirname)
184 free(fulldirname);
185 }
186 setcharsprinted(chpr);
187 }
188
189
190 /* Panasonic-specific tagnames for makernotes. */
191
192 /* The tagname routine is the first place in the code path which */
193 /* requires knowledge of the note version. If the version is not */
194 /* given in the model table (e.g. the model is unknown), then switch */
195 /* code in find_maker_scheme() should have set it. This routine */
196 /* repeats the check for non-zero noteversion and is prepared to set */
197 /* the noteversion first time through, but should never need to do */
198 /* so. Noteversion should always be non-zero; it should be set to -1 */
199 /* if generic processing is required. */
200
201 char *
maker_panasonic_tagname(unsigned short tag,int model)202 maker_panasonic_tagname(unsigned short tag,int model)
203 {
204 char *tagname = (char *)0;
205 int noteversion = 0;
206
207 /* Should have to do this only once, and only for unrecognized */
208 /* models. If the model is recognized (or the user has forced a */
209 /* noteversion) noteversion will already be set. */
210 if((noteversion = getnoteversion()) == 0)
211 {
212
213 noteversion = 1;
214 setnoteversion(1);
215 }
216
217 switch(noteversion)
218 {
219 case 1:
220 tagname = maker_panasonic1_tagname(tag,model);
221 break;
222 default:
223 break;
224 }
225 return(tagname);
226 }
227
228 char *
maker_panasonic1_tagname(unsigned short tag,int model)229 maker_panasonic1_tagname(unsigned short tag,int model)
230 {
231 char *tagname = CNULL;
232
233 switch(tag)
234 {
235 case 0x0001: tagname = "Quality"; break;
236 case 0x0003: tagname = "WhiteBalance"; break;
237 case 0x0007: tagname = "FocusMode"; break;
238 case 0x000f: tagname = "SpotMode"; break;
239 case 0x001a: tagname = "StabilizerMode"; break;
240 case 0x001c: tagname = "Macro"; break;
241 case 0x001f: tagname = "PictureMode"; break;
242 case 0x0020: tagname = "Audio"; break;
243 case 0x0023: tagname = "WhiteBalanceAdjust"; break;
244 case 0x0024: tagname = "FlashStrength"; break;
245 case 0x0028: tagname = "ColorMode"; break;
246 case 0x002c: tagname = "Contrast"; break;
247 case 0x002d: tagname = "NoiseReduction"; break;
248 case 0x0e00: tagname = "PrintIM"; break;
249 default: break;
250 }
251 setnotetagset(1);
252 return(tagname);
253 }
254
255
256 /* Report the "meaning" of tag values found at offsets in a Panasonic */
257 /* MakerNote IFD entry (not at an offset). */
258
259 void
panasonic1_interpret_value(struct ifd_entry * entry_ptr)260 panasonic1_interpret_value(struct ifd_entry *entry_ptr)
261 {
262 switch(entry_ptr->tag)
263 {
264 case 0x0001: /* Quality */
265 print_startvalue();
266 switch(entry_ptr->value)
267 {
268 case 2: printf("Fine"); break;
269 case 3: printf("Standard"); break;
270 default: printred("undefined"); break;
271 }
272 print_endvalue();
273 break;
274 case 0x0003: /* White Balance */
275 print_startvalue();
276 switch(entry_ptr->value)
277 {
278 case 1: printf("Auto"); break;
279 case 2: printf("Daylight"); break;
280 case 3: printf("Cloudy"); break;
281 case 4: printf("Halogen"); break;
282 case 5: printf("Manual"); break;
283 case 8: printf("Flash"); break;
284 default: printred("undefined"); break;
285 }
286 print_endvalue();
287 break;
288 case 0x0007: /* Focus Mode */
289 print_startvalue();
290 switch(entry_ptr->value)
291 {
292 case 1: printf("Auto"); break;
293 case 2: printf("Manual"); break;
294 default: printred("undefined"); break;
295 }
296 print_endvalue();
297 break;
298 case 0x000f: /* Spot Mode */
299 print_startvalue();
300 switch(entry_ptr->value)
301 {
302 case 1: printf("Spot"); break;
303 case 16: printf("1 Area"); break;
304 case 256: printf("9 Area/On"); break;
305 case 4096: printf("3 Area/Off"); break;
306 default: printred("undefined"); break;
307 }
308 print_endvalue();
309 break;
310 case 0x001a: /* Stabilizer Mode */
311 print_startvalue();
312 switch(entry_ptr->value)
313 {
314 case 2: printf("Mode 1"); break;
315 case 3: printf("Off"); break;
316 case 4: printf("Mode 2"); break;
317 default: printred("undefined"); break;
318 }
319 print_endvalue();
320 break;
321 case 0x001c: /* Macro */
322 print_startvalue();
323 switch(entry_ptr->value)
324 {
325 case 1: printf("On"); break;
326 case 2: printf("Off"); break;
327 default: printred("undefined"); break;
328 }
329 print_endvalue();
330 break;
331 case 0x001f: /* Picture Mode */
332 print_startvalue();
333 switch(entry_ptr->value)
334 {
335 case 2: printf("Portrait"); break;
336 case 3: printf("Scenery"); break;
337 case 4: printf("Sports"); break;
338 case 5: printf("Night Portrait"); break;
339 case 6: printf("Program"); break;
340 case 7: printf("Aperture Priority"); break;
341 case 8: printf("Shutter Priority"); break;
342 case 9: printf("Macro"); break;
343 case 11: printf("Manual"); break;
344 case 13: printf("Panning"); break;
345 case 18: printf("Fireworks"); break;
346 case 19: printf("Party"); break;
347 case 20: printf("Snow"); break;
348 case 21: printf("Night Scenery"); break;
349 default: printred("undefined");
350 }
351 print_endvalue();
352 break;
353 case 0x0020: /* Audio */
354 print_startvalue();
355 switch(entry_ptr->value)
356 {
357 case 1: printf("Yes"); break;
358 case 2: printf("No"); break;
359 default: printred("undefined"); break;
360 }
361 print_endvalue();
362 break;
363 case 0x0023: /* White Balance Adjust */
364 print_startvalue();
365 switch(entry_ptr->value)
366 {
367 case 0xfffb: printf("-5"); break;
368 case 0xfffc: printf("-4"); break;
369 case 0xfffd: printf("-3"); break;
370 case 0xfffe: printf("-2"); break;
371 case 0xffff: printf("-1"); break;
372 case 0x0000: printf("0"); break;
373 case 0x0001: printf("+1"); break;
374 case 0x0002: printf("+2"); break;
375 case 0x0003: printf("+3"); break;
376 case 0x0004: printf("+4"); break;
377 case 0x0005: printf("+5"); break;
378 default: printred("undefined"); break;
379 }
380 print_endvalue();
381 break;
382 case 0x0024: /* Flash Strength */
383 print_startvalue();
384 switch(entry_ptr->value)
385 {
386 case 0xfffa: printf("-2 EV"); break;
387 case 0xfffb: printf("-1.67 EV"); break;
388 case 0xfffc: printf("-1.33 EV"); break;
389 case 0xfffd: printf("-1 EV"); break;
390 case 0xfffe: printf("-0.67 EV"); break;
391 case 0xffff: printf("-0.33 EV"); break;
392 case 0x0000: printf("0 EV"); break;
393 case 0x0001: printf("+0.33 EV"); break;
394 case 0x0002: printf("+0.67 EV"); break;
395 case 0x0003: printf("+1 EV"); break;
396 case 0x0004: printf("+1.33 EV"); break;
397 case 0x0005: printf("+1.67 EV"); break;
398 case 0x0006: printf("+2 EV"); break;
399 default: printred("undefined"); break;
400 }
401 print_endvalue();
402 break;
403 case 0x0028: /* Color Mode */
404 print_startvalue();
405 switch(entry_ptr->value)
406 {
407 case 1: printf("Off"); break;
408 case 2: printf("Warm"); break;
409 case 3: printf("Cool"); break;
410 case 4: printf("Black/White"); break;
411 case 5: printf("Sepia"); break;
412 default: printred("undefined"); break;
413 }
414 print_endvalue();
415 break;
416 case 0x002c: /* Contrast */
417 print_startvalue();
418 switch(entry_ptr->value)
419 {
420 case 0: printf("Standard"); break;
421 case 1: printf("Low"); break;
422 case 2: printf("High"); break;
423 default: printred("undefined"); break;
424 }
425 print_endvalue();
426 break;
427 case 0x002d: /* Noise Reduction */
428 print_startvalue();
429 switch(entry_ptr->value)
430 {
431 case 0: printf("Standard"); break;
432 case 1: printf("Low"); break;
433 case 2: printf("High"); break;
434 default: printred("undefined"); break;
435 }
436 print_endvalue();
437 break;
438 default:
439 break;
440 }
441 }
442