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