1 /*
2  * Copyright (c) 2003, 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: sanyo.c,v 1.4 2004/12/23 20:38:52 ejohnst Exp $
33  */
34 
35 /*
36  * Exif tag definitions for Sanyo maker notes.
37  * Developed from http://www.exif.org/makernotes/SanyoMakerNote.html.
38  *
39  */
40 
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 
45 #include "makers.h"
46 
47 
48 /* Macro mode. */
49 
50 static struct descrip sanyo_macro[] = {
51 	{ 0,	"Normal" },
52 	{ 1,	"Macro" },
53 	{ -1,	"Unknown" },
54 };
55 
56 
57 /* Quality. */
58 
59 static struct descrip sanyo_quality[] = {
60 	{ 0,	"Normal" },
61 	{ 1,	"Fine" },
62 	{ 2,	"Superfine" },
63 	{ -1,	"Unknown" },
64 };
65 
66 
67 /* Resolution. */
68 
69 static struct descrip sanyo_res[] = {
70 	{ 0,	"Very Low Resolution" },
71 	{ 1,	"Low Resolution" },
72 	{ 2,	"Medium Low Resolution" },
73 	{ 3,	"Medium Resolution" },
74 	{ 4,	"Medium High Resolution" },
75 	{ 5,	"High Resolution" },
76 	{ 6,	"Very High Resolution" },
77 	{ 7,	"Super High Resolution" },
78 	{ -1,	"Unknown Resolution" },
79 };
80 
81 
82 /* Sequential shot method. */
83 
84 static struct descrip sanyo_seqshot[] = {
85 	{ 0,	"None" },
86 	{ 1,	"Standard" },
87 	{ 2,	"Best" },
88 	{ 3,	"Adjust Exposure" },
89 	{ -1,	"Unknown" },
90 };
91 
92 
93 /* Boolean value. */
94 
95 static struct descrip sanyo_offon[] = {
96 	{ 0,	"Off" },
97 	{ 1,	"On" },
98 	{ -1,	"Unknown" },
99 };
100 
101 
102 /* Record shutter release. */
103 
104 static struct descrip sanyo_shutter[] = {
105 	{ 0,	"Record While Held" },
106 	{ 1,	"Press to Start, Stop" },
107 	{ -1,	"Unknown" },
108 };
109 
110 
111 /* Enabled/disabled value. */
112 
113 static struct descrip sanyo_toggle[] = {
114 	{ 0,	"Disabled" },
115 	{ 1,	"Enabled" },
116 	{ -1,	"Unknown" },
117 };
118 
119 
120 /* Yes/no value. */
121 
122 static struct descrip sanyo_noyes[] = {
123 	{ 0,	"No" },
124 	{ 1,	"Yes" },
125 	{ -1,	"Unknown" },
126 };
127 
128 
129 /* Scene selection. */
130 
131 static struct descrip sanyo_scene[] = {
132 	{ 0,	"Off" },
133 	{ 1,	"Sport" },
134 	{ 2,	"TV" },
135 	{ 3,	"Night" },
136 	{ 4,	"User 1" },
137 	{ 5,	"User 2" },
138 	{ -1,	"Unknown" },
139 };
140 
141 
142 /* Sequential shot interval. */
143 
144 static struct descrip sanyo_interval[] = {
145 	{ 0,	"5 frames/sec" },
146 	{ 1,	"10 frames/sec" },
147 	{ 2,	"15 frames/sec" },
148 	{ 3,	"20 frames/sec" },
149 	{ -1,	"Unknown" },
150 };
151 
152 
153 /* Flash mode. */
154 
155 static struct descrip sanyo_flash[] = {
156 	{ 0,	"Auto" },
157 	{ 1,	"Force" },
158 	{ 2,	"Disabled" },
159 	{ 3,	"Red-Eye" },
160 	{ -1,	"Unknown" },
161 };
162 
163 
164 /* Maker note IFD tags. */
165 
166 static struct exiftag sanyo_tags[] = {
167 	{ 0x0100, TIFF_UNKN, 0, ED_UNK, "SanyoThumb",
168 	  "JPEG Thumbnail", NULL },
169 	{ 0x0200, TIFF_LONG, 3, ED_VRB, "SanyoShootMode",
170 	  "Shooting Mode", NULL },
171 	{ 0x0201, TIFF_SHORT, 1, ED_IMG, "SanyoQuality",
172 	  "Quality Setting", NULL },
173 	{ 0x0202, TIFF_SHORT, 1, ED_IMG, "SanyoMacroMode",
174 	  "Macro Mode", sanyo_macro },
175 	{ 0x0204, TIFF_RTNL, 1, ED_IMG, "SanyoDigiZoom",
176 	  "Digital Zoom", NULL },
177 	{ 0x0207, TIFF_ASCII, 5, ED_IMG, "SanyoFirmware",
178 	  "Firmware Version", NULL },
179 	{ 0x0208, TIFF_ASCII, 52, ED_IMG, "SanyoPicInfo",
180 	  "Picture Info", NULL },
181 	{ 0x0209, TIFF_UNKN, 32, ED_UNK, "SanyoCameraID",
182 	  "Camera ID", NULL },
183 	{ 0x020e, TIFF_SHORT, 1, ED_IMG, "SanyoSeqShot",
184 	  "Sequential Shot Method", sanyo_seqshot },
185 	{ 0x020f, TIFF_SHORT, 1, ED_IMG, "SanyoWideRange",
186 	  "Wide Range", sanyo_offon },
187 	{ 0x0210, TIFF_SHORT, 1, ED_IMG, "SanyoColorAdjust",
188 	  "Color Adjustment", NULL },
189 	{ 0x0213, TIFF_SHORT, 1, ED_IMG, "SanyoQuickShot",
190 	  "Quick Shot", sanyo_offon },
191 	{ 0x0214, TIFF_SHORT, 1, ED_IMG, "SanyoSelfTime",
192 	  "Self Timer", sanyo_offon },
193 	{ 0x0216, TIFF_SHORT, 1, ED_IMG, "SanyoVoiceMemo",
194 	  "Voice Memo", sanyo_offon },
195 	{ 0x0217, TIFF_SHORT, 1, ED_IMG, "SanyoRecShutter",
196 	  "Record Shutter Release", sanyo_shutter },
197 	{ 0x0218, TIFF_SHORT, 1, ED_IMG, "SanyoFlicker",
198 	  "Flicker Reduce", sanyo_offon },
199 	{ 0x0219, TIFF_SHORT, 1, ED_IMG, "SanyoOpticalZoom",
200 	  "Optical Zoom", sanyo_toggle },
201 	{ 0x021b, TIFF_SHORT, 1, ED_IMG, "SanyoDigiZoom",
202 	  "Digital Zoom", sanyo_toggle },
203 	{ 0x021d, TIFF_SHORT, 1, ED_IMG, "SanyoLightSrc",
204 	  "Special Light Source", sanyo_offon },
205 	{ 0x021e, TIFF_SHORT, 1, ED_IMG, "SanyoResaved",
206 	  "Image Re-saved", sanyo_noyes },
207 	{ 0x021f, TIFF_SHORT, 1, ED_IMG, "SanyoScene",
208 	  "Scene Selection", sanyo_scene },
209 	{ 0x0223, TIFF_SHORT, 1, ED_IMG, "SanyoFocalDist",
210 	  "Focal Distance", NULL },
211 	{ 0x0224, TIFF_SHORT, 1, ED_IMG, "SanyoSeqInterval",
212 	  "Sequential Shot Interval", sanyo_interval },
213 	{ 0x0225, TIFF_SHORT, 1, ED_IMG, "SanyoFlash",
214 	  "Flash Mode", sanyo_flash },
215 	{ 0x0e00, TIFF_UNKN, 0, ED_UNK, "SanyoPrintIM",
216 	  "Print IM Flags", NULL },
217 	{ 0x0f00, TIFF_UNKN, 0, ED_UNK, "SanyoDump",
218 	  "Data Dump", NULL },
219 	{ 0xffff, TIFF_UNKN, 0, ED_UNK, "SanyoUnknown",
220 	  "Sanyo Unknown", NULL },
221 };
222 
223 
224 /* Picture mode. */
225 
226 static struct descrip sanyo_picmode[] = {
227 	{ 0,	"Normal" },
228 	{ 2,	"Fast" },
229 	{ 3,	"Panorama" },
230 	{ -1,	"Unknown" },
231 };
232 
233 
234 /* Panoramic direction. */
235 
236 static struct descrip sanyo_pandir[] = {
237 	{ 1,	"Left to Right" },
238 	{ 2,	"Right to Left" },
239 	{ 3,	"Bottom to Top" },
240 	{ 4,	"Top to Bottom" },
241 	{ -1,	"Unknown" },
242 };
243 
244 
245 /* Shooting mode subtags. */
246 
247 static struct exiftag sanyo_shoottags[] = {
248 	{ 0x0000, TIFF_UNKN, 0, ED_IMG, "SanyoPicMode",
249 	  "Picture Mode", sanyo_picmode },
250 	{ 0x0001, TIFF_UNKN, 0, ED_IMG, "SanyoSeqNum",
251 	  "Sequence Number", NULL },
252 	{ 0x0002, TIFF_UNKN, 0, ED_IMG, "SanyoPanDir",
253 	  "Panoramic Direction", sanyo_pandir },
254 	{ 0xffff, TIFF_UNKN, 0, ED_UNK, "SanyoShootUnknown",
255 	  "Sanyo Shooting Unknown", NULL },
256 };
257 
258 
259 /*
260  * Process Sanyo maker note tags.
261  */
262 void
sanyo_prop(struct exifprop * prop,struct exiftags * t)263 sanyo_prop(struct exifprop *prop, struct exiftags *t)
264 {
265 	int i, j;
266 	u_int32_t a, b;
267 	char *c1, *c2;
268 	struct exifprop *aprop;
269 
270 	switch (prop->tag) {
271 
272 	/* Various image data. */
273 
274 	case 0x0200:
275 		if (debug)
276 			printf("Processing %s (0x%04X) directory, %d entries\n",
277 			    prop->name, prop->tag, prop->count);
278 
279 		for (i = 0; i < (int)prop->count; i++) {
280 			a = exif4byte(t->mkrmd.btiff + prop->value + i * 2,
281 			    t->mkrmd.order);
282 
283 			aprop = childprop(prop);
284 			aprop->value = a;
285 			aprop->tag = i;
286 			aprop->tagset = sanyo_shoottags;
287 			aprop->type = prop->type;
288 			aprop->count = 1;
289 
290 			/* Lookup property name and description. */
291 
292 			for (j = 0; sanyo_shoottags[j].tag < EXIF_T_UNKNOWN &&
293 			    sanyo_shoottags[j].tag != i; j++);
294 			aprop->name = sanyo_shoottags[j].name;
295 			aprop->descr = sanyo_shoottags[j].descr;
296 			aprop->lvl = sanyo_shoottags[j].lvl;
297 			if (sanyo_shoottags[j].table)
298 				aprop->str =
299 				    finddescr(sanyo_shoottags[j].table,
300 				    (u_int16_t)a);
301 
302 			switch (aprop->tag) {
303 			case 0x0001:
304 				if (!aprop->value)
305 					aprop->lvl = ED_VRB;
306 				aprop->value += 1;
307 				break;
308 			}
309 
310 			dumpprop(aprop, NULL);
311 		}
312 		break;
313 
314 	/* Image quality & resolution. */
315 
316 	case 0x0201:
317 		c1 = finddescr(sanyo_quality,
318 		    (u_int16_t)((prop->value >> 8) & 0xff));
319 		c2 = finddescr(sanyo_res, (u_int16_t)(prop->value & 0xff));
320 		exifstralloc(&prop->str, strlen(c1) + strlen(c2) + 3);
321 		sprintf(prop->str, "%s, %s", c1, c2);
322 		free(c1);
323 		free(c2);
324 		break;
325 
326 	/* Digital zoom. */
327 
328 	case 0x0204:
329 		a = exif4byte(t->mkrmd.btiff + prop->value, t->mkrmd.order);
330 		b = exif4byte(t->mkrmd.btiff + prop->value + 4, t->mkrmd.order);
331 
332 		if (!a || !b || a == b)
333 			snprintf(prop->str, 31, "None");
334 		else
335 			snprintf(prop->str, 31, "x%.1f", (float)a / (float)b);
336 		break;
337 
338 	/* Color adjust. */
339 
340 	case 0x0210:
341 		prop->str = finddescr(sanyo_offon, (u_int16_t)(!!prop->value));
342 		break;
343 	}
344 }
345 
346 
347 /*
348  * Try to read a Sanyo maker note IFD.
349  */
350 struct ifd *
sanyo_ifd(u_int32_t offset,struct tiffmeta * md)351 sanyo_ifd(u_int32_t offset, struct tiffmeta *md)
352 {
353 	struct ifd *myifd;
354 
355 	/*
356 	 * Seems that Sanyo maker notes start with an ID string.  Therefore,
357 	 * try reading the IFD starting at offset + 8 ("SANYO" + 3).
358 	 */
359 
360 	if (!strcmp((const char *)(md->btiff + offset), "SANYO"))
361 		readifd(offset + strlen("SANYO") + 3, &myifd, sanyo_tags, md);
362 	else
363 		readifd(offset, &myifd, sanyo_tags, md);
364 
365 	return (myifd);
366 }
367