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_sanyo.c,v 1.23 2005/07/24 22:56:27 alex Exp $";
11 #endif
12
13 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14 /* sanyo camera maker-specific routines */
15 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
16 /* The information coded here is largely due to John Hawkins as shown */
17 /* at: */
18 /* http://www.exif.org/makernotes/SanyoMakerNote.html */
19
20 /* (John even lists the JPEG thumbnail in TIFF makernotes and the */
21 /* Epson PrintIM tag!) */
22 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include "defs.h"
28 #include "datadefs.h"
29 #include "maker_datadefs.h"
30 #include "summary.h"
31 #include "maker.h"
32 #include "misc.h"
33 #include "tags.h"
34 #include "maker_extern.h"
35 #include "extern.h"
36
37 extern struct camera_id sanyo_model_id[];
38
39 /* Find the identifying number assigned to known Sanyo camera models. */
40 /* This number is used to dispatch print and interpret routines */
41 /* approopriate to the current image. */
42
43 int
sanyo_model_number(char * model,char * software)44 sanyo_model_number(char *model,char *software)
45 {
46 struct camera_id *model_id;
47 int number = NO_MODEL;
48
49 for(model_id = &sanyo_model_id[0]; model_id && model_id->name; ++model_id)
50 {
51 if(strncasecmp(model,model_id->name,model_id->namelen) == 0)
52 {
53 number = model_id->id;
54 setnoteversion(model_id->noteversion);
55 setnotetagset(model_id->notetagset); /* info only */
56 break;
57 }
58 }
59
60 return(number);
61 }
62
63 /* Dispatch a print routine based upon model */
64
65 void
print_sanyo_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)66 print_sanyo_makervalue(struct ifd_entry *entry_ptr,int make,int model,
67 char *prefix)
68 {
69 int noteversion = 0;
70
71 noteversion = getnoteversion();
72
73 if(entry_ptr && (PRINT_VALUE))
74 {
75 switch(noteversion)
76 {
77 case 1:
78 print_sanyo1_makervalue(entry_ptr,make,model,prefix);
79 sanyo1_interpret_value(entry_ptr);
80 break;
81 default:
82 print_value(entry_ptr,PREFIX);
83 break;
84 }
85 }
86 }
87
88 /* Model-specific print routine for sanyo cameras. This routine is */
89 /* responsible for picking off any direct entry tags which are */
90 /* peculiar and will not be handled properly by print_value() */
91 /* (usually UNDEFINED values which fit in the 4-byte entry value). If */
92 /* there are no such entries, this function simply calls */
93 /* print_value(). */
94
95 void
print_sanyo1_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)96 print_sanyo1_makervalue(struct ifd_entry *entry_ptr,int make,int model,
97 char *prefix)
98 {
99 if(entry_ptr && (PRINT_VALUE))
100 {
101 switch(entry_ptr->tag)
102 {
103 default:
104 print_value(entry_ptr,PREFIX);
105 break;
106 }
107 }
108 }
109
110
111 /* Dispatch a routine to decode and print offset values for sanyo */
112 /* cameras. */
113 void
print_sanyo_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_sanyo_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 sanyo1_offset_makervalue(inptr,byteorder,entry_ptr,
129 fileoffset_base,summary_entry,
130 parent_name,prefix,indent,
131 make,model,at_offset);
132 sanyo1_interpret_offset_makervalue(inptr,byteorder,entry_ptr,
133 fileoffset_base);
134 break;
135 default:
136 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
137 fileoffset_base,parent_name,prefix,indent,
138 make,model,at_offset);
139 break;
140 }
141 }
142 }
143
144 /* Model-specific routine to print UNDEFINED values found at offsets */
145 /* in sanyo makernotes. One of these may be supplied for each model */
146 /* with unique UNDEFINED tags. */
147
148 void
sanyo1_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)149 sanyo1_offset_makervalue(FILE *inptr,unsigned short byteorder,
150 struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
151 struct image_summary *summary_entry,char *parent_name,char*prefix,
152 int indent,int make,int model,int at_offset)
153 {
154 unsigned long value_offset;
155 unsigned long dumplength;
156 unsigned long count;
157 unsigned short marker;
158 unsigned long max_offset = 0;
159 char *nameoftag;
160 char *fulldirname = NULL;
161 int status = 0;
162 int chpr = 0;
163
164 if(entry_ptr)
165 {
166 nameoftag = maker_tagname(entry_ptr->tag,make,model);
167 fulldirname = splice(parent_name,".",nameoftag);
168 value_offset = fileoffset_base + entry_ptr->value;
169 count = entry_ptr->count;
170 switch(entry_ptr->tag)
171 {
172 case 0x0100: /* Jpeg Thumbnail in TIFF MakerNote */
173 if(at_offset && (PRINT_SECTION))
174 {
175 print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix);
176 extraindent(4);
177 chpr += printf("# Start of JPEG Thumbnail from MakerNote");
178 chpr += printf(" length %ld",count);
179 }
180 else if(!at_offset && (PRINT_VALUE))
181 {
182 if(!(PRINT_OFFSET))
183 chpr += printf("@%lu:%lu",value_offset,entry_ptr->count);
184 else
185 chpr += printf(":%lu", entry_ptr->count);
186 if(!(PRINT_VALUE_AT_OFFSET))
187 chpr += printf(" # UNDEFINED");
188 }
189 if((PRINT_SECTION) || (PRINT_SEGMENT))
190 chpr = newline(chpr);
191 marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset);
192 max_offset = process_jpeg_segments(inptr,value_offset,marker,
193 count,summary_entry,fulldirname,
194 prefix,indent+(SUBINDENT * 2));
195 if(at_offset)
196 {
197 if((PRINT_SECTION))
198 {
199 if((status = jpeg_status(0) == JPEG_EARLY_EOI))
200 chpr = newline(chpr);
201 jpeg_status(status);
202 print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1,
203 indent,"-");
204 extraindent(SUBINDENT);
205 chpr += printf("# End of JPEG Thumbnail from MakerNote");
206 if((PRINT_ENTRY) && !(PRINT_VALUE))
207 chpr = newline(chpr);
208 }
209 }
210 print_jpeg_status();
211 if(marker && summary_entry)
212 {
213 /* The new one is on the end of the chain */
214 if((summary_entry = last_summary_entry(summary_entry)))
215 {
216 summary_entry->filesubformat |= FILESUBFMT_MNOTE;
217 summary_entry->datatype = MAKER_IFD;
218 summary_entry->subfiletype = THUMBNAIL_TYPE;
219 }
220 }
221 /* make certain we're at the end */
222 clearerr(inptr);
223 fseek(inptr,value_offset + count,0);
224 break;
225 case 0x0e00: /* PrintIM (Epson Print Image matching) */
226 if(!at_offset && (PRINT_VALUE))
227 {
228 if(!(PRINT_OFFSET))
229 {
230 chpr += printf("@%lu:%lu",value_offset,count);
231 chpr = newline(chpr);
232 }
233 }
234 process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base,
235 count,nameoftag,parent_name,prefix,indent);
236 break;
237 case 0x0f00: /* Data */
238 if(at_offset && (PRINT_ENTRY))
239 {
240 print_tag_address(ENTRY,value_offset,indent,prefix);
241 print_makertagid(entry_ptr,23," : ",make,model);
242 chpr += printf("length %-9lu # UNDEFINED", count);
243 if(Max_undefined == 0)
244 {
245 if(chpr)
246 printred(" (not dumped, use -U)");
247 }
248 else
249 {
250 if((Max_undefined == DUMPALL) || (Max_undefined > count))
251 dumplength = count;
252 else
253 dumplength = Max_undefined;
254 chpr = newline(chpr);
255 hexdump(inptr,value_offset,count,dumplength,12,
256 indent,SUBINDENT);
257 chpr = newline(1);
258 }
259 }
260 else if(!at_offset && (PRINT_VALUE))
261 {
262 if(!(PRINT_OFFSET))
263 chpr += printf("@%lu:%lu",value_offset,entry_ptr->count);
264 else
265 chpr += printf(":%lu", entry_ptr->count);
266 if(!(PRINT_VALUE_AT_OFFSET))
267 chpr += printf(" # UNDEFINED");
268 }
269 /* make certain we're at the end */
270 fseek(inptr,value_offset + count,0);
271 break;
272 default:
273 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
274 fileoffset_base,fulldirname,prefix,indent,
275 make,model,at_offset);
276 break;
277 }
278 if(fulldirname)
279 free(fulldirname);
280 }
281 setcharsprinted(chpr);
282 }
283
284
285 /* sanyo-specific tagnames for makernotes. */
286
287 /* The tagname routine is the first place in the code path which */
288 /* requires knowledge of the note version. If the version is not */
289 /* given in the model table (e.g. the model is unknown), then switch */
290 /* code in find_maker_scheme() should have set it. This routine */
291 /* repeats the check for non-zero noteversion and is prepared to set */
292 /* the noteversion first time through, but should never need to do */
293 /* so. Noteversion should always be non-zero; it should be set to -1 */
294 /* if generic processing is required. */
295
296 char *
maker_sanyo_tagname(unsigned short tag,int model)297 maker_sanyo_tagname(unsigned short tag,int model)
298 {
299 char *tagname = CNULL;
300 int noteversion = 0;
301
302 if(((noteversion = getnoteversion()) == 0))
303 {
304 /* Need more model samples before it is safe to assume a */
305 /* default */
306 noteversion = 1;
307 setnoteversion(1);
308 }
309
310 switch(noteversion)
311 {
312 case 1:
313 tagname = maker_sanyo1_tagname(tag,model);
314 break;
315 default:
316 break;
317 }
318
319 /* If no model-specific tag is found, check "generic" tags */
320 if(tagname == NULL)
321 {
322 switch(tag)
323 {
324 case 0x0e00: tagname = "PrintIM"; break;
325 default: break;
326 }
327 }
328 return(tagname);
329 }
330
331 char *
maker_sanyo1_tagname(unsigned short tag,int model)332 maker_sanyo1_tagname(unsigned short tag,int model)
333 {
334 char *tagname = CNULL;
335
336 switch(tag)
337 {
338 case 0x0100: tagname = "JpegThumbnail"; break;
339 case 0x0200: tagname = "SpecialMode"; break;
340 case 0x0201: tagname = "Quality"; break;
341 case 0x0202: tagname = "Macro"; break;
342 case 0x0204: tagname = "DigiZoom"; break;
343 case 0x0207: tagname = "SoftwareRelease"; break;
344 case 0x0208: tagname = "PictureInfo"; break;
345 case 0x0209: tagname = "CameraID"; break;
346 case 0x020e: tagname = "SeqShotMethod"; break;
347 case 0x020f: tagname = "WideRange"; break;
348 case 0x0210: tagname = "ColorAdjMode"; break;
349 case 0x0213: tagname = "QuickShot"; break;
350 case 0x0214: tagname = "SelfTImer"; break;
351 case 0x0216: tagname = "VoiceMemo"; break;
352 case 0x0217: tagname = "RecordShutterRel"; break;
353 case 0x0218: tagname = "FlickerReduce"; break;
354 case 0x0219: tagname = "OpticalZoom"; break;
355 case 0x021b: tagname = "DigitalZoom"; break;
356 case 0x021d: tagname = "LightSourceSpecial"; break;
357 case 0x021e: tagname = "Resaved"; break;
358 case 0x021f: tagname = "SceneSelect"; break;
359 case 0x0223: tagname = "ManualFocalDist"; break;
360 case 0x0224: tagname = "SeqShotIntvl"; break;
361 case 0x0225: tagname = "FlashMode"; break;
362 case 0x0e00: tagname = "PrintIM"; break;
363 case 0x0f00: tagname = "Data"; break;
364 default: break;
365 }
366 setnotetagset(1);
367 return(tagname);
368 }
369
370
371 void
sanyo1_interpret_value(struct ifd_entry * entry_ptr)372 sanyo1_interpret_value(struct ifd_entry *entry_ptr)
373 {
374 int chpr = 0;
375
376 if(entry_ptr && (PRINT_VALUE))
377 {
378 switch(entry_ptr->tag)
379 {
380 case 0x0201: /* Quality */
381 print_startvalue();
382 /* ###%%% is this related to image size, e.g. 640x480? */
383 /* This tag is the same tag number as used by the */
384 /* Olympus, Epson, and Minolta F100, except that "super */
385 /* high" + "super fine" would give a (short) value of 34, */
386 /* which is the value used for uncompressed tiff in the */
387 /* Epson at 2048x1536. */
388 switch(entry_ptr->value & 0xff)
389 {
390 case 0: chpr += printf("very low res,"); break;
391 case 1: chpr += printf("low res,"); break;
392 case 2: chpr += printf("medium low res,"); /* 640 x 480 */ break;
393 case 3: chpr += printf("medium res,"); break;
394 case 4: chpr += printf("medium high res,"); break;
395 case 5: chpr += printf("high res,"); break;
396 case 6: chpr += printf("very high res,"); break;
397 case 7: chpr += printf("super high"); break;
398 default: printred("undefined"); break;
399 }
400 /* ###%%% is this related to compression, e.g TIFF vs */
401 /* JPEG ??? */
402 switch((entry_ptr->value >> 8) & 0xff)
403 {
404 case 0: chpr += printf(" normal"); break;
405 case 1: chpr += printf(" fine"); break;
406 case 2: chpr += printf(" super fine"); break;
407 }
408 print_endvalue();
409 break;
410 case 0x0202: /* Macro */
411 print_startvalue();
412 switch(entry_ptr->value)
413 {
414 case 0: chpr += printf("Normal"); break;
415 case 1: chpr += printf("Macro"); break;
416 case 2: chpr += printf("View"); break;
417 case 3: chpr += printf("Manual"); break;
418 default: printred("undefined"); break;
419 }
420 print_endvalue();
421 break;
422 case 0x020e: /* Sequential Shot Method */
423 print_startvalue();
424 switch(entry_ptr->value)
425 {
426 case 0: chpr += printf("none"); break;
427 case 1: chpr += printf("Standard"); break;
428 case 2: chpr += printf("Best"); break;
429 case 3: chpr += printf("Exposure Adjust"); break;
430 default: printred("undefined"); break;
431 }
432 print_endvalue();
433 break;
434 case 0x020f: /* Wide Range */
435 print_startvalue();
436 switch(entry_ptr->value)
437 {
438 case 0: chpr += printf("Off"); break;
439 case 1: chpr += printf("On"); break;
440 default: printred("undefined"); break;
441 }
442 print_endvalue();
443 break;
444 case 0x0210: /* Color Adjustment Mode */
445 print_startvalue();
446 switch(entry_ptr->value)
447 {
448 case 0: chpr += printf("Off"); break;
449 case 1: chpr += printf("On"); break;
450 default: printred("undefined"); break;
451 }
452 print_endvalue();
453 break;
454 case 0x0213: /* Quick Shot */
455 print_startvalue();
456 switch(entry_ptr->value)
457 {
458 case 0: chpr += printf("Off"); break;
459 case 1: chpr += printf("On"); break;
460 default: printred("undefined"); break;
461 }
462 print_endvalue();
463 break;
464 case 0x0214: /* Self Timer */
465 print_startvalue();
466 switch(entry_ptr->value)
467 {
468 case 0: chpr += printf("Off"); break;
469 case 1: chpr += printf("On"); break;
470 default: printred("undefined"); break;
471 }
472 print_endvalue();
473 break;
474 case 0x0216: /* Voice Memo */
475 print_startvalue();
476 switch(entry_ptr->value)
477 {
478 case 0: chpr += printf("Off"); break;
479 case 1: chpr += printf("On"); break;
480 default: printred("undefined"); break;
481 }
482 print_endvalue();
483 break;
484 case 0x0217: /* Record Shutter Release */
485 print_startvalue();
486 switch(entry_ptr->value)
487 {
488 case 0: chpr += printf("Held"); break;
489 case 1: chpr += printf("Start/Stop"); break;
490 default: printred("undefined"); break;
491 }
492 print_endvalue();
493 break;
494 case 0x0218: /* Flicker Reduce */
495 print_startvalue();
496 switch(entry_ptr->value)
497 {
498 case 0: chpr += printf("Off"); break;
499 case 1: chpr += printf("On"); break;
500 default: printred("undefined"); break;
501 }
502 print_endvalue();
503 break;
504 case 0x0219: /* Optical Zoom */
505 print_startvalue();
506 switch(entry_ptr->value)
507 {
508 case 0: chpr += printf("Disabled"); break;
509 case 1: chpr += printf("Enabled"); break;
510 default: printred("undefined"); break;
511 }
512 print_endvalue();
513 break;
514 case 0x021b: /* Digital Zoom */
515 print_startvalue();
516 switch(entry_ptr->value)
517 {
518 case 0: chpr += printf("Disabled"); break;
519 case 1: chpr += printf("Enabled"); break;
520 default: printred("undefined"); break;
521 }
522 print_endvalue();
523 break;
524 case 0x021d: /* Light Source Special */
525 print_startvalue();
526 switch(entry_ptr->value)
527 {
528 case 0: chpr += printf("Off"); break;
529 case 1: chpr += printf("On"); break;
530 default: printred("undefined"); break;
531 }
532 print_endvalue();
533 break;
534 case 0x021e: /* Resaved */
535 print_startvalue();
536 switch(entry_ptr->value)
537 {
538 case 0: chpr += printf("No"); break;
539 case 1: chpr += printf("Yes"); break;
540 default: printred("undefined"); break;
541 }
542 print_endvalue();
543 break;
544 case 0x021f: /* Scene Select */
545 print_startvalue();
546 switch(entry_ptr->value)
547 {
548 case 0: chpr += printf("Off"); break;
549 case 1: chpr += printf("Sport"); break;
550 case 2: chpr += printf("TV?"); break;
551 case 3: chpr += printf("Night"); break;
552 case 4: chpr += printf("User 1"); break;
553 case 5: chpr += printf("User 2"); break;
554 default: printred("undefined"); break;
555 }
556 print_endvalue();
557 break;
558 case 0x0224: /* Sequential Shot Interval */
559 print_startvalue();
560 switch(entry_ptr->value)
561 {
562 case 0: chpr += printf("5 frames/sec"); break;
563 case 1: chpr += printf("10 frames/sec"); break;
564 case 2: chpr += printf("15 frames/sec?"); break;
565 case 3: chpr += printf("20 frames/sec"); break;
566 default: printred("undefined"); break;
567 }
568 print_endvalue();
569 break;
570 case 0x0225: /* Flash Mode */
571 print_startvalue();
572 switch(entry_ptr->value)
573 {
574 case 0: chpr += printf("Auto"); break;
575 case 1: chpr += printf("Force"); break;
576 case 2: chpr += printf("Disabled"); break;
577 case 3: chpr += printf("Redeye"); break;
578 default: printred("undefined"); break;
579 }
580 print_endvalue();
581 break;
582
583 default:
584 break;
585 }
586 }
587 setcharsprinted(chpr);
588 }
589
590 void
sanyo1_interpret_offset_makervalue(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base)591 sanyo1_interpret_offset_makervalue(FILE *inptr,unsigned short byteorder,
592 struct ifd_entry *entry_ptr,unsigned long fileoffset_base)
593 {
594 unsigned long offset,value;
595 int chpr = 0;
596
597 if(entry_ptr && (PRINT_VALUE))
598 {
599 offset = entry_ptr->value + fileoffset_base;
600 switch(entry_ptr->tag)
601 {
602 case 0x0200: /* SpecialMode */
603 value = read_ulong(inptr,byteorder,offset);
604 print_startvalue();
605 switch(value)
606 {
607 case 0: chpr += printf("Normal"); break;
608 case 1: chpr += printf("Unkown"); break;
609 case 2: chpr += printf("Fast"); break;
610 case 3: chpr += printf("Panorama,");
611 value = read_ulong(inptr,byteorder,HERE);
612 chpr += printf("#%lu,",value);
613 value = read_ulong(inptr,byteorder,HERE);
614 switch(value)
615 {
616 case 1: chpr += printf(" Left to Right"); break;
617 case 2: chpr += printf(" Right to Left"); break;
618 case 3: chpr += printf(" Bottom to Top"); break;
619 case 4: chpr += printf(" Top to Bottom"); break;
620 default: printred(" undefined"); break;
621 }
622 break;
623 default: printred("undefined"); break;
624 }
625 print_endvalue();
626 break;
627 default:
628 break;
629 }
630 }
631 setcharsprinted(chpr);
632 }
633