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