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_agfa.c,v 1.19 2005/07/24 22:56:26 alex Exp $";
11 #endif
12
13 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14 /* AGFA camera maker-specific routines */
15 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
16 /* This information is from a page by Johannes Tschebisch at: */
17 /* http://www.jojotsch.de/downloads/jojothumb/beispiele/ */
18 /* html_exif/bilder/agfa-c150.html */
19 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include "defs.h"
25 #include "summary.h"
26 #include "datadefs.h"
27 #include "maker_datadefs.h"
28 #include "maker.h"
29 #include "misc.h"
30 #include "tags.h"
31 #include "maker_extern.h"
32 #include "extern.h"
33
34 extern struct camera_id agfa_model_id[];
35
36 /* Find the identifying number assigned to known Agfa camera */
37 /* models. This number is used to dispatch print and interpret */
38 /* routines approopriate to the current image. */
39
40 int
agfa_model_number(char * model,char * software)41 agfa_model_number(char *model,char *software)
42 {
43 struct camera_id *model_id;
44 int number = NO_MODEL;
45
46 for(model_id = &agfa_model_id[0]; model_id && model_id->name; ++model_id)
47 {
48 if(strncasecmp(model,model_id->name,model_id->namelen) == 0)
49 {
50 number = model_id->id;
51 setnoteversion(model_id->noteversion);
52 setnotetagset(model_id->notetagset); /* info only */
53 break;
54 }
55 }
56 return(number);
57 }
58
59 /* Dispatch a print routine based upon model */
60
61 void
print_agfa_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)62 print_agfa_makervalue(struct ifd_entry *entry_ptr,int make, int model,
63 char *prefix)
64 {
65 int noteversion;
66
67 noteversion = getnoteversion();
68
69 if(entry_ptr && (PRINT_VALUE))
70 {
71 switch(noteversion)
72 {
73 case 1:
74 print_agfa1_makervalue(entry_ptr,make,model,prefix);
75 agfa1_interpret_value(entry_ptr);
76 break;
77 default:
78 print_value(entry_ptr,PREFIX);
79 break;
80 }
81 }
82 }
83
84 /* Model-specific print routine for Agfa cameras. This routine is */
85 /* responsible for picking off any direct entry tags which are */
86 /* peculiar and will not be handled properly by print_value() */
87 /* (usually UNDEFINED values which fit in the 4-byte entry value). If */
88 /* there are no such entries, this function simply calls */
89 /* print_value(). */
90
91 void
print_agfa1_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)92 print_agfa1_makervalue(struct ifd_entry *entry_ptr,int make, int model,
93 char *prefix)
94 {
95 if(entry_ptr && (PRINT_VALUE))
96 {
97 switch(entry_ptr->tag)
98 {
99 default:
100 print_value(entry_ptr,PREFIX);
101 break;
102 }
103 }
104 }
105
106 /* Dispatch a routine to decode and print offset values for Agfa */
107 /* cameras. */
108 void
print_agfa_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)109 print_agfa_offset_makervalue(FILE *inptr,unsigned short byteorder,
110 struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
111 struct image_summary *summary_entry,char *parent_name,char*prefix,
112 int indent,int make,int model,int at_offset)
113 {
114 int noteversion;
115
116 noteversion = getnoteversion();
117
118 if(entry_ptr)
119 {
120 switch(noteversion)
121 {
122 case 1:
123 agfa1_offset_makervalue(inptr,byteorder,entry_ptr,
124 fileoffset_base,summary_entry,
125 parent_name,prefix,indent,
126 make,model,at_offset);
127 agfa1_interpret_offset_makervalue(inptr,byteorder,entry_ptr,
128 fileoffset_base);
129 break;
130 default:
131 /* Insufficent information about other models to do */
132 /* anything but generic. */
133 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
134 fileoffset_base,parent_name,prefix,indent,
135 make,model,at_offset);
136 break;
137 }
138 }
139 }
140
141 /* Model-specific routine to print values found at offsets in Agfa */
142 /* makernotes. One of these may be supplied for each unique note */
143 /* version */
144
145 void
agfa1_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)146 agfa1_offset_makervalue(FILE *inptr,unsigned short byteorder,
147 struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
148 struct image_summary *summary_entry,char *parent_name,char*prefix,
149 int indent,int make,int model,int at_offset)
150 {
151 unsigned long max_offset = 0;
152 unsigned long value_offset;
153 unsigned long dumplength,count;
154 unsigned short marker;
155 char *nameoftag;
156 char *fulldirname = NULL;
157 int status = 0;
158 int chpr = 0;
159
160 if(entry_ptr)
161 {
162 nameoftag = maker_tagname(entry_ptr->tag,make,model);
163 fulldirname = splice(parent_name,".",nameoftag);
164 value_offset = fileoffset_base + entry_ptr->value;
165 count = entry_ptr->count;
166
167 switch(entry_ptr->tag)
168 {
169 case 0x0209: /* CameraId */
170 if(at_offset && (PRINT_VALUE_AT_OFFSET))
171 {
172 print_tag_address(ENTRY,value_offset,indent,prefix);
173 print_makertagid(entry_ptr,23," = ",make,model);
174 }
175 if((PRINT_VALUE))
176 print_ascii(inptr,entry_ptr->count,value_offset);
177 break;
178 case 0x0100: /* Jpeg Thumbnail */
179 if(at_offset && (PRINT_SECTION))
180 {
181 print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix);
182 chpr += printf("# Start of JPEG Thumbnail from MakerNote");
183 chpr += printf(" length %ld",count);
184 }
185 else if(!at_offset && (PRINT_VALUE))
186 {
187 if(!(PRINT_OFFSET))
188 chpr += printf("@%lu",value_offset);
189 else
190 chpr = printf("length %lu",count);
191 }
192 if((PRINT_SECTION) || (PRINT_SEGMENT))
193 chpr = newline(chpr);
194 marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset);
195 max_offset = process_jpeg_segments(inptr,value_offset,marker,
196 count,summary_entry,fulldirname,
197 prefix,indent+SMALLINDENT);
198 if(at_offset)
199 {
200 if((PRINT_SECTION))
201 {
202 if((status = jpeg_status(0) == JPEG_EARLY_EOI))
203 chpr = newline(chpr);
204 jpeg_status(status);
205 print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1,
206 indent,"-");
207 chpr += printf("# End of JPEG Thumbnail from MakerNote");
208 if((PRINT_ENTRY) && !(PRINT_VALUE))
209 chpr = newline(chpr);
210 }
211 }
212 print_jpeg_status();
213 if(marker && summary_entry)
214 {
215 /* The new one is on the end of the chain */
216 if((summary_entry = last_summary_entry(summary_entry)))
217 {
218 summary_entry->filesubformat |= FILESUBFMT_MNOTE;
219 summary_entry->datatype = MAKER_IFD;
220 summary_entry->subfiletype = THUMBNAIL_TYPE;
221 }
222 }
223 /* make certain we're at the end */
224 clearerr(inptr);
225 fseek(inptr,value_offset + count,0);
226 break;
227 case 0x0f00: /* Data */
228 if(at_offset && (PRINT_ENTRY))
229 {
230 print_tag_address(ENTRY,value_offset,indent,prefix);
231 print_makertagid(entry_ptr,MAKERTAGWIDTH," : ",make,model);
232 chpr += printf(" length %-9lu", count);
233 if(Max_undefined == 0)
234 {
235 if(chpr)
236 printred(" (not dumped, use -U)");
237 }
238 else
239 {
240 if((Max_undefined == DUMPALL) || (Max_undefined > count))
241 dumplength = count;
242 else
243 dumplength = Max_undefined;
244 chpr = newline(chpr);
245 hexdump(inptr,value_offset,count,dumplength,12,
246 indent,SUBINDENT);
247 chpr = newline(1);
248 }
249 }
250 else if(!at_offset && (PRINT_VALUE))
251 {
252 if(!(PRINT_OFFSET))
253 chpr += printf("@%lu:%lu",value_offset,entry_ptr->count);
254 else
255 chpr = printf("length %lu", entry_ptr->count);
256 if(!(PRINT_VALUE_AT_OFFSET))
257 chpr += printf(" # UNDEFINED");
258 }
259 /* make certain we're at the end */
260 fseek(inptr,value_offset + count,0);
261 break;
262 default:
263 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
264 fileoffset_base,fulldirname,prefix,indent,
265 make,model,at_offset);
266 break;
267 }
268 if(fulldirname)
269 free(fulldirname);
270 }
271 setcharsprinted(chpr);
272 }
273
274 /* Agfa-specific tagnames for makernotes. */
275
276 char *
maker_agfa_tagname(unsigned short tag,int model)277 maker_agfa_tagname(unsigned short tag,int model)
278 {
279 char *tagname = CNULL;
280 int noteversion = 0;
281
282 /* Should have to do this only once, and only for unrecognized */
283 /* models. If the model is recognized (or the user has forced a */
284 /* noteversion) noteversion will already be set. */
285 if((noteversion = getnoteversion()) == 0)
286 {
287 noteversion = 1;
288 setnoteversion(1);
289 }
290
291 switch(noteversion)
292 {
293 case 1:
294 tagname = maker_agfa1_tagname(tag);
295 break;
296 default:
297 setnotetagset(noteversion); /* for info only */
298 break;
299 }
300
301 /* If no model-specific tag is found, check "generic" tags */
302 if(tagname == NULL)
303 {
304 switch(tag)
305 {
306 case 0x0e00: tagname = "PrintIM"; break;
307 default: break;
308 }
309 }
310 return(tagname);
311 }
312
313 char *
maker_agfa1_tagname(unsigned short tag)314 maker_agfa1_tagname(unsigned short tag)
315 {
316 char *tagname = CNULL;
317
318 switch(tag)
319 {
320 case 0x0100: tagname = "JpegThumbnail"; break;
321 case 0x0200: tagname = "SpecialMode"; break;
322 case 0x0201: tagname = "Quality"; break;
323 case 0x0202: tagname = "Macro"; break;
324 case 0x0204: tagname = "DigitalZoom"; break;
325 case 0x0207: tagname = "SoftwareRelease"; break;
326 case 0x0208: tagname = "PictureInfo"; break;
327 case 0x0209: tagname = "CameraID"; break;
328 case 0x020b: tagname = "ImageWidth"; break; /* ? */
329 case 0x020c: tagname = "ImageHeight"; break; /* ? */
330 case 0x0f00: tagname = "Data"; break;
331 default: break;
332 }
333 setnotetagset(1);
334 return(tagname);
335 }
336
337
338 void
agfa1_interpret_value(struct ifd_entry * entry_ptr)339 agfa1_interpret_value(struct ifd_entry *entry_ptr)
340 {
341 int chpr = 0;
342
343 if(entry_ptr && (PRINT_VALUE))
344 {
345 switch(entry_ptr->tag)
346 {
347 case 0x0201: /* Compression Mode */
348 print_startvalue();
349 switch(entry_ptr->value)
350 {
351 case 1: chpr += printf("SQ"); break;
352 case 2: chpr += printf("HQ"); break;
353 case 3: chpr += printf("SHQ"); break;
354 case 33: chpr += printf("not compressed"); break; /* TIFF */
355 case 34: /* not sure about this one ###%%% */
356 chpr += printf("not compressed");
357 break;
358 default: printred("undefined"); break;
359 }
360 print_endvalue();
361 break;
362 case 0x0202: /* Macro */
363 print_startvalue();
364 switch(entry_ptr->value)
365 {
366 case 0: chpr += printf("Normal"); break;
367 case 1: chpr += printf("Macro"); break;
368 case 2: chpr += printf("View"); break;
369 default: printred("undefined"); break;
370 }
371 print_endvalue();
372 break;
373 default:
374 break;
375 }
376 }
377 }
378
379 void
agfa1_interpret_offset_makervalue(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base)380 agfa1_interpret_offset_makervalue(FILE *inptr,unsigned short byteorder,
381 struct ifd_entry *entry_ptr,unsigned long fileoffset_base)
382 {
383 unsigned long offset,value;
384 int chpr = 0;
385
386 if(entry_ptr && (PRINT_VALUE))
387 {
388 offset = entry_ptr->value + fileoffset_base;
389 switch(entry_ptr->tag)
390 {
391 case 0x0200: /* SpecialMode */
392 value = read_ulong(inptr,byteorder,offset);
393 print_startvalue();
394 switch(value)
395 {
396 case 0: chpr += printf("Normal"); break;
397 case 1: chpr += printf("Unkown"); break;
398 case 2: chpr += printf("Fast"); break;
399 case 3: chpr += printf("Panorama,");
400 value = read_ulong(inptr,byteorder,HERE);
401 chpr += printf("#%lu,",value);
402 value = read_ulong(inptr,byteorder,HERE);
403 switch(value)
404 {
405 case 1: chpr += printf(" Left to Right"); break;
406 case 2: chpr += printf(" Right to Left"); break;
407 case 3: chpr += printf(" Bottom to Top"); break;
408 case 4: chpr += printf(" Top to Bottom"); break;
409 default: printred(" undefined"); break;
410 }
411 break;
412 default: printred("undefined"); break;
413 }
414 print_endvalue();
415 break;
416 default:
417 break;
418 }
419 }
420 setcharsprinted(chpr);
421 }
422