1/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
2/*          EXIFPROBE - TIFF/JPEG/EXIF image file probe               */
3/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
4/* Copyright (C) 2002 by Duane H. Hesser. All rights reserved.        */
5/*                                                                    */
6/* See the file LICENSE.EXIFPROBE for terms of use.                   */
7/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
8
9#ifndef WALL
10static char *ModuleId = "@(#) $Id: maker_template,v 1.4 2005/01/27 02:27:32 alex Exp $";
11#endif
12
13/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14/* THIS_MAKE camera maker-specific routines.                          */
15/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
16/* Template file for maker-specific routines.                         */
17/* 1. Copy this to a file maker_XXX.c and edit as necessary.          */
18/*    a. Replace the string "THIS_MAKE" with the maker name.          */
19/*    b. assign numbers to make and model names as reqd in maker.h    */
20/*       (required iff more than one style of MakerNote exists across */
21/*       models)
22/*    c. edit THIS_MAKE_model_number to decode the MODEL, using the   */
23/*       SOFTWARE name as well if necessary.  The returned number     */
24/*       will be used to select the print and interpret routines for  */
25/*       the model.                                                   */
26/*    d. Edit print_THIS_MAKE_value() and                             */
27/*       print_THIS_MAKE_value_at_offset() to select the correct      */
28/*       print and interpret routines for each note style             */
29/*    e. code the specific print and interpret routines.              */
30/*    f. remove any unnecessary template material.                    */
31/* 2. Move the function prototypes to extern.h                        */
32/* 3. Edit print_maker.c to add a case for THIS_MAKER to              */
33/*    print_makervalue() and print_offset_makervalue().               */
34/* 4. Edit maker_generic.c to add a case for THIS_MAKER to            */
35/*    maker_number() and model_number().                              */
36/* 5. Edit maker_tagnames.c to add a case for THIS_MAKER to           */
37/*    maker_tagname().                                                */
38/* 6. Replace this comment with something appropriate.                */
39/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
40
41#include <stdio.h>
42#include <string.h>
43#include "defs.h"
44#include "extern.h"
45#include "misc.h"
46#include "maker.h"
47
48/* Find the id number assigned to known THIS_MAKE camera models.      */
49/* This number is used to dispatch print and interpret routines       */
50/* apporopriate to the current image.                                 */
51
52int
53THIS_MAKE_model_number(char *model,char *software)
54{
55	int number = GENERIC;
56
57	switch(*model)
58	{
59		default:
60			number = GENERIC;
61			break;
62	}
63	return(number);
64}
65
66/* Dispatch a print routine based upon model                          */
67
68void
69print_THIS_MAKE_makervalue(struct ifd_entry *entry_ptr,int make, int model,
70					char *prefix)
71{
72
73	switch(model)
74	{
75		case MODEL1:
76			print_THIS_MAKE1_makervalue(entry_ptr,make,model,prefix);
77			THIS_MAKE1_interpret_value(entry_ptr);
78			break;
79		case MODEL2:
80		case MODEL3:
81			print_THIS_MAKE2_makervalue(entry_ptr,make,model,prefix);
82			THIS_MAKE2_interpret_value(entry_ptr);
83			break;
84		case GENERIC:
85		default:
86			print_THIS_MAKE1_makervalue(entry_ptr,make,model,prefix);
87			THIS_MAKE2_interpret_value(entry_ptr);
88			break;
89	}
90}
91
92/* Model-specific print routine for THIS_MAKE cameras. This routine is    */
93/* responsible for picking off any direct entry tags which are        */
94/* peculiar and will not be handled properly by print_value()         */
95/* (usually UNDEFINED values which fit in the 4-byte entry value). If */
96/* there are no such entries, this function simply calls              */
97/* print_value().                                                     */
98
99void
100print_THIS_MAKE1_makervalue(struct ifd_entry *entry_ptr,int make, int model,
101					char *prefix)
102{
103	if(entry_ptr)
104	{
105		switch(entry_ptr->tag)
106		{
107			/* pick off values that need special handling in cases    */
108            /* here                                                   */
109			default:
110				print_value(entry_ptr,PREFIX);
111				break;
112		}
113	}
114}
115
116/* Dispatch a routine to decode and print offset values for THIS_MAKE   */
117/* cameras.                                                           */
118
119void
120print_THIS_MAKE_offset_makervalue(FILE *inptr,unsigned short byteorder,
121	struct ifd_entry *entry_ptr,unsigned long offset_ref,char *prefix,
122	int indent,int addrwidth,int make,int model,int at_offset)
123{
124
125	switch(model)
126	{
127		case MODEL1:
128			THIS_MAKE1_offset_makervalue(inptr,byteorder,entry_ptr,
129										offset_ref,prefix,indent,
130										addrwidth,make,model,int at_offset);
131			break;
132		case MODEL2:
133		default:
134			THIS_MAKE2_offset_makervalue(inptr,byteorder,entry_ptr,
135										offset_ref,prefix,indent,
136										addrwidth,make,model,int at_offset);
137			break;
138	}
139}
140
141/* Model-specific routine to print values found at an offset from the */
142/* IFD entry in THIS_MAKE makernotes.                                     */
143
144/* One of these may be supplied for each model if necessary           */
145
146void
147THIS_MAKE1_offset_makervalue(FILE *inptr,unsigned short byteorder,
148	struct ifd_entry *entry_ptr,unsigned long offset_ref,char *prefix,
149	int indent,int addrwidth,int make,int model,int at_offset)
150{
151	unsigned long value_offset;
152	unsigned long dumplength;
153	unsigned short marker;
154	char *nameoftag;
155
156	if(entry_ptr)
157	{
158		nameoftag = maker_tagname(entry_ptr->tag,make,model);
159		value_offset = offset_ref + entry_ptr->value;
160
161		/* Pick off UNDEFINED tag types. The rest can be handled by   */
162        /* the generic routine.                                       */
163		switch(entry_ptr->tag)
164		{
165			case 0x0100: /* JPEG Thumbnail in TIFF MakerNote          */
166				print_tag_address(value_offset,indent,prefix,addrwidth);
167				putindent(SUBINDENT);
168				printf("Start of %s length %ld\n",nameoftag,entry_ptr->count);
169				marker = read_imagemarker(inptr,value_offset);
170				(void)process_jpeg_segments(inptr,value_offset,
171											marker,entry_ptr->count,indent+2,
172											addrwidth);
173				STARTCOLOR(MAKER_COLOR);
174				print_tag_address(value_offset + entry_ptr->count,indent,"-",
175											addrwidth);
176				putindent(SUBINDENT);
177				printf("End of %s",nameoftag);
178				/* make certain we're at the end unless 'inptr' bad   */
179				fseek(inptr,value_offset + entry_ptr->count,0);
180				break;
181			case 0x0e00: /* PrintIM (Epson Print Image matching)      */
182			case 0x0f00: /* Data                                      */
183				print_tag_address(value_offset,indent,prefix,addrwidth);
184				putindent(SUBINDENT);
185				printf("%s: length %lu",nameoftag,entry_ptr->count);
186				if(Max_undefined == 0)
187					printf(" (not dumped, use -U)");
188				else
189				{
190					if((Max_undefined == DUMPALL)
191						|| (Max_undefined > entry_ptr->count))
192							dumplength = entry_ptr->count;
193					else
194						dumplength = Max_undefined;
195					putchar('\n');
196					hexdump(inptr,value_offset,entry_ptr->count,dumplength,12,
197								indent,SUBINDENT,addrwidth);
198				}
199				/* make certain we're at the end unless 'inptr' bad   */
200				fseek(inptr,value_offset + entry_ptr->count,0);
201				break;
202			default:
203				print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
204										offset_ref,prefix,indent,
205										addrwidth,make,model,at_offset);
206				break;
207		}
208	}
209}
210
211void
212THIS_MAKE2_offset_makervalue(FILE *inptr,unsigned short byteorder,
213	struct ifd_entry *entry_ptr,unsigned long offset_ref,char *prefix,
214	int indent,int addrwidth,int make,int model,int at_offset)
215{
216	unsigned long value_offset;
217	unsigned long dumplength;
218	unsigned short marker;
219	char *nameoftag;
220
221	if(entry_ptr)
222	{
223		nameoftag = maker_tagname(entry_ptr->tag,make,model);
224		value_offset = offset_ref + entry_ptr->value;
225		switch(entry_ptr->tag)
226		{
227			case 0x0100: /* JPEG Thumbnail in TIFF MakerNote, for     */
228				print_tag_address(value_offset,indent,prefix,addrwidth);
229				putindent(SUBINDENT);
230				printf("Start of %s length %ld\n",nameoftag,entry_ptr->count);
231				marker = read_imagemarker(inptr,value_offset);
232				(void)process_jpeg_segments(inptr,value_offset,
233											marker,entry_ptr->count,indent+2,
234											addrwidth);
235				STARTCOLOR(MAKER_COLOR);
236				print_tag_address(value_offset + entry_ptr->count,indent,"-",
237											addrwidth);
238				putindent(SUBINDENT);
239				printf("End of %s",nameoftag);
240				/* make certain we're at the end unless 'inptr' bad   */
241				fseek(inptr,value_offset + entry_ptr->count,0);
242				break;
243			case 0x0010: /* Data                                      */
244				print_tag_address(value_offset,indent,prefix,addrwidth);
245				putindent(SUBINDENT);
246				printf("%s: length %lu",nameoftag,entry_ptr->count);
247				if(Max_undefined == 0)
248					printf(" (not dumped, use -U)");
249				else
250				{
251					if((Max_undefined == DUMPALL)
252						|| (Max_undefined > entry_ptr->count))
253							dumplength = entry_ptr->count;
254					else
255						dumplength = Max_undefined;
256					putchar('\n');
257					hexdump(inptr,value_offset,entry_ptr->count,dumplength,12,
258								indent,SUBINDENT,addrwidth);
259				}
260				/* make certain we're at the end          */
261				fseek(inptr,value_offset + entry_ptr->count,0);
262				break;
263			default:
264				print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
265										offset_ref,prefix,indent,
266										addrwidth,make,model,int at_offset);
267				break;
268		}
269	}
270}
271
272char *
273maker_THIS_MAKE_tagname(unsigned short tag,int model)
274{
275	char *tagname = (char *)0;
276
277	/* Check specific models first                                    */
278	switch(model)
279	{
280		case MODEL1:
281			tagname = maker_THIS_MAKE1_tagname(tag,model);
282			break;
283		case MODEL2:
284			tagname = maker_THIS_MAKE2_tagname(tag,model);
285			break;
286		default:
287			/* Call a specific routine here, or leave it blank to     */
288            /* just call the generic tag maker.                       */
289			break;
290	}
291	return(tagname);
292}
293
294/* Tags for the older cameras.                                        */
295
296char *
297maker_THIS_MAKE1_tagname(unsigned short tag,int model)
298{
299	char *tagname = (char *)0;
300
301	switch(tag)
302	{
303		/* ###%%% be sure to change these                             */
304		case 0x0003: tagname = "Quality"; break;
305		case 0x0004: tagname = "Color Mode"; break;
306		case 0x0005: tagname = "Image Adjustment"; break;
307		case 0x0006: tagname = "ISO Setting"; break;
308		case 0x0007: tagname = "White Balance"; break;
309		case 0x0008: tagname = "Focus"; break;
310		case 0x000a: tagname = "Digital Zoom"; break;
311		case 0x000b: tagname = "LensConverter"; break;
312		case 0x0f00: tagname = "Data"; break;
313		case 0x0100: tagname = "JPEG Thumbnail"; break;
314			default: break;
315	}
316	return(tagname);
317}
318
319
320char *
321maker_THIS_MAKE2_tagname(unsigned short tag,int model)
322{
323	char *tagname = (char *)0;
324
325	switch(tag)
326	{
327		/* ###%%% be sure to change these                             */
328		case 0x0001: tagname = "Version"; break;
329		case 0x0002: tagname = "ISO Setting"; break;
330		case 0x0003: tagname = "Color Mode"; break;
331		case 0x0004: tagname = "Quality"; break;
332		case 0x0005: tagname = "White Balance"; break;
333		case 0x0006: tagname = "Image Sharpening"; break;
334		case 0x0007: tagname = "Focus Mode"; break;
335		case 0x0008: tagname = "Flash Setting"; break;
336		case 0x000f: tagname = "ISO Selection"; break;
337		case 0x0010: tagname = "Data"; break;
338		case 0x0080: tagname = "Image Adjustment"; break;
339		case 0x0082: tagname = "Adapter"; break;
340		case 0x0085: tagname = "Manual Focus Distance"; break;
341		case 0x0086: tagname = "Digital Zoom"; break;
342		case 0x0088: tagname = "Auto Focus Position"; break;
343		case 0x0e00: tagname = "PrintIM Data"; break;
344		case 0x0100: tagname = "JPEG Thumbnail"; break;
345		default: break;
346	}
347	return(tagname);
348}
349
350void
351THIS_MAKE1_interpret_value(struct ifd_entry *entry_ptr)
352{
353	switch(entry_ptr->tag)
354	{
355		case 0xQUALITY:	/* Quality */
356			switch(entry_ptr->value)
357			{
358				default: printred(" [???]",MAKER_COLOR); break;
359			}
360			break;
361		case 0xCOLOR:	/* Color Mode */
362			if(entry_ptr->value == COLOR)
363				printf(" [color]");
364			else if(entry_ptr->value == MONOCHROME)
365				printf(" [monochrome]");
366			else
367				printred(" [???]",MAKER_COLOR);
368			break;
369		case 0xADJUST:	/* Image Adjustment */
370			switch(entry_ptr->value)
371			{
372				default:
373					printred(" [???]",MAKER_COLOR);
374					break;
375			}
376			break;
377		default:
378			break;
379	}
380}
381
382void
383THIS_MAKE2_interpret_value(struct ifd_entry *entry_ptr)
384{
385
386	switch(entry_ptr->tag)
387	{
388			case 0x000b:
389			case 0x000d:
390			case 0x000e:
391			case 0x0011:
392			case 0x0083:
393			case 0x0087:
394			case 0x0089:
395			case 0x008a:
396			case 0x008b:
397			case 0x0092:
398			case 0x0094:
399				printred(" [???]",MAKER_COLOR);
400				break;
401			default:
402				printred(" [???]",MAKER_COLOR);
403				break;
404	}
405}
406