exifprobe-2.0.1+git20170416-3c2b76/0000755000000000000000000000000013074742216014511 5ustar rootrootexifprobe-2.0.1+git20170416-3c2b76/maker_kyocera.c0000644000000000000000000001465613074742216017505 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_kyocera.c,v 1.5 2005/07/24 22:56:26 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Kyocera camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id kyocera_model_id[]; int kyocera_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &kyocera_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine for direct values in Kyocera cameras, */ /* based upon model */ void print_kyocera_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 1: print_kyocera1_makervalue(entry_ptr,make,model,prefix); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Kyocera cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_kyocera1_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for Kyocera */ /* cameras. */ void print_kyocera_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) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 1: kyocera1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr,fileoffset_base, parent_name,prefix,indent, make,model,at_offset); break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in Kyocera makernotes. */ void kyocera1_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) { unsigned long value_offset,count; char *nameoftag; char *fulldirname = NULL; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0e00: /* PrintIM (Epson Print Image matching) */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) { chpr += printf("@%lu:%lu",value_offset,count); chpr = newline(chpr); } } process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix, indent,make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Kyocera-specific tagnames for makernotes. */ char * maker_kyocera_tagname(unsigned short tag,int model) { char *tagname = CNULL; int noteversion = 0; /* Should have to do this only once, and only for unrecognized */ /* models. If the model is recognized (or the user has forced a */ /* noteversion) noteversion will already be set. */ if((noteversion = getnoteversion()) == 0) { noteversion = -1; setnoteversion(-1); } if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } exifprobe-2.0.1+git20170416-3c2b76/exifgrep.10000644000000000000000000000754613074742216016420 0ustar rootroot... ... (C) Copyright 2003, 2005 Duane H. Hesser, see LICENSE.EXIFPROBE file ... @(#) $Id: exifgrep.1,v 1.3 2005/07/02 13:08:18 alex Exp $ ... .TH EXIFGREP 1 LOCAL .SH NAME exifgrep \- select and reformat the output of \fBexifprobe\fP .SH SYNOPSIS .br .B exifgrep [\fioptions\fP] [\fIegrep_options\fP] \fIegrep_pattern\fP [\fINOT egrep-pattern] \fIfilename(s)\fP .SH DESCRIPTION .B Exifgrep is a shell script which applies \fBegrep(1)\fP to the output of \fBexifprobe\fP\ \fI-L\fP, permitting easy selection and minor reformatting of output items. \fBexifprobe\fP is small, fast, and utterly sycophantic in its desire to report \fIeverything\fP it finds in an image. \fBexifgrep\fP applies the regular expression matching capabilities of \fBegrep\fP to the output barrage to extract only wanted information. \fBexifgrep\fP also performs a mild form of selection on the output fields of \fBexifprobe\fP \fI-L\fP. Many items reported by exifprobe are represented in the image file by a \fInumber\fP which compactly represents a defined value. E.g. \fBexifprobe\fP \fI-L\fP may report TIFF.Ifd1.ResolutionUnit = 2 = 'pixels per inch' where the value \*(lq2\*(rq must be interpreted to mean that resolution values (\fITIFF.IFd1.Xresolution\fP and \fTIFF.IFd1.YResolution\fP) are recorded in pixels per inch, rather than, say, pixels per centimeter. \fBexifprobe\fP reports both fields; \fBexifprobe\fP may also report interpreted values for items which are recorded in unfamiliar units, such as .nf JPEG.APP1.Ifd0.Exif.FNumber = 5.6 APEX = 'f7.0' .fi In all such cases, \fBexifgrep\fP reports (by default) only the "human readable" field: .nf TIFF.Ifd1.ResolutionUnit = 'pixels per inch' JPEG.APP1.Ifd0.Exif.FNumber = 'f7.0' .fi unless the "\fI-num\fP" option is given to select the numerical value. In addition, a `variable' format may be selected ("\fI-var\fP") which eliminates whitespace, providing a format which typical shells may use directly to set variables for further processing. E.g. .nf TIFF.Ifd1.ResolutionUnit='pixels per inch' JPEG.APP1.Ifd0.Exif.FNumber='f7.0' .fi .SH OPTIONS .IP \-r 10 \fIfile\fP arguments may be directories, which will be searched via \fBfind\fP for all image types recognized by \fBexifprobe\fP. .IP \-n 10 force \fBexifprobe\fP to print a filename for each line of its output, which \fIexifgrep\fP will turn into a comment at the end of each matching line. .IP \-t 10 force \fBexifprobe\fP to print tag numbers for all itemes that have them, so that matches may be made on hex or decimal tag numbers. .IP \-c 10 turn on color output from \fBexifprobe\fP .IP \-h 10 print a usage message (help) .IP \-var 10 report in "variable" format, which may be directly `sourced' by any Bourne-compatible shell (except that most shells will insist that the dots must be replaced, e.g. by underscores). .IP \-export 10 report in "variable" format, but with a Bourne-compatible \fIexport\fP command .IP \-num 10 report numerical values rather than interpreted strings, for fields which have both. .P NOTE: the \fI\-var\fP and \fI\-export\fP options are obsolescent; they are retained for compatibility with earlier versions of \fIexifprobe\fP. A post-processor such as \fIreformat.sh\fP may be more effective for the current version if shell-compatible output is desired. .P Any option not recognized by the script will be passed on to \fBegrep\fP. The first non-option argument will be used as the pattern passed to \fBegrep\fP. This may be followed by the keyword \fINOT\fP and an expression representing matches to be \fIrejected\fP. This pattern will be passed to \fBegrep\fP \fI-v\fP. Only one argument of each type may be given, and the "accept" expression (if given) must appear before the "reject" expression. All remaining arguments are interpreted as image filenames. .SH SEE ALSO \fBexifprobe(1)\fP .SH AUTHOR .br Duane H. Hesser .br dhh@virtual-cafe.com exifprobe-2.0.1+git20170416-3c2b76/raf.h0000644000000000000000000000201113074742216015424 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: raf.h,v 1.2 2005/07/09 15:31:22 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef RAF_INCLUDED #define RAF_INCLUDED /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Fujifilm RAF definitions and incluedes */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #define RAF_JPEGLOC 84 #endif /* RAF_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/options.c0000644000000000000000000003617113074742216016360 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002, 2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: options.c,v 1.21 2005/07/24 17:18:27 alex Exp $"; #endif #include #include #include #include #include #include "version.h" #include "defs.h" #include "summary.h" #include "datadefs.h" #include "extern.h" #include "maker_extern.h" int Debug = 0; int process_options(int argc,char **argv) { int opt; unsigned long bits; int nv; if((CHECK_TTY_FOR_COLOR)) { if(isatty(fileno(stdout)) == 0) Print_options &= ~PCOLOR; } while((opt = getopt(argc,argv,"ace:hil:m:np:s:tuA:B:C:DILM:N:O:RSU:VXY:Z")) != EOF) { switch(opt & 0xff) { case 'I': /* Indent: after -> before -> none -> after */ if(PRINT_INDENT_AFTER_ADDRESS) { Print_options &= ~INDENT_AFTER_ADDRESS; Print_options |= INDENT_BEFORE_ADDRESS; } else if(PRINT_INDENT_BEFORE_ADDRESS) Print_options &= ~(INDENT_BEFORE_ADDRESS|INDENT_AFTER_ADDRESS); else { Print_options &= ~INDENT_BEFORE_ADDRESS; Print_options |= INDENT_AFTER_ADDRESS; } break; /* Modes: structural (default), report, or list */ case 'S': Print_options = DEFAULT_OPTIONS; break; case 'R': Print_options = REPORT_OPTIONS; break; case 'L': Print_options = LIST_OPTIONS; break; /* Want hex?...or decimal */ case 'D': bits = Print_options & HEX_ONLY; bits = (bits << 1) & DECIMAL_ONLY; Print_options &= ~HEX_ONLY; Print_options |= bits; break; case 'X': bits = Print_options & DECIMAL_ONLY; bits = (bits >> 1) & HEX_ONLY; Print_options &= ~DECIMAL_ONLY; Print_options |= bits; break; /* Zero all print options; leaves only image summary and */ /* filetype/fileformat. Leave LONGNAMES on. */ case 'Z': Print_options = LONGNAMES_FLAG; break; /* toggle use of color highlighting */ case 'c': Print_options = toggle(Print_options,PCOLOR); break; /* toggle printing of offset values in IFDs "(i)nline" */ /* with the directory entry (not at the value offset) */ case 'i': Print_options = toggle(Print_options,VALUE_AT_OFFSET); break; case 'a': Print_options = toggle(Print_options,HEXADDRESS | DECADDRESS); break; /* 'e'ntry options; which parts of an entry to */ /* (de)activate */ case 'e': while(*optarg) { switch(*optarg) { case 't': Print_options = toggle(Print_options,TAGNAME); break; case 'n': Print_options = toggle(Print_options,DECTAGNO); break; case 'N': Print_options = toggle(Print_options,HEXTAGNO); break; case 'T': Print_options = toggle(Print_options,TYPE); break; case 'v': Print_options = toggle(Print_options,DECVALUE); break; case 'V': Print_options = toggle(Print_options,HEXVALUE); break; case 'o': Print_options = toggle(Print_options,DECOFFSET); break; case 'O': Print_options = toggle(Print_options,HEXOFFSET); break; case 'r': Print_options = toggle(Print_options,RELOFFSET); break; case 'R': Print_options = toggle(Print_options,RAW_VALUES); break; case 'a': Print_options = toggle(Print_options,ASCII_IGNORE_LENGTH); break; case 'A': Print_options = toggle(Print_options,MULTIVAL_PRINT_ALL); break; } ++optarg; } break; case 'n': Print_options = toggle(Print_options,FILENAMES); break; /* 'p'rint options; which sections/features to */ /* (de)activeate */ case 'p': while(*optarg) { switch(*optarg) { case 'l': Print_options = toggle(Print_options,LONGNAMES_FLAG); break; case 's': Print_options = toggle(Print_options,SECTION); break; case 'a': Print_options = toggle(Print_options,APP_ENTRY); break; case 'g': Print_options = toggle(Print_options,SEGMENT); break; case 'm': Print_options |= MAKERNOTE_SCHEME; break; case 'M': Print_options |= MAKERNOTE_SCHEME|SCHEME_DEBUG; break; case 'e': Print_options = toggle(Print_options,ENTRY); break; } ++optarg; } break; case 'B': /* dump binary image segments and failed Jpeg */ /* image segments */ if(optarg) { if(*optarg == 'a') Max_imgdump = DUMPALL; else Max_imgdump = strtoul(optarg,NULL,0); } else Max_imgdump = DUMPALL; break; case 'U': /* dump UNDEFINED segments */ /* Also affects raw image sections */ if(optarg) { if(*optarg == 'a') Max_undefined = DUMPALL; else Max_undefined = strtoul(optarg,NULL,0); } else Max_undefined = DUMPALL; break; case 'M': /* dump MakerNotes */ Print_options |= MAKERDUMP; if(optarg) { if(*optarg == 'a') Max_makerdump = DUMPALL; else Max_makerdump = strtoul(optarg,NULL,0); } break; case 'N': /* force a noteversion */ if(optarg) { nv = atoi(optarg); setoptionnoteversion(nv); } break; case 'A': /* dump APPn segments */ Print_options |= APPNDUMP; if(optarg) { if(*optarg == 'a') Max_appdump = DUMPALL; else Max_appdump = strtoul(optarg,NULL,0); } break; /* Options to force makernote routines to use a specific */ /* set of routines to interpret MakerNotes. Scheme */ /* detection is automatic and (largely) unaffected */ /* (except for certain details which are unavoidably */ /* maker-specific). This may be used to check whether a */ /* set of MakerNote tags for an undocumented camera */ /* actually match a set for which routines exist for */ /* another camera */ /* "Software" has proven unreliable for identification */ /* purposes, and is not used for anything. Changing it */ /* here will accomplish nothing. */ case 'm': Use_Make_name = optarg; break; case 'l': Use_Model_name = optarg; break; case 's': Use_Software_name = optarg; /* useless */ break; /* help and version */ case 'h': usage(); exit(0); break; case 'V': print_version(); break; /* Y is this happpening? Random debug for development */ /* only; e.g bit 0x4 shows summary debug, bit 0x8 shows */ /* noteversion debug... */ case 'Y': Debug = strtoul(optarg,(char **)0,0); break; /* Print make and/or model names of digital cameras */ /* "known" to the program. The format is -C make+model, */ /* where 'make' and 'model' are strings subjected to a */ /* simple substring match with known info. A missing */ /* pattern matches everything, so "-C +" prints all known */ /* makes and models. As a special case "-C -" prints all */ /* makes. Make and Model are significant only for */ /* MakerNotes. */ case 'C': Camera_name_pattern = optarg; Print_options = toggle(Print_options,CAMERA_NAMES); break; case 'O': Start_offset = strtoul(optarg,0,0); break; case 't': Print_options = toggle(Print_options,TTY_COLOR_CHECK); break; case 'u': Print_options = toggle(Print_options,UNICODE_FLAG); break; default: usage(); exit(1); break; } } return(optind); } /* Grab options from the environment. */ #define MAXARGV 256 extern int vector(); void env_options() { char *argv[MAXARGV]; char *envopts; int argc; envopts = getenv("EXIFPROBE_OPTIONS"); if(envopts && *envopts) { char *argstr = calloc(strlen(envopts) + 3, 1); strcpy(argstr, "e "); strcat(argstr, envopts); optind = 0; /* make an argument vector */ argc = vector(argstr, argv, " \t", 0, MAXARGV); (void)process_options(argc,argv); optind = 1; free(argstr); } } void usage() { printf("Usage:\n%s [options] filenames(s)\n",Progname); printf("\t-h - print this help message\n"); printf("\t-V - print program version and copyright\n"); (void)putchar('\n'); printf("\t-R - Report mode: only tagnames and decimal values, indented, inline\n"); printf("\t-S - Structure mode: everything, offset values not inline (default)\n"); printf("\t-L - List mode: list all tags and values (only); no structure\n"); printf("\t-Z - Zero (turn off) all output flags\n"); (void)putchar('\n'); printf("\t-a - toggle print addresses in hex and decimal\n"); printf("\t-D - toggle print enabled addresses, tag numbers and values in decimal only\n"); printf("\t-X - toggle print enabled addresses, tag numbers and values in hex only\n"); printf("\t-I - toggle indent (after address -> before -> none)\n"); printf("\t-i - toggle \"inline\" print of IFD values\n"); printf("\t-n - toggle printing of filename at start of each output line\n"); printf("\t-c - toggle use of color to highlight certain sections\n"); printf("\t-u - print all 16 bits of unicode data\n"); (void)putchar('\n'); printf("\t-p[items] - toggle print identifiers for:\n"); printf("\t\ts - sections\n"); printf("\t\tg - segments\n"); printf("\t\te - IFD entries\n"); printf("\t\ta - expand known entries in APP0...APPN segents\n"); printf("\t\tm - print MakerNote scheme detection info\n"); printf("\t\tM - debug MakerNote scheme detection info\n"); printf("\t\tl - long tagnames (default in List mode)\n"); (void)putchar('\n'); printf("\t-e[items] - toggle print IFD entry items:\n"); printf("\t\tt - tagname\n"); printf("\t\tn - tag number in decimal\n"); printf("\t\tN - tag number in hex\n"); printf("\t\tT - entry type\n"); printf("\t\tv - value in decimal\n"); printf("\t\tV - value in hex\n"); printf("\t\to - file offset to value in decimal\n"); printf("\t\tO - file offset to value in hex\n"); printf("\t\tr - relative (unadjusted) offset in decimal\n"); printf("\t\tR - print \"raw\" values where expansion of values is needed\n"); printf("\t\ta - print ascii strings until null, rather than by length\n"); printf("\t\tA - print ALL elements of multiple-value tags\n"); (void)putchar('\n'); printf("\t-M[len|a] - hex/ascii dump 'len' (or all) bytes of unknown MakerNotes\n"); printf("\t-A[len|a] - hex/ascii dump 'len' (or all) bytes of unknown APPn segments\n"); printf("\t-U[len|a] - hex/ascii dump 'len' (or all) bytes of UNDEFINED data of unknown format\n"); printf("\t-B[len|a] - hex/ascii dump 'len' (or all) bytes of binary images or invalid JPEG data\n"); printf("\t-N[num] - force noteversion 'num' for MakerNote interpretation\n"); printf("\t-m[name] - force use of maker 'name' to select MakerNote interpretation routines\n"); printf("\t-l[model] - force use of 'model' to select MakerNote interpretation routines\n"); (void)putchar('\n'); printf("\t-O[offset] - start processing at 'offset' in file\n"); printf("\t-C[make]+[model] - print makes matching 'make', models matching 'model' (substrings)\n"); (void)putchar('\n'); print_version(); } extern char *Comptime; void print_version() { printf("\tProgram: '%s' version %s",Progname,Program_version); if(PATCHLEVEL > 0) printf(" patchlevel %d",PATCHLEVEL); (void)putchar('\n'); if(Comptime) printf("\tCompiled: %s\n",Comptime); printf("\t%s\n",Copyright); printf("\t\t(open source; see LICENSE.EXIFPROBE)\n"); } exifprobe-2.0.1+git20170416-3c2b76/jpegtags.h0000644000000000000000000000520713074742216016472 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: jpegtags.h,v 1.3 2003/02/20 00:30:07 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Tags ("markers") defined in the JPEG (ITU) spec */ #ifndef JPEG_MARKERS_INCLUDED #define JPEG_MARKERS_INCLUDED #define JPEG_SOF_0 0xFFC0 #define JPEG_SOF_1 0xFFC1 #define JPEG_SOF_2 0xFFC2 #define JPEG_SOF_3 0xFFC3 #define JPEG_DHT 0xFFC4 #define JPEG_SOF_5 0xFFC5 #define JPEG_SOF_6 0xFFC6 #define JPEG_SOF_7 0xFFC7 #define JPEG_JPG 0xFFC8 #define JPEG_SOF_9 0xFFC9 #define JPEG_SOF_10 0xFFCA #define JPEG_SOF_11 0xFFCB #define JPEG_DAC 0xFFCC #define JPEG_SOF_13 0xFFCD #define JPEG_SOF_14 0xFFCE #define JPEG_SOF_15 0xFFCF #define JPEG_RST0 0xFFD0 #define JPEG_RST1 0xFFD1 #define JPEG_RST2 0xFFD2 #define JPEG_RST3 0xFFD3 #define JPEG_RST4 0xFFD4 #define JPEG_RST5 0xFFD5 #define JPEG_RST6 0xFFD6 #define JPEG_RST7 0xFFD7 #define JPEG_SOI 0xFFD8 #define JPEG_BADSOI 0x00D8 /* minolta */ #define JPEG_EOI 0xFFD9 #define JPEG_SOS 0xFFDA #define JPEG_DQT 0xFFDB #define JPEG_DNL 0xFFDC #define JPEG_DRI 0xFFDD #define JPEG_DHP 0xFFDE #define JPEG_EXP 0xFFDF #define JPEG_APP0 0xFFE0 #define JPEG_APP1 0xFFE1 #define JPEG_APP2 0xFFE2 #define JPEG_APP3 0xFFE3 #define JPEG_APP4 0xFFE4 #define JPEG_APP5 0xFFE5 #define JPEG_APP6 0xFFE6 #define JPEG_APP7 0xFFE7 #define JPEG_APP8 0xFFE8 #define JPEG_APP9 0xFFE9 #define JPEG_APP10 0xFFEA #define JPEG_APP11 0xFFEB #define JPEG_APP12 0xFFEC #define JPEG_APP13 0xFFED #define JPEG_APP14 0xFFEE #define JPEG_APP15 0xFFEF #define JPEG_JPG0 0xFFF0 #define JPEG_JPG1 0xFFF1 #define JPEG_JPG2 0xFFF2 #define JPEG_JPG3 0xFFF3 #define JPEG_JPG4 0xFFF4 #define JPEG_JPG5 0xFFF5 #define JPEG_JPG6 0xFFF6 #define JPEG_JPG7 0xFFF7 #define JPEG_JPG8 0xFFF8 #define JPEG_JPG9 0xFFF9 #define JPEG_JPG10 0xFFFA #define JPEG_JPG11 0xFFFB #define JPEG_JPG12 0xFFFC #define JPEG_JPG13 0xFFFD #define JPEG_COM 0xFFFE #define JPEG_TEM 0xFF01 #define JPEG_RES 0xFF02 #endif exifprobe-2.0.1+git20170416-3c2b76/exifgrep.1.html0000644000000000000000000001133213074742216017347 0ustar rootroot


EXIFGREP(1)                                                        EXIFGREP(1)



NAME
       exifgrep - select and reformat the output of exifprobe


SYNOPSIS
       exifgrep  [options]  [egrep_options]  egrep_pattern [NOT egrep-pattern]
       filename(s)


DESCRIPTION
       Exifgrep is a shell script which applies  egrep(1)  to  the  output  of
       exifprobe -L,  permitting easy selection and minor reformatting of out-
       put items.

       exifprobe is small, fast, and utterly  sycophantic  in  its  desire  to
       report  everything  it finds in an image.  exifgrep applies the regular
       expression matching capabilities of egrep  to  the  output  barrage  to
       extract only wanted information.

       exifgrep also performs a mild form of selection on the output fields of
       exifprobe -L.  Many items reported by exifprobe are represented in  the
       image file by a number which compactly represents a defined value.

       E.g. exifprobe -L may report

       TIFF.Ifd1.ResolutionUnit              = 2 = 'pixels per inch'

       where  the value "2" must be interpreted to mean that resolution values
       (TIFF.IFd1.Xresolution and IFF.IFd1.YResolution) are recorded in pixels
       per  inch,  rather than, say, pixels per centimeter.  exifprobe reports
       both fields; exifprobe may also report  interpreted  values  for  items
       which are recorded in unfamiliar units, such as

       JPEG.APP1.Ifd0.Exif.FNumber           = 5.6 APEX = 'f7.0'

       In  all such cases, exifgrep reports (by default) only the "human read-
       able" field:

       TIFF.Ifd1.ResolutionUnit = 'pixels per inch'
       JPEG.APP1.Ifd0.Exif.FNumber = 'f7.0'

       unless the "-num" option is given to select the numerical value.

       In addition, a `variable' format may be selected ("-var") which  elimi-
       nates  whitespace,  providing  a  format  which  typical shells may use
       directly to set variables for further processing.  E.g.

       TIFF.Ifd1.ResolutionUnit='pixels per inch'
       JPEG.APP1.Ifd0.Exif.FNumber='f7.0'



OPTIONS
       -r        file arguments may be directories, which will be searched via
                 find for all image types recognized by exifprobe.

       -n        force exifprobe to print a filename for each line of its out-
                 put, which exifgrep will turn into a comment at  the  end  of
                 each matching line.

       -t        force exifprobe to print tag numbers for all itemes that have
                 them, so that matches may be  made  on  hex  or  decimal  tag
                 numbers.

       -c        turn on color output from exifprobe

       -h        print a usage message (help)

       -var      report  in "variable" format, which may be directly `sourced'
                 by any Bourne-compatible shell (except that most shells  will
                 insist  that the dots must be replaced, e.g. by underscores).

       -export   report in "variable" format,  but  with  a  Bourne-compatible
                 export command

       -num      report  numerical values rather than interpreted strings, for
                 fields which have both.


       NOTE: the -var and -export options are obsolescent; they  are  retained
       for compatibility with earlier versions of exifprobe.  A post-processor
       such as reformat.sh may be more effective for the  current  version  if
       shell-compatible output is desired.


       Any option not recognized by the script will be passed on to egrep.

       The  first  non-option  argument  will be used as the pattern passed to
       egrep.  This may be followed by the keyword NOT and an expression  rep-
       resenting matches to be rejected.  This pattern will be passed to egrep
       -v.  Only one argument of each type may  be  given,  and  the  "accept"
       expression (if given) must appear before the "reject" expression.

       All remaining arguments are interpreted as image filenames.


SEE ALSO
       exifprobe(1)


AUTHOR
       Duane H. Hesser
       dhh@virtual-cafe.com




                                     LOCAL                         EXIFGREP(1)

Man(1) output converted with man2html
exifprobe-2.0.1+git20170416-3c2b76/maker_sony.c0000644000000000000000000001635413074742216017035 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_sony.c,v 1.3 2005/07/24 22:56:27 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Sony camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* */ /* A bare minimum is known at this time (4/22/03)...just the PrintIM */ /* tag. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id sony_model_id[]; /* Find the identifying number assigned to known Sony camera models. */ /* This number is used to dispatch print and interpret routines */ /* approopriate to the current image. */ int sony_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &sony_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine for direct values in Sony cameras, */ /* based upon noteversion. */ void print_sony_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 1: print_sony1_makervalue(entry_ptr,make,model,prefix); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Sony cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ /* This routine is currently unnecessary */ void print_sony1_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for Sony */ /* cameras. */ void print_sony_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) { int noteversion = 0; if(entry_ptr) { noteversion = getnoteversion(); switch(noteversion) { case 1: sony1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; default: break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in Sony makernotes. */ void sony1_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) { unsigned long value_offset,count; char *nameoftag; char *fulldirname = NULL; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0e00: /* PrintIM (Epson Print Image matching) */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) { chpr += printf("@%lu:%lu",value_offset,count); chpr = newline(chpr); } } process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* sony-specific tagnames for makernotes. */ /* The tagname routine is the first place in the code path which */ /* requires knowledge of the note version. If the version is not */ /* given in the model table (e.g. the model is unknown), then switch */ /* code in find_maker_scheme() should have set it. This routine */ /* repeats the check for non-zero noteversion and is prepared to set */ /* the noteversion first time through, but should never need to do */ /* so. Noteversion should always be non-zero; it should be set to -1 */ /* if generic processing is required. */ char * maker_sony_tagname(unsigned short tag,int model) { char *tagname = (char *)0; int noteversion = 0; if((noteversion = getnoteversion()) == 0) { noteversion = 1; setnoteversion(1); } switch(noteversion) { default: break; } /* If no model-specific tag is found, check "generic" tags */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } exifprobe-2.0.1+git20170416-3c2b76/maker_toshiba.c0000644000000000000000000001617213074742216017474 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_toshiba.c,v 1.4 2005/07/24 22:56:27 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Toshiba camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id toshiba_model_id[]; /* Find the identifying number assigned to known Toshiba camera */ /* models. This number is used to dispatch print and interpret */ /* routines approopriate to the current image. */ int toshiba_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &toshiba_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine for direct values in Toshiba cameras, */ /* based upon model */ void print_toshiba_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { int noteversion = 0; if(entry_ptr && (PRINT_VALUE)) { noteversion = getnoteversion(); switch(noteversion) { default: print_toshiba1_makervalue(entry_ptr,make,model,PREFIX); break; } } } /* Model-specific print routine for Toshiba cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_toshiba1_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for Toshiba */ /* cameras. */ void print_toshiba_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) { int noteversion = 0; if(entry_ptr) { noteversion = getnoteversion(); switch(noteversion) { case 1: toshiba1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in Toshiba makernotes. */ void toshiba1_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) { unsigned long value_offset,count; char *nameoftag; char *fulldirname = NULL; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0e00: /* PrintIM (Epson Print Image matching) */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) { chpr += printf("@%lu:%lu",value_offset,count); chpr = newline(chpr); } } process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix, indent,make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* toshiba-specific tagnames for makernotes. */ /* The tagname routine is the first place in the code path which */ /* requires knowledge of the note version. If the version is not */ /* given in the model table (e.g. the model is unknown), then switch */ /* code in find_maker_scheme() should have set it. This routine */ /* repeats the check for non-zero noteversion and is prepared to set */ /* the noteversion first time through, but should never need to do */ /* so. Noteversion should always be non-zero; it should be set to -1 */ /* if generic processing is required. */ char * maker_toshiba_tagname(unsigned short tag,int model) { char *tagname = CNULL; #if 0 int noteversion = 0; if((noteversion = getnoteversion()) == 0) { noteversion = 1; setnoteversion(1); } switch(noteversion) { case 1: tagname = maker_toshiba1_tagname(tag,model); default: break; } #endif /* If no model-specific tag is found, check "generic" tags */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } exifprobe-2.0.1+git20170416-3c2b76/ricoh_datadefs.h0000644000000000000000000000176313074742216017630 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: ricoh_datadefs.h,v 1.1 2005/06/21 15:34:51 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef RICOH_DATADEFS_INCLUDED #define RICOH_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id ricoh_model_id[] = { { "RDC-5300 ", 9, RICOH_RDC5300, 0, 0 }, { "RDC-6000", 9, RICOH_RDC6000, 0, 0 }, { 0, 0, 0, 0, 0 } }; #endif /* RICOH_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/fujifilm_datadefs.h0000644000000000000000000000273613074742216020332 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: fujifilm_datadefs.h,v 1.5 2005/06/25 15:12:52 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef FUJIFILM_DATADEFS_INCLUDED #define FUJIFILM_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id fujifilm_model_id[] = { { "DX-10", 6, FUJI_DX10, 1, 1 }, { "FUJIFILM FinePixA204", 20, FUJI_FP_A204, 1, 1 }, { "FinePix40i", 11, FUJI_40i, 1, 1 }, { "FinePix4900ZOOM",16, FUJI_4900ZOOM, 1, 1 }, { "FinePix E550 ",16, FUJI_E550, 1, 1 }, { "FinePix F601 ZOOM",18, FUJI_F601ZOOM, 1, 1 }, { "FinePixS1Pro",13, FUJI_S1PRO, 1, 1 }, { "FinePixS2Pro",13, FUJI_S2PRO, 1, 1 }, { "FinePix S20Pro ",16, FUJI_S20PRO, 1, 1 }, { "FinePix S5000 ",15, FUJI_S5000, 1, 1 }, { "MX-1700ZOOM",12, FUJI_MX1700ZOOM, 1, 1 }, { "SP-2000",12, FUJI_SP2000, 0, 0 }, { 0, 0, 0, 0, 0 } }; #endif /* FUJIFILM_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/tagnames.c0000644000000000000000000012064113074742216016460 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFFJPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: tagnames.c,v 1.21 2005/07/24 19:40:09 alex Exp $"; #endif #include #include #include "defs.h" #include "defs.h" #include "datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "ciff.h" #include "dngtags.h" /* This function attempts to print a "canonical" name for every tag */ /* in the TIFF6, TIFF_EP, EXIF, DNG, and JPEG (10918-1) */ /* specifications, without intervention of arbitrary "defines"...what */ /* you see is what you get. */ /* The 'case' values are given in hex here, with the decimal values */ /* in leading comments, and the specifications in which the tag */ /* appears given in trailing comments. There are additonal private */ /* tags (not yet listed here) which may be found in the "tiff.h" file */ /* of the "libtiff" distribution by Sam Leffler (Silicon Graphics); */ char * tagname(unsigned short tag) { static char unknown_buf[16]; char *tagname; switch(tag) { /* 1 */ case 0x01: tagname = "PanasonicRawVersion"; break; /* RW2 */ /* 2 */ case 0x02: tagname = "SensorWidth"; break; /* RW2 */ /* 3 */ case 0x03: tagname = "SensorHeight"; break; /* RW2 */ /* 4 */ case 0x04: tagname = "SensorTopBorder"; break; /* RW2 */ /* 5 */ case 0x05: tagname = "SensorLeftBorder"; break; /* RW2 */ /* 6 */ case 0x06: tagname = "ImageHeight"; break; /* RW2 */ /* 7 */ case 0x07: tagname = "ImageWidth"; break; /* RW2 */ /* 17 */ case 0x11: tagname = "RedBalance"; break; /* RW2 */ /* 18 */ case 0x12: tagname = "BlueBalance"; break; /* RW2 */ /* 23 */ case 0x17: tagname = "ISO"; break; /* RW2 */ /* 36 */ case 0x24: tagname = "WBRedLevel"; break; /* RW2 */ /* 37 */ case 0x25: tagname = "WBGreenLevel"; break; /* RW2 */ /* 38 */ case 0x26: tagname = "WBBlueLevel"; break; /* RW2 */ /* 47 */ case 0x2E: tagname = "JpgFromRaw"; break; /* RW2 */ /* 254 */ case 0xFE: tagname = "NewSubFileType"; break; /* TIFF6, TIFFEP */ /* 255 */ case 0xFF: tagname = "SubFileType"; break; /* TIFF6 */ /* 256 */ case 0x100: tagname = "ImageWidth"; break; /* TIFF6 EXIF TIFFEP */ /* 257 */ case 0x101: tagname = "ImageLength"; break; /* TIFF6 EXIF TIFFEP */ /* 258 */ case 0x102: tagname = "BitsPerSample"; break; /* TIFF6 EXIF TIFFEP */ /* 259 */ case 0x103: tagname = "Compression"; break; /* TIFF6 EXIF TIFFEP */ /* 260 */ /* 261 */ /* 262 */ case 0x106: tagname = "PhotometricInterpretation"; break; /* TIFF6 EXIF TIFFEP */ /* 263 */ case 0x107: tagname = "Thresholding"; break; /* TIFF6 */ /* 264 */ case 0x108: tagname = "CellWiddth"; break; /* TIFF6 */ /* 265 */ case 0x109: tagname = "CellLength`"; break; /* TIFF6 */ /* 266 */ case 0x10A: tagname = "FillOrder"; break; /* TIFF6 */ /* 267 */ /* 268 */ /* 269 */ case 0x10D: tagname = "DocumentName"; break; /* TIFF6 */ /* 270 */ case 0x10E: tagname = "ImageDescription"; break; /* TIFF6 EXIF TIFFEP */ /* 271 */ case 0x10F: tagname = "Make"; break; /* TIFF6 EXIF TIFFEP */ /* 272 */ case 0x110: tagname = "Model"; break; /* TIFF6 EXIF TIFFEP */ /* 273 */ case 0x111: tagname = "StripOffsets"; break; /* TIFF6 EXIF TIFFEP */ /* 274 */ case 0x112: tagname = "Orientation"; break; /* TIFF6 EXIF TIFFEP */ /* 275 */ /* 276 */ /* 277 */ case 0x115: tagname = "SamplesPerPixel"; break; /* TIFF6 EXIF TIFFEP */ /* 278 */ case 0x116: tagname = "RowsPerStrip"; break; /* TIFF6 EXIF TIFFEP */ /* 279 */ case 0x117: tagname = "StripByteCounts"; break; /* TIFF6 EXIF TIFFEP */ /* 280 */ case 0x118: tagname = "MinSampleValue"; break; /* TIFF6 */ /* 281 */ case 0x119: tagname = "MaxSampleValue"; break; /* TIFF6 */ /* 282 */ case 0x11A: tagname = "XResolution"; break; /* TIFF6 EXIF TIFFEP */ /* 283 */ case 0x11B: tagname = "YResolution"; break; /* TIFF6 EXIF TIFFEP */ /* 284 */ case 0x11C: tagname = "PlanarConfiguration"; break; /* TIFF6 EXIF TIFFEP */ /* 285 */ case 0x11D: tagname = "PageName"; break; /* TIFF6 */ /* 286 */ case 0x11E: tagname = "XPosition"; break; /* TIFF6 */ /* 287 */ case 0x11F: tagname = "YPosition"; break; /* TIFF6 */ /* 288 */ case 0x120: tagname = "FreeOffsets"; break; /* TIFF6 */ /* 289 */ case 0x121: tagname = "FreeByteCounts"; break; /* TIFF6 */ /* 290 */ case 0x122: tagname = "GrayResponseUnit"; break; /* TIFF6 */ /* 291 */ case 0x123: tagname = "GrayResponseCurve"; break; /* TIFF6 */ /* 292 */ case 0x124: tagname = "T4Options"; break; /* TIFF6 */ /* 293 */ case 0x125: tagname = "T6Options"; break; /* TIFF6 */ /* 294 */ /* 295 */ /* 296 */ case 0x128: tagname = "ResolutionUnit"; break; /* TIFF6 EXIF TIFFEP */ /* 297 */ case 0x129: tagname = "PageNumber"; break; /* TIFF6 */ /* 298 */ /* 299 */ /* 300 */ case 0x12C: tagname = "ColorResponseUnit"; break; /* libtiff */ /* 301 */ case 0x12D: tagname = "TransferFunction"; break; /* TIFF6 EXIF */ /* 302 */ /* 303 */ /* 304 */ /* 305 */ case 0x131: tagname = "Software"; break; /* TIFF6 EXIF TIFFEP */ /* 306 */ case 0x132: tagname = "DateTime"; break; /* TIFF6 EXIF TIFFEP */ /* 307 - 314 */ /* 315 */ case 0x13B: tagname = "Artist"; break; /* TIFF6 EXIF TIFFEP */ /* 316 */ case 0x13C: tagname = "HostComputer"; break; /* TIFF6 */ /* 317 */ case 0x13D: tagname = "Predictor"; break; /* TIFF6 */ /* 318 */ case 0x13E: tagname = "WhitePoint"; break; /* TIFF6 EXIF */ /* 319 */ case 0x13F: tagname = "PrimaryChromaticities"; break; /* TIFF6 EXIF */ /* 320 */ case 0x140: tagname = "ColorMap"; break; /* TIFF6 */ /* 321 */ case 0x141: tagname = "HalftoneHints"; break; /* TIFF6 */ /* 322 */ case 0x142: tagname = "TileWidth"; break; /* TIFFEP TIFF6 */ /* 323 */ case 0x143: tagname = "TileLength"; break; /* TIFFEP TIFF6 */ /* 324 */ case 0x144: tagname = "TileOffsets"; break; /* TIFFEP TIFF6 */ /* 325 */ case 0x145: tagname = "TileByteCounts"; break; /* TIFFEP TIFF6 */ /* 326 */ case 0x146: tagname = "BadFaxLines"; break; /* libtiff */ /* 327 */ case 0x147: tagname = "CleanFaxData"; break; /* libtiff */ /* 328 */ case 0x148: tagname = "ConsecutiveBadFaxLines"; break; /* libtiff */ /* 329 */ /* 330 */ case 0x14A: tagname = "SubIFDs"; break; /* TIFFEP */ /* 331 */ /* 332 */ case 0x14C: tagname = "InkSet"; break; /* TIFF6 */ /* 333 */ case 0x14D: tagname = "InkNames"; break; /* TIFF6 */ /* 334 */ case 0x14E: tagname = "NumberOfInks"; break; /* TIFF6 */ /* 335 */ /* 336 */ case 0x150: tagname = "DotRange"; break; /* TIFF6 */ /* 337 */ case 0x151: tagname = "TargetPrinter"; break; /* TIFF6 */ /* 338 */ case 0x152: tagname = "ExtraSamples"; break; /* TIFF6 */ /* 339 */ case 0x153: tagname = "SampleFOrmat"; break; /* TIFF6 */ /* 340 */ case 0x154: tagname = "SMinSampleValue"; break; /* TIFF6 */ /* 341 */ case 0x155: tagname = "SMaxSampleValue"; break; /* TIFF6 */ /* 342 */ case 0x156: tagname = "TransferRange"; break; /* TIFF6 */ /* 343 - 346 */ /* 347 */ case 0x15B: tagname = "JPEGTables"; break; /* TIFFEP */ /* 348 - 511 */ /* 512 */ case 0x200: tagname = "JpegProc"; break; /* TIFF6 */ /* 513 */ case 0x201: tagname = "JPEGInterchangeFormat"; break; /* TIFF6 EXIF */ /* 514 */ case 0x202: tagname = "JPEGInterchangeFormatLength"; break; /* TIFF6 EXIF */ /* 515 */ case 0x203: tagname = "JPEGRestartInterval"; break; /* TIFF6 */ /* 516 */ /* 517 */ case 0x205: tagname = "JPEGLosslessPredictor"; break; /* TIFF6 */ /* 518 */ case 0x206: tagname = "JPEGPointTransforms"; break; /* TIFF6 */ /* 519 */ case 0x207: tagname = "JPEGQTables"; break; /* TIFF6 */ /* 520 */ case 0x208: tagname = "JPEGDCTables"; break; /* TIFF6 */ /* 521 */ case 0x209: tagname = "JPEGACTables"; break; /* TIFF6 */ /* 522 - 528 */ /* 529 */ case 0x211: tagname = "YCbCrCoefficients"; break; /* TIFF6 TIFFEP */ /* 530 */ case 0x212: tagname = "YCbCrSubSampling"; break; /* TIFF6 TIFFEP */ /* 531 */ case 0x213: tagname = "YCbCrPositioning"; break; /* TIFF6 TIFFEP */ /* 532 */ case 0x214: tagname = "ReferenceBlackWhite"; break; /* TIFF6 TIFFEP */ /* 700 */ case 0x2bc: tagname = "XMLPacket"; break; /* Adobe, libtiff */ /* 32953 */ case 0x80B9: tagname = "Refpts"; break; /* libtiff */ /* 32954 */ case 0x80BA: tagname = "Regiontackpoint"; break; /* libtiff */ /* 32955 */ case 0x80BB: tagname = "Regionwarpcorners"; break; /* libtiff */ /* 32956 */ case 0x80BC: tagname = "Regionaffine"; break; /* libtiff */ /* 32995 */ case 0x80E3: tagname = "Matteing"; break; /* libtiff */ /* 32996 */ case 0x80E4: tagname = "Datatype"; break; /* libtiff */ /* 32997 */ case 0x80E5: tagname = "Imagedepth"; break; /* libtiff */ /* 32998 */ case 0x80E6: tagname = "Tiledepth"; break; /* libtiff */ /* 33300 */ case 0x8214: tagname = "Pixar_imagefullwidth"; break; /* libtiff */ /* 33301 */ case 0x8215: tagname = "Pixar_imagefulllength"; break; /* libtiff */ /* 33302 */ case 0x8216: tagname = "Pixar_textureformat"; break; /* libtiff */ /* 33303 */ case 0x8217: tagname = "Pixar_wrapmodes"; break; /* libtiff */ /* 33304 */ case 0x8218: tagname = "Pixar_fovcot"; break; /* libtiff */ /* 33305 */ case 0x8219: tagname = "Pixar_matrix_worldtoscreen"; break; /* libtiff */ /* 33306 */ case 0x821A: tagname = "Pixar_matrix_worldtocamera"; break; /* libtiff */ /* 33405 */ case 0x827D: tagname = "Writerserialnumber"; break; /* libtiff */ /* 33421 */ case 0x828D: tagname = "EPCFARepeatPatternDim"; break; /* TIFFEP */ /* 33422 */ case 0x828E: tagname = "EPCFAPattern"; break; /* TIFFEP */ /* 33423 */ case 0x828F: tagname = "BatteryLevel"; break; /* TIFFEP */ /* 33432 */ case 0x8298: tagname = "Copyright"; break; /* TIFF6 EXIF TIFFEP */ /* 33434 */ case 0x829A: tagname = "ExposureTime"; break; /* EXIF TIFFEP */ /* 33437 */ case 0x829D: tagname = "FNumber"; break; /* EXIF TIFFEP */ /* 33550 */ case 0x830E: tagname = "GeoPixelScale"; break; /* libgeotiff */ /* 33723 */ case 0x83BB: tagname = "RichTiffIPTC"; break; /* TIFFEP */ /* 33920 */ case 0x8480: tagname = "IntergraphMatrix"; break; /* libgeotiff */ /* 33922 */ case 0x8482: tagname = "GeoTiePoints"; break; /* libgeotiff */ /* 34016 */ case 0x84E0: tagname = "IT8site"; break; /* libtiff */ /* 34017 */ case 0x84E1: tagname = "IT8colorsequence"; break; /* libtiff */ /* 34018 */ case 0x84E2: tagname = "IT8header"; break; /* libtiff */ /* 34019 */ case 0x84E3: tagname = "IT8rasterpadding"; break; /* libtiff */ /* 34020 */ case 0x84E4: tagname = "IT8bitsperrunlength"; break; /* libtiff */ /* 34021 */ case 0x84E5: tagname = "IT8bitsperextendedrunlength"; break; /* libtiff */ /* 34022 */ case 0x84E6: tagname = "IT8colortable"; break; /* libtiff */ /* 34023 */ case 0x84E7: tagname = "IT8imagecolorindicator"; break; /* libtiff */ /* 34024 */ case 0x84E8: tagname = "IT8bkgcolorindicator"; break; /* libtiff */ /* 34025 */ case 0x84E9: tagname = "IT8imagecolorvalue"; break; /* libtiff */ /* 34026 */ case 0x84EA: tagname = "IT8bkgcolorvalue"; break; /* libtiff */ /* 34027 */ case 0x84EB: tagname = "IT8pixelintensityrange"; break; /* libtiff */ /* 34028 */ case 0x84EC: tagname = "IT8transparencyindicator"; break; /* libtiff */ /* 34029 */ case 0x84ED: tagname = "IT8colorcharacterization"; break; /* libtiff */ /* 34232 */ case 0x85B8: tagname = "Framecount"; break; /* libtiff */ /* 34263 */ case 0x85D7: tagname = "JPLCartoIFD"; break; /* libgeotiff */ /* 34264 */ case 0x85D8: tagname = "GeoTransMatrix"; break; /* libgeotiff */ /* 34377 */ case 0x8649: tagname = "PhotoShop"; break; /* libtiff */ /* 34750 */ case 0x87BE: tagname = "JBIGoptions"; break; /* libtiff */ /* 34908 */ case 0x885C: tagname = "Faxrecvparams"; break; /* libtiff */ /* 34909 */ case 0x885D: tagname = "Faxsubaddress"; break; /* libtiff */ /* 34910 */ case 0x885E: tagname = "Faxrecvtime"; break; /* libtiff */ /* 34929 */ case 0x8871: tagname = "Fedex_edr"; break; /* libtiff */ /* 37439 */ case 0x923F: tagname = "StoNits"; break; /* libtiff */ /* 34665 */ case 0x8769: tagname = "ExifIFDPointer"; break; /* EXIF */ /* 34675 */ case 0x8773: tagname = "InterColorProfile3"; break; /* TIFFEP */ /* 34735 */ case 0x87AF: tagname = "GeoKeyDirectory"; break; /* libgeotiff */ /* 34736 */ case 0x87B0: tagname = "GeoDoubleParams"; break; /* libgeotiff */ /* 34737 */ case 0x87B1: tagname = "GeoAsciiParams"; break; /* libgeotiff */ /* 34850 */ case 0x8822: tagname = "ExposureProgram"; break; /* EXIF TIFFEP */ /* 34862 */ case 0x8824: tagname = "SpectralSensitivity"; break; /* EXIF TIFFEP */ /* 34853 */ case 0x8825: tagname = "GPSInfoIFDPointer"; break; /* EXIF TIFFEP */ /* 34855 */ case 0x8827: tagname = "ISOSpeedRatings"; break; /* EXIF TIFFEP */ /* 34856 */ case 0x8828: tagname = "OECF"; break; /* EXIF TIFFEP */ /* 34857 */ case 0x8829: tagname = "Interlace"; break; /* TIFFEP */ /* 34864 */ case 0x8830: tagname = "SensitivityType"; break; /* Exiv2 */ /* 34858 */ case 0x882A: tagname = "TimeZoneOffset"; break; /* TIFFEP */ /* 34859 */ case 0x882B: tagname = "SelfTimerMode"; break; /* TIFFEP */ /* 36864 */ case 0x9000: tagname = "Version"; break; /* EXIF */ /* 36867 */ case 0x9003: tagname = "DateTimeOriginal"; break; /* EXIF TIFFEP */ /* 36868 */ case 0x9004: tagname = "DateTimeDigitized"; break; /* EXIF */ /* 37121 */ case 0x9101: tagname = "ComponentsConfiguration"; break; /* EXIF */ /* 37122 */ case 0x9102: tagname = "CompressedBitsPerPixel"; break; /* EXIF TIFFEP */ /* 37377 */ case 0x9201: tagname = "ShutterSpeedValue"; break; /* EXIF TIFFEP */ /* 37378 */ case 0x9202: tagname = "ApertureValue"; break; /* EXIF TIFFEP */ /* 37379 */ case 0x9203: tagname = "BrightnessValue"; break; /* EXIF TIFFEP */ /* 37380 */ case 0x9204: tagname = "ExposureBiasValue"; break; /* EXIF TIFFEP */ /* 37381 */ case 0x9205: tagname = "MaxApertureValue"; break; /* EXIF TIFFEP */ /* 37382 */ case 0x9206: tagname = "SubjectDistance"; break; /* EXIF TIFFEP */ /* 37383 */ case 0x9207: tagname = "MeteringMode"; break; /* EXIF TIFFEP */ /* 37384 */ case 0x9208: tagname = "LightSource"; break; /* EXIF TIFFEP */ /* 37385 */ case 0x9209: tagname = "Flash"; break; /* EXIF TIFFEP */ /* 37386 */ case 0x920A: tagname = "FocalLength"; break; /* EXIF TIFFEP */ /* 37387 */ case 0x920B: tagname = "EPFlashEnergy"; break; /* TIFFEP */ /* 37388 */ case 0x920C: tagname = "EPSpatialFrequencyResponse"; break; /* TIFFEP */ /* 37389 */ case 0x920D: tagname = "Noise"; break; /* TIFFEP */ /* 37390 */ case 0x920E: tagname = "EPFocalPlaneXResolution"; break; /* TIFFEP */ /* 37391 */ case 0x920F: tagname = "EPFocalPlaneYResolution"; break; /* TIFFEP */ /* 37392 */ case 0x9210: tagname = "EPFocalPlaneResolutionUnit"; break; /* TIFFEP */ /* 37393 */ case 0x9211: tagname = "ImageNumber"; break; /* TIFFEP */ /* 37394 */ case 0x9212: tagname = "SecurityClassification"; break; /* TIFFEP */ /* 37395 */ case 0x9213: tagname = "ImageHistory"; break; /* TIFFEP */ /* 37396 */ case 0x9214: tagname = "SubjectArea"; break; /* TIFFEP EXIF2.2 */ /* 37397 */ case 0x9215: tagname = "EPExposureIndex"; break; /* TIFFEP */ /* 37398 */ case 0x9216: tagname = "TIFFEPStandardID"; break; /* TIFFEP */ /* 37399 */ case 0x9217: tagname = "EPSensingMethod"; break; /* TIFFEP */ /* 37500 */ case 0x927C: tagname = "MakerNote"; break; /* EXIF */ /* 37510 */ case 0x9286: tagname = "UserComment"; break; /* EXIF */ /* 37520 */ case 0x9290: tagname = "SubSecTime"; break; /* EXIF */ /* 37521 */ case 0x9291: tagname = "SubSecTimeOriginal"; break; /* EXIF */ /* 37522 */ case 0x9292: tagname = "SubSecTimeDigitized"; break; /* EXIF */ /* 40960 */ case 0xA000: tagname = "FlashPixVersion"; break; /* EXIF */ /* 40961 */ case 0xA001: tagname = "ColorSpace"; break; /* EXIF */ /* 40962 */ case 0xA002: tagname = "PixelXDimension"; break; /* EXIF */ /* 40963 */ case 0xA003: tagname = "PixelYDimension"; break; /* EXIF */ /* 40964 */ case 0xA004: tagname = "RelatedSoundFile"; break; /* EXIF */ /* 40965 */ case 0xA005: tagname = "Interoperability"; break; /* EXIF */ /* 41483 */ case 0xA20B: tagname = "FlashEnergy"; break; /* EXIF */ /* 41484 */ case 0xA20C: tagname = "SpatialFrequencyResponse"; break; /* EXIF */ /* 41486 */ case 0xA20E: tagname = "FocalPlaneXResolution"; break; /* EXIF */ /* 41487 */ case 0xA20F: tagname = "FocalPlaneYResolution"; break; /* EXIF */ /* 41488 */ case 0xA210: tagname = "FocalPlaneResolutionUnit"; break; /* EXIF */ /* 41492 */ case 0xA214: tagname = "SubjectLocation"; break; /* EXIF */ /* 41493 */ case 0xA215: tagname = "ExposureIndex"; break; /* EXIF */ /* 41495 */ case 0xA217: tagname = "SensingMethod"; break; /* EXIF */ /* 41728 */ case 0xA300: tagname = "FileSource"; break; /* EXIF */ /* 41729 */ case 0xA301: tagname = "SceneType"; break; /* EXIF */ /* 41730 */ case 0xA302: tagname = "CFAPattern"; break; /* EXIF */ /* 41985 */ case 0xA401: tagname = "CustomRendered"; break; /* EXIF */ /* 41986 */ case 0xA402: tagname = "ExposureMode"; break; /* EXIF */ /* 41987 */ case 0xA403: tagname = "WhiteBalance"; break; /* EXIF */ /* 41988 */ case 0xA404: tagname = "DigitalZoomRatio"; break; /* EXIF */ /* 41989 */ case 0xA405: tagname = "FocalLengthIn35mmFilm"; break; /* EXIF */ /* 41990 */ case 0xA406: tagname = "SceneCaptureType"; break; /* EXIF */ /* 41991 */ case 0xA407: tagname = "GainControl"; break; /* EXIF */ /* 41992 */ case 0xA408: tagname = "Contrast"; break; /* EXIF */ /* 41993 */ case 0xA409: tagname = "Saturation"; break; /* EXIF */ /* 41994 */ case 0xA40A: tagname = "Sharpness"; break; /* EXIF */ /* 41995 */ case 0xA40B: tagname = "DeviceSettingDescription"; break; /* EXIF */ /* 41996 */ case 0xA40C: tagname = "SubjectDistanceRange"; break; /* EXIF */ /* 42016 */ case 0xA420: tagname = "ImageUniqueId"; break; /* EXIF */ /* 42034 */ case 0xA432: tagname = "LensSpecification"; break; /* Fuji? Exiv2 */ /* 42035 */ case 0xA433: tagname = "LensMake"; break; /* Fuji? Exiv2 */ /* 42036 */ case 0xA434: tagname = "LensModel"; break; /* Fuji? Exiv2 */ /* 42037 */ case 0xA435: tagname = "LensSerial"; break; /* Fuji? Exiv2 */ /* 42240 */ case 0xA500: tagname = "Gamma"; break; /* EXIF 221 */ /* 50003 */ case 0xC353: tagname = "META_Model"; break; /* Kodak APP3 Meta */ /* 50341 */ case 0xC4A5: tagname = "PrintIM"; break; /* Epson PIM */ /* Don't know what these are; appear in Canon CR2 files */ /* 50648 */ case 0xC5D8: tagname = "TAG_CR2c5d8"; break; /* Canon CR2 */ /* 50649 */ case 0xC5D9: tagname = "TAG_CR2c5d9"; break; /* Canon CR2 */ /* 50656 */ case 0xC5E0: tagname = "TAG_CR2c5e0"; break; /* Canon CR2 */ /* 50752 */ case 0xC640: tagname = "CR2Slice"; break; /* Canon CR2 */ /* 50706 */ case 0xC612: tagname = "DNGVersion"; break; /* DNG */ /* 50707 */ case 0xC613: tagname = "DNGBackwardVersion"; break; /* DNG */ /* 50708 */ case 0xC614: tagname = "UniqueCameraModel"; break; /* DNG */ /* 50709 */ case 0xC615: tagname = "LocalizedCameraModel"; break; /* DNG */ /* 50710 */ case 0xC616: tagname = "CFAPlaneColor"; break; /* DNG */ /* 50711 */ case 0xC617: tagname = "CFALayout"; break; /* DNG */ /* 50712 */ case 0xC618: tagname = "LinearizationTable"; break; /* DNG */ /* 50713 */ case 0xC619: tagname = "BlackLevelRepeatDim"; break; /* DNG */ /* 50714 */ case 0xC61A: tagname = "BlackLevel"; break; /* DNG */ /* 50715 */ case 0xC61B: tagname = "BlackLevelDeltaH"; break; /* DNG */ /* 50716 */ case 0xC61C: tagname = "BlackLevelDeltaV"; break; /* DNG */ /* 50717 */ case 0xC61D: tagname = "WhiteLevel"; break; /* DNG */ /* 50718 */ case 0xC61E: tagname = "DefaultScale"; break; /* DNG */ /* 50719 */ case 0xC61F: tagname = "DefaultCropOrigin"; break; /* DNG */ /* 50720 */ case 0xC620: tagname = "DefaultCropSize"; break; /* DNG */ /* 50721 */ case 0xC621: tagname = "ColorMatrix1"; break; /* DNG */ /* 50722 */ case 0xC622: tagname = "ColorMatrix2"; break; /* DNG */ /* 50723 */ case 0xC623: tagname = "CameraCalibration1"; break; /* DNG */ /* 50724 */ case 0xC624: tagname = "CameraCalibration2"; break; /* DNG */ /* 50725 */ case 0xC625: tagname = "ReductionMatrix1"; break; /* DNG */ /* 50726 */ case 0xC626: tagname = "ReductionMatrix2"; break; /* DNG */ /* 50727 */ case 0xC627: tagname = "AnalogBalance"; break; /* DNG */ /* 50728 */ case 0xC628: tagname = "AsShotNeutral"; break; /* DNG */ /* 50729 */ case 0xC629: tagname = "AsShotWhiteXY"; break; /* DNG */ /* 50730 */ case 0xC62A: tagname = "BaselineExposure"; break; /* DNG */ /* 50731 */ case 0xC62B: tagname = "BaselineNoise"; break; /* DNG */ /* 50732 */ case 0xC62C: tagname = "BaselineSharpness"; break; /* DNG */ /* 50733 */ case 0xC62D: tagname = "BayerGreenSplit"; break; /* DNG */ /* 50734 */ case 0xC62E: tagname = "LinearResponseLimit"; break; /* DNG */ /* 50735 */ case 0xC62F: tagname = "CameraSerialNumber"; break; /* DNG */ /* 50736 */ case 0xC630: tagname = "LensInfo"; break; /* DNG */ /* 50737 */ case 0xC631: tagname = "ChromaBlurRadius"; break; /* DNG */ /* 50738 */ case 0xC632: tagname = "AntiAliasStrength"; break; /* DNG */ /* 50739 */ case 0xC633: tagname = "ShadowScale"; break; /* DNG */ /* 50740 */ case 0xC634: tagname = "DNGPrivateData"; break; /* DNG */ /* 50741 */ case 0xC635: tagname = "MakerNoteSafety"; break; /* DNG */ /* 50778 */ case 0xC65A: tagname = "CalibrationIlluminant1"; break; /* DNG */ /* 50779 */ case 0xC65B: tagname = "CalibrationIlluminant2"; break; /* DNG */ /* 50780 */ case 0xC65C: tagname = "BestQualityScale"; break; /* DNG */ /* 50781 */ case 0xC65D: tagname = "RawDataUniqueID"; break; /* DNG */ /* 50827 */ case 0xC68B: tagname = "OriginalRawFileName"; break; /* DNG */ /* 50828 */ case 0xC68C: tagname = "OriginalRawFileData"; break; /* DNG */ /* 50829 */ case 0xC68D: tagname = "ActiveArea"; break; /* DNG */ /* 50830 */ case 0xC68E: tagname = "MaskedAreas"; break; /* DNG */ /* 50831 */ case 0xC68F: tagname = "AsShotICCProfile"; break; /* DNG */ /* 50832 */ case 0xC690: tagname = "AsShotPreProfileMatrix"; break; /* DNG */ /* 50833 */ case 0xC691: tagname = "CurrentICCProfile"; break; /* DNG */ /* 50834 */ case 0xC692: tagname = "CurrentPreProfileMatrix"; break; /* DNG */ /* 50879 */ case 0xC6BF: tagname = "ColorimetricReference"; break; /* DNG 1.2 */ /* 50931 */ case 0xC6F3: tagname = "CameraCalibrationSignature"; break; /* DNG 1.2 */ /* 50932 */ case 0xC6F4: tagname = "ProfileCalibrationSignature"; break;/* DNG 1.2 */ /* 50933 */ case 0xC6F5: tagname = "ExtraCameraProfiles"; break; /* DNG 1.2 */ /* 50934 */ case 0xC6F6: tagname = "AsShotProfileName"; break; /* DNG 1.2 */ /* 50935 */ case 0xC6F7: tagname = "NoiseReductionApplied"; break; /* DNG 1.2 */ /* 50936 */ case 0xC6F8: tagname = "ProfileName"; break; /* DNG 1.2 */ /* 50937 */ case 0xC6F9: tagname = "ProfileHueSatMapDims"; break; /* DNG 1.2 */ /* 50938 */ case 0xC6FA: tagname = "ProfileHueSatMapData1"; break; /* DNG 1.2 */ /* 50939 */ case 0xC6FB: tagname = "ProfileHueSatMapData2"; break; /* DNG 1.2 */ /* 50940 */ case 0xC6FC: tagname = "ProfileToneCurve"; break; /* DNG 1.2 */ /* 50941 */ case 0xC6FD: tagname = "ProfileEmbedPolicy"; break; /* DNG 1.2 */ /* 50942 */ case 0xC6FE: tagname = "ProfileCopyright"; break; /* DNG 1.2 */ /* 50964 */ case 0xC714: tagname = "ForwardMatrix1"; break; /* DNG 1.2 */ /* 50965 */ case 0xC715: tagname = "ForwardMatrix2"; break; /* DNG 1.2 */ /* 50966 */ case 0xC716: tagname = "PreviewApplicationName"; break; /* DNG 1.2 */ /* 50967 */ case 0xC717: tagname = "PreviewApplicationVersion"; break; /* DNG 1.2 */ /* 50968 */ case 0xC718: tagname = "PreviewSettingsName"; break; /* DNG 1.2 */ /* 50969 */ case 0xC719: tagname = "PreviewSettingsDigest"; break; /* DNG 1.2 */ /* 50970 */ case 0xC71A: tagname = "PreviewColorSpace"; break; /* DNG 1.2 */ /* 50971 */ case 0xC71B: tagname = "PreviewDateTime"; break; /* DNG 1.2 */ /* 50972 */ case 0xC71C: tagname = "RawImageDigest"; break; /* DNG 1.2 */ /* 50973 */ case 0xC71D: tagname = "OriginalRawFileDigest"; break; /* DNG 1.2 */ /* 50974 */ case 0xC71E: tagname = "SubTileBlockSize"; break; /* DNG 1.2 */ /* 50975 */ case 0xC71F: tagname = "RowInterleaveFactor"; break; /* DNG 1.2 */ /* 50981 */ case 0xC725: tagname = "ProfileLookTableDims"; break; /* DNG 1.2 */ /* 50982 */ case 0xC726: tagname = "ProfileLookTableData"; break; /* DNG 1.2 */ /* 51008 */ case 0xC740: tagname = "OpcodeList1"; break; /* DNG 1.3 */ /* 51009 */ case 0xC741: tagname = "OpcodeList2"; break; /* DNG 1.3 */ /* 51022 */ case 0xC74E: tagname = "OpcodeList3"; break; /* DNG 1.3 */ /* 51041 */ case 0xC761: tagname = "NoiseProfile"; break; /* DNG 1.3 */ /* 51043 */ case DNGTAG_TimeCodes: tagname = "TimeCodes"; break; /* Cinama DNG */ /* 51044 */ case DNGTAG_FrameRate: tagname = "FrameRate"; break; /* Cinema DNG */ /* 51058 */ case DNGTAG_TStop: tagname = "TStop"; break; /* Cinema DNG */ /* 51081 */ case DNGTAG_ReelName: tagname = "ReelName"; break; /* Cinema DNG */ /* 51105 */ case DNGTAG_CameraLabel: tagname = "CameraLabel"; break; /* Cinema DNG */ /* 51089 */ case DNGTAG_OriginalDefaultFinalSize: tagname = "OriginalDefaultFinalSize"; break; /* DNG 1.4.0 */ /* 51090 */ case DNGTAG_OriginalBestQualityFinalSize: tagname = "OriginalBestQualityFinalSize"; break; /* DNG 1.4.0 */ /* 51091 */ case DNGTAG_OriginalDefaultCropSize: tagname = "OriginalDefaultCropSize"; break; /* DNG 1.4.0 */ /* 51107 */ case DNGTAG_ProfileHueSatMapEncoding: tagname = "ProfileHueSatMapEncoding"; break; /* DNG 1.4.0 */ /* 51108 */ case DNGTAG_ProfileLookTableEncoding: tagname = "ProfileLookTableEncoding"; break; /* DNG 1.4.0 */ /* 51109 */ case DNGTAG_BaselineExposureOffset: tagname = "BaselineExposureOffset"; break; /* DNG 1.4.0 */ /* 51110 */ case DNGTAG_DefaultBlackRender: tagname = "DefaultBlackRender"; break; /* DNG 1.4.0 */ /* 51111 */ case DNGTAG_NewRawImageDigest: tagname = "NewRawImageDigest"; break; /* DNG 1.4.0 */ /* 51112 */ case DNGTAG_RawToPreviewGain: tagname = "RawToPreviewGain"; break; /* DNG 1.4.0 */ /* 51125 */ case DNGTAG_DefaultUserCrop: tagname = "DefaultUserCrop"; break; /* DNG 1.4.0 */ /* %%%%% */ case 0xffc0: tagname = "JPEG_SOF_0"; break; /* JPEG */ /* EXIF */ /* %%%%% */ case 0xffc1: tagname = "JPEG_SOF_1"; break; /* JPEG */ /* %%%%% */ case 0xffc2: tagname = "JPEG_SOF_2"; break; /* JPEG */ /* %%%%% */ case 0xffc3: tagname = "JPEG_SOF_3"; break; /* JPEG */ /* %%%%% */ case 0xffc4: tagname = "JPEG_DHT"; break; /* JPEG */ /* EXIF */ /* %%%%% */ case 0xffc5: tagname = "JPEG_SOF_5"; break; /* JPEG */ /* %%%%% */ case 0xffc6: tagname = "JPEG_SOF_6"; break; /* JPEG */ /* %%%%% */ case 0xffc7: tagname = "JPEG_SOF_7"; break; /* JPEG */ /* %%%%% */ case 0xffc8: tagname = "JPEG_JPG"; break; /* JPEG */ /* %%%%% */ case 0xffc9: tagname = "JPEG_SOF_9"; break; /* JPEG */ /* %%%%% */ case 0xffca: tagname = "JPEG_SOF_10"; break; /* JPEG */ /* %%%%% */ case 0xffcb: tagname = "JPEG_SOF_11"; break; /* JPEG */ /* %%%%% */ case 0xffcd: tagname = "JPEG_SOF_13"; break; /* JPEG */ /* %%%%% */ case 0xffce: tagname = "JPEG_SOF_14"; break; /* JPEG */ /* %%%%% */ case 0xffcf: tagname = "JPEG_SOF_15"; break; /* JPEG */ /* %%%%% */ case 0xffcc: tagname = "JPEG_DAC"; break; /* JPEG */ /* %%%%% */ case 0xffd0: tagname = "JPEG_RST0"; break; /* JPEG */ /* %%%%% */ case 0xffd1: tagname = "JPEG_RST1"; break; /* JPEG */ /* %%%%% */ case 0xffd2: tagname = "JPEG_RST2"; break; /* JPEG */ /* %%%%% */ case 0xffd3: tagname = "JPEG_RST3"; break; /* JPEG */ /* %%%%% */ case 0xffd4: tagname = "JPEG_RST4"; break; /* JPEG */ /* %%%%% */ case 0xffd5: tagname = "JPEG_RST5"; break; /* JPEG */ /* %%%%% */ case 0xffd6: tagname = "JPEG_RST6"; break; /* JPEG */ /* %%%%% */ case 0xffd7: tagname = "JPEG_RST7"; break; /* JPEG */ /* %%%%% */ case 0xffd8: tagname = "JPEG_SOI"; break; /* JPEG */ /* EXIF */ /* ????? */ case 0x00d8: tagname = "JPEG_BADSOI"; break; /* Minolta MakerNote thumbnails */ /* %%%%% */ case 0xffd9: tagname = "JPEG_EOI"; break; /* JPEG */ /* EXIF */ /* %%%%% */ case 0xffda: tagname = "JPEG_SOS"; break; /* JPEG */ /* EXIF */ /* %%%%% */ case 0xffdb: tagname = "JPEG_DQT"; break; /* JPEG */ /* EXIF */ /* %%%%% */ case 0xffdc: tagname = "JPEG_DNL"; break; /* JPEG */ /* %%%%% */ case 0xffdd: tagname = "JPEG_DRI"; break; /* JPEG */ /* EXIF */ /* %%%%% */ case 0xffde: tagname = "JPEG_DHP"; break; /* JPEG */ /* %%%%% */ case 0xffdf: tagname = "JPEG_EXP"; break; /* JPEG */ /* %%%%% */ case 0xffe0: tagname = "JPEG_APP0"; break; /* JPEG */ /* %%%%% */ case 0xffe1: tagname = "JPEG_APP1"; break; /* JPEG */ /* EXIF */ /* %%%%% */ case 0xffe2: tagname = "JPEG_APP2"; break; /* JPEG */ /* EXIF */ /* %%%%% */ case 0xffe3: tagname = "JPEG_APP3"; break; /* JPEG */ /* %%%%% */ case 0xffe4: tagname = "JPEG_APP4"; break; /* JPEG */ /* %%%%% */ case 0xffe5: tagname = "JPEG_APP5"; break; /* JPEG */ /* %%%%% */ case 0xffe6: tagname = "JPEG_APP6"; break; /* JPEG */ /* %%%%% */ case 0xffe7: tagname = "JPEG_APP7"; break; /* JPEG */ /* %%%%% */ case 0xffe8: tagname = "JPEG_APP8"; break; /* JPEG */ /* %%%%% */ case 0xffe9: tagname = "JPEG_APP9"; break; /* JPEG */ /* %%%%% */ case 0xffea: tagname = "JPEG_APP10"; break; /* JPEG */ /* %%%%% */ case 0xffeb: tagname = "JPEG_APP11"; break; /* JPEG */ /* %%%%% */ case 0xffec: tagname = "JPEG_APP12"; break; /* JPEG */ /* %%%%% */ case 0xffed: tagname = "JPEG_APP13"; break; /* JPEG */ /* %%%%% */ case 0xffee: tagname = "JPEG_APP14"; break; /* JPEG */ /* %%%%% */ case 0xffef: tagname = "JPEG_APP15"; break; /* JPEG */ /* %%%%% */ case 0xfff0: tagname = "JPEG_JPG0"; break; /* JPEG */ /* %%%%% */ case 0xfff1: tagname = "JPEG_JPG1"; break; /* JPEG */ /* %%%%% */ case 0xfff2: tagname = "JPEG_JPG2"; break; /* JPEG */ /* %%%%% */ case 0xfff3: tagname = "JPEG_JPG3"; break; /* JPEG */ /* %%%%% */ case 0xfff4: tagname = "JPEG_JPG4"; break; /* JPEG */ /* %%%%% */ case 0xfff5: tagname = "JPEG_JPG5"; break; /* JPEG */ /* %%%%% */ case 0xfff6: tagname = "JPEG_JPG6"; break; /* JPEG */ /* %%%%% */ case 0xfff7: tagname = "JPEG_JPG7"; break; /* JPEG */ /* %%%%% */ case 0xfff8: tagname = "JPEG_JPG8"; break; /* JPEG */ /* %%%%% */ case 0xfff9: tagname = "JPEG_JPG9"; break; /* JPEG */ /* %%%%% */ case 0xfffa: tagname = "JPEG_JPG10"; break; /* JPEG */ /* %%%%% */ case 0xfffb: tagname = "JPEG_JPG11"; break; /* JPEG */ /* %%%%% */ case 0xfffc: tagname = "JPEG_JPG12"; break; /* JPEG */ /* %%%%% */ case 0xfffd: tagname = "JPEG_JPG13"; break; /* JPEG */ /* %%%%% */ case 0xfffe: tagname = "JPEG_COM"; break; /* JPEG */ /* %%%%% */ case 0xff01: tagname = "JPEG_TEM"; break; /* JPEG */ /* %%%%% */ case 0xff02: tagname = "JPEG_RES"; break; /* JPEG */ default: if(snprintf(unknown_buf,11,"TAG_%#06x",(int)tag) > 11) { printf(" bad tag %#x not converted\n",tag); why(stdout); tagname = ""; } else tagname = unknown_buf; break; } return(tagname); } char * interop_tagname(unsigned short tag) { static char unknown_buf[16]; char *tagname; switch(tag) { case 0x0001: tagname = "InteroperabilityIndex"; break; /* EXIF */ case 0x0002: tagname = "InteroperabilityVersion"; break; /* EXIF */ case 0x1000: tagname = "RelatedImageFileFormat"; break; /* EXIF */ case 0x1001: tagname = "RelatedImageWidth"; break; /* EXIF */ case 0x1002: tagname = "RelatedImageLength"; break; /* EXIF */ default: if(snprintf(unknown_buf,11,"IOP_%#06x",(int)tag) > 11) { printf(" bad tag %#x not converted\n",tag); why(stdout); tagname = ""; } else tagname = unknown_buf; break; } return(tagname); } char * gps_tagname(unsigned short tag) { static char unknown_buf[16]; char *tagname; switch(tag) { case 0x0000: tagname = "VersionID"; break; /* EXIF, TIFFEP */ case 0x0001: tagname = "LatitudeRef"; break; /* EXIF, TIFFEP */ case 0x0002: tagname = "Latitude"; break; /* EXIF, TIFFEP */ case 0x0003: tagname = "LongitudeRef"; break; /* EXIF, TIFFEP */ case 0x0004: tagname = "Longitude"; break; /* EXIF, TIFFEP */ case 0x0005: tagname = "AltitudeRef"; break; /* EXIF, TIFFEP */ case 0x0006: tagname = "Altitude"; break; /* EXIF, TIFFEP */ case 0x0007: tagname = "TimeStamp"; break; /* EXIF, TIFFEP */ case 0x0008: tagname = "Satellites"; break; /* EXIF, TIFFEP */ case 0x0009: tagname = "Status"; break; /* EXIF, TIFFEP */ case 0x000A: tagname = "MeasureMode"; break; /* EXIF, TIFFEP */ case 0x000B: tagname = "DOP"; break; /* EXIF, TIFFEP */ case 0x000C: tagname = "SpeedRef"; break; /* EXIF, TIFFEP */ case 0x000D: tagname = "Speed"; break; /* EXIF, TIFFEP */ case 0x000E: tagname = "TrackRef"; break; /* EXIF, TIFFEP */ case 0x000F: tagname = "Track"; break; /* EXIF, TIFFEP */ case 0x0010: tagname = "DirectionRef"; break; /* EXIF, TIFFEP */ case 0x0011: tagname = "Direction"; break; /* EXIF, TIFFEP */ case 0x0012: tagname = "MapDatum"; break; /* EXIF, TIFFEP */ case 0x0013: tagname = "DestlatitudeRef"; break; /* EXIF, TIFFEP */ case 0x0014: tagname = "Destlatitude"; break; /* EXIF, TIFFEP */ case 0x0015: tagname = "DestLongitudeRef"; break; /* EXIF, TIFFEP */ case 0x0016: tagname = "DestLongitude"; break; /* EXIF, TIFFEP */ case 0x0017: tagname = "BearingRef"; break; /* EXIF, TIFFEP */ case 0x0018: tagname = "Bearing"; break; /* EXIF, TIFFEP */ case 0x0019: tagname = "DestDistanceRef"; break; /* EXIF, TIFFEP */ case 0x001A: tagname = "DestDistance"; break; /* EXIF, TIFFEP */ case 0x001B: tagname = "ProcessingMethod"; break; /* EXIF */ case 0x001C: tagname = "AreaInformation"; break; /* EXIF */ case 0x001D: tagname = "DateStamp"; break; /* EXIF */ case 0x001E: tagname = "Differential"; break; /* EXIF */ default: if(snprintf(unknown_buf,11,"GPS_%#06x",(int)tag) > 11) { printf(" bad tag %#x not converted\n",tag); why(stdout); tagname = ""; } else tagname = unknown_buf; break; } return(tagname); } char * cifftagname(unsigned short tag) { static char unknown_buf[16]; char *tagname; switch(tag) { case 0x0000: tagname = "NullRecord"; break; case 0x0001: tagname = "FreeBytes"; break; case 0x0032: tagname = "ColorInfo1"; break; case 0x0805: tagname = "FileDescription"; break; case 0x080a: tagname = "RawMakeModel"; break; case 0x080b: tagname = "FirmwareVersion"; break; case 0x080c: tagname = "ComponentVersion"; break; case 0x080d: tagname = "RomOperationMode"; break; case 0x0810: tagname = "OwnerName"; break; case 0x0815: tagname = "ImageType"; break; case 0x0816: tagname = "OriginalFilename"; break; case 0x0817: tagname = "ThumbnailFilename"; break; case 0x100a: tagname = "TargetImageType"; break; case 0x1010: tagname = "ShutterReleaseMethod"; break; case 0x1011: tagname = "ShutterReleaseTiming"; break; case 0x1016: tagname = "ReleaseSetting"; break; case 0x101c: tagname = "BaseISO"; break; /* case 0x1028: tagname = "TAG_0x1028"; break; */ case 0x1029: tagname = "FocalLengthInfo"; break; case 0x102a: tagname = "ShotInfo"; break; case 0x102c: tagname = "ColorInfo2"; break; case 0x102d: tagname = "CameraSettings"; break; case 0x1031: tagname = "SensorInfo"; break; case 0x1033: tagname = "CustomFunctions"; break; case 0x1038: tagname = "PictureInfo"; break; /* case 0x1039: tagname = "TAG_0x1039"; break; */ /* case 0x1093: tagname = "TAG_0x1093"; break; */ /* case 0x10a8: tagname = "TAG_0x10a8"; break; */ case 0x10a9: tagname = "WhiteBalanceTable"; break; /* case 0x10aa: tagname = "TAG_0x10aa"; break; */ /* case 0x10ae: tagname = "TAG_0x10ae"; break; */ case 0x10b4: tagname = "ColorSpace"; break; /* case 0x10b5: tagname = "TAG_0x10b5"; break; */ /* case 0x10c0: tagname = "0X10c0"; break; */ /* case 0x10c1: tagname = "0X10c1"; break; */ case 0x1803: tagname = "ImageSpec"; break; case 0x1804: tagname = "RecordId"; break; case 0x1806: tagname = "SelfTimerTime"; break; case 0x1807: tagname = "TargetDistanceSetting"; break; case 0x180b: tagname = "SerialNumber"; break; case 0x180e: tagname = "CapturedTime"; break; case 0x1810: tagname = "ImageInfo"; break; case 0x1813: tagname = "FlashInfo"; break; case 0x1814: tagname = "MeasuredEv"; break; case 0x1817: tagname = "Filenumber"; break; case 0x1818: tagname = "ExposureInfo"; break; /* case 0x1834: tagname = "TAG_0x1834"; break; */ case 0x1835: tagname = "DecoderTable"; break; /* case 0x183b: tagname = "TAG_0X183b"; break; */ case 0x2005: tagname = "RawImageData"; break; case 0x2007: tagname = "JpegImage"; break; case 0x2008: tagname = "JpegThumbnail"; break; case 0x2804: tagname = "ImageDescription"; break; case 0x2807: tagname = "CameraObject"; break; case 0x3002: tagname = "ShootingRecord"; break; case 0x3003: tagname = "MeasuredInfo"; break; case 0x3004: tagname = "CameraSpecification"; break; case 0x300a: tagname = "ImageProperties"; break; case 0x300b: tagname = "ExifInformation"; break; default: if(snprintf(unknown_buf,11,"TAG_%#06x",(int)tag) > 11) { printf(" bad tag %#x not converted\n",tag); why(stdout); tagname = ""; } else tagname = unknown_buf; break; } tagname = strdup(tagname); return(tagname); } char * jp2000tagname(unsigned short tag) { static char unknown_buf[16]; char *tagname; switch(tag) { case 0xFF4F: tagname = "JP2C_SOC"; break; case 0xFF90: tagname = "JP2C_SOT"; break; case 0xFF93: tagname = "JP2C_SOD"; break; case 0xFFd9: tagname = "JP2C_EOC"; break; case 0xFF51: tagname = "JP2C_SIZ"; break; case 0xFF52: tagname = "JP2C_COD"; break; case 0xFF53: tagname = "JP2C_COC"; break; case 0xFF5e: tagname = "JP2C_RGN"; break; case 0xFF5c: tagname = "JP2C_QCD"; break; case 0xFF5d: tagname = "JP2C_QCC"; break; case 0xFF5F: tagname = "JP2C_POC"; break; case 0xFF55: tagname = "JP2C_TLM"; break; case 0xFF57: tagname = "JP2C_PLM"; break; case 0xFF58: tagname = "JP2C_PLT"; break; case 0xFF60: tagname = "JP2C_PPM"; break; case 0xFF61: tagname = "JP2C_PPT"; break; case 0xFF91: tagname = "JP2C_SOP"; break; case 0xFF92: tagname = "JP2C_EPH"; break; case 0xFF63: tagname = "JP2C_CRG"; break; case 0xFF64: tagname = "JP2C_COM"; break; default: if(snprintf(unknown_buf,12,"JP2C_%#06x",(int)tag) > 12) { printf(" bad tag %#x not converted\n",tag); why(stdout); tagname = ""; } else tagname = unknown_buf; break; } tagname = strdup(tagname); return(tagname); } exifprobe-2.0.1+git20170416-3c2b76/global.h0000644000000000000000000000245513074742216016130 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: global.h,v 1.6 2005/06/03 13:23:25 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef GLOBAL_INCLUDED #define GLOBAL_INCLUDED char *Progname; unsigned long Print_options = DEFAULT_OPTIONS; unsigned long Max_undefined = 0UL; unsigned long Max_makerdump = 0UL; unsigned long Max_appdump = 0UL; unsigned long Max_imgdump = 0UL; unsigned long Start_offset = 0UL; char *Make_name = (char *)0; char *Model_name = (char *)0; char *Software_name = (char *)0; /* Used for undocumented -m, -l, -s options. */ char *Use_Make_name = (char *)0; char *Use_Model_name = (char *)0; char *Use_Software_name = (char *)0; char *Camera_name_pattern = (char *)0; #endif exifprobe-2.0.1+git20170416-3c2b76/canon_extern.h0000644000000000000000000001051113074742216017343 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef CANON_EXTERN_INCLUDED #define CANON_EXTERN_INCLUDED /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Canon camera maker-specific external definitions */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ extern char *maker_canon_tagname(unsigned short,int); extern char *maker_canon1_tagname(unsigned short,int); extern int canon_model_number(char *,char *); extern int print_canon_serialno(unsigned long); extern void canon1_interpret_value(struct ifd_entry *); extern void print_canon_makervalue(struct ifd_entry *,int,int,char *); extern void print_canon1_makervalue(struct ifd_entry *,int,int,char *); extern void print_canon_offset_makervalue(FILE *,unsigned short, struct ifd_entry *,unsigned long, struct image_summary *,char *,char *, int,int,int,int); extern void canon1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *,unsigned long, struct image_summary *,char *,char *, int,int,int,int); extern unsigned long canon_camera_settings(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_shotinfo(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_customfunctions(FILE *,unsigned short,char *, unsigned long,unsigned long,int,int); extern unsigned long canon_customfunctions_unk(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_customfunctionsD30(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_customfunctions10D(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_customfunctions20D(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_customfunctions1D(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_sensorinfo(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_aspectinfo(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_pictureinfo(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_colorspace(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_whitebalancetable(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_imageinfo(FILE *,unsigned short,char *, unsigned long,unsigned long,int, struct image_summary *); extern unsigned long canon_exposureinfo(FILE *,unsigned short,char *, unsigned long,unsigned long,int, struct image_summary *); extern unsigned long canon_focusinfo(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern unsigned long canon_ct_to_datetime(FILE *,unsigned short,char *, unsigned long,unsigned long,int); extern int maker_canon_value_is_offset(struct ifd_entry *,int); #endif /* CANON_EXTERN_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/jp2_datadefs.h0000644000000000000000000000227113074742216017212 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: jp2_datadefs.h,v 1.1 2005/05/24 19:07:06 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef JP2_DATADEFS_INCLUDED #define JP2_DATADEFS_INCLUDED struct jp2_header { unsigned long length; unsigned long type; unsigned long magic; }; struct jp2box { unsigned long lbox; unsigned long tbox; unsigned long dataoffset; /* from boxoffset */ unsigned long boxoffset; /* ###%%% should be long long */ unsigned long boxlength; /* ###%%% should be long long */ }; #endif /* JP2_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/kodak_datadefs.h0000644000000000000000000000275413074742216017616 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: kodak_datadefs.h,v 1.2 2005/07/12 04:57:53 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef KODAK_DATADEFS_INCLUDED #define KODAK_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id kodak_model_id[] = { { "DC200 Zoom (V05.00)", 20, KODAK_DC200, 0, 0 }, { "DC210 Zoom (V05.00)", 20, KODAK_DC210, 0, 0 }, { "DCS720X", 7, KODAK_DCS720X, 0, 0 }, { "DCS760C", 7, KODAK_DCS760C, 0, 0 }, { "Kodak DC120 ZOOM Digital Camera", 32, KODAK_DK120, 0, 0 }, { "Kodak DC240 ZOOM Digital Camera", 32, KODAK_DC240, 0, 0 }, { "Kodak DC4800 ZOOM Digital Camera", 33, KODAK_DC4800, 0, 0 }, { "KODAK DC25 DIGITAL CAMERA", 25, KODAK_DC25, 0, 0 }, { "KODAK LS443 ZOOM DIGITAL CAMERA", 32, KODAK_LS443, 0, 0 }, { "Kodak Digital Science DC50 Zoom Camera", 39, KODAK_DC50, 0, 0 }, { 0, 0, 0, 0, 0 } }; #endif /* KODAK_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/maker_kodak.c0000644000000000000000000000262213074742216017127 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_kodak.c,v 1.2 2005/07/24 22:56:26 alex Exp $"; #endif #include #include #include #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "maker_extern.h" extern struct camera_id kodak_model_id[]; /* Find the identifying number assigned to known Kodak camera models. */ int kodak_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &kodak_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } exifprobe-2.0.1+git20170416-3c2b76/exifprobe.10000644000000000000000000005422713074742216016570 0ustar rootroot... ... (C) Copyright 2002, 2003, 2005 Duane H. Hesser, see LICENSE.EXIFPROBE file ... @(#) $Id: exifprobe.1,v 1.30 2005/07/12 18:16:47 alex Exp $ ... .TH EXIFPROBE 1 LOCAL .SH NAME exifprobe \- probe and report structure and metadata content of camera image files .SH SYNOPSIS .br .B exifprobe [\fIoptions\fP] \fIfilename(s)\fP .SH DESCRIPTION .B Exifprobe reads image files produced by digital cameras (including several so-called "raw" file formats) and reports the structure of the files and the auxilliary data and metadata contained within them. In addition to TIFF, JPEG, and EXIF, the program understands several formats which may contain "raw" camera data, including MRW, CIFF/CRW, JP2/JPEG2000, RAF, and X3F, as well as most most TIFF-derived "raw" formats, including DNG, ORF, CR2, NEF, K25/KDC/DCR, and PEF. Other TIFF or JPEG-derived formats (which begin with a TIFF header or JPEG marker) should also be readable. The program attempts to display ALL information in the image file, in a manner which mimics the structure of the file as closely as possible. Where possible, output is not limited to \*(lqknown\*(rq data items. I.e. for tagged file formats, unknown tags will be identified by tag number and type, and values shown without interpretation. Proprietary, untagged or fixed format files do not permit this, but unknown or undefined data can usually be dumped in a hex/ascii format for examination, so long as the file structure is understood. The program will report the contents of any properly structured TIFF IFD or CIFF directory encountered, even when entry tags are not recognized. Recognized TIFF, TIFF/EP, DNG, and CIFF tags are expanded, including EXIF2.2 sections and camera MakerNotes which are found to be in TIFF IFD format. TIFF and/or JPEG sections found in MRW, RAF or JP2 files will be reported, along with the \*(lqnative\*(rq sections of those formats. JP2 boxes will be reported whether known or unknown, and expanded if known. Unknown boxes cannot be expanded, since JP2 is not tagged below the box (or sub-box) level. An effort is made to identify all sub-images (in any image format) contained in multi-image files; the location, size, and format of such images is reported, and a hex/ascii dump of the image data may be requested. Image data is not processed, but the program will recognize and report all standard JPEG and JPEG2000 markers (including JPEG APPn markers) and will expand APP0 (JFIF/JFXX) and APP1 (EXIF) sections. Since the program does not attempt to display images or modify the contents of files, it can often recover from and report failures or warn about structural oddities which would confuse a display or image edit program. There are a wide variety of output formats, selectable in detail by the \*(lqlower case\*(rq options described in the \fBOPTIONS\fP section below. These options select which items to print, and within narrow confines, how and where to print them. A large number of combinations of options exist, and some of those combinations may not be sensible. In order to avoid the need for constant creativity or invention, three \*(lqprefabricated\*(rq output formats are provided, selected by the \fIupper case\fP option letters. The \fIstructural\fP (\fB-S\fP) output format (default) provides a description of the image file which mimics as closely as possible the layout and structure of the data in the image file, including file offsets of headers, section and segment markers, fully described TIFF IFDs, CIFF directories, or JP2 boxes, and the location of actual image and/or thumbnail data. The contents of each section are indented relative to the beginning of the section, and \*(rqoffset\*(rq values for TIFF IFDs and CIFF directories are reported at the offsets where they are found (usually following the entry list for TIFF, or in the HEAP for CIFF). The peculiar \*(lqreverse\*(rq structures of CIFF and X3F formats are handled sensibly. The \fIreport\fP format (\fB-R\fP) shows the \*(lqlogical\*(rq structure of the image file, but eliminates addresses, offsets, IFD value types and counts, etc., and prints \*(lqoffset\*(rq directory values inline, while otherwise preserving the primary structure of the data. The \fIlist\fP format (\fB-L\fP) omits all structural data. It writes only \*(lqtag\*(rq values from TIFF, Exif, and MakerNote IFDs, CIFF or other format directories or JP2 boxes, including section and image offsets and sizes. Identifiable values from non-tagged formats are written in a similar manner. This format may be useful for extracting information for photo galleries. The \fIstructural\fP format is default. This format provides maximum information about the contents of an image file, and may reveal information (sometimes important) which other formats (or image info programs) may hide. In all formats, the filename, file \fItype\fP, file size, an \fIimage summary\fP, and a summary \fIfile format\fP will be displayed (even when all other output is disabled by option). The image summary includes a summary report, for each subimage found, giving the image type, compression type (if any), pixel size, data length, file offset where found, and section of the file which includes or references the image. In some cases, short remarks may be included for images mentioned but not found, etc. The summary concludes with the number of images found, and number of images not found (if any). The summary is followed by a listing of format sections found (TIFF/JPEG/EXIF, etc.) and a type identifier for TIFF-derived types (e.g. \fICR2\fP) where possible. An environment variable may be set to a list of options to customize the default output behavior (see below). .SS MakerNotes Camera-generated images which contain EXIF sections may also contain sections introduced by a \fIMakerNote\fP tag, which may contain information about camera or firmware settings used to produce the image. The structure and contents of MakerNote sections is not mandated by the Exif specification, but many camera MakerNotes are written in TIFF IFD format, possibly offset following an ID string or new TIFF header (or both), and sometimes with inventive handling of \*(lqoffsets\*(rq. .B Exifprobe currently understands and automatically detects such schemes and prints the contents of the IFD (and the ID string, if present). This detection is not dependent upon make or model of camera. \fIMake\fP and \fIModel\fP information will usually be available from the first TIFF IFD in the file; this information may be used to \fIinterpret\fP the MakerNote information for \*(lqknown\*(rq cameras; otherwise, tag numbers, sizes, types, and raw values from the IFD will be shown (if permitted by option settings). Some camera makes are known to use more than one version of MakerNote, depending upon model. If an unknown model from that maker is encountered, the note will be briefly examined and a noteversion assigned automatically if possible. If that fails, the note will be displayed without interpretation. MakerNotes which are not in a recognizable IFD format will be reported (start and end offsets) in structural (\fB-S\fP) and report (\fI-R\fP) formats , and the beginning of the note section hex/ascii dumped. The remainder of the note may be dumped, in whole or in part, by the \fI-M\fP option (see below). In list (\fI-L\fP) format, the starting file offset and length supplied by the MakerNote tag will be reported, and three \*(lqpseudo\*(rq tags which report the offset (\fIMakerNote.Offset\fP), size (\fIMakerNote.Length\fP) and scheme (\fIMakerNote.Scheme\fP) will appear. .SS JPEG APPn In JPEG interchange format files, APP0 (JFIF,JFXX) and APP1 (Exif) segments will be fully decoded, and the \*(lqprintable\*(rq portions of APP12 sections will be displayed. APP3 (Meta) sections will be expanded and the contained TIFF IFD will be displayed, although little interpretation is done. Other APP markers will be reported, and the sections may be hex/ascii dumped in whole or in part using the \fI-A\fP option. APP1 sections not marked as \fIExif\fP will be treated as unknown. .SS ANSI Color The program (by default) emits ANSI color escape sequences to highlight Exif, MakerNote , and Interoperability sub-sections. Errors and warnings are highlighted in red. These sequences are effective, of course, only for terminals or terminal emulators (e.g. \fBxterm\fP) which respond to ANSI color escape sequences. If a pager is used to display the output when these sequences are present, a \*(lqraw\*(rq option to the pager may be required (e.g. \fBless\fP -R). The use of these sequences may be toggled by the \fB-c\fP option. LIST mode turns color sequences off. The program may be compiled without support for color sequences. .SH OUTPUT FORMATS In all formats, and regardless of option setting, the first three lines of output for each file processed are the filename, image \fItype\fP (TIFF, CIFF, JP2, etc.), and the file size. If the type (taken from the file header) specifies a data byte order, the byte order will be indicated with the type as `II' (Intel byte order) or `MM' (Motorola byte order). The image summary and summary format will always be printed at the end. .SS Structural Format Structural format output begins with a display of the file header. The header is followed by lines of the form .RS .I .RE .RS ... .RE .RS .RE .RS .I .RE .RS ... .RE .RS .RE .RS .I .RE .RS ... .RE .RS .RE etc. to indicate the beginning and end of each \*(lqsection\*(rq of the file. Actual section names will, of course, depend upon the file format and/or the tags encountered. Only the TIFF IFD format is described here; other formats are similar, except that JP2 box names are printed inside square (rather than angle) brackets, and MRW section names inside curly braces. Within sections, directory entries, subdirectories, the contents of known APP sections, JPEG segment markers, etc. are printed. Non-jpeg image data sections will be shown with a few lines of hex/ascii dump of the beginning of the data. Each line of output is preceded by a file offset given in hex and decimal. File offsets are preceded by the character `@', except that section end markers are preceded by `-' and the character `>' may be used to mark sections which are located outside the IFD in which they are declared. If that section includes a subsection which is similarly afflicted, the '>' is replaced by '+' in the subsection. In JP2 files, the '@' is replaced by '=', for no particular reason. JPEG and JPEG2000 segment markers are written with the marker name, and the decoded values of any information associated with the marker. TIFF information is written in a manner which reflects the structure of the IFD, with all values interpreted according to the applicable specification where possible. All IFD fields are reported. The following fields will appear on each line (in the order given, following the file offset): .IP \(bu Tag number in hex and decimal representations, enclosed in brackets. .IP \(bu Tag name (where known); names for unknown tags are created as a hex representation of the tag number prefixed by the string 'TAG_'. .IP \(bu The TIFF type number, name, and byte count for the associated value, enclosed in square brackets. .IP \(bu The \*(lqvalue/offset\*(rq for the entry. If the value fits in the four bytes of the entry, the value is printed directly. If the value for the entry did not fit in the four bytes of the entry, then the value found is an offset to the actual location of the data; that offset is printed preceded by an '@' symbol. The actual value will be printed later, at the file offset where it was found (except in some non-conforming MakerNote IFDs). If the value requires \fIinterpretation\fP (e.g. TIFF \fIOrientation\fP) it is followed by an '=' sign and the interpretation, enclosed in double quotes (e.g. \fI\*(lq0,0 top left\*(rq\fP). .P The list of entries will be followed by a line giving the offset to the next IFD (often 0) which is always found at the end of a TIFF IFD entry list. .P If there were offset entries found in the list above, the TIFF (and Exif) specification requires that they will be located next in the file, immediately following the dirctory entries. This stricture is frequently ignored in MakerNotes and TIFF-derived formats. A line reporting the beginning of these offset values will be printed immediately after the next IFD offset, followed by one line for each offset entry, with the tag name repeated, followed by the actual value, followed by its interpretation (if any). .P Multiple values in entries are printed on a single line, but large lists will be elided, with just the first two or three values shown, followed by an ellipsis, followed by the last value, the number of values, and the offset of the last value in the list. The full value list may be printed using the \fB-eA\fP option. .P In structural format, ascii strings in the entry are printed for the entire length given in the IFD entry, including nulls and non-ascii values (if present), which are printed in `backslashed' octal notation. The \fB-ea\fP option may be used to force ascii values to be printed only up to the first null. This option is often necessary for CIFF format files, and is enabled by default in \*(lqlist\*(rq mode. Entries are indented slightly from the start identifier for the IFD, and subsegments (e.g. an Exif IFD, SubIFD, or MakerNote) will be further indented in order to indicate the structure of the file. .P The resulting output displays the contents of the IFD much as it appears in the file (see the TIFF or EXIF specifications for descriptions of the IFD format). Finally, the start and end of actual image data for the primary image (and possibly thumbnail or reduced-resolution image) is reported at the end. For JPEG images, this usually includes display of the JPEG segment markers within the image. Binary format image data will be shown with a brief hex/ascii dump of the beginning of the data, between start and end markers. .I Note that \fIvalues\fP preceded by `@' are always offsets \fIfrom the beginning of the file\fP to the actual value. IFD offsets are usually recorded in the file as offsets relative to the beginning of the TIFF header (which is offset from the beginning of the file in JPEG APP1 files) but are adjusted by \fBexifprobe\fP to show offset from the beginning of the file. If it is important to see the recorded value, the \fB-er\fP option may be used to print the recorded value in parentheses, following the adjusted file offset. .SS Report Format The \fIreport\fP format (\fI-R\fP) displays all sections and segments of the image file, including start and end of sections, but eliminates much of the \*(lqcruft\*(rq of the structural format by eliminating address/offset information and much of the `internal' information from the TIFF IFD (tag number, type and count). \fIOffset\fP values are printed inline with the tag name. The output is indented to show the \fIlogical\fP structure of the image file, but is much less difficult to view than the structural format. .SS List format The \fIlist\fP format (\fI-L\fP) suppresses structural information, writing only \fIcontent\fP in the format \fItagname = value\fP or \fItagname = value = \*(lqwhat value means\*(rq\fP. For non-tagged file formats, the tagname will be replaced by a fixed identifier for the item. In LIST format, \*(lqlong\*(rq tagnames are used, which include the names of all parent sections of the section in which the data is found. Long tagnames can be toggled off, although this is unwise if the file contains multiple image sections. The \*(lqvalue\*(rq of tags or items which represent an offset to a subsection or image are printed in \fIlist\fP format as \*(lq\fI@offset:length\fP\*(rq. The List format is used by the auxilliary script \fBexifgrep\fP, which permits selective extraction of information e.g. for photo galleries, and output in (almost) \*(lqshell variable\*(rq format. .SS Custom Formats The \fB-Z\fP option \*(lqzeroes\*(rq all option flags (except the \fIlongnames\fP modifier), after which the lower-case options may be used to set desired options. The lower-case options are `toggles', which may also be used to turn \fIoff\fP items in the pre-defined formats. As an example, the command: .nf \fIexifprobe -Z -et somefile.tif\fP .fi may be used to list just the TIFF and Exif tags, without values (or anything else) in \*(lqlong name\*(rq format. .nf \fI exifprobe -eNnT somefile.tif\fP .fi will print in structural format, suppressing output of hex and decimal tag numbers, and tag type and count. The \*(lqzero-level\*(rq output still reports the file data and image summary as described above. .SH OPTIONS The environment variable \fBEXIFPROBE_OPTIONS\fP may be set to any valid option string, which will be evaluated before command line options. E.g. export EXIFPROBE_OPTIONS='-L -c' will make list format the default output format, and re-enable the color sequences turned off by \fI-L\fP. Options are evaluated from left to right, so \fB-Z\fP should be given first, while \fB-D\fP (decimal only) or \fB-X\fP (hex only) should be given last. .IP \-S 10 Structure mode: (default) almost everything; offset values not inline .IP \-R 10 Report mode: like structural, but only tagnames and decimal values, indented, inline .IP \-L 10 List mode: print only tags and values (including interpreted values); no section info; no color .IP \-Z 10 turn off (zero) all optional output. Prints only filename, filetype, filesize, image summary, and file format. .IP \-c 10 toggle use of ANSI color control sequences to emphasize EXIF sections. (default 'on' except list mode, unless compiled with no color support) .IP \-a 10 toggle printing of addresses (file offsets) in hex and decimal .IP \-I 10 three-way toggle indent (after address -> before -> none) .IP \-o 10 toggle \*(lqinline\*(rq print of offset IFD values .IP \-p[items] 10 toggle print identifiers for: .RS 10 .IP s 4 - sections (IFDs, APPn) .IP g 4 - segments (JPEG segments) .IP a 4 - JPEG APP0...APPn entries .IP l 4 - long names (dot-separated list of parent sections preceding item name) .IP e 4 - entries. Includes tag names, numbers, types, values. .IP m 4 - print MakerNote scheme description .IP M 4 - watch debug of MakerNote scheme detection .IP .RE .IP \-e[items] 10 toggle print IFD entry items: .RS 10 .IP t 4 - tagname .IP n 4 - tag number in decimal .IP N 4 - tag number in hex .IP T 4 - entry type and count .IP v 4 - value in decimal .IP V 4 - value in hex .IP o 4 - file offset to value in decimal .IP O 4 - file offset to value in hex .IP r 4 - relative (unadjusted) offset in decimal .IP R 4 - also print \*(lqraw\*(rq values where normal values are computed (e.g. rational values, or some MakerNote values where APEX values must be computed from a raw value). .IP A 4 - print ALL elements of multiple-value tags .IP a 4 - ascii "ignore length" (stop at first null) .RE .IP \-D 10 limit all enabled numerical values to decimal only (addresses, tag numbers, offsets, values) .IP \-X 10 limit all enabled numerical values to hex only (addresses, tag numbers, offsets, values) .IP \-U[len|a] 10 dump \fIlen\fP (or all) bytes of UNDEFINED data found in TIFF IFDS in hex/ascii form (but only if the structure of the data is not known) .IP \-M[len|a] 10 dump \fIlen\fP (or all) bytes of unrecognized MakerNotes in hex/ascii form (but only if the structure of the data is not known) .IP \-A[len|a] 10 dump \fIlen\fP (or all) bytes of unrecognized JPEG APP segments in hex/ascii form (but only if the structure of the data is not known) .IP \-B[len|a] 10 dump \fIlen\fP (or all) bytes of binary image data or failed JPEG image data .IP \-C[make]+[model] 10 print a list of camera makes/models matching .I make or .I model as substrings. .B `+' by itself prints everything .IP \-O\ start_offset 10 start processing at file offset .I start_offset .IP \-n 10 print filename at beginning of each line of output (useful when grepping multiple files in LIST mode) .IP \-N\ noteversion 10 force use of note version .I noteversion when interpreting MakerNotes. Useful only if you know what you're doing. .IP \-m\ make 10 Force the makernote code to interpret the note according to the \fImake\fP given, rather than that contained in the file. .IP \-l\ model 10 force the makernote code to interpret the note according to the \fImodel\fP given, rather than that contained in the file. .IP \-t 10 This option has effect only if set in \fBEXIFPROBE_OPTIONS\fP. If set when command line options are processed, color will be be off \fIby default\fP if the output is not to a tty. Any command line option which toggles or sets color (e.g. \*(lq-R\*(rq) will turn color back on. .IP \-u 10 Print \*(lqraw\*(rq Unicode data. Normally 16 bit data is printed as though the high byte is zero (which is often the case). Writing the nulls would annoy most ascii terminal devices, so the default is more hospitable. The \fI\-u\fP option forces printing of the full value. .IP \-h 10 print a help message .IP \-V 10 print program version and copyright .SH SEE ALSO .B exifgrep(1) .br The TIFF6 specification: .br https://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf .br The Exif 2.2 specification: .br http://tsc.jeita.or.jp/avs/data/cp3451.pdf .br The JFIF specification: .br http://www.w3.org/Graphics/JPEG/jfif3.pdf .br The TIFF/EP specification: .br http://www.map.tu.chiba-u.ac.jp/IEC/100/TA2/recdoc/N4378.pdf .br The CIFF specification http://xyrion.org/ciff/CIFFspecV1R04.pdf .br The X3F public specification http://www.sd9.org.uk/X3F_Format.pdf .br The JPEG2000 public draft (outdated) http://www.jpeg.org/public/fcd15444-1.pdf .SH DIAGNOSTICS Most diagnostics are printed \*(lqinline\*(rq to stdout, in red if color is enabled, and the program attempts to proceed. .SH BUGS Interpretation of MakerNote data for specific cameras is incomplete and probably always will be. The X3F specification is incomplete, and the final JPEG2000/JP2 specification is not freely available; support for these formats is therefore not complete, and may not be entirely accurate. The RAF file format support is preliminary (there is no published specification). Floating point values read from the file are expected to be in IEEE format (or at least, native format); i.e. no conversions are attempted. ANSI color sequence support should use termcap/terminfo facilities; it does not. .SH AUTHOR .br Duane H. Hesser .br dhh@virtual-cafe.com exifprobe-2.0.1+git20170416-3c2b76/mrw.h0000644000000000000000000000227713074742216015477 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: mrw.h,v 1.1 2005/05/25 00:53:56 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef MRW_INCLUDED #define MRW_INCLUDED /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Minolta MRW definitions and incluedes */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #define MRM_PRD 0x00505244 #define MRM_TTW 0x00545457 #define MRM_WBG 0x00574247 #define MRM_RIF 0x00524946 #define MRM_PAD 0x00504144 #include "mrw_datadefs.h" #include "mrw_extern.h" #endif /* MRW_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/maker_olympus.c0000644000000000000000000015170513074742216017555 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_olympus.c,v 1.25 2005/07/24 22:56:26 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Olympus camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Most of the information coded here is due to TsuruZoh Tachibanaya */ /* at: */ /* http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* April, 2005: */ /* Much of the new information for later models is taken from */ /* information provided by a Phil Harvey (author of 'exiftool') at: */ /* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/index.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "maker_extern.h" extern struct camera_id olympus_model_id[]; /* Find the identifying number assigned to known Olympus camera */ /* models. This number is used to dispatch print and interpret */ /* routines approopriate to the current image. */ int olympus_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &olympus_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine based upon model */ void print_olympus_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 1: print_olympus1_makervalue(entry_ptr,make,model,PREFIX); olympus1_interpret_value(entry_ptr); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Olympus cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_olympus1_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { if(entry_ptr) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for Olympus */ /* cameras. */ void print_olympus_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) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 1: olympus1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); olympus1_interpret_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in OLYMPUS makernotes. */ void olympus1_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) { unsigned long value_offset,max_offset; unsigned long dumplength; unsigned long count; unsigned short marker; char *nameoftag; char *fulldirname = CNULL; int status = 0; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); if((PRINT_LONGNAMES)) { fulldirname = splice(parent_name,".",nameoftag); nameoftag = fulldirname; } value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0209: /* CameraId */ if(at_offset) { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,MAKERTAGWIDTH," = ",make,model); } if((PRINT_VALUE)) print_ascii(inptr,entry_ptr->count,value_offset); break; case 0x0100: /* JPEG Thumbnail in TIFF MakerNote */ if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix); chpr += printf("# Start of JPEG Thumbnail from MakerNote"); chpr += printf(" length %lu",count); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%-9lu",value_offset,entry_ptr->count); else chpr += printf(":%-9lu", entry_ptr->count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); setcharsprinted(chpr); chpr = 0; max_offset = process_jpeg_segments(inptr,value_offset,marker, count,summary_entry,fulldirname, prefix,indent+SMALLINDENT); if(at_offset) { if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1, indent,"-"); chpr += printf("# End of JPEG Thumbnail from MakerNote"); if((PRINT_ENTRY) && !(PRINT_VALUE)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_IFD; summary_entry->subfiletype = THUMBNAIL_TYPE; } } /* make certain we're at the end */ clearerr(inptr); fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0f00: /* Data */ if(at_offset && (PRINT_ENTRY)) { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,MAKERTAGWIDTH," : ",make,model); chpr += printf("length %-9lu # UNDEFINED", count); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%-9lu",value_offset,entry_ptr->count); else chpr += printf(":%-9lu", entry_ptr->count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } if(Max_undefined == 0) { if(chpr) printred(" (not dumped, use -U)"); } else { if((Max_undefined == DUMPALL) || (Max_undefined > count)) dumplength = count; else dumplength = Max_undefined; chpr = newline(chpr); hexdump(inptr,value_offset,count,dumplength,12, indent,SUBINDENT); chpr = newline(1); } /* make certain we're at the end */ fseek(inptr,value_offset + count,SEEK_SET); break; case 0x2010: /* Private IFD's all */ case 0x2020: case 0x2030: case 0x2040: case 0x2050: if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",value_offset); } chpr = newline(chpr); max_offset = entry_ptr->value + fileoffset_base + entry_ptr->count; max_offset = process_private_ifd(inptr,byteorder,entry_ptr->value, fileoffset_base,max_offset,entry_ptr->tag, summary_entry,nameoftag,prefix, make,model,indent); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Olympus-specific tagnames for makernotes. */ /* The tagname routine is the first place in the code path which */ /* requires knowledge of the note version. If the version is not */ /* given in the model table (e.g. the model is unknown), then switch */ /* code in find_maker_scheme() should have set it. This routine */ /* repeats the check for non-zero noteversion and is prepared to set */ /* the noteversion first time through, but should never need to do */ /* so. Noteversion should always be non-zero; it should be set to -1 */ /* if generic processing is required. */ char * maker_olympus_tagname(unsigned short tag,int model) { char *tagname = CNULL; int noteversion = 0; if((noteversion = getnoteversion()) == 0) { /* Need more model samples before it is safe to assume a */ /* default */ noteversion = 1; setnoteversion(1); } /* Check specific models first */ switch(noteversion) { case 1: tagname = maker_olympus1_tagname(tag,model); break; default: break; } return(tagname); } char * maker_olympus1_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0100: tagname = "JpegThumbnail"; break; case 0x0200: tagname = "SpecialMode"; break; case 0x0201: tagname = "CompressionMode"; break; /* "Quality"? */ case 0x0202: tagname = "Macro"; break; case 0x0203: tagname = "BWMode"; break; case 0x0204: tagname = "DigitalZoom"; break; case 0x0205: tagname = "FocalplaneDiagonal"; break; case 0x0207: tagname = "SoftwareRelease"; break; case 0x0208: tagname = "PictureInfo"; break; case 0x0209: tagname = "CameraID"; break; case 0x020b: tagname = "ImageWidth"; break; /* ? */ case 0x020c: tagname = "ImageHeight"; break; /* ? */ case 0x0f00: tagname = "Data"; break; case 0x0300: tagname = "PrecaptureFrames"; break; case 0x0302: tagname = "OneTouchWB"; break; case 0x1004: tagname = "FlashMode"; break; case 0x1005: tagname = "FlashDevice"; break; case 0x1006: tagname = "Bracket"; break; case 0x100b: tagname = "FocusMode"; break; case 0x100c: tagname = "FocusDistance"; break; case 0x100d: tagname = "Zoom"; break; case 0x100e: tagname = "MacroFocus"; break; case 0x100f: tagname = "SharpnessFactor"; break; case 0x1011: tagname = "ColorMatrix"; break; case 0x1012: tagname = "BlackLevel"; break; case 0x1015: tagname = "WhiteBalance"; break; case 0x1017: tagname = "RedBalance"; break; case 0x1018: tagname = "BlueBalance"; break; case 0x101a: tagname = "SerialNumber"; break; case 0x1023: tagname = "FlashBias"; break; case 0x1029: tagname = "Contrast"; break; case 0x102a: tagname = "SharpnessFactor"; break; case 0x102b: tagname = "ColorControl"; break; case 0x102c: tagname = "ValidBits"; break; case 0x102d: tagname = "CoringFilter"; break; case 0x102e: tagname = "ImageWidth"; break; case 0x102f: tagname = "ImageHeight"; break; case 0x1034: tagname = "CompressionRatio"; break; case 0x1035: tagname = "PreviewImageValid"; break; case 0x1036: tagname = "PreviewImageOffset"; break; case 0x1037: tagname = "PreviewImageLength"; break; case 0x2010: tagname = "Equipment"; break; /* IFD */ case 0x2020: tagname = "CameraSettings"; break; /* IFD */ case 0x2030: tagname = "RawDevelopment"; break; /* IFD */ case 0x2040: tagname = "ImageProcessing"; break; /* IFD */ case 0x2050: tagname = "FocusInfo"; break; /* IFD */ default: break; } setnotetagset(1); return(tagname); } void olympus1_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0201: /* Compression Mode */ print_startvalue(); /* This appears to report "compression" only, while the */ /* camera's "quality" setting combines compression and */ /* image size in incomprehensible ways. */ switch(entry_ptr->value) { case 1: chpr += printf("SQ"); break; case 2: chpr += printf("HQ"); break; case 3: chpr += printf("SHQ"); break; case 4: chpr += printf("RAW1"); break; case 6: chpr += printf("RAW2"); break; case 33: chpr += printf("not compressed"); break; /* TIFF */ case 34: /* not sure about this one ###%%% */ chpr += printf("not compressed"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0202: /* Macro */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Macro"); break; case 2: chpr += printf("View"); break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } void olympus1_interpret_offset_makervalue(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base) { unsigned long offset,value; int chpr = 0; if((entry_ptr) && (PRINT_VALUE)) { offset = entry_ptr->value + fileoffset_base; switch(entry_ptr->tag) { case 0x0200: /* SpecialMode */ value = read_ulong(inptr,byteorder,offset); print_startvalue(); switch(value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Unkown"); break; case 2: chpr += printf("Fast"); break; case 3: chpr += printf("Panorama,"); value = read_ulong(inptr,byteorder,HERE); chpr += printf("#%lu,",value); value = read_ulong(inptr,byteorder,HERE); switch(value) { case 1: chpr += printf(" Left to Right"); break; case 2: chpr += printf(" Right to Left"); break; case 3: chpr += printf(" Bottom to Top"); break; case 4: chpr += printf(" Top to Bottom"); break; default: printred(" undefined"); break; } break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } /* ================== OLYMPUS SUBIFD ======================== */ char * olympus_private_tagname(unsigned short tag,unsigned short subifd_ident) { char *tagname = CNULL; switch(subifd_ident) { case 0x2010: tagname = olympus_private_2010_tagname(tag); break; case 0x2020: tagname = olympus_private_2020_tagname(tag); break; case 0x2030: tagname = olympus_private_2030_tagname(tag); break; case 0x2040: tagname = olympus_private_2040_tagname(tag); break; case 0x2050: tagname = olympus_private_2050_tagname(tag); break; default: break; } return(tagname); } char * olympus_private_2010_tagname(unsigned short tag) { char *tagname = CNULL; switch(tag) { case 0x0000: tagname = "EquipmentInfoVersion"; break; case 0x0100: tagname = "FirmwareVersion2"; break; case 0x0101: tagname = "SerialNumber"; break; case 0x0103: tagname = "FocalPlaneDiagonal"; break; case 0x0104: tagname = "BodyFirmwareVersion"; break; case 0x0201: tagname = "Lens"; break; case 0x0202: tagname = "LensSerialNumber"; break; case 0x0204: tagname = "LensFirmwareVersion"; break; case 0x0206: tagname = "MaxApertureAtMaxFocal"; break; case 0x0207: tagname = "MinFocalLength"; break; case 0x0208: tagname = "MaxFocalLength"; break; case 0x0301: tagname = "Extender"; break; case 0x0302: tagname = "ExtenderSerialNumber"; break; case 0x0304: tagname = "ExtenderFirmwareVersion"; break; case 0x1000: tagname = "FlashType"; break; case 0x1001: tagname = "FlashModel"; break; case 0x1003: tagname = "FlashSerialNumber"; break; case 0x1004: tagname = "FlashFirmwareVersion"; break; default: break; } return(tagname); } char * olympus_private_2020_tagname(unsigned short tag) { char *tagname = CNULL; switch(tag) { case 0x0000: tagname = "CameraSettingsVersion"; break; case 0x0100: tagname = "PreviewImageValid"; break; case 0x0101: tagname = "PreviewImageOffset"; break; case 0x0102: tagname = "PreviewImageLength"; break; case 0x0200: tagname = "ExposureMode"; break; case 0x0202: tagname = "MeteringMode"; break; case 0x0300: tagname = "MacroMode"; break; case 0x0301: tagname = "FocusMode"; break; case 0x0302: tagname = "FocusProcess"; break; case 0x0303: tagname = "AFSearch"; break; case 0x0304: tagname = "AFAreas"; break; case 0x0400: tagname = "FlashMode"; break; case 0x0401: tagname = "FlashExposureCompensation"; break; case 0x0501: tagname = "WhiteBalanceTemperature"; break; case 0x0502: tagname = "WhiteBalanceBracket"; break; case 0x0503: tagname = "CustomSaturation"; break; case 0x0504: tagname = "ModifiedSaturation"; break; case 0x0505: tagname = "ContrastSetting"; break; case 0x0506: tagname = "SharpnessSetting"; break; case 0x0507: tagname = "ColorSpace"; break; case 0x0509: tagname = "SceneMode"; break; case 0x050a: tagname = "NoiseReduction"; break; case 0x050b: tagname = "DistortionCorrection"; break; case 0x050c: tagname = "ShadingCompensation"; break; case 0x050d: tagname = "CompressionFactor"; break; case 0x050f: tagname = "Gradation"; break; case 0x0600: tagname = "Sequence"; break; case 0x0603: tagname = "ImageQuality2"; break; default: break; } return(tagname); } char * olympus_private_2030_tagname(unsigned short tag) { char *tagname = CNULL; switch(tag) { case 0x0000: tagname = "RawDevVersion"; break; case 0x0100: tagname = "RawDevExposureBiasValue"; break; case 0x0101: tagname = "RawDevWhiteBalanceValue"; break; case 0x0102: tagname = "RawDevWBFineAdjustment"; break; case 0x0103: tagname = "RawDevGrayPoint"; break; case 0x0104: tagname = "RawDevSaturationEmphasis"; break; case 0x0105: tagname = "RawDevMemoryColorEmphasis"; break; case 0x0106: tagname = "RawDevContrastValue"; break; case 0x0107: tagname = "RawDevSharpnessValue"; break; case 0x0108: tagname = "RawDevColorSpace"; break; case 0x0109: tagname = "RawDevEngine"; break; case 0x010a: tagname = "RawDevNoiseReduction"; break; case 0x010b: tagname = "RawDevEditStatus"; break; case 0x010c: tagname = "RawDevSettings"; break; default: break; } return(tagname); } char * olympus_private_2040_tagname(unsigned short tag) { char *tagname = CNULL; switch(tag) { case 0x0000: tagname = "ImageProcessingVersion"; break; case 0x0100: tagname = "RedBlueBias"; break; case 0x0200: tagname = "ColorMatrix"; break; case 0x0300: tagname = "SmoothingParameter1"; break; case 0x0310: tagname = "SmoothingParameter2"; break; case 0x0600: tagname = "SmoothingThresholds"; break; case 0x0610: tagname = "SmoothingThreshold2"; break; case 0x0611: tagname = "ValidBits"; break; case 0x0614: tagname = "ImageWidth2"; break; case 0x0615: tagname = "ImageHeight2"; break; case 0x1010: tagname = "NoiseFilter2"; break; case 0x1012: tagname = "ShadingCompensation2"; break; default: break; } return(tagname); } char * olympus_private_2050_tagname(unsigned short tag) { char *tagname = CNULL; switch(tag) { case 0x0000: tagname = "FocusInfoVersion"; break; case 0x0209: tagname = "AutoFocus?"; break; case 0x0300: tagname = "ZoomPosition"; break; case 0x0305: tagname = "FocusDistance"; break; case 0x1201: tagname = "ExternalFlash"; break; case 0x1208: tagname = "InternalFlash"; break; default: break; } return(tagname); } void olympus_interpret_pe_value(struct ifd_entry *entry_ptr,unsigned short subifd_ident, char *prefix) { if(entry_ptr) { switch(subifd_ident) { case 0x2010: olympus2010_interpret_value(entry_ptr,prefix); break; case 0x2020: olympus2020_interpret_value(entry_ptr,prefix); break; case 0x2030: olympus2030_interpret_value(entry_ptr,prefix); break; case 0x2040: olympus2040_interpret_value(entry_ptr,prefix); break; case 0x2050: olympus2050_interpret_value(entry_ptr,prefix); break; default: break; } } } void olympus2010_interpret_value(struct ifd_entry *entry_ptr,char *prefix) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x1000: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("None"); break; case 2: chpr += printf("Simple E-System"); break; case 3: chpr += printf("E-System"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x1001: print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("FL-20"); break; case 2: chpr += printf("FL-50"); break; case 3: chpr += printf("RF-11"); break; case 4: chpr += printf("TF-22"); break; case 5: chpr += printf("FL-36"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } void olympus2020_interpret_value(struct ifd_entry *entry_ptr,char *prefix) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0100: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("No"); break; case 1: chpr += printf("yes"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0200: print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Manual"); break; case 3: chpr += printf("Aperture-priority"); break; case 4: chpr += printf("Shutter-priority"); break; case 5: chpr += printf("Program AE"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0202: print_startvalue(); switch(entry_ptr->value) { case 2: chpr += printf("Center Weighted"); break; case 3: chpr += printf("Spot"); break; case 5: chpr += printf("ESP"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0300: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0301: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Single AF"); break; case 1: chpr += printf("Sequential Shooting AF"); break; case 2: chpr += printf("Continuous AF"); break; case 3: chpr += printf("Multi AF"); break; case 10: chpr += printf("Manual"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0302: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("AF Off"); break; case 1: chpr += printf("AF On"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0303: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Not Ready"); break; case 1: chpr += printf("Ready"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0504: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("CM1 (Red Enhance)"); break; case 2: chpr += printf("CM2 (Green Enhance)"); break; case 3: chpr += printf("CM3 (Blue Enhance)"); break; case 4: chpr += printf("CM4 (Skin Tones)"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0507: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("sRGB"); break; case 1: chpr += printf("Adobe RGB"); break; case 2: chpr += printf("Pro Photo RGB"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0509: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Standard"); break; case 7: chpr += printf("Sport"); break; case 8: chpr += printf("Portrait"); break; case 9: chpr += printf("Landscape+Portrait"); break; case 10: chpr += printf("Landscape"); break; case 11: chpr += printf("Night schene"); break; case 17: chpr += printf("Night+Portrait"); break; case 19: chpr += printf("Fireworks"); break; case 20: chpr += printf("Sunset"); break; case 22: chpr += printf("Macro"); break; case 25: chpr += printf("Documents"); break; case 26: chpr += printf("Museum"); break; case 28: chpr += printf("Beach&Snow"); break; case 30: chpr += printf("Candle"); break; case 39: chpr += printf("High Key"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x050a: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("Noise Reduction On"); break; case 2: chpr += printf("Noise Filter On"); break; case 3: chpr += printf("Noise Reduction + Noise Filter On"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x050b: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x050c: print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x050f: print_startvalue(); switch(entry_ptr->value) { case -1: chpr += printf("Low Key"); break; case 0: chpr += printf("Normal"); break; case 1: chpr += printf("High Key"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0600: chpr += printf("%#x,%#x",(unsigned short)entry_ptr->value & 0xffff,(unsigned short)((entry_ptr->value & 0xffff0000) >> 16)); break; case 0x0603: print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("SQ"); break; case 2: chpr += printf("HQ"); break; case 3: chpr += printf("SHQ"); break; case 4: chpr += printf("RAW1"); break; case 6: chpr += printf("RAW2"); break; case 33: chpr += printf("not compressed"); break; case 34: /* not sure about this one ###%%% */ chpr += printf("not compressed"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } void olympus2030_interpret_value(struct ifd_entry *entry_ptr,char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: break; } } } void olympus2040_interpret_value(struct ifd_entry *entry_ptr,char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: break; } } } void olympus2050_interpret_value(struct ifd_entry *entry_ptr,char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: break; } } } /* Pick the appropriate offset value processor for Olympus private */ /* IFDs based upon noteversion. */ void olympus_offset_pe_value(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base, unsigned short subifd_ident,struct image_summary *summary_entry, char *parent_name,char*prefix, int indent,int make,int model,int at_offset) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 1: olympus1_offset_pe_value(inptr,byteorder,entry_ptr, fileoffset_base,subifd_ident, summary_entry,parent_name,prefix, indent,make,model,at_offset); olympus1_interpret_offset_pe_value(inptr,byteorder,entry_ptr, fileoffset_base,subifd_ident); break; default: print_private_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,subifd_ident, parent_name,prefix,indent, make,model,at_offset); break; } } } /* Pick the appropriate offset value processor for Olympus */ /* noteversion 1 private IFDs, based upon the tag number of the IFD. */ void olympus1_offset_pe_value(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base, unsigned short subifd_ident,struct image_summary *summary_entry, char *parent_name,char*prefix, int indent,int make,int model,int at_offset) { if(entry_ptr) { switch(subifd_ident) { case 0x2010: olympus2010_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case 0x2020: olympus2020_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case 0x2030: olympus2030_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case 0x2040: olympus2040_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case 0x2050: olympus2050_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; default: print_private_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,subifd_ident, parent_name,prefix,indent, make,model,at_offset); break; } } } /* Olympus 'Equipment' IFD from Makernote (0x2010) */ void olympus2010_offset_value(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) { unsigned long value_offset; unsigned long count; char *nameoftag; char *fulldirname = CNULL; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); if((PRINT_LONGNAMES)) { fulldirname = splice(parent_name,".",nameoftag); nameoftag = fulldirname; } value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0100: case 0x0101: case 0x0102: case 0x0202: case 0x0301: case 0x0302: case 0x1003: default: print_private_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,0x2010, fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Olympus 'CameraSettings' IFD from Makernote (0x2020) */ void olympus2020_offset_value(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) { static unsigned long jpegthumbnailoffset = 0UL; static unsigned long jpegthumbnailvalid = 1UL; unsigned long value_offset,max_offset; unsigned long count; unsigned short marker; char *nameoftag; char *fulldirname = CNULL; int status = 0; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); if((PRINT_LONGNAMES)) { fulldirname = splice(parent_name,".",nameoftag); nameoftag = fulldirname; } value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0100: /* JPEG Thumbnail valid */ /* The default is 1 (valid), so this can turn off */ /* processing if present and 0. Better to attempt */ /* processing when invalid than miss a valid image. */ jpegthumbnailvalid = value_offset; break; case 0x0101: /* JPEG Thumbnail offset */ jpegthumbnailoffset = value_offset; if(!(PRINT_VALUE_AT_OFFSET)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",jpegthumbnailoffset); } break; case 0x0102: /* JPEG Thumbnail length */ if(jpegthumbnailvalid == 0) { jpegthumbnailvalid = 0; break; } if(jpegthumbnailoffset) { count = entry_ptr->value; value_offset = jpegthumbnailoffset; jpegthumbnailoffset = 0UL; } else { printred("# Warning: no thumbnail offset"); break; } indent += SMALLINDENT; if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix); chpr += printf("# Start of JPEG Thumbnail from MakerNote SubIFD"); chpr += printf(" length %ld",count); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); max_offset = process_jpeg_segments(inptr,value_offset,marker, count,summary_entry,fulldirname, prefix,indent+MEDIUMINDENT); if(at_offset) { if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1, indent,"-"); chpr += printf("# End of JPEG Thumbnail from MakerNote SubIFD"); if((PRINT_ENTRY) && !(PRINT_VALUE)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_SUBIFD; summary_entry->subfiletype = REDUCED_RES_TYPE; } } /* make certain we're at the end */ clearerr(inptr); fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0304: case 0x0503: case 0x0505: case 0x0506: case 0x050f: default: print_private_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,0x2020, fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Olympus 'RawDevelopment' IFD from Makernote (0x2030) */ void olympus2030_offset_value(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) { unsigned long value_offset; unsigned long count; char *nameoftag; char *fulldirname = CNULL; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); if((PRINT_LONGNAMES)) { fulldirname = splice(parent_name,".",nameoftag); nameoftag = fulldirname; } value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { default: print_private_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,0x2030, fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Olympus 'ImageProcessing' IFD from Makernote (0x2040) */ void olympus2040_offset_value(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) { unsigned long value_offset; unsigned long count; char *nameoftag; char *fulldirname = CNULL; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); if((PRINT_LONGNAMES)) { fulldirname = splice(parent_name,".",nameoftag); nameoftag = fulldirname; } value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { default: print_private_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,0x2040, fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Olympus 'FocusInfo' IFD from Makernote (0x2050) */ void olympus2050_offset_value(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) { unsigned long value_offset; unsigned long count; char *nameoftag; char *fulldirname = CNULL; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); if((PRINT_LONGNAMES)) { fulldirname = splice(parent_name,".",nameoftag); nameoftag = fulldirname; } value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { default: print_private_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,0x2050, fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } void olympus1_interpret_offset_pe_value(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base, unsigned short subifd_ident) { if(entry_ptr) { switch(subifd_ident) { case 0x2010: olympus2010_interpret_offset_value(inptr,byteorder,entry_ptr,fileoffset_base); break; case 0x2020: olympus2020_interpret_offset_value(inptr,byteorder,entry_ptr,fileoffset_base); break; case 0x2030: olympus2030_interpret_offset_value(inptr,byteorder,entry_ptr,fileoffset_base); break; case 0x2040: olympus2040_interpret_offset_value(inptr,byteorder,entry_ptr,fileoffset_base); break; case 0x2050: olympus2050_interpret_offset_value(inptr,byteorder,entry_ptr,fileoffset_base); break; default: break; } } } void olympus2010_interpret_offset_value(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base) { unsigned long offset; if(entry_ptr) { offset = entry_ptr->value + fileoffset_base; switch(entry_ptr->tag) { default: break; } } } void olympus2020_interpret_offset_value(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base) { unsigned long offset; if(entry_ptr) { offset = entry_ptr->value + fileoffset_base; switch(entry_ptr->tag) { default: break; } } } void olympus2030_interpret_offset_value(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base) { unsigned long offset; if(entry_ptr) { offset = entry_ptr->value + fileoffset_base; switch(entry_ptr->tag) { default: break; } } } void olympus2040_interpret_offset_value(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base) { unsigned long offset; if(entry_ptr) { offset = entry_ptr->value + fileoffset_base; switch(entry_ptr->tag) { default: break; } } } void olympus2050_interpret_offset_value(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base) { unsigned long offset; if(entry_ptr) { offset = entry_ptr->value + fileoffset_base; switch(entry_ptr->tag) { default: break; } } } int olympus_private_value_is_offset(unsigned short subifd_ident,unsigned short tag) { int is_offset = 0; switch(subifd_ident) { case 0x2010: break; case 0x2020: is_offset = olympus2020_value_is_offset(tag); break; case 0x2030: break; case 0x2040: break; case 0x2050: break; default: break; } return(is_offset); } int olympus2020_value_is_offset(unsigned short tag) { int is_offset = 0; switch(tag) { case 0x0100: is_offset = -1; break; case 0x0101: is_offset = 1; break; case 0x0102: is_offset = -1; break; default: break; } return(is_offset); } exifprobe-2.0.1+git20170416-3c2b76/maker_agfa.c0000644000000000000000000003636213074742216016744 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_agfa.c,v 1.19 2005/07/24 22:56:26 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* AGFA camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* This information is from a page by Johannes Tschebisch at: */ /* http://www.jojotsch.de/downloads/jojothumb/beispiele/ */ /* html_exif/bilder/agfa-c150.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "summary.h" #include "datadefs.h" #include "maker_datadefs.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id agfa_model_id[]; /* Find the identifying number assigned to known Agfa camera */ /* models. This number is used to dispatch print and interpret */ /* routines approopriate to the current image. */ int agfa_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &agfa_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine based upon model */ void print_agfa_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { int noteversion; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 1: print_agfa1_makervalue(entry_ptr,make,model,prefix); agfa1_interpret_value(entry_ptr); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Agfa cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_agfa1_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for Agfa */ /* cameras. */ 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) { int noteversion; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 1: agfa1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); agfa1_interpret_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base); break; default: /* Insufficent information about other models to do */ /* anything but generic. */ print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; } } } /* Model-specific routine to print values found at offsets in Agfa */ /* makernotes. One of these may be supplied for each unique note */ /* version */ 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) { unsigned long max_offset = 0; unsigned long value_offset; unsigned long dumplength,count; unsigned short marker; char *nameoftag; char *fulldirname = NULL; int status = 0; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0209: /* CameraId */ if(at_offset && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,23," = ",make,model); } if((PRINT_VALUE)) print_ascii(inptr,entry_ptr->count,value_offset); break; case 0x0100: /* Jpeg Thumbnail */ if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix); chpr += printf("# Start of JPEG Thumbnail from MakerNote"); chpr += printf(" length %ld",count); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",value_offset); else chpr = printf("length %lu",count); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); max_offset = process_jpeg_segments(inptr,value_offset,marker, count,summary_entry,fulldirname, prefix,indent+SMALLINDENT); if(at_offset) { if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1, indent,"-"); chpr += printf("# End of JPEG Thumbnail from MakerNote"); if((PRINT_ENTRY) && !(PRINT_VALUE)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_IFD; summary_entry->subfiletype = THUMBNAIL_TYPE; } } /* make certain we're at the end */ clearerr(inptr); fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0f00: /* Data */ if(at_offset && (PRINT_ENTRY)) { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,MAKERTAGWIDTH," : ",make,model); chpr += printf(" length %-9lu", count); if(Max_undefined == 0) { if(chpr) printred(" (not dumped, use -U)"); } else { if((Max_undefined == DUMPALL) || (Max_undefined > count)) dumplength = count; else dumplength = Max_undefined; chpr = newline(chpr); hexdump(inptr,value_offset,count,dumplength,12, indent,SUBINDENT); chpr = newline(1); } } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,entry_ptr->count); else chpr = printf("length %lu", entry_ptr->count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } /* make certain we're at the end */ fseek(inptr,value_offset + count,SEEK_SET); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Agfa-specific tagnames for makernotes. */ char * maker_agfa_tagname(unsigned short tag,int model) { char *tagname = CNULL; int noteversion = 0; /* Should have to do this only once, and only for unrecognized */ /* models. If the model is recognized (or the user has forced a */ /* noteversion) noteversion will already be set. */ if((noteversion = getnoteversion()) == 0) { noteversion = 1; setnoteversion(1); } switch(noteversion) { case 1: tagname = maker_agfa1_tagname(tag); break; default: setnotetagset(noteversion); /* for info only */ break; } /* If no model-specific tag is found, check "generic" tags */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } char * maker_agfa1_tagname(unsigned short tag) { char *tagname = CNULL; switch(tag) { case 0x0100: tagname = "JpegThumbnail"; break; case 0x0200: tagname = "SpecialMode"; break; case 0x0201: tagname = "Quality"; break; case 0x0202: tagname = "Macro"; break; case 0x0204: tagname = "DigitalZoom"; break; case 0x0207: tagname = "SoftwareRelease"; break; case 0x0208: tagname = "PictureInfo"; break; case 0x0209: tagname = "CameraID"; break; case 0x020b: tagname = "ImageWidth"; break; /* ? */ case 0x020c: tagname = "ImageHeight"; break; /* ? */ case 0x0f00: tagname = "Data"; break; default: break; } setnotetagset(1); return(tagname); } void agfa1_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0201: /* Compression Mode */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("SQ"); break; case 2: chpr += printf("HQ"); break; case 3: chpr += printf("SHQ"); break; case 33: chpr += printf("not compressed"); break; /* TIFF */ case 34: /* not sure about this one ###%%% */ chpr += printf("not compressed"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0202: /* Macro */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Macro"); break; case 2: chpr += printf("View"); break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } } void agfa1_interpret_offset_makervalue(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base) { unsigned long offset,value; int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { offset = entry_ptr->value + fileoffset_base; switch(entry_ptr->tag) { case 0x0200: /* SpecialMode */ value = read_ulong(inptr,byteorder,offset); print_startvalue(); switch(value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Unkown"); break; case 2: chpr += printf("Fast"); break; case 3: chpr += printf("Panorama,"); value = read_ulong(inptr,byteorder,HERE); chpr += printf("#%lu,",value); value = read_ulong(inptr,byteorder,HERE); switch(value) { case 1: chpr += printf(" Left to Right"); break; case 2: chpr += printf(" Right to Left"); break; case 3: chpr += printf(" Bottom to Top"); break; case 4: chpr += printf(" Top to Bottom"); break; default: printred(" undefined"); break; } break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } exifprobe-2.0.1+git20170416-3c2b76/hp_datadefs.h0000644000000000000000000000176013074742216017130 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: hp_datadefs.h,v 1.1 2005/06/21 15:34:51 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef HP_DATADEFS_INCLUDED #define HP_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id hp_model_id[] = { { "HP PhotoSmart C912", 18, HP_C912, 0, 0 }, { "HP PhotoSmart R707", 18, HP_R707, 0, 0 }, { 0, 0, 0, 0, 0 } }; #endif /* HP_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/CREDITS0000644000000000000000000000660513074742216015540 0ustar rootrootMost of the MakerNote information in the exifprobe code is taken from documents posted to the web by the people listed below. If errors exist, they are likely due to transription errors on my part, or to additions I have made after examining a few images (notify me at dhh@virutal-cafe.com). If I've missed a proper attribution, please let me know about that, too. /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Nikon, Fujitsu (Fujifilm), Olympus */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ TsuruZoh Tachibanaya at: http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html The Nikon E990 data in that document is attributed to Max Lyons, and may also be found at: http://www.tawbaware.com/990exif.htm Additonal tags for later Nikons (specifically E5700) from web page by Johannes Tschebisch at: http://www.jojotsch.de/ The Casio information in that document is attributed to Eckhard Henkel: (see Dicasoft below) The Olympus information in that document is attributed to Peter Esherick. /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Canon */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ David Burren at: http://www.burren.cx/david/canon.html /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Casio (older models) */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ Dicasoft: http://www.dicasoft.de/casiomn.htm /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Sanyo */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ John Hawkins at: http://www.exif.org/makernotes/SanyoMakerNote.html /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Minolta DiMAGE 5, 7*, S304, S404, S414, F300 */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ Dalibor Jelinek at: http://www.dalibor.cz/minolta/makernote.htm Upates for A1, A2 by Stanislav Brabec http://www.penguin.cz/~utx /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Panasonic */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ Tom Hughes tom@compton.nu /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Sigma/Foveon (NOTE: manufacturer data!) */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ http://www.x3f.info/technotes/FileDocs/MakerNoteDoc.html /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* PrintIM structure, Asahi makernotes, latest Casio notes */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ evan@ozhiker.com http://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* April, 2005: Olympus, Nikon, Canon, Asahi updates; some CIFF info */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ Phil Harvey (author of 'exiftool') at: http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/index.html exifprobe-2.0.1+git20170416-3c2b76/nikon_datadefs.h0000644000000000000000000000327513074742216017642 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: nikon_datadefs.h,v 1.3 2005/06/30 18:36:00 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef NIKON_DATADEFS_INCLUDED #define NIKON_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id nikon_model_id[] = { { "E700", 5, NIKON_700, 1, 1 }, { "E775", 5, NIKON_775, 2, 2 }, { "E800", 5, NIKON_800, 1, 1 }, { "E885", 5, NIKON_885, 2, 2 }, { "E900", 5, NIKON_900, 1, 1 }, { "E950", 5, NIKON_950, 1, 1 }, { "E990", 5, NIKON_990, 2, 2 }, { "E995", 5, NIKON_995, 2, 2 }, { "E3700", 6, NIKON_3700, 2, 2 }, { "E5000", 6, NIKON_5000, 2, 2 }, { "E5200", 6, NIKON_5200, 2, 2 }, { "E5700", 6, NIKON_5700, 2, 2 }, { "E8700", 6, NIKON_8700, 2, 2 }, { "E8800", 6, NIKON_8800, 2, 2 }, { "NIKON D1 ",10, NIKON_D1, 2, 2 }, { "NIKON D1X",10, NIKON_D1X, 2, 2 }, { "NIKON D70", 10, NIKON_D70, 2, 2 }, { "NIKON D100 ", 12, NIKON_D100, 2, 2 }, { "NIKON D2H",10, NIKON_D2H, 2, 2 }, { "NIKON D2X",10, NIKON_D2X, 2, 2 }, { "SQ ",5, NIKON_SQ, 2, 2 }, { 0, 0, 0, 0, 0 } }; #endif /* NIKON_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/private_tags.h0000644000000000000000000001267613074742216017366 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: private_tags.h,v 1.8 2005/07/15 17:41:41 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* "private" TIFF tags assigned by Adobe to vendors */ /* Most of these are taken from libtiff/tiff.h, viz. */ /* A few are taken from GeoTIFF */ #ifndef PRIVATE_TAGS_INCLUDED #define PRIVATE_TAGS_INCLUDED #define TIFFTAG_XML 0x02bc /* 700 */ #define TIFFTAG_REFPTS 0x80B9 /* 32953 */ #define TIFFTAG_REGIONTACKPOINT 0x80BA /* 32954 */ #define TIFFTAG_REGIONWARPCORNERS 0x80BB /* 32955 */ #define TIFFTAG_REGIONAFFINE 0x80BC /* 32956 */ #define TIFFTAG_MATTEING 0x80E3 /* 32995 */ #define TIFFTAG_DATATYPE 0x80E4 /* 32996 */ #define TIFFTAG_IMAGEDEPTH 0x80E5 /* 32997 */ #define TIFFTAG_TILEDEPTH 0x80E6 /* 32998 */ #define TIFFTAG_PIXAR_IMAGEFULLWIDTH 0x8214 /* 33300 */ #define TIFFTAG_PIXAR_IMAGEFULLLENGTH 0x8215 /* 33301 */ #define TIFFTAG_PIXAR_TEXTUREFORMAT 0x8216 /* 33302 */ #define TIFFTAG_PIXAR_WRAPMODES 0x8217 /* 33303 */ #define TIFFTAG_PIXAR_FOVCOT 0x8218 /* 33304 */ #define TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN 0x8219 /* 33305 */ #define TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA 0x821A /* 33306 */ #define TIFFTAG_WRITERSERIALNUMBER 0x827D /* 33405 */ #define TIFFTAG_GEOPIXELSCALE 0x830e /* 33550 */ #define TIFFTAG_RICHTIFFIPTC 0x83bb /* 33723 */ #define TIFFTAG_INTERGRAPH_MATRIX 0x8480 /* 33920 */ #define TIFFTAG_GEOTIEPOINTS 0x8482 /* 33922 */ #define TIFFTAG_IT8SITE 0x84E0 /* 34016 */ #define TIFFTAG_IT8COLORSEQUENCE 0x84E1 /* 34017 */ #define TIFFTAG_IT8HEADER 0x84E2 /* 34018 */ #define TIFFTAG_IT8RASTERPADDING 0x84E3 /* 34019 */ #define TIFFTAG_IT8BITSPERRUNLENGTH 0x84E4 /* 34020 */ #define TIFFTAG_IT8BITSPEREXTENDEDRUNLENGTH 0x84E5 /* 34021 */ #define TIFFTAG_IT8COLORTABLE 0x84E6 /* 34022 */ #define TIFFTAG_IT8IMAGECOLORINDICATOR 0x84E7 /* 34023 */ #define TIFFTAG_IT8BKGCOLORINDICATOR 0x84E8 /* 34024 */ #define TIFFTAG_IT8IMAGECOLORVALUE 0x84E9 /* 34025 */ #define TIFFTAG_IT8BKGCOLORVALUE 0x84EA /* 34026 */ #define TIFFTAG_IT8PIXELINTENSITYRANGE 0x84EB /* 34027 */ #define TIFFTAG_IT8TRANSPARENCYINDICATOR 0x84EC /* 34028 */ #define TIFFTAG_IT8COLORCHARACTERIZATION 0x84ED /* 34029 */ #define TIFFTAG_FRAMECOUNT 0x85B8 /* 34232 */ #define TIFFTAG_JPL_CARTO_IFD 0x85D7 /* 34263 */ #define TIFFTAG_GEOTRANSMATRIX 0x85D8 /* 34264 */ #define TIFFTAG_ICCPROFILE 0x8773 /* 34675 */ #define TIFFTAG_PHOTOSHOP 0x8649 /* 34377 */ #define TIFFTAG_GEOKEYDIRECTORY 0x87AF /* 34735 */ #define TIFFTAG_GEODOUBLEPARAMS 0x87B0 /* 34736 */ #define TIFFTAG_GEOASCIIPARAMS 0x87B1 /* 34737 */ #define TIFFTAG_JBIGOPTIONS 0x87BE /* 34750 */ #define TIFFTAG_FAXRECVPARAMS 0x885C /* 34908 */ #define TIFFTAG_FAXSUBADDRESS 0x885D /* 34909 */ #define TIFFTAG_FAXRECVTIME 0x885E /* 34910 */ #define TIFFTAG_FEDEX_EDR 0x8871 /* 34929 */ #define TIFFTAG_STONITS 0x923F /* 37439 */ /* Kodak APP3 Meta */ #define TIFFTAG_META_0xc353 0xC353 /* 50003 */ #define TIFFTAG_PrintIM 0xC4A5 /* 50341 */ /* Canon CR2 files */ #define TIFFTAG_CR2_0xc5d8 0xC5D8 /* 50648 */ #define TIFFTAG_CR2_0xc5d9 0xC5D9 /* 50649 */ #define TIFFTAG_CR2_0xc5e0 0xC5E0 /* 50656 */ #define TIFFTAG_CR2_SLICE 0xC640 /* 50752 */ #define TIFFTAG_CR2_SRAWTYPE 0xC6C5 /* 50885 */ /* Panasonic RAW / RW2 */ #define TIFFTAG_RW2_PANASONICRAWVERSION 0x0001 /* 00001 */ #define TIFFTAG_RW2_SENSORWIDTH 0x0002 /* 00002 */ #define TIFFTAG_RW2_SENSORHEIGHT 0x0003 /* 00003 */ #define TIFFTAG_RW2_SENSORTOPBORDER 0x0004 /* 00004 */ #define TIFFTAG_RW2_SENSORLEFTBORDER 0x0005 /* 00005 */ #define TIFFTAG_RW2_IMAGEHEIGHT 0x0006 /* 00006 */ #define TIFFTAG_RW2_IMAGEWIDTH 0x0007 /* 00007 */ #define TIFFTAG_RW2_REDBALANCE 0x0011 /* 00017 */ #define TIFFTAG_RW2_BLUEBALANCE 0x0012 /* 00018 */ #define TIFFTAG_RW2_ISO 0x0017 /* 00023 */ #define TIFFTAG_RW2_WBREDLEVEL 0x0024 /* 00036 */ #define TIFFTAG_RW2_WBGREENLEVEL 0x0025 /* 00037 */ #define TIFFTAG_RW2_WBBLUELEVEL 0x0026 /* 00038 */ #define TIFFTAG_RW2_JPGFROMRAW 0x002E /* 00047 */ #define TIFFTAG_DCSHUESHIFTVALUES 0xFFFF /* 65535 */ #endif exifprobe-2.0.1+git20170416-3c2b76/leica_datadefs.h0000644000000000000000000000206613074742216017576 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: leica_datadefs.h,v 1.2 2005/07/24 21:30:58 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef LEICA_DATADEFS_INCLUDED #define LEICA_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id leica_model_id[] = { { "DIGILUX 2",10, LEICA_DIGILUX2, 0, 0 }, { "digilux 4.3",12, LEICA_DIGILUX43, 1, 1 }, { "R9 - Digital Back DMR",22,LEICA_R9_DB_DMR, 0, 0 }, { 0, 0, 0, 0, 0 } }; #endif /* LEICA_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/mkcomptime0000755000000000000000000000017713074742216016611 0ustar rootroot#!/bin/sh # @(#) $Id: mkcomptime,v 1.1 2003/01/06 19:31:55 alex Exp $ date=`date` echo "char *Comptime = \"${date}\";" exit 0 exifprobe-2.0.1+git20170416-3c2b76/maker_tagnames.c0000644000000000000000000001070513074742216017636 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_tagnames.c,v 1.14 2005/07/24 21:32:11 alex Exp $"; #endif /* This file contains routines to produce tag names for tags found in */ /* EXIF image MakerNotes on a make/model basis. The "master" routine, */ /* maker_tagname() dispatches to maker-specific routines, which may */ /* then examine model magic number (maker.h). Those maker-specific */ /* routines are arranged to check first for model-specific tags; if */ /* the model-specific routine does not exist, or does not name the */ /* current tag, the caller (maker-specific routine) may examine a */ /* "generic" list of tags for that maker. Finally, if the */ /* maker-specific routine finds nothing, the top-level routine */ /* (maker_tagname()) produces and returns a string which is the hex */ /* value of the tag, constructed in static storage. */ /* Note that only "known" tags are decoded; tags marked "unknnown" in */ /* the various references used are unlisted in the maker_specific */ /* routines, so that the tag number will print. */ #include #include #include "defs.h" #include "maker.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" /* The "master" tagname routine; dispatches to maker-specific */ /* routines. If no maker-specific routine is supplied, a name (hex */ /* value of the tag) will be constructed in static storage. This */ /* routine intends to always return a non-null pointer; */ char * maker_tagname(unsigned short tag,int make,int model) { static char unknown_buf[16]; char *tagname = NULL; switch(make) { case MAKER_AGFA: tagname = maker_agfa_tagname(tag,model); break; case MAKER_ASAHI: case MAKER_PENTAX: tagname = maker_asahi_tagname(tag,model); break; case MAKER_CANON: tagname = maker_canon_tagname(tag,model); break; case MAKER_CASIO: tagname = maker_casio_tagname(tag,model); break; case MAKER_EPSON: tagname = maker_epson_tagname(tag,model); break; case MAKER_FUJIFILM: tagname = maker_fujifilm_tagname(tag,model); break; case MAKER_KYOCERA: tagname = maker_kyocera_tagname(tag,model); break; case MAKER_LEICA: tagname = maker_leica_tagname(tag,model); break; case MAKER_MINOLTA: tagname = maker_minolta_tagname(tag,model); break; case MAKER_NIKON: tagname = maker_nikon_tagname(tag,model); break; case MAKER_OLYMPUS: tagname = maker_olympus_tagname(tag,model); break; case MAKER_PANASONIC: tagname = maker_panasonic_tagname(tag,model); break; case MAKER_SANYO: tagname = maker_sanyo_tagname(tag,model); break; case MAKER_SIGMA: tagname = maker_sigma_tagname(tag,model); break; case MAKER_TOSHIBA: tagname = maker_toshiba_tagname(tag,model); break; case MAKER_SONY: case MAKER_KODAK: case MAKER_KONICA: case MAKER_HP: case MAKER_RICOH: case MAKER_TRAVELER: default: break; } if(tagname == NULL) { memset(unknown_buf,'\0',16); /* "regular" tags use lower case; use upper case for */ /* MakerNote tags */ if(snprintf(unknown_buf,11,"TAG_%#06X",(int)tag) > 11) { printf(" bad tag %#x not converted\n",tag); why(stdout); tagname = "Maker_BADTAG"; } else tagname = unknown_buf; } return(tagname); } exifprobe-2.0.1+git20170416-3c2b76/maker_canon.c0000644000000000000000000045361113074742216017144 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_canon.c,v 1.29 2005/07/24 22:56:26 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Canon camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* The information coded here is derived from information provided by */ /* David Burren at: */ /* http://www.burren.cx/david/canon.html */ /* April 05: new tag information and CustomFunctions for additional */ /* models from Phil Harvey's exiftool pages at: */ /* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/index.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id canon_model_id[]; /* Find the identifying number assigned to known Canon camera models. */ /* This number is used to dispatch appropriate print and interpret */ /* routines approopriate to the current image. */ int canon_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &canon_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine based upon previously set noteversion */ /* Everything is (currently) mapped to one set of routines. */ void print_canon_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 1: case 2: case 3: case 4: case 5: print_canon1_makervalue(entry_ptr,make,model,prefix); canon1_interpret_value(entry_ptr); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Canon cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_canon1_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x000C: /* Camera serial number */ print_value(entry_ptr,PREFIX); /* ###%%% */ /* perhaps this should be in canon1_interpret_value() */ (void)print_canon_serialno(entry_ptr->value); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Canon serial numbers are encoded. It is not clear that this is */ /* consistent across all models, but since the "raw" value is */ /* displayed as well, it will do no harm to display this */ /* unconditionally. */ int print_canon_serialno(unsigned long value) { unsigned long tmp; int chpr = 0; print_startvalue(); tmp = (value & 0xffff0000) >> 16; chpr += printf("%04lX",value & 0xffff); tmp = value & 0xffff; chpr += printf("%05lu",value & 0xffff); print_endvalue(); setcharsprinted(chpr); return(chpr); } /* Dispatch a routine to decode and print offset values for Canon */ /* cameras. There is currently only one tagset, and 1 interpretation */ /* of each tag, except that there are 4 different varieties of custom */ /* functions. The canon_customfunctions() routine will do the */ /* selection on noteversion; everything is handled the same here. */ void print_canon_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) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { /* noteversion 1 assumes the single known tagset is */ /* correct, but imposes a "generic" routine for */ /* CustomFunctions (which presents values but interprets */ /* nothing) for unrecognized models or those for which no */ /* information is available. */ case 1: case 2: case 3: case 4: case 5: canon1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr,fileoffset_base, parent_name,prefix,indent, make,model,at_offset); break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in canon makernotes. */ void canon1_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) { unsigned long value_offset; unsigned long count; unsigned long max_offset = 0; unsigned long filesize = 0UL; unsigned short marker; char *nameoftag,*tagprefix; char *fulldirname = NULL; int status = 0; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; filesize = get_filesize(inptr); switch(entry_ptr->tag) { case 0x0001: /* Camera Settings */ if(at_offset) { if((PRINT_SECTION)) { print_tag_address(SECTION,value_offset,indent,prefix); chpr += printf("<%s> ",nameoftag); chpr += printf("%lu entries",entry_ptr->count - 1); } } else if((PRINT_VALUE)) chpr += printf("\'%lu entries\'",entry_ptr->count - 1); if((PRINT_LONGNAMES)) tagprefix = fulldirname; else tagprefix = nameoftag; setcharsprinted(chpr); chpr = 0; (void)canon_camera_settings(inptr,byteorder,tagprefix,value_offset, entry_ptr->count * sizeof(unsigned short), indent + MEDIUMINDENT); if(PRINT_SECTION) { print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1, indent,prefix); chpr += printf(" ",nameoftag); } break; case 0x0002: /* Focus Info */ if(at_offset) { if((PRINT_SECTION)) { print_tag_address(SECTION,value_offset,indent,prefix); chpr += printf("<%s> ",nameoftag); chpr += printf("%lu entries",entry_ptr->count); } } else if((PRINT_VALUE)) chpr += printf("\'%lu entries\'",entry_ptr->count); if((PRINT_LONGNAMES)) tagprefix = fulldirname; else tagprefix = nameoftag; setcharsprinted(chpr); chpr = 0; (void)canon_focusinfo(inptr,byteorder,tagprefix,value_offset, entry_ptr->count * sizeof(unsigned short), indent + MEDIUMINDENT); if(PRINT_SECTION) { print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1, indent,prefix); chpr += printf(" ",nameoftag); } break; case 0x0004: /* Shot Info */ if(at_offset) { if((PRINT_SECTION)) { print_tag_address(SECTION,value_offset,indent,prefix); chpr += printf("<%s> ",nameoftag); chpr += printf("%lu entries",entry_ptr->count - 1); } } else if((PRINT_VALUE)) chpr += printf("\'%lu entries\'",entry_ptr->count - 1); if((PRINT_LONGNAMES)) tagprefix = fulldirname; else tagprefix = nameoftag; setcharsprinted(chpr); chpr = 0; (void)canon_shotinfo(inptr,byteorder,tagprefix,value_offset, entry_ptr->count * sizeof(unsigned short), indent + MEDIUMINDENT); if(PRINT_SECTION) { print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1, indent,prefix); chpr += printf(" ",nameoftag); } break; case 0x0090: /* Custom Functions */ case 0x000F: /* Custom Functions */ if(at_offset) { if((PRINT_SECTION)) { print_tag_address(SECTION,value_offset,indent,prefix); chpr += printf("<%s> ",nameoftag); chpr += printf("%lu entries",entry_ptr->count - 1); } } else if((PRINT_VALUE)) chpr += printf("\'%lu entries\'",entry_ptr->count - 1); if((PRINT_LONGNAMES)) tagprefix = fulldirname; else tagprefix = nameoftag; setcharsprinted(chpr); chpr = 0; (void)canon_customfunctions(inptr,byteorder,tagprefix,value_offset, entry_ptr->count * sizeof(unsigned short), model,indent + MEDIUMINDENT); if(PRINT_SECTION) { print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1, indent,prefix); chpr += printf(" ",nameoftag); } break; case 0x00E0: /* Sensor Info */ if(at_offset) { if((PRINT_SECTION)) { print_tag_address(SECTION,value_offset,indent,prefix); chpr += printf("<%s> ",nameoftag); chpr += printf("%lu entries",entry_ptr->count - 1); } } else if((PRINT_VALUE)) chpr += printf("\'%lu entries\'",entry_ptr->count - 1); if((PRINT_LONGNAMES)) tagprefix = fulldirname; else tagprefix = nameoftag; setcharsprinted(chpr); chpr = 0; (void)canon_sensorinfo(inptr,byteorder,tagprefix,value_offset, entry_ptr->count * sizeof(unsigned short), indent + MEDIUMINDENT); if(PRINT_SECTION) { print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1, indent,prefix); chpr += printf(" ",nameoftag); } break; case 0x0012: /* Picture Info */ if(at_offset) { if((PRINT_SECTION)) { print_tag_address(SECTION,value_offset,indent,prefix); chpr += printf("<%s> ",nameoftag); chpr += printf("%lu entries",entry_ptr->count - 1); } } else if((PRINT_VALUE)) chpr += printf("\'%lu entries\'",entry_ptr->count - 1); if((PRINT_LONGNAMES)) tagprefix = fulldirname; else tagprefix = nameoftag; setcharsprinted(chpr); chpr = 0; (void)canon_pictureinfo(inptr,byteorder,tagprefix,value_offset, entry_ptr->count * sizeof(unsigned short), indent + MEDIUMINDENT); if(PRINT_SECTION) { print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1, indent,prefix); chpr += printf(" ",nameoftag); } break; case 0x0081: /* JPEG image offset */ if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix); chpr += printf("# Start of JPEG image from MakerNote"); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",value_offset); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); max_offset = process_jpeg_segments(inptr,value_offset,marker, 0,summary_entry,fulldirname, prefix,indent+SMALLINDENT); if(at_offset) { if((PRINT_SECTION)) { if(max_offset == 0UL) max_offset = filesize; if(max_offset) { if((status = jpeg_status(0)) == JPEG_EARLY_EOI) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,max_offset - 1,indent,"-"); chpr += printf("# End of JPEG image from MakerNote"); chpr += printf(" length %lu",max_offset - value_offset); } if(!(PRINT_VALUE) && (status == JPEG_NO_ERROR)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_IFD; if((summary_entry->compression == JPEG_SOF_3) && (max_offset == 0)) summary_entry->length = filesize - value_offset; } } clearerr(inptr); break; case 0x009a: /* AspectInfo */ if(at_offset) { if((PRINT_SECTION)) { print_tag_address(SECTION,value_offset,indent,prefix); chpr += printf("<%s> ",nameoftag); chpr += printf("%lu entries",entry_ptr->count - 1); } } else if((PRINT_VALUE)) chpr += printf("\'%lu entries\'",entry_ptr->count - 1); if((PRINT_LONGNAMES)) tagprefix = fulldirname; else tagprefix = nameoftag; setcharsprinted(chpr); chpr = 0; (void)canon_aspectinfo(inptr,byteorder,tagprefix,value_offset, entry_ptr->count * sizeof(long), indent + MEDIUMINDENT); if(PRINT_SECTION) { print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1, indent,prefix); chpr += printf(" ",nameoftag); } break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr,fileoffset_base, fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Canon-specific tagnames for makernotes. */ /* There is currently only one tagset, but there are (at least) 4 */ /* different sets of custom functions. */ char * maker_canon_tagname(unsigned short tag,int model) { char *tagname = CNULL; int noteversion = 0; /* Should have to do this only once, and only for unrecognized */ /* models. If the model is recognized (or the user has forced a */ /* noteversion) noteversion will already be set. */ if(((noteversion = getnoteversion()) == 0)) { /* Assume the tagset is correct, but use the generic */ /* CustomFunctions routine if required (some models don't */ /* have custom functions) */ noteversion = 1; setnoteversion(1); } switch(noteversion) { case 1: case 2: case 3: case 4: case 5: tagname = maker_canon1_tagname(tag,model); break; default: /* This essentially turns off tagname interpretation; it */ /* should happen only if the user has deliberately set a */ /* non-existent version (e.g. -1) */ break; } /* If no model-specific tag is found, check "generic" tags */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } char * maker_canon1_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0001: tagname = "CameraSettings"; break; case 0x0002: tagname = "FocusInfo"; break; case 0x0004: tagname = "ShotInfo"; break; case 0x0006: tagname = "ImageType"; break; case 0x0007: tagname = "FirmwareVersion"; break; case 0x0008: tagname = "ImageNumber"; break; case 0x0009: tagname = "OwnerName"; break; case 0x000a: tagname = "ColorInfoD30*"; break; case 0x000c: tagname = "CameraSerialNo"; break; case 0x000d: tagname = "CameraInfo"; break; case 0x000e: tagname = "FileLength"; break; case 0x000f: tagname = "CustomFunctions"; break; case 0x0010: tagname = "UniqueModelId"; break; /* from dcraw */ case 0x0012: tagname = "PictureInfo"; break; case 0x0013: tagname = "ThumbnailImageValidArea"; break; case 0x0081: tagname = "JpegImage"; break; case 0x0090: tagname = "CustomFunctions"; break; case 0x0093: tagname = "FileInfo**"; break; /* exiftool shows wrong type */ case 0x0095: tagname = "LensName"; break; case 0x0098: tagname = "CropInfo"; break; case 0x009a: tagname = "AspectInfo"; break; case 0x00a0: tagname = "ColorInfo**"; break; /* exiftool - wrong # values */ case 0x00a9: tagname = "WhiteBalanceTable"; break; case 0x00ae: tagname = "ColorTemperature"; break; case 0x00b6: tagname = "PreviewImageInfo"; break; case 0x00e0: tagname = "SensorInfo"; break; default: break; } setnotetagset(1); return(tagname); } /* Report the "meaning" of tag values found directly in a Canon */ /* MakerNote IFD entry (not at an offset). */ /* There are currently no direct entry tags for which the meaning is */ /* known, so this routine is null, empty, void. There are observed */ /* tags with unknown meaning, so this routine will be necessary. */ /* I suspect that ImageNumber could be decomposed into a DCF folder */ /* number and sequence number), */ void canon1_interpret_value(struct ifd_entry *entry_ptr) { switch(entry_ptr->tag) { default: break; } } /* ###%%% FIXIT: none of the routines below honor the PRINT_TAGNAMES */ /* or PRINT_VALUE options. */ /* Interpret the "Camera Settings" tag data from Canon MakerNotes. */ unsigned long canon_camera_settings(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; struct fileheader *header = NULL; unsigned short length,value; char *sep; int i; int chpr = 0; end_offset = offset + dirlength; length = read_ushort(inptr,byteorder,offset); if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); if(length != dirlength) { chpr = newline(chpr); PUSHCOLOR(RED); print_tag_address(SECTION,offset,indent,"@"); chpr += printf("# WARNING: length %u from segment does not match length %lu from directory", length,dirlength); POPCOLOR(); } } chpr = newline(chpr); offset += 2; count = (dirlength / sizeof(unsigned short)) - 1; if((PRINT_ENTRY)) { for(i = 1; i <= count; ++i) { value = read_ushort(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); /* tagprefix has already been adjusted according to the */ /* setting of PRINT_LONGNAMES. */ if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); offset += 2; switch(i) { case 1: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"MacroMode"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 1: chpr += printf("macro"); break; case 2: chpr += printf("normal"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 2: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"SelfTimer"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); if(value) chpr += printf(".%u sec",value); /* ###%%% ? */ else chpr += printf("off"); print_endvalue(); } break; case 3: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Quality"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 2: chpr += printf("normal"); break; case 3: chpr += printf("fine"); break; case 4: header = read_imageheader(inptr,0); switch(header->probe_magic) { case TIFF_MAGIC: case PROBE_JPEGMAGIC: chpr += printf("Lossless JPEG"); break; case PROBE_CIFFMAGIC: default: chpr += printf("RAW"); break; } break; case 5: chpr += printf("super fine"); break; default: printred("unknown"); break; } print_endvalue(); } break; case 4: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"FlashMode"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("flash did not fire"); break; case 1: chpr += printf("auto"); break; case 2: chpr += printf("on"); break; case 3: chpr += printf("redeye"); break; case 4: chpr += printf("slow sync"); break; case 5: chpr += printf("auto + redeye"); break; case 6: chpr += printf("on + redeye"); break; case 16: chpr += printf("external flash"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 5: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"ContinuousMode"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("single or timer"); break; case 1: chpr += printf("continuous"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 6: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 7: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"FocusMode"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("One Shot AF"); break; case 1: chpr += printf("AI Servo AF"); break; case 2: chpr += printf("AI Focus AF"); break; case 3: chpr += printf("Manual Focus"); break; case 4: chpr += printf("single"); break; case 5: chpr += printf("Continuous"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 8: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 9: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 10: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"ImageSize"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("Large"); break; case 1: chpr += printf("Medium"); break; case 2: chpr += printf("Small"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 11: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"EasyShootMode"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("Full Auto"); break; case 1: chpr += printf("Manual"); break; case 2: chpr += printf("Landscape"); break; case 3: chpr += printf("Fast Shutter"); break; case 4: chpr += printf("Slow Shutter"); break; case 5: chpr += printf("Night"); break; case 6: chpr += printf("B & W"); break; case 7: chpr += printf("Sepia"); break; case 8: chpr += printf("Portrait"); break; case 9: chpr += printf("Sports"); break; case 10: chpr += printf("Macro/CloseUp"); break; case 11: chpr += printf("Pan Focus"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 12: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"DigitalZoom"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("none"); break; case 1: chpr += printf("2x"); break; case 2: chpr += printf("4x"); break; default: printred("(2 * ZoomedResBase) / ZoomedResValue**"); break; } print_endvalue(); } break; case 13: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Contrast"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("High"); break; case 0xffff: chpr += printf("Low"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 14: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Saturation"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("High"); break; case 0xffff: chpr += printf("Low"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 15: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Sharpness"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("High"); break; case 0xffff: chpr += printf("Low"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 16: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"ISO"); if((PRINT_VALUE)) { chpr += printf(" = %#x/%u",value,value); print_startvalue(); switch(value) { case 0: chpr += printf("Use Exif ISOSpeedRating"); break; case 15: chpr += printf("Auto"); break; case 16: chpr += printf("50"); break; case 17: chpr += printf("100"); break; case 18: chpr += printf("200"); break; case 19: chpr += printf("400"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 17: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"MeteringMode"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("Default"); break; case 1: chpr += printf("Spot"); break; case 3: chpr += printf("Evaluative"); break; case 4: chpr += printf("Partial"); break; case 5: chpr += printf("Center-weighted"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 18: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"FocusType"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("Manual"); break; case 1: chpr += printf("Auto1"); break; case 2: chpr += printf("Auto2"); break; case 3: chpr += printf("Macro"); break; case 7: chpr += printf("Infinity"); break; case 8: chpr += printf("Locked (pan mode)"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 19: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"AFPositionSelected"); if((PRINT_VALUE)) { chpr += printf(" = %#x",value); print_startvalue(); switch(value) { case 0x2005: chpr += printf("Manual AF Point select"); break; case 0x3000: chpr += printf("None (manual focus)"); break; case 0x3001: chpr += printf("Auto-selected"); break; case 0x3002: chpr += printf("Right"); break; case 0x3003: chpr += printf("Center"); break; case 0x3004: chpr += printf("Left"); break; case 0x4001: chpr += printf("Auto AF Point select"); break; default: printred("undefined"); } print_endvalue(); } break; case 20: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"ExposureMode"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("Easy Shooting"); break; case 1: chpr += printf("Program AE"); break; case 2: chpr += printf("Shutter priority AE"); break; case 3: chpr += printf("Aperture priority AE"); break; case 4: chpr += printf("Manual"); break; case 5: chpr += printf("Depth of field AE"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 21: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 22: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"LensType"); if((PRINT_VALUE)) chpr += printf(" = %u",value); /* ###%% Phil Harvey gives a massive Lens type */ /* table */ break; case 23: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"FocalLength_long"); if((PRINT_VALUE)) chpr += printf(" = %u units",value); break; case 24: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"FocalLength_short"); if((PRINT_VALUE)) chpr += printf(" = %u units",value); break; case 25: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"FocalUnits*"); if((PRINT_VALUE)) { if(value > 1) chpr += printf(" = %u units per mm*",value); else chpr += printf(" = %u unit per mm",value); } break; case 26: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 27: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 28: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"FlashActivity"); if((PRINT_VALUE)) { chpr += printf(" = %#x",value); print_startvalue(); switch(value) { case 0: chpr += printf("did not fire"); break; case 1: chpr += printf("fired"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 29: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"FlashDetails"); if((PRINT_VALUE)) { chpr += printf(" = %#x",value); print_startvalue(); sep = ""; if(value & 0x0e) { chpr += printf("%sexternal E-TTL",sep); sep = ","; } if(value & 0x0d) { chpr += printf("%sInternal flash**",sep); sep = ","; } if(value & 0x0b) { chpr += printf("%sFP sync used",sep); sep = ","; } if(value & 0x07) { chpr += printf("%s2nd-curtain sync used",sep); sep = ","; } if(value & 0x04) { chpr += printf("%sFP sync enabled",sep); sep = ","; } if(value & 0x03) { chpr += printf("%sOn",sep); sep = ","; } print_endvalue(); } break; case 30: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 31: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 32: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"FocusMode"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("Single"); break; case 1: chpr += printf("Continuous"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 36: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"ZoomedResValue**"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 37: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"ZoomedResBase**"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 42: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"ColorTone**"); if((PRINT_VALUE)) chpr += printf(" = %#x/%u",value,value); break; default: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-23.23s",i,"undefined"); if((PRINT_VALUE)) chpr += printf(" = %#x/%u",value,value); break; } chpr = newline(chpr); } } setcharsprinted(chpr); return(end_offset); } /* Interpret the "ShotInfo" settings in a Cannon MakerNote or */ /* CIFF file */ unsigned long canon_shotinfo(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; unsigned short length,value; int i; int chpr = 0; end_offset = offset + dirlength; length = read_ushort(inptr,byteorder,offset); if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); if(length != dirlength) { chpr = newline(chpr); PUSHCOLOR(RED); print_tag_address(SECTION,offset,indent,"@"); chpr += printf("# WARNING: length %u from segment does not match length %lu from directory", length,dirlength); POPCOLOR(); } } chpr = newline(chpr); if((PRINT_ENTRY)) { offset += 2; count = (dirlength / sizeof(unsigned short)) - 1; for(i = 1; i <= count; ++i) { value = read_ushort(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); offset += 2; switch(i) { case 1: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; case 2: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"ISO"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 3: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; case 4: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; case 5: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; case 6: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"ExposureCompensation**"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 7: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"WhiteBalance"); if((PRINT_VALUE)) { chpr += printf(" = %u",value); print_startvalue(); switch(value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Sunny"); break; case 2: chpr += printf("Cloudy"); break; case 3: chpr += printf("Tungsten"); break; case 4: chpr += printf("Fluorescent"); break; case 5: chpr += printf("Flash"); break; case 6: chpr += printf("Custom"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 8: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; case 9: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"SequenceNumber"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 10: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; case 11: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; case 12: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; case 13: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; case 14: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"AFPositionUsed"); if((PRINT_VALUE)) { chpr += printf(" = %#x",value); print_startvalue(); if(value & 0xf000) { switch(value & 0x7) { case 0: chpr += printf("none (MF)"); break; case 1: chpr += printf("right"); break; case 2: chpr += printf("center"); break; case 3: chpr += printf("center+right"); break; case 4: chpr += printf("left"); break; case 5: chpr += printf("left+right"); break; case 6: chpr += printf("left+center"); break; case 7: chpr += printf("all"); break; default: printred("undefined"); break; } chpr += printf(" of %d points",(value & 0xf000) >> 12); } else chpr += printf("MF"); print_endvalue(); } break; case 15: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"FlashBias"); if((PRINT_VALUE)) { chpr += printf(" = %#x",value); print_startvalue(); switch(value) { case 0xffc0: chpr += printf("-2 EV"); break; case 0xffcc: chpr += printf("-1.67 EV"); break; case 0xffd0: chpr += printf("-1.50 EV"); break; case 0xffd4: chpr += printf("-1.33 EV"); break; case 0xffe0: chpr += printf("-1 EV"); break; case 0xffec: chpr += printf("-0.67 EV"); break; case 0xfff0: chpr += printf("-0.50 EV"); break; case 0xfff4: chpr += printf("-0.33 EV"); break; case 0x0000: chpr += printf("0 EV"); break; case 0x000c: chpr += printf("+0.33 EV"); break; case 0x0010: chpr += printf("+0.50 EV"); break; case 0x0014: chpr += printf("+0.67 EV"); break; case 0x0020: chpr += printf("+1 EV"); break; case 0x002c: chpr += printf("+1.33 EV"); break; case 0x0030: chpr += printf("+1.50 EV"); break; case 0x0034: chpr += printf("+1.67 EV"); break; case 0x0040: chpr += printf("+2 EV"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 16: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"AutoExposureBracketing**"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 17: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"AEBracketValue**"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 18: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; case 19: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"FocusDistanceMax**"); if((PRINT_VALUE)) chpr += printf(" = %u mm",value); break; case 20: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"FocusDistanceMin**"); if((PRINT_VALUE)) chpr += printf(" = %u mm",value); break; case 21: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"ApertureValue**"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 22: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"ExposureTime**"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 24: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"BulbDuration**"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 27: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"AutoRotate**"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 29: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"SelfTimer2**"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; default: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-28.28s",i,"Undefined"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; } chpr = newline(chpr); } } setcharsprinted(chpr); return(end_offset); } /* Interpret Canon Custom Functions */ unsigned long canon_customfunctions(FILE *inptr,unsigned short byteorder, char *tagprefix,unsigned long offset, unsigned long dirlength,int model,int indent) { unsigned long max_offset; int noteversion = 0; noteversion = getnoteversion(); switch(noteversion) { case 5: /* 20 entries (or 21,22) */ max_offset = canon_customfunctions1D(inptr,byteorder,tagprefix,offset,dirlength,indent); break; case 4: /* 18 entries */ max_offset = canon_customfunctions20D(inptr,byteorder,tagprefix,offset,dirlength,indent); break; case 3: /* 17 entries starting at 1*/ max_offset = canon_customfunctions10D(inptr,byteorder,tagprefix,offset,dirlength,indent); break; case 2: /* 16 entries */ max_offset = canon_customfunctionsD30(inptr,byteorder,tagprefix,offset,dirlength,indent); break; case 1: /* unknown customfuctions */ default: max_offset = canon_customfunctions_unk(inptr,byteorder,tagprefix,offset,dirlength,indent); break; } return(max_offset); } /* A "generic" version of customfunctions; just prints the data, with */ /* no interpretation. */ unsigned long canon_customfunctions_unk(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; unsigned short length,value; int i,cfn,cfv; int chpr = 0; length = read_ushort(inptr,byteorder,offset); end_offset = offset + dirlength; if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); if(length != dirlength) { chpr = newline(chpr); PUSHCOLOR(RED); print_tag_address(SECTION,offset,indent,"@"); chpr += printf("# WARNING: length %u from segment does not match length %lu from directory", length,dirlength); POPCOLOR(); } } chpr = newline(chpr); if((PRINT_ENTRY)) { offset += 2; count = (dirlength / sizeof(unsigned short)) - 1; for(i = 0; i < count; ++i) { value = read_ushort(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); chpr += printf("%s",tagprefix); offset += 2; cfn = (value & 0xff00) >> 8; cfv = value & 0xff; if(PRINT_SECTION) chpr += printf("Unk.%02d: = %#x/%u",cfn,cfv,cfv); else chpr += printf("Unk.%02d = %#x/%u",cfn,cfv,cfv); chpr = newline(chpr); } } setcharsprinted(chpr); return(end_offset); } /* CustomFunctions for Canon D30 */ unsigned long canon_customfunctionsD30(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; unsigned short length,value; int i,cfn,cfv; int chpr = 0; length = read_ushort(inptr,byteorder,offset); end_offset = offset + dirlength; if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); if(length != dirlength) { chpr = newline(chpr); PUSHCOLOR(RED); print_tag_address(SECTION,offset,indent,"@"); chpr += printf("# WARNING: length %u from segment does not match length %lu from directory", length,dirlength); POPCOLOR(); } } chpr = newline(chpr); if((PRINT_ENTRY)) { offset += 2; count = (dirlength / sizeof(unsigned short)) - 1; for(i = 0; i < count; ++i) { value = read_ushort(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); offset += 2; cfn = (value & 0xff00) >> 8; cfv = value & 0xff; switch(cfn) { case 1: if((PRINT_TAGINFO)) chpr += printf("D30.%02d:%-30.30s",cfn,"LongExposureNoiseReduction"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 2: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"ShutterAElockButtons"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("AF/AE lock"); break; case 1: chpr += printf("AE lock/AF"); break; case 2: chpr += printf("AF/AF lock"); break; case 3: chpr += printf("AE+release/AE+AF"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 3: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"MirrorLockup"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Disabled"); break; case 1: chpr += printf("Enabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 4: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"TvAvAndExposureLevel"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("1/2 stop"); break; case 1: chpr += printf("1/3 stop"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 5: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"AFAssistLight"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("On (auto)"); break; case 1: chpr += printf("Off"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 6: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"FlashSyncSpeedAv"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("D30/200 (fixed)"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 7: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"AEBSequenceAutoCancellation"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("0,-,+/Enabled"); break; case 1: chpr += printf("0,-,+/Disabled"); break; case 2: chpr += printf("-,0,+/Enabled"); break; case 3: chpr += printf("-,0,+/Disabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 8: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"ShutterCurtainSync"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("D30-curtain sync"); break; case 1: chpr += printf("2nd-curtain sync"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 9: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"LensAFStopButtonFnSwitch"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("AF Stop"); break; case 1: chpr += printf("Operate AF"); break; case 2: chpr += printf("Lock AE and start timer"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 10: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"AutoReductionOfFillFlash"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Enabled"); break; case 1: chpr += printf("Disabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 11: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"MenuButtonReturnPosition"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Top"); break; case 1: chpr += printf("Previous (volatile)"); break; case 2: chpr += printf("Previous"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 12: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"SETButtonFuncWhenShooting"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Not assigned"); break; case 1: chpr += printf("Change quality"); break; case 2: chpr += printf("Change ISO speed"); break; case 3: chpr += printf("PreviouSelect parameters"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 13: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"SensorCleaning"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Disabled"); break; case 1: chpr += printf("Enabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 14: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"SuperimposedDisplay*"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("On"); break; case 1: chpr += printf("Off"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 15: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"ShutterReleaseNoCFCard*"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Yes"); break; case 1: chpr += printf("No"); break; default: printred("undefined"); break; } print_endvalue(); } break; default: if((PRINT_TAGINFO)) chpr += printf("D30.%02d_%-30.30s",cfn,"undefined"); if((PRINT_VALUE)) chpr += printf(" = %#x/%u",cfv,cfv); break; } chpr = newline(chpr); } } setcharsprinted(chpr); return(end_offset); } /* CustomFunctions for Canon 10D */ unsigned long canon_customfunctions10D(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; unsigned short length,value; int i,cfn,cfv; int chpr = 0; end_offset = offset + dirlength; length = read_ushort(inptr,byteorder,offset); if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); if(length != dirlength) { chpr = newline(chpr); PUSHCOLOR(RED); print_tag_address(SECTION,offset,indent,"@"); chpr += printf("# WARNING: length %u from segment does not match length %lu from directory", length,dirlength); POPCOLOR(); } } chpr = newline(chpr); if((PRINT_ENTRY)) { offset += 2; count = (dirlength / sizeof(unsigned short)) - 1; for(i = 0; i < count; ++i) { value = read_ushort(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); offset += 2; cfn = (value & 0xff00) >> 8; cfv = value & 0xff; switch(cfn) { case 1: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"Set Button Function"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Not assigned"); break; case 1: chpr += printf("Change quality"); break; case 2: chpr += printf("Change parameters"); break; case 3: chpr += printf("Menu display"); break; case 4: chpr += printf("Image replay"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 2: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"ShutterReleaseNoCFCard"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Yes"); break; case 1: chpr += printf("No"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 3: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"FlashSyncSpeedAv"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("1/200 (fixed)"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 4: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"ShutterAElockButtons"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("AF/AE lock"); break; case 1: chpr += printf("AE lock/AF"); break; case 2: chpr += printf("AF/AF lock"); break; case 3: chpr += printf("AE/AF"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 5: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"AFAssistLight"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Emits/Fires"); break; case 1: chpr += printf("Does not emit/Fires"); break; case 2: chpr += printf("Only ext flash emits/Fires"); break; case 3: chpr += printf("Emits/Does not fire"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 6: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"ExposureLevelIncrements"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("1/2 stop"); break; case 1: chpr += printf("1/3 stop"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 7: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"AFPointRegistration"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Center"); break; case 1: chpr += printf("Bottom"); break; case 2: chpr += printf("Right"); break; case 3: chpr += printf("Extreme Right"); break; case 4: chpr += printf("Automatic"); break; case 5: chpr += printf("Extreme Left"); break; case 6: chpr += printf("Left"); break; case 7: chpr += printf("Top"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 8: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"RawandJpegRecording"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("RAW+Small/Normal"); break; case 1: chpr += printf("RAW+Small/Fine"); break; case 2: chpr += printf("RAW+Medium/Normal"); break; case 3: chpr += printf("RAW+Medium/Fine"); break; case 4: chpr += printf("RAW+Large/Normal"); break; case 5: chpr += printf("RAW+Large/Fine"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 9: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"AEBSequence"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("0,-,+/Enabled"); break; case 1: chpr += printf("0,-,+/Disabled"); break; case 2: chpr += printf("-,0,+/Enabled"); break; case 3: chpr += printf("-,0,+/Disabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 10: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"SuperimposedDisplay"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("On"); break; case 1: chpr += printf("Off"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 11: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"MenuButtonDisplayPosition"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Previous (volatile)"); break; case 1: chpr += printf("Previous"); break; case 2: chpr += printf("Top"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 12: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"MirrorLockup"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Disabled"); break; case 1: chpr += printf("Enabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 13: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"AssistButtonFunction"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Select home position"); break; case 2: chpr += printf("Select HP (while pressing)"); break; case 3: chpr += printf("Ax+/-(AF point by QCD)"); break; case 4: chpr += printf("FE lock"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 14: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"FillFlashAutoReduction"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Enabled"); break; case 1: chpr += printf("Disabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 15: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"ShutterCurtainSync"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("1st-curtain sync"); break; case 1: chpr += printf("2nd-curtain sync"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 16: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"SafetyShiftInAvOrTv"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Disable"); break; case 1: chpr += printf("Enable"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 17: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"LensAFStopButton"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("AF Stop"); break; case 1: chpr += printf("Operate AF"); break; case 2: chpr += printf("Lock AE and start timer"); break; default: printred("undefined"); break; } print_endvalue(); } break; default: if((PRINT_TAGINFO)) chpr += printf("10D.%02d_%-30.30s",cfn,"undefined"); if((PRINT_VALUE)) chpr += printf(" = %#x/%u",cfv,cfv); break; } chpr = newline(chpr); } } setcharsprinted(chpr); return(end_offset); } /* CustomFunctions for Canon 20D */ unsigned long canon_customfunctions20D(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; unsigned short length,value; int i,cfn,cfv; int chpr = 0; end_offset = offset + dirlength; length = read_ushort(inptr,byteorder,offset); if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); if(length != dirlength) { chpr = newline(chpr); PUSHCOLOR(RED); print_tag_address(SECTION,offset,indent,"@"); chpr += printf("# WARNING: length %u from segment does not match length %lu from directory", length,dirlength); POPCOLOR(); } } chpr = newline(chpr); if((PRINT_ENTRY)) { offset += 2; count = (dirlength / sizeof(unsigned short)) - 1; for(i = 0; i < count; ++i) { value = read_ushort(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); offset += 2; cfn = (value & 0xff00) >> 8; cfv = value & 0xff; switch(cfn) { case 0: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"SetButtonFunctionWhenShooting"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("(no function)"); break; case 1: chpr += printf("change quality"); break; case 2: chpr += printf("change parameters"); break; case 3: chpr += printf("menu display"); break; case 4: chpr += printf("image replay"); break; default: printred("undefined"); break; } } print_endvalue(); break; case 1: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"LongExposureNoiseReduction"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 2: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"FlashSyncSpeedAv"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("1/200 (fixed)"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 3: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"ShutterAElockButtons"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("AF/AE lock"); break; case 1: chpr += printf("AE lock/AF"); break; case 2: chpr += printf("AF/AF lock"); break; case 3: chpr += printf("AE+release/AE+AF"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 4: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"AFAssistLight"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Emits"); break; case 1: chpr += printf("Does not emit"); break; case 2: chpr += printf("Only ext flash emits"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 5: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"ExposureLevelIncrements"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("1/2 stop"); break; case 1: chpr += printf("1/3 stop"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 6: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"FlashFiring"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Fires"); break; case 1: chpr += printf("Does not fire"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 7: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"ISOSpeedExpansion"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 8: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"AEBSequence"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("0,-,+/Enabled"); break; case 1: chpr += printf("0,-,+/Disabled"); break; case 2: chpr += printf("-,0,+/Enabled"); break; case 3: chpr += printf("-,0,+/Disabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 9: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"SuperimposedDisplay"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("On"); break; case 1: chpr += printf("Off"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 10: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"MenuButtonDisplayPosition"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Top"); break; case 1: chpr += printf("Previous (volatile)"); break; case 2: chpr += printf("Previous"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 11: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"MirrorLockup"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Disabled"); break; case 1: chpr += printf("Enabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 12: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"AFPointSelectionMethod"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Multi-controller direct"); break; case 2: chpr += printf("Quick control dial direct"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 13: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"ETTLII"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Evaluative"); break; case 1: chpr += printf("Average"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 14: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"ShutterCurtainSync"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("1st-curtain sync"); break; case 1: chpr += printf("2nd-curtain sync"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 15: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"SafetyShiftInAvOrTv"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Disable"); break; case 1: chpr += printf("Enable"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 16: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"LensAFStopButton"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("AF Stop"); break; case 1: chpr += printf("Operate AF"); break; case 2: chpr += printf("Lock AE and start timer"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 17: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"AddOriginalDecisionData"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); } break; default: if((PRINT_TAGINFO)) chpr += printf("20D.%02d_%-30.30s",cfn,"undefined"); if((PRINT_VALUE)) chpr += printf(" = %#x/%u",cfv,cfv); break; } chpr = newline(chpr); } } setcharsprinted(chpr); return(end_offset); } /* CustomFunctions for Canon 1D */ unsigned long canon_customfunctions1D(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; unsigned short length,value; int i,cfn,cfv; int chpr = 0; end_offset = offset + dirlength; length = read_ushort(inptr,byteorder,offset); if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); if(length != dirlength) { chpr = newline(chpr); PUSHCOLOR(RED); print_tag_address(SECTION,offset,indent,"@"); chpr += printf("# WARNING: length %u from segment does not match length %lu from directory", length,dirlength); POPCOLOR(); } } chpr = newline(chpr); if((PRINT_ENTRY)) { offset += 2; count = (dirlength / sizeof(unsigned short)) - 1; for(i = 0; i < count; ++i) { value = read_ushort(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); chpr += printf("%s",tagprefix); offset += 2; cfn = (value & 0xff00) >> 8; cfv = value & 0xff; switch(cfn) { case 0: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"FocusingScreen"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Ec-N,R"); break; case 1: chpr += printf("Ec-A,B,C,CII,CIII,D,H,I,L"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 1: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"FinderDisplayDuringExposure"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 2: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"ShutterReleaseNoCFCard"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Yes"); break; case 1: chpr += printf("No"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 3: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"ISOSpeedExpansion"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("No"); break; case 1: chpr += printf("Yes"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 4: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"ShutterAElockButtons"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("AF/AE lock"); break; case 1: chpr += printf("AE lock/AF"); break; case 2: chpr += printf("AF/AF lock"); break; case 3: chpr += printf("AE+release/AE+AF"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 5: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"ManualTv"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Tv:Main/Av:Control"); break; case 1: chpr += printf("Tv:Control/Av:Main"); break; case 2: chpr += printf("Tv:Main/Av:Main w/o lens"); break; case 3: chpr += printf("Tv:Control/Av:Main w/o lens"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 6: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"ExposureLevelIncrements"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("1/3-Stop set, 1/3-Stop comp"); break; case 1: chpr += printf("1-Stop set, 1/3-Stop comp"); break; case 2: chpr += printf("1/2-Stop set, 1/2-Stop comp"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 7: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"USMLensElectronicMF"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Turns on after one-shot AF"); break; case 1: chpr += printf("Turns off after one-shot AF"); break; case 2: chpr += printf("Always off"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 8: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"LCDPanels"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Remaining shots/File no"); break; case 1: chpr += printf("ISO/Remaining shots"); break; case 2: chpr += printf("ISO/File no"); break; case 3: chpr += printf("Shots in folder/Remaining shots"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 9: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"AEBSequenceAutoCancellation"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("0,-,+/Enabled"); break; case 1: chpr += printf("0,-,+/Disabled"); break; case 2: chpr += printf("-,0,+/Enabled"); break; case 3: chpr += printf("-,0,+/Disabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 10: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"AFPointIllumination"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("On"); break; case 1: chpr += printf("Off"); break; case 2: chpr += printf("On without dimming"); break; case 3: chpr += printf("Brighter"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 11: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"AFPointSelection"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("H:AF+Main, V:AF+Command"); break; case 1: chpr += printf("H:Comp+Main, V:AF+Comp+Command"); break; case 2: chpr += printf("H:Command only, V:Assist+Main"); break; case 3: chpr += printf("H:FEL_Main, V:FEL+Command"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 12: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"MirrorLockup"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Disabled"); break; case 1: chpr += printf("Enabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 13: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"AFPointSpotMetering"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("45/Center of Point"); break; case 1: chpr += printf("11/Active AF point"); break; case 2: chpr += printf("11/Center AF point"); break; case 3: chpr += printf("9/Active af pOINT"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 14: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"FillFlashAutoReduction"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Enabled"); break; case 1: chpr += printf("Disabled"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 15: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"ShutterCurtainSync"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("1st-curtain sync"); break; case 1: chpr += printf("2nd-curtain sync"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 16: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"SafetyShiftIn"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Disable"); break; case 1: chpr += printf("Enable"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 17: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"AF Point Activation Area"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Single AF point"); break; case 1: chpr += printf("Expanded (7 AF points)"); break; case 2: chpr += printf("Auto expanded (max 13)"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 18: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"SwitchToRegisteredAFPoint"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("AF + assist"); break; case 1: chpr += printf("Assist"); break; case 2: chpr += printf("Only while pressing Assist"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 19: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"Lens AF Stop Button"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("AF Stop"); break; case 1: chpr += printf("AF Start"); break; case 2: chpr += printf("AE Lock whuile metering"); break; case 3: chpr += printf("AF Point: M > Auto, Auto > Center"); break; case 4: chpr += printf("AF Mode: oneshot/servo"); break; case 5: chpr += printf("IS Start"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 20: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"AIServoTrackingSensitivity"); if((PRINT_VALUE)) { chpr += printf(" = %u",cfv); print_startvalue(); switch(cfv) { case 0: chpr += printf("Standard"); break; case 1: chpr += printf("Slow"); break; case 2: chpr += printf("Moderately slow"); break; case 3: chpr += printf("Moderately fast"); break; case 4: chpr += printf("Fast"); break; default: printred("undefined"); break; } print_endvalue(); } break; default: if((PRINT_TAGINFO)) chpr += printf("1D.%02d_%-30.30s",cfn,"undefined"); if((PRINT_VALUE)) chpr += printf(" = %#x/%u",cfv,cfv); break; } chpr = newline(chpr); } } setcharsprinted(chpr); return(end_offset); } unsigned long canon_sensorinfo(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; unsigned short length,value; int i; int chpr = 0; end_offset = offset + dirlength; length = read_ushort(inptr,byteorder,offset); if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); if(length != dirlength) { chpr = newline(chpr); PUSHCOLOR(RED); print_tag_address(SECTION,offset,indent,"@"); chpr += printf("# WARNING: length %u from segment does not match length %lu from directory", length,dirlength); POPCOLOR(); } } chpr = newline(chpr); if((PRINT_ENTRY)) { offset += 2; count = (dirlength / sizeof(unsigned short)) - 1; for(i = 1; i <= count; ++i) { value = read_ushort(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); offset += 2; switch(i) { case 1: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"SensorWidth"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 2: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"SensorHeight"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 3: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 4: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 5: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"SensorLeftBorder"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 6: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"SensorTopBorder"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 7: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"SensorRightBorder"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 8: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"SensorBottomBorder"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 9: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"BlackMaskLeftBorder"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 10: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"BlackMaskTopBorder"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 11: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"BlackMaskRightBorder"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 12: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"BlackMaskBottomBorder"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; default: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"Undefined"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; } chpr = newline(chpr); } } setcharsprinted(chpr); return(end_offset); } unsigned long canon_aspectinfo(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; unsigned long value; int i; int chpr = 0; end_offset = offset + dirlength; if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); } chpr = newline(chpr); if((PRINT_ENTRY)) { count = (dirlength / sizeof(long)); for(i = 0; i <= count; ++i) { value = read_ulong(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); offset += 4; switch(i) { case 0: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"AspectRatio"); if((PRINT_VALUE)) chpr += printf(" = %#lx",value); print_startvalue(); switch(value) { case 0: chpr += printf("3:2"); break; case 1: chpr += printf("1:1"); break; case 2: chpr += printf("4:3"); break; case 7: chpr += printf("16:9"); break; case 8: chpr += printf("4:5"); break; default: printred("undefined"); break; } print_endvalue(); break; case 1: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"CroppedImageWidth"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 2: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"CroppedImageHeight"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 3: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"CroppedImageLeft"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 4: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"CroppedImageRight"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; default: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-26.26s",i,"Undefined"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; } chpr = newline(chpr); } } setcharsprinted(chpr); return(end_offset); } /* not a directory; an array of shorts used as rationals */ unsigned long canon_whitebalancetable(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; unsigned short length; unsigned short num,denom; float value; int i; int chpr = 0; end_offset = offset + dirlength; length = read_ushort(inptr,byteorder,offset); if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); if(length != dirlength) { chpr = newline(chpr); PUSHCOLOR(RED); print_tag_address(SECTION,offset,indent,"@"); chpr += printf("# WARNING: length %u from segment does not match length %lu from directory", length,dirlength); POPCOLOR(); } chpr = newline(chpr); } if((PRINT_ENTRY)) { offset += 2; count = (dirlength - 2) / sizeof(float); for(i = 0; i < count; ++i) { num = read_ushort(inptr,byteorder,offset); denom = read_ushort(inptr,byteorder,offset+2); value = (float)num / (float)denom; print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); switch(i) { case 0: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"RedBalanceAuto"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 1: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"BlueBalanceAuto"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 2: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"RedBalanceDaylight"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 3: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"BlueBalanceDaylight"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 4: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"RedBalanceCloudy"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 5: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"BlueBalanceCloudy"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 6: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"RedBalanceTungsten"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 7: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"BlueBalanceTungsten"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 8: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"RedBalanceFluorescent"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 9: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"BlueBalanceFluorescent"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 10: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"RedBalanceFlash"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 11: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"BlueBalanceFlash"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 12: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"RedBalanceCustom"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 13: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"BlueBalanceCustom"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 14: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"RedBalanceB&W"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 15: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"BlueBalanceB&W"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 16: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"RedBalanceShade"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; case 17: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"BlueBalanceShade"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; default: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"Undefined"); if((PRINT_VALUE)) chpr += printf(" = %f",value); break; } offset += 4; chpr = newline(chpr); } } setcharsprinted(chpr); return(end_offset); } /* pictureinfo appears to be treated as a directory, except that the */ /* 'length' which should appear at the beginning of a ciff-style */ /* directory often does not agree with the length passed from the */ /* parent. */ unsigned long canon_pictureinfo(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; unsigned short value,length; int i; int chpr = 0; end_offset = offset + dirlength; length = read_ushort(inptr,byteorder,offset); if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); if(length != dirlength) { chpr = newline(chpr); PUSHCOLOR(RED); print_tag_address(SECTION,offset,indent,"@"); chpr += printf("# WARNING: length %u from segment does not match length %lu from directory", length,dirlength); POPCOLOR(); } } chpr = newline(chpr); if((PRINT_ENTRY)) { offset += 2; count = (dirlength / sizeof(unsigned short)) - 1; for(i = 1; i <= count; ++i) { value = read_ushort(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); offset += 2; switch(i) { case 1: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 2: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"ImageWidth"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 3: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"ImageHeight"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 4: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"ImageWidthAsShot"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 5: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"ImageHeightAsShot"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 22: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"AFPointsUsed"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; default: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"Undefined"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; } chpr = newline(chpr); } } setcharsprinted(chpr); return(end_offset); } /* Currently identified only in CIFF files */ unsigned long canon_imageinfo(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent, struct image_summary *summary_entry) { unsigned long count,value; unsigned long end_offset; float fvalue; int i; int chpr = 0; if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); chpr = newline(chpr); } /* NOTE that imageinfo is not treated as a directory; there is no */ /* 2-byte count at the beginning. */ end_offset = offset + dirlength; count = (dirlength / sizeof(unsigned long)); /* Must always do the processing, in order to pick up the image */ /* width and height for the summary, even if nothing is to be */ /* printed */ for(i = 0; i < count; ++i) { value = read_ulong(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent + MEDIUMINDENT,"@"); if((PRINT_ENTRY)) { if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); } offset += 4; switch(i) { case 0: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"ImageWidth"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); if(summary_entry) summary_entry->pixel_width = value; break; case 1: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"ImageHeight"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); if(summary_entry) summary_entry->pixel_height = value; break; case 2: fvalue = to_float(value); if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"PixelAspectRatio"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 3: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"Rotation"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 4: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"ComponentBitDepth"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 5: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"ColorBitDepth"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 6: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"ColorBW"); if((PRINT_VALUE)) { chpr += printf(" = %#lx/%lu",value,value); if((value & 0xff) == 1) chpr += printf(" = color"); else chpr += printf(" = greyscale"); if(((value & 0xff00) >> 8) == 1) chpr += printf(" = \'pixel ratio postproc reqd\'"); } break; default: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"Undefined"); if((PRINT_VALUE)) chpr += printf(" = %#lx/%lu",value,value); break; } chpr = newline(chpr); } setcharsprinted(chpr); return(end_offset); } /* Currently identified only in CIFF files */ unsigned long canon_exposureinfo(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent, struct image_summary *summary_entry) { unsigned long count,value; unsigned long end_offset; float fvalue; int i; int chpr = 0; if(PRINT_SECTION) { chpr += printf(" length %lu",dirlength); chpr = newline(chpr); } /* NOTE that exposureinfo is not treated as a directory; there is */ /* no 2-byte count at the beginning. */ end_offset = offset + dirlength; count = (dirlength / sizeof(unsigned long)); for(i = 0; i < count; ++i) { value = read_ulong(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_ENTRY)) { if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); } offset += 4; switch(i) { case 0: fvalue = to_float(value); if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"ExposureCompensation"); if((PRINT_VALUE)) chpr += printf(" = %f",fvalue); break; case 1: fvalue = to_float(value); if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"Tv"); if((PRINT_VALUE)) chpr += printf(" = %f",fvalue); break; case 2: fvalue = to_float(value); if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"Av"); if((PRINT_VALUE)) chpr += printf(" = %f",fvalue); break; default: fvalue = to_float(value); if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"Undefined"); if((PRINT_VALUE)) chpr += printf(" = %f",fvalue); break; } chpr = newline(chpr); } setcharsprinted(chpr); return(end_offset); } unsigned long canon_focusinfo(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count; unsigned long end_offset; unsigned short value; int i; int chpr = 0; if(PRINT_SECTION) chpr += printf(" length %lu",dirlength); chpr = newline(chpr); /* NOTE that focallength is not treated as a directory; there is */ /* no 2-byte count at the beginning. */ end_offset = offset + dirlength; count = (dirlength / sizeof(unsigned short)); for(i = 0; i < count; ++i) { value = read_ushort(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_ENTRY)) { if((PRINT_TAGINFO)) chpr += printf("%s",tagprefix); } offset += 2; switch(i) { case 0: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"unknown"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 1: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"FocalLength"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 2: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"FocalPlaneXSize"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; case 3: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"FocalPlaneYSize"); if((PRINT_VALUE)) chpr += printf(" = %u",value); break; default: if((PRINT_TAGINFO)) chpr += printf(".%02d_%-22.22s",i,"Undefined"); if((PRINT_VALUE)) chpr += printf(" = %#x%u",value,value); break; } chpr = newline(chpr); } setcharsprinted(chpr); return(end_offset); } /* Some makernotes record offsets as LONG values rather than simply */ /* using UNDEFINED with a size; the same technique used for */ /* the ExifIFDPointer itself, or JpegInterchangeFormat, etc. */ /* This routine hardcodes such tags so that the print_makerentry() */ /* routine will present them as offsets. */ int maker_canon_value_is_offset(struct ifd_entry *entry_ptr,int model) { int is_offset = 0; int noteversion = 0; if(entry_ptr) { noteversion = getnoteversion(); switch(noteversion) { default: switch(entry_ptr->tag) { case 0x0081: is_offset = 1; break; default: break; } break; } } return(is_offset); } /* <0xc5d9=50649> = 2 compression=6 CR2 RGB (Ifd 2) <0xc5d8=50648> = 0 compression=6 primary? (biggest) CR2 Ifd 3 <0xc5e0=50656> = 1 CR2 Ifd 3 <0xc640-50752> = offset to 3 shorts (EOS 350D) CR2 Ifd 3 <0xc640-50752> = offset to 3 shorts (EOS-1Ds Mark II) CR2 Ifd 3 2,1680,1748 (e0=3) */ exifprobe-2.0.1+git20170416-3c2b76/.travis.yml0000644000000000000000000000135413074742216016625 0ustar rootrootlanguage: c os: - linux - osx matrix: include: - os: linux dist: trusty - os: osx osx_image: xcode7.2 - os: osx osx_image: xcode8.1 - compiler: gcc env: COMPILER=gcc - compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test packages: - gcc-5 env: COMPILER=gcc-5 - compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test packages: - gcc-6 env: COMPILER=gcc-6 before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi #- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ; fi script: - make exifprobe-2.0.1+git20170416-3c2b76/print.c0000644000000000000000000033050713074742216016021 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: print.c,v 1.51 2005/07/24 17:16:59 alex Exp $"; #endif /* This file contains the primary "print" routines for TIFF/EXIF */ /* data, file offsets, etc. */ #include #include #include #include "defs.h" #include "datadefs.h" #include "summary.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "maker_extern.h" #include "ciff_extern.h" #include "jp2_extern.h" #include "mrw_extern.h" /* Print the "header" information from the beginning of a file which */ /* identifies the image type and/or image characteristics. Return 0 */ /* if all goes well, -1 if no header is passed or the header magic */ /* number is invlid. */ int print_header(struct fileheader *header,unsigned long section_id) { int status = -1; int chpr = 0; if(header) { switch(header->probe_magic) { case JPEG_SOI: if(Print_options & section_id) chpr += printf("JPEG SOI %#06x",header->file_marker); status = 0; chpr = newline(chpr); break; case ORF1_MAGIC: status = print_tiff_header(ORF1_MAGIC,header->file_marker,section_id); /* no newline */ break; case ORF2_MAGIC: status = print_tiff_header(ORF2_MAGIC,header->file_marker,section_id); /* no newline */ break; case RW2_MAGIC: status = print_tiff_header(RW2_MAGIC,header->file_marker,section_id); /* no newline */ break; case TIFF_MAGIC: status = print_tiff_header(TIFF_MAGIC,header->file_marker,section_id); /* no newline */ break; case PROBE_CIFFMAGIC: status = print_ciff_header(header,section_id); chpr = newline(chpr); break; case PROBE_JP2MAGIC: status = print_jp2_header(header,section_id); chpr = newline(chpr); break; case PROBE_MRWMAGIC: status = print_mrw_header(header,section_id); chpr = newline(chpr); break; case PROBE_RAFMAGIC: chpr = printf("FUJIFILMCCD-RAW "); chpr = newline(chpr); break; default: if(Print_options & section_id) chpr += printf("UNKNOWN HEADER MAGIC %#06lx",header->probe_magic); chpr = newline(chpr); break; } } else fprintf(stderr,"%s: null fileheader to print_header()\n",Progname); return(status); } /* Print TIFF header information if options permit. Return 0 if */ /* information is valid to print or does not need to be printed for */ /* the identified section id. Return -1 if the magic number or */ /* byteorder are invalid. */ int print_tiff_header(unsigned short magic,unsigned short byteorder,unsigned long section_id) { char *name = CNULL; int status = -1; int chpr = 0; if(Print_options & section_id) { switch(magic) { case TIFF_MAGIC: name = "TIFF"; break; case ORF1_MAGIC: name = "ORF1"; break; case ORF2_MAGIC: name = "ORF2"; break; case RW2_MAGIC: name = "RW2"; break; default: break; } if(name) { chpr += printf("%s",name); switch(byteorder) { case TIFF_INTEL: case TIFF_MOTOROLA: print_byteorder(byteorder,1); print_magic((unsigned long)magic,2); status = 0; break; default: chpr += printf("INVALID %s BYTEORDER ",name); print_byteorder(byteorder,1); print_magic((unsigned long)magic,2); break; } } else { chpr += printf("INVALID TIFF IDENTIFIER, byteorder "); print_byteorder(byteorder,1); print_magic((unsigned long)magic,2); } } else status = 0; setcharsprinted(chpr); return(status); } /* Print the file type as indicated by the "header" information at */ /* the start of the file. */ int print_filetype(unsigned long magic,unsigned short marker) { int status = -1; int chpr = 0; switch(magic) { case JPEG_SOI: chpr += printf("JPEG"); status = 0; break; case ORF1_MAGIC: chpr += printf("ORF1"); switch(marker) { case TIFF_INTEL: chpr += printf(":II"); break; case TIFF_MOTOROLA: chpr += printf(":MM"); break; default: break; } status = 0; break; case ORF2_MAGIC: chpr += printf("ORF2"); switch(marker) { case TIFF_INTEL: chpr += printf(":II"); break; case TIFF_MOTOROLA: chpr += printf(":MM"); break; default: break; } status = 0; break; case RW2_MAGIC: chpr += printf("RW2"); switch(marker) { case TIFF_INTEL: chpr += printf(":II"); break; case TIFF_MOTOROLA: chpr += printf(":MM"); break; default: break; } status = 0; break; case TIFF_MAGIC: chpr += printf("TIFF"); switch(marker) { case TIFF_INTEL: chpr += printf(":II"); break; case TIFF_MOTOROLA: chpr += printf(":MM"); break; default: break; } status = 0; break; case PROBE_CIFFMAGIC: chpr += printf("CIFF"); switch(marker) { case TIFF_INTEL: chpr += printf(":II"); break; case TIFF_MOTOROLA: chpr += printf(":MM"); break; default: break; } status = 0; break; case PROBE_JP2MAGIC: chpr += printf("JP2"); status = 0; break; case PROBE_MRWMAGIC: chpr += printf("MRW"); status = 0; break; case PROBE_RAFMAGIC: chpr += printf("RAF"); status = 0; break; case PROBE_X3FMAGIC: chpr += printf("X3F"); status = 0; break; default: chpr += printf("UNKNOWN"); break; } setcharsprinted(chpr); return(status); } /* Print an address in the file (offset from beginning of file), in */ /* hex, decimal, or both, offset from left margin by 'indent' spaces. */ /* "Addresses" are usually prefixed by an "@", but may be prefixed by */ /* a string passed as argument (this is normally used to pass a '-' */ /* prefix to mark the end of a segment, or something to flag an */ /* out-of-order segment). */ /* If this routine is called with all PRINT_ADDRESS bits off, it */ /* produces only the indent. */ void print_tag_address(unsigned long section_id,unsigned long address,int indent,char *prefix) { int chpr = 0; if(Print_options & section_id) { print_filename(); if(PRINT_INDENT_BEFORE_ADDRESS) putindent(indent); if(!prefix) prefix = "@"; if(address == HERE) { /* special case; bland address field */ if(PRINT_BOTH_ADDRESS) chpr += printf("%*s: ",(ADDRWIDTH * 2) + 3,prefix); else if(PRINT_HEX_ADDRESS) chpr += printf("%*s: ",ADDRWIDTH + 1,prefix); else if(PRINT_DEC_ADDRESS) chpr += printf("%*s: ",ADDRWIDTH,prefix); } else { if(PRINT_BOTH_ADDRESS) chpr += printf("%s%#0*lx=%-*lu: ",prefix,ADDRWIDTH+1,address,ADDRWIDTH,address); else if(PRINT_HEX_ADDRESS) chpr += printf("%s%#0*lx: ",prefix,ADDRWIDTH+1,address); else if(PRINT_DEC_ADDRESS) chpr += printf("%s%-*lu: ",prefix,ADDRWIDTH,address); } if(PRINT_INDENT_AFTER_ADDRESS) putindent(indent); setcharsprinted(chpr); } } /* Print the option-selected items in a TIFF IFD entry, including the */ /* tag number, tag name, tag type, and offset or value. If the */ /* "value" doesn't fit in 4 bytes, print_offset_value() will be */ /* called and may defer printing to be handled later (by the caller's */ /* second pass) or may print the offset, preceded by an '@' sign if */ /* appropriate. If the value does fit in the 4 bytes provided in the */ /* entry, print it according to its TIFF type, intercepting tags */ /* which require special handling of value. */ unsigned long print_entry(FILE *inptr,unsigned short byteorder,struct ifd_entry *entry_ptr, unsigned long fileoffset_base,struct image_summary *summary_entry, char *parent_name,int ifdtype,int ifdnum,int subifdnum,int indent) { int value_is_offset = 0; unsigned long endoffset = 0UL; int chpr = 0; value_is_offset = is_offset(entry_ptr); if((PRINT_ENTRY)) { print_taginfo(entry_ptr,parent_name,indent,ifdtype,ifdnum,subifdnum); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) { clearerr(inptr); printred("# INVALID ENTRY"); endoffset = ftell(inptr); } else if(entry_ptr->count == 0) { if(PRINT_VALUE) chpr += printf(" EMPTY (value=%#lx)",entry_ptr->value); endoffset = ftell(inptr); } else if(value_is_offset) { /* Offsets read from the file are printed relative to the */ /* beginning of the file (with fileoffset_base added) so */ /* that the values, printed later, will be easy to find. */ if(PRINT_BOTH_OFFSET) chpr += printf("@%#lx=%lu",entry_ptr->value + fileoffset_base, entry_ptr->value + fileoffset_base); else if(PRINT_HEX_OFFSET) chpr += printf("@%#lx",entry_ptr->value + fileoffset_base); else if(PRINT_DEC_OFFSET) chpr += printf("@%lu",entry_ptr->value + fileoffset_base); if(fileoffset_base && (PRINT_ENTRY_RELOFFSET)) chpr += printf(" (%lu) ",entry_ptr->value); /* Print "inline" in REPORT & LIST modes */ if(!(PRINT_VALUE_AT_OFFSET)) { setcharsprinted(chpr); chpr = 0; endoffset = print_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,parent_name, ifdtype,indent,0); } } else if(PRINT_VALUE) { /* Intercept some EXIF values which print_value() would */ /* not handle properly, possibly because they are ascii */ /* items tagged as UNDEFINED. A few items given as LONG */ /* type are actually offsets, and are printed as such */ /* here, with fileoffset_base added. */ switch(entry_ptr->tag) { case EXIFTAG_ExifVersion: case EXIFTAG_FlashPixVersion: case INTEROPTAG_Version: case INTEROPTAG_Index: /* ASCII */ /* ###%%% show_string()? */ chpr += printf("%s\'%s\'",PREFIX,(char *)&entry_ptr->value); break; case EXIFTAG_ExifIFDPointer: case EXIFTAG_GPSInfoIFDPointer: case EXIFTAG_Interoperability: case TIFFTAG_JPEGInterchangeFormat: /* OFFSETS */ if(PRINT_BOTH_OFFSET) { chpr += printf("@%#lx=%lu",entry_ptr->value + fileoffset_base, entry_ptr->value + fileoffset_base); } else if(PRINT_HEX_OFFSET) chpr += printf("@%#lx",entry_ptr->value + fileoffset_base); else if((PRINT_DEC_OFFSET) || is_a_long_offset(entry_ptr)) chpr += printf("@%lu",entry_ptr->value + fileoffset_base); if(fileoffset_base && (PRINT_ENTRY_RELOFFSET)) chpr += printf(" (%lu)",entry_ptr->value); break; default: /* VALUES */ if(entry_ptr->tag == TIFFTAG_StripOffsets) print_value(entry_ptr,"@"); else print_value(entry_ptr,PREFIX); /* This one is worth flagging... */ if((entry_ptr->tag == TIFFTAG_StripOffsets) && (entry_ptr->value == 0)) { printred(" (BAD START OFFSET)"); } interpret_value(entry_ptr,summary_entry); break; } } chpr = newline(chpr); } return(endoffset); } /* Some items are marked as LONG, but are intended to be interpreted */ /* as offsets. */ int is_a_long_offset(struct ifd_entry *entry_ptr) { int is_an_offset = 0; if(entry_ptr) { switch(entry_ptr->tag) { case EXIFTAG_ExifIFDPointer: case EXIFTAG_GPSInfoIFDPointer: case EXIFTAG_Interoperability: case TIFFTAG_JPEGInterchangeFormat: ++is_an_offset; break; default: break; } } return(is_an_offset); } /* Repeat the tag identifier for values printed at an offset. This is */ /* called only when printing offset values at the offset (rather than */ /* "inline"), and repeats only one of the identifiers (preferably */ /* tagname). */ void print_tagid(struct ifd_entry *entry_ptr,int indent,int ifdtype) { char *nameoftag; int chpr = 0; if(entry_ptr && (PRINT_ENTRY)) { if(PRINT_TAGNAME || !(PRINT_TAGNO)) { switch(ifdtype) { case GPS_IFD: nameoftag = gps_tagname(entry_ptr->tag); break; case INTEROP_IFD: nameoftag = interop_tagname(entry_ptr->tag); break; case EXIF_IFD: case TIFF_IFD: case TIFF_SUBIFD: default: nameoftag = tagname(entry_ptr->tag); break; } chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,nameoftag); } else if(PRINT_HEX_TAGNO) chpr += printf("<%#06x>",entry_ptr->tag & 0xffff); else if(PRINT_DEC_TAGNO) chpr += printf("<%5u>",entry_ptr->tag & 0xffff); } setcharsprinted(chpr); } /* Print the part of an IFD entry describing the entry tag, including */ /* it's tag number, name and type. Only the items enabled in */ /* "Print_options" are printed. */ /* When the LONGNAMES option bit is set prefix the tag name with a */ /* section identifier (parent_name). */ void print_taginfo(struct ifd_entry *entry_ptr,char *parent_name, int indent,int ifdtype,int ifdnum,int subifdnum) { char *nameoftag; char *nameof_value_type; int tagwidth = TAGWIDTH; int chpr = 0; if(entry_ptr && (PRINT_ENTRY)) { if(PRINT_BOTH_TAGNO) chpr += printf("<%#06x=%5u> ",entry_ptr->tag & 0xffff,entry_ptr->tag & 0xffff); else if(PRINT_DEC_TAGNO) chpr += printf("<%5u> ",entry_ptr->tag & 0xffff); else if(PRINT_HEX_TAGNO) chpr += printf("<%#06x> ",entry_ptr->tag & 0xffff); if((PRINT_TAGNAME)) { switch(ifdtype) { case GPS_IFD: nameoftag = gps_tagname(entry_ptr->tag); break; case INTEROP_IFD: nameoftag = interop_tagname(entry_ptr->tag); break; case EXIF_IFD: case TIFF_IFD: case TIFF_SUBIFD: nameoftag = tagname(entry_ptr->tag); break; default: nameoftag = tagname(entry_ptr->tag); break; } if((PRINT_LONGNAMES)) printf("%s.",parent_name); chpr += printf("%-*.*s",tagwidth,tagwidth,nameoftag ? nameoftag : "NULL"); } if(PRINT_TYPE) { nameof_value_type = value_type_name(entry_ptr->value_type); chpr += printf(" [%-2u=%-9.9s %5lu] ",entry_ptr->value_type, nameof_value_type,entry_ptr->count); } if(PRINT_VALUE) chpr += printf(" = "); } setcharsprinted(chpr); } /* Print a "value" from an ifd structure entry, according to the TIFF */ /* type recorded in the entry. Print in hex or decimal (or both) */ /* according to the global Print_options variable. */ void print_value(struct ifd_entry *entry_ptr,char *prefix) { unsigned long byte; unsigned short ushort_val; unsigned long i; int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { if(prefix) chpr += printf("%s",prefix); switch(entry_ptr->value_type) { case SBYTE: byte = entry_ptr->value; for(i = 0; i < entry_ptr->count; ++i) { if(PRINT_BOTH_VALUE) chpr += printf("%#x=%d",(unsigned int)((char)byte & 0xff), (int)((char)byte & 0xff)); else if(PRINT_HEX_VALUE) chpr += printf("%#x",(unsigned int)((char)byte & 0xff)); else if(PRINT_DEC_VALUE) chpr += printf("%d",(int)((char)byte & 0xff)); byte >>= 8; } break; case SHORT: ushort_val = entry_ptr->value ; if(PRINT_BOTH_VALUE) chpr += printf("%#x=%u",ushort_val,ushort_val); else if(PRINT_HEX_VALUE) chpr += printf("%#x",ushort_val); else if(PRINT_DEC_VALUE) chpr += printf("%u",ushort_val); if(entry_ptr->count > 1) { (void)putchar(','); ++chpr; ushort_val = (entry_ptr->value & 0xffff0000) >> 16; if(PRINT_BOTH_VALUE) chpr += printf("%#x=%u",ushort_val,ushort_val); else if(PRINT_HEX_VALUE) chpr += printf("%#x",ushort_val); else if(PRINT_DEC_VALUE) chpr += printf("%u",ushort_val); } break; case SSHORT: ushort_val = entry_ptr->value & 0xffff; if(PRINT_BOTH_VALUE) chpr += printf("%#x=%d",(unsigned int)ushort_val, (int)ushort_val); else if(PRINT_HEX_VALUE) chpr += printf("%#x",(unsigned int)ushort_val); else if(PRINT_DEC_VALUE) chpr += printf("%d",(int)ushort_val); if(entry_ptr->count > 1) { (void)putchar(','); ushort_val = (entry_ptr->value & 0xffff0000) >> 16; if(PRINT_BOTH_VALUE) chpr += printf("%#x=%d",(unsigned int)ushort_val, (int)ushort_val); else if(PRINT_HEX_VALUE) chpr += printf("%#x",(unsigned int)ushort_val); else if(PRINT_DEC_VALUE) chpr += printf("%d",(int)ushort_val); } break; case LONG: if(PRINT_BOTH_VALUE) chpr += printf("0x%08lx=%lu",entry_ptr->value, entry_ptr->value); else if(PRINT_HEX_VALUE) chpr += printf("0x%08lx",entry_ptr->value); else if(PRINT_DEC_VALUE) chpr += printf("%lu",entry_ptr->value); break; case SLONG: if(PRINT_BOTH_VALUE) chpr += printf("%#lx=%ld",(unsigned long)entry_ptr->value, (long)entry_ptr->value); else if(PRINT_HEX_VALUE) chpr += printf("%#lx",(unsigned long)entry_ptr->value); else if(PRINT_DEC_VALUE) chpr += printf("%ld",(long)entry_ptr->value); break; case ASCII: byte = entry_ptr->value; if(entry_ptr->count <= 4) { chpr += printf("\'"); for(i = 0; i < entry_ptr->count; ++i) { if(isprint(byte & 0xff)) (void)putchar(byte & 0xff); else chpr += printf("\\%03ld",byte & 0xff); byte >>= 8; ++chpr; } chpr += printf("\'"); } break; case FLOAT: chpr += printf("%g",(float)entry_ptr->value); break; case DOUBLE: /* double is not possible in a direct ifd entry */ chpr += printf("# DOUBLE TYPE IS INVALID HERE"); break; case UNDEFINED: /* fall through; handle these as BYTE */ case BYTE: default: byte = entry_ptr->value; for(i = 0; i < entry_ptr->count; ++i) { if(i) (void)putchar(','); if(PRINT_BOTH_VALUE) chpr += printf("%#lx=%lu",byte & 0xff,byte & 0xff); else if(PRINT_HEX_VALUE) chpr += printf("%#lx",byte & 0xff); else if(PRINT_DEC_VALUE) chpr += printf("%lu",byte & 0xff); byte >>= 8; } /* UNDEFINED stuff may be ascii */ byte = entry_ptr->value; if((entry_ptr->value_type == UNDEFINED) && (entry_ptr->count == 4) && isprint(byte & 0xff)) { chpr += printf(" = \'"); for(i = 0; i < entry_ptr->count; ++i) { if(isprint(byte & 0xff)) (void)putchar(byte & 0xff); else (void)putchar('.'); byte >>= 8; ++chpr; } (void)putchar('\''); ++chpr; } break; } } setcharsprinted(chpr); } /* Goto the offset given by an IFD entry whose value couldn't be */ /* squeezed into the 4 bytes of the entry itself, and read the value */ /* found at that offset, printing according to the TIFF type found in */ /* the entry. UNDEFINED entry types must/may be special-cased, else */ /* their presence and size will be noted and the data skipped or */ /* hexdumped. */ /* Returns the file pointer offset at the end of processing, which */ /* may be 0 if the seek or read fails, or if the entry does not have */ /* offset data, or the data is outside the current IFD (e.g. */ /* JPEGTables). */ unsigned long print_offset_value(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base, char *parent_name,int ifdtype,int indent, int at_offset) { unsigned long endoffset = 0L; unsigned long value_offset,dumplength,total; char *nameoftag,*data; int chpr = 0; if(inptr && entry_ptr) { value_offset = fileoffset_base + entry_ptr->value; endoffset = value_offset + (value_type_size(entry_ptr->value_type) * entry_ptr->count); if(PRINT_VALUE) { if((at_offset && (PRINT_VALUE_AT_OFFSET)) || ((PRINT_OFFSET) && (entry_ptr->value_type != UNDEFINED))) chpr += printf(" = "); switch(entry_ptr->value_type) { case UNDEFINED: if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,entry_ptr->count); else chpr += printf(":%lu", entry_ptr->count); } switch(entry_ptr->tag) { case EXIFTAG_CFAPattern: if(!at_offset && (PRINT_VALUE)) chpr += printf(" = "); nameoftag = tagname(entry_ptr->tag); setcharsprinted(chpr); chpr = 0; print_cfapattern(inptr,entry_ptr->count, byteorder,value_offset, parent_name,nameoftag); break; case EXIFTAG_UserComment: if(!at_offset && (PRINT_VALUE)) chpr += printf(" = "); setcharsprinted(chpr); chpr = 0; print_user_comment(inptr,entry_ptr->count, value_offset,byteorder); break; case TIFFTAG_META_0xc353: /* This should probably be handled */ /* through the 'private IFD' mechanism, */ /* but do it here for now. */ if(!at_offset && (PRINT_VALUE)) chpr += printf(" = "); /* The first 8 bytes should say "UNICODE" */ if((data = (char *)read_bytes(inptr,8UL,value_offset)) && (strncmp(data,"UNICODE",8) == 0)) { if(!(LIST_MODE)) chpr += printf("UNICODE: "); setcharsprinted(chpr); chpr = 0; print_unicode(inptr,entry_ptr->count - 8,HERE,byteorder); } else { chpr = newline(chpr); dumplength = entry_ptr->count; hexdump(inptr,value_offset,dumplength,dumplength,16,0,SUBINDENT); } break; case TIFFTAG_PrintIM: case EXIFTAG_MakerNote: case TIFFTAG_JPEGTables: break; /* TIFFEP_CFAPATTERN is not quite the same as */ /* EXIF_CFAPattern: it will be handled in */ /* interpret.c */ case TIFFEPTAG_CFAPattern: case TIFFEPTAG_SpatialFrequencyResponse: case EXIFTAG_SpatialFrequencyResponse: case EXIFTAG_SpectralSensitivity: case EXIFTAG_OECF: /* fall through, until some routines are */ /* written for these. */ default: /* Could make a pseudo-tag for 'count' in */ /* LIST mode... */ if(at_offset) { if(Max_undefined == 0L) chpr += printf(" (not dumped, use -U)"); else { /* Even in LIST mode */ if((Max_undefined == DUMPALL) || (Max_undefined > entry_ptr->count)) dumplength = entry_ptr->count; else dumplength = Max_undefined; chpr = newline(1); hexdump(inptr,value_offset,entry_ptr->count, dumplength,12,indent,SUBINDENT); } } /* make certain we're at the end */ fseek(inptr,(long)(value_offset + entry_ptr->count),SEEK_SET); break; } if(!at_offset && (PRINT_VALUE)) chpr += printf(" # UNDEFINED"); break; case BYTE: if(entry_ptr->tag == DNGTAG_OriginalRawFileName) print_ascii(inptr,entry_ptr->count,value_offset); else print_ubytes(inptr,entry_ptr->count,value_offset); break; case SBYTE: print_sbytes(inptr,entry_ptr->count,value_offset); break; case ASCII: print_ascii(inptr,entry_ptr->count,value_offset); if(Debug & NOTE_DEBUG) { if(entry_ptr->tag == TIFFTAG_Make) chpr += printf(" [%d]",maker_number(Make_name)); else if(entry_ptr->tag == TIFFTAG_Model) chpr += printf(" [%d]",model_number(maker_number(Make_name), Model_name,CNULL)); } break; case SHORT: if(entry_ptr->tag == TIFFTAG_StripOffsets) chpr += printf("@"); print_ushort(inptr,entry_ptr->count,byteorder,value_offset); if(entry_ptr->tag == TIFFTAG_StripByteCounts) { total = sum_strip_bytecounts(inptr,byteorder, entry_ptr->value + fileoffset_base, entry_ptr->count,entry_ptr->value_type); chpr += printf(" = %lu",total); } break; case SSHORT: print_sshort(inptr,entry_ptr->count,byteorder,value_offset); break; case LONG: if(entry_ptr->tag == TIFFTAG_StripOffsets) chpr += printf("@"); print_ulong(inptr,entry_ptr->count,byteorder,value_offset); if(entry_ptr->tag == TIFFTAG_StripByteCounts) { total = sum_strip_bytecounts(inptr,byteorder, entry_ptr->value + fileoffset_base, entry_ptr->count,entry_ptr->value_type); chpr += printf(" = %lu",total); } break; case SLONG: print_slong(inptr,entry_ptr->count,byteorder,value_offset); break; case RATIONAL: print_urational(inptr,entry_ptr->count,byteorder,value_offset); break; case SRATIONAL: print_srational(inptr,entry_ptr->count,byteorder,value_offset); break; case FLOAT: print_float(inptr,entry_ptr->count,byteorder,value_offset); break; case DOUBLE: print_double(inptr,entry_ptr->count,byteorder,value_offset); break; default: chpr += printf(" INVALID TYPE %#x",entry_ptr->value_type); break; } setcharsprinted(chpr); chpr = 0; interpret_offset_value(inptr,entry_ptr,byteorder,fileoffset_base); chpr = newline(chpr); } } else { chpr += printf(" invalid call to print_offset_value() "); if(inptr == (FILE *)0) chpr += printf(" - no input file pointer "); if(entry_ptr == (struct ifd_entry *)0) chpr += printf(" - null entry pointer"); chpr = newline(chpr); } return(endoffset); } /* Read 'count' unsigned bytes starting at 'offset' and print their */ /* values in hex. If there are a lot, just print the first few, an */ /* elipsis to admit that something is left out, then print the count */ /* and the last value and its offset. */ void print_ubytes(FILE *inptr,unsigned long count,unsigned long offset) { int i,j; unsigned short byte; int chpr = 0; if(count) { byte = read_ubyte(inptr,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf("%02x",(unsigned int)byte & 0xff); } if(PRINT_MULTIVAL_ALL) { for(i = 1; i < count; ++i,offset += 2L) { byte = read_ubyte(inptr,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%02x",(unsigned int)byte & 0xff); } } else { #define MAX 10UL j = count > MAX + 2 ? MAX : count; for(i = 1; i < j; ++i) { byte = read_ubyte(inptr,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%02x",(unsigned int)byte & 0xff); } if((count > j) && (ferror(inptr) == 0)) { chpr += printf(" ... "); offset += (unsigned long)(count - 1); byte = read_ubyte(inptr,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%02x (%lu)",(unsigned int)byte & 0xff,count); if(PRINT_ADDRESS) chpr += printf(" -> @%lu",offset); } #undef MAX } } /* Read 'count' signed bytes starting at 'offset' and print their */ /* values in decimale. If there are a lot, just print the first few, */ /* an elipsis to admit that something is left out, then print the */ /* last value and its offset. */ void print_sbytes(FILE *inptr,unsigned long count,unsigned long offset) { int i,j; short byte; int chpr = 0; if(count) { byte = read_ubyte(inptr,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf("%d",byte); } if(PRINT_MULTIVAL_ALL) { for(i = 1; i < count; ++i,offset += 2L) { byte = read_ubyte(inptr,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%d",byte); } } else { #define MAX 10UL j = count > MAX + 2 ? MAX : count; for(i = 1; i < j; ++i) { byte = read_ubyte(inptr,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%d",byte); } if((count > j) && (ferror(inptr) == 0)) { chpr += printf(" ... "); offset += (unsigned long)(count - 1); byte = read_ubyte(inptr,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%d (%lu)",byte,count); if(PRINT_ADDRESS) chpr += printf(" -> @%lu",offset); } #undef MAX } setcharsprinted(chpr); } /* Read 'count' unsigned short integers starting at 'offset' and */ /* print their values. If there are a lot, just print the first few, */ /* an elipsis to admit that something is left out, then print the */ /* last value and it's offset. */ void print_ushort(FILE *inptr,unsigned long count,unsigned short byteorder, unsigned long offset) { int i,j; unsigned short value; int chpr = 0; if(count) { value = read_ushort(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_BOTH_VALUE) chpr += printf("%#x/%u",value,value); else if(PRINT_HEX_VALUE) chpr += printf("%#x",value); else if(PRINT_DEC_VALUE) chpr += printf("%u",value); } if(PRINT_MULTIVAL_ALL) { for(i = 1; i < count; ++i,offset += 2L) { value = read_ushort(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_BOTH_VALUE) chpr += printf(",%#x/%u",value,value); else if(PRINT_HEX_VALUE) chpr += printf(",%#x",value); else if(PRINT_DEC_VALUE) chpr += printf(",%u",value); } } else { #define MAX 5UL j = count > MAX + 2 ? MAX : count; for(i = 1; i < j; ++i,offset += 2L) { value = read_ushort(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_BOTH_VALUE) chpr += printf(",%#x/%u",value,value); else if(PRINT_HEX_VALUE) chpr += printf(",%#x",value); else if(PRINT_DEC_VALUE) chpr += printf(",%u",value); } if((count > j) && (ferror(inptr) == 0)) { chpr += printf(" ... "); offset += (unsigned long)(count - j) * 2L; value = read_ushort(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_BOTH_VALUE) chpr += printf(",%#x/%u (%lu)",value,value,count); else if(PRINT_HEX_VALUE) chpr += printf(",%#x (%lu)",value,count); else if(PRINT_DEC_VALUE) chpr += printf(",%u (%lu)",value,count); if(PRINT_ADDRESS) chpr += printf(" -> @%lu",offset); } #undef MAX } setcharsprinted(chpr); } /* Read 'count' signed short integers starting at 'offset' and print */ /* their values. If there are a lot, just print the first 5, an */ /* elipsis to admit that something is left out, then print the last */ /* value and it's offset. */ void print_sshort(FILE *inptr,unsigned long count,unsigned short byteorder, unsigned long offset) { int i,j; short value; int chpr = 0; if(count) { value = (short)read_ushort(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf("%d",value); } if(PRINT_MULTIVAL_ALL) { for(i = 1; i < count; ++i,offset += 2L) { value = (short)read_ushort(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%d",value); } } else { #define MAX 5UL j = count > MAX + 2 ? MAX : count; for(i = 1; i < j; ++i,offset += 2L) { value = (short)read_ushort(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%d",value); } if(count > j) { chpr += printf(" ... "); offset += (unsigned long)(count - j) * 2L; value = (short)read_ushort(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%d (%lu)",value,count); if(PRINT_ADDRESS) chpr += printf(" -> @%lu",offset); } #undef MAX } setcharsprinted(chpr); } /* Read 'count' unsigned long integers starting at 'offset' and print */ /* their values. If there are a lot, just print the first 3, an */ /* elipsis to admit that something is left out, then print the last */ /* value and it's offset. */ void print_ulong(FILE *inptr,unsigned long count,unsigned short byteorder, unsigned long offset) { int i,j; unsigned long value; int chpr = 0; if(count) { value = read_ulong(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_BOTH_VALUE) chpr += printf("%#lx/%lu",value,value); else if(PRINT_HEX_VALUE) chpr += printf("%#lx",value); else if(PRINT_DEC_VALUE) chpr += printf("%lu",value); } if(PRINT_MULTIVAL_ALL) { for(i = 1; i < count; ++i,offset += 4L) { value = read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_BOTH_VALUE) chpr += printf(",%#lx/%lu",value,value); else if(PRINT_HEX_VALUE) chpr += printf(",%#lx",value); else if(PRINT_DEC_VALUE) chpr += printf(",%lu",value); } } else { #define MAX 3UL j = count > MAX + 2 ? MAX : count; for(i = 1; i < j; ++i,offset += 4L) { value = read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_BOTH_VALUE) chpr += printf(",%#lx/%lu",value,value); else if(PRINT_HEX_VALUE) chpr += printf(",%#lx",value); else if(PRINT_DEC_VALUE) chpr += printf(",%lu",value); } if(count > j) { chpr += printf(" ... "); offset += (unsigned long)(count - j) * 4L; value = read_ulong(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_BOTH_VALUE) chpr += printf(",%#lx/%lu (%lu)",value,value,count); else if(PRINT_HEX_VALUE) chpr += printf(",%#lx (%lu)",value,count); else if(PRINT_DEC_VALUE) chpr += printf(",%lu (%lu)",value,count); if(PRINT_ADDRESS) chpr += printf(" -> @%lu",offset); } #undef MAX } setcharsprinted(chpr); } /* Read 'count' signed long integers starting at 'offset' and print */ /* their values. If there are a lot, just print the first 3, an */ /* elipsis to admit that something is left out, then print the last */ /* value and it's offset. */ void print_slong(FILE *inptr,unsigned long count,unsigned short byteorder, unsigned long offset) { int i,j; long value; int chpr = 0; if(count) { value = (long)read_ulong(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf("%ld",value); } if(PRINT_MULTIVAL_ALL) { for(i = 1; i < count; ++i,offset += 4L) { value = (long)read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%ld",value); } } else { #define MAX 3UL j = count > MAX + 2 ? MAX : count; for(i = 1; i < j; ++i) { value = (long)read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%ld",value); } if(count > j) { chpr += printf(" ... "); offset += (unsigned long)(count - j) * 4L; value = (long)read_ulong(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%ld (%lu)",value,count); if(PRINT_ADDRESS) chpr += printf(" -> @%lu",offset); } #undef MAX } setcharsprinted(chpr); } /* Read 'count' unsigned rational values starting at 'offset' and */ /* print their values. If there are a lot, just print the first 3, an */ /* elipsis to admit that something is left out, then print the last */ /* value and it's offset. */ void print_urational(FILE *inptr,unsigned long count,unsigned short byteorder, unsigned long offset) { int i,j; unsigned long num,denom; int chpr = 0; if(count) { num = read_ulong(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } denom = read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_RAW_VALUES) chpr += printf("%lu/%lu = ",num,denom); if(num == 0UL) chpr += printf("0"); else chpr += printf("%g",(double)((double)num/(double)denom)); } if(PRINT_MULTIVAL_ALL) { for(i = 1; i < count; ++i) { num = read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } denom = read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_RAW_VALUES) chpr += printf("%lu/%lu = ",num,denom); if(num == 0UL) chpr += printf(",0"); else chpr += printf(",%g",(double)((double)num/(double)denom)); } } else { #define MAX 3UL j = count > MAX + 2 ? MAX : count; for(i = 1; i < j; ++i) { num = read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } denom = read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_RAW_VALUES) chpr += printf("%lu/%lu = ",num,denom); if(num == 0UL) chpr += printf(",0"); else chpr += printf(",%g",(double)((double)num/(double)denom)); } if(count > j) { chpr += printf(" ... "); offset += (unsigned long)(count - j) * 8UL; fseek(inptr,offset,SEEK_SET); num = read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } denom = read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_RAW_VALUES) chpr += printf("%lu/%lu = ",num,denom); else if(num == 0UL) chpr += printf(",0 (%lu)",count); else chpr += printf(",%g (%lu)",(double)((double)num/(double)denom),count); if(PRINT_ADDRESS) chpr += printf(" -> @%lu",offset); } #undef MAX } setcharsprinted(chpr); } void print_srational(FILE *inptr,unsigned long count,unsigned short byteorder, unsigned long offset) { int i,j; long num,denom; int chpr = 0; if(count) { num = (long)read_ulong(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } denom = (long)read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_RAW_VALUES) chpr += printf("%ld/%ld = ",num,denom); if(num == 0UL) chpr += printf("0"); else chpr += printf("%g",(double)((double)num/(double)denom)); } if(PRINT_MULTIVAL_ALL) { for(i = 1; i < count; ++i) { num = (long)read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } denom = (long)read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_RAW_VALUES) chpr += printf("%ld/%ld = ",num,denom); if(num == 0UL) chpr += printf(",0"); else chpr += printf(",%g",(double)((double)num/(double)denom)); } } else { #define MAX 3UL j = count > MAX + 2 ? MAX : count; for(i = 1; i < j; ++i) { num = (long)read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } denom = (long)read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_RAW_VALUES) chpr += printf("%ld/%ld = ",num,denom); if(num == 0UL) chpr += printf(",0"); else chpr += printf(",%g",(double)((double)num/(double)denom)); } if(count > j) { chpr += printf(" ... "); offset += (unsigned long)(count - j) * 8UL; fseek(inptr,offset,SEEK_SET); num = (long)read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } denom = (long)read_ulong(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } if(PRINT_RAW_VALUES) chpr += printf("%ld/%ld = ",num,denom); if(num == 0UL) chpr += printf(",0 (%lu)",count); else chpr += printf(",%g (%lu)",(double)((double)num/(double)denom),count); if(PRINT_ADDRESS) chpr += printf(" -> @%lu",offset); } #undef MAX } setcharsprinted(chpr); } void print_float(FILE *inptr,unsigned long count,unsigned short byteorder, unsigned long offset) { int i,j; double data; int chpr = 0; if(count) { data = read_float(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf("%g",data); } if(PRINT_MULTIVAL_ALL) { for(i = 1; i < count; ++i) { data = read_float(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%g",data); } } else { #define MAX 3L j = count > MAX + 2 ? MAX : count; for(i = 1; i < j; ++i) { data = read_float(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%g",data); } if(count > j) { chpr += printf(" ... "); offset += (unsigned long)(count - j) * 4L; data = read_float(inptr,byteorder,offset); chpr += printf(",%g (%lu)",data,count); if(PRINT_ADDRESS) chpr += printf(" -> @%lu",offset); } #undef MAX } setcharsprinted(chpr); } void print_double(FILE *inptr,unsigned long count,unsigned short byteorder, unsigned long offset) { int i,j; double data; int chpr = 0; if(count) { data = read_double(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf("%g",data); } if(PRINT_MULTIVAL_ALL) { for(i = 1; i < count; ++i) { data = read_double(inptr,byteorder,HERE); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%g",data); } } else { #define MAX 3L j = count > MAX + 2 ? MAX : count; for(i = 1; i < j; ++i) { data = read_double(inptr,byteorder,HERE); chpr += printf(",%g",data); } if(count > j) { chpr += printf(" ... "); offset += (unsigned long)(count - j) * 8UL; data = read_double(inptr,byteorder,offset); if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); return; } chpr += printf(",%g (%lu)",data,count); if(PRINT_ADDRESS) chpr += printf(" -> @%lu",offset); } #undef MAX } setcharsprinted(chpr); } /* Print up to 'count' bytes read from the image file, starting at */ /* 'offset', as an ascii string, expanding nulls and unprintable */ /* characters. */ /* If PRINT_ASCII_IGNORE_LENGTH is set in Print_options, quit */ /* printing (but not reading) if a null byte is encountered. */ int print_ascii(FILE *inptr,unsigned long count,unsigned long offset) { int remaining; int nread; int ch,lastch; int chpr = 0; int indent = 0; remaining = count; nread = 0; if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) { chpr += printf(" seek failed to offset %lu to print ascii",offset); chpr = newline(chpr); } else { indent = charsprinted(); lastch = 'A'; (void)putchar('\''); chpr++; while((remaining > 0) && !feof(inptr)) { ch = fgetc(inptr); ++nread; --remaining; if(ch && isprint(ch)) { if(isdigit(ch) && (lastch == '\0')) chpr += printf("00"); (void)putchar(ch); chpr++; } else if(ch == '\0') { if((PRINT_ASCII_IGNORE_LENGTH)) { /* read it but don't print any more */ while((remaining-- > 0) && !feof(inptr)) { ch = fgetc(inptr); ++nread; } break; } chpr += printf("\\0"); } else if((ch == '\n') && !(LIST_MODE)) { chpr = newline(chpr); putindent(indent); } else if((ch == '\011') && !(LIST_MODE)) { putchar(ch); ++ch; } else chpr += printf("\\%03o",(unsigned int)(ch & 0xff)); lastch = ch; } (void)putchar('\''); chpr++; if(ferror(inptr)) clearerr(inptr); } setcharsprinted(chpr); return(nread); } /* Write 16 bit 'unicode' data. The data is read as unsigned short */ /* characters and normally printed via putchar() (unsigned char). If */ /* the user specifically requests PRINT_UNICODE, blast out both */ /* bytes. */ /* Any checks for UNICODE should be done by the caller. */ int print_unicode(FILE *inptr,unsigned long count,unsigned long offset,unsigned short byteorder) { int remaining; int nread; int ch = 0; int chpr = 0; nread = 0; if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) { chpr += printf(" seek failed to offset %lu to print unicode",offset); chpr = newline(chpr); } remaining = count / 2; putchar('\''); ++chpr; while((remaining > 0) && !feof(inptr)) { if(ch == 0) chpr += printf("\\0"); else ch = read_ushort(inptr,byteorder,HERE); ++nread; ++chpr; --remaining; /* Write both bytes iff requested by user */ if((PRINT_UNICODE)) (void)fwrite((char *)&ch,2,1,stdout); else putchar(ch); } putchar('\''); ++chpr; if(ferror(inptr)) clearerr(inptr); setcharsprinted(chpr); return(nread); } /* Print an ascii string, expanding nulls and unprintable characters. */ /* Print up to a null byte, or up to 'maxchars', whichever occurs */ /* first. */ /* ###%%% IGNORE_LENGTH? */ int show_string(char *string,int maxchars,int noquotes) { int lastch; int chpr = 0; int indent = 0; int printed = 0; char *ch; if(string) { indent = charsprinted(); lastch = 'A'; if(!noquotes) { (void)putchar('\''); chpr++; } ch = string; while(printed < maxchars) { if(*ch == '\0') { printf("\\0"); break; } else if(isprint(*ch)) { if(isdigit(*ch) && (lastch == '\0')) chpr += printf("00"); (void)putchar(*ch); chpr++; } else if(*ch == '\n') { chpr = newline(chpr); putindent(indent); } else if(*ch == '\011') { putchar(*ch); ++ch; } else chpr += printf("\\%03o",(unsigned int)(*ch & 0xff)); lastch = *ch; ++printed; ++ch; } if(!noquotes) { (void)putchar('\''); chpr++; } } setcharsprinted(chpr); return(printed); } /* Print the UserComment field from an EXIF segment, which is */ /* expected at 'offset' in the file and should be 'count' bytes long. */ /* The field begins with an 8 byte "character code", followed by */ /* 'count - 8' bytes of actual comment. The length is printed as */ /* "%d+8" to give the user the usable length of the comment, but */ /* remind that the 8 bytes is there. An "undefined" field is printed */ /* as ascii, but checked to see if it is filled with nulls or spaces. */ /* Non-ascii comment types are simply hexdumped. */ void print_user_comment(FILE *inptr,unsigned long count,unsigned long offset, unsigned short byteorder) { char *data; int i; int chpr = 0; /* The first 8 bytes identify the character code */ if(PRINT_ENTRY) { if(PRINT_SECTION) chpr += printf("length %lu+8: (CC=",count - 8); if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) { chpr += printf("seek failed to offset %lu to process user comment)",offset); chpr = newline(chpr); } else if((data = (char *)read_bytes(inptr,8UL,HERE))) { if(offset == HERE) offset = ftell(inptr); /* need to return after check */ if((data[0] == 0) || (strncmp(data,"ASCII",5) == 0)) { if(PRINT_SECTION) { if(data[0] == 0) chpr += printf("undefined"); else { for(i = 0; i < 8; ++i) { if(data[i] && isascii(data[i])) { (void)putchar(data[i]); chpr++; } } } (void)putchar(')'); chpr++; chpr += printf(" = "); } i = 8; if(PRINT_SECTION) { /* check for all nulls */ for( ; i < count; ++i) { if(fgetc(inptr) != '\0') break; } } if(i == count) chpr += printf(" (%lu nulls)",count - 8); else { /* check for all spaces */ if(fseek(inptr,offset + 8,SEEK_SET)) { chpr += printf(" re-seek to comment offset %lu failed ",offset + 8); chpr = newline(chpr); why(stdout); } else { i = 8; for( ; i < count; ++i) { if(fgetc(inptr) != ' ') break; } if(i >= count) chpr += printf("(%d spaces)",i - 8); else { if(fseek(inptr,offset + i,SEEK_SET)) { chpr += printf(" re-seek to comment offset %lu failed ",offset + 8); why(stdout); } else { chpr++; /* note that the above loop strips leading spaces */ if((i > 20) && (PRINT_SECTION)) chpr += printf("(%d spaces)",i - 8); print_ascii(inptr,count - i,offset + i); } } } } if((LIST_MODE)) { chpr += printf(" # CC='"); if(data[0]) { for(i = 0; i < 8; ++i) { if(data[i] && isascii(data[i])) { (void)putchar(data[i]); chpr++; } } putchar('\''); ++chpr; } else chpr += printf("undefined'"); } } else if(strncmp(data,"UNICODE",5) == 0) { if((PRINT_SECTION)) { for(i = 0; i < 8; ++i) { if(data[i] && isascii(data[i])) { (void)putchar(data[i]); chpr++; } } } print_unicode(inptr,count - 8,HERE,byteorder); if((LIST_MODE)) { chpr += printf(" # CC='"); if(data[0]) { for(i = 0; i < 8; ++i) { if(data[i] && isascii(data[i])) { (void)putchar(data[i]); chpr++; } } putchar('\''); ++chpr; } else chpr += printf("undefined'"); } } else { chpr = newline(chpr); hexdump(inptr,offset,count,count,16,0,SUBINDENT); chpr = newline(chpr); } } setcharsprinted(chpr); } } #define COLORSTACKSIZE 16 static int colorstack[COLORSTACKSIZE]; static int colorstack_index = -1; void pushcolor(int color) { if(USE_COLOR) { if(colorstack_index < 0) { colorstack_index = 0; colorstack[0] = END_COLOR; } else if(colorstack_index >= (COLORSTACKSIZE - 1)) colorstack_index = 0; printf("\033[%dm",color); colorstack[++colorstack_index] = color; } } void popcolor() { if(USE_COLOR) { if(colorstack_index > 0) colorstack[colorstack_index--] = END_COLOR; printf("\033[0m"); if(colorstack_index >= 0) printf("\033[%dm",colorstack[colorstack_index]); } } void printred(char *msg) { int chpr = 0; PUSHCOLOR(RED); chpr = printf("%s",msg); POPCOLOR(); setcharsprinted(chpr); } /* Print the Color Filter Array pattern in a human-readable form. */ /* The array pattern is printed on a single line, as simply as */ /* possible. This could be annoying for arrays larger than 2x2. */ /* This prints the color characters... */ void putcolorchar(unsigned short color) { switch(color & 0xff) { case 0: putchar('R'); break; case 1: putchar('G'); break; case 2: putchar('B'); break; case 3: putchar('C'); break; case 4: putchar('M'); break; case 5: putchar('Y'); break; case 6: putchar('W'); break; default: putchar('?'); break; } setcharsprinted(1); } /* ...and this does the grunt work. */ void print_cfapattern(FILE *inptr,unsigned long count,unsigned short byteorder, unsigned long offset,char *parent_name,char *nameoftag) { unsigned short horiz_repeat; unsigned short hr = 0; unsigned short vert_repeat; unsigned short vr = 0; unsigned short color; unsigned long cfaoffset,hoffset; int h,v,show; int chpr = 0; int curindent = 0; #define MAX_REPEAT 8 #define MAX_COLOR 6 if((PRINT_SECTION)) chpr += printf("length %lu: ",count); if(offset == HERE) cfaoffset = ftell(inptr); else cfaoffset = offset; horiz_repeat = read_ushort(inptr,byteorder,cfaoffset); vert_repeat = read_ushort(inptr,byteorder,HERE); if((horiz_repeat == 0) || (vert_repeat == 0) || (horiz_repeat > MAX_REPEAT) || (vert_repeat > MAX_REPEAT)) { /* This section checks for possible byteorder reversal in the */ /* repeat counts. */ if(byteorder == TIFF_INTEL) { hr = read_ushort(inptr,TIFF_MOTOROLA,cfaoffset); vr = read_ushort(inptr,TIFF_MOTOROLA,HERE); } else { hr = read_ushort(inptr,TIFF_INTEL,HERE); vr = read_ushort(inptr,TIFF_INTEL,HERE); } if(PRINT_SECTION) { curindent = charsprinted() + chpr; chpr += printf("H=%#x/%u, V=%#x/%u ",horiz_repeat,vert_repeat, horiz_repeat,vert_repeat); PUSHCOLOR(RED); chpr += printf(" (INVALID or BYTE SWAPPED!)*"); POPCOLOR(); chpr = newline(chpr); } else { PUSHCOLOR(RED); chpr += printf("%ux%u",horiz_repeat,vert_repeat); chpr += printf(" # WARNING: repeat counts INVALID or BYTE SWAPPED"); POPCOLOR(); } if((hr > 0) && (vr > 0) && ((hr < MAX_REPEAT) || (vr < MAX_REPEAT))) { horiz_repeat = hr; vert_repeat = vr; if(PRINT_SECTION) { print_tag_address(ENTRY|APP_ENTRY,HERE,0,"*"); curindent -= charsprinted(); putindent(curindent); } else if(PRINT_TAGINFO) { chpr = newline(chpr); print_tag_address(ENTRY|APP_ENTRY,HERE,MEDIUMINDENT,"*"); if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,nameoftag); if((PRINT_VALUE)) chpr += printf(" = "); } } } if(PRINT_SECTION) { chpr += printf("H=%#x/%u, V=%#x/%u ",horiz_repeat,vert_repeat, horiz_repeat,vert_repeat); /* Some sanity checks */ if((horiz_repeat == 0) || (vert_repeat == 0) || (horiz_repeat > MAX_REPEAT) || (vert_repeat > MAX_REPEAT)) { PUSHCOLOR(RED); chpr += printf(" INVALID REPEAT COUNT"); POPCOLOR(); } else { chpr += printf(" = "); hoffset = ftell(inptr); for(v = 0; v < vert_repeat; ++v) { putchar('['); ++chpr; /* show 2 repetitions */ for(show = 0; show < 2; ++show) { for(h = 0; h < horiz_repeat; ++h) { color = read_ubyte(inptr,hoffset+h); if(ferror(inptr)) break; if(color <= MAX_COLOR) { putcolorchar(color & 0xff); putchar(','); ++chpr; } else { putchar('?'); ++chpr; setcharsprinted(chpr); return; } } } chpr += printf(" ...],"); hoffset = ftell(inptr); } chpr += printf(" ..."); if(hr) printred(" (BYTE SWAPPED) "); } } else { chpr += printf("%dx%d",horiz_repeat,vert_repeat); if((horiz_repeat == 0) || (vert_repeat == 0) || (horiz_repeat > MAX_REPEAT) || (vert_repeat > MAX_REPEAT)) { PUSHCOLOR(RED); chpr += printf("# INVALID REPEAT COUNT"); POPCOLOR(); } else { print_startvalue(); hoffset = ftell(inptr); for(v = 0; v < vert_repeat; ++v) { for(h = 0; h < horiz_repeat; ++h) { color = read_ubyte(inptr,hoffset+h); if(ferror(inptr)) break; if(color < MAX_COLOR) { putcolorchar(color & 0xff); if((h + 1) < horiz_repeat) putchar(','); ++chpr; } else { putchar('?'); ++chpr; setcharsprinted(chpr); return; } } hoffset = ftell(inptr); if((v + 1) < vert_repeat) putchar(':'); } print_endvalue(); if(hr) printred(" # BYTE SWAPPED"); } } if(ferror(inptr)) clearerr(inptr); setcharsprinted(chpr); } /* Dump a bunch of bytes in traditional hex/ascii format. The offset */ /* and size of the chunk to dump are passed, with a separate argument */ /* for the number of bytes to print, which is constrained to be <= */ /* the size. The per-line width of the output is also passed */ /* (sometimes this program uses 16, sometimes 12 if the chunk might */ /* be in IFD format). */ /* This function checks to assure that the buffer in read_bytes() is */ /* not overrun (read_bytes() can't report truncation) and loops on */ /* the data if necessary. */ /* If the length of data to be printed is less than the actual size, */ /* the last line is annotated with "ect..." to indicate that there is */ /* more. On the other hand, if 'max_to_print' expires before the last */ /* line is full, both fields are padded with spaces. */ /* NOTE: this routine never prints a final newline (intentionally) */ void hexdump(FILE *inptr,unsigned long offset,unsigned long size, unsigned long max_to_print,int width,int indent, int subindent) { char *data,*next; int bytes = 0; int printed = 0; int etc = 0; unsigned long remaining,readlength; int i; int chpr = 0; if(inptr) { if((size > 0L) && (max_to_print > 0L)) { if(size > MAXBUFLEN) readlength = MAXBUFLEN; else readlength = size; /* Always read in multiples of "width" if doing multiple */ /* reads. */ if(size > readlength) readlength = (readlength / width) * width; if(size < max_to_print) max_to_print = size; if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) { chpr += printf(" seek failed to offset %lu to print hex/ascii dump",offset); chpr = newline(chpr); why(stdout); return; } while((printed < max_to_print) && (data = (char *)read_bytes(inptr,readlength,HERE))) { if(feof(inptr) || ferror(inptr)) { clearerr(inptr); setcharsprinted(chpr); break; } if(max_to_print < readlength) { readlength = max_to_print; ++etc; } bytes = 0; while(bytes < readlength) { next = data; remaining = readlength - bytes; /* start address of each line */ print_tag_address(ENTRY|APP_ENTRY,offset + printed, indent + SUBINDENT," "); extraindent(subindent); /* This is the hex part */ for(i = 0; i < width; ++i) { if(i && ((i % 4) == 0)) putchar(' '); if(i < remaining) chpr += printf("%02x ",(unsigned int)(*data++ & 0xff)); else chpr += printf(" "); } /* Now do it again for the ascii side */ chpr += printf(" |"); remaining = readlength - bytes; for(i = 0; i < width; ++i,++next,++bytes,++printed) { if(i >= remaining) /* pad at the end */ putchar(' '); else if(isprint(*next)) putchar(*next); else putchar('.'); /* can't win 'em all */ ++chpr; } if(printed < max_to_print) chpr += printf("|\n"); /* every line except the last */ else chpr += printf("|"); } if((max_to_print - printed) < readlength) readlength = max_to_print - printed; } if(etc) /* didn't print the whole chunk... */ chpr += printf(" etc..."); } } else printred(" INTERNAL ERROR: no input file to hexdump()\n"); setcharsprinted(chpr); } /* indent the following text by printing 'indent' spaces */ void putindent(int spaces) { int spaces_left; if(spaces > MAXINDENT) spaces = MAXINDENT; spaces_left = spaces; while(spaces_left-- > 0) (void)putchar(' '); setcharsprinted(spaces); } /* conditionally indent the following text */ void extraindent(int spaces) { if(PRINT_INDENT) putindent(spaces); } #define START_VALUE " = \'" void print_startvalue() { printf("%s",START_VALUE); setcharsprinted(sizeof(START_VALUE)); } #define END_VALUE "\'" void print_endvalue() { printf("%s",END_VALUE); setcharsprinted(sizeof(END_VALUE)); } /* Print the TIFF byteorder. If verbose, print as "(hex=ascii)", */ /* otherwise just print the 2 bytes as a string, with octal escapes */ /* for unprintable bytes. */ void print_byteorder(unsigned short byteorder,int verbose) { int chpr = 0; if(verbose == 1) chpr += printf("("); else if(verbose == 2) chpr += printf("\'"); (void)show_string((char *)&byteorder,2,1); /* Check for a legitimate TIFF byteorder */ if(verbose == 1) { switch(byteorder) { case TIFF_INTEL: case TIFF_MOTOROLA: chpr += printf("=%#06x)",byteorder); break; default: chpr +=printf("=%#06x=unknown)",byteorder); break; } } else if(verbose == 2) chpr += printf("\'"); setcharsprinted(chpr); } /* Print a "magic number". The 'size' argument should be 2 for */ /* unsigned short magic numbers, 4 for unsigned long. */ void print_magic(unsigned long magic,int size) { int chpr = 0; chpr += printf(" magic=%#06lx=",magic); show_string((char *)&magic,size,0); setcharsprinted(chpr); } /* Check and clear the status recorded by jpeg_status() from */ /* process_jpeg_segments() and report anomalies. Output is preceded */ /* by shell comment markers and normally appears at the end of a */ /* line. */ void print_jpeg_status() { int status = 0; /* get and clear the status */ status = jpeg_status(status); if((PRINT_SEGMENT)) { if(status == JPEG_NO_SOI) printred(" ### (JPEG_SOI NOT FOUND)"); if(status == JPEG_HAD_ERROR) printred(" ### (INVALID JPEG MARKER)"); else if(status == JPEG_NO_EOI) printred(" ### (JPEG_EOI NOT FOUND)"); else if(status == JPEG_EARLY_EOI) printred(" (JPEG_EOI FOUND EARLY)"); } } void display_end_of_ifd(unsigned long max_ifd_offset,int ifdtype,int ifdnum,int subifdnum, int indent,char *ifdname,char *prefix) { int chpr = 0; print_tag_address(SECTION,max_ifd_offset - 1,indent,prefix); switch(ifdtype) { case TIFF_IFD: if(PRINT_SECTION) chpr += printf("",ifdnum); break; case TIFF_SUBIFD: if(PRINT_SECTION) chpr += printf("",subifdnum,ifdnum); break; case INTEROP_IFD: if(PRINT_SECTION) chpr += printf(""); break; case GPS_IFD: if(PRINT_SECTION) chpr += printf(""); break; case EXIF_IFD: if(PRINT_SECTION) chpr += printf(""); break; case MAKER_SUBIFD: if(PRINT_SECTION) chpr += printf("",ifdname); break; default: if(PRINT_SECTION) chpr += printf("",ifdtype); break; } chpr = newline(chpr); } /* Provide a short hex/ascii dump of interesting sections. The */ /* default dumplength can be increased via the -U option. This allows */ /* examination of the tables and CFA sections. */ void dumpsection(FILE *inptr,unsigned long offset,unsigned long length,int indent) { unsigned long dumplength; if(inptr) { if(Max_imgdump > 0L) dumplength = Max_imgdump; else dumplength = DEF_DUMPLENGTH; if(dumplength > length) dumplength = length; if(dumplength) { hexdump(inptr,offset,length,dumplength,16,indent,0); (void)newline(1); } } } /* ================= PRIVATE IFDs ==================== */ /* process_private_ifd() reads an ifd section which is defined */ /* "privately" (e.g. by a camera maker for use in makernotes) and for */ /* which tag numbers are thus defined without reference to the TIFF */ /* spec. Any interpretation of tag numbers, values, etc. must be */ /* switched through routines which recognize the make of the camera */ /* or other device which produced the file, and might potentially */ /* need to recognize a "note version" as well. */ /* The routine currently assumes a single IFD (no IFD chaining), */ /* which may be be short-sighted considering the inventive nature of */ /* camera producers. Please stand by... */ /* There is a mild assumption that these IFDs will be contained in */ /* makernotes, since the TIFF, JPEG and Exif specs do not provide for */ /* such things outside the maker blob. */ unsigned long process_private_ifd(FILE *inptr,unsigned short byteorder, unsigned long subifd_offset,unsigned long fileoffset_base, unsigned long max_offset,unsigned short subifd_ident, struct image_summary *summary_entry,char *parent_name, char *prefix,int make,int model,int indent) { struct ifd_entry *entry_ptr; unsigned long max_value_offset = 0L; unsigned long next_ifd_offset,current_offset,max_subifd_offset; unsigned long start_entry_offset,entry_offset,value_offset; int entry_num,num_entries,value_is_offset,use_second_pass; int chpr = 0; if(inptr == (FILE *)0) { fprintf(stderr,"%s: no open file pointer to read makernote %s subifd\n", Progname,parent_name); return(0L); } if(summary_entry) summary_entry->filesubformat |= FILESUBFMT_MNSUBIFD; /* If the section appears to be beyond the end of the parent ifd, */ /* mark the start address to call attention. */ if(max_offset && ((subifd_offset + fileoffset_base) > max_offset)) prefix = "+"; max_subifd_offset = max_offset; print_tag_address(SECTION,subifd_offset + fileoffset_base,indent,prefix); if(PRINT_SECTION) chpr += printf("<%s SubIFD> (in MakerNote)",parent_name); num_entries = read_ushort(inptr,byteorder,subifd_offset + fileoffset_base); if(ferror(inptr) || feof(inptr)) goto blewit; current_offset = entry_offset = start_entry_offset = ftell(inptr); if(PRINT_SECTION) { chpr += printf(" %d entries ",num_entries); chpr += printf("starting at file offset %#lx=%lu", current_offset,current_offset); chpr = newline(chpr); } use_second_pass = value_is_offset = 0; /* The direct entries */ for(entry_num = 0; entry_num < num_entries; ++entry_num) { entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) { int invalid_entry = 0; unsigned long limit_offset = 0L; print_tag_address(ENTRY,entry_offset,indent,prefix); chpr += printf(" INVALID MAKERNOTE SUBIFD ENTRY (%lu)",entry_ptr->value); chpr = newline(chpr); clearerr(inptr); current_offset = ftell(inptr); if(max_offset > 0) limit_offset = max_offset; else { if(fseek(inptr,0L,SEEK_END) != -1) { limit_offset = ftell(inptr); fseek(inptr,current_offset,SEEK_SET); } } /* If there's an error on input, or we can't check */ /* for absurd num_entries, give up. */ if(!ferror(inptr) && (limit_offset > 0)) { /* If the number of entries would read past the */ /* size of the IFD, or past EOF, give up */ if((entry_offset + (12 * num_entries)) < limit_offset) { /* Limit the number of consecutive failures. */ /* An apparently valid entry resets the count */ /* to 0. */ if(invalid_entry++ < MAX_INVALID_ENTRIES) { entry_offset = current_offset; continue; } } } chpr = newline(chpr); goto blewit; } current_offset = ftell(inptr); print_tag_address(ENTRY,entry_offset,indent,prefix); value_offset = print_private_entry(inptr,byteorder,entry_ptr,fileoffset_base, subifd_ident,summary_entry,parent_name, prefix,make,model,SUBINDENT); if(value_offset == 0UL) value_offset = current_offset; if(value_offset > max_value_offset) max_value_offset = value_offset; if((PRINT_VALUE_AT_OFFSET) && (is_offset(entry_ptr))) ++use_second_pass; entry_offset = current_offset; } next_ifd_offset = read_ulong(inptr,byteorder,current_offset); /* offsets found in the next pass should be within the bounds of */ /* the parent ifd. The following helps to detect chunks that are */ /* written "out of place". */ /* There should be no next_ifd_offset (it should be 0) */ /* ###%%% prepare for chains? */ if(next_ifd_offset > 0L) { /* ###%%% report unwillingness to handle chained IFDs */ if((PRINT_ADDRESS) && (PRINT_VALUE) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(ENTRY,current_offset,indent,prefix); extraindent(SUBINDENT); chpr += printf("**** next IFD offset %lu ",next_ifd_offset); next_ifd_offset += fileoffset_base; if(next_ifd_offset < ftell(inptr)) { printred("BAD NEXT IFD OFFSET"); next_ifd_offset = 0L; } else chpr += printf("(+ %lu = %#lx/%lu)",fileoffset_base, next_ifd_offset,next_ifd_offset); chpr = newline(chpr); } else next_ifd_offset += fileoffset_base; /* This should never happen */ max_subifd_offset = next_ifd_offset; } else { if((PRINT_ADDRESS) && (PRINT_VALUE) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(ENTRY,current_offset,indent,prefix); extraindent(SUBINDENT); chpr += printf("**** next IFD offset 0"); chpr = newline(chpr); } } if(ferror(inptr) || feof(inptr)) { chpr += printf(" READ NEXT IFD OFFSET FAILED "); chpr = newline(chpr); why(stdout); clearerr(inptr); /* keep going... */ } else current_offset = ftell(inptr); value_offset = current_offset; /* Second pass, to evaluate entries which are stored indirectly. */ /* This occurs when the value requires more than 4 bytes, AND for */ /* certain LONG values which are intended to be used as offsets */ if(use_second_pass) { if((PRINT_VALUE) && (PRINT_ADDRESS) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(ENTRY,value_offset,indent,prefix); extraindent(SUBINDENT); chpr += printf("============= VALUES, %s IFD ============",parent_name); chpr = newline(chpr); } entry_offset = start_entry_offset; for(entry_num = 0; entry_num < num_entries; ++entry_num) { entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) { /* If the first pass made it through invalid entries, */ /* this pass should just ignore them and quietly */ /* continue. */ clearerr(inptr); entry_offset = current_offset = ftell(inptr); continue; } current_offset = entry_offset = ftell(inptr); if(is_offset(entry_ptr) || private_value_is_offset(make,subifd_ident,entry_ptr->tag)) { value_offset = print_offset_pe_value(inptr,byteorder, entry_ptr,fileoffset_base, subifd_ident,summary_entry, parent_name,prefix,indent, make,model,1); } if(value_offset > max_value_offset) max_value_offset = value_offset; } } else if(current_offset > max_value_offset) max_value_offset = current_offset; if(max_offset && (max_value_offset > max_offset)) { max_value_offset = max_offset; print_tag_address(SECTION,max_value_offset - 1,indent,">"); } else print_tag_address(SECTION,max_value_offset - 1,indent,"-"); if(PRINT_SECTION) { chpr += printf(" (in MakerNote)",parent_name); chpr = newline(chpr); } return(max_value_offset); blewit: clearerr(inptr); current_offset = ftell(inptr); print_tag_address(SECTION,current_offset - 1,indent,"-"); if(PRINT_SECTION) { chpr += printf(""); chpr = newline(chpr); } return(0L); } unsigned long print_private_entry(FILE *inptr,unsigned short byteorder,struct ifd_entry *entry_ptr, unsigned long fileoffset_base, unsigned short subifd_ident, struct image_summary *summary_entry, char *parent_name, char *prefix,int make,int model,int indent) { int value_is_offset = 0; unsigned long endoffset = 0UL; int chpr = 0; if((PRINT_ENTRY)) { value_is_offset = is_offset(entry_ptr); if(value_is_offset == 0) value_is_offset = private_value_is_offset(make,subifd_ident,entry_ptr->tag); print_private_taginfo(entry_ptr,subifd_ident,parent_name,make,indent); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) { clearerr(inptr); printred("# INVALID ENTRY"); endoffset = ftell(inptr); } else if(entry_ptr->count == 0) { if(PRINT_VALUE) chpr += printf(" EMPTY (value=%#lx)",entry_ptr->value); endoffset = ftell(inptr); } else if(value_is_offset) { if(value_is_offset > 0) { /* Offsets read from the file are printed relative to the */ /* beginning of the file (with fileoffset_base added) so */ /* that the values, printed later, will be easy to find. */ if(PRINT_BOTH_OFFSET) chpr += printf("@%#lx=%lu",entry_ptr->value + fileoffset_base, entry_ptr->value + fileoffset_base); else if(PRINT_HEX_OFFSET) chpr += printf("@%#lx",entry_ptr->value + fileoffset_base); else if(PRINT_DEC_OFFSET) chpr += printf("@%lu",entry_ptr->value + fileoffset_base); if(fileoffset_base && (PRINT_ENTRY_RELOFFSET)) chpr += printf(" (%lu) ",entry_ptr->value); } else if((value_is_offset < 0) && (PRINT_VALUE)) { print_value(entry_ptr,PREFIX); interpret_pe_value(entry_ptr,subifd_ident,make,prefix); } /* Print "inline" in REPORT & LIST modes */ if(!(PRINT_VALUE_AT_OFFSET)) { setcharsprinted(chpr); chpr = 0; endoffset = print_offset_pe_value(inptr,byteorder, entry_ptr,fileoffset_base, subifd_ident,summary_entry, parent_name,"@",indent + MEDIUMINDENT, make,model,0); } } else if(PRINT_VALUE) { print_value(entry_ptr,PREFIX); interpret_pe_value(entry_ptr,subifd_ident,make,prefix); } chpr = newline(chpr); } return(endoffset); } int private_value_is_offset(int make,unsigned short subifd_ident,unsigned short tag) { int is_offset = 0; switch(make) { case MAKER_OLYMPUS: is_offset = olympus_private_value_is_offset(subifd_ident,tag); break; default: break; } return(is_offset); } void print_private_taginfo(struct ifd_entry *entry_ptr,unsigned short subifd_ident, char *parent_name,int make,int indent) { char *nameoftag = CNULL; char *nameof_value_type = CNULL; int tagwidth = TAGWIDTH; int chpr = 0; if(entry_ptr && (PRINT_ENTRY)) { extraindent(indent); if(PRINT_BOTH_TAGNO) chpr += printf("<%#06x=%5u> ",entry_ptr->tag & 0xffff,entry_ptr->tag & 0xffff); else if(PRINT_DEC_TAGNO) chpr += printf("<%5u> ",entry_ptr->tag & 0xffff); else if(PRINT_HEX_TAGNO) chpr += printf("<%#06x> ",entry_ptr->tag & 0xffff); if((PRINT_TAGNAME)) { nameoftag = private_tagname(make,entry_ptr->tag,subifd_ident); if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",tagwidth,tagwidth,nameoftag ? nameoftag : "NULL"); } if(PRINT_TYPE) { nameof_value_type = value_type_name(entry_ptr->value_type); chpr += printf(" [%-2u=%-9.9s %5lu] ",entry_ptr->value_type, nameof_value_type,entry_ptr->count); } if(PRINT_VALUE) chpr += printf(" = "); } setcharsprinted(chpr); } void print_private_tagid(struct ifd_entry *entry_ptr,unsigned short subifd_ident, int make,int indent) { char *nameoftag; int chpr = 0; if(entry_ptr && (PRINT_ENTRY)) { extraindent(indent); if(PRINT_TAGNAME || !(PRINT_TAGNO)) { nameoftag = private_tagname(make,entry_ptr->tag,subifd_ident); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,nameoftag); } else if(PRINT_HEX_TAGNO) chpr += printf("<%#06x>",entry_ptr->tag & 0xffff); else if(PRINT_DEC_TAGNO) chpr += printf("<%5u>",entry_ptr->tag & 0xffff); /* ###%%% should be done just befor value is printed, not */ /* here */ if(PRINT_VALUE) chpr += printf(" = "); } setcharsprinted(chpr); } char * private_tagname(int make,unsigned short tag,unsigned short subifd_ident) { static char unknown_buf[16]; char *tagname = CNULL; switch(make) { case MAKER_OLYMPUS: tagname = olympus_private_tagname(tag,subifd_ident); break; default: break; } if(tagname == CNULL) { unknown_buf[0] = '\0'; if(snprintf(unknown_buf,11,"TAG_%#06x",(int)tag) > 11) { printf(" bad tag %#x not converted\n",tag); why(stdout); tagname = ""; } else tagname = unknown_buf; } return(tagname); } /* Interpret private entry values */ void interpret_pe_value(struct ifd_entry *entry_ptr,unsigned short subifd_ident, int make,char *prefix) { if(entry_ptr) { switch(make) { case MAKER_OLYMPUS: olympus_interpret_pe_value(entry_ptr,subifd_ident,prefix); break; default: break; } } } unsigned long print_offset_pe_value(FILE *inptr,unsigned short byteorder,struct ifd_entry *entry_ptr, unsigned long fileoffset_base,unsigned short subifd_ident, struct image_summary *summary_entry,char *parent_name,char*prefix, int indent,int make,int model,int at_offset) { unsigned long endoffset = 0L; if(inptr && entry_ptr) { endoffset = fileoffset_base + entry_ptr->value + (value_type_size(entry_ptr->value_type) * entry_ptr->count); switch(make) { case MAKER_OLYMPUS: olympus_offset_pe_value(inptr,byteorder,entry_ptr,fileoffset_base, subifd_ident,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; default: print_private_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,subifd_ident, parent_name,prefix,indent, make,model,at_offset); break; } } else { printred(" invalid call to print_offset_pe_makervalue "); if(inptr == (FILE *)0) printred(" no input file pointer "); if(entry_ptr == (struct ifd_entry *)0) printred(" null entry pointer"); } if(ferror(inptr) || feof(inptr)) clearerr(inptr); (void)newline(0); return(endoffset); } void print_private_offset_value(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base, unsigned short subifd_ident,char *parent_name, char *prefix, int indent,int make,int model,int at_offset) { unsigned long value_offset; unsigned long dumplength; int chpr = 0; if((value_type_size(entry_ptr->value_type) * entry_ptr->count) > 4) { value_offset = fileoffset_base + entry_ptr->value; if(PRINT_VALUE) { if(at_offset) { print_tag_address(ENTRY,value_offset,indent,prefix); print_private_tagid(entry_ptr,subifd_ident,make,SUBINDENT); } else { if((PRINT_OFFSET) && (entry_ptr->value_type != UNDEFINED)) chpr += printf(" = "); } switch(entry_ptr->value_type) { case UNDEFINED: /* Could make a pseudo-tag for 'count' in LIST */ /* mode... */ if((PRINT_SECTION)) chpr += printf("length %-9lu # UNDEFINED",entry_ptr->count); else { if(!(PRINT_OFFSET)) chpr += printf("@%lu",value_offset); chpr += printf(":%lu # UNDEFINED",entry_ptr->count); } if(Max_undefined == 0) { if((PRINT_SECTION)) printred(" (not dumped, use -U)"); } else { /* Even in LIST mode */ if((Max_undefined == DUMPALL) || (Max_undefined > entry_ptr->count)) dumplength = entry_ptr->count; else dumplength = Max_undefined; chpr = newline(1); hexdump(inptr,entry_ptr->value + fileoffset_base, entry_ptr->count,dumplength,12, indent,SUBINDENT); } /* make certain we're at the end */ fseek(inptr,(long)(entry_ptr->value + fileoffset_base + entry_ptr->count),SEEK_SET); break; case ASCII: print_ascii(inptr,entry_ptr->count,value_offset); break; case BYTE: print_ubytes(inptr,entry_ptr->count,value_offset); break; case SBYTE: print_sbytes(inptr,entry_ptr->count,value_offset); break; case SHORT: print_ushort(inptr,entry_ptr->count,byteorder,value_offset); break; case SSHORT: print_sshort(inptr,entry_ptr->count,byteorder,value_offset); break; case LONG: print_ulong(inptr,entry_ptr->count,byteorder,value_offset); break; case SLONG: print_slong(inptr,entry_ptr->count,byteorder,value_offset); break; case RATIONAL: print_urational(inptr,entry_ptr->count,byteorder,value_offset); break; case SRATIONAL: print_srational(inptr,entry_ptr->count,byteorder,value_offset); break; case FLOAT: print_float(inptr,entry_ptr->count,byteorder,value_offset); break; case DOUBLE: print_double(inptr,entry_ptr->count,byteorder,value_offset); break; default: chpr = printf(" INVALID TYPE %#x",entry_ptr->value_type); break; } } } if(ferror(inptr) || feof(inptr)) clearerr(inptr); setcharsprinted(chpr); } /* ================= END PRIVATE IFDS ================== */ exifprobe-2.0.1+git20170416-3c2b76/INSTALLING0000644000000000000000000000474313074742216016110 0ustar rootroot# @(#) $Id: INSTALLING,v 1.8 2005/06/30 17:51:42 alex Exp $ The program should compile on any reasonably modern Unix or Linux system, but has been tested only on FreeBSD and RedHat Linux. No extra libraries are required. If you compile on other systems, please let me know. I have deliberately attempted to avoid the need for massive "autoconfuse" scripts, but time will tell. For FreeBSD and Linux, it should be sufficient to just type 'make' unless you wish to change defaults for CFLAGS (see below). On some systems you may need 'gmake' (or edit the PREFIX line to something your make will accept). If your system does not have a system include file "endian.h" which defines BYTE_ORDER (or __BYTE_ORDER) as LITTLE-something or BIG-something, you may need to fix the file "makebyteorder.sh", or manually create a file "byteorder.h" in the distribution directory. If your machine's native byte order is big-endian, add the single line: #define NATIVE_BYTEORDER_BIGENDIAN The sources assume little-endian unless told otherwise, so an empty "byteorder.h" is sufficient in that case. Check CFLAGS: If your system includes provide the type 'uint32_t' in types.h but not 'u_int32_t' (Solaris), uncomment the line which defines uint32_t (or add the definition to CFLAGS). BSD and Linux define u_int32_t in sys/types.h, which is where this code expects it. If you do NOT want support for ANSI color sequences to emphasize certain sections of the output, remove -DCOLOR Alternatively, if you want color but find my selections bilious, you can change a few defines in defs.h. The colors currently used are intended to be used with a light background; I don't recommend them with 'reverse-video' or otherwise dark backgrounds. If you want color compiled in, but don't want it by default (the '-c' flag toggles color if support is compiled in) edit defs.h to remove the PRINT_COLOR bit from PRINT_DEFAULTS. Check PREFIX, BINDIR and MANDIR: set to the directories where the executable and manual page should be copied. Normally, you will only need to set PREFIX. Then do (optional) make depend (requires the executable 'makedepend') make and when you're ready make install The files in the 'aux" directory must be compiled and/or installed manually. There is a simple Makefile for the C programs. You may want to modify the scripts for your own purposes. Duane Hesser dhh@virtual-cafe.com http://virtual-cafe.com/~dhh/tools.d/software.html exifprobe-2.0.1+git20170416-3c2b76/x3f_extern.h0000644000000000000000000000647313074742216016761 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: x3f_extern.h,v 1.2 2005/07/24 21:03:53 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef X3F_EXTERN_INCLUDED #define X3F_EXTERN_INCLUDED /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Fujifilm X3F-specific external definitions */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ extern struct x3f_header *read_x3fheader(FILE *,unsigned long); extern int print_x3f_header(FILE *,struct fileheader *,unsigned long); extern unsigned long process_x3f(FILE *,struct fileheader *,unsigned long, struct image_summary *, char *,int,int); extern unsigned long process_x3f_dir(FILE *,unsigned short,struct x3f_header *, unsigned long,struct image_summary *, char *,int,int); extern void process_x3f_direntry(FILE *,unsigned short,struct x3f_direntry *, unsigned long,struct image_summary *, char *,int,int); extern struct x3f_direntry *read_x3f_direntry(FILE *,unsigned short, struct x3f_direntry *, unsigned long offset); extern void print_x3f_direntry(FILE *,struct x3f_direntry *,unsigned long, char *,int,int); extern struct x3f_imag_header *read_x3f_imag_header(FILE *,unsigned short,unsigned long); extern struct x3f_prop_header *read_x3f_prop_header(FILE *,unsigned short,unsigned long); extern struct x3f_camf_header *read_x3f_camf_header(FILE *,unsigned short,unsigned long); extern unsigned long display_x3f_imag_header(struct x3f_direntry *,struct x3f_imag_header *, char *,int,int); extern unsigned long display_x3f_prop_header(struct x3f_direntry *,struct x3f_prop_header *, char *,int,int); extern unsigned long display_x3f_camf_header(struct x3f_direntry *,struct x3f_camf_header *, char *,int,int); extern unsigned long process_x3f_props(FILE *,unsigned short,unsigned long,unsigned long, unsigned long,char *,unsigned long,int); extern void print_property(FILE *,unsigned short,unsigned long,unsigned long,unsigned long, char *,int,int); #endif /* X3F_EXTERN_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/maker_konica.c0000644000000000000000000001630413074742216017304 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_konica.c,v 1.3 2005/07/24 22:56:26 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Konica camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* */ /* A bare minimum is known at this time (4/22/03)...just the PrintIM */ /* tag. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id konica_model_id[]; /* Find the identifying number assigned to known Konica camera */ /* models. This number is used to dispatch print and interpret */ /* routines approopriate to the current image. */ int konica_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &konica_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine for direct values in Konica cameras, */ /* based upon model */ void print_konica_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { int noteversion = 0; if(entry_ptr && (PRINT_VALUE)) { noteversion = getnoteversion(); switch(noteversion) { case 1: print_konica_makervalue(entry_ptr,make,model,prefix); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Konica cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_konica1_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for Konica */ /* cameras. */ void print_konica_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) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 1: konica1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in Konica makernotes. */ void konica1_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) { unsigned long value_offset; unsigned long count; char *nameoftag; char *fulldirname = NULL; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0e00: /* PrintIM (Epson Print Image matching) */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) { chpr += printf("@%lu:%lu",value_offset,count); chpr = newline(chpr); } } process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Konica-specific tagnames for makernotes. */ /* The tagname routine is the first place in the code path which */ /* requires knowledge of the note version. If the version is not */ /* given in the model table (e.g. the model is unknown), then switch */ /* code in find_maker_scheme() should have set it. This routine */ /* repeats the check for non-zero noteversion and is prepared to set */ /* the noteversion first time through, but should never need to do */ /* so. Noteversion should always be non-zero; it should be set to -1 */ /* if generic processing is required. */ char * maker_konica_tagname(unsigned short tag,int model) { char *tagname = (char *)0; /* If no model-specific tag is found, use a "generic" tag */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } exifprobe-2.0.1+git20170416-3c2b76/mrw.c0000644000000000000000000007522713074742216015477 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: mrw.c,v 1.11 2005/07/24 20:27:36 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Minolta MRW routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* The information coded here is derived from information reported */ /* by Dalibor Jelinek at: */ /* http://www.dalibor.cz/minolta/raw_file_format.htm */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include #include "defs.h" #include "datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "mrw.h" /* Print the (rather simple) MRW header information. */ int print_mrw_header(struct fileheader *fileheader,unsigned long section_id) { struct mrw_header mrwheader; int status = -1; int chpr = 0; if(Print_options & section_id) { if(fileheader && (fileheader->probe_magic == PROBE_MRWMAGIC)) { mrwheader = fileheader->mrw_header; if(mrwheader.mrw_magic == PROBE_MRWMAGIC) { chpr += printf("MRW magic %#lx, length %u, offset to image data %lu", mrwheader.mrw_magic,8,mrwheader.mrw_dataoffset + 8); chpr = newline(chpr); status = 0; } else chpr += printf(" MRW HEADER MAGIC BAD"); } else chpr += printf(" NOT AN MRW HEADER"); } chpr = newline(chpr); return(status); } /* Process a Minolta (now Konica Minolta) MRW file, starting right */ /* after the MRM header. */ unsigned long process_mrw(FILE *inptr,unsigned long offset,unsigned long data_offset, unsigned long data_length,struct image_summary *summary_entry, char *parent_name,int indent) { char *blockname; char *fulldirname = CNULL; struct fileheader *header; unsigned long blocklength,blockid; unsigned long ifd_offset; unsigned long max_offset = 0UL; int chpr = 0; int status = 0; if(inptr && data_offset) { if((summary_entry == NULL) || summary_entry->entry_lock) summary_entry = new_summary_entry(summary_entry,0,IMGFMT_MRW); if(summary_entry) { /* This isn't strictly necessary, because we're going to */ /* do it again at the end, but allows the TIFF processor */ /* to avoid changing this stuff if it notices they're */ /* already set. */ if(summary_entry->length <= 0) summary_entry->length = data_length; if(summary_entry->offset <= 0) summary_entry->offset = data_offset; summary_entry->imageformat = IMGFMT_MRW; summary_entry->imagesubformat = IMGSUBFMT_CFA; /* Don't lock it here; the TIFF processor should use it */ /* (and lock it) */ } chpr = newline(chpr); while(offset < data_offset) { blockid = read_ulong(inptr,TIFF_MOTOROLA,offset); blockname = read_string(inptr,offset+1,3); blocklength = read_ulong(inptr,TIFF_MOTOROLA,HERE); print_tag_address(SECTION,offset,indent,"@"); if(blockid != MRM_PAD) offset += 8; if((PRINT_SECTION)) { chpr += printf("{%s} (%#lx) length %lu starting at offset %#lx/%lu",blockname, blockid,blocklength,offset,offset); chpr = newline(chpr); } if(Debug) { chpr = newline(chpr); hexdump(inptr,offset,48,48,16,0,0); chpr = newline(1); } switch(blockid) { case MRM_PRD: max_offset = process_prd(inptr,offset,blocklength,summary_entry,indent); offset += blocklength; break; case MRM_TTW: header = read_imageheader(inptr,offset); if(header && (header->probe_magic == PROBE_TIFFMAGIC)) { ifd_offset = read_ulong(inptr,header->file_marker,HERE); if(PRINT_SECTION) { print_tag_address(SECTION,offset,indent + 4,"@"); status = print_header(header,SECTION); chpr += printf(" ifd offset = %#lx/%lu)",ifd_offset,ifd_offset); if(offset) { chpr += printf(" (+ %lu = %#lx/%lu)",offset,offset + ifd_offset, offset + ifd_offset); } chpr = newline(chpr); } fulldirname = splice(parent_name,".",blockname); max_offset = process_tiff_ifd(inptr,header->file_marker, ifd_offset,offset,offset + blocklength,summary_entry, fulldirname,TIFF_IFD,0,-1,indent + 4); if(max_offset > 0L) status = 0; max_offset = offset + blocklength; fflush(stdout); if(fulldirname) free(fulldirname); fulldirname = CNULL; } else chpr += printf(" NOT A TIFF HEADER"); offset += blocklength; break; case MRM_WBG: max_offset = process_wbg(inptr,offset,blocklength,summary_entry,indent); offset += blocklength; break; case MRM_RIF: max_offset = process_rif(inptr,offset,blocklength,summary_entry,indent); offset += blocklength; break; case MRM_PAD: offset += blocklength; max_offset = offset; break; default: offset += blocklength; max_offset = offset - 8; break; } chpr = newline(0); if((PRINT_SECTION)) { print_tag_address(SECTION,max_offset - 1,indent,"@"); chpr += printf("{/%s}",blockname ? blockname : "UNK"); } chpr = newline(chpr); } if((PRINT_SECTION)) { print_tag_address(SECTION,data_offset,indent,"@"); chpr += printf("MRW (CFA) data length %lu",data_length); chpr = newline(chpr); dumpsection(inptr,data_offset,data_length,indent + SMALLINDENT); print_tag_address(SECTION,data_offset + data_length - 1,indent,"@"); chpr += printf("End of MRW data"); } chpr = newline(chpr); /* Fix up any damage done by the TIFF IFD... */ /* This information supercedes anything the TIFF processor */ /* may have done...image processing software can trash the */ /* TIFF structure (and some do), but this is basic */ /* information from the MRW header. */ if(summary_entry) { summary_entry->length = data_length; summary_entry->offset = data_offset; summary_entry->imageformat = IMGFMT_MRW; summary_entry->imagesubformat = IMGSUBFMT_CFA; /* The TIFF processor should have locked it, but make */ /* sure */ summary_entry->entry_lock = lock_number(summary_entry); } } return(data_offset + data_length); } #define SHORTNAMEWIDTH 20 #define LONGNAMEWIDTH 24 unsigned long process_prd(FILE *inptr,unsigned long offset,unsigned long blocklength, struct image_summary *summary_entry,int indent) { unsigned short ccd_height,ccd_width; unsigned short image_height,image_width; unsigned short datasize,pixelsize,storage_method; unsigned short unknown1,unknown2,unknown3; char *version; int chpr = 0; blocklength += offset; chpr = newline(chpr); version = (char *)read_bytes(inptr,8UL,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"Version"); } if((PRINT_VALUE)) chpr += printf(" = %8.8s",version); chpr = newline(chpr); } offset += 8; ccd_height = read_ushort(inptr,TIFF_MOTOROLA,offset); ccd_width = read_ushort(inptr,TIFF_MOTOROLA,HERE); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"ccdWidth"); } if((PRINT_VALUE)) chpr += printf(" = %u",ccd_width); chpr = newline(chpr); print_tag_address(ENTRY,offset + 4,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"ccdHeight"); } if((PRINT_VALUE)) chpr += printf(" = %u",ccd_height); } else { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"CCDSize"); } if((PRINT_VALUE)) chpr += printf(" = %ux%u",ccd_width,ccd_height); } chpr = newline(chpr); } offset += 4; image_height = read_ushort(inptr,TIFF_MOTOROLA,offset); image_width = read_ushort(inptr,TIFF_MOTOROLA,HERE); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"ImageWidth"); } if((PRINT_VALUE)) chpr += printf(" = %u",image_width); chpr = newline(chpr); print_tag_address(ENTRY,offset + 4,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"ImageHeight"); } if((PRINT_VALUE)) chpr += printf(" = %u",image_height); } else { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"ImageSize"); } if((PRINT_VALUE)) chpr += printf(" = %ux%u",image_width,image_height); } chpr = newline(chpr); /* This is also in the TIFF IFD0 */ if(summary_entry) { summary_entry->pixel_width = image_width; summary_entry->pixel_height = image_height; } } offset += 4; datasize = read_ubyte(inptr,offset); if(summary_entry) { summary_entry->sample_size = datasize; summary_entry->spp = 1; } if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"DataSize"); } if((PRINT_VALUE)) chpr += printf(" = %u",datasize); chpr = newline(chpr); } ++offset; pixelsize = read_ubyte(inptr,offset); if(summary_entry) summary_entry->bps[0] = (int)pixelsize; if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"PixelSize"); } if((PRINT_VALUE)) chpr += printf(" = %u",pixelsize); chpr = newline(chpr); } ++offset; storage_method = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"StorageMethod"); } if((PRINT_VALUE)) chpr += printf(" = %#x/%u",storage_method,storage_method); chpr = newline(chpr); } ++offset; unknown1 = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"unknown1"); } if((PRINT_VALUE)) chpr += printf(" = %u",unknown1); chpr = newline(chpr); } ++offset; unknown2 = read_ushort(inptr,TIFF_MOTOROLA,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"unknown2"); } if((PRINT_VALUE)) chpr += printf(" = %u",unknown1); chpr = newline(chpr); } offset += 2; unknown3 = read_ushort(inptr,TIFF_MOTOROLA,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.PRD."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"unknown3"); } if((PRINT_VALUE)) chpr += printf(" = %u",unknown1); chpr = newline(chpr); } offset += 2; return(offset); } /* The White Balance blob. Weird stuff. */ unsigned long process_wbg(FILE *inptr,unsigned long offset,unsigned long blocklength, struct image_summary *summary_entry,int indent) { unsigned short wbr_denom,wbg1_denom,wbg2_denom,wbb_denom; unsigned short wbr_num,wbg1_num,wbg2_num,wbb_num; double wbr,wbg1,wbg2,wbb; int chpr = 0; blocklength += offset; chpr = newline(chpr); wbr_denom = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"WbrDenominator"); } if((PRINT_VALUE)) chpr += printf(" = %u",wbr_denom); switch(wbr_denom) { case 0: wbr_denom = 64; break; case 1: wbr_denom = 128; break; case 2: wbr_denom = 256; break; case 3: wbr_denom = 512; break; case 4: wbr_denom = 1024; break; default: break; } if((PRINT_VALUE)) chpr += printf(" = %u",wbr_denom); chpr = newline(chpr); } offset++; wbg1_denom = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"Wbg1Denominator"); } if((PRINT_VALUE)) chpr += printf(" = %u",wbg1_denom); switch(wbg1_denom) { case 0: wbg1_denom = 64; break; case 1: wbg1_denom = 128; break; case 2: wbg1_denom = 256; break; case 3: wbg1_denom = 512; break; case 4: wbg1_denom = 1024; break; default: break; } if((PRINT_VALUE)) chpr += printf(" = %u",wbg1_denom); chpr = newline(chpr); } offset++; wbg2_denom = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"Wbg2Denominator"); } if((PRINT_VALUE)) chpr += printf(" = %u",wbg2_denom); switch(wbg2_denom) { case 0: wbg2_denom = 64; break; case 1: wbg2_denom = 128; break; case 2: wbg2_denom = 256; break; case 3: wbg2_denom = 512; break; case 4: wbg2_denom = 1024; break; default: break; } if((PRINT_VALUE)) chpr += printf(" = %u",wbg2_denom); chpr = newline(chpr); } offset++; wbb_denom = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"WbbDenominator"); } if((PRINT_VALUE)) chpr += printf(" = %u",wbb_denom); switch(wbb_denom) { case 0: wbb_denom = 64; break; case 1: wbb_denom = 128; break; case 2: wbb_denom = 256; break; case 3: wbb_denom = 512; break; case 4: wbb_denom = 1024; break; default: break; } if((PRINT_VALUE)) chpr += printf(" = %u",wbb_denom); chpr = newline(chpr); } offset++; wbr_num = read_ushort(inptr,TIFF_MOTOROLA,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"WbrNumerator"); } if((PRINT_VALUE)) chpr += printf(" = %u",wbr_num); if((PRINT_SECTION)) { if(wbr_denom) { wbr = (double)wbr_num / (double)wbr_denom; chpr += printf(" => wbr = %.3f",wbr); } else chpr += printf(" => wbr = inf"); } else { chpr = newline(chpr); print_tag_address(ENTRY,HERE,indent + 4,"*"); if((PRINT_TAGINFO)) { /* pseudo-tag for result whitebalance */ if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"WbRed"); } if((PRINT_VALUE)) { if(wbr_denom) { wbr = (double)wbr_num / (double)wbr_denom; chpr += printf(" = %.3f",wbr); } else chpr += printf(" = inf"); } } chpr = newline(chpr); } offset += 2; wbg1_num = read_ushort(inptr,TIFF_MOTOROLA,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"Wbg1Numerator"); } if((PRINT_VALUE)) chpr += printf(" = %u",wbg1_num); if((PRINT_SECTION)) { if(wbg1_denom) { wbg1 = (double)wbg1_num / (double)wbg1_denom; chpr += printf(" => wbg1 = %.3f",wbg1); } else chpr += printf(" => wbg1 = inf"); } else { chpr = newline(chpr); print_tag_address(ENTRY,HERE,indent + 4,"*"); if((PRINT_TAGINFO)) { /* pseudo-tag for result whitebalance */ if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"WbGreen1"); } if((PRINT_VALUE)) { if(wbg1_denom) { wbg1 = (double)wbg1_num / (double)wbg1_denom; chpr += printf(" = %.3f",wbg1); } else chpr += printf(" => wbg1 = inf"); } } chpr = newline(chpr); } offset += 2; wbg2_num = read_ushort(inptr,TIFF_MOTOROLA,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"Wbg2Numerator"); } if((PRINT_VALUE)) chpr += printf(" = %u",wbg2_num); if((PRINT_SECTION)) { if(wbg2_denom) { wbg2 = (double)wbg2_num / (double)wbg2_denom; chpr += printf(" => wbg2 = %.3f",wbg2); } else chpr += printf(" => wbg2 = inf"); } else { chpr = newline(chpr); print_tag_address(ENTRY,HERE,indent + 4,"*"); if((PRINT_TAGINFO)) { /* pseudo-tag for result whitebalance */ if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"WbGreen2"); } if((PRINT_VALUE)) { if(wbg2_denom) { wbg2 = (double)wbg2_num / (double)wbg2_denom; chpr += printf(" = %.3f",wbg2); } else chpr += printf(" => wbg2 = inf"); } } chpr = newline(chpr); } offset += 2; wbb_num = read_ushort(inptr,TIFF_MOTOROLA,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"WbbNumerator"); } if((PRINT_VALUE)) chpr += printf(" = %u",wbb_num); if((PRINT_SECTION)) { if(wbb_denom) { wbb = (double)wbb_num / (double)wbb_denom; chpr += printf(" => wbb = %.3f",wbb); } else chpr += printf(" => wbb = inf"); } else { chpr = newline(chpr); print_tag_address(ENTRY,HERE,indent + 4,"*"); if((PRINT_TAGINFO)) { /* pseudo-tag for result whitebalance */ if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.WBG."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"WbBlue"); } if((PRINT_VALUE)) { if(wbb_denom) { wbb = (double)wbb_num / (double)wbb_denom; chpr += printf(" = %.3f",wbb); } else chpr += printf(" => wbb = inf"); } } chpr = newline(chpr); } offset += 2; return(offset); } /* Requested Image Format */ unsigned long process_rif(FILE *inptr,unsigned long offset,unsigned long blocklength, struct image_summary *summary_entry,int indent) { unsigned long end_offset; unsigned short saturation,contrast; unsigned short sharpness,white_balance; unsigned short subject_program,iso; unsigned short color_mode,color_filter,bw_filter; unsigned short unknown; double fvalue; int chpr = 0; end_offset = offset + blocklength; chpr = newline(chpr); unknown = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.RIF."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"unknown"); } if((PRINT_VALUE)) chpr += printf(" = %u",unknown); chpr = newline(chpr); } ++offset; saturation = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.RIF."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"Saturation"); } if((PRINT_VALUE)) chpr += printf(" = %u",saturation); chpr = newline(chpr); } ++offset; contrast = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.RIF."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"Contrast"); } if((PRINT_VALUE)) chpr += printf(" = %u",contrast); chpr = newline(chpr); } ++offset; sharpness = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.RIF."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"Sharpness"); } if((PRINT_VALUE)) chpr += printf(" = %u",sharpness); chpr = newline(chpr); } ++offset; white_balance = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.RIF."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"WhiteBalance"); } if((PRINT_VALUE)) chpr += printf(" = %u/%#x",white_balance,white_balance); chpr = newline(chpr); } ++offset; subject_program = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.RIF."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"SubjectProgram"); } if((PRINT_VALUE)) chpr += printf(" = %u",subject_program); chpr = newline(chpr); } ++offset; iso = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.RIF."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"CCDSensitivity"); } if((PRINT_VALUE)) { if(PRINT_RAW_VALUES) chpr += printf(" = %u",iso); fvalue = ((double)iso/8.0) - 1.0; chpr += printf(" = %.3g APEX",fvalue); fvalue = pow(2.0,fvalue) * 3.125; chpr += printf(" = %.3g ISO",fvalue); } chpr = newline(chpr); } ++offset; color_mode = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.RIF."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"ColorMode"); } if((PRINT_VALUE)) chpr += printf(" = %u/%#x",color_mode,color_mode); chpr = newline(chpr); } ++offset; color_filter = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.RIF."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"ColorFilter"); } if((PRINT_VALUE)) chpr += printf(" = %u/%#x",color_filter,color_filter); chpr = newline(chpr); } ++offset; bw_filter = read_ubyte(inptr,offset); if((PRINT_ENTRY)) { print_tag_address(ENTRY,offset,indent + 4,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s","MRW.RIF."); chpr += printf("%-*.*s",SHORTNAMEWIDTH,SHORTNAMEWIDTH,"BWFilter"); } if((PRINT_VALUE)) chpr += printf(" = %u/%#x",bw_filter,bw_filter); chpr = newline(chpr); } ++offset; /* Remaining values are unknown */ return(end_offset); } exifprobe-2.0.1+git20170416-3c2b76/maker_epson.c0000644000000000000000000005152013074742216017163 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_epson.c,v 1.22 2005/07/24 22:56:26 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Epson camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* This is currently a near-duplicate of the Olympus, based upon the */ /* similarity of tag numbers, the appearance of sample images taken */ /* from the Web, and reports that some Olympus, Epson, Minolta and */ /* Sanyo models use similar firmware. */ /* The "photopc" site at soucrceforge provides some insight: */ /* http://photopc.sourceforge.net/cameras.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id epson_model_id[]; /* Find the identifying number assigned to known Epson camera models. */ /* This number is used to dispatch appropriate print and interpret */ /* routines approopriate to the current image. */ int epson_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &epson_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine for direct IFD values in Epson */ /* MakerNotes, based upon model */ void print_epson_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 1 : print_epson1_makervalue(entry_ptr,make,model,prefix); epson1_interpret_value(entry_ptr); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Epson cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_epson1_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values in MakerNotes */ /* from Epson cameras. */ void print_epson_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) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 1 : epson1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); epson1_interpret_offset_makervalue(inptr,byteorder, entry_ptr,fileoffset_base); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix, indent,make,model,at_offset); break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in epson makernotes. */ void epson1_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) { unsigned long value_offset,count; unsigned long dumplength; unsigned long max_offset = 0; unsigned short marker; char *nameoftag; char *fulldirname = NULL; int status = 0; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x020a: /* MakerNote version of UserComment */ if(at_offset) { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,23," = ",make,model); } if((PRINT_VALUE)) { if((PRINT_OFFSET) && !at_offset) chpr += chpr += printf(" = "); print_user_comment(inptr,entry_ptr->count,value_offset,byteorder); } break; case 0x0209: /* CameraId */ if(at_offset) { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,23," = ",make,model); } if((PRINT_VALUE)) { if((PRINT_OFFSET) && !at_offset) chpr += chpr += printf(" = "); print_ascii(inptr,entry_ptr->count,value_offset); } break; case 0x0301: /* This is an odd one. Overwrite the values for */ /* offset and length, then fall through and display */ /* the thumbnail. */ /* Why didn't they just do this as an UNDEFINED */ /* section? */ value_offset = read_ulong(inptr,byteorder,value_offset); count = read_ulong(inptr,byteorder,HERE); if(at_offset && (PRINT_SECTION)) { print_tag_address(SECTION,fileoffset_base + entry_ptr->value, indent,prefix); print_makertagid(entry_ptr,23," = ",make,model); if((PRINT_VALUE)) chpr += printf("@%lu:%lu",value_offset,count); chpr = newline(chpr); } else if((LIST_MODE) && !at_offset) { if((PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",fileoffset_base + entry_ptr->value); } chpr = newline(chpr); /* In list mode, when SECTIONS are not printed, */ /* provide these items as "pseudotags". */ print_tag_address(ENTRY,value_offset,indent,prefix); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fulldirname); chpr += printf("%-*.*s",9,9,"Offset"); } if((PRINT_VALUE)) { if((PRINT_OFFSET)) { if(PRINT_BOTH_OFFSET) chpr += printf(" = @%#lx=%lu",value_offset,value_offset); else if(PRINT_HEX_OFFSET) chpr += printf(" = @%#lx",value_offset); else if(PRINT_DEC_OFFSET) chpr += printf(" = @%lu",value_offset); } else chpr += printf(" = @%lu",value_offset); } chpr = newline(chpr); print_tag_address(ENTRY,value_offset,indent,prefix); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fulldirname); chpr += printf("%-*.*s",9,9,"Length"); } if((PRINT_VALUE)) chpr += printf(" = %lu",count); } /* fall through and process the thumbnail */ case 0x0100: /* Jpeg Thumbnail */ if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix); chpr += printf("# Start of JPEG Thumbnail from MakerNote"); chpr += printf(" length %ld",count); } else if(!at_offset && (PRINT_VALUE) && (entry_ptr->tag == 0x0100)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,entry_ptr->count); else chpr = printf("length %lu", entry_ptr->count); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); max_offset = process_jpeg_segments(inptr,value_offset,marker, count,summary_entry,fulldirname, prefix,indent+SMALLINDENT); if(at_offset) { if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1, indent,prefix); chpr += printf("# End of JPEG Thumbnail from MakerNote"); if((PRINT_ENTRY) && !(PRINT_VALUE)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_IFD; summary_entry->subfiletype = THUMBNAIL_TYPE; } } /* make certain we're at the end */ clearerr(inptr); fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0e00: /* PrintIM (Epson Print Image matching) */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) { chpr += printf("@%lu:%lu",value_offset,count); chpr = newline(chpr); } } process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent); break; case 0x0f00: /* Data */ if(at_offset && (PRINT_ENTRY)) { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,23," : ",make,model); chpr += printf("length %lu", count); if(Max_undefined == 0) { if(chpr) printred(" (not dumped, use -U)"); } else { if((Max_undefined == DUMPALL) || (Max_undefined > count)) dumplength = count; else dumplength = Max_undefined; chpr = newline(chpr); hexdump(inptr,value_offset,count,dumplength,12, indent,SUBINDENT); chpr = newline(1); } } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,entry_ptr->count); else chpr = printf("length %lu", entry_ptr->count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } /* make certain we're at the end */ fseek(inptr,value_offset + count,SEEK_SET); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Epson-specific tagnames for makernotes. */ char * maker_epson_tagname(unsigned short tag,int model) { char *tagname = CNULL; int noteversion = 0; /* Should have to do this only once, and only for unrecognized */ /* models. If the model is recognized (or the user has forced a */ /* noteversion) noteversion will already be set. */ if((noteversion = getnoteversion()) == 0) { noteversion = 1; setnoteversion(1); } switch(noteversion) { case 1 : tagname = maker_epson1_tagname(tag,model); break; default: break; } if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; case 0x0100: tagname = "JpegThumbnail"; break; default: break; } } return(tagname); } char * maker_epson1_tagname(unsigned short tag,int model) { char *tagname = CNULL; /* These are the Olympus tags; try them ###%%% ??? */ /* Update: the SoftwareRelease tag on Olympus is 0x0207; here it */ /* is 0x020d. One Epson model sports a hidden thumbnail (0x0301) */ switch(tag) { case 0x0200: tagname = "SpecialMode"; break; case 0x0201: tagname = "CompressionMode"; break; case 0x0202: tagname = "Macro"; break; case 0x0204: tagname = "DigitalZoom"; break; case 0x0208: tagname = "PictureInfo"; break; case 0x0209: tagname = "CameraID"; break; case 0x020a: tagname = "MakerUserComment"; break; case 0x020b: tagname = "ImageWidth"; break; case 0x020c: tagname = "ImageHeight"; break; case 0x020d: tagname = "SoftwareRelease"; break; case 0x0301: tagname = "JpegThumbnailData"; break; case 0x0e00: tagname = "PrintIM"; break; case 0x0f00: tagname = "Data"; break; default: break; } setnotetagset(1); return(tagname); } /* This arbitrarily assumes that the Epsons use firmware similar to */ /* that of the Olympus. I have seen no information on the web from */ /* Epson owners who have decoded notes from their cameras. The */ /* following seems to be correct based upon Epson PhotoPC 3000Z */ /* images downloaded from "dpreview" and "imaging resources". */ void epson1_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0201: /* Compression Mode */ print_startvalue(); /* 'Quality' is a mix of this and image size. */ /* Interestingly, 'HyPict' (2544x1904) interpolated */ /* images are marked '34' (same as uncompressed 'tiff') */ /* but are in JPEG format with CompressedBitsPerPixel=1. */ /* The value '33' is used by Olympus cameras, which */ /* appear to use similar software. Of course, the Minolta */ /* F100 looks a lot like this too, but uses '4' for */ /* uncompressed. */ switch(entry_ptr->value) { case 1: chpr += printf("SQ"); break; case 2: chpr += printf("HQ"); break; case 3: chpr += printf("SHQ"); break; case 33: chpr += printf("not compressed"); break; case 34: chpr += printf("not compressed"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0202: /* Macro */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Macro"); break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } /* Report the "meaning" of tag values found at offsets in an Epson */ /* MakerNote IFD entry (not at an offset). */ void epson1_interpret_offset_makervalue(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base) { unsigned long offset,value; int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { offset = entry_ptr->value + fileoffset_base; switch(entry_ptr->tag) { case 0x0200: /* SpecialMode */ value = read_ulong(inptr,byteorder,offset); print_startvalue(); /* Don't know what the last 2 values might mean for */ /* "normal" or "fast". */ switch(value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Unkown"); break; case 2: chpr += printf("Fast"); break; case 3: chpr += printf("Panorama,"); value = read_ulong(inptr,byteorder,HERE); chpr += printf("#%lu,",value); value = read_ulong(inptr,byteorder,HERE); switch(value) { case 1: chpr += printf(" Left to Right"); break; case 2: chpr += printf(" Right to Left"); break; case 3: chpr += printf(" Bottom to Top"); break; case 4: chpr += printf(" Top to Bottom"); break; default: printred(" undefined"); break; } break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } exifprobe-2.0.1+git20170416-3c2b76/.gitignore0000644000000000000000000000004413074742216016477 0ustar rootroot*.o byteorder.h comptime.c exifprobeexifprobe-2.0.1+git20170416-3c2b76/DESCRIPTION0000644000000000000000000000302613074742216016220 0ustar rootrootExifprobe reads image files produced by digital cameras (including several so-called "raw" file formats) and reports the structure of the files and the auxilliary data and metadata contained within them. In addition to TIFF, JPEG, and EXIF, the program understands several formats which may contain "raw" camera data, including MRW, CIFF/CRW, JP2/JPEG2000, RAF, and X3F, as well as most most TIFF-derived "raw" formats, including DNG, ORF, CR2, NEF, K25/KDC/DCR, and PEF. MakerNote sections found in Exif IFDs are reported and expanded if the note is in a semblance of TIFF IFD format. Information which has been published on the internet is used to interpret notes where possible. The default output attempts to describe the structure of the file, showing location, size and content of auxilliary data, metadata, and image sections. Multiple images contained in a single file are noted (and JPEG sub-image markers examined for useful data). A summary of images found is printed at the end of output for each file. Many options are provided for detail control of output format. For convenience, two pre-set formats (in addition to the default 'structural' format) are provided: a "report" format (which shows "structure" of TIFF ifds, but with values printed inline), and a "list" format which eliminates structural elements and presents data in a human (or script) readable format for possible use in gallery applications. exifprobe-2.0.1+git20170416-3c2b76/interpret.c0000644000000000000000000006172513074742216016704 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: interpret.c,v 1.18 2005/07/24 21:26:04 alex Exp $"; #endif #include #include "defs.h" #include "datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "ciff.h" /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* This file contains the functions which interpret and print */ /* "meaningful" descriptions for values found in TIFF and EXIF ifds. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ static void print_aperture(FILE *,unsigned short,unsigned long); static void print_brightness(FILE *,unsigned short,unsigned long); static void print_shutterspeed(FILE *,unsigned short,unsigned long); static void print_capturetype(unsigned long); static void print_colorspace(unsigned long); static void print_componentsconfig(unsigned long); static void print_compression(unsigned long); static void print_contrast(unsigned long); static void print_custom(unsigned long); static void print_epfpresunit(unsigned long); static void print_epcfapattern(unsigned long,unsigned long); static void print_offset_epcfapattern(FILE *,struct ifd_entry *, unsigned long); static void print_exposuremode(unsigned long); static void print_exposureprogram(unsigned long); static void print_filesource(unsigned long source); static void print_flash(unsigned long flash); static void print_gaincontrol(unsigned long); static void print_jpegproc(unsigned long); static void print_lightsource(unsigned long); static void print_meteringmode(unsigned long); static void print_newsubfiletype(unsigned long); static void print_oldsubfiletype(unsigned long); static void print_orientation(unsigned long); static void print_photometric(unsigned long,int); static void print_planarconfig(unsigned long); static void print_resunit(unsigned long); static void print_saturation(unsigned long); static void print_scenetype(unsigned long type); static void print_sensingmethod(unsigned long); static void print_sharpness(unsigned long); static void print_subjectdistancerange(unsigned long); static void print_whitebalance(unsigned long); static void print_ycbcrpositioning(unsigned long); static void print_35mmfocallength(); void interpret_value(struct ifd_entry *entry_ptr,struct image_summary *summary_entry) { switch(entry_ptr->tag) { case TIFFTAG_Compression: print_compression(entry_ptr->value); break; case TIFFTAG_PhotometricInterpretation: if (summary_entry) { print_photometric(entry_ptr->value,summary_entry->fileformat); } break; case TIFFTAG_Orientation: print_orientation(entry_ptr->value); break; case TIFFTAG_ResolutionUnit: case EXIFTAG_FocalPlaneResolutionUnit: print_resunit(entry_ptr->value); break; case TIFFEPTAG_FocalPlaneResolutionUnit: print_epfpresunit(entry_ptr->value); break; case EXIFTAG_ColorSpace: print_colorspace(entry_ptr->value); break; case EXIFTAG_MeteringMode: print_meteringmode(entry_ptr->value); break; case TIFFEPTAG_CFAPattern: print_epcfapattern(entry_ptr->value,entry_ptr->count); break; case TIFFEPTAG_SensingMethod: case EXIFTAG_SensingMethod: print_sensingmethod(entry_ptr->value); break; case EXIFTAG_ExposureProgram: print_exposureprogram(entry_ptr->value); break; case EXIFTAG_ComponentsConfiguration: print_componentsconfig(entry_ptr->value); break; case TIFFTAG_OldSubFileType: print_oldsubfiletype(entry_ptr->value); break; case TIFFTAG_NewSubFileType: print_newsubfiletype(entry_ptr->value); break; case TIFFTAG_PlanarConfiguration: print_planarconfig(entry_ptr->value); break; case TIFFTAG_JpegProc: print_jpegproc(entry_ptr->value); break; case TIFFTAG_YcbCrPositioning: print_ycbcrpositioning(entry_ptr->value); break; case EXIFTAG_LightSource: print_lightsource(entry_ptr->value); break; case EXIFTAG_Flash: print_flash(entry_ptr->value); break; case EXIFTAG_FileSource: print_filesource(entry_ptr->value); break; case EXIFTAG_SceneType: print_scenetype(entry_ptr->value); break; case EXIFTAG_ExifCustomRendered: print_custom(entry_ptr->value); break; case EXIFTAG_ExifExposureMode: print_exposuremode(entry_ptr->value); break; case EXIFTAG_ExifWhiteBalance: print_whitebalance(entry_ptr->value); break; case EXIFTAG_ExifDigitalZoomRatio: /* Nothing to do */ break; case EXIFTAG_ExifFocalLengthIn35mmFilm: print_35mmfocallength(); break; case EXIFTAG_ExifSceneCaptureType: print_capturetype(entry_ptr->value); break; case EXIFTAG_ExifGainControl: print_gaincontrol(entry_ptr->value); break; case EXIFTAG_ExifContrast: print_contrast(entry_ptr->value); break; case EXIFTAG_ExifSaturation: print_saturation(entry_ptr->value); break; case EXIFTAG_ExifSharpness: print_sharpness(entry_ptr->value); break; case EXIFTAG_ExifSubjectDistanceRange: print_subjectdistancerange(entry_ptr->value); break; case EXIFTAG_ExifImageUniqueId: /* Nothing to do */ break; default: break; } } void interpret_offset_value(FILE *inptr,struct ifd_entry *entry_ptr,unsigned short byteorder, unsigned long fileoffset_base) { unsigned long offset; int chpr = 0; switch(entry_ptr->tag) { case TIFFEPTAG_CFAPattern: print_offset_epcfapattern(inptr,entry_ptr,fileoffset_base); break; case EXIFTAG_ExposureTime: setcharsprinted(printf(" sec")); break; case EXIFTAG_ShutterSpeedValue: chpr += printf(" APEX"); offset = entry_ptr->value + fileoffset_base; print_shutterspeed(inptr,byteorder,offset); break; case EXIFTAG_ApertureValue: case EXIFTAG_MaxApertureValue: case EXIFTAG_FNumber: chpr += printf(" APEX"); offset = entry_ptr->value + fileoffset_base; print_aperture(inptr,byteorder,offset); break; case EXIFTAG_BrightnessValue: chpr += printf(" APEX"); offset = entry_ptr->value + fileoffset_base; print_brightness(inptr,byteorder,offset); break; case EXIFTAG_FocalLength: chpr += printf(" mm"); break; case EXIFTAG_SubjectDistance: chpr += printf(" meters"); break; case EXIFTAG_ExposureBiasValue: chpr += printf(" APEX"); break; } setcharsprinted(chpr); } void print_compression(unsigned long compvalue) { char *compstr; int chpr = 0; if((compstr = tiff_compression_string(compvalue))) { print_startvalue(); chpr += printf("%s",compstr); print_endvalue(); } setcharsprinted(chpr); } void print_photometric(unsigned long metric,int fileformat) { int chpr = 0; switch(fileformat) { case FILEFMT_ORF1: case FILEFMT_ORF2: print_startvalue(); switch(metric) { case 1: chpr += printf("CFA 16 bit"); break; case 2: chpr += printf("CFA 12 bit"); break; default: chpr += printf("undefined"); break; } print_endvalue(); break; default: print_startvalue(); switch(metric) { case 0: chpr += printf("MINISWHITE"); break; case 1: chpr += printf("MINISBLACK"); break; case 2: chpr += printf("RGB"); break; case 3: chpr += printf("Palette"); break; case 4: chpr += printf("Transparency Mask"); break; case 5: chpr += printf("Separated"); break; case 6: chpr += printf("YCbCr"); break; case 8: chpr += printf("CIELAB"); break; case 10: chpr += printf("ITULAB"); break; case 32803: chpr += printf("CFA"); break; /* TIFFEP, DNG */ case 32844: chpr += printf("CIE Log2(L)"); break; case 32845: chpr += printf("CIE Log2(L) (u',v')"); break; case 34892: chpr += printf("LinearRaw"); break; default: chpr += printf("undefined"); break; } print_endvalue(); break; } setcharsprinted(chpr); } void print_orientation(unsigned long value) { int chpr = 0; print_startvalue(); switch(value) { case 1: chpr += printf("0,0 is top left"); break; case 2: chpr += printf("0,0 is top right"); break; case 3: chpr += printf("0,0 is bottom right"); break; case 4: chpr += printf("0,0 is bottom left"); break; case 5: chpr += printf("0,0 is left top"); break; case 6: chpr += printf("0,0 is right top"); break; case 7: chpr += printf("0,0 is right bottom"); break; case 8: chpr += printf("0,0 is left bottom"); break; default: chpr += printf("undefined"); break; } print_endvalue(); setcharsprinted(chpr); } void print_resunit(unsigned long unit) { int chpr = 0; print_startvalue(); switch(unit) { case 1: chpr += printf("no units"); break; case 2: chpr += printf("pixels per inch"); break; case 3: chpr += printf("pixels per cm"); break; default: chpr += printf("undefined"); break; } print_endvalue(); setcharsprinted(chpr); } void print_epfpresunit(unsigned long unit) { int chpr = 0; print_startvalue(); switch(unit) { case 1: chpr += printf("no units"); break; case 2: chpr += printf("per meter"); break; case 3: chpr += printf("per cm"); break; case 4: chpr += printf("per mm"); break; case 5: chpr += printf("per um"); break; default: chpr += printf("undefined"); break; } print_endvalue(); setcharsprinted(chpr); } void print_epcfapattern(unsigned long value,unsigned long count) { unsigned char *p; int i; int chpr = 0; p = (unsigned char *)&value; print_startvalue(); for(i = 0; i < count; ++i) { if(i) { putchar(','); ++chpr; } putcolorchar((unsigned short)*p++ & 0xff); } print_endvalue(); setcharsprinted(chpr); } void print_offset_epcfapattern(FILE *inptr,struct ifd_entry *entry_ptr, unsigned long fileoffset_base) { unsigned long offset; unsigned short p; int i; int chpr = 0; if(inptr) { offset = entry_ptr->value + fileoffset_base; print_startvalue(); for(i = 0; i < entry_ptr->count; ++i) { p = read_ubyte(inptr,offset++); if(i) { putchar(','); ++chpr; } putcolorchar(p & 0xff); } print_endvalue(); } setcharsprinted(chpr); } void print_colorspace(unsigned long space) { int chpr = 0; print_startvalue(); if(space == 1) chpr += printf("sRGB"); else if(space == 0xffff) chpr += printf("uncalibrated"); else chpr += printf("reserved"); print_endvalue(); setcharsprinted(chpr); } void print_meteringmode(unsigned long mode) { int chpr = 0; print_startvalue(); switch(mode) { case 0: chpr += printf("unknown"); break; case 1: chpr += printf("Average"); break; case 2: chpr += printf("Center Weighted Average"); break; case 3: chpr += printf("Spot"); break; case 4: chpr += printf("Multi Spot"); break; case 5: chpr += printf("Pattern"); break; case 6: chpr += printf("Partial"); break; default: if(mode < 255) chpr += printf("reserved"); else chpr += printf("other"); break; } print_endvalue(); setcharsprinted(chpr); } void print_sensingmethod(unsigned long method) { int chpr = 0; print_startvalue(); switch(method) { case 0: chpr += printf("Not defined"); break; case 1: chpr += printf("Monochrome area sensor"); break; case 2: chpr += printf("One-chip color area sensor"); break; case 3: chpr += printf("Two-chip color area sensor"); break; case 4: chpr += printf("Three-chip color area sensor"); break; case 5: chpr += printf("Color sequential area sensor"); break; case 7: chpr += printf("Trilinear sensor"); break; case 8: chpr += printf("Color sequential linear sensor"); break; default: chpr += printf("reserved"); break; } print_endvalue(); setcharsprinted(chpr); } void print_exposureprogram(unsigned long program) { int chpr = 0; print_startvalue(); switch(program) { case 0: chpr += printf("Not defined"); break; case 1: chpr += printf("Manual"); break; case 2: chpr += printf("Normal"); break; case 3: chpr += printf("Aperture Priority"); break; case 4: chpr += printf("Shutter Priority"); break; case 5: chpr += printf("Creative Program"); break; case 6: chpr += printf("Action Program"); break; case 7: chpr += printf("Portrait Mode"); break; case 8: chpr += printf("Landscape Mode"); break; default: if(program < 255) printf("reserved"); break; } print_endvalue(); setcharsprinted(chpr); } void print_componentsconfig(unsigned long components) { char *comp = (char *)&components; int i; int chpr = 0; print_startvalue(); for(i = 0; i < 4; ++i) { switch(*comp++) { case 1: putchar('Y'); break; case 2: putchar('C'); putchar('b'); break; case 3: putchar('C'); putchar('r'); break; case 4: putchar('R'); break; case 5: putchar('G'); break; case 6: putchar('B'); break; case 0: break; default: putchar('.'); break; } ++chpr; } print_endvalue(); setcharsprinted(chpr); } void print_newsubfiletype(unsigned long type) { int chpr = 0; print_startvalue(); switch(type) { case 0: chpr += printf("primary"); break; case 1: chpr += printf("thumbnail"); break; case 2: chpr += printf("page"); break; case 4: chpr += printf("mask"); break; default: chpr += printf("unknown"); break; } print_endvalue(); setcharsprinted(chpr); } void print_oldsubfiletype(unsigned long type) { int chpr = 0; print_startvalue(); if(type == 1) chpr += printf("primary"); else if(type == 2) chpr += printf("thumbnail"); else chpr += printf("unknown"); print_endvalue(); setcharsprinted(chpr); } void print_planarconfig(unsigned long config) { int chpr = 0; print_startvalue(); if(config == 1) chpr += printf("chunky/contig"); else if(config == 2) chpr += printf("planar/separate"); else chpr += printf("unknown"); print_endvalue(); setcharsprinted(chpr); } void print_jpegproc(unsigned long process) { int chpr = 0; print_startvalue(); if(process == 1) chpr += printf("baseline"); else if(process == 14) chpr += printf("lossless"); else chpr += printf("unknown"); print_endvalue(); setcharsprinted(chpr); } void print_ycbcrpositioning(unsigned long position) { int chpr = 0; print_startvalue(); if(position == 1) chpr += printf("centered"); else if(position == 2) chpr += printf("co-sited"); else chpr += printf("unknown"); print_endvalue(); setcharsprinted(chpr); } void print_lightsource(unsigned long source) { int chpr = 0; print_startvalue(); switch(source) { case 0: chpr += printf("unknown"); break; case 1: chpr += printf("Daylight"); break; case 2: chpr += printf("Fluorescent"); break; case 3: chpr += printf("Tungsten"); break; case 4: chpr += printf("Flash"); break; case 9: chpr += printf("Fine weather"); break; case 10: chpr += printf("Cloudy weather"); break; case 11: chpr += printf("Shade"); break; case 12: chpr += printf("Daylight fluorescent"); break; case 13: chpr += printf("Day white fluorescent"); break; case 14: chpr += printf("Cool white fluorescent"); break; case 15: chpr += printf("Fluorescent"); break; case 17: chpr += printf("Standard light A"); break; case 18: chpr += printf("Standard light B"); break; case 19: chpr += printf("Standard light C"); break; case 20: chpr += printf("D65"); break; case 21: chpr += printf("D55"); break; case 22: chpr += printf("D75"); break; case 23: chpr += printf("D50"); break; case 24: chpr += printf("ISO studio tungsten"); break; case 25: chpr += printf("Other light source"); break; default: chpr += printf("reserved"); break; } print_endvalue(); setcharsprinted(chpr); } void print_flash(unsigned long flash) { unsigned long bits; int chpr = 0; print_startvalue(); bits = flash & 0x1; if(bits != 0) chpr += printf("flash fired"); else chpr += printf("no flash"); /* there will be more */ bits = (flash & 0x6) >> 1; switch(bits) /* return detection */ { case 2: chpr += printf(" - return not detected"); break; case 3: chpr += printf(" - return detected"); break; default: break; } bits = (flash & 0x18) >> 3; /* flash mode */ switch(bits) { case 1: chpr += printf(" - compulsory"); break; case 2: chpr += printf(" - suppressed"); break; case 3: chpr += printf(" - auto"); break; default: break; } bits = (flash & 0x20) >> 5; /* flash function */ if(bits != 0) chpr += printf(" - no flash function present"); bits = (flash & 0x40) >> 6; /* red-eye */ if(bits != 0) chpr += printf(" - no red-eye function present"); print_endvalue(); setcharsprinted(chpr); } void print_filesource(unsigned long source) { int chpr = 0; print_startvalue(); switch(source) { case 0: chpr += printf("not specified"); break; case 1: chpr += printf("scanner - transparent"); break; case 2: chpr += printf("scanner - reflex"); break; case 3: chpr += printf("DSC"); break; default: chpr += printf("undefined"); } print_endvalue(); setcharsprinted(chpr); } void print_scenetype(unsigned long type) { int chpr = 0; print_startvalue(); if(type == 1) chpr += printf("direct photo"); else chpr += printf("not direct photo"); print_endvalue(); setcharsprinted(chpr); } void print_custom(unsigned long rendered) { int chpr = 0; print_startvalue(); if(rendered == 0) chpr += printf("Normal"); else if(rendered == 1) chpr += printf("Custom"); else chpr += printf("reserved"); print_endvalue(); setcharsprinted(chpr); } void print_exposuremode(unsigned long mode) { int chpr = 0; print_startvalue(); switch(mode) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Manual"); break; case 2: chpr += printf("Auto Bracket"); break; default: chpr += printf("???"); break; } print_endvalue(); setcharsprinted(chpr); } void print_whitebalance(unsigned long mode) { int chpr = 0; print_startvalue(); switch(mode) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Manual"); break; default: chpr += printf("???"); break; } print_endvalue(); setcharsprinted(chpr); } void print_35mmfocallength() { /* %%%### */ printf("mm"); setcharsprinted(2); } void print_capturetype(unsigned long type) { int chpr = 0; print_startvalue(); switch(type) { case 0: chpr += printf("Standard"); break; case 1: chpr += printf("Landscape"); break; case 2: chpr += printf("Portrait"); break; case 3: chpr += printf("Night Scene"); break; default: chpr += printf("reserved"); break; } print_endvalue(); setcharsprinted(chpr); } void print_gaincontrol(unsigned long type) { int chpr = 0; print_startvalue(); switch(type) { case 0: chpr += printf("None"); break; case 1: chpr += printf("Low gain up"); break; case 2: chpr += printf("High gain up"); break; case 3: chpr += printf("Low gain down"); break; case 4: chpr += printf("Hign gain down"); break; default: chpr += printf("reserved"); break; } print_endvalue(); setcharsprinted(chpr); } void print_contrast(unsigned long contrast) { int chpr = 0; print_startvalue(); switch(contrast) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Soft"); break; case 2: chpr += printf("Hard"); break; default: chpr += printf("???"); break; } print_endvalue(); setcharsprinted(chpr); } void print_saturation(unsigned long saturation) { int chpr = 0; print_startvalue(); switch(saturation) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Low"); break; case 2: chpr += printf("High"); break; default: chpr += printf("???"); break; } print_endvalue(); setcharsprinted(chpr); } void print_sharpness(unsigned long sharpness) { int chpr = 0; print_startvalue(); switch(sharpness) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Soft"); break; case 2: chpr += printf("Hard"); break; default: chpr += printf("???"); break; } print_endvalue(); setcharsprinted(chpr); } void print_subjectdistancerange(unsigned long range) { int chpr = 0; print_startvalue(); switch(range) { case 0: chpr += printf("???"); break; case 1: chpr += printf("Macro"); break; case 2: chpr += printf("Close view"); break; case 3: chpr += printf("Distant view"); break; default: chpr += printf("???"); break; } print_endvalue(); setcharsprinted(chpr); } #include void print_aperture(FILE *inptr,unsigned short byteorder,unsigned long offset) { double aperture_value,fnumber; unsigned long num,denom; int chpr = 0; num = read_ulong(inptr,byteorder,offset); denom = read_ulong(inptr,byteorder,HERE); aperture_value = (double)((double)num/(double)denom); fnumber = pow(2.0,aperture_value/2.0); print_startvalue(); chpr += printf("f%.1f",fnumber); print_endvalue(); setcharsprinted(chpr); } void print_shutterspeed(FILE *inptr,unsigned short byteorder,unsigned long offset) { double speed_value,exptime; long num,denom; int chpr = 0; num = read_ulong(inptr,byteorder,offset); denom = read_ulong(inptr,byteorder,HERE); speed_value = (double)((double)num/(double)denom); exptime = pow(2.0,-speed_value); print_startvalue(); chpr += printf("%g sec",exptime); print_endvalue(); setcharsprinted(chpr); } void print_brightness(FILE *inptr,unsigned short byteorder,unsigned long offset) { double brightness_value,brightness; long num,denom; int chpr = 0; num = read_ulong(inptr,byteorder,offset); denom = read_ulong(inptr,byteorder,HERE); brightness_value = (double)((double)num/(double)denom); brightness = pow(2.0,brightness_value); print_startvalue(); chpr += printf("%.3g foot lambert",brightness); print_endvalue(); setcharsprinted(chpr); } exifprobe-2.0.1+git20170416-3c2b76/exiftags.h0000644000000000000000000001235413074742216016501 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: exiftags.h,v 1.6 2005/06/26 23:49:34 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* All tags defined tags in EXIF spec not also defined in TIFF6 or */ /* JPEG specs */ #ifndef EXIFTAGS_INCLUDED #define EXIFTAGS_INCLUDED #define EXIFTAG_ExposureTime 0x829A /* 33434 */ #define EXIFTAG_FNumber 0x829D /* 33437 */ #define EXIFTAG_ExifIFDPointer 0x8769 /* 34665 */ #define EXIFTAG_ExposureProgram 0x8822 /* 34850 */ #define EXIFTAG_SpectralSensitivity 0x8824 /* 34862 */ #define EXIFTAG_GPSInfoIFDPointer 0x8825 /* 34853 */ #define EXIFTAG_ISOSpeedRatings 0x8827 /* 34855 */ #define EXIFTAG_OECF 0x8828 /* 34856 */ #define EXIFTAG_ExifVersion 0x9000 /* 36864 */ #define EXIFTAG_DateTimeOriginal 0x9003 /* 36867 */ #define EXIFTAG_DateTimeDigitized 0x9004 /* 36868 */ #define EXIFTAG_ComponentsConfiguration 0x9101 /* 37121 */ #define EXIFTAG_CompressedBitsPerPixel 0x9102 /* 37122 */ #define EXIFTAG_ShutterSpeedValue 0x9201 /* 37377 */ #define EXIFTAG_ApertureValue 0x9202 /* 37378 */ #define EXIFTAG_BrightnessValue 0x9203 /* 37379 */ #define EXIFTAG_ExposureBiasValue 0x9204 /* 37380 */ #define EXIFTAG_MaxApertureValue 0x9205 /* 37381 */ #define EXIFTAG_SubjectDistance 0x9206 /* 37382 */ #define EXIFTAG_MeteringMode 0x9207 /* 37383 */ #define EXIFTAG_LightSource 0x9208 /* 37384 */ #define EXIFTAG_Flash 0x9209 /* 37385 */ #define EXIFTAG_FocalLength 0x920A /* 37386 */ /* The next tag is called SubjectLocation in TIFF EP */ #define EXIFTAG_SubjectArea 0x9214 /* 37396 */ #define EXIFTAG_MakerNote 0x927C /* 37500 */ #define EXIFTAG_UserComment 0x9286 /* 37510 */ #define EXIFTAG_SubSecTime 0x9290 /* 37520 */ #define EXIFTAG_SubSecTimeOriginal 0x9291 /* 37521 */ #define EXIFTAG_SubSecTimeDigitized 0x9292 /* 37522 */ #define EXIFTAG_FlashPixVersion 0xA000 /* 40960 */ #define EXIFTAG_ColorSpace 0xA001 /* 40961 */ #define EXIFTAG_PixelXDimension 0xA002 /* 40962 */ #define EXIFTAG_PixelYDimension 0xA003 /* 40963 */ #define EXIFTAG_RelatedSoundFile 0xA004 /* 40964 */ #define EXIFTAG_Interoperability 0xA005 /* 40965 */ #define EXIFTAG_FlashEnergy 0xA20B /* 41483 */ #define EXIFTAG_SpatialFrequencyResponse 0xA20C /* 41484 */ #define EXIFTAG_FocalPlaneXResolution 0xA20E /* 41486 */ #define EXIFTAG_FocalPlaneYResolution 0xA20F /* 41487 */ #define EXIFTAG_FocalPlaneResolutionUnit 0xA210 /* 41488 */ #define EXIFTAG_SubjectLocation 0xA214 /* 41492 */ #define EXIFTAG_ExposureIndex 0xA215 /* 41493 */ #define EXIFTAG_SensingMethod 0xA217 /* 41495 */ #define EXIFTAG_FileSource 0xA300 /* 41728 */ #define EXIFTAG_SceneType 0xA301 /* 41729 */ #define EXIFTAG_CFAPattern 0xA302 /* 41730 */ #define EXIFTAG_ExifCustomRendered 0xA401 /* 41985 */ #define EXIFTAG_ExifExposureMode 0xA402 /* 41986 */ #define EXIFTAG_ExifWhiteBalance 0xA403 /* 41987 */ #define EXIFTAG_ExifDigitalZoomRatio 0xA404 /* 41988 */ #define EXIFTAG_ExifFocalLengthIn35mmFilm 0xA405 /* 41989 */ #define EXIFTAG_ExifSceneCaptureType 0xA406 /* 41990 */ #define EXIFTAG_ExifGainControl 0xA407 /* 41991 */ #define EXIFTAG_ExifContrast 0xA408 /* 41992 */ #define EXIFTAG_ExifSaturation 0xA409 /* 41993 */ #define EXIFTAG_ExifSharpness 0xA40A /* 41994 */ #define EXIFTAG_ExifDeviceSettingDescription 0xA40B /* 41995 */ #define EXIFTAG_ExifSubjectDistanceRange 0xA40C /* 41996 */ #define EXIFTAG_ExifImageUniqueId 0xA420 /* 42016 */ #define EXIFTAG_ExifGamma 0xA500 /* 42240 */ #define INTEROPTAG_Index 0x0001 #define INTEROPTAG_Version 0x0002 #define INTEROPTAG_RelatedFileFormat 0x1000 #define INTEROPTAG_RelatedImageWidth 0x1001 #define INTEROPTAG_RelatedImageLength 0x1002 #endif exifprobe-2.0.1+git20170416-3c2b76/win/0000755000000000000000000000000013074742216015306 5ustar rootrootexifprobe-2.0.1+git20170416-3c2b76/win/exifprobe.sln0000644000000000000000000000156413074742216020015 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exifprobe", "exifprobe.vcxproj", "{6489E0DA-98B2-4B8B-BDE5-68D3CE5E0CD3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {6489E0DA-98B2-4B8B-BDE5-68D3CE5E0CD3}.Debug|Win32.ActiveCfg = Debug|Win32 {6489E0DA-98B2-4B8B-BDE5-68D3CE5E0CD3}.Debug|Win32.Build.0 = Debug|Win32 {6489E0DA-98B2-4B8B-BDE5-68D3CE5E0CD3}.Release|Win32.ActiveCfg = Release|Win32 {6489E0DA-98B2-4B8B-BDE5-68D3CE5E0CD3}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal exifprobe-2.0.1+git20170416-3c2b76/win/byteorder.h0000644000000000000000000000004713074742216017457 0ustar rootroot#define NATIVE_BYTEORDER_LITTLE_ENDIAN exifprobe-2.0.1+git20170416-3c2b76/win/README_WIN.txt0000644000000000000000000000444713074742216017532 0ustar rootrootHow to build exifprobe with Microsoft Windows Visual Studio 2010 ================================================================ The "win" directory contains a Visual Studio 2010 solution which builds exifprobe under the Windows OS. The Visual Studio solution has successfully been used to compile the original exifprobe 2.0.1 sources developed 2002-2005 by Duane H. Hesser (who died in 2012) as well as the forked and improved version 2.1.0 from Hubert Figuiere (this code, available at https://github.com/hfiguiere/exifprobe). The original 2.0.1 source code archive can be found at http://archive.ubuntu.com/ubuntu/pool/universe/e/exifprobe/exifprobe_2.0.1.orig.tar.gz * The Visual Studio project file exifprobe.vcxproj contains the following custom settings: - Additional Include Directories: . - Preprocessor: u_int32_t=uint32_t strncasecmp=_strnicmp * The following files have been added in the "win" directory. They are only used when exifprobe is build under Windows. - a file byteorder.h with defines NATIVE_BYTEORDER_LITTLE_ENDIAN - a file comptime.h - an empty file as a replacement for unistd.h - a replacement for getopt.h and getopt.c (with BSD license) from http://www.rohitab.com/discuss/topic/39420-a-proper-port-of-getopt/ - a file snprintf.c which wrapps the Windows _snprintf() function to work around its non standard negative return value, see http://stackoverflow.com/a/13067917/321013 * The following modifications had to be applied to the original 2.0.1 source code diff exifprobe-2.0.1.orig/main.c exifprobe-2.0.1/main.c 86c86 < inptr = fopen(file,"r"); --- > inptr = fopen(file,"rb"); diff exifprobe-2.0.1.orig/process.c exifprobe-2.0.1/process.c 254c254,255 < fseek(inptr,0L,current_offset); --- > fseek(inptr,current_offset,0); diff exifprobe-2.0.1.orig/readfile.c exifprobe-2.0.1/readfile.c 25a26 > #include * To generate the Windows executable open and build the solution exifprobe.sln in Visual Studio 2010 or later. A number of warnigns will be displayed (mixing unsigned and signed integers, use of deprecated posix functions). Finally the generated exifprobe.exe file can be found in the Debug directory. exifprobe-2.0.1+git20170416-3c2b76/win/exifprobe.vcxproj.user0000644000000000000000000000056613074742216021672 0ustar rootroot WindowsLocalDebugger exifprobe-2.0.1+git20170416-3c2b76/win/snprintf.c0000644000000000000000000000050013074742216017310 0ustar rootroot#include #include int snprintf(char *buffer, size_t count, const char *format, ...) { int len; va_list args; va_start(args, format); len = vsnprintf(buffer, count, format, args); va_end(args); if (len < 0) { len = count + 1; } return len; } exifprobe-2.0.1+git20170416-3c2b76/win/exifprobe.vcxproj.filters0000644000000000000000000001300413074742216022353 0ustar rootroot {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files exifprobe-2.0.1+git20170416-3c2b76/win/comptime.c0000644000000000000000000000005013074742216017262 0ustar rootrootchar *Comptime = __DATE__ " " __TIME__; exifprobe-2.0.1+git20170416-3c2b76/win/unistd.h0000644000000000000000000000000013074742216016753 0ustar rootrootexifprobe-2.0.1+git20170416-3c2b76/win/exifprobe.vcxproj0000644000000000000000000001421013074742216020704 0ustar rootroot Debug Win32 Release Win32 {6489E0DA-98B2-4B8B-BDE5-68D3CE5E0CD3} Win32Proj exifprobe Application true Unicode Application false true Unicode true false Level3 Disabled WIN32;u_int32_t=uint32_t;strncasecmp=_strnicmp;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) . Console true Level3 MaxSpeed true true WIN32;u_int32_t=uint32_t;strncasecmp=_strnicmp;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) . Console true true true exifprobe-2.0.1+git20170416-3c2b76/win/getopt.h0000644000000000000000000000056613074742216016770 0ustar rootroot#ifndef GETOPT_H #define GETOPT_H #ifndef _WIN32 #include #else /* _WIN32 */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ extern char *optarg; extern int optind, opterr, optopt, optreset; int getopt(int nargc, char * const nargv[], const char *ostr); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* !_WIN32 */ #endif /* !GETOPT_H */ exifprobe-2.0.1+git20170416-3c2b76/win/getopt.c0000644000000000000000000001010213074742216016746 0ustar rootroot/* $NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $ */ /* * Copyright (c) 1987, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include "getopt.h" int opterr = 1, /* if error message should be printed */ optind = 1, /* index into parent argv vector */ optopt, /* character checked for validity */ optreset; /* reset getopt */ char *optarg; /* argument associated with option */ #define BADCH (int)'?' #define BADARG (int)':' #define EMSG "" /* * Get program name in Windows */ const char * _getprogname(void); /* * getopt -- * Parse argc/argv argument vector. */ int getopt(int nargc, char * const nargv[], const char *ostr) { static char *place = EMSG; /* option letter processing */ char *oli; /* option letter list index */ if (optreset || *place == 0) { /* update scanning pointer */ optreset = 0; place = nargv[optind]; if (optind >= nargc || *place++ != '-') { /* Argument is absent or is not an option */ place = EMSG; return (-1); } optopt = *place++; if (optopt == '-' && *place == 0) { /* "--" => end of options */ ++optind; place = EMSG; return (-1); } if (optopt == 0) { /* Solitary '-', treat as a '-' option if the program (eg su) is looking for it. */ place = EMSG; if (strchr(ostr, '-') == NULL) return (-1); optopt = '-'; } } else optopt = *place++; /* See if option letter is one the caller wanted... */ if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) { if (*place == 0) ++optind; if (opterr && *ostr != ':') (void)fprintf(stderr, "%s: illegal option -- %c\n", _getprogname(), optopt); return (BADCH); } /* Does this option need an argument? */ if (oli[1] != ':') { /* don't need argument */ optarg = NULL; if (*place == 0) ++optind; } else { /* Option-argument is either the rest of this argument or the entire next argument. */ if (*place) optarg = place; else if (nargc > ++optind) optarg = nargv[optind]; else { /* option-argument absent */ place = EMSG; if (*ostr == ':') return (BADARG); if (opterr) (void)fprintf(stderr, "%s: option requires an argument -- %c\n", _getprogname(), optopt); return (BADCH); } place = EMSG; ++optind; } return (optopt); /* return option letter */ } const char * _getprogname() { char *pgmptr = NULL; _get_pgmptr(&pgmptr); return strrchr(pgmptr,'\\')+1; } exifprobe-2.0.1+git20170416-3c2b76/maker_panasonic.c0000644000000000000000000003673213074742216020022 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_panasonic.c,v 1.5 2005/07/24 22:56:27 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* panasonic camera maker-specific routines */ /* panasonic support contributed by Tom Hughes */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* The information coded here is derived from experimentation with */ /* a Panasonic DMC-FZ10 and from looking at a few images from other */ /* cameras found on various web sites. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id panasonic_model_id[]; /* Find the identifying number assigned to known Panasonic camera */ /* models. This number is used to dispatch print and interpret */ /* routines approopriate to the current image. */ int panasonic_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &panasonic_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine for direct values in Panasonic cameras, */ /* based upon model */ void print_panasonic_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 1: print_panasonic1_makervalue(entry_ptr,make,model,prefix); panasonic1_interpret_value(entry_ptr); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Panasonic cameras. This routine */ /* is responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_panasonic1_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for Panasonic */ /* cameras. */ void print_panasonic_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) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 1: panasonic1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in Panasonic makernotes. */ void panasonic1_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) { unsigned long value_offset,count; char *nameoftag; char *fulldirname = NULL; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0e00: /* PrintIM (Epson Print Image matching) */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) { chpr += printf("@%lu:%lu",value_offset,count); chpr = newline(chpr); } } process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Panasonic-specific tagnames for makernotes. */ /* The tagname routine is the first place in the code path which */ /* requires knowledge of the note version. If the version is not */ /* given in the model table (e.g. the model is unknown), then switch */ /* code in find_maker_scheme() should have set it. This routine */ /* repeats the check for non-zero noteversion and is prepared to set */ /* the noteversion first time through, but should never need to do */ /* so. Noteversion should always be non-zero; it should be set to -1 */ /* if generic processing is required. */ char * maker_panasonic_tagname(unsigned short tag,int model) { char *tagname = (char *)0; int noteversion = 0; /* Should have to do this only once, and only for unrecognized */ /* models. If the model is recognized (or the user has forced a */ /* noteversion) noteversion will already be set. */ if((noteversion = getnoteversion()) == 0) { noteversion = 1; setnoteversion(1); } switch(noteversion) { case 1: tagname = maker_panasonic1_tagname(tag,model); break; default: break; } return(tagname); } char * maker_panasonic1_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0001: tagname = "Quality"; break; case 0x0002: tagname = "FirmwareVersion"; break; case 0x0003: tagname = "WhiteBalance"; break; case 0x0007: tagname = "FocusMode"; break; case 0x000f: tagname = "SpotMode"; break; case 0x001a: tagname = "StabilizerMode"; break; case 0x001c: tagname = "Macro"; break; case 0x001f: tagname = "PictureMode"; break; case 0x0020: tagname = "Audio"; break; case 0x0023: tagname = "WhiteBalanceAdjust"; break; case 0x0024: tagname = "FlashStrength"; break; case 0x0028: tagname = "ColorMode"; break; case 0x0029: tagname = "TimeSincePowerOn"; break; case 0x002c: tagname = "Contrast"; break; case 0x002d: tagname = "NoiseReduction"; break; case 0x0e00: tagname = "PrintIM"; break; default: break; } setnotetagset(1); return(tagname); } /* Report the "meaning" of tag values found at offsets in a Panasonic */ /* MakerNote IFD entry (not at an offset). */ void panasonic1_interpret_value(struct ifd_entry *entry_ptr) { switch(entry_ptr->tag) { case 0x0001: /* Quality */ print_startvalue(); switch(entry_ptr->value) { case 2: printf("Fine"); break; case 3: printf("Standard"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0003: /* White Balance */ print_startvalue(); switch(entry_ptr->value) { case 1: printf("Auto"); break; case 2: printf("Daylight"); break; case 3: printf("Cloudy"); break; case 4: printf("Halogen"); break; case 5: printf("Manual"); break; case 8: printf("Flash"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0007: /* Focus Mode */ print_startvalue(); switch(entry_ptr->value) { case 1: printf("Auto"); break; case 2: printf("Manual"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x000f: /* Spot Mode */ print_startvalue(); switch(entry_ptr->value) { case 1: printf("Spot"); break; case 16: printf("1 Area"); break; case 256: printf("9 Area/On"); break; case 4096: printf("3 Area/Off"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x001a: /* Stabilizer Mode */ print_startvalue(); switch(entry_ptr->value) { case 2: printf("Mode 1"); break; case 3: printf("Off"); break; case 4: printf("Mode 2"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x001c: /* Macro */ print_startvalue(); switch(entry_ptr->value) { case 1: printf("On"); break; case 2: printf("Off"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x001f: /* Picture Mode */ print_startvalue(); switch(entry_ptr->value) { case 2: printf("Portrait"); break; case 3: printf("Scenery"); break; case 4: printf("Sports"); break; case 5: printf("Night Portrait"); break; case 6: printf("Program"); break; case 7: printf("Aperture Priority"); break; case 8: printf("Shutter Priority"); break; case 9: printf("Macro"); break; case 11: printf("Manual"); break; case 13: printf("Panning"); break; case 18: printf("Fireworks"); break; case 19: printf("Party"); break; case 20: printf("Snow"); break; case 21: printf("Night Scenery"); break; default: printred("undefined"); } print_endvalue(); break; case 0x0020: /* Audio */ print_startvalue(); switch(entry_ptr->value) { case 1: printf("Yes"); break; case 2: printf("No"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0023: /* White Balance Adjust */ print_startvalue(); switch(entry_ptr->value) { case 0xfffb: printf("-5"); break; case 0xfffc: printf("-4"); break; case 0xfffd: printf("-3"); break; case 0xfffe: printf("-2"); break; case 0xffff: printf("-1"); break; case 0x0000: printf("0"); break; case 0x0001: printf("+1"); break; case 0x0002: printf("+2"); break; case 0x0003: printf("+3"); break; case 0x0004: printf("+4"); break; case 0x0005: printf("+5"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0024: /* Flash Strength */ print_startvalue(); switch(entry_ptr->value) { case 0xfffa: printf("-2 EV"); break; case 0xfffb: printf("-1.67 EV"); break; case 0xfffc: printf("-1.33 EV"); break; case 0xfffd: printf("-1 EV"); break; case 0xfffe: printf("-0.67 EV"); break; case 0xffff: printf("-0.33 EV"); break; case 0x0000: printf("0 EV"); break; case 0x0001: printf("+0.33 EV"); break; case 0x0002: printf("+0.67 EV"); break; case 0x0003: printf("+1 EV"); break; case 0x0004: printf("+1.33 EV"); break; case 0x0005: printf("+1.67 EV"); break; case 0x0006: printf("+2 EV"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0028: /* Color Mode */ print_startvalue(); switch(entry_ptr->value) { case 1: printf("Off"); break; case 2: printf("Warm"); break; case 3: printf("Cool"); break; case 4: printf("Black/White"); break; case 5: printf("Sepia"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x002c: /* Contrast */ print_startvalue(); switch(entry_ptr->value) { case 0: printf("Standard"); break; case 1: printf("Low"); break; case 2: printf("High"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x002d: /* Noise Reduction */ print_startvalue(); switch(entry_ptr->value) { case 0: printf("Standard"); break; case 1: printf("Low"); break; case 2: printf("High"); break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } exifprobe-2.0.1+git20170416-3c2b76/makebyteorder.sh0000755000000000000000000000105613074742216017707 0ustar rootroot#!/bin/sh # @(#) $Id: makebyteorder.sh,v 1.1 2003/01/12 19:30:31 alex Exp $ if test -f /usr/include/machine/endian.h then byteorder=`grep BYTE_ /usr/include/machine/endian.h` elif test -f /usr/include/bits/endian.h then byteorder=`grep BYTE_ /usr/include/bits/endian.h` fi case "${byteorder}" in *BIG*) echo "#define NATIVE_BYTEORDER_BIGENDIAN" > byteorder.h ;; *LITTLE*) echo "#define NATIVE_BYTEORDER_LITTLE_ENDIAN" > byteorder.h ;; *) echo "#define NATIVE_BYTEORDER_UNKNOWN /* assume little-endian */" > byteorder.h ;; esac exit 0 exifprobe-2.0.1+git20170416-3c2b76/summary.h0000644000000000000000000001622413074742216016364 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: summary.h,v 1.9 2005/07/24 21:15:04 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Definitions for image summarys */ #ifndef SUMMARY_INCLUDED #define SUMMARY_INCLUDED /* FILE formats */ #define FILEFMT_TIFF PROBE_TIFFMAGIC #define FILEFMT_ORF1 PROBE_ORF1MAGIC #define FILEFMT_ORF2 PROBE_ORF2MAGIC #define FILEFMT_RW2 PROBE_RW2MAGIC #define FILEFMT_JPEG PROBE_JPEGMAGIC #define FILEFMT_JP2 PROBE_JP2MAGIC #define FILEFMT_CIFF PROBE_CIFFMAGIC #define FILEFMT_MRW PROBE_MRWMAGIC #define FILEFMT_RAF PROBE_RAFMAGIC #define FILEFMT_X3F PROBE_X3FMAGIC /* FILE formats modifiers */ #define FILESUBFMT_TIFF 0x00001 #define FILESUBFMT_TIFFOLD 0x00002 #define FILESUBFMT_TIFFEP 0x00004 #define FILESUBFMT_JPEG 0x00008 #define FILESUBFMT_EXIF 0x00010 #define FILESUBFMT_NEF 0x00020 #define FILESUBFMT_CR2 0x00040 #define FILESUBFMT_DNG 0x00080 /* ADD DCR, KDC? ###%%% */ #define FILESUBFMT_MNOTE 0x00100 #define FILESUBFMT_MNSUBIFD 0x00200 #define FILESUBFMT_CIFF 0x00400 /* may be used in APP0 */ #define FILESUBFMT_GEOTIFF 0x00800 /* not used yet */ #define FILESUBFMT_JFIF 0x01000 #define FILESUBFMT_JFXX 0x02000 #define FILESUBFMT_FPIX 0x04000 #define FILESUBFMT_APPN 0x08000 /* ADD Meta(APP3)? ###%%% */ #define FILESUBFMT_TIFFUSED 0x003ff /* IMAGE formats */ #define IMGFMT_NOIMAGE 0 #define IMGFMT_TIFF PROBE_TIFFMAGIC /* including ORF */ #define IMGFMT_JPEG PROBE_JPEGMAGIC #define IMGFMT_JPEG2000 PROBE_JP2MAGIC #define IMGFMT_CRW PROBE_CIFFMAGIC #define IMGFMT_MRW PROBE_MRWMAGIC #define IMGFMT_RAF PROBE_RAFMAGIC #define IMGFMT_X3F PROBE_X3FMAGIC #define IMGFMT_MISMARKED 0x10000000 /* for CR2 "JPEG" RGB */ /* IMAGE format modifiers */ /* TIFF Photometric values; first 16 bits if 17th bit */ #define IMGSUBFMT_CFA 0x18023 /* 32803 */ #define IMGSUBFMT_MINISWHITE 0x10000 #define IMGSUBFMT_MINISBLACK 0x10001 #define IMGSUBFMT_RGB 0x10002 #define IMGSUBFMT_PALETTE 0x10003 #define IMGSUBFMT_MASK 0x10004 #define IMGSUBFMT_SEPARATED 0x10005 #define IMGSUBFMT_YCBCR 0x10006 #define IMGSUBFMT_CIELAB 0x10008 #define IMGSUBFMT_ICCLAB 0x10009 #define IMGSUBFMT_ITULAB 0x10010 #define IMGSUBFMT_LOGL 0x1804c /* 32844 */ #define IMGSUBFMT_LOGLUV 0x1804d /* 32845 */ #define IMGSUBFMT_LINEARRAW 0x1884c /* 38492 */ #define IMGSUBFMT_PMIMASK 0x0ffff /* If this bit is set, the PMIMASKED value is the */ /* PhotoMetricInterpretation */ #define IMGSUBFMT_VALUE_IS_PMI 0x10000 /* If PMI bit isn't set */ #define IMGSUBFMT_JPEGTABLES 0x015b #define IMGSUBFMT_HUFF_COMPRESSED_RGB 0x20001 #define IMGSUBFMT_JPEG_COMPRESSED_RGB 0x20002 #define IMGSUBFMT_X3F_UNSPECIFIED 0x20003 #define IMGSUBFMT_X3F_COMPRESSED 0x20004 #if 0 #define IMGSUBFMT_CMY 0x1000 #define IMGSUBFMT_GREYSCALE 0x00e1 #define IMGSUBFMT_BILEVEL 0x0010 #endif #define IMGSUBFMT_TRUNCATED 0x10000000 #define IMGSUBFMT_JPEG_EARLY_EOI 0x20000000 #define IMGSUBFMT_NO_JPEG 0x40000000 /* no SOI */ #define IMGSUBFMT_JPEGFAILED 0x80000000 /* failed after SOI */ #define IMGSUBFMT_ERRORMASK 0xf0000000 #define MAXSAMPLE 16 /* size of bps array */ struct image_summary { struct image_summary *prev_entry; struct image_summary *next_entry; int entry_lock; /* If set, entry is used, add a new one */ /* per file */ int fileformat; /* identifies image FILE format */ int filesubformat; /* file format modifier bits */ int filesubformatAPPN[16]; /* APPn sections present in file */ unsigned long primary_width; /* size of the primary image */ unsigned long primary_height; /* per image */ unsigned long pixel_width; unsigned long pixel_height; unsigned long imageformat; /* IMAGE: JPEG, CFA, JP2, TIFF,... */ unsigned long imagesubformat; /* image format modifiers */ unsigned long offset; /* file offset of start of image */ unsigned long length; /* image length in bytes */ /* These are used to process individually jpeg-compressed tiles */ unsigned long offset_loc; /* location of offset table */ unsigned long length_loc; /* location of bytecount table */ unsigned long chunkhow; /* strips or tiles */ unsigned long chunktype; /* short or long */ int noffsets; /* number of strips, tiles */ int subfiletype; /* PRIMARY, THUMBNAIL, etc. */ int compression; /* interpret according to imageformat */ /* This stuff is experimental; not used everywhere */ int spp; /* samples per pixel */ int bps[MAXSAMPLE]; /* one for each conponent */ int sample_size; /* assume all are the same size */ float compress_percent; /* calulate in scan_summary() */ /* datatype describes the data structure from which the current */ /* image is described. For some file types this may be just the */ /* file type, for TIFF it will be the type of IFD (e.g. TIFF_IFD, */ /* SubIFD, Exif, Interop, etc. */ int datatype; /* TIFF, EXIF, Interop, GPS, SubIFD... */ /* Used only for TIFF */ int ifdnum; /* parent idfnum if subifd */ int subifdnum; }; #endif /* SUMMARY INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/ciff_datadefs.h0000644000000000000000000000217013074742216017424 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: ciff_datadefs.h,v 1.1 2005/05/25 15:38:07 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef CIFF_DATADEFS_INCLUDED #define CIFF_DATADEFS_INCLUDED struct ciff_header { unsigned short byteorder; unsigned long headerlength; char type[5]; char subtype[5]; unsigned long version; unsigned long reserved1; unsigned long reserved2; }; struct ciff_direntry { unsigned short type; unsigned long length; unsigned long offset; }; #endif /* CIFF_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/x3f_datadefs.h0000644000000000000000000000412713074742216017221 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: x3f_datadefs.h,v 1.1 2005/06/09 02:20:32 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef X3F_DATADEFS_INCLUDED #define X3F_DATADEFS_INCLUDED struct x3f_header { unsigned long magic; unsigned short version_minor; unsigned short version_major; char unique_id[16]; unsigned long mark_bits; unsigned long image_width; unsigned long image_height; unsigned long image_rotation; char white_balance[32]; char extended_data_types[32]; unsigned long extended_data_values[32]; }; struct x3f_direntry { unsigned long section_id; unsigned long data_offset; unsigned long data_length; unsigned long data_type; }; struct x3f_imag_header { unsigned long section_id; unsigned short version_minor; unsigned short version_major; unsigned long image_type; unsigned long image_format; unsigned long image_width; unsigned long image_height; unsigned long image_rowsize; }; struct x3f_prop_header { unsigned long section_id; unsigned short version_minor; unsigned short version_major; unsigned long num_entries; unsigned long char_format; unsigned long reserved; unsigned long entry_length; }; struct x3f_camf_header { unsigned long section_id; unsigned short version_minor; unsigned short version_major; unsigned long item1; unsigned long item2; unsigned long item3; unsigned long item4; unsigned long item5; }; #endif /* X3F_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/ABOUT_PIM0000644000000000000000000000245713074742216016023 0ustar rootrootBeginning with version 1.2.6, exifprobe reports the structure of Print Image Matching sections, according to information provided by evan@ozhiker.com on the web page at http://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html The meaning of the PIM tags and the interpretation of the 4 bytes of data in each entry are not known. Exifprobe prints the tags by hexadecimal number, and prints the data in two formats: a "hex dump" of each data entry, followed by the hex and decimal values of the data interpreted as unsigned long integers in the prevailing byteorder of the Exif data. Print IM is a feature of Epson Printers, supported by several camera manufacturers. The PrintIM section is included in either the first TIFF IFD or in the MakerNote, or both. The section records a "profile" indicating certain transformations which the manufacturer finds will improve the image presentation on a PrintIM-enabled printer. Epson provides a FAQ at http://www.printimagematching.com/faq4.php which better describes Print Image Matching. According to the FAQ, the values provided in the PrintIM section may include: Gamma Level Color Space Color Balance Contrast Brightness Sharpness Saturation Shadow Highlight PIM version II also may include Noise Reduction Custom Scene setting exifprobe-2.0.1+git20170416-3c2b76/lib/0000755000000000000000000000000013074742216015257 5ustar rootrootexifprobe-2.0.1+git20170416-3c2b76/lib/veclib.c0000644000000000000000000000737213074742216016700 0ustar rootroot#ifndef lint static char *Module_id = "$Id: veclib.c,v 2.6 2003/02/20 00:56:58 alex Exp $"; #endif #define CNULL (char *)0 static char *next_word(); static int is_sep(); /* FUNCTION vector() */ /* Convert a null-terminated string into a vector of words. Words */ /* are strings separated by "sepchars". The string is broken up "in */ /* place", and separators are replaced by null characters. The */ /* vector is constructed in "wstart", which must be at least size */ /* 'maxent'. The vector is null-terminated, so 'maxent' must */ /* include space for the terminating null entry. */ /* RETURNS the number of words in the vector, including the */ /* terminating null. */ int vector(buf,wstart,sepchars,singlesep,maxent) char *buf,**wstart,*sepchars; int singlesep,maxent; { char *bptr = buf; int pos = 0; if(!wstart) return(0); wstart[0] = bptr; if(!buf || (*buf == '\0')) return(0); bptr = buf; /* first word */ wstart[0] = bptr; /* next_word() replaces the next separator with a null char */ /* and returns the start of the next word (which may be null */ /* if there are no more words. */ while(bptr && (bptr = next_word(wstart[pos],sepchars,singlesep))) { wstart[++pos] = bptr; if(pos >= (maxent - 1)) break; } wstart[++pos] = CNULL; return(pos); } /* FUNCTION next_word() */ /* Finds the beginning of the second "word" pointed to by its */ /* argument. A word ends at the first ocurrence of any character */ /* in sepchars, which is replaced in the string by a null. The */ /* start of the next word is the next character not in sepchars. */ /* RETURNS a pointer to the start of the second word, or CNULL */ /* if no second word. If 'singlesep' is non-zero, adjacent */ /* separators surround null "words"; otherwise, contiguous strings */ /* of sepchars delineate words. */ char * next_word(string,sepchars,singlesep) char *string,*sepchars; int singlesep; { char *x; if(string == CNULL) return(string); x = string; while(*x && !is_sep(*x,sepchars)) ++x; if(!*x) /* end of line */ return(CNULL); /* replace separator after first word with null */ *x++ = '\0'; if(!singlesep) { /* find and return pointer to the first non-sep char */ while(is_sep(*x,sepchars)) ++x; if(!*x) /* end of line */ return(CNULL); } /* If the current char is a separator (singlesep) it will be */ /* replaced by a null next time through. */ return(x); } #ifndef is_sep /* FUNCTION is_sep */ /* Examines character passed as argument and RETURNS 1 if the */ /* character is in the string defined by "sepchars", otherwise */ /* returns 0. (0 is returned if character is null). */ int is_sep(c,sepchars) char c,*sepchars; { char *tmp = sepchars; if(c) { while(*tmp) { if(*tmp == c) return(1); else ++tmp; } } return(0); } #endif #include /* FUNCTION prvector() prints to 'toptr' the null-terminated vector */ /* passed as argument. For debugging only. Prints at most 'nwords' */ /* words. */ void prvector(ioptr,vec,nwords) FILE * ioptr; char **vec; int nwords; { int i = 0; fprintf(ioptr,"%d words:\n",nwords); if(vec) { while(*vec && (i < nwords)) fprintf(ioptr,"\t[%d] \"%s\"\n",i++,*vec++); } else fprintf(ioptr,"no words (nwords = %d\n",nwords); } exifprobe-2.0.1+git20170416-3c2b76/print_maker.c0000644000000000000000000007771213074742216017206 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: print_maker.c,v 1.29 2005/07/24 17:27:09 alex Exp $"; #endif #include #include #include #include "defs.h" #include "summary.h" #include "maker.h" #include "datadefs.h" #include "maker_datadefs.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_name Camera_make[]; #ifndef STRCASESTR #define STRCASESTR fake_strcasestr extern char *fake_strcasestr(char *,char *); #endif /* Print an IFD entry presumed to be from a MakerNote. */ /* This differs from print_entry() in that it dispatches */ /* maker_tagname() to get tag names specific to a specific make and */ /* (possibly) model, and calls print_makervalue() to intercept any */ /* tags which may require special treatment due to maker oddities. */ /* The maker-specific routines dispatched by print_makervalue() will */ /* also handle interpretation of the tag values if known. */ unsigned long print_makerentry(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base, struct image_summary *summary_entry,char *parent_name, int indent,int make,int model) { int value_is_offset = 0; unsigned long endoffset = 0UL; int chpr = 0; value_is_offset = is_offset(entry_ptr); if(value_is_offset == 0) value_is_offset = maker_value_is_offset(entry_ptr,make,model); else value_is_offset += maker_value_is_offset(entry_ptr,make,model); if(PRINT_ENTRY) print_makertaginfo(entry_ptr,parent_name,indent,make,model); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE)) { if(PRINT_ENTRY) chpr = printf("# INVALID MAKERNOTE ENTRY (%#lx)",entry_ptr->value); endoffset = ftell(inptr); } else if(entry_ptr->count == 0) { if(PRINT_VALUE) chpr = printf("EMPTY (%lu)",entry_ptr->value); endoffset = ftell(inptr); } else if(value_is_offset) { if(value_is_offset > 0) { if(PRINT_BOTH_OFFSET) chpr += printf("@%#lx=%lu",entry_ptr->value + fileoffset_base, entry_ptr->value + fileoffset_base); else if(PRINT_HEX_OFFSET) chpr += printf("@%#lx",entry_ptr->value + fileoffset_base); else if(PRINT_DEC_OFFSET) chpr += printf("@%lu",entry_ptr->value + fileoffset_base); if(fileoffset_base && (PRINT_ENTRY_RELOFFSET)) chpr += printf(" (%lu)",entry_ptr->value); } else if((value_is_offset < 0) && (PRINT_VALUE)) print_makervalue(entry_ptr,make,model,PREFIX); /* Print "inline" in REPORT & LIST modes */ if(!(PRINT_VALUE_AT_OFFSET)) { setcharsprinted(chpr); chpr = 0; endoffset = print_offset_makervalue(inptr,byteorder, entry_ptr,fileoffset_base, summary_entry,parent_name, "@",indent + SUBINDENT, make,model,0); } } else if(PRINT_VALUE) print_makervalue(entry_ptr,make,model,PREFIX); chpr = newline(chpr); return(endoffset); } /* Repeat the tag identifier for values printed at an offset. This is */ /* called only from the "*makervalue-at_offset()" routines when */ /* printing offset values at the offset (rather than "inline"), and */ /* repeats only one of the identifiers (preferably tagname) followed */ /* by the value separator (if values are printed at all). If no tag */ /* identifier is enabled in Print_options, the tag name will be */ /* printed, as in the entry line printed by print_makertaginfo(). */ /* The caller will normally pass the 'sep' argument as ' = ' if an */ /* actual value is to follow, or ': ' if a description (e.g. length */ /* of UNDEFINED segment which is not expanded). */ void print_makertagid(struct ifd_entry *entry_ptr,int width, char *sep, int make,int model) { char *nameoftag; int chpr = 0; if(entry_ptr) { if((PRINT_TAGNAME)) { nameoftag = maker_tagname(entry_ptr->tag,make,model); chpr = printf("%-*.*s",width,width,nameoftag); } else if(PRINT_HEX_TAGNO) chpr = printf("<%#06x>",entry_ptr->tag & 0xffff); else if(PRINT_DEC_TAGNO) chpr = printf("<%5u>",entry_ptr->tag & 0xffff); if(PRINT_VALUE) chpr += printf("%s",sep ? sep : " = "); } setcharsprinted(chpr); } /* Print the part of a MakerNote entry describing the entry tag, */ /* including it's tag number, name and type. Only the items enabled */ /* in "Print_options" are printed. */ /* In LIST mode prefix the tag name with a section identifier, so */ /* that the resulting names may be recognized by patterns or regular */ /* expressions applied to the output (e.g. 'egrep') in */ /* post-processing. */ void print_makertaginfo(struct ifd_entry *entry_ptr,char *parent_name, int indent,int make,int model) { char *nameoftag; char *nameof_value_type; int chpr = 0; if(entry_ptr) { if(PRINT_BOTH_TAGNO) chpr = printf("<%#06X=%5u> ",entry_ptr->tag & 0xffff,entry_ptr->tag & 0xffff); else if(PRINT_HEX_TAGNO) chpr = printf("<%#06X> ",entry_ptr->tag & 0xffff); else if(PRINT_DEC_TAGNO) chpr = printf("<%5u> ",entry_ptr->tag & 0xffff); if((PRINT_TAGNAME)) { nameoftag = maker_tagname(entry_ptr->tag,make,model); if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",MAKERTAGWIDTH,MAKERTAGWIDTH,nameoftag); } if(PRINT_TYPE) { nameof_value_type = value_type_name(entry_ptr->value_type); chpr += printf(" [%2u=%-9.9s %5lu] ",entry_ptr->value_type, nameof_value_type,entry_ptr->count); } if(Debug & NOTE_DEBUG) { chpr += printf(" %d:%d,%d ",model,getnoteversion(),getnotetagset()); } if(PRINT_VALUE) chpr += printf(" = "); } setcharsprinted(chpr); } /* Dispatch maker-specific routines to print (and possibly interpret) */ /* non-offset values in MakerNote IFDs. If the make is not known, the */ /* normal print_value() routine will be called, and the */ /* maker-specific routines are free to do the same if the tag doesn't */ /* need special handling (such as a 4 byte UNDEFINED which should be */ /* printed as ascii). The maker-specific routines can also call */ /* routines to interpret the value (e.g "On", "Off", etc.) according */ /* to the requirements of the make and model. */ void print_makervalue(struct ifd_entry *entry_ptr,int make,int model,char *prefix) { if(entry_ptr) { switch(make) { case MAKER_AGFA: print_agfa_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_ASAHI: /* Asahi is Pentax */ case MAKER_PENTAX: /* Pentax is Asahi */ print_asahi_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_CANON: print_canon_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_CASIO: print_casio_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_EPSON: print_epson_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_FUJIFILM: print_fujifilm_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_HP: print_value(entry_ptr,PREFIX); break; case MAKER_KODAK: print_value(entry_ptr,PREFIX); break; case MAKER_KONICA: print_konica_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_KYOCERA: print_kyocera_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_LEICA: print_leica_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_MINOLTA: print_minolta_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_NIKON: print_nikon_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_OLYMPUS: print_olympus_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_PANASONIC: print_panasonic_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_RICOH: print_value(entry_ptr,PREFIX); break; case MAKER_SANYO: print_sanyo_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_SIGMA: print_sigma_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_SONY: print_sony_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_TOSHIBA: print_toshiba_makervalue(entry_ptr,make,model,PREFIX); break; case MAKER_TRAVELER: print_value(entry_ptr,PREFIX); break; default: /* No maker_specific print routine available */ print_value(entry_ptr,PREFIX); /* use default` */ break; } } } /* Print values found at offsets in a MakerNote entry by dispatching */ /* maker-specific routines which know how to interpret UNDEFINED */ /* values for that maker. These routines may also intercept "defined" */ /* values which are handled strangely, such as a "long" value which */ /* is really an offset, or a 4-byte UNDEFINED value which is really */ /* an offset to an UNDEFINED blob. If a maker-specific routine is */ /* called, it must handle all values for that maker (possibly by */ /* calling the generic routine). The generic and maker-specific */ /* routines are all 'void' functions, which should assure that the */ /* file pointer is moved past the subject data. This routine */ /* clears any IO errors (or EOF) and returns the calculated file */ /* offset of the end of the section. */ unsigned long print_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) { unsigned long endoffset = 0L; if(inptr && entry_ptr) { if((value_type_size(entry_ptr->value_type) * entry_ptr->count) <= 4UL) endoffset = 0; else endoffset = fileoffset_base + entry_ptr->value + (value_type_size(entry_ptr->value_type) * entry_ptr->count); switch(make) { case MAKER_AGFA: print_agfa_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent,make, model,at_offset); break; case MAKER_ASAHI: /* Pentax */ case MAKER_PENTAX: /* Pentax */ print_asahi_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent,make, model,at_offset); break; case MAKER_CANON: print_canon_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent,make, model,at_offset); break; case MAKER_CASIO: print_casio_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent,make, model,at_offset); break; case MAKER_EPSON: print_epson_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent,make, model,at_offset); break; case MAKER_FUJIFILM: print_fujifilm_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case MAKER_HP: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; case MAKER_KODAK: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; case MAKER_KYOCERA: print_kyocera_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case MAKER_KONICA: print_konica_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case MAKER_LEICA: print_leica_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case MAKER_MINOLTA: print_minolta_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent,make, model,at_offset); break; case MAKER_NIKON: print_nikon_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent,make, model,at_offset); break; case MAKER_OLYMPUS: print_olympus_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent,make, model,at_offset); break; case MAKER_PANASONIC: print_panasonic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case MAKER_RICOH: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; case MAKER_SANYO: print_sanyo_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent,make, model,at_offset); break; case MAKER_SIGMA: print_sigma_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case MAKER_SONY: print_sony_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case MAKER_TOSHIBA: print_toshiba_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case MAKER_TRAVELER: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; } } else { printred(" invalid call to print_offset_makervalue "); if(inptr == (FILE *)0) printred(" no input file pointer "); if(entry_ptr == (struct ifd_entry *)0) printred(" null entry pointer"); } if(ferror(inptr) || feof(inptr)) clearerr(inptr); (void)newline(0); if(ftell(inptr) > endoffset) endoffset = ftell(inptr); return(endoffset); } /* Print the value found at an offset in a generic MakerNote, if no */ /* maker-specific routine wants to deal with it. Similar to */ /* print_offset_value(). The routine is expected to read or skip all */ /* data associated with the entry. */ void print_generic_offset_makervalue(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base,char *parent_name, char *prefix,int indent,int make,int model,int at_offset) { unsigned long value_offset; unsigned long dumplength; int chpr = 0; if((value_type_size(entry_ptr->value_type) * entry_ptr->count) > 4) { value_offset = fileoffset_base + entry_ptr->value; if(PRINT_VALUE) { if(at_offset) { print_tag_address(ENTRY,value_offset,indent,prefix); if(entry_ptr->value_type == UNDEFINED) print_makertagid(entry_ptr,MAKERTAGWIDTH," : ",make,model); else print_makertagid(entry_ptr,MAKERTAGWIDTH," = ",make,model); } else { if((PRINT_OFFSET) && (entry_ptr->value_type != UNDEFINED)) chpr += printf(" = "); } switch(entry_ptr->value_type) { case UNDEFINED: /* Could make a pseudo-tag for 'count' in LIST */ /* mode... */ if((PRINT_SECTION) && at_offset && (PRINT_VALUE_AT_OFFSET)) chpr += printf("length %-9lu # UNDEFINED",entry_ptr->count); else { if(!(PRINT_OFFSET)) chpr += printf("@%lu",value_offset); chpr += printf(":%-9lu # UNDEFINED",entry_ptr->count); } if(Max_undefined == 0) { if((PRINT_SECTION)) printred(" (not dumped, use -U)"); } else { /* Even in LIST and REPORT modes */ if((Max_undefined == DUMPALL) || (Max_undefined > entry_ptr->count)) dumplength = entry_ptr->count; else dumplength = Max_undefined; chpr = newline(1); hexdump(inptr,entry_ptr->value + fileoffset_base, entry_ptr->count,dumplength,12, indent,SUBINDENT); } /* make certain we're at the end */ fseek(inptr,entry_ptr->value + fileoffset_base + entry_ptr->count,SEEK_SET); break; case ASCII: print_ascii(inptr,entry_ptr->count,value_offset); break; case BYTE: print_ubytes(inptr,entry_ptr->count,value_offset); break; case SBYTE: print_sbytes(inptr,entry_ptr->count,value_offset); break; case SHORT: print_ushort(inptr,entry_ptr->count,byteorder,value_offset); break; case SSHORT: print_sshort(inptr,entry_ptr->count,byteorder,value_offset); break; case LONG: print_ulong(inptr,entry_ptr->count,byteorder,value_offset); break; case SLONG: print_slong(inptr,entry_ptr->count,byteorder,value_offset); break; case RATIONAL: print_urational(inptr,entry_ptr->count,byteorder,value_offset); break; case SRATIONAL: print_srational(inptr,entry_ptr->count,byteorder,value_offset); break; case FLOAT: print_float(inptr,entry_ptr->count,byteorder,value_offset); break; case DOUBLE: print_double(inptr,entry_ptr->count,byteorder,value_offset); break; default: chpr = printf(" INVALID TYPE %#x",entry_ptr->value_type); break; } } } if(ferror(inptr) || feof(inptr)) clearerr(inptr); setcharsprinted(chpr); } void print_scheme(FILE *inptr,struct maker_scheme *maker_scheme) { int chpr = 0; PUSHCOLOR(HI_BLACK); chpr = newline(1); chpr += printf("MakerNote Scheme:"); chpr += printf(" (at offset %lu, length %lu)",maker_scheme->note_fileoffset, maker_scheme->note_length); chpr = newline(chpr); chpr += printf("\tScheme Type = "); switch(maker_scheme->scheme_type) { case PLAIN_IFD_SCHEME: chpr += printf("\"Plain IFD\" (%#lx) at offset %lu",maker_scheme->scheme_type, maker_scheme->note_fileoffset); chpr = newline(chpr); break; case HAS_ID_SCHEME: chpr += printf("\"ID\" (%#lx)\n",maker_scheme->scheme_type); chpr += printf("\tID = \"%s\";",maker_scheme->id[0] ? maker_scheme->id : "(NONE)"); chpr += printf(" length = %d, at offset %lu\n",maker_scheme->id_length, maker_scheme->note_fileoffset); chpr += printf("\tIFD is offset %d from start of section",maker_scheme->ifd_offset); chpr = newline(chpr); break; case HAS_ID_PLUS_TIFFHDR_SCHEME: chpr += printf("\"ID plus TIFF header\" (%#lx)\n",maker_scheme->scheme_type); chpr += printf("\tID = \"%s\";",maker_scheme->id[0] ? maker_scheme->id : "(NONE)"); chpr += printf("\tlength = %d, at offset %lu\n",maker_scheme->id_length, maker_scheme->note_fileoffset); chpr += printf("\tTIFF header is offset %d from start of section\n",maker_scheme->tiffhdr_offset); chpr += printf("\tIFD is offset %d from start of TIFF header",maker_scheme->ifd_offset); chpr = newline(chpr); break; case UNKNOWN_SCHEME: default: chpr += printf("\"UNKNOWN\" (%#lx)\n",maker_scheme->scheme_type); chpr += printf("\tID = \"%s\";",maker_scheme->id[0] ? maker_scheme->id : "(NONE)"); chpr += printf(" length = %d, at offset %lu",maker_scheme->id_length, maker_scheme->note_fileoffset); chpr = newline(chpr); break; } if(maker_scheme->note_byteorder && (maker_scheme->note_byteorder != maker_scheme->tiff_byteorder)) PUSHCOLOR(HI_RED); chpr += printf("\tNote byteorder = "); print_byteorder(maker_scheme->note_byteorder,2); if(maker_scheme->note_byteorder && (maker_scheme->note_byteorder != maker_scheme->tiff_byteorder)) { chpr += printf(" != "); POPCOLOR(); } else { chpr = newline(chpr); chpr += printf("\t"); } chpr += printf("Tiff byteorder = "); print_byteorder(maker_scheme->tiff_byteorder,2); chpr += newline(chpr); switch(maker_scheme->offsets_relative_to) { case START_OF_TIFFHEADER: chpr += printf("\tOffsets relative to TIFF header at offset %lu", maker_scheme->fileoffset_base); chpr = newline(chpr); break; case START_OF_NOTE: PUSHCOLOR(HI_RED); chpr += printf("\tOffsets relative to start of MakerNote"); POPCOLOR(); chpr += printf(" at offset %lu",maker_scheme->note_fileoffset); chpr += newline(1); break; case START_OF_ENTRY: PUSHCOLOR(HI_RED); chpr += printf("\tOffsets relative to start of entry"); POPCOLOR(); chpr += newline(1); break; default: chpr += printf("(UNKNOWN)\n"); break; } chpr += printf("\tNumber of entries = %d",maker_scheme->num_entries); chpr = newline(chpr); if((maker_scheme->scheme_type != UNKNOWN_SCHEME) && maker_scheme->no_nextifd_offset) { putchar('\t'); ++chpr; PUSHCOLOR(HI_RED); chpr += printf("No next IFD offset"); POPCOLOR(); chpr += newline(1); } if(Make_name) { putchar('\t'); ++chpr; chpr += printf("Make = \"%s\"",Make_name); chpr += printf(" (maker id = %d)",maker_scheme->make); chpr = newline(1); } if(Model_name) { putchar('\t'); ++chpr; chpr += printf("Model = \"%s\"",Model_name); chpr += printf(" (model id = %d)",maker_scheme->model); chpr = newline(1); } if(Software_name) { putchar('\t'); ++chpr; chpr += printf("Software = \"%s\"",Software_name); chpr = newline(1); } putchar('\t'); ++chpr; chpr += printf("Note version = %d (tagset = %d)",maker_scheme->note_version,maker_scheme->tagset); POPCOLOR(); chpr = newline(chpr); chpr = newline(1); } /* Print a list of camera makes known to the program. If a global */ /* matching pattern has been set for names (by option) , limit the */ /* output to camera names for which a case-insensitive substring */ /* match occurs, otherwise list all makes. For each make printed, */ /* print the list of recognized models. The Make and Model names (in */ /* the camera_names.h and "maker"_datadefs.h files) are. or should */ /* be, the "official" names used by the maker in the Make and Model */ /* entries of and TIFF IFD or CIFF Make/Model entry. */ void print_camera_makes() { struct camera_name *maker_id; char *pattern,*model_pattern; int chpr = 0; chpr = newline(0); chpr += printf("Camera Makes:"); chpr = newline(chpr); if(Camera_name_pattern) { pattern = Camera_name_pattern; if((model_pattern = strchr(pattern,'+'))) *model_pattern++ = '\0'; else model_pattern = NULL; /* 'Camera_make' is a global parameter */ for(maker_id = Camera_make; maker_id && maker_id->name; ++maker_id) { if(pattern) { if(*pattern == '-') { chpr += printf("\t%-32.32s [%d]",maker_id->name,maker_id->id); chpr = newline(chpr); } else { if((*pattern) && !STRCASESTR(maker_id->name,pattern)) continue; chpr += printf("\t%-32.32s [%d]",maker_id->name,maker_id->id); chpr = newline(chpr); if(model_pattern) { if(*model_pattern) print_camera_models(maker_id->model,model_pattern); else print_camera_models(maker_id->model,NULL); } } } } } } /* Print the list of recognized models for given device make. If a */ /* non-null pattern is passed as argument, limit the output to models */ /* for which a case-insensitive substring match to the pattern occurs */ /* in the name, otherwise print all names. */ void print_camera_models(struct camera_id *model_names,char *pattern) { struct camera_id *maker_id; int chpr = 0; chpr = newline(0); for(maker_id = model_names ; maker_id && maker_id->name; ++maker_id) { if(pattern) { if(STRCASESTR(maker_id->name,pattern)) { chpr += printf("\t\t%-32.32s ",maker_id->name); chpr += printf("\t[%2d,%d]",maker_id->id, maker_id->noteversion); chpr = newline(chpr); } } else { chpr += printf("\t\t%-32.32s ",maker_id->name); chpr += printf("\t[%2d,%d]",maker_id->id, maker_id->noteversion); chpr = newline(chpr); } } } char * fake_strcasestr(char *string,char *pattern) { char *match = CNULL; int plen,slen; if(string && pattern) { plen = strlen(pattern); if(plen == 0) match = string; else { slen = strlen(string); while(plen <= slen) { if(strncasecmp(string,pattern,plen) == 0) { match = string; break; } ++string; --slen; } } } return(match); } exifprobe-2.0.1+git20170416-3c2b76/maker_fujifilm.c0000644000000000000000000003343013074742216017644 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_fujifilm.c,v 1.13 2005/07/24 22:56:26 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Fujitsu camera maker-specific routines (Fujifilm) */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Most of the information coded here is due to TsuruZoh Tachibanaya */ /* at: */ /* http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id fujifilm_model_id[]; /* Find the identifying number assigned to known Fujifilm camera */ /* models. This number is used to dispatch print and interpret */ /* routines approopriate to the current image. */ int fujifilm_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &fujifilm_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine for direct values in Fujifilm cameras, */ /* based upon model */ void print_fujifilm_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { int noteversion = 0; if(entry_ptr && (PRINT_VALUE)) { noteversion = getnoteversion(); switch(noteversion) { case 1: print_fujifilm1_makervalue(entry_ptr,make,model,prefix); fujifilm1_interpret_value(entry_ptr); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Fujifilm cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_fujifilm1_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for Fujifilm */ /* cameras. */ void print_fujifilm_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) { int noteversion = 0; if(entry_ptr) { noteversion = getnoteversion(); switch(noteversion) { default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; } } } /* Fujifilm-specific tagnames for makernotes. */ char * maker_fujifilm_tagname(unsigned short tag,int model) { char *tagname = (char *)0; int noteversion = 0; /* Should have to do this only once, and only for unrecognized */ /* models. If the model is recognized (or the user has forced a */ /* noteversion) noteversion will already be set. */ if((noteversion = getnoteversion()) == 0) { /* Only one tagset has been observed so far; it seems */ /* reasonable to default to that tagset (rather than none). */ noteversion = 1; setnoteversion(1); } switch(noteversion) { case 1: tagname = maker_fujifilm1_tagname(tag,model); break; default: break; } /* If no model-specific tag is found, check "generic" tags */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } char * maker_fujifilm1_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0000: tagname = "Version"; break; case 0x0010: tagname = "UniqueSerial"; break; /* Exiv2 */ case 0x1000: tagname = "Quality"; break; case 0x1001: tagname = "Sharpness"; break; case 0x1002: tagname = "WhiteBalance"; break; case 0x1003: tagname = "Color"; break; case 0x1004: tagname = "Tone"; break; case 0x1010: tagname = "FlashMode"; break; case 0x1011: tagname = "FlashStrength"; break; case 0x1020: tagname = "Macro"; break; case 0x1021: tagname = "FocusMode"; break; case 0x1030: tagname = "SlowSync"; break; case 0x1031: tagname = "PictureMode"; break; case 0x1100: tagname = "ContTake-Bracket"; break; case 0x1300: tagname = "BlurWarning"; break; case 0x1301: tagname = "FocusWarning"; break; case 0x1302: tagname = "AEWarning"; break; case 0x1401: tagname = "FilmMode"; break; /* Exiv2 */ case 0x1402: tagname = "DynamicRangeSettings"; break; /* Exiv2 */ case 0x1403: tagname = "DevelopmentDynamicRange"; break; /* Exiv2 */ case 0x1404: tagname = "FocalLengthMin"; break; case 0x1405: tagname = "FocalLengthMax"; break; case 0x1406: tagname = "MaxApertureAtMinFocal"; break; case 0x1407: tagname = "MaxApertureAtMaxFocal"; break; default: break; } setnotetagset(1); return(tagname); } /* Report the "meaning" of tag values found at offsets in a Fujifilm */ /* MakerNote IFD entry (not at an offset). */ void fujifilm1_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x1001: /* Sharpness */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Soft"); break; case 2: chpr += printf("Soft"); break; case 3: chpr += printf("Normal"); break; case 4: chpr += printf("Hard"); break; case 5: chpr += printf("Hard"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1002: /* White Balance */ print_startvalue(); /* I think we're looking at a bit mask here, but I have */ /* no way to check; this is the way Tachibanaya */ /* characterizes it. */ switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 256: chpr += printf("Daylight"); break; case 512: chpr += printf("Cloudy"); break; case 768: /* ???? */ printf("DaylightColor-Fluorescent"); break; case 769: /* ???? */ printf("DaywhiteColor-Fluorescent"); break; case 770: /* ???? */ printf("White-Fluorescent"); break; case 1024: chpr += printf("Incandescent"); break; case 3840: chpr += printf("Custom"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1003: /* Color Saturation */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Standard"); break; case 256: chpr += printf("High"); break; case 512: chpr += printf("Low"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1004: /* Tone */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Standard"); break; case 256: chpr += printf("High"); break; case 512: chpr += printf("Low"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1010: /* Flash Mode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("On"); break; case 2: chpr += printf("Off"); break; case 3: chpr += printf("Redeye"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1020: /* Macro Mode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1021: /* Focusing Mode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Manual"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1030: /* Slow Sync */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1031: /* Picture Mode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Portrait"); break; case 2: chpr += printf("Landscape"); break; case 4: chpr += printf("Sports"); break; case 5: chpr += printf("Night"); break; case 6: chpr += printf("Program Normal"); break; case 256: chpr += printf("Aperture Priority"); break; case 512: chpr += printf("Shutter Priority"); break; case 768: chpr += printf("Manual"); break; default: printred("undefined"); } print_endvalue(); break; case 0x1100: /* Continuous Take/Bracket */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1300: /* Blur Warning */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Ok"); break; case 1: chpr += printf("Blurred"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1301: /* Focus Warning */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Ok"); break; case 1: chpr += printf("Out of focus"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1302: /* AE Warning */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Ok"); break; case 1: chpr += printf("Overexposed"); break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } exifprobe-2.0.1+git20170416-3c2b76/readfile.c0000644000000000000000000006457713074742216016453 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: readfile.c,v 1.30 2005/07/24 18:15:28 alex Exp $"; #endif /* This file contains routines for reading specific value types with */ /* byte-swapping for integer values, specialized routines for */ /* strings, a file header decoder for various imagefile types, and a */ /* general IFD entry reader. */ /* The code needs to know the native byteorder of the machine, which */ /* is currently not autoconfigured. If not sure, look for a file like */ /* . "MOTOROLA" byteorder is "big-endian", "INTEL" */ /* byteorder is "little-endian". The code does not currently handle */ /* "pdp11" byteorder. */ #include #include #include #include #include #include #include "byteorder.h" #include "defs.h" #include "datadefs.h" #include "summary.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "ciff.h" #include "x3f.h" /* Read a short integer value in the expectation that it is a TIFF or */ /* JPEG header marker/tag. If a valid JPEG_SOI is found, we're done. */ /* If the value is a TIFF indicator, but the TIFF magic marker is not */ /* found, the magic number is then checked for a valid ORF or CIFF */ /* header. If the marker is not a recognized magic number/string, */ /* start over and check for a JP2 header box, or MRW, RAF, or X3F */ /* header. */ /* When appropriage, ciff, mrw, x3f or jp2 header structures are */ /* filled in and the fileheader magic set to indictate which is */ /* valid. */ /* The return is a fileheader structure containing an exifprobe */ /* private "magic number" and appropriate information about the file */ /* structure, if any. */ struct fileheader * read_imageheader(FILE *inptr,unsigned long offset) { static struct fileheader fileheader; struct ciff_header *ciffheader; struct jp2_header jp2header; struct mrw_header mrwheader; struct x3f_header *x3fheader; unsigned short marker,magic; unsigned char *type; unsigned long umagic,length; char *string; marker = 0; fileheader.probe_magic = PROBE_NOMAGIC; fileheader.file_marker = 0; fileheader.ciff_header = NULL; fileheader.x3f_header = NULL; memset(&fileheader.jp2_header,'\0',sizeof(struct jp2_header)); memset(&fileheader.mrw_header,'\0',sizeof(struct mrw_header)); if(inptr && !feof(inptr) && !ferror(inptr)) { /* The order of bytes for this read does not matter for TIFF, */ /* but must be high-byte first for JPEG. */ marker = read_ushort(inptr,TIFF_MOTOROLA,offset); switch(marker) { case TIFF_MOTOROLA: case TIFF_INTEL: if((magic = read_ushort(inptr,marker,HERE)) == TIFF_MAGIC) { fileheader.probe_magic = TIFF_MAGIC; fileheader.file_marker = marker; } else if(magic == ORF1_MAGIC) { fileheader.probe_magic = ORF1_MAGIC; fileheader.file_marker = marker; } else if(magic == ORF2_MAGIC) { fileheader.probe_magic = ORF2_MAGIC; fileheader.file_marker = marker; } else if(magic == RW2_MAGIC) { fileheader.probe_magic = RW2_MAGIC; fileheader.file_marker = marker; } else if((ciffheader = read_ciffheader(inptr,marker,offset))) { fileheader.file_marker = ciffheader->byteorder; fileheader.probe_magic = PROBE_CIFFMAGIC; fileheader.ciff_header = ciffheader; } else { fileheader.probe_magic = PROBE_NOMAGIC; fileheader.file_marker = 0; printf(" invalid TIFF magic (%#06x)",magic); printf(", apparent TIFF byteorder is "); print_byteorder(marker,1); (void)newline(0); } break; case JPEG_SOI: fileheader.probe_magic = JPEG_SOI; fileheader.file_marker = marker; break; default: fileheader.probe_magic = PROBE_NOMAGIC; fileheader.file_marker = 0; if(marker == 0) { /* check for jpeg2000 */ length = read_ulong(inptr,TIFF_MOTOROLA,offset); if(length == 12) { type = read_bytes(inptr,4,HERE); if(type && ((strncmp((char *)type,"jP\040\040 ",4) == 0) || (strncmp((char *)type,"jP\032\032 ",4) == 0))) { umagic = read_ulong(inptr,TIFF_MOTOROLA,HERE); if(umagic == 0x0d0a870a) { fileheader.probe_magic = PROBE_JP2MAGIC; fileheader.file_marker = 0; jp2header.length = length; jp2header.type = to_ulong(type,TIFF_MOTOROLA); if(!ferror(inptr) && !feof(inptr)) { jp2header.magic = umagic; fileheader.jp2_header = jp2header; } } } } } else if(marker == 0x004d) { umagic = read_ulong(inptr,TIFF_MOTOROLA,offset); if(umagic == 0x004d524d) { /* Minolta MRW */ mrwheader.mrw_magic = umagic; mrwheader.mrw_dataoffset = read_ulong(inptr,TIFF_MOTOROLA,HERE); if(!ferror(inptr) && !feof(inptr)) { fileheader.probe_magic = PROBE_MRWMAGIC; fileheader.mrw_header = mrwheader; } } } else if((marker == 0x5546) || (marker == 0x4655)) { /* Fujifile RAF */ string = read_string(inptr,offset,16); if(string && (strncmp(string,"FUJIFILMCCD-RAW ",16) == 0)) fileheader.probe_magic = PROBE_RAFMAGIC; } else if(marker == 0x464f) /* "FO" */ { /* Sigma/Foveon X3F */ umagic = read_ulong(inptr,TIFF_INTEL,offset); if(umagic == PROBE_X3FMAGIC) { x3fheader = read_x3fheader(inptr,offset); if(x3fheader) { fileheader.x3f_header = x3fheader; fileheader.probe_magic = PROBE_X3FMAGIC; } } } else { /* Unknown format */ fileheader.probe_magic = PROBE_NOMAGIC; fileheader.file_marker = 0; fileheader.ciff_header = NULL; fileheader.x3f_header = NULL; } break; } } return(&fileheader); } /* Read a generic TIFF IFD entry at the given offset, swapping */ /* byteorder of entry values as required. */ /* The return is a pointer to a static structure representing the */ /* entry. */ struct ifd_entry * read_ifd_entry(FILE *inptr,unsigned short byteorder,unsigned long offset) { static struct ifd_entry entry; unsigned char *value; memset(&entry,0,sizeof(struct ifd_entry)); if(inptr && !feof(inptr) && !ferror(inptr)) { entry.tag = read_ushort(inptr,byteorder,offset); entry.value_type = read_ushort(inptr,byteorder,HERE); entry.count = read_ulong(inptr,byteorder,HERE); value = read_bytes(inptr,4,HERE); if(value) { if((value_type_size(entry.value_type) * entry.count) > 4) entry.value = to_ulong(value,byteorder); /* offset */ else /* actual value(s) */ { entry.value = 0L; switch(entry.value_type) { case SSHORT: case SHORT: if(entry.count == 1) entry.value = to_ushort(value,byteorder); else { entry.value = to_ushort(value,byteorder); if(byteorder == TIFF_MOTOROLA) entry.value |= (((unsigned long)to_ushort(value + 2,byteorder) & 0xffff) << 16); else entry.value = (to_ushort(value + 2,byteorder) & 0xffff) | ((entry.value & 0xffff) << 16); } break; case BYTE: case SBYTE: case UNDEFINED: case ASCII: entry.value = *(unsigned long *)value; break; case LONG: case SLONG: default: entry.value = to_ulong(value,byteorder); break; } } } else entry.value = 0L; } return(&entry); } /* Read 2 bytes at the given offset and interpret them as an unsigned */ /* short integer value, swapping bytes as necessary. */ unsigned short read_ushort(FILE *inptr,unsigned short byteorder,unsigned long offset) { unsigned char rbuf[2]; unsigned long curoffset; unsigned short value = 0; int chpr = 0; if(inptr) { clearerr(inptr); curoffset = ftell(inptr); if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) { printred(" SEEK FAILED to read unsigned short at offset "); printf("%lu",offset); } else if(fread(rbuf,1,sizeof(unsigned short),inptr) == sizeof(unsigned short)) value = to_ushort(rbuf,byteorder); else { printred(" FAILED to read unsigned short value at offset "); if(offset == HERE) offset = curoffset; chpr += printf("%lu",offset); } if(ferror(inptr)) { chpr += printf(" ("); setcharsprinted(chpr); chpr = 0; printred(strerror(errno)); chpr += printf(")"); chpr = newline(chpr); } else if(feof(inptr)) { printred(" (EOF)"); chpr = newline(chpr); } } setcharsprinted(chpr); return(value); } /* read a single byte at the given offset and return it as an */ /* unsigned short value */ unsigned short read_ubyte(FILE *inptr,unsigned long offset) { unsigned char rbuf[1]; unsigned long curoffset; unsigned short value = 0; int chpr = 0; if(inptr) { clearerr(inptr); curoffset = ftell(inptr); if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) { printred(" SEEK FAILED to read unsigned byte at offset "); chpr += printf("%lu",offset); } else if(fread(rbuf,1,1,inptr) == 1) value = rbuf[0] & 0xff; else { if(offset == HERE) offset = curoffset; printred(" FAILED to read unsigned byte at offset "); chpr += printf("%lu",offset); } if(ferror(inptr)) { chpr += printf(" ("); setcharsprinted(chpr); chpr = 0; printred(strerror(errno)); chpr += printf(")"); chpr = newline(chpr); } else if(feof(inptr)) { printred(" (EOF)"); chpr = newline(chpr); } } setcharsprinted(chpr); return(value); } /* Read 4 bytes at the given offset and interpret as an unsigned long */ /* integer, swapping bytes as necessary */ /* NOTE: the routine *reads* a 4 byte number, but returns it as an */ /* unsigned long in the native machine size. */ unsigned long read_ulong(FILE *inptr,unsigned short byteorder,unsigned long offset) { unsigned char rbuf[4]; unsigned long curoffset; unsigned long value = 0; int chpr = 0; if(inptr) { clearerr(inptr); curoffset = ftell(inptr); if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) { printred(" SEEK FAILED to read unsigned 32bit integer at offset "); printf("%lu",offset); } else if(fread(rbuf,1,4,inptr) == 4) value = to_ulong(rbuf,byteorder); else { printred(" FAILED to read unsigned 32bit integer at offset "); if(offset == HERE) offset = curoffset; chpr += printf("%lu",offset); } if(ferror(inptr)) { chpr += printf(" ("); setcharsprinted(chpr); chpr = 0; printred(strerror(errno)); chpr += printf(")"); chpr = newline(chpr); } else if(feof(inptr)) { printred(" (EOF)"); chpr = newline(chpr); } } setcharsprinted(chpr); return(value); } float read_float(FILE *inptr,unsigned short byteorder,unsigned long offset) { float value = 0.0; unsigned long ulval; ulval = read_ulong(inptr,byteorder,offset); value = to_float(ulval); return(value); } /* Read 8 bytes at the given offset and interpret as a long long, */ /* swapping bytes as necessary. */ unsigned long long read_ulong64(FILE *inptr,unsigned short byteorder,unsigned long offset) { unsigned char rbuf[sizeof(double)]; unsigned long curoffset; unsigned long long value = 0; int chpr = 0; if(inptr) { clearerr(inptr); curoffset = ftell(inptr); if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) chpr += printf(" seek failed to offset %lu to read unsigned long\n", offset); else if(fread(rbuf,1,sizeof(long long),inptr) == sizeof(long long)) value = to_ulong64(rbuf,byteorder); else { printred(" FAILED to read unsigned 64bit integer at offset "); if(offset == HERE) offset = curoffset; chpr += printf("%lu\n",offset); } } setcharsprinted(chpr); return(value); } unsigned long long to_ulong64(unsigned char *buf,unsigned short byteorder) { unsigned long long value = 0; unsigned char swap[sizeof(long long)]; unsigned char *p; int i,size; if(buf) { p = buf; #ifdef NATIVE_BYTEORDER_BIGENDIAN if(byteorder == TIFF_INTEL) #else if(byteorder == TIFF_MOTOROLA) #endif { size = sizeof(long long); for(i = 0; i < size; ++i) swap[i] = buf[size - 1 - i]; p = swap; } value = *(long long *)p; } return(value); } /* Read 8 bytes at the given offset and interpret as a double, */ /* swapping bytes as necessary. */ double read_double(FILE *inptr,unsigned short byteorder,unsigned long offset) { unsigned char rbuf[sizeof(double)]; unsigned long curoffset; double value = 0.0; int chpr = 0; if(inptr) { clearerr(inptr); curoffset = ftell(inptr); if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) chpr += printf(" seek failed to offset %lu to read unsigned long\n", offset); else if(fread(rbuf,1,sizeof(double),inptr) == sizeof(double)) value = to_double(rbuf,byteorder); else { if(offset == HERE) offset = curoffset; PUSHCOLOR(RED); chpr += printf(" failed to read double value at offset %lu\n",offset); POPCOLOR(); } } setcharsprinted(chpr); return(value); } /* Read 'nbytes' of bytes at the given offset; no byte swapping. */ /* The result is a chunk of bytes...not a string. */ unsigned char * read_bytes(FILE *inptr,unsigned long nbytes,unsigned long offset) { static unsigned char rbuf[MAXBUFLEN]; unsigned long curoffset; unsigned char *value = NULL; int chpr = 0; memset(rbuf,0,MAXBUFLEN); if(inptr) { if(nbytes > MAXBUFLEN) { chpr += printf(" read %lu bytes would overrun buffer; truncating to %d\n", nbytes,MAXBUFLEN); nbytes = MAXBUFLEN; } if(nbytes) { if(inptr) /* ###%%% redundant; FIXME */ { clearerr(inptr); curoffset = ftell(inptr); if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) { printred(" SEEK FAILED to read unsigned bytes at offset "); chpr += printf("%lu",offset); } else { if(fread(rbuf,1,nbytes,inptr) == nbytes) value = rbuf; else { if(offset == HERE) offset = curoffset; PUSHCOLOR(RED); chpr += printf(" FAILED to read %lu unsigned bytes at offset ",nbytes); chpr += printf("%lu",offset); POPCOLOR(); } } if(ferror(inptr)) { chpr += printf(" ("); setcharsprinted(chpr); chpr = 0; printred(strerror(errno)); chpr += printf(")"); chpr = newline(chpr); } else if(feof(inptr)) { printred(" (EOF)"); chpr = newline(chpr); } } } } return(value); } /* convert a couple of bytes to an unsigned short integer in native */ /* byte order, swapping bytes if file byteorder differs. */ /* If byteorder is not TIFF_INTEL or TIFF_MOTOROLA, the native byte */ /* order is used. */ unsigned short to_ushort(unsigned char *buf,unsigned short byteorder) { unsigned short value = 0; if(buf) { value = *(unsigned short *)buf; #ifdef NATIVE_BYTEORDER_BIGENDIAN if(byteorder == TIFF_INTEL) value = (buf[1] << 8) | buf[0]; #else if(byteorder == TIFF_MOTOROLA) value = (buf[0] << 8) | buf[1]; #endif } return(value); } /* convert a bunch of bytes to an unsigned long integer in native */ /* byte order, swapping bytes if file byteorder differs. */ /* If byteorder is not TIFF_INTEL or TIFF_MOTOROLA, the native byte */ /* order is used. */ unsigned long to_ulong(unsigned char *buf,unsigned short byteorder) { u_int32_t value = 0; if(buf) { value = *(u_int32_t *)buf; #ifdef NATIVE_BYTEORDER_BIGENDIAN if(byteorder == TIFF_INTEL) #else if(byteorder == TIFF_MOTOROLA) #endif value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; } return((unsigned long)value); } /* convert a bunch of bytes to a 'float' value in native byte order, */ /* swapping bytes if file byteorder differs. If byteorder is not */ /* TIFF_INTEL or TIFF_MOTOROLA, the native byte order is used. */ /* This is pretty primitive; it assumes that the native floating */ /* point format is the same as the floating point format written to */ /* the image file, probably IEEE as required by the TIFF6 */ /* specification. See 'libtiff' for some conversion routines. */ float to_float(unsigned long uval) { float value = 0.0; unsigned long *uval_ptr = &uval; value = *(float *)uval_ptr; return(value); } /* convert a bunch of bytes to a 'double' value in native byte order, */ /* swapping bytes if file byteorder differs. If byteorder is not */ /* TIFF_INTEL or TIFF_MOTOROLA, the native byte order is used. */ /* This is pretty primitive; it assumes that the native floating */ /* point format is the same as the floating point format written to */ /* the image file, probably IEEE as required by the TIFF6 */ /* specification. See 'libtiff' for some conversion routines. */ double to_double(unsigned char *buf,unsigned short byteorder) { double value = 0.0; unsigned char swap[sizeof(double)]; unsigned char *p; int i,size; if(buf) { p = buf; #ifdef NATIVE_BYTEORDER_BIGENDIAN if(byteorder == TIFF_INTEL) #else if(byteorder == TIFF_MOTOROLA) #endif { size = sizeof(double); for(i = 0; i < size; ++i) swap[i] = buf[size - 1 - i]; p = swap; } value = *(double *)p; } return(value); } /* Read a few bytes at 'offset' which are expected to be a JPEG APPn */ /* id string, where 'n' is given as an argument. */ char * read_appstring(FILE *inptr,unsigned short apptype,unsigned long offset) { unsigned long length; char *appstring = NULLSTRING; if(inptr) { switch(apptype) { case JPEG_APP0: length = 32; /* should be 5; allow for garbage */ break; case JPEG_APP1: case JPEG_APP2: length = 32; /* should be 5; allow for garbage */ break; default: length = 32; break; } if(length) appstring = read_string(inptr,offset,length); } return(appstring); } /* Read an ascii string, up to a null byte or 'max_bytes', at */ /* 'offset' relative to the beginning of the file. */ /* Returns the string in static storage. Use it or lose it. */ char * read_string(FILE *inptr,unsigned long offset,unsigned long max_bytes) { static char stringbuf[MAXBUFLEN]; unsigned long curoffset; char *bufp; int nread = 0; int chpr = 0; bufp = stringbuf; *bufp = '\0'; if(inptr) { clearerr(inptr); curoffset = ftell(inptr); if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) { printred(" SEEK FAILED to read ascii string at offset "); chpr += printf("%lu",offset); } else if(max_bytes > 0) { if(max_bytes > MAXBUFLEN) max_bytes = MAXBUFLEN - 2; while((nread < max_bytes) && (*bufp = fgetc(inptr)) && !feof(inptr) && !ferror(inptr) && isascii(*bufp++)) { ++nread; } *bufp = '\0'; if(feof(inptr) || ferror(inptr)) { if(offset == HERE) offset = curoffset; PUSHCOLOR(RED); chpr += printf(" FAILED to read character at offset "); chpr += printf("%lu",offset); POPCOLOR(); if(ferror(inptr)) { chpr += printf(" ("); setcharsprinted(chpr); chpr = 0; printred(strerror(errno)); chpr += printf(")"); chpr = newline(chpr); } else if(feof(inptr)) { printred(" (EOF)"); chpr = newline(chpr); } } } } setcharsprinted(chpr); return(stringbuf); } int ateof(FILE *inptr) { int atend = 0; if(feof(inptr)) atend++; else if(fgetc(inptr) == -1) atend++; return(atend); } /* Get the size of the file open on the argument stream, by seeking */ /* to the end and enquiring of the resulting offset. Return the file */ /* offset to its original location. If anything goes wrong, return 0, */ /* indicating failure (or a zero length file). */ unsigned long get_filesize(FILE *inptr) { unsigned long size = 0L; long current_offset; if(inptr) { clearerr(inptr); /* move back here after getting the size */ current_offset = ftell(inptr); if(fseek(inptr,0L,SEEK_END) == 0) { size = ftell(inptr); if(fseek(inptr,current_offset,SEEK_SET) != 0) clearerr(inptr); /* silently */ } else size = 0L; } return(size); } exifprobe-2.0.1+git20170416-3c2b76/mrw_extern.h0000644000000000000000000000324113074742216017054 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: mrw_extern.h,v 1.1 2005/05/25 00:53:56 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef MRW_EXTERN_INCLUDED #define MRW_EXTERN_INCLUDED /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Minolta MRW-specific external definitions */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ extern int print_mrw_header(struct fileheader *,unsigned long); extern unsigned long process_mrw(FILE *,unsigned long,unsigned long, unsigned long, struct image_summary *, char *,int); extern unsigned long process_prd(FILE *,unsigned long,unsigned long, struct image_summary *,int); extern unsigned long process_wbg(FILE *,unsigned long,unsigned long, struct image_summary *,int); extern unsigned long process_rif(FILE *,unsigned long,unsigned long, struct image_summary *,int); #endif /* MRW_EXTERN_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/toshiba_datadefs.h0000644000000000000000000000172513074742216020153 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: toshiba_datadefs.h,v 1.2 2005/06/21 15:20:41 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef TOSHIBA_DATADEFS_INCLUDED #define TOSHIBA_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id toshiba_model_id[] = { { "PDR-3300", 8, TOSHIBA_PDR_3300, 1, 1 }, { 0, 0, 0, 0, 0} }; #endif /* TOSHIBA_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/tiffeptags.h0000644000000000000000000000430713074742216017022 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: tiffeptags.h,v 1.2 2003/01/30 20:47:31 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* All tags defined in TIFFEP spec not defined in TIFF6 or EXIF specs */ #ifndef TIFFEP_TAGS_INCLUDED #define TIFFEP_TAGS_INCLUDED #define TIFFEPTAG_CFARepeatPatternDim 0x828D /* 33421 */ #define TIFFEPTAG_CFAPattern 0x828E /* 33422 */ #define TIFFEPTAG_BatteryLevel 0x828F /* 33423 */ #define TIFFEPTAG_IPTC_NAA 0x83BB /* 33723 */ #define TIFFEPTAG_InterColorProfile3 0x8773 /* 34675 */ #define TIFFEPTAG_Interlace 0x8829 /* 34857 */ #define TIFFEPTAG_TimeZoneOffset 0x882A /* 34858 */ #define TIFFEPTAG_SelfTimerMode 0x882B /* 34859 */ #define TIFFEPTAG_FlashEnergy 0x920B /* 37387 */ #define TIFFEPTAG_SpatialFrequencyResponse 0x920C /* 37388 */ #define TIFFEPTAG_Noise 0x920D /* 37389 */ #define TIFFEPTAG_FocalPlaneXResolution 0x920E /* 37390 */ #define TIFFEPTAG_FocalPlaneYResolution 0x920F /* 37391 */ #define TIFFEPTAG_FocalPlaneResolutionUnit 0x9210 /* 37392 */ #define TIFFEPTAG_ImageNumber 0x9211 /* 37393 */ #define TIFFEPTAG_SecurityClassification 0x9212 /* 37394 */ #define TIFFEPTAG_ImageHistory 0x9213 /* 37395 */ #define TIFFEPTAG_ExposureIndex 0x9215 /* 37397 */ #define TIFFEPTAG_TIFF_EPStandardID 0x9216 /* 37398 */ #define TIFFEPTAG_SensingMethod 0x9217 /* 37399 */ #endif exifprobe-2.0.1+git20170416-3c2b76/x3f.c0000644000000000000000000015433413074742216015367 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: x3f.c,v 1.7 2005/07/24 20:31:30 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Sigma/FOVEON x3f routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* See http://www.sd9.org.uk/X3F_Format.pdf */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "x3f.h" #include "maker_extern.h" /* Read and record the X3F file header */ struct x3f_header * read_x3fheader(FILE *inptr,unsigned long offset) { static struct x3f_header header; struct x3f_header *headerptr = NULL; unsigned long xmagic; unsigned char *bytearray; memset(&header,0,sizeof(struct x3f_header)); if(inptr) { xmagic = read_ulong(inptr,TIFF_INTEL,offset); if(xmagic == PROBE_X3FMAGIC) { header.magic = xmagic; header.version_major = read_ushort(inptr,TIFF_INTEL,HERE); header.version_minor = read_ushort(inptr,TIFF_INTEL,HERE); bytearray = read_bytes(inptr,16,HERE); if(bytearray) memcpy(header.unique_id,bytearray,16); header.mark_bits = read_ulong(inptr,TIFF_INTEL,HERE); header.image_width = read_ulong(inptr,TIFF_INTEL,HERE); header.image_height = read_ulong(inptr,TIFF_INTEL,HERE); header.image_rotation = read_ulong(inptr,TIFF_INTEL,HERE); if(header.version_minor >= 1) { /* this is a string, e.g. "AUTO\0" */ bytearray = read_bytes(inptr,32,HERE); if(bytearray) memcpy(header.white_balance,bytearray,32); bytearray = read_bytes(inptr,32,HERE); if(bytearray) memcpy(header.extended_data_types,bytearray,32); bytearray = read_bytes(inptr,128,HERE); if(bytearray) memcpy(header.extended_data_values,bytearray,128); } headerptr = &header; } } return(headerptr); } /* Print X3f header information if options permit. Return 0 if */ /* information is valid to print, or -1 if the header is invalid */ int print_x3f_header(FILE *inptr,struct fileheader *header,unsigned long section_id) { struct x3f_header *x3fheader = NULL; int status = -1; int chpr = 0; int i; if(header) { if(header->x3f_header) { x3fheader = header->x3f_header; if(header->probe_magic == PROBE_X3FMAGIC) { if(Print_options & section_id) { chpr += printf("%4.4s (%#06lx) version %2u.%-2u, id ", (char *)&(x3fheader->magic), x3fheader->magic, x3fheader->version_major, x3fheader->version_minor); chpr += printf("%#02x ",x3fheader->unique_id[0] & 0xff); for(i = 0; i < 16; ++i) chpr += printf("%02x ",x3fheader->unique_id[i] & 0xff); chpr = newline(chpr); if(x3fheader->version_minor >= 1) { print_tag_address(ENTRY,24,MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("X3f.Header."); chpr += printf("MarkBits"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 8); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%#06lx",x3fheader->mark_bits); chpr = newline(chpr); } print_tag_address(ENTRY,28,MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("X3f.Header."); chpr += printf("ImageWidth"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 10); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",x3fheader->image_width); chpr = newline(chpr); print_tag_address(ENTRY,32,MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("X3f.Header."); chpr += printf("ImageHeight"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 11); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",x3fheader->image_height); chpr = newline(chpr); print_tag_address(ENTRY,36,MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("X3f.Header."); chpr += printf("ImageRotation"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 13); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",x3fheader->image_rotation); chpr = newline(chpr); if(x3fheader->version_minor >= 1) { print_tag_address(ENTRY,40,MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("X3f.Header."); chpr += printf("WhiteBalance"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 12); chpr += printf(" = "); } } if((PRINT_VALUE)) show_string(x3fheader->white_balance,32,0); chpr = newline(chpr); print_tag_address(ENTRY,72,MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("X3f.Header."); chpr += printf("ExtendedDataTypes"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 17); chpr += printf(" = "); } } if((PRINT_VALUE)) print_ubytes(inptr,32,72); chpr = newline(chpr); print_tag_address(ENTRY,104,MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("X3f.Header."); chpr += printf("ExtendedDataValues"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 19); chpr += printf(" = "); } } if((PRINT_VALUE)) print_ulong(inptr,32,TIFF_INTEL,104); chpr = newline(chpr); } print_tag_address(SECTION,104 + 128 - 1,0,"@"); chpr += printf(""); chpr = newline(chpr); } status = 0; } else if(Print_options & section_id) { chpr += printf("INVALID X3F IDENTIFIER "); print_magic(header->probe_magic,4); } } else fprintf(stderr,"%s: null x3fheader to print_x3f_header()\n",Progname); } else fprintf(stderr,"%s: null fileheader to print_x3f_header()\n",Progname); chpr = newline(chpr); return(status); } /* Process the remainder of an X3F file, after the header has been */ /* read and validated. Returns the maximum offset reached in */ /* processing, which is normally end of file. */ unsigned long process_x3f(FILE *inptr,struct fileheader *header,unsigned long fileoffset_base, struct image_summary *summary_entry, char *parent_name,int level,int indent) { struct x3f_header *x3fheader; unsigned long max_offset = 0UL; unsigned short byteorder = 0; unsigned long directory_pointer = 0UL; if(inptr) { if(header) { if(header->x3f_header) { x3fheader = header->x3f_header; /* X3F is always little-endian; nonetheless, pass it */ /* as an argument to lower-level functions. Just set */ /* it here. */ byteorder = TIFF_INTEL; if(fseek(inptr,-4L,SEEK_END) == 0) directory_pointer = ftell(inptr); if(ferror(inptr) == 0) { max_offset = process_x3f_dir(inptr,byteorder,x3fheader, directory_pointer,summary_entry, parent_name,level,indent); if(max_offset > 0L) max_offset += 4; } else fprintf(stderr,"%s: cannot read directory offset\n",Progname); } else fprintf(stderr,"%s: null x3fheader to process_x3f()\n",Progname); } else fprintf(stderr,"%s: null fileheader to process_x3f()\n",Progname); } else fprintf(stderr,"%s: no open file pointer to read Print Image data\n", Progname); return(max_offset); } /* Find the directory at the end of the file and process it. Report */ /* the detail data first, then show the directory itself. */ unsigned long process_x3f_dir(FILE *inptr,unsigned short byteorder,struct x3f_header *x3fheader, unsigned long directory_pointer, struct image_summary *summary_entry, char *parent_name,int level,int indent) { struct x3f_direntry *entry; unsigned long directory_offset = 0UL; unsigned long section_id; unsigned long max_dir_offset = 0L; unsigned long entry_offset,next_entry_offset; unsigned long num_entries; unsigned short version_major; unsigned short version_minor; int i; int chpr = 0; directory_offset = read_ulong(inptr,byteorder,directory_pointer); section_id = read_ulong(inptr,byteorder,directory_offset); version_minor = read_ushort(inptr,byteorder,HERE); version_major = read_ushort(inptr,byteorder,HERE); num_entries = read_ulong(inptr,byteorder,HERE); entry = NULL; entry_offset = ftell(inptr); /* Print the entries first, in order */ for(i = 0; i < num_entries; ++i) { entry = read_x3f_direntry(inptr,byteorder,entry,entry_offset); if(ferror(inptr)) { fprintf(stderr,"%s: error reading directory entry at %lu\n", Progname,entry_offset); break; } if(entry == NULL) { fprintf(stderr,"%s: null entry %d\n",Progname,i); break; } next_entry_offset = ftell(inptr); process_x3f_direntry(inptr,byteorder,entry,entry_offset, summary_entry,parent_name,i,indent); entry_offset = next_entry_offset; } chpr = newline(chpr); /* Now show the directory itself */ if((PRINT_SECTION)) { print_tag_address(SECTION,directory_offset,indent,"@"); chpr += printf(" version %d.%d id \"%4.4s\", %lu entries", version_major,version_minor, (char *)§ion_id,num_entries); } chpr = newline(chpr); entry_offset = directory_offset + 12; for(i = 0; i < num_entries; ++i) { entry = read_x3f_direntry(inptr,byteorder,entry,entry_offset); if(ferror(inptr)) { fprintf(stderr,"%s: error reading directory entry at %lu\n", Progname,entry_offset); break; } if(entry == NULL) { fprintf(stderr,"%s: null entry %d\n",Progname,i); break; } next_entry_offset = ftell(inptr); print_x3f_direntry(inptr,entry,entry_offset, parent_name,i,indent); entry_offset = next_entry_offset; } max_dir_offset = ftell(inptr); if((PRINT_SECTION)) { print_tag_address(SECTION,max_dir_offset - 1,indent,"@"); chpr += printf(""); chpr = newline(chpr); } print_tag_address(ENTRY,directory_pointer,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%s","DirectoryOffset"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 15); chpr += printf(" = "); } } if((PRINT_VALUE)) { if(PRINT_BOTH_OFFSET) chpr += printf("@%#lx=%lu",directory_offset,directory_offset); else if(PRINT_HEX_OFFSET) chpr += printf("@%#lx",directory_offset); else chpr += printf("@%lu",directory_offset); } chpr = newline(chpr); if(entry) free(entry); return(max_dir_offset); } /* Process a directory entry, representing one section of the file. */ /* An entry number is added to the section id, so that sections with */ /* the same name (e.g. IMGA) can be identified, especially in LIST */ /* mode. */ void process_x3f_direntry(FILE *inptr,unsigned short byteorder,struct x3f_direntry *entry, unsigned long offset,struct image_summary *summary_entry, char *parent_name,int entry_num,int indent) { struct x3f_imag_header *imag_header; struct x3f_prop_header *prop_header; struct x3f_camf_header *camf_header; unsigned long data_offset = 0UL; unsigned long data_length = 0UL; char *dirname = CNULL; int chpr = 0; if(entry) { if((PRINT_SECTION)) { print_tag_address(SECTION,entry->data_offset,indent,"@"); chpr += printf("<%4.4s:%d> (%#06lx)",(char *)&entry->data_type,entry_num,entry->data_type); chpr += printf(" length %lu",entry->data_length); chpr = newline(chpr); } switch(entry->data_type) { case X3F_IMAG: dirname = splice(parent_name,".","IMAG"); imag_header = read_x3f_imag_header(inptr,byteorder,entry->data_offset); data_offset = display_x3f_imag_header(entry,imag_header,dirname,entry_num, indent + MEDIUMINDENT); data_length = entry->data_length - (data_offset - entry->data_offset); if((summary_entry == NULL) || summary_entry->entry_lock) summary_entry = new_summary_entry(summary_entry,FILEFMT_X3F,IMGFMT_X3F); if(summary_entry) { switch(imag_header->image_type) { case 2: summary_entry->subfiletype = REDUCED_RES_TYPE; break; case 3: /* observed; spec doesn't say */ summary_entry->subfiletype = PRIMARY_TYPE; break; default: /* assume this; spec doesn't say */ summary_entry->subfiletype = REDUCED_RES_TYPE; break; } switch(imag_header->image_format) { case 3: summary_entry->imagesubformat = IMGSUBFMT_RGB; break; case 11: summary_entry->imagesubformat = IMGSUBFMT_HUFF_COMPRESSED_RGB; break; case 18: summary_entry->imagesubformat = IMGSUBFMT_JPEG_COMPRESSED_RGB; break; case 6: summary_entry->imagesubformat = IMGSUBFMT_X3F_COMPRESSED; break; default: summary_entry->imagesubformat = IMGSUBFMT_X3F_UNSPECIFIED; break; } summary_entry->imageformat = IMGFMT_X3F; summary_entry->pixel_width = imag_header->image_width; summary_entry->pixel_height = imag_header->image_height; summary_entry->offset = data_offset; summary_entry->length = data_length; summary_entry->entry_lock = lock_number(summary_entry); } if((PRINT_SECTION)) { print_tag_address(SECTION,data_offset,indent + MEDIUMINDENT,"@"); chpr += printf(" length %lu",data_length); chpr = newline(chpr); dumpsection(inptr,data_offset,data_length,indent + LARGEINDENT); print_tag_address(SECTION,entry->data_offset + entry->data_length - 1, indent + MEDIUMINDENT,"@"); chpr += printf(""); } else if((LIST_MODE)) { print_tag_address(ENTRY,data_offset,indent + MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.",dirname,entry_num); else chpr += printf("IMAG:%d.",entry_num); chpr += printf("Data"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 7); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("@%lu:%lu",data_offset,data_length); } chpr = newline(chpr); break; case X3F_IMA2: dirname = splice(parent_name,".","IMA2"); imag_header = read_x3f_imag_header(inptr,byteorder,entry->data_offset); data_offset = display_x3f_imag_header(entry,imag_header,dirname,entry_num, indent + MEDIUMINDENT); data_length = entry->data_length - (data_offset - entry->data_offset); if((summary_entry == NULL) || summary_entry->entry_lock) summary_entry = new_summary_entry(summary_entry,FILEFMT_X3F,IMGFMT_X3F); if(summary_entry) { switch(imag_header->image_type) { case 2: summary_entry->subfiletype = REDUCED_RES_TYPE; break; case 3: /* observed; spec doesn't say */ summary_entry->subfiletype = PRIMARY_TYPE; break; default: /* assume this; spec doesn't say */ summary_entry->subfiletype = REDUCED_RES_TYPE; break; } switch(imag_header->image_format) { case 3: summary_entry->imagesubformat = IMGSUBFMT_RGB; break; case 11: summary_entry->imagesubformat = IMGSUBFMT_HUFF_COMPRESSED_RGB; break; case 18: summary_entry->imagesubformat = IMGSUBFMT_JPEG_COMPRESSED_RGB; break; case 6: /* No idea how "raw" this is, or how it's */ /* compressed/encoded */ summary_entry->imagesubformat = IMGSUBFMT_X3F_COMPRESSED; break; default: summary_entry->imagesubformat = IMGSUBFMT_X3F_UNSPECIFIED; break; } summary_entry->imageformat = IMGFMT_X3F; summary_entry->pixel_width = imag_header->image_width; summary_entry->pixel_height = imag_header->image_height; summary_entry->offset = data_offset; summary_entry->length = data_length; summary_entry->entry_lock = lock_number(summary_entry); } if((PRINT_SECTION)) { print_tag_address(SECTION,data_offset,indent + MEDIUMINDENT,"@"); chpr += printf(" length %lu",data_length); chpr = newline(chpr); dumpsection(inptr,data_offset,data_length,indent + LARGEINDENT); print_tag_address(SECTION,entry->data_offset + entry->data_length - 1, indent + MEDIUMINDENT,"@"); chpr += printf(""); } else if((LIST_MODE)) { print_tag_address(ENTRY,data_offset,indent + MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.",dirname,entry_num); else chpr += printf("IMA2:%d.",entry_num); chpr += printf("Data"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 7); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("@%lu:%lu",data_offset,data_length); } chpr = newline(chpr); break; case X3F_PROP: dirname = splice(parent_name,".","PROP"); prop_header = read_x3f_prop_header(inptr,byteorder,entry->data_offset); data_offset = display_x3f_prop_header(entry,prop_header,dirname,entry_num, indent + MEDIUMINDENT); data_length = entry->data_length - (data_offset - entry->data_offset); process_x3f_props(inptr,byteorder,data_offset,data_length, prop_header->char_format,dirname, prop_header->num_entries, indent + MEDIUMINDENT); break; case X3F_CAMF: dirname = splice(parent_name,".","CAMF"); camf_header = read_x3f_camf_header(inptr,byteorder,entry->data_offset); data_offset = display_x3f_camf_header(entry,camf_header,dirname,entry_num, indent + MEDIUMINDENT); data_length = entry->data_length - (data_offset - entry->data_offset); if((PRINT_SECTION)) { print_tag_address(SECTION,data_offset,indent + MEDIUMINDENT,"@"); chpr += printf(" length %lu",data_length); chpr = newline(chpr); dumpsection(inptr,data_offset,data_length,indent + LARGEINDENT); print_tag_address(SECTION,entry->data_offset + entry->data_length - 1, indent + MEDIUMINDENT,"@"); chpr += printf(""); } else if((LIST_MODE)) { print_tag_address(ENTRY,data_offset,indent + MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.",dirname,entry_num); else chpr += printf("CAMF:%d.",entry_num); chpr += printf("Data"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 7); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("@%lu:%lu",data_offset,data_length); } chpr = newline(chpr); break; default: if((PRINT_SECTION)) { print_tag_address(SECTION,entry->data_offset,indent + MEDIUMINDENT,"@"); chpr += printf("<%4.4s> length %lu",(char *)&entry->section_id,entry->data_length); chpr = newline(chpr); dumpsection(inptr,data_offset,data_length,indent + LARGEINDENT); print_tag_address(SECTION,entry->data_offset + entry->data_length - 1, indent + MEDIUMINDENT,"@"); chpr += printf("",(char *)&entry->section_id); } else if((LIST_MODE)) { print_tag_address(ENTRY,data_offset,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.",dirname,entry_num); else chpr += printf("%4.4s:%d.",(char *)&entry->section_id,entry_num); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 7); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("@%lu:%lu",entry->data_offset,entry->data_length); } chpr = newline(chpr); break; } if((PRINT_SECTION)) { print_tag_address(SECTION,entry->data_offset + entry->data_length - 1,indent,"@"); chpr += printf("",(char *)&entry->data_type,entry_num); chpr += newline(chpr); } if(dirname) free(dirname); } } void print_x3f_direntry(FILE *inptr,struct x3f_direntry *entry,unsigned long offset, char *parent_name,int entry_num,int indent) { int chpr = 0; if(entry) { print_tag_address(ENTRY,offset,indent + MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%4.4s:%-2d",(char *)&entry->data_type,entry_num); if((PRINT_VALUE)) putindent(X3FTAGWIDTH - 7); } if((PRINT_VALUE)) { chpr += printf(" = "); chpr += printf("@%lu:%lu",entry->data_offset,entry->data_length); } chpr += newline(chpr); } } struct x3f_direntry * read_x3f_direntry(FILE *inptr,unsigned short byteorder,struct x3f_direntry *entry, unsigned long offset) { if(inptr) { if(entry == NULL) entry = (struct x3f_direntry *)malloc(sizeof(struct x3f_direntry)); if(entry) { memset(entry,0,sizeof(struct x3f_direntry)); entry->data_offset = read_ulong(inptr,byteorder,offset); entry->data_length = read_ulong(inptr,byteorder,HERE); entry->data_type = read_ulong(inptr,byteorder,HERE); } } else entry = (struct x3f_direntry *)0; return(entry); } struct x3f_imag_header * read_x3f_imag_header(FILE *inptr,unsigned short byteorder,unsigned long offset) { static struct x3f_imag_header header; struct x3f_imag_header *headerptr= (struct x3f_imag_header *)0; if(!feof(inptr) && !ferror(inptr)) { header.section_id = read_ulong(inptr,byteorder,offset); header.version_minor = read_ushort(inptr,byteorder,HERE); header.version_major = read_ushort(inptr,byteorder,HERE); header.image_type = read_ulong(inptr,byteorder,HERE); header.image_format = read_ulong(inptr,byteorder,HERE); header.image_width = read_ulong(inptr,byteorder,HERE); header.image_height = read_ulong(inptr,byteorder,HERE); header.image_rowsize = read_ulong(inptr,byteorder,HERE); if(!feof(inptr) && !ferror(inptr)) headerptr = &header; } return(headerptr); } struct x3f_camf_header * read_x3f_camf_header(FILE *inptr,unsigned short byteorder,unsigned long offset) { static struct x3f_camf_header header; struct x3f_camf_header *headerptr = (struct x3f_camf_header *)0; if(!feof(inptr) && !ferror(inptr)) { header.section_id = read_ulong(inptr,byteorder,offset); header.version_minor = read_ushort(inptr,byteorder,HERE); header.version_major = read_ushort(inptr,byteorder,HERE); header.item1 = read_ulong(inptr,byteorder,HERE); header.item2 = read_ulong(inptr,byteorder,HERE); header.item3 = read_ulong(inptr,byteorder,HERE); header.item4 = read_ulong(inptr,byteorder,HERE); header.item5 = read_ulong(inptr,byteorder,HERE); if(!feof(inptr) && !ferror(inptr)) headerptr = &header; } return(headerptr); } struct x3f_prop_header * read_x3f_prop_header(FILE *inptr,unsigned short byteorder,unsigned long offset) { static struct x3f_prop_header header; struct x3f_prop_header *headerptr = (struct x3f_prop_header *)0; if(!feof(inptr) && !ferror(inptr)) { header.section_id = read_ulong(inptr,byteorder,offset); header.version_minor = read_ushort(inptr,byteorder,HERE); header.version_major = read_ushort(inptr,byteorder,HERE); header.num_entries = read_ulong(inptr,byteorder,HERE); header.char_format = read_ulong(inptr,byteorder,HERE); header.reserved = read_ulong(inptr,byteorder,HERE); header.entry_length = read_ulong(inptr,byteorder,HERE); if(!feof(inptr) && !ferror(inptr)) headerptr = &header; } return(headerptr); } unsigned long display_x3f_imag_header(struct x3f_direntry *direntry,struct x3f_imag_header *header, char *dirname,int entry_num,int indent) { int chpr = 0; print_tag_address(ENTRY,direntry->data_offset,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","SectionId"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 9); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%4.4s",(char *)&header->section_id); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 4,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","Version"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 7); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%u.%u",header->version_major,header->version_minor); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 8,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","ImageType"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 9); chpr += printf(" = "); } } if((PRINT_VALUE)) { chpr += printf("%-2lu",header->image_type); switch(header->image_type) { case 2: chpr += printf(" = \"Preview\""); break; case 3: chpr += printf(" = \"Primary\""); break; default: break; } } chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 12,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","ImageFormat"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 11); chpr += printf(" = "); } } if((PRINT_VALUE)) { chpr += printf("%-2lu",header->image_format); switch(header->image_format) { case 3: chpr += printf(" = \"uncompressed RGB\""); break; case 6: chpr += printf(" = \"compressed RAW\""); break; case 11: chpr += printf(" = \"Huffman compressed RGB\""); break; case 18: chpr += printf(" = \"JPEG compressed RGB\""); break; default: break; } } chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 16,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","ImageWidth"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 10); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",header->image_width); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 20,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","ImageHeight"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 11); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",header->image_height); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 24,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","RowSize"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 7); chpr += printf(" = "); } } if((PRINT_VALUE)) { chpr += printf("%lu",header->image_rowsize); if(header->image_rowsize == 0) chpr += printf(" = \"variable length\""); } chpr = newline(chpr); return(direntry->data_offset + 28); } unsigned long display_x3f_prop_header(struct x3f_direntry *direntry,struct x3f_prop_header *header, char *dirname,int entry_num,int indent) { int chpr = 0; print_tag_address(ENTRY,direntry->data_offset,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","SectionId"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 9); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%4.4s",(char *)&header->section_id); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 4,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","Version"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 7); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%u.%u",header->version_major,header->version_minor); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 8,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","Entries"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 7); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",header->num_entries); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 12,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","CharFormat"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 10); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",header->char_format); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 16,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","RESERVED"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 8); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",header->reserved); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 20,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","SectionLength"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 13); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",header->entry_length); chpr = newline(chpr); return(direntry->data_offset + 24); } unsigned long display_x3f_camf_header(struct x3f_direntry *direntry,struct x3f_camf_header *header, char *dirname,int entry_num,int indent) { int chpr = 0; print_tag_address(ENTRY,direntry->data_offset,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","SectionId"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 9); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%4.4s",(char *)&header->section_id); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 4,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","Version"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 7); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%u.%u",header->version_major,header->version_minor); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 8,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","Item1"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 5); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",header->item1); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 12,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","Item2"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 5); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",header->item2); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 16,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","Item3"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 5); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%4.4s",(char *)&header->item3); chpr = newline(chpr); print_tag_address(ENTRY,direntry->data_offset + 20,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s:%d.Header.",dirname,entry_num); chpr += printf("%s","Item4"); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 5); chpr += printf(" = "); } } if((PRINT_VALUE)) chpr += printf("%lu",header->item4); chpr = newline(chpr); /* Not sure how long the header is... CAMF is not described in */ /* the public X3F spec. */ /* Assume the header is same length as PROP for the purposes of */ /* dumping the data section */ return(direntry->data_offset + 24); } /* Process the property section. After the header, the section starts */ /* with an index of offsets to each name and value. The actual names */ /* and values follow. */ unsigned long process_x3f_props(FILE *inptr,unsigned short byteorder,unsigned long data_offset, unsigned long data_length,unsigned long char_format, char *dirname,unsigned long num_entries,int indent) { unsigned long max_offset = 0UL; unsigned long name_offset = 0UL; unsigned long value_offset = 0UL; unsigned long offset = 0UL; unsigned long property_offset = 0UL; unsigned long index_length = 0UL; unsigned long list_data_length = 0UL; int chpr = 0; int i; if(inptr) { clearerr(inptr); offset = data_offset; property_offset = data_offset + (num_entries * 8); index_length = num_entries * 8; list_data_length = data_length - index_length; if((PRINT_SECTION)) { print_tag_address(SECTION,data_offset,indent,"@"); chpr += printf(" %ld entries, length %lu",num_entries,data_length); chpr = newline(chpr); print_tag_address(SECTION,data_offset,indent + SMALLINDENT,"@"); chpr += printf(" %ld entries, length %lu",num_entries,index_length); chpr = newline(chpr); } /* Print the index of name/value offsets first */ for(i = 0; i < num_entries; ++i) { if(fseek(inptr,offset,SEEK_SET) == 0) { name_offset = read_ulong(inptr,byteorder,HERE); name_offset *= 2; if(feof(inptr) || ferror(inptr)) { PUSHCOLOR(RED); chpr += printf(" FAILED to read Property List name %d at offset %lu",i,offset); POPCOLOR(); break; } value_offset = read_ulong(inptr,byteorder,HERE); value_offset *= 2; if(feof(inptr) || ferror(inptr)) { PUSHCOLOR(RED); chpr += printf(" FAILED to read Property List value %d at offset %lu",i,offset + 4); POPCOLOR(); break; } /* Show the name/value offsets, even in LIST mode */ print_tag_address(ENTRY,offset,indent + MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.Index.",dirname); chpr += printf("NameOffset.%-2d",i); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 15); chpr += printf(" = "); } } if((PRINT_VALUE)) { chpr += printf("@%lu",name_offset + property_offset); if((PRINT_RAW_VALUES)) chpr += printf(" (%lu)",name_offset); } chpr = newline(chpr); print_tag_address(ENTRY,offset + 4,indent + MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.Index.",dirname); chpr += printf("ValueOffset.%-2d",i); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 16); chpr += printf(" = "); } } if((PRINT_VALUE)) { chpr += printf("@%lu",value_offset + property_offset); if((PRINT_RAW_VALUES)) chpr += printf(" (%lu)",value_offset); } chpr = newline(chpr); } else { PUSHCOLOR(RED); chpr += printf(" SEEK FAILED reading Property List item %d at offset %lu",i,offset); POPCOLOR(); break; } offset += 8; max_offset = ftell(inptr); } if((PRINT_SECTION)) { print_tag_address(SECTION,max_offset - 1,indent + SMALLINDENT,"@"); chpr += printf(""); chpr = newline(chpr); print_tag_address(SECTION,property_offset,indent + SMALLINDENT,"@"); chpr += printf(" length %lu",list_data_length); chpr = newline(chpr); } offset = data_offset; /* Read 'em again, and this time show the names and values */ for(i = 0; i < num_entries; ++i) { if(fseek(inptr,offset,SEEK_SET) == 0) { name_offset = read_ulong(inptr,byteorder,HERE); name_offset *= 2; if(feof(inptr) || ferror(inptr)) { PUSHCOLOR(RED); chpr += printf(" FAILED to read Property List name %d at offset %lu",i,offset); POPCOLOR(); break; } value_offset = read_ulong(inptr,byteorder,HERE); value_offset *= 2; if(feof(inptr) || ferror(inptr)) { PUSHCOLOR(RED); chpr += printf(" FAILED to read Property List value %d at offset %lu",i,offset + 4); POPCOLOR(); break; } name_offset += property_offset; value_offset += property_offset; print_property(inptr,byteorder,name_offset,value_offset,char_format, dirname,i,indent + MEDIUMINDENT); } else { PUSHCOLOR(RED); chpr += printf(" SEEK FAILED reading Property List item %d at offset %lu",i,offset); POPCOLOR(); break; } offset += 8; max_offset = ftell(inptr); } if((PRINT_SECTION)) { print_tag_address(SECTION,max_offset - 1,indent + SMALLINDENT,"@"); chpr += printf(""); chpr = newline(chpr); } if((PRINT_SECTION)) { print_tag_address(SECTION,property_offset + list_data_length - 1,indent,"@"); chpr += printf(""); chpr = newline(chpr); } } else { PUSHCOLOR(RED); fprintf(stderr,"%s: no file pointer to read X3F Properties List\n",Progname); POPCOLOR(); } setcharsprinted(chpr); return(max_offset); } /* Displays property names and values, given their offsets. The */ /* characters are encoded as 16 bit 'unicode'. This routine reads */ /* each character as an unsigned short and echos it via putchar(). */ void print_property(FILE *inptr,unsigned short byteorder,unsigned long name_offset, unsigned long value_offset,unsigned long char_format, char *dirname,int index,int indent) { int chpr = 0; int i = 0; int ch; if(inptr) { clearerr(inptr); if(fseek(inptr,name_offset,SEEK_SET) == 0) { if((PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(ENTRY,name_offset,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.Data.",dirname); chpr += printf("Name.%-2d",index); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 17); chpr += printf(" = "); } } if((PRINT_VALUE)) { while((ch = read_ushort(inptr,byteorder,HERE))) { if((PRINT_UNICODE)) fwrite((char *)&ch,2,1,stdout); else putchar(ch); ++chpr; } } } else { print_tag_address(ENTRY,name_offset,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.Data.",dirname); i = 0; while((ch = read_ushort(inptr,byteorder,HERE))) { if((PRINT_UNICODE)) fwrite((char *)&ch,2,1,stdout); else putchar(ch); ++chpr; ++i; } if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - i - 6); chpr += printf(" = "); } } } } if((PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) chpr = newline(chpr); if(fseek(inptr,value_offset,SEEK_SET) == 0) { if((PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(ENTRY,value_offset,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",dirname); chpr += printf("Value.%-2d",index); if((PRINT_VALUE)) { putindent(X3FTAGWIDTH - 18); chpr += printf(" = "); } } if((PRINT_VALUE)) { while((ch = read_ushort(inptr,byteorder,HERE))) { if((PRINT_UNICODE)) fwrite((char *)&ch,2,1,stdout); else putchar(ch & 0xff); ++chpr; } } } else if((PRINT_VALUE)) { while((ch = read_ushort(inptr,byteorder,HERE))) { if((PRINT_UNICODE)) fwrite((char *)&ch,2,1,stdout); else putchar(ch & 0xff); ++chpr; } } } chpr = newline(chpr); } } exifprobe-2.0.1+git20170416-3c2b76/sigma_datadefs.h0000644000000000000000000000176013074742216017621 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: sigma_datadefs.h,v 1.2 2005/06/15 23:34:09 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef SIGMA_DATADEFS_INCLUDED #define SIGMA_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id sigma_model_id[] = { { "SIGMA SD9", 10, SIGMA_SD9, 1, 1 }, { "SIGMA SD10", 11, SIGMA_SD10, 1, 1 }, { 0, 0, 0, 0, 0 } }; #endif /* SIGMA_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/maker.h0000644000000000000000000002045713074742216015771 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: maker.h,v 1.18 2005/07/24 21:17:17 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* General definitions for makernotes */ #ifndef MAKER_INCLUDED #define MAKER_INCLUDED #define MAX_IDLEN 24 /* max makernote id length to look for */ #define MAKERTAGWIDTH 25 #define UNKNOWN_SCHEME 0x0 #define PLAIN_IFD_SCHEME 0x1 #define HAS_ID_SCHEME 0x2 #define HAS_ID_PLUS_TIFFHDR_SCHEME 0x4 /* offset values relative to... */ #define START_OF_TIFFHEADER 0 #define START_OF_NOTE 1 #define START_OF_ENTRY 2 /* Magic numbers for maker */ /* ###%%% these should go into maker-specific includes */ #define NO_MAKE 0 #define NO_MODEL 0 #define MAKER_AGFA 1 #define MAKER_ASAHI 2 #define MAKER_CANON 3 #define MAKER_CASIO 4 #define MAKER_KODAK 5 #define MAKER_FUJIFILM 6 #define MAKER_HP 7 #define MAKER_MINOLTA 8 #define MAKER_KONICA 9 #define MAKER_KYOCERA 10 #define MAKER_LEICA 11 #define MAKER_NIKON 12 #define MAKER_OLYMPUS 13 #define MAKER_PANASONIC 14 #define MAKER_PENTAX 15 #define MAKER_RICOH 16 #define MAKER_SANYO 17 #define MAKER_EPSON 18 #define MAKER_SIGMA 19 #define MAKER_SONY 20 #define MAKER_TOSHIBA 21 #define MAKER_TRAVELER 22 /* Agfa model magic */ #define AGFA_SR841 1 /* Canon model magic */ #define CANON_IXUS 1 #define CANON_EOS1D 2 #define CANON_EOS1DMARKII 3 #define CANON_EOS1DS 4 #define CANON_EOS1DSMARKII 5 #define CANON_EOS10D 6 #define CANON_EOS20D 7 #define CANON_EOSD30 8 #define CANON_EOSD60 9 #define CANON_EOS350 10 #define CANON_EOSDIGITALREBEL 11 #define CANON_POWERSHOT_A1 12 #define CANON_POWERSHOT_A400 13 #define CANON_POWERSHOT_A5 14 #define CANON_POWERSHOT_G2 15 #define CANON_POWERSHOT_PRO1 16 #define CANON_POWERSHOT_S70 17 /* Casio model magic */ #define CASIO_QV2000UX 1 #define CASIO_QV3000EX 2 #define CASIO_QV4000 3 #define CASIO_QV8000SX 4 #define CASIO_QVR51 5 #define CASIO_EX_P505 6 #define CASIO_EX_P600 7 #define CASIO_EX_P700 8 #define CASIO_EX_S100 9 #define CASIO_EX_Z55 10 #define CASIO_GV_20 11 /* Eastman Kodak */ #define KODAK_DC200 1 #define KODAK_DC210 2 #define KODAK_DCS720X 3 #define KODAK_DCS760C 4 #define KODAK_DK120 5 #define KODAK_DC240 6 #define KODAK_DC4800 7 #define KODAK_DC25 8 #define KODAK_LS443 9 #define KODAK_DC50 10 /* Epson model magic */ #define EPSON_850Z 1 #define EPSON_3000Z 2 #define EPSON_3100Z 3 #define EPSON_L500V 4 /* Fujifilm model magic */ #define FUJI_DX10 1 /* No makernote */ #define FUJI_FP_A204 2 #define FUJI_40i 3 #define FUJI_4900ZOOM 4 #define FUJI_E550 5 #define FUJI_F601ZOOM 6 #define FUJI_S1PRO 7 /* No makernote */ #define FUJI_S2PRO 8 #define FUJI_S20PRO 9 #define FUJI_S5000 10 #define FUJI_MX1700ZOOM 11 /* No makernote */ #define FUJI_SP2000 12 /* HP model magic */ #define HP_C912 1 #define HP_R707 2 /* Konica model magic */ #define KONICA_QM100 1 #define KONICA_KD400Z 2 /* Kyocera model magic */ #define KYOCERA_FCS3 1 #define KYOCERA_FINECAMS5 2 /* Leica model magic */ #define LEICA_DIGILUX2 1 #define LEICA_DIGILUX43 2 /* Identical to FUJI */ #define LEICA_R9_DB_DMR 3 /* Digital back */ /* Minolta model magic */ #define MINOLTA_DIMAGE5 1 #define MINOLTA_DIMAGE7 2 #define MINOLTA_DIMAGE7Hi 3 #define MINOLTA_DIMAGE7i 4 #define MINOLTA_DIMAGEA1 5 #define MINOLTA_DIMAGEA2 6 #define MINOLTA_DIMAGEA200 7 #define MINOLTA_DIMAGEEX 8 #define MINOLTA_DIMAGEF100 9 #define MINOLTA_DIMAGEF200 10 #define MINOLTA_DIMAGEF300 11 #define MINOLTA_DIMAGES404 12 #define MINOLTA_DIMAGES414 13 #define MINOLTA_DIMAGEX 14 #define MINOLTA_DIMAGEX20 15 #define MINOLTA_DYNAX7D 16 #define MINOLTA_MAXXUM7D 17 /* Nikon Model magic */ #define NIKON_700 1 #define NIKON_775 2 #define NIKON_800 3 #define NIKON_885 4 #define NIKON_900 5 #define NIKON_950 6 #define NIKON_990 7 #define NIKON_995 8 #define NIKON_3700 9 #define NIKON_5000 10 #define NIKON_5200 11 #define NIKON_5700 12 #define NIKON_8700 13 #define NIKON_8800 14 #define NIKON_D1 15 #define NIKON_D1X 16 #define NIKON_D70 17 #define NIKON_D100 18 #define NIKON_D2H 19 #define NIKON_D2X 20 #define NIKON_SQ 21 /* Olympus model magic */ #define OLYMPUS_700UZ 1 #define OLYMPUS_C70ZC7000Z 2 #define OLYMPUS_960Z 3 #define OLYMPUS_2040Z 4 #define OLYMPUS_C2500L 5 #define OLYMPUS_3030Z 6 #define OLYMPUS_3040Z 7 #define OLYMPUS_C8080WZ 8 #define OLYMPUS_E_1 9 #define OLYMPUS_E_300 10 #define OLYMPUS_u40D 11 /* Asahi/Pentax model magic */ #define ASAHI_PENTAX330 1 #define ASAHI_PENTAX330RS 2 #define ASAHI_PENTAX430 3 #define ASAHI_PENTAX430RS 4 #define PENTAX_OPTIO550 5 #define PENTAX_OPTIO750Z 6 #define PENTAX_OPTIOS 7 #define PENTAX_OPTIOS5i 8 #define PENTAX_STARIST_D 9 #define PENTAX_STARIST_DS 10 /* Panasonic model magic */ #define PANASONIC_DMCFX7 1 #define PANASONIC_DMCFZ1 2 #define PANASONIC_DMCFZ2 3 #define PANASONIC_DMCFZ3 4 #define PANASONIC_DMCFZ10 5 #define PANASONIC_DMCFZ15 6 #define PANASONIC_DMCFZ20 7 #define PANASONIC_DMCLC5 8 #define PANASONIC_DMCLC33 9 #define PANASONIC_DMCLC40 10 #define PANASONIC_DMCLC43 11 /* Ricoh model magic */ #define RICOH_RDC5300 1 #define RICOH_RDC6000 2 /* Sanyo model magic */ #define SANYO_SR6 1 #define SANYO_SX113 2 #define SANYO_SX215 3 /* Sigma model magic */ #define SIGMA_SD9 1 #define SIGMA_SD10 2 /* Sony model magic */ #define SONY_CYBERSHOT 1 #define SONY_DIGITALMAVICA 2 #define SONY_DSCD700 3 #define SONY_DSCV3 4 #define SONY_MAVICA 5 /* Toshiba model magic */ #define TOSHIBA_PDR_3300 1 /* Traveler model magic */ #define TRAVELER_SX330Z 1 #endif exifprobe-2.0.1+git20170416-3c2b76/exifgrep0000755000000000000000000001626313074742216016260 0ustar rootroot#!/bin/sh # @(#) $Id: exifgrep,v 1.11 2005/07/02 13:10:03 alex Exp $ # Run 'egrep' on the output of exifprobe -L, massaging the output a la # 'list-photo'. Accepts the -var, -export, -num, and '-' options of # list_photo; all other options are passed to egrep. usage() { echo "Usage: exifgrep [-var|-export] [-num] [-r] [-t] [-n] [-c] [egrep-options] egrep-pattern [NOT egrep-pattern] imagefilename[s]" 1>&2 exit 1 } # Create the output format, choosing numerical or "interpreted" values # from the exifprobe output lines, and stripping unwanted spaces for # "variable" format (while quoting multi-word values). format() { filename= vars="var nequals nvalue iequals value remainder" case "${nameopt}" in "-n") vars="filename var nequals nvalue iequals value remainder" ;; esac while read $vars do case "$filename" in "#") continue ;; "#"*) continue; ;; *"#") continue ;; esac case ${var} in "#") continue ;; "#"*) continue; ;; *"#") continue ;; esac if test 0$dovar -ne 0 then if test ${donum} -eq 1 then case ${nvalue} in [0-9]*) echo -n "${export}${var}=${nvalue}" ;; *) quote ${var} ${nvalue} ${iequals} ${value} ${remainder};; esac else case "${iequals}" in "") quote ${var} ${nvalue}${value}${remainder} ;; =) quote ${var} ${value} ${remainder} ;; APEX) quote ${var} ${remainder} ;; *) quote ${var} ${nvalue} ${iequals} ${value} ${remainder} ;; esac fi elif test ${donum} -eq 1 then case ${nvalue} in "'"*) echo -n "${var}=${nvalue}" case "${iequals}" in "") ;; *) echo -n " ${iequals} ${value} ${remainder}" ;; esac ;; *) case "${var}" in "#") ;; *) echo -n "${var}=${nvalue}" ;; esac ;; esac else echo -n $var $nequals $nvalue $iequals $value $remainder fi case "${filename}" in "") echo ;; *) echo " # ${filename}" ;; esac done } # On output, place double-quotes around multi-word values which # are not already quoted. This is necessary for 'variable' format. # Do not include "commented" material in quoted phrase. quote() { local inquote inquote=0 case $# in 0) ;; 1) echo -n "${export}$1=" ;; 2) echo -n "${export}$1=$2" ;; *) case $1 in \#*) echo -n "$1" ;; *) echo -n "${export}$1"= ;; esac shift while test $# -gt 0 do case $1 in \'*) echo -n $*; break ;; \#*) case $inquote in 1) echo -n "' " ;; esac inquote=0 echo -n "$*" break ;; *) case $inquote in 0) echo -n "'"; inquote=1 ;; esac echo -n "$1" shift ;; esac done case $inquote in 1) echo -n "'" ;; esac ;; esac } exifgrep_imagefind() { local dir dir="$*" find ${dir:="."} \ \( \ -iname "*.tiff" -o -iname "*.tiff" -o -iname "*.tiff.Z" \ -o -iname "*.tif" -o -iname "*.tif" -o -iname "*.tif.Z" \ -o -iname "*.jpeg" -o -iname "*.jpeg.gz" -o -iname "*.jpeg.Z" \ -o -iname "*.jpg" -o -iname "*.jpg.gz" -o -iname "*.jpg.Z" \ -o -iname "*.jpe" -o -iname "*.jpe.gz" -o -iname "*.jpe.Z" \ -o -iname "*.kqp" -o -iname "*.kqp.gz" -o -iname "*.kqp.Z" \ -o -iname "*.mrw" -o -iname "*.mrw.gz" -o -iname "*.mrw.Z" \ -o -iname "*.nef" -o -iname "*.nef.gz" -o -iname "*.nef.Z" \ -o -iname "*.orf" -o -iname "*.orf.gz" -o -iname "*.orf.Z" \ -o -iname "*.pef" -o -iname "*.pef.gz" -o -iname "*.pef.Z" \ -o -iname "*.x3f" -o -iname "*.x3f.gz" -o -iname "*.x3f.Z" \ -o -iname "*.dng" -o -iname "*.dng.gz" -o -iname "*.dng.Z" \ -o -iname "*.erf" -o -iname "*.erf.gz" -o -iname "*.erf.Z" \ -o -iname "*.raf" -o -iname "*.raf.gz" -o -iname "*.raf.Z" \ -o -iname "*.cr2" -o -iname "*.cr2.gz" -o -iname "*.cr2.Z" \ -o -iname "*.crw" -o -iname "*.crw.gz" -o -iname "*.crw.Z" \ -o -iname "*.jp2" -o -iname "*.jp2.gz" -o -iname "*.jp2.Z" \ -o -iname "*.k25" -o -iname "*.k25.gz" -o -iname "*.k25.Z" \ -o -iname "*.kdc" -o -iname "*.kdc.gz" -o -iname "*.kdc.Z" \ \) -print } : PROBE=${PROBE:=exifprobe} # Gather options first. This is kind of wierd. dovar=0 donum=0 recursisve=0 export= egrep_options= vgrep_options= pattern= notpattern= nameopt= tagopt= coloropt= while test $# -ge 1 do case $1 in -var) dovar=1; shift ;; -num) donum=1; shift ;; -c) coloropt="-c" ; shift ;; -n) nameopt="-n"; shift ;; # may need this if reading from stdin -r) recursive=1; shift ;; -t) tagopt="-enN" ; shift ;; -export*) export="export "; dovar=1; shift ;; -h) usage ;; -*) egrep_options="$egrep_options $1"; shift ;; NOT) case "$2" in -f) notpattern="-f $3"; shift; shift; shift; break ;; *) notpattern="$2"; shift; shift; break ;; esac ;; *) pattern=$1; shift case $1 in NOT) case "$2" in -f) notpattern="-f $3"; shift; shift; shift; break ;; *) notpattern="$2"; shift; shift; break ;; esac ;; *) break ;; esac ;; esac done if test $# -lt 1 -a "X${pattern}${notpattern}" = "X" then usage fi # This should probably be modified somehow to use xargs. case "${recursive}" in 1) args=$( exifgrep_imagefind $* ) set -- ${args} ;; esac # All variables are global. # If there are no filenames, read from stdin, which is expected to be # exifprobe -L output. case $# in 0) egrep ${egrep_options} ${pattern} | format ;; *) case $# in 1) ;; *) nameopt="-n" ;; # Use names if more than one file esac case "${notpattern}" in "") ${PROBE} -L ${coloropt} ${nameopt} ${tagopt} $* | egrep ${egrep_options} ${pattern} | format ;; *) case "${pattern}" in "") ${PROBE} -L ${coloropt} ${nameopt} ${tagopt} $* | egrep ${egrep_options} -v ${notpattern} | format ;; *) ${PROBE} -L ${coloropt} ${nameopt} ${tagopt} $* | egrep ${egrep_options} ${pattern} | egrep -v ${notpattern} | format ;; esac ;; esac ;; esac exifprobe-2.0.1+git20170416-3c2b76/tags.h0000644000000000000000000000164413074742216015625 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: tags.h,v 1.4 2005/07/12 04:59:05 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef TAGS_INCLUDED #define TAGS_INCLUDED #include "tifftags.h" #include "exiftags.h" #include "tiffeptags.h" #include "dngtags.h" #include "jpegtags.h" #include "private_tags.h" #include "cifftags.h" #endif exifprobe-2.0.1+git20170416-3c2b76/aux/0000755000000000000000000000000013074742216015306 5ustar rootrootexifprobe-2.0.1+git20170416-3c2b76/aux/extract_section.c0000644000000000000000000001002413074742216020645 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* This program extracts an arbitrary section of a file from */ /* 'start_offset' to 'end_offset', writing it to a file named with */ /* the original filename suffixed by ".%d-%d" start,end. */ /* section to be extracted may be specified by a second argument */ /* "@start:length" or by second and third arguments "start end". */ /* This is intended to extract sections from image files, and is much */ /* faster than 'dd' for the purpose. */ #ifndef lint static char *ModuleId = "@(#) $Id: extract_section.c,v 1.1 2005/06/30 17:50:27 alex Exp $"; #endif #include #include #include #include #include #define END_OF_FILE MAXINT #define COPYBUFSIZE 16384 #define NAMELENGTH 1024 extern char *optarg; char *Progname; main(int argc,char **argv) { char copybuf[COPYBUFSIZE]; char outfilename[NAMELENGTH]; char *arg,*infilename,*colon; unsigned long start_offset = 0UL; unsigned long end_offset = END_OF_FILE; int opt; FILE *ifp,*ofp; int readsize = 0; int bytesread = 0; int byteswritten = 0; int bytescopied = 0; int sizeleft = 0; int onamelength = 0; Progname = *argv; if(argc >= 2) { infilename = *++argv; arg = *++argv; if(arg && (*arg == '@')) { start_offset = strtoul(++arg,(char **)0,0); colon = strchr(arg,':'); if(colon) end_offset = start_offset + strtoul(++colon,(char **)0,0) - 1; } else if(arg) { start_offset = strtoul(arg,(char **)0,0); if(*++argv) { arg = *argv; end_offset = strtoul(arg,(char **)0,0); } } } if(infilename) { if(end_offset == END_OF_FILE) onamelength = snprintf(outfilename,NAMELENGTH,"%s.%d-eof",infilename,start_offset); else onamelength = snprintf(outfilename,NAMELENGTH,"%s.%d-%d",infilename,start_offset,end_offset); if(onamelength < (strlen(infilename) + 2)) { fprintf(stderr,"%s: can't make output name",Progname); perror("\tbecause"); exit(2); } } else { fprintf(stderr,"%s: no input file name\n",Progname); exit(1); } printf("copy from %s to %s\n",infilename,outfilename); printf("start_offset = %lu, ",start_offset); sizeleft = end_offset - start_offset + 1; if(end_offset == END_OF_FILE) printf("end_offset = end of file\n"); else printf("end_offset = %d, copy length = %d\n",end_offset,sizeleft); if((ifp = fopen(infilename,"r")) != (FILE *)0) { if((ofp = fopen(outfilename,"w")) == (FILE *)0) { fprintf(stderr,"%s: could not open output file \"%s\"\n",Progname,outfilename); perror("\tbecause"); exit(3); } fseek(ifp,start_offset,SEEK_SET); if(sizeleft < COPYBUFSIZE) readsize = sizeleft; else readsize = COPYBUFSIZE; while(sizeleft && ((bytesread = fread(copybuf,1,readsize,ifp)) > 0)) { byteswritten = fwrite(copybuf,1,bytesread,ofp); sizeleft -= byteswritten; bytescopied += byteswritten; if(sizeleft < COPYBUFSIZE) readsize = sizeleft; } clearerr(ifp); printf("copied %d bytes from %d to %d\n",bytescopied,start_offset,ftell(ifp) - 1); } else { fprintf(stderr,"%s: could not open input file \"%s\"\n",Progname,infilename); perror("\tbecause"); exit(3); } exit(0); } exifprobe-2.0.1+git20170416-3c2b76/aux/probetohtml0000755000000000000000000000760613074742216017604 0ustar rootroot#!/bin/sh # Convert the output of 'exifprobe' to a simple HTML file. # Usage: # probe2html [exifprobe options] pathname # (runs exifprobe with options on 'pathname' and writes a file named by # the last component of 'pathname' + the options (with spaces removed) # and a ".html" extension. # OR # [command] | probetohtml - [command | almost anything] # [command] should generate exifprobe output (e.g. 'exifgrep'). The '-' # argument to probe2html forces reading from stdin; the output filename # is a unique filename generated from the first word following the '-' # the prefix PROBE, a number making the filename unique, and the extension # ".html". The page will be titled with *all* of the words following '-' # This allows something like # exifgrep Maker some/file/name | probe2html - exifgrep some/file/name # which will produce a file PROBEexifgrep.0.html with the output of that # command and a title which shows the command. unique_name() { prefix= case $# in 0) name="unique.$$" ;; *) name=$1; prefix=$2; suffix=$3 ;; esac case ${prefix} in X) prefix= ;; esac case "${suffix}" in .*|"") ;; *) suffix=.${suffix} ;; esac if test -d ${prefix}${name}${suffix} -o -d ${prefix}${name}.0${suffix} then vers=1 while test -d ${prefix}${name}.${vers}${suffix} do vers=`expr $vers + 1` done fi if test -f ${prefix}${name}${suffix} -o -f ${prefix}${name}.0${suffix} then vers=${vers:=1} while test -f ${prefix}${name}.${vers}${suffix} -o -f ${prefix}${name}.${vers}${suffix}.gz -o -d ${prefix}${name}.${vers}${suffix} do vers=`expr $vers + 1` done fi case "${vers}" in "") echo ${prefix}${name}.0${suffix} ;; *) echo ${prefix}${name}.${vers}${suffix} ;; esac } # Get the last component of the argument pathname lastcomp() { local oifs #local IFS oifs="${IFS}" IFS=/ set -- ${1} IFS="${oifs}" case "${1}" in "") case $# in 0) ;; *) shift ;; esac ;; esac while test $# -gt 1 do case "${2}" in "") break ;; esac shift done echo ${1} } # Get the first component of the argument pathname firstcomp() { local oifs oifs="${IFS}" IFS=/ set -- ${1} IFS="${oifs}" basename $1 .d } # make a temp file for the sed script... tmp=$(mktemp /tmp/PROBE.XXXXXX) # and make the script cat << 'END' > ${tmp} s//\>/g s/\[0m/<\/FONT>/g s/\[30m//g s/\[31m//g s/\[32m//g s/\[35m//g s/\[94m//g s/\[90m//g END probeopts= suffix= lastcomp= while test $# -gt 1 do case "$1" in -) infile=stdin basename=$2 destfile=$( unique_name ${basename} PROBE .html ) shift title="$*" suffix= set -- break ;; -*) probeopts="${probeopts} $1" suffix="${suffix}$1" shift ;; *) break ;; esac done case ${infile} in stdin) ;; *) case $# in 0) echo "$0: no input file" 1>&2; exit 1 ;; esac infile=$1 destfile=$( lastcomp ${infile} ) title=$( firstcomp ${infile} ) title="${title} - $destfile ${probeopts}" destfile="${destfile}${suffix}.html" ;; esac echo input file is ${infile} # Start the page cat << HEAD > ${destfile} ${title}
HEAD

case "${infile}" in
 stdin) sed -f ${tmp} >> ${destfile}
        ;;
     *) ${PROBE} ${probeopts} ${infile} | sed -f ${tmp} >> ${destfile} ;;
esac

# end the file
cat << TAIL >> ${destfile}
TAIL # Done rm -f ${tmp} echo output file is ${destfile} echo title is ${title} exifprobe-2.0.1+git20170416-3c2b76/aux/findjpeg.c0000644000000000000000000002032113074742216017236 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: findjpeg.c,v 1.1 2005/06/30 17:50:27 alex Exp $"; #endif /* This program does a quick sweep through any file looking for JPEG */ /* data streams bracketed by JPEG_SOI and JPEG_EOI, and attempts to */ /* show start offset and length of segments found. It crudely */ /* attempts to pair up SOI and EOI when embedded images are found */ /* (e.g. in APP1/TIFF/EXIF files). */ /* Output should be taken with a grain of salt; the tag numbers */ /* representing JPEG tags may occur randomly in any binary format */ /* file. The program also recognizes and reports a small subset of */ /* additional jpeg markers which should occur in a jpeg stream, as an */ /* aid to recognizing real image streams. */ /* In particular, a lookout should be kept for spurious APPn markers, */ /* since the program does not look for the "header" information which */ /* validates the section. */ /* The program will check a section of a file if given a second */ /* argument of "@offset:length" or second and third arguments "offset */ /* length", which may be in decimal of hex formats. */ /* The first argument must be a valid filename */ /* Suspected jpeg streams are reported at the end as "@offset:length. */ #include #include #include #include #define END_OF_FILE 0xffffffff extern char *optarg; main(int argc,char **argv) { int opt; unsigned long start_offset = 0UL; unsigned long end_offset = END_OF_FILE; char *arg,*filename,*colon; int soi[16]; int eoi[16]; int soi_index = 0; int eoi_index = 0; int tagloc = 0; FILE *fp; int highbyte,lobyte; int i,j; int tabs = 0; int hadsoi = 0; memset(soi,0,16); memset(eoi,0,16); if(argc >= 2) { filename = *++argv; arg = *++argv; if(arg && (*arg == '@')) { start_offset = strtoul(++arg,(char **)0,0); colon = strchr(arg,':'); if(colon) end_offset = start_offset + strtoul(++colon,(char **)0,0); } else if(arg) { start_offset = strtoul(arg,(char **)0,0); if(*++argv) { arg = *argv; end_offset = strtoul(arg,(char **)0,0); } } } printf("filename=%s\n",filename); printf("start_offset = %lu\n",start_offset); if(end_offset == END_OF_FILE) printf("end_offset = end of file\n"); else printf("end_offset = %lu\n",end_offset); if((fp = fopen(filename,"r")) != (FILE *)0) { fseek(fp,start_offset,SEEK_SET); while(((highbyte = fgetc(fp)) != EOF) && (ftell(fp) <= end_offset)) { if(highbyte != 0xff) continue; tagloc = ftell(fp) - 1; lobyte = fgetc(fp); { switch(lobyte) { case 0xd8: for(i = 0; i < tabs; ++i) putchar('\t'); soi[soi_index] = tagloc; printf("JPEG_SOI=%#x/%d (e%d,s%d)\n",soi[soi_index],soi[soi_index],eoi_index,soi_index); /* must be a JPEG marker next */ if(((highbyte = fgetc(fp)) != EOF) && (ftell(fp) <= end_offset)) { //printf(" %#02x ",highbyte); if(highbyte != 0xff) { fseek(fp,-1L,SEEK_CUR); continue; } if(((lobyte = fgetc(fp)) != EOF) && (ftell(fp) <= end_offset)) { if((lobyte < 0xc0) || (lobyte > 0xfe)) continue; fseek(fp,-2L,SEEK_CUR); if(tagloc == 0) soi_index = -1; ++soi_index; ++tabs; ++hadsoi; //printf(" %#02x, soi_index => %d\n",lobyte,soi_index); } } continue; break; case 0xd9: if(soi[eoi_index]) { eoi[eoi_index] = tagloc; for(i = 1; i < tabs; ++i) putchar('\t'); printf("JPEG_EOI=%#x/%d (e%d,s%d)\n",eoi[eoi_index],eoi[eoi_index],eoi_index,soi_index); ++eoi_index; --tabs; } else { for(i = 0; i < tabs; ++i) putchar('\t'); printf("JPEG_EOI=%#x/%d\n",tagloc,tagloc); } break; case 0xc4: for(i = 0; i < tabs; ++i) putchar('\t'); printf("JPEG_DHT=%#04x/%d\n",tagloc,tagloc); break; case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc5: case 0xc6: case 0xc7: case 0xc9: case 0xca: case 0xcb: case 0xcd: case 0xce: case 0xcf: for(i = 0; i < tabs; ++i) putchar('\t'); printf("JPEG_SOF%d=%#04x/%d (e%d,s%d)\n",lobyte & 0xf,tagloc,tagloc,eoi_index,soi_index); break; case 0xda: for(i = 0; i < tabs; ++i) putchar('\t'); printf("JPEG_SOS=%#04x/%d (e%d,s%d)\n",tagloc,tagloc,eoi_index,soi_index); break; case 0xdb: for(i = 0; i < tabs; ++i) putchar('\t'); printf("JPEG_DQT=%#04x/%d (e%d,s%d)\n",tagloc,tagloc,eoi_index,soi_index); break; case 0xe1: case 0xe0: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: for(i = 0; i < tabs; ++i) putchar('\t'); printf("JPEG_APP%d =%#04x/%d (e%d,s%d)\n",lobyte & 0xf,tagloc,tagloc,eoi_index,soi_index); break; default: /* if((lobyte >= 0xc0) && (lobyte < 0xff)) printf("JPEG_%#04x\n",lobyte); */ break; } } } i = soi_index - eoi_index; for(j = eoi_index - 1; i < soi_index; ++i,--j) { if(soi[i] == -1) soi[i] = 0; if((i >= 0) && (j>= 0)) printf("%d:%d @%d:%d => %d\n",i,j,soi[i],(eoi[i] + 2) - soi[i],eoi[i] + 1); } } exit(0); } exifprobe-2.0.1+git20170416-3c2b76/aux/convert_rgb_to_tiff0000755000000000000000000000072213074742216021261 0ustar rootroot#!/bin/sh # Converts the RGB blob extracted from a Canon CR2 file to a displayable TIFF image. # Extract the section with 'exifgrep Ifd2.Strip filename', then # 'extract_section @StripOffsets:StripByteCounts' # Rename the file to have an 'rgb' extension, then run this using the basename of the # rgb file as argument. # ...or write a better script to automate the process. convert -verbose -size 384x256 -depth 8 -gamma 2.2 -density 72x72 $1.rgb'[384x256]' $1.tif exifprobe-2.0.1+git20170416-3c2b76/aux/dump_section.c0000644000000000000000000003525713074742216020157 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* This program reads an arbitrary section of a file from */ /* 'start_offset' to 'end_offset', printing the data as numerical */ /* values in one or more of the requested formats. */ /* First argument is filename; section to be dumped may be specified */ /* by a second argument "@start:length" or by second and third */ /* arguments "start end". */ #ifndef lint static char *ModuleId = "@(#) $Id: dump_section.c,v 1.3 2005/07/24 22:57:36 alex Exp $"; #endif #include /* #include */ #include #include #include /* Needed for MAXINT, no matter what compiler */ /* may say */ #define END_OF_FILE MAXINT #define NAMELENGTH 1024 #define TIFF_INTEL 0x4949 #define TIFF_MOTOROLA 0x4d4d #define HERE (unsigned long)0xffffffff extern char *optarg; char *Progname; extern int errno; extern unsigned short read_ushort(FILE *,unsigned short,unsigned long); extern unsigned short to_ushort(unsigned char *,unsigned short); extern unsigned long read_ulong(FILE *,unsigned short,unsigned long); extern unsigned long to_ulong(unsigned char *,unsigned short); main(int argc,char **argv) { char *arg,*infilename,*colon; unsigned long offset = 0UL; unsigned long start_offset = 0UL; unsigned long end_offset = END_OF_FILE; int opt,i; FILE *ifp; unsigned long section_size = 0; unsigned long lvalue; unsigned short svalue; unsigned short byteorder = TIFF_INTEL; unsigned short snumerator,sdenominator; unsigned long lnumerator,ldenominator; double rvalue; int show_bytes = 0; int show_bytes_decimal = 0; int show_bytes_hex = 0; int show_short = 0; int show_short_decimal = 0; int show_short_hex = 0; int show_long = 0; int show_long_decimal = 0; int show_long_hex = 0; int show_rational = 0; int show_long_rational = 0; int show_short_rational = 0; Progname = *argv++; --argc; while(argc > 2 && *argv) { arg = *argv; if(arg && (*arg == '-')) { switch(*++arg) { case 'b': /* bytes */ show_bytes = 1; if(*++arg == '\0') { show_bytes_decimal = 1; show_bytes_hex = 1; } if(strchr(arg,'d')) show_bytes_decimal = 1; if(strchr(arg,'h')) show_bytes_hex = 1; break; case 's': /* shorts */ show_short = 1; if(*++arg == '\0') { show_short_decimal = 1; show_short_hex = 1; } if(strchr(arg,'d')) show_short_decimal = 1; if(strchr(arg,'h')) show_short_hex = 1; break; case 'l': /* longs */ show_long = 1; if(*++arg == '\0') { show_long_decimal = 1; show_long_hex = 1; } if(strchr(arg,'d')) show_long_decimal = 1; if(strchr(arg,'h')) show_long_hex = 1; break; case 'r': show_rational = 1; if(*++arg == '\0') { show_long_rational = 1; show_short_rational = 1; } if(strchr(arg,'l')) show_long_rational = 1; if(strchr(arg,'s')) show_short_rational = 1; break; case 'i': /* Intel byteorder */ byteorder = TIFF_INTEL; break; case 'm': /* Motorola byteorder */ byteorder = TIFF_MOTOROLA; break; } --argc; ++argv; } else break; } if(argc >= 1) { infilename = *argv; arg = *++argv; if(arg && (*arg == '@')) { start_offset = strtoul(++arg,(char **)0,0); colon = strchr(arg,':'); if(colon) end_offset = start_offset + strtoul(++colon,(char **)0,0) - 1; } else if(arg) { start_offset = strtoul(arg,(char **)0,0); if(*++argv) { arg = *argv; end_offset = strtoul(arg,(char **)0,0); } } } printf("input file %s\n",infilename); printf("start_offset = %lu, ",start_offset); section_size = end_offset - start_offset + 1; if(end_offset == END_OF_FILE) printf("end_offset = end of file\n"); else printf("end_offset = %ld, section length = %ld\n",end_offset,section_size); printf("byteorder = %2.2s\n",(char *)&byteorder); if((ifp = fopen(infilename,"r")) != (FILE *)0) { if(show_bytes) { if(show_bytes_decimal) { fseek(ifp,start_offset,SEEK_SET); offset = start_offset; i = 0; printf("\n=============================================\nUnsigned byte - decimal:\n"); while((offset <= end_offset) && !feof(ifp) && !ferror(ifp)) { svalue = fgetc(ifp); printf("%#06lx/%-04lu: %-12u",offset,offset,svalue); ++offset; if(++i == 4) { putchar('\n'); i = 0; } } } if(show_bytes_hex) { printf("\n=============================================\nUnsigned byte - hex:\n"); fseek(ifp,start_offset,SEEK_SET); offset = start_offset; i = 0; while((offset <= end_offset) && !feof(ifp) && !ferror(ifp)) { svalue = fgetc(ifp); printf("%#06lx/%-04lu: %-12#x",offset,offset,svalue); ++offset; if(++i == 4) { putchar('\n'); i = 0; } } } } if(show_short) { if(show_short_decimal) { offset = start_offset; i = 0; printf("\n=============================================\nUnsigned short - decimal:\n"); while((offset <= end_offset) && !feof(ifp) && !ferror(ifp)) { svalue = read_ushort(ifp,byteorder,offset); printf("%#06lx/%-04lu: %-12u",offset,offset,svalue); offset += 2; if(++i == 4) { putchar('\n'); i = 0; } } } if(show_short_hex) { offset = start_offset; i = 0; printf("\n=============================================\nUnsigned short - hex:\n"); while((offset <= end_offset) && !feof(ifp) && !ferror(ifp)) { svalue = read_ushort(ifp,byteorder,offset); printf("%#06lx/%-04lu: %-12#x",offset,offset,svalue); offset += 2; if(++i == 4) { putchar('\n'); i = 0; } } } } if(show_long) { if(show_long_decimal) { fseek(ifp,start_offset,SEEK_SET); offset = start_offset; i = 0; printf("\n=============================================\nUnsigned long - decimal:\n"); while((offset <= end_offset) && !feof(ifp) && !ferror(ifp)) { lvalue = read_ulong(ifp,byteorder,offset); printf("%#06x/%-04lu: %-12lu",offset,offset,lvalue); offset += 4; if(++i == 4) { putchar('\n'); i = 0; } } putchar('\n'); } if(show_long_hex) { fseek(ifp,start_offset,SEEK_SET); offset = start_offset; i = 0; printf("\n=============================================\nUnsigned long - hex:\n"); while((offset <= end_offset) && !feof(ifp) && !ferror(ifp)) { lvalue = read_ulong(ifp,byteorder,offset); printf("%#06x/%-04lu: %-12#lx",offset,offset,lvalue); offset += 4; if(++i == 4) { putchar('\n'); i = 0; } } putchar('\n'); } } if(show_rational) { if(show_long_rational) { fseek(ifp,start_offset,SEEK_SET); offset = start_offset; i = 0; printf("\n=============================================\nUnsigned long - rational:\n"); while((offset <= end_offset) && !feof(ifp) && !ferror(ifp)) { rvalue = 0.0; lnumerator = read_ulong(ifp,byteorder,offset); ldenominator = read_ulong(ifp,byteorder,HERE); if(sdenominator) rvalue = (double)lnumerator / (double)ldenominator; printf("%#06x/%-04lu: %-12.8f",offset,offset,rvalue); offset += 8; if(++i == 4) { putchar('\n'); i = 0; } } putchar('\n'); } if(show_short_rational) { fseek(ifp,start_offset,SEEK_SET); offset = start_offset; i = 0; printf("\n=============================================\nUnsigned short rational:\n"); while((offset <= end_offset) && !feof(ifp) && !ferror(ifp)) { rvalue = 0.0; snumerator = read_ushort(ifp,byteorder,offset); sdenominator = read_ushort(ifp,byteorder,HERE); if(sdenominator) rvalue = (double)snumerator / (double)sdenominator; printf("%#06x/%-04lu: %-12.8f",offset,offset,rvalue); offset += 4; if(++i == 4) { putchar('\n'); i = 0; } } putchar('\n'); } } } else { fprintf(stderr,"%s: could not open input file \"%s\"\n",Progname,infilename); perror("\tbecause"); exit(3); } exit(0); } unsigned short read_ushort(FILE *inptr,unsigned short byteorder,unsigned long offset) { unsigned char rbuf[2]; unsigned long curoffset; unsigned short value = 0; int chpr = 0; if(inptr /*&& !feof(inptr) && !ferror(inptr)*/) { clearerr(inptr); curoffset = ftell(inptr); if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) { printf(" SEEK FAILED to read unsigned short at offset "); printf("%lu",offset); } else if(fread(rbuf,1,sizeof(unsigned short),inptr) == sizeof(unsigned short)) value = to_ushort(rbuf,byteorder); else { printf(" FAILED to read unsigned short value at offset "); if(offset == HERE) offset = curoffset; chpr += printf("%lu",offset); } if(ferror(inptr)) { chpr += printf(" ("); printf(strerror(errno)); chpr += printf(")"); chpr = putchar('\n'); } else if(feof(inptr)) { printf(" (EOF)"); chpr = putchar('\n'); } } return(value); } unsigned long read_ulong(FILE *inptr,unsigned short byteorder,unsigned long offset) { unsigned char rbuf[4]; unsigned long curoffset; unsigned long value = 0; int chpr = 0; if(inptr /* && !feof(inptr) && !ferror(inptr)*/) { clearerr(inptr); curoffset = ftell(inptr); if((offset != HERE) && (fseek(inptr,offset,SEEK_SET) == -1)) { printf(" SEEK FAILED to read unsigned 32bit integer at offset "); printf("%lu",offset); } else if(fread(rbuf,1,4,inptr) == 4) value = to_ulong(rbuf,byteorder); else { printf(" FAILED to read unsigned 32bit integer at offset "); if(offset == HERE) offset = curoffset; chpr += printf("%lu",offset); } if(ferror(inptr)) { chpr += printf(" ("); printf(strerror(errno)); chpr += printf(")"); putchar('\n'); } else if(feof(inptr)) { printf(" (EOF)"); chpr = putchar('\n'); } } return(value); } unsigned short to_ushort(unsigned char *buf,unsigned short byteorder) { unsigned short value = 0; if(buf) { value = *(unsigned short *)buf; #ifdef NATIVE_BYTEORDER_BIGENDIAN if(byteorder == TIFF_INTEL) value = (buf[1] << 8) | buf[0]; #else if(byteorder == TIFF_MOTOROLA) value = (buf[0] << 8) | buf[1]; #endif } return(value); } unsigned long to_ulong(unsigned char *buf,unsigned short byteorder) { unsigned long value = 0; if(buf) { value = *(unsigned long *)buf; #ifdef NATIVE_BYTEORDER_BIGENDIAN if(byteorder == TIFF_INTEL) #else if(byteorder == TIFF_MOTOROLA) #endif value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; } return((unsigned long)value); } exifprobe-2.0.1+git20170416-3c2b76/aux/README0000644000000000000000000000265013074742216016171 0ustar rootrootThese programs are rather crude but may be useful. extract_section - extracts a section of a file given start offset and length, or start and end offset (which you can get from exifprobe output). An easy way to extract embedded JPEGs. findjpeg - scan a file for valid jpeg streams. VERY crude, and not useful on mostly binary files. dump_section - print a specified chunk of a file as bytes, shorts, longs, or short or long rationals. probetohtml - a simple shell script which uses 'sed' to convert color escape sequences to font color tags and generate an HTML file for the output of exifprobe. reformat.sh - script to reformat LIST output to change dots to underscores, remove comments, etc. to make the output acceptable to a shell for sourcine. The '-var' and '-export' options of exifgrep are no longer adequate for that purpose. convert_rgb_to_tiff - convert the RGB section of a Canon CR2 file to a 384x256 TIFF image that anybody can see. Uses ImageMagick 'convert' utility. convert_rgb_to_jpeg - convert the RGB section of a Canon CR2 file to a 384x256 JPEG image that anybody can see. Uses ImageMagick 'convert' utility. exifprobe-2.0.1+git20170416-3c2b76/aux/convert_rgb_to_jpeg0000755000000000000000000000072213074742216021256 0ustar rootroot#!/bin/sh # Converts the RGB blob extracted from a Canon CR2 file to a displayable JPEG image. # Extract the section with 'exifgrep Ifd2.Strip filename', then # 'extract_section @StripOffsets:StripByteCounts' # Rename the file to have an 'rgb' extension, then run this using the basename of the # rgb file as argument. # ...or write a better script to automate the process. convert -verbose -size 384x256 -depth 8 -gamma 2.2 -density 72x72 $1.rgb'[384x256]' $1.jpg exifprobe-2.0.1+git20170416-3c2b76/aux/Makefile0000644000000000000000000000057013074742216016750 0ustar rootrootall: extract_section dump_section findjpeg extract_section: extract_section.c ${CC} -o extract_section extract_section.c dump_section: dump_section.c ${CC} -o dump_section dump_section.c findjpeg: findjpeg.c ${CC} -o findjpeg findjpeg.c extract_section: extract_section.c ${CC} -o extract_section extract_section.c clean: rm -f extract_section dump_section findjpeg exifprobe-2.0.1+git20170416-3c2b76/aux/reformat.sh0000755000000000000000000000356413074742216017474 0ustar rootroot#!/bin/sh # Reformat the output of 'exifprobe -L' to remove the "." separators, # which are not valid in shell variable names, and produce output # which may be 'sourced' by a shell. The value of the variable will # be the last value present (the "interpreted" value, if available). # Comments are stripped. # This doesn't allow filenames on each line (exifprobe -n) # Replace dots with underscores. to_underscore() { local nextarg nextarg= OIFS=${IFS} IFS="." set - $* echo -n $1 shift # strip off asterisks for nextarg in $* do nextarg=${nextarg%[*]} echo -n _${nextarg%[*]} done IFS=${OIFS} } # Replace the dots and pick out the value, stripping comments. reformat() { local lastarg case $# in 0) return ;; esac lastarg= endquote= to_underscore $1 shift # Pick out value after the last '=', quote it if not already quoted, # and strip off comments. while test $# -ge 1 do case "$1" in \#*) break ;; \:*) break ;; =) lastarg=; shift ;; \') case "${lastarg}" in "") lastarg="'" ;; *) endquote="'"; break ;; esac ;; \'?*) lastarg="$1"; endquote=; shift ;; *) case "${lastarg}" in "") lastarg="'$1"; endquote="'" ;; *) lastarg="${lastarg} $1" ;; esac shift ;; esac done echo "=${lastarg}${endquote}" } # Prepend value of 'MARK' to each line of output. MARK= case $# in 0) ;; *) MARK="${1}:" ;; esac # expects output of 'exifprobe -L' (without '-n') while read LINE do case "${LINE}" in ?[*m\#*) continue ;; \#*) continue ;; "") continue ;; esac echo -n "${MARK}" reformat $LINE done exifprobe-2.0.1+git20170416-3c2b76/konica_datadefs.h0000644000000000000000000000204413074742216017761 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: konica_datadefs.h,v 1.2 2005/06/03 14:04:22 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef KONICA_DATADEFS_INCLUDED #define KONICA_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id konica_model_id[] = { { "Konica Digital Camera Q-M100", 29, KONICA_QM100, 1, 1 }, { "Konica Digital Camera KD-400Z", 30, KONICA_KD400Z, 1, 1 }, { 0, 0, 0, 0, 0 } }; #endif /* KONICA_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/4_SPACE_TABS0000644000000000000000000000000013074742216016311 0ustar rootrootexifprobe-2.0.1+git20170416-3c2b76/exifprobe.1.html0000644000000000000000000006425413074742216017534 0ustar rootroot


EXIFPROBE(1)                                                      EXIFPROBE(1)



NAME
       exifprobe  -  probe and report structure and metadata content of camera
       image files

SYNOPSIS
       exifprobe [options] filename(s)

DESCRIPTION
       Exifprobe reads image files produced by digital cameras (including sev-
       eral  so-called  "raw"  file  formats) and reports the structure of the
       files and the auxilliary data and metadata contained  within  them.  In
       addition  to TIFF, JPEG, and EXIF, the program understands several for-
       mats which may contain "raw"  camera  data,  including  MRW,  CIFF/CRW,
       JP2/JPEG2000,  RAF,  and  X3F,  as well as most most TIFF-derived "raw"
       formats, including DNG, ORF, CR2, NEF, K25/KDC/DCR, and PEF. Other TIFF
       or JPEG-derived formats (which begin with a TIFF header or JPEG marker)
       should also be readable.  The program attempts to display ALL  informa-
       tion  in  the image file, in a manner which mimics the structure of the
       file as closely as possible.

       Where possible, output is not limited to "known" data items.  I.e.  for
       tagged  file formats, unknown tags will be identified by tag number and
       type, and values shown without interpretation. Proprietary, untagged or
       fixed  format  files  do not permit this, but unknown or undefined data
       can usually be dumped in a hex/ascii format for examination, so long as
       the  file structure is understood. The program will report the contents
       of any properly structured TIFF IFD or CIFF directory encountered, even
       when entry tags are not recognized.  Recognized TIFF, TIFF/EP, DNG, and
       CIFF tags are expanded, including EXIF2.2 sections  and  camera  Maker-
       Notes  which are found to be in TIFF IFD format.  TIFF and/or JPEG sec-
       tions found in MRW, RAF or JP2 files will be reported, along  with  the
       "native"  sections of those formats. JP2 boxes will be reported whether
       known or unknown, and expanded  if  known.   Unknown  boxes  cannot  be
       expanded, since JP2 is not tagged below the box (or sub-box) level.

       An effort is made to identify all sub-images (in any image format) con-
       tained in multi-image files; the location, size,  and  format  of  such
       images  is  reported,  and  a  hex/ascii  dump of the image data may be
       requested. Image data is not processed, but the program will  recognize
       and  report all standard JPEG and JPEG2000 markers (including JPEG APPn
       markers) and will expand APP0 (JFIF/JFXX) and APP1 (EXIF) sections.

       Since the program does not attempt to display images or modify the con-
       tents  of  files, it can often recover from and report failures or warn
       about structural oddities which would confuse a display or  image  edit
       program.

       There are a wide variety of output formats, selectable in detail by the
       "lower case" options described in the  OPTIONS  section  below.   These
       options  select  which  items to print, and within narrow confines, how
       and where to print them.  A large number  of  combinations  of  options
       exist, and some of those combinations may not be sensible.  In order to
       avoid the need for constant creativity or invention,  three  "prefabri-
       cated"  output  formats are provided, selected by the upper case option
       letters.

       The structural (-S) output format (default) provides a  description  of
       the  image  file  which  mimics  as  closely as possible the layout and
       structure of the data in the image  file,  including  file  offsets  of
       headers,  section  and segment markers, fully described TIFF IFDs, CIFF
       directories, or JP2 boxes, and the  location  of  actual  image  and/or
       thumbnail  data.  The contents of each section are indented relative to
       the beginning of the section, and "offset" values  for  TIFF  IFDs  and
       CIFF directories are reported at the offsets where they are found (usu-
       ally following the entry list for TIFF, or in the HEAP for CIFF).   The
       peculiar  "reverse" structures of CIFF and X3F formats are handled sen-
       sibly.

       The report format (-R) shows the "logical" structure of the image file,
       but  eliminates  addresses,  offsets, IFD value types and counts, etc.,
       and prints "offset" directory values inline, while otherwise preserving
       the primary structure of the data.

       The  list  format  (-L) omits all structural data. It writes only "tag"
       values from TIFF, Exif, and MakerNote IFDs, CIFF or other format direc-
       tories  or  JP2  boxes,  including section and image offsets and sizes.
       Identifiable values from non-tagged formats are written  in  a  similar
       manner.  This format may be useful for extracting information for photo
       galleries.

       The structural format is default.  This format provides maximum  infor-
       mation  about the contents of an image file, and may reveal information
       (sometimes important) which other formats (or image info programs)  may
       hide.

       In  all  formats, the filename, file type, file size, an image summary,
       and a summary file format will be displayed (even when all other output
       is  disabled  by  option). The image summary includes a summary report,
       for each subimage found, giving the image type,  compression  type  (if
       any),  pixel size, data length, file offset where found, and section of
       the file which includes or references the image.  In some cases,  short
       remarks  may  be  included for images mentioned but not found, etc. The
       summary concludes with the number of images found, and number of images
       not found (if any). The summary is followed by a listing of format sec-
       tions found (TIFF/JPEG/EXIF, etc.) and  a  type  identifier  for  TIFF-
       derived types (e.g. CR2) where possible.

       An  environment  variable  may be set to a list of options to customize
       the default output behavior (see below).


   MakerNotes
       Camera-generated images which contain EXIF sections  may  also  contain
       sections  introduced  by a MakerNote tag, which may contain information
       about camera or firmware settings  used  to  produce  the  image.   The
       structure  and  contents  of  MakerNote sections is not mandated by the
       Exif specification, but many camera MakerNotes are written in TIFF  IFD
       format,  possibly  offset following an ID string or new TIFF header (or
       both), and sometimes with inventive handling of  "offsets".   Exifprobe
       currently understands and automatically detects such schemes and prints
       the contents of the IFD (and the ID string, if present).   This  detec-
       tion  is  not  dependent  upon make or model of camera.  Make and Model
       information will usually be available from the first TIFF  IFD  in  the
       file;  this information may be used to interpret the MakerNote informa-
       tion for "known" cameras; otherwise, tag numbers, sizes, types, and raw
       values from the IFD will be shown (if permitted by option settings).

       Some  camera makes are known to use more than one version of MakerNote,
       depending upon model.  If an unknown model from that maker  is  encoun-
       tered,  the  note  will  be briefly examined and a noteversion assigned
       automatically if possible.  If that fails, the note will  be  displayed
       without interpretation.

       MakerNotes  which are not in a recognizable IFD format will be reported
       (start and end offsets) in structural (-S) and report  (-R)  formats  ,
       and  the beginning of the note section hex/ascii dumped.  The remainder
       of the note may be dumped, in whole or in part, by the -M  option  (see
       below).

       In  list  (-L)  format, the starting file offset and length supplied by
       the MakerNote tag will be  reported,  and  three  "pseudo"  tags  which
       report  the  offset  (MakerNote.Offset),  size  (MakerNote.Length)  and
       scheme (MakerNote.Scheme) will appear.


   JPEG APPn
       In JPEG interchange format files, APP0 (JFIF,JFXX) and APP1 (Exif) seg-
       ments will be fully decoded, and the "printable" portions of APP12 sec-
       tions will be displayed. APP3 (Meta) sections will be expanded and  the
       contained TIFF IFD will be displayed, although little interpretation is
       done. Other APP markers will be  reported,  and  the  sections  may  be
       hex/ascii dumped in whole or in part using the -A option. APP1 sections
       not marked as Exif will be treated as unknown.


   ANSI Color
       The program (by default) emits ANSI color escape sequences to highlight
       Exif,  MakerNote , and Interoperability sub-sections.  Errors and warn-
       ings are highlighted in red.  These sequences are effective, of course,
       only  for terminals or terminal emulators (e.g. xterm) which respond to
       ANSI color escape sequences.  If a pager is used to display the  output
       when  these  sequences  are present, a "raw" option to the pager may be
       required (e.g. less -R).  The use of these sequences may be toggled  by
       the -c option.  LIST mode turns color sequences off.

       The program may be compiled without support for color sequences.


OUTPUT FORMATS
       In all formats, and regardless of option setting, the first three lines
       of output for each file processed are the filename, image  type  (TIFF,
       CIFF,  JP2, etc.), and the file size.  If the type (taken from the file
       header) specifies a data byte order, the byte order will  be  indicated
       with the type as `II' (Intel byte order) or `MM' (Motorola byte order).
       The image summary and summary format will always be printed at the end.


   Structural Format
       Structural format output begins with a display of the file header.  The
       header is followed by lines of the form
              <IFD0>
                  ...
              </IFD0>
              <APP0>
                  ...
              </APP0>
              <DIRECTORY>
                  ...
              </DIRECTORY>
       etc.  to indicate the beginning and end of each "section" of the  file.
       Actual  section  names  will,  of  course,  depend upon the file format
       and/or the tags encountered.  Only the TIFF  IFD  format  is  described
       here;  other formats are similar, except that JP2 box names are printed
       inside square (rather than  angle)  brackets,  and  MRW  section  names
       inside curly braces.

       Within  sections,  directory  entries,  subdirectories, the contents of
       known APP sections, JPEG segment markers, etc. are  printed.   Non-jpeg
       image data sections will be shown with a few lines of hex/ascii dump of
       the beginning of the data.

       Each line of output is preceded by a file offset given in hex and deci-
       mal.   File  offsets  are  preceded  by  the character `@', except that
       section end markers are preceded by `-' and the character  `>'  may  be
       used  to  mark sections which are located outside the IFD in which they
       are declared.  If that section includes a subsection which is similarly
       afflicted, the '>' is replaced by '+' in the subsection.  In JP2 files,
       the '@' is replaced by '=', for no particular reason.

       JPEG and JPEG2000 segment markers are written with the marker name, and
       the decoded values of any information associated with the marker.

       TIFF information is written in a manner which reflects the structure of
       the IFD, with all values interpreted according to the applicable speci-
       fication  where  possible.  All IFD fields are reported.  The following
       fields will appear on each line (in the order given, following the file
       offset):

       o      Tag  number  in  hex  and  decimal  representations, enclosed in
              brackets.

       o      Tag name (where known); names for unknown tags are created as  a
              hex  representation  of  the  tag  number prefixed by the string
              'TAG_'.

       o      The TIFF type number, name, and byte count  for  the  associated
              value, enclosed in square brackets.

       o      The "value/offset" for the entry.  If the value fits in the four
              bytes of the entry, the value is printed directly.

              If the value for the entry did not fit in the four bytes of  the
              entry,  then the value found is an offset to the actual location
              of the data; that offset is printed preceded by an  '@'  symbol.
              The actual value will be printed later, at the file offset where
              it was found (except in some non-conforming MakerNote IFDs).  If
              the  value requires interpretation (e.g. TIFF Orientation) it is
              followed by an '=' sign and the interpretation, enclosed in dou-
              ble quotes (e.g. "0,0 top left").

       The list of entries will be followed by a line giving the offset to the
       next IFD (often 0) which is always found at the end of a TIFF IFD entry
       list.

       If  there  were  offset  entries found in the list above, the TIFF (and
       Exif) specification requires that they will  be  located  next  in  the
       file,  immediately  following  the dirctory entries.  This stricture is
       frequently ignored in MakerNotes  and  TIFF-derived  formats.   A  line
       reporting  the beginning of these offset values will be printed immedi-
       ately after the next IFD offset, followed by one line for  each  offset
       entry,  with  the tag name repeated, followed by the actual value, fol-
       lowed by its interpretation (if any).

       Multiple values in entries are printed on  a  single  line,  but  large
       lists  will  be  elided, with just the first two or three values shown,
       followed by an ellipsis, followed by the last value, the number of val-
       ues, and the offset of the last value in the list.  The full value list
       may be printed using the -eA option.


       In structural format, ascii strings in the entry are  printed  for  the
       entire  length  given  in  the IFD entry, including nulls and non-ascii
       values (if present), which are printed in `backslashed' octal notation.
       The  -ea option may be used to force ascii values to be printed only up
       to the first null.  This option is  often  necessary  for  CIFF  format
       files, and is enabled by default in "list" mode.

       Entries  are  indented  slightly from the start identifier for the IFD,
       and subsegments (e.g. an  Exif  IFD,  SubIFD,  or  MakerNote)  will  be
       further indented in order to indicate the structure of the file.

       The  resulting  output  displays  the  contents  of  the IFD much as it
       appears in the file (see the TIFF or EXIF specifications  for  descrip-
       tions of the IFD format).

       Finally,  the  start and end of actual image data for the primary image
       (and possibly thumbnail or reduced-resolution image) is reported at the
       end.   For  JPEG images, this usually includes display of the JPEG seg-
       ment markers within the image.  Binary format image data will be  shown
       with a brief hex/ascii dump of the beginning of the data, between start
       and end markers.

       Note that values preceded by `@' are always offsets from the  beginning
       of  the  file to the actual value.  IFD offsets are usually recorded in
       the file as offsets relative to the beginning of the TIFF header (which
       is  offset  from  the beginning of the file in JPEG APP1 files) but are
       adjusted by exifprobe to show offset from the beginning  of  the  file.
       If  it  is  important  to see the recorded value, the -er option may be
       used to print the recorded value in parentheses, following the adjusted
       file offset.


   Report Format
       The  report format (-R) displays all sections and segments of the image
       file, including start and end of sections, but eliminates much  of  the
       "cruft" of the structural format by eliminating address/offset informa-
       tion and much of the `internal' information from the TIFF IFD (tag num-
       ber,  type  and  count).  Offset values are printed inline with the tag
       name.  The output is indented to show  the  logical  structure  of  the
       image file, but is much less difficult to view than the structural for-
       mat.


   List format
       The list format (-L) suppresses structural  information,  writing  only
       content  in the format tagname = value or tagname = value = "what value
       means". For non-tagged file formats, the tagname will be replaced by  a
       fixed  identifier  for  the  item.  In LIST format, "long" tagnames are
       used, which include the names of all parent sections of the section  in
       which  the  data  is found.  Long tagnames can be toggled off, although
       this is unwise if the file contains multiple image sections.

       The "value" of tags or items which represent an offset to a  subsection
       or image are printed in list format as "@offset:length".

       The  List  format is used by the auxilliary script exifgrep, which per-
       mits selective extraction of information e.g. for photo galleries,  and
       output in (almost) "shell variable" format.


   Custom Formats
       The  -Z  option  "zeroes"  all option flags (except the longnames modi-
       fier), after which the lower-case options may be used  to  set  desired
       options.   The lower-case options are `toggles', which may also be used
       to turn off items in the pre-defined formats.

       As an example, the command:

           exifprobe -Z -et somefile.tif

       may be used to list just the TIFF and Exif  tags,  without  values  (or
       anything else) in "long name" format.

            exifprobe -eNnT somefile.tif

       will  print in structural format, suppressing output of hex and decimal
       tag numbers, and tag type and count.

       The "zero-level" output still reports the file data and  image  summary
       as described above.


OPTIONS
       The  environment  variable  EXIFPROBE_OPTIONS  may  be set to any valid
       option string, which will be evaluated  before  command  line  options.
       E.g.

       export EXIFPROBE_OPTIONS='-L -c'

       will  make  list  format  the  default output format, and re-enable the
       color sequences turned off by -L.

       Options are evaluated from left to right, so -Z should be given  first,
       while -D (decimal only) or -X (hex only) should be given last.


       -S        Structure  mode:  (default)  almost everything; offset values
                 not inline

       -R        Report mode: like structural, but only tagnames  and  decimal
                 values, indented, inline

       -L        List  mode: print only tags and values (including interpreted
                 values); no section info; no color

       -Z        turn off (zero) all optional output.  Prints  only  filename,
                 filetype, filesize, image summary, and file format.

       -c        toggle  use of ANSI color control sequences to emphasize EXIF
                 sections.  (default 'on' except list  mode,  unless  compiled
                 with no color support)

       -a        toggle  printing of addresses (file offsets) in hex and deci-
                 mal

       -I        three-way toggle indent (after address -> before -> none)

       -o        toggle "inline" print of offset IFD values

       -p[items] toggle print identifiers for:

                 s   - sections (IFDs, APPn)

                 g   - segments (JPEG segments)

                 a   - JPEG APP0...APPn entries

                 l   - long names (dot-separated list of parent sections  pre-
                     ceding item name)

                 e   - entries. Includes tag names, numbers, types, values.

                 m   - print MakerNote scheme description

                 M   - watch debug of MakerNote scheme detection


       -e[items] toggle print IFD entry items:

                 t   - tagname

                 n   - tag number in decimal

                 N   - tag number in hex

                 T   - entry type and count

                 v   - value in decimal

                 V   - value in hex

                 o   - file offset to value in decimal

                 O   - file offset to value in hex

                 r   - relative (unadjusted) offset in decimal

                 R   -  also  print  "raw" values where normal values are com-
                     puted (e.g. rational values,  or  some  MakerNote  values
                     where APEX values must be computed from a raw value).

                 A   - print ALL elements of multiple-value tags

                 a   - ascii "ignore length" (stop at first null)

       -D        limit   all   enabled   numerical   values  to  decimal  only
                 (addresses, tag numbers, offsets, values)

       -X        limit all enabled numerical values to  hex  only  (addresses,
                 tag numbers, offsets, values)

       -U[len|a] dump  len (or all) bytes of UNDEFINED data found in TIFF IFDS
                 in hex/ascii form (but only if the structure of the  data  is
                 not known)

       -M[len|a] dump  len  (or  all)  bytes  of  unrecognized  MakerNotes  in
                 hex/ascii form (but only if the structure of the data is  not
                 known)

       -A[len|a] dump  len (or all) bytes of unrecognized JPEG APP segments in
                 hex/ascii form (but only if the structure of the data is  not
                 known)

       -B[len|a] dump  len  (or all) bytes of binary image data or failed JPEG
                 image data

       -C[make]+[model]
                 print a list of camera makes/models matching make or model as
                 substrings.  `+' by itself prints everything

       -O start_offset
                 start processing at file offset start_offset

       -n        print  filename  at  beginning of each line of output (useful
                 when grepping multiple files in LIST mode)

       -N noteversion
                 force use of note version noteversion when interpreting  Mak-
                 erNotes.  Useful only if you know what you're doing.

       -m make   Force  the  makernote code to interpret the note according to
                 the make given, rather than that contained in the file.

       -l model  force the makernote code to interpret the note  according  to
                 the model given, rather than that contained in the file.

       -t        This  option has effect only if set in EXIFPROBE_OPTIONS.  If
                 set when command line options are processed, color   will  be
                 be off by default if the output is not to a tty.  Any command
                 line option which toggles or sets color (e.g. "-R") will turn
                 color back on.

       -u        Print "raw" Unicode data.  Normally 16 bit data is printed as
                 though the high byte is  zero  (which  is  often  the  case).
                 Writing the nulls would annoy most ascii terminal devices, so
                 the default is more hospitable.  The -u option forces  print-
                 ing of the full value.

       -h        print a help message

       -V        print program version and copyright


SEE ALSO
       exifgrep(1)
       The TIFF6 specification:
        https://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf
       The Exif 2.2 specification:
        http://tsc.jeita.or.jp/avs/data/cp3451.pdf
       The JFIF specification:
        http://www.w3.org/Graphics/JPEG/jfif3.pdf
       The TIFF/EP specification:
        http://www.map.tu.chiba-u.ac.jp/IEC/100/TA2/recdoc/N4378.pdf
       The CIFF specification
        http://xyrion.org/ciff/CIFFspecV1R04.pdf
       The X3F public specification
        http://www.sd9.org.uk/X3F_Format.pdf
       The JPEG2000 public draft (outdated)
        http://www.jpeg.org/public/fcd15444-1.pdf

DIAGNOSTICS
       Most  diagnostics  are  printed  "inline" to stdout, in red if color is
       enabled, and the program attempts to proceed.

BUGS
       Interpretation of MakerNote data for specific cameras is incomplete and
       probably  always will be.  The X3F specification is incomplete, and the
       final JPEG2000/JP2 specification is not freely available;  support  for
       these  formats is therefore not complete, and may not be entirely accu-
       rate.

       The RAF file format support is preliminary (there is no published spec-
       ification).

       Floating  point  values  read  from the file are expected to be in IEEE
       format (or at least, native format); i.e. no conversions are attempted.

       ANSI  color sequence support should use termcap/terminfo facilities; it
       does not.


AUTHOR
       Duane H. Hesser
       dhh@virtual-cafe.com




                                     LOCAL                        EXIFPROBE(1)

Man(1) output converted with man2html
exifprobe-2.0.1+git20170416-3c2b76/raf.c0000644000000000000000000004715413074742216015440 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: raf.c,v 1.7 2005/07/24 20:33:55 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Fujifilm RAF routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* This is *experimental* and incomplete. It is based upon */ /* examination of only four (count 'em' FOUR) images which I have */ /* found on the web. This is sufficient to find and print the JPEG */ /* image contained within the file, and even extract it with */ /* something like 'extract_section'. The names and even identities of */ /* the items describing the CFA array are arbitrary and possibly */ /* wrong; feedback is welcome. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include #include "defs.h" #include "datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "raf.h" /* Print the RAF header information, even though it's hard to tell */ /* exactly where the header ends and data begins. */ int print_raf_header(FILE *inptr,struct fileheader *fileheader,unsigned long section_id) { int status = -1; int chpr = 0; if(Print_options & section_id) { /* ###%%% for now, the first 60 bytes are "header" */ if(fileheader && (fileheader->probe_magic == PROBE_RAFMAGIC)) { print_ascii(inptr,28,0); chpr += printf(" Model = "); print_ascii(inptr,32,28); status = 0; } else chpr += printf(" NOT AN RAF HEADER"); } chpr = newline(chpr); return(status); } /* Process a Fujifilm RAF file, starting right after the RAF header. */ /* At this point, I *think* the location of the jpeg image is fixed; */ /* the rest is unclear, but do the best we can. */ unsigned long process_raf(FILE *inptr,unsigned long offset, struct image_summary *summary_entry, char *parent_name,int indent) { unsigned long start_of_jpeg,jpeg_length,max_offset; unsigned long table1_offset,table2_offset; unsigned long table1_length,table2_length; unsigned long CFA_offset,CFA_length; unsigned long unknown2,CFA_primaryarraywidth,CFA_fullarraywidth; unsigned long Secondary_offset,Secondary_length; unsigned long unknown3,Secondary_arraywidth,Secondary_fullarraywidth; unsigned long unused_value; struct image_summary *tmp_summary_entry; int unused; char *fullname = CNULL; int chpr = 0; unsigned short tag; CFA_primaryarraywidth = Secondary_offset = table1_offset = table2_offset = 0UL; /* Record the primary for the image summary */ if(((summary_entry == NULL) || summary_entry->entry_lock) || (summary_entry->imageformat != IMGFMT_NOIMAGE)) { summary_entry = new_summary_entry(summary_entry,FILEFMT_RAF,IMGFMT_RAF); } if(summary_entry) { summary_entry->imageformat = IMGFMT_RAF; summary_entry->imagesubformat = IMGSUBFMT_CFA; summary_entry->entry_lock = lock_number(summary_entry); } chpr = newline(chpr); /* A short section of zeros; why? */ if((PRINT_SECTION)) { print_tag_address(SECTION,offset,indent,"@"); chpr += printf(""); chpr = newline(chpr); } /* Some sort of ID or version? */ print_tag_address(ENTRY,offset,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"HeaderVersion"); } if((PRINT_VALUE)) { chpr += printf(" = "); print_ascii(inptr,4,offset); } chpr = newline(chpr); offset += 4; /* A 20 bytes section of zeros. Unknown */ if((PRINT_SECTION)) { print_tag_address(ENTRY,offset,indent + SMALLINDENT,"@"); if((PRINT_VALUE)) print_ubytes(inptr,20,offset); chpr = newline(chpr); } /* A jpeg reduced resolution image, complete with EXIF */ start_of_jpeg = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC); print_tag_address(ENTRY,RAF_JPEGLOC,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"JpegImageOffset"); } if((PRINT_VALUE)) chpr += printf(" = @%lu",start_of_jpeg); chpr = newline(chpr); print_tag_address(ENTRY,RAF_JPEGLOC + 4,indent + SMALLINDENT,"@"); jpeg_length = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 4); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"JpegImageLength"); } if((PRINT_VALUE)) chpr += printf(" = %lu",jpeg_length); chpr = newline(chpr); /* An offset to what may be a white balance table */ print_tag_address(ENTRY,RAF_JPEGLOC + 8,indent + SMALLINDENT,"@"); table1_offset = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 8); table1_length = read_ulong(inptr,TIFF_MOTOROLA,HERE); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"Table1Offset"); } if((PRINT_VALUE)) chpr += printf(" = @%lu",table1_offset); chpr = newline(chpr); /* The length of the table; probably also the number of rows in */ /* the CFA array */ print_tag_address(ENTRY,RAF_JPEGLOC + 12,indent + SMALLINDENT,"@"); table1_length = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 12); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"Table1Length"); } if((PRINT_VALUE)) chpr += printf(" = %lu",table1_length); chpr = newline(chpr); /* If there is a second table, this must be an SR Super CCD with */ /* a secondary CFA table containing the data for the secondary */ /* photodiodes. The start offset for the secondary data is offset */ /* one row (2944 bytes) from the start of the primary data, */ /* suggesting that the primary and secondary CFA arrays are */ /* interleaved by rows (of 1472 unsigned shorts) */ table2_offset = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 36); table2_length = read_ulong(inptr,TIFF_MOTOROLA,HERE); if(table2_offset == 0) { print_tag_address(ENTRY,RAF_JPEGLOC + 16,indent + SMALLINDENT,"@"); CFA_offset = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 16); CFA_length = read_ulong(inptr,TIFF_MOTOROLA,HERE); Secondary_length = 0; if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"CFAOffset"); } if((PRINT_VALUE)) chpr += printf(" = @%lu",CFA_offset); chpr = newline(chpr); print_tag_address(ENTRY,RAF_JPEGLOC + 20,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"CFALength"); } if((PRINT_VALUE)) chpr += printf(" = %lu",CFA_length); chpr = newline(chpr); for(unused = 24; unused < 64; unused += 4) { print_tag_address(ENTRY,RAF_JPEGLOC + unused,indent + SMALLINDENT,"@"); unused_value = read_ulong(inptr,TIFF_MOTOROLA,(unsigned long)(RAF_JPEGLOC + unused)); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%s%-2d%*.*s","unused",(unused - 24)/4 + 1,TAGWIDTH-8,TAGWIDTH-8," "); } if((PRINT_VALUE)) chpr += printf(" = %lu",unused_value); chpr = newline(chpr); } } else { /* No secondary; easy. */ CFA_offset = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 16); CFA_length = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 20); print_tag_address(ENTRY,RAF_JPEGLOC + 16,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"CFA_Offset"); } if((PRINT_VALUE)) chpr += printf(" = @%lu",CFA_offset); chpr = newline(chpr); print_tag_address(ENTRY,RAF_JPEGLOC + 20,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"CFA_length"); } if((PRINT_VALUE)) chpr += printf(" = @%lu",CFA_length); chpr = newline(chpr); print_tag_address(ENTRY,RAF_JPEGLOC + 24,indent + SMALLINDENT,"@"); unknown2 = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 24); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"unknown2"); } if((PRINT_VALUE)) chpr += printf(" = %lu",unknown2); chpr = newline(chpr); CFA_primaryarraywidth = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 28); print_tag_address(ENTRY,RAF_JPEGLOC + 28,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { /* Array width in 16 bit unsigned shorts */ if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"CFAPrimaryArrayWidth"); } if((PRINT_VALUE)) chpr += printf(" = %lu",CFA_primaryarraywidth); chpr = newline(chpr); print_tag_address(ENTRY,RAF_JPEGLOC + 32,indent + SMALLINDENT,"@"); CFA_fullarraywidth = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 32); if((PRINT_TAGINFO)) { /* Array width in bytes */ if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"CFAFullArrayWidth"); } if((PRINT_VALUE)) chpr += printf(" = %lu",CFA_fullarraywidth); chpr = newline(chpr); print_tag_address(ENTRY,RAF_JPEGLOC + 36,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"Table2Offset"); } if((PRINT_VALUE)) chpr += printf(" = @%lu",table2_offset); chpr = newline(chpr); print_tag_address(ENTRY,RAF_JPEGLOC + 40,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"Table2Length"); } if((PRINT_VALUE)) chpr += printf(" = %lu",table2_length); chpr = newline(chpr); /* It appears that the secondary CFA data is interlaced by */ /* row with the primary data. */ Secondary_offset = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 44); Secondary_length = read_ulong(inptr,TIFF_MOTOROLA,HERE); print_tag_address(ENTRY,RAF_JPEGLOC + 44,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"CFASecondaryOffset**"); } if((PRINT_VALUE)) chpr += printf(" = @%lu",Secondary_offset); chpr = newline(chpr); print_tag_address(ENTRY,RAF_JPEGLOC + 48,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"CFASecondaryLength**"); } if((PRINT_VALUE)) chpr += printf(" = %lu",Secondary_length); chpr = newline(chpr); unknown3 = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 52); Secondary_arraywidth = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 56); Secondary_fullarraywidth = read_ulong(inptr,TIFF_MOTOROLA,RAF_JPEGLOC + 60); print_tag_address(ENTRY,RAF_JPEGLOC + 52,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"unknown3"); } if((PRINT_VALUE)) chpr += printf(" = %lu",unknown3); chpr = newline(chpr); print_tag_address(ENTRY,RAF_JPEGLOC + 56,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"CFASecondaryArrayWidth"); } if((PRINT_VALUE)) chpr += printf(" = %lu",Secondary_arraywidth); chpr = newline(chpr); print_tag_address(ENTRY,RAF_JPEGLOC + 60,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); /* I dunno what to call this... */ chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"CFASecondaryFullArrayWidth"); } if((PRINT_VALUE)) chpr += printf(" = %lu",Secondary_fullarraywidth); chpr = newline(chpr); } if((PRINT_SECTION)) { print_tag_address(SECTION,RAF_JPEGLOC + 63,indent,"@"); chpr += printf(""); chpr = newline(chpr); } /* Finish the summary entry */ if(summary_entry) { if(summary_entry->length <= 0) summary_entry->length = CFA_length + Secondary_length; if(summary_entry->offset <= 0) summary_entry->offset = CFA_offset; /* Not really compression; just record the presence of the */ /* secondary */ if(Secondary_offset) summary_entry->compression = 1; else summary_entry->compression = 0; /* These aren't really pixel sizes, since the actual number */ /* of columns is half the arraywidth, and the array will have */ /* to be rotated 45 degrees. And then there is the secondary */ /* pixel data... */ /* It's what we know, and post-processing can do what it */ /* wants. */ if(CFA_primaryarraywidth) { summary_entry->pixel_width = CFA_primaryarraywidth; summary_entry->pixel_height = table1_length; summary_entry->primary_width = CFA_primaryarraywidth; summary_entry->primary_height = table1_length; } else { /* No size provided; this is the best we can do. */ summary_entry->pixel_width = (CFA_length + Secondary_length)/table1_length; summary_entry->pixel_height = table1_length; summary_entry->primary_width = summary_entry->pixel_width; summary_entry->primary_height = table1_length; } summary_entry->subfiletype = PRIMARY_TYPE; } /* Now display the offset sections, starting with the jpeg image */ /* (but only if showing sections) */ if((PRINT_SECTION)) { print_tag_address(SECTION,start_of_jpeg,indent,"@"); chpr += printf("#### Start of Jpeg Image, length %lu",jpeg_length); chpr = newline(chpr); } /* Is this really a jpeg section? */ tag = read_ushort(inptr,TIFF_MOTOROLA,start_of_jpeg); if(tag == JPEG_SOI) { /* If so, process it regardless of output options, to pick up */ /* information for the image summary */ fullname = splice(parent_name,".","JPEG"); max_offset = process_jpeg_segments(inptr,start_of_jpeg,JPEG_SOI,jpeg_length, summary_entry,fullname,"@",SMALLINDENT); print_jpeg_status(); if(summary_entry) { /* The jpeg summary entry should be next in the chain; */ /* there may be others following; mark the jpeg entry so */ /* that it will show up in the format summary. */ if((tmp_summary_entry = summary_entry->next_entry)) tmp_summary_entry->filesubformat |= FILESUBFMT_JPEG; } } else dumpsection(inptr,start_of_jpeg,jpeg_length,indent + SMALLINDENT); if((PRINT_SECTION)) { print_tag_address(SECTION,start_of_jpeg + jpeg_length - 1,indent,"@"); chpr += printf("#### End of Jpeg Image, length %lu",jpeg_length); chpr = newline(chpr); print_tag_address(SECTION,table1_offset,indent,"@"); chpr += printf(" length %lu",table1_length); chpr = newline(chpr); if((PRINT_VALUE)) dumpsection(inptr,table1_offset,table1_length,indent + SMALLINDENT); print_tag_address(SECTION,table1_offset + table1_length - 1,indent,"@"); chpr += printf("
"); chpr = newline(chpr); if(table2_offset) { print_tag_address(SECTION,table2_offset,indent,"@"); chpr += printf(" length %lu",table2_length); chpr = newline(chpr); if((PRINT_VALUE)) dumpsection(inptr,table2_offset,table2_length,indent + SMALLINDENT); print_tag_address(SECTION,table2_offset + table2_length - 1,indent,"@"); chpr += printf("
"); chpr = newline(chpr); } /* The full CFA, with secondary if present */ print_tag_address(SECTION,CFA_offset,indent,"@"); chpr += printf(" length %lu",CFA_length + Secondary_length); chpr = newline(chpr); if((PRINT_VALUE)) dumpsection(inptr,CFA_offset,CFA_length + Secondary_length,indent + SMALLINDENT); print_tag_address(SECTION,CFA_offset + CFA_length + Secondary_length - 1,indent,"@"); chpr += printf(""); chpr = newline(chpr); } setcharsprinted(chpr); return(get_filesize(inptr)); } exifprobe-2.0.1+git20170416-3c2b76/extern.h0000644000000000000000000003062113074742216016171 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: extern.h,v 1.33 2005/07/24 21:18:02 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef EXTERN_INCLUDED #define EXTERN_INCLUDED extern int optind; extern char *optarg; extern int getopt(); extern int Debug; extern char *Progname; extern long Header_offset; extern unsigned long Max_undefined; extern unsigned long Max_makerdump; extern unsigned long Max_appdump; extern unsigned long Max_imgdump; extern unsigned long Print_options; extern unsigned long Start_offset; extern char *Make_name; extern char *Model_name; extern char *Software_name; /* Used when forcing camera make, model, or software (-m, -l, -s) */ extern char *Use_Make_name; extern char *Use_Model_name; extern char *Use_Software_name; extern char *Camera_name_pattern; /* =================== Function prototypes ========================= */ extern int process_options(int,char **); extern void env_options(); extern void print_byteorder(unsigned short,int); extern void print_magic(unsigned long,int); extern unsigned long process_tiff_ifd(FILE *,unsigned short,unsigned long, unsigned long,unsigned long, struct image_summary *,char *, int,int,int,int); extern unsigned long process_exif_ifd(FILE *,unsigned short,unsigned long, unsigned long,unsigned long, struct image_summary *,char *, int,int); extern unsigned long process_gps_ifd(FILE *,unsigned short,unsigned long, unsigned long,unsigned long, struct image_summary *,char *, int,int); extern unsigned long process_subifd(FILE *,unsigned short,struct ifd_entry *, unsigned long,unsigned long, struct image_summary *,char *, int,int,int,int); extern unsigned long process_makernote(FILE *,unsigned short,struct ifd_entry *, unsigned long,unsigned long, struct image_summary *,char *, int); extern unsigned long process_app0(FILE *,unsigned long,unsigned short, struct image_summary *, char *,int); extern unsigned long process_app1(FILE *,unsigned long,unsigned short, struct image_summary *, char *,int); extern unsigned long process_app3(FILE *,unsigned long,unsigned short, struct image_summary *, char *,int); extern unsigned long process_app12(FILE *,unsigned long,unsigned short, struct image_summary *, char *,int); extern unsigned long process_appn(FILE *,unsigned long,unsigned short, struct image_summary *, char *,int); extern unsigned long process_jpeg_segments(FILE *,unsigned long, unsigned short,unsigned long, struct image_summary *,char *, char *,int); extern unsigned long process_pim(FILE *,unsigned short,unsigned long, unsigned long, unsigned long,char *, char *,char *,int); extern int jpeg_status(int); extern void print_jpeg_status(); extern int skip_past_newline(FILE *,unsigned long); extern int skip_to_bracket(FILE *,unsigned long); extern int putword(FILE *,int,unsigned long,int); extern int invalid_ifd_entry(FILE *,unsigned long,unsigned long,int,unsigned short); extern unsigned short valid_tiffhdr(FILE *,unsigned long,int); extern char *check_printable(char *,int); extern char *splice(char *,char *,char *); extern int newline(int); extern void setcharsprinted(int); extern int charsprinted(); extern void putcolorchar(unsigned short); extern struct ifd_entry *read_ifd_entry(FILE *,unsigned short,unsigned long); extern unsigned long read_ulong(FILE *,unsigned short,unsigned long); extern unsigned long long read_ulong64(FILE *,unsigned short,unsigned long); extern unsigned long to_ulong(unsigned char *,unsigned short); extern unsigned long long to_ulong64(unsigned char *,unsigned short); extern unsigned short read_ushort(FILE *,unsigned short,unsigned long); extern unsigned short to_ushort(unsigned char *,unsigned short); extern float read_float(FILE *,unsigned short,unsigned long); extern float to_float(unsigned long); extern double read_double(FILE *,unsigned short,unsigned long); extern double to_double(unsigned char *,unsigned short); extern unsigned short read_ubyte(FILE *,unsigned long); extern struct fileheader *read_imageheader(FILE *,unsigned long); extern unsigned char *read_bytes(FILE *,unsigned long,unsigned long); extern char *read_appstring(FILE *,unsigned short,unsigned long); extern char *read_string(FILE *,unsigned long,unsigned long); extern void print_ubytes(FILE *,unsigned long,unsigned long); extern void print_sbytes(FILE *,unsigned long,unsigned long); extern void print_ushort(FILE *,unsigned long,unsigned short,unsigned long); extern void print_sshort(FILE *,unsigned long,unsigned short,unsigned long); extern void print_ulong(FILE *,unsigned long,unsigned short,unsigned long); extern void print_slong(FILE *,unsigned long,unsigned short,unsigned long); extern void print_urational(FILE *,unsigned long,unsigned short,unsigned long); extern void print_srational(FILE *,unsigned long,unsigned short,unsigned long); extern void print_float(FILE *,unsigned long,unsigned short,unsigned long); extern void print_double(FILE *,unsigned long,unsigned short,unsigned long); extern void print_user_comment(FILE *,unsigned long,unsigned long,unsigned short); extern void print_cfapattern(FILE *,unsigned long,unsigned short,unsigned long, char *,char *); extern void print_version(); extern void print_startvalue(); extern void print_endvalue(); extern int print_filetype(unsigned long,unsigned short); extern unsigned long get_filesize(FILE *inptr); extern int ateof(FILE *); extern void setfilename(char *); extern void print_filename(); extern char *find_camera_name(int); extern void clear_memory(); extern void usage(); extern void print_summary(struct image_summary *); extern int print_image_summary_entry(struct image_summary *,char *); extern int scan_summary(struct image_summary *); extern void print_imageformat(struct image_summary *); extern void print_imagecompression(struct image_summary *); extern void print_tiff_compression(struct image_summary *); extern void print_jpeg_compression(struct image_summary *); extern void print_jp2c_compression(struct image_summary *); extern void print_crw_compression(struct image_summary *); extern void print_raf_compression(struct image_summary *); extern void print_imagesubformat(struct image_summary *); extern void print_imagesubtype(struct image_summary *); extern void print_imagesize(struct image_summary *); extern void print_location(struct image_summary *); extern char *tiff_compression_string(unsigned long); extern struct image_summary *new_summary_entry(struct image_summary *,int,int); extern struct image_summary *last_summary_entry(struct image_summary *); extern struct image_summary *destroy_summary(struct image_summary *); extern int lock_number(struct image_summary *); extern void print_fileformat(struct image_summary *); extern void print_tag_address(unsigned long,unsigned long,int,char *); extern unsigned long print_entry(FILE*,unsigned short,struct ifd_entry *, unsigned long,struct image_summary *, char *,int,int,int,int); extern int print_ascii(FILE *,unsigned long,unsigned long); extern int print_unicode(FILE *,unsigned long,unsigned long,unsigned short); extern int show_string(char *,int,int); extern int show_string(char *,int,int); extern int print_header(struct fileheader *,unsigned long); extern int print_tiff_header(unsigned short,unsigned short,unsigned long); extern int value_type_size(unsigned short); extern void print_tagid(struct ifd_entry *,int,int); extern void print_taginfo(struct ifd_entry *,char *,int,int,int,int); extern void print_value(struct ifd_entry *,char *); extern unsigned long print_offset_value(FILE *,unsigned short, struct ifd_entry *,unsigned long, char *,int,int,int); extern unsigned long sum_strip_bytecounts(FILE *,unsigned short,unsigned long, unsigned long,unsigned short); extern void display_end_of_ifd(unsigned long,int,int,int,int,char *,char *); extern int is_offset(struct ifd_entry *); extern int is_a_long_offset(struct ifd_entry *); extern char *value_type_name(unsigned short); extern char *tagname(unsigned short); extern char *interop_tagname(unsigned short); extern char *gps_tagname(unsigned short); extern char *get_type_name(int); extern void putindent(int); extern void extraindent(int); extern void pushcolor(int); extern void popcolor(); extern void printred(char *); extern void why(FILE *); extern unsigned long toggle(unsigned long,unsigned long); extern void hexdump(FILE *,unsigned long,unsigned long,unsigned long, int,int,int); /* =============== Routines to interpret values ==================== */ extern void interpret_value(struct ifd_entry *,struct image_summary *); extern void interpret_offset_value(FILE *,struct ifd_entry *,unsigned short, unsigned long); /* ================= Private IFDs ==================== */ extern unsigned long process_private_ifd(FILE *,unsigned short,unsigned long, unsigned long,unsigned long, unsigned short,struct image_summary *, char *,char *,int,int,int); extern unsigned long print_private_entry(FILE *,unsigned short,struct ifd_entry *, unsigned long,unsigned short, struct image_summary *, char *,char *,int,int,int); extern void print_private_taginfo(struct ifd_entry *,unsigned short,char *,int,int); extern void print_private_tagid(struct ifd_entry *,unsigned short,int,int); extern void interpret_pe_value(struct ifd_entry *,unsigned short,int,char *); extern unsigned long print_offset_pe_value(FILE *,unsigned short,struct ifd_entry *, unsigned long,unsigned short, struct image_summary *,char *,char*, int,int,int,int); extern char *private_tagname(int,unsigned short,unsigned short); extern int private_value_is_offset(int,unsigned short,unsigned short); extern void print_private_offset_value(FILE *,unsigned short,struct ifd_entry *, unsigned long,unsigned short,char *, char *,int,int,int,int); extern int print_raf_header(FILE *,struct fileheader *,unsigned long); extern unsigned long process_raf(FILE *,unsigned long, struct image_summary *, char *,int); extern void dumpsection(FILE *,unsigned long,unsigned long,int); #endif /* EXTERN_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/agfa_datadefs.h0000644000000000000000000000167613074742216017425 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: agfa_datadefs.h,v 1.1 2005/05/25 15:38:07 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef AGFA_DATADEFS_INCLUDED #define AGFA_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id agfa_model_id[] = { { "SR841", 6, AGFA_SR841, 1, 1 }, { 0, 0, 0, 0, 0 } }; #endif /* AGFA_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/jp2tags.h0000644000000000000000000000444313074742216016241 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: jp2tags.h,v 1.1 2005/05/24 19:08:57 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* tags defined in JP2 spec or "jasper" */ #ifndef JP2TAGS_INCLUDED #define JP2TAGS_INCLUDED #define JP2C_SOC 0xff4f /* Start of code stream */ #define JP2C_SIZ 0xff51 /* Image and tile size */ #define JP2C_COD 0xff52 /* Coding style default */ #define JP2C_COC 0xff53 /* Coding style component */ #define JP2C_TLM 0xff55 /* Tile-part lengths, main header */ #define JP2C_PLM 0xff57 /* Packet length, main header */ #define JP2C_PLT 0xff58 /* Packet length, tile-part header */ #define JP2C_RGN 0xff5e /* Region of interest */ #define JP2C_QCD 0xff5c /* Quantization default */ #define JP2C_QCC 0xff5d /* Quantization component */ #define JP2C_POC 0xff5f /* Progression order default */ #define JP2C_PPM 0xff60 /* Packed packet headers, main header */ #define JP2C_PPT 0xff61 /* Packet packet headers, tile-part header */ #define JP2C_CRG 0xff63 /* Component registration */ #define JP2C_COM 0xff64 /* Comment */ #define JP2C_SOT 0xff90 /* Start of tile-part */ #define JP2C_SOP 0xff91 /* Start of packet */ #define JP2C_EPH 0xff92 /* End of packet header */ #define JP2C_SOD 0xff93 /* Start of data */ #define JP2C_EOC 0xffd9 /* End of code stream */ #endif /* JP2TAGS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/MAKER_NOTES0000644000000000000000000000411013074742216016237 0ustar rootroot# @(#) $Id: MAKER_NOTES,v 1.8 2005/07/05 17:02:24 alex Exp $ Only one camera maker (Foveon, for the Sigma/Foveon camera) currently publishes the form or interpretation of their makernote data; the data is apparently recorded just to make the image file larger. Exifprobe's identification and interpretation of tags in MakerNotes is based largely upon information reverse-engineered by others and posted to the Web (see CREDITS). A few items are based upon examination of images downloaded from websites whose operators are kind enough to make camera images available for download (including some rather *large* images). I recommend that you examine any output for your camera to assure yourself that the associations between tag identifiers and the interpretation of the associated values is reasonable and correct. Please report to me (dhh@virtual-cafe.com) any corrections you think should be made for any make or model of camera, and any additional information you may deduce for any camera (or other device). It should be noted that tag numbers, types, and values shown by exifprobe will be correct if shown...they are read directly from the image file. It is the "interpretation" of tags and associated values which could be suspect. The strategy used by exifprobe to read MakerNotes does *not* depend upon a table of makes and models. The program scans the offset given for the note to see if it can find an ID string, a TIFF header, and/or a valid IFD entry or two at a reasonable offset and in either byteorder. The features it finds are recorded as a "scheme" which is used for reading and printing the MakerNote information. If a valid IFD is found the program consults make and model information for the oddball variations used by some manufacturers (e.g. offsets relative to the start of the note or start of each entry) and to see if tagnames and value interpretations are available. If tagnames and interpretations are not available, the program will print the raw data with tagnames constructed from the tag number. dhh@virtual-cafe.com exifprobe-2.0.1+git20170416-3c2b76/dngtags.h0000644000000000000000000001512113074742216016311 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: dngtags.h,v 1.2 2005/07/12 18:25:13 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef DNGTAGS_INCLUDED #define DNGTAGS_INCLUDED #define DNGTAG_DNGVersion 0xC612 /* 50706 */ #define DNGTAG_DNGBackwardVersion 0xC613 /* 50707 */ #define DNGTAG_UniqueCameraModel 0xC614 /* 50708 */ #define DNGTAG_LocalizedCameraModel 0xC615 /* 50709 */ #define DNGTAG_CFAPlaneColor 0xC616 /* 50710 */ #define DNGTAG_CFALayout 0xC617 /* 50711 */ #define DNGTAG_LinearizationTable 0xC618 /* 50712 */ #define DNGTAG_BlackLevelRepeatDim 0xC619 /* 50713 */ #define DNGTAG_BlackLevel 0xC61A /* 50714 */ #define DNGTAG_BlackLevelDeltaH 0xC61B /* 50715 */ #define DNGTAG_BlackLevelDeltaV 0xC61C /* 50716 */ #define DNGTAG_WhiteLevel 0xC61D /* 50717 */ #define DNGTAG_DefaultScale 0xC61E /* 50718 */ #define DNGTAG_DefaultCropOrigin 0xC61F /* 50719 */ #define DNGTAG_DefaultCropSize 0xC620 /* 50720 */ #define DNGTAG_ColorMatrix1 0xC621 /* 50721 */ #define DNGTAG_ColorMatrix2 0xC622 /* 50722 */ #define DNGTAG_CameraCalibration1 0xC623 /* 50723 */ #define DNGTAG_CameraCalibration2 0xC624 /* 50724 */ #define DNGTAG_ReductionMatrix1 0xC625 /* 50725 */ #define DNGTAG_ReductionMatrix2 0xC626 /* 50726 */ #define DNGTAG_AnalogBalance 0xC627 /* 50727 */ #define DNGTAG_AsShotNeutral 0xC628 /* 50728 */ #define DNGTAG_AsShotWhiteXY 0xC629 /* 50729 */ #define DNGTAG_BaselineExposure 0xC62A /* 50730 */ #define DNGTAG_BaselineNoise 0xC62B /* 50731 */ #define DNGTAG_BaselineSharpness 0xC62C /* 50732 */ #define DNGTAG_BayerGreenSplit 0xC62D /* 50733 */ #define DNGTAG_LinearResponseLimit 0xC62E /* 50734 */ #define DNGTAG_CameraSerialNumber 0xC62F /* 50735 */ #define DNGTAG_LensInfo 0xC630 /* 50736 */ #define DNGTAG_ChromaBlurRadius 0xC631 /* 50737 */ #define DNGTAG_AntiAliasStrength 0xC632 /* 50738 */ #define DNGTAG_ShadowScale 0xC633 /* 50739 */ #define DNGTAG_DNGPrivateData 0xC634 /* 50740 */ #define DNGTAG_MakerNoteSafety 0xC635 /* 50741 */ #define DNGTAG_CalibrationIlluminant1 0xC65A /* 50778 */ #define DNGTAG_CalibrationIlluminant2 0xC65B /* 50779 */ #define DNGTAG_BestQualityScale 0xC65C /* 50780 */ #define DNGTAG_RawDataUniqueID 0xC65D /* 50781 */ #define DNGTAG_OriginalRawFileName 0xC68B /* 50827 */ #define DNGTAG_OriginalRawFileData 0xC68C /* 50828 */ #define DNGTAG_ActiveArea 0xC68D /* 50829 */ #define DNGTAG_MaskedAreas 0xC68E /* 50830 */ #define DNGTAG_AsShotICCProfile 0xC68F /* 50831 */ #define DNGTAG_AsShotPreProfileMatrix 0xC690 /* 50832 */ #define DNGTAG_CurrentICCProfile 0xC691 /* 50833 */ #define DNGTAG_CurrentPreProfileMatrix 0xC692 /* 50834 */ /* DNG 1.2.0 */ #define DNGTAG_ColorimetricReference 0xC6BF /* 50879 */ #define DNGTAG_CameraCalibrationSignature 0xC6F3 /* 50931 */ #define DNGTAG_ProfileCalibrationSignature 0xC6F4 /* 50932 */ #define DNGTAG_ExtraCameraProfiles 0xC6F5 /* 50933 */ #define DNGTAG_AsShotProfileName 0xC6F6 /* 50934 */ #define DNGTAG_NoiseReductionApplied 0xC6F7 /* 50935 */ #define DNGTAG_ProfileName 0xC6F8 /* 50936 */ #define DNGTAG_ProfileHueSatMapDims 0xC6F9 /* 50937 */ #define DNGTAG_ProfileHueSatMapData1 0xC6FA /* 50938 */ #define DNGTAG_ProfileHueSatMapData2 0xC6FB /* 50939 */ #define DNGTAG_ProfileToneCurve 0xC6FC /* 50940 */ #define DNGTAG_ProfileEmbedPolicy 0xC6FD /* 50941 */ #define DNGTAG_ProfileCopyright 0xC6FE /* 50942 */ #define DNGTAG_ForwardMatrix1 0xC714 /* 50964 */ #define DNGTAG_ForwardMatrix2 0xC715 /* 50965 */ #define DNGTAG_PreviewApplicationName 0xC716 /* 50966 */ #define DNGTAG_PreviewApplicationVersion 0xC717 /* 50967 */ #define DNGTAG_PreviewSettingsName 0xC718 /* 50968 */ #define DNGTAG_PreviewPreviewSettingsDigest 0xC719 /* 50969 */ #define DNGTAG_PreviewPreviewColorSpace 0xC71A /* 50970 */ #define DNGTAG_PreviewPreviewDateTime 0xC71B /* 50971 */ #define DNGTAG_RawImageDigest 0xC71C /* 50972 */ #define DNGTAG_OriginalRawFileDigest 0xC71D /* 50973 */ #define DNGTAG_SubTileBlockSize 0xC71E /* 50974 */ #define DNGTAG_RowInterleaveFactor 0xC71F /* 50975 */ #define DNGTAG_ProfileLookTableDims 0xC725 /* 50981 */ #define DNGTAG_ProfileLookTableData 0xC726 /* 50982 */ /* DNG 1.3.0 */ #define DNGTAG_OpcodeList1 0xC740 /* 51008 */ #define DNGTAG_OpcodeList2 0xC741 /* 51009 */ #define DNGTAG_OpcodeList3 0xC74E /* 51022 */ #define DNGTAG_NoiseProfile 0xC761 /* 51041 */ /* Cinema DNG */ #define DNGTAG_TimeCodes 0xC763 /* 51043 */ #define DNGTAG_FrameRate 0xC764 /* 51044 */ #define DNGTAG_TStop 0xC772 /* 51058 */ #define DNGTAG_ReelName 0xC789 /* 51081 */ #define DNGTAG_CameraLabel 0xC7A1 /* 51105 */ /* DNG 1.4.0 */ #define DNGTAG_OriginalDefaultFinalSize 0xC791 /* 51089 */ #define DNGTAG_OriginalBestQualityFinalSize 0xC792 /* 51090 */ #define DNGTAG_OriginalDefaultCropSize 0xC793 /* 51091 */ #define DNGTAG_ProfileHueSatMapEncoding 0xC7A3 /* 51107 */ #define DNGTAG_ProfileLookTableEncoding 0xC7A4 /* 51108 */ #define DNGTAG_BaselineExposureOffset 0xC7A5 /* 51109 */ #define DNGTAG_DefaultBlackRender 0xC7A6 /* 51110 */ #define DNGTAG_NewRawImageDigest 0xC7A7 /* 51111 */ #define DNGTAG_RawToPreviewGain 0xC7A8 /* 51112 */ #define DNGTAG_DefaultUserCrop 0xC7B5 /* 51125 */ #endif /* DNGTAGS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/process.c0000644000000000000000000063657513074742216016361 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002, 2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: process.c,v 1.47 2005/07/25 22:05:10 alex Exp $"; #endif /* Process segment types such as TIFF IFD, JPEG APP segments, and */ /* JPEG basic segments. */ #include #include #include #include #include #include #include "defs.h" #include "summary.h" #include "maker.h" #include "datadefs.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "ciff.h" /* Read and decode a TIFF IFD, attempting to describe the location */ /* and structure of the data as it is read. Entry values which live */ /* at an offset from the entry are displayed following the last entry */ /* in the IFD (actually after the "next ifd offset") if */ /* VALUE_AT_OFFSET is set in Print_options, so that most IFDS will */ /* have a VALUES section following the entry lines, in just the */ /* manner that the file is laid out by spec. Tag names for offset */ /* values are repeated when the value is printed. If VALUE_AT_OFFSET */ /* is not set, the value is printed immediately, unless the tag */ /* represents a subsection, in which case the offset of the */ /* subsection is printed as the tag value, and the subsection handled */ /* in a second pass, after all entries are done. */ /* Returns a file offset which represents the "highest" position of */ /* the file pointer read by this routine and its subroutines, which */ /* may be used by the caller to read the remainder of the file. This */ /* number (less one) is printed as the offset of the end of the IFD. */ /* At the same time, the function notices non-zero values of "next */ /* ifd offset" which may be contained in this ifd, and passes it as */ /* "max_offset" to routines which read subifds, on the assumption */ /* that this ifd should not write into the next ifd. That value is */ /* used to mark segments which appear to be out of order in the file. */ /* If the routine detects by this means that *this* ifd is outside */ /* its natural bounds, and cannot be contained within its parent, it */ /* returns 0, rather than the maximum value offset, so that the */ /* parent routine will not improperly alter its maximum offset. */ /* The arguments are the byteorder to be used when reading integer */ /* data (usually taken from the TIFF header), the offset of the start */ /* of the directory, relative to the TIFF header, the offset of the */ /* TIFF header from the beginning of the file, the sequence number of */ /* the IFD, and formatting values (indent and address width) to be */ /* used when printing. */ /* The routine also attempts to record the location, size, image type */ /* and compression method used for actual image data contained within */ /* or referenced by a tiff IFD. This information is printed at the */ /* end, as a summary of images found in the file. */ unsigned long process_tiff_ifd(FILE *inptr,unsigned short byteorder,unsigned long ifd_offset, unsigned long fileoffset_base,unsigned long max_offset, struct image_summary *summary_entry,char *parent_name, int ifdtype,int ifdnum,int subifdnum,int indent) { struct ifd_entry *entry_ptr = NULL; struct image_summary *tmp_summary_entry; unsigned long cur_ifd_offset,next_ifd_offset,current_offset; unsigned long start_entry_offset,entry_offset,value_offset; unsigned long value_start_offset = 0UL; unsigned long offset_limit = 0UL; unsigned long max_value_offset = 0UL; unsigned long max_ifd_offset = 0UL; unsigned long thn_offset = 0UL; /* JPegInterchangeFormat */ unsigned long thn_length = 0UL; /* JpegInterChangeFormat */ unsigned long tmp_length = 0L; unsigned long alt_length = 0L; unsigned long limit_offset = 0L; unsigned long filesize = 0UL; unsigned short marker,alt_byteorder = 0; int invalid_entry = 0; int value_is_offset = 0; int use_second_pass = 0; int status = 0; int chpr = 0; int entry_num,num_entries,i; char dirnamebuf[16]; char *ifdname,*prefix,*dirname,*nameoftag,*tprefix; char *fulldirname = CNULL; char *listname = CNULL; if(inptr == (FILE *)0) { fprintf(stderr,"%s: no open file pointer to read TIFF IFD\n", Progname); return(0L); } if(Debug & OUT_DEBUG) { printf("PS=%d,",(Print_options & PRINT_SECTION) > 0); printf("PV=%d,",(Print_options & PRINT_VALUE) > 0); printf("PO=%d,",(Print_options & PRINT_OFFSET) > 0); printf("PVAO=%d\n",(Print_options & PRINT_VALUE_AT_OFFSET) > 0); } filesize = get_filesize(inptr); next_ifd_offset = ifd_offset + fileoffset_base; while(next_ifd_offset) { clearerr(inptr); /* max_offset, if set, is the maximum offset which the parent */ /* is willing to claim. max_ifd_offset is the maximum offset */ /* reached by this ifd, which may be constrained by the */ /* "next_ifd_offset" of chained ifds. */ cur_ifd_offset = next_ifd_offset; if(max_offset && (cur_ifd_offset > max_offset)) prefix = ">"; /* outside the parent */ else prefix = "@"; print_tag_address(SECTION,cur_ifd_offset,indent,prefix); switch(ifdtype) { case TIFF_IFD: if(PRINT_SECTION) chpr += printf("",ifdnum); ifdname = "IFD"; sprintf(dirnamebuf,"Ifd%d",ifdnum); dirname = dirnamebuf; break; case TIFF_SUBIFD: if(PRINT_SECTION) chpr += printf("",subifdnum,ifdnum); ifdname = "SubIFD"; sprintf(dirnamebuf,"SubIfd%d",subifdnum); dirname = dirnamebuf; break; case INTEROP_IFD: if(PRINT_SECTION) chpr += printf(""); ifdname = "Interoperability SubIFD"; dirname = "Interop"; break; case GPS_IFD: if(PRINT_SECTION) chpr += printf(""); ifdname = "GPS SubIFD"; dirname = "Gps"; break; case EXIF_IFD: /* This shouldn't happen */ if(PRINT_SECTION) chpr += printf(""); ifdname = "EXIF IFD"; dirname = "Exif"; break; case MAKER_SUBIFD: ifdname = "MakerNote SubIFD"; if(PRINT_SECTION) chpr += printf("<%s>",ifdname); dirname = CNULL; break; default: if(PRINT_SECTION) chpr += printf("",ifdtype); /* SECTION */ ifdname = "UNKNOWN IFD TYPE"; dirname = CNULL; break; } if(dirname) listname = fulldirname = splice(parent_name,".",dirname); else listname = parent_name; num_entries = read_ushort(inptr,byteorder,cur_ifd_offset); max_value_offset = max_ifd_offset = 0L; if(ferror(inptr) || feof(inptr)) { chpr = newline(chpr); printred("#========= WARNING: FAILED to read number of entries for IFD at offset "); chpr += printf("%lu",cur_ifd_offset); if(ferror(inptr)) why(stdout); chpr = newline(chpr); goto blewit; } /* The file pointer is now at the start of the IFD entries */ current_offset = entry_offset = start_entry_offset = ftell(inptr); if(PRINT_SECTION) { chpr += printf(" %d entries ",num_entries); chpr += printf("starting at file offset %#lx=%lu", start_entry_offset,start_entry_offset); chpr = newline(chpr); } if((summary_entry == NULL) || summary_entry->entry_lock) summary_entry = new_summary_entry(summary_entry,0,ifdtype); else summary_entry = last_summary_entry(summary_entry); if(summary_entry) { summary_entry->datatype = ifdtype; summary_entry->imageformat = IMGFMT_NOIMAGE; summary_entry->filesubformat |= FILESUBFMT_TIFF; if((ifdtype == TIFF_IFD) || (ifdtype == TIFF_SUBIFD) || (ifdtype == MAKER_SUBIFD)) { summary_entry->ifdnum = ifdnum; summary_entry->subifdnum = subifdnum; } } use_second_pass = value_is_offset = 0; indent += SMALLINDENT; for(entry_num = 0; entry_num < num_entries; ++entry_num) { entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) { print_tag_address(ENTRY,entry_offset,indent,prefix); print_taginfo(entry_ptr,listname,SMALLINDENT,ifdtype,ifdnum,subifdnum); if((PRINT_ENTRY)) printred(" INVALID ENTRY"); chpr = newline(chpr); /* If there are a few invalid entries in an otherwise */ /* valid IFD, the invalid entries should be reported. */ /* An invalid IFD, with 50,000 entries or so, all */ /* invalid, should be nipped in the bud. */ clearerr(inptr); current_offset = ftell(inptr); if(max_offset > 0) limit_offset = max_offset; else { if(fseek(inptr,0L,SEEK_END) != -1) { limit_offset = ftell(inptr); fseek(inptr,current_offset,SEEK_SET); } } /* If there's an error on input, or we can't check */ /* for absurd num_entries, give up. */ if(!ferror(inptr) && !feof(inptr) && (limit_offset > 0)) { /* If the number of entries would read past the */ /* size of the IFD, or past EOF, give up */ if((ifd_offset + (12 * num_entries)) < limit_offset) { /* Limit the number of consecutive failures. */ /* An apparently valid entry resets the count */ /* to 0. */ if(invalid_entry++ < MAX_INVALID_ENTRIES) { entry_offset = current_offset; clearerr(inptr); continue; } } } chpr = newline(chpr); goto blewit; } invalid_entry = 0; current_offset = ftell(inptr); switch(entry_ptr->tag) { case TIFFTAG_OldSubFileType: /* old, deprecated */ if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_TIFFEP; if(entry_ptr->value == 1) summary_entry->subfiletype = PRIMARY_TYPE; else if(entry_ptr->value == 2) summary_entry->subfiletype = REDUCED_RES_TYPE; else if(entry_ptr->value == 3) summary_entry->subfiletype = PAGE_TYPE; } break; case TIFFTAG_NewSubFileType: if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_TIFFEP; if(entry_ptr->value == 0) summary_entry->subfiletype = PRIMARY_TYPE; else if(entry_ptr->value == 1) summary_entry->subfiletype = REDUCED_RES_TYPE; else if(entry_ptr->value == 2) summary_entry->subfiletype = PAGE_TYPE; else if(entry_ptr->value == 3) summary_entry->subfiletype = MASK_TYPE; } break; case INTEROPTAG_RelatedImageWidth: /* ###%%% ??? */ case TIFFTAG_ImageWidth: if(summary_entry) summary_entry->pixel_width = entry_ptr->value; break; case INTEROPTAG_RelatedImageLength: /* ###%%% ??? */ case TIFFTAG_ImageLength: if(summary_entry) summary_entry->pixel_height = entry_ptr->value; break; case TIFFTAG_Compression: if(summary_entry) { summary_entry->compression = entry_ptr->value; if((entry_ptr->value == 7) || (entry_ptr->value == 6)) { if(entry_ptr->value == 6) summary_entry->filesubformat |= FILESUBFMT_TIFFOLD; /* Some of this may have to be undone */ /* later, if we find out they lied */ summary_entry->entry_lock = lock_number(summary_entry); if(summary_entry->imageformat == 0) summary_entry->imageformat = IMGFMT_JPEG; } else { summary_entry->entry_lock = lock_number(summary_entry); if(summary_entry->imageformat == 0) summary_entry->imageformat = IMGFMT_TIFF; if(summary_entry->compression == 34713) summary_entry->filesubformat |= FILESUBFMT_NEF; /* If there is no subfiletype tag, this */ /* could be the primary, or it could be a */ /* thumbnail */ if(summary_entry->subfiletype <= POSSIBLE_PRIMARY_TYPE) summary_entry->subfiletype = POSSIBLE_PRIMARY_TYPE; } } break; case TIFFTAG_PhotometricInterpretation: /* It appears that the PMI values used in Olympus */ /* ORF files (1 or 2 for the primary image) do */ /* not correspond to legitimate TIFF PMI values. */ /* Record them "as is" here, but they shouldn't */ /* be *interpreted* in the same way as TIFF files */ if(summary_entry) summary_entry->imagesubformat = entry_ptr->value | IMGSUBFMT_VALUE_IS_PMI; break; case TIFFTAG_JPEGInterchangeFormat: /* actually an offset... */ /* This method of JPEG-in-TIFF is discouraged by */ /* the TIFF spec (after Technote 2), for good and */ /* sufficient reason> */ thn_offset = entry_ptr->value + fileoffset_base; break; case TIFFTAG_JPEGInterchangeFormatLength: thn_length = entry_ptr->value; break; case TIFFTAG_StripOffsets: case TIFFTAG_TileOffsets: /* If there are multiple strips, this will be */ /* wrong, but will be overwritten in the second */ /* pass. */ if(summary_entry) { summary_entry->offset = entry_ptr->value; if((summary_entry->compression != 6) && (summary_entry->compression != 7)) { summary_entry->entry_lock = lock_number(summary_entry); } } break; case TIFFTAG_StripByteCounts: case TIFFTAG_TileByteCounts: /* This may also be overwritten in the second */ /* pass */ if(summary_entry) { summary_entry->length = entry_ptr->value; if((summary_entry->compression != 6) && (summary_entry->compression != 7)) { summary_entry->entry_lock = lock_number(summary_entry); } } break; case TIFFEPTAG_TIFF_EPStandardID: if(summary_entry) summary_entry->filesubformat |= FILESUBFMT_TIFFEP; break; case TIFFTAG_Make: case TIFFTAG_Model: case TIFFTAG_Software: { char *makename,*modelname,*swname; /* These items will be read and printed in */ /* the second pass, if one is made. This */ /* grabs them and records them in globals, */ /* which may be used later by the makernote */ /* code. */ switch(entry_ptr->tag) { case TIFFTAG_Make: if(Make_name == NULL) { Make_name = strdup_value(entry_ptr, inptr, fileoffset_base); } break; case TIFFTAG_Model: if(Model_name == NULL) { Model_name = strdup_value(entry_ptr, inptr, fileoffset_base); } break; case TIFFTAG_Software: if(Software_name == NULL) { Software_name = strdup_value(entry_ptr, inptr, fileoffset_base); } break; } } break; case TIFFTAG_BitsPerSample: if(summary_entry) { /* Do not override information from */ /* earlier sections; the tiff section in */ /* e.g. MRW sections can lie if the image */ /* has been improperly handled by */ /* other-party software. */ if(summary_entry->bps[0] == 0) { if(entry_ptr->count < 3) { summary_entry->bps[0] = (unsigned short)entry_ptr->value & 0xffff; if(entry_ptr->count == 2) summary_entry->bps[1] = (unsigned short)((entry_ptr->value & 0xffff0000) >> 16); } else { summary_entry->bps[0] = read_ushort(inptr,byteorder,entry_ptr->value); for(i = 1; (i < entry_ptr->count) && (i < MAXSAMPLE); ++i) summary_entry->bps[i] = read_ushort(inptr,byteorder,HERE); } } } break; case TIFFTAG_SamplesPerPixel: if((summary_entry) && (summary_entry->spp == 0)) summary_entry->spp = entry_ptr->value; break; case DNGTAG_DNGVersion: /* A DNG-specific tag */ if(summary_entry) summary_entry->filesubformat |= FILESUBFMT_DNG; break; case TIFFTAG_CR2_0xc5d9: /* A CR2-specific tag */ if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_CR2; if((summary_entry->compression == 6) && (summary_entry->imagesubformat == IMGSUBFMT_RGB)) { summary_entry->subfiletype = REDUCED_RES_TYPE; } } break; case TIFFTAG_CR2_0xc5d8: case TIFFTAG_CR2_0xc5e0: case TIFFTAG_CR2_SLICE: /* These tags appear (so far) only in the */ /* weird IFD containing the lossless jpeg */ /* primary. It is possible to check for other */ /* things, e.g. just compression, strip */ /* offset and bytecount (1 each), but for now */ /* just assume that any of these tags means */ /* CR2. The compression at this point will be */ /* 6, but will be re-marked JPEG_SOF_3 when */ /* the image is scanned. */ if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_CR2; summary_entry->subfiletype = PRIMARY_TYPE; } break; case TIFFTAG_SubIFDtag: case EXIFTAG_ExifIFDPointer: case EXIFTAG_GPSInfoIFDPointer: case EXIFTAG_Interoperability: case TIFFTAG_PrintIM: use_second_pass++; break; default: break; } print_tag_address(ENTRY,entry_offset,indent,prefix); value_offset = print_entry(inptr,byteorder,entry_ptr,fileoffset_base, summary_entry,listname,ifdtype, ifdnum, subifdnum, SMALLINDENT); /* Keep track of how far into the file reading progresses */ if(value_offset == 0UL) value_offset = current_offset; if(value_offset > max_value_offset) max_value_offset = value_offset; if((is_offset(entry_ptr))) ++use_second_pass; entry_offset = current_offset; } next_ifd_offset = read_ulong(inptr,byteorder,current_offset); if(next_ifd_offset > 0UL) { if((PRINT_VALUE) && (PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(SECTION,current_offset,indent,prefix); chpr += printf("**** next IFD offset %lu",next_ifd_offset); next_ifd_offset += fileoffset_base; chpr += printf("(+ %lu = %#lx/%lu)",fileoffset_base, next_ifd_offset,next_ifd_offset); } else next_ifd_offset += fileoffset_base; /* Corrupt file will cause infinite loops. So we abort. * It is possible this can be worked around better. * See Issue #9 https://github.com/hfiguiere/exifprobe/issues/9 */ if(next_ifd_offset < ftell(inptr)) { printred("\nReading IFD backwards. INVALID FILE. ABORTING.\n"); exit(1); } else if (next_ifd_offset > filesize) { printred("\nReading IFD past EOF. INVALID FILE. ABORTING.\n"); exit(1); } /* We should be able to tolerate these */ if ((ifdtype != TIFF_IFD) && (ifdtype != TIFF_SUBIFD)) { if(PRINT_SECTION) printred(" INVALID NEXT IFD OFFSET "); else { chpr = newline(chpr); printred("# ========= WARNING: INVALID NEXT IFD OFFSET "); chpr += printf("%ld in ",next_ifd_offset); /* Until someone creates a subifd in a subifd, */ /* this is enough. */ if(ifdtype == TIFF_IFD) chpr += printf("IFD %d =========",ifdnum); else if(ifdtype == TIFF_SUBIFD) chpr += printf("SUBIFD %d of IFD %d =========",subifdnum,ifdnum); else chpr += printf("%s =========",ifdname); } next_ifd_offset = 0L; } /* This is the limit of offsets which should be part of */ /* this ifd; a limit may have been passed in from the */ /* parent, if it had a length of this section. This will */ /* replace that number unconditionally, although it may */ /* be that one should be checked against the other... */ /* This can be checked against max_value_offset, and */ /* value_offset in the second pass. */ max_offset = next_ifd_offset; chpr = newline(chpr); } else { if((PRINT_VALUE) && (PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(SECTION,current_offset,indent,prefix); chpr += printf("**** next IFD offset 0"); chpr = newline(chpr); } } if(max_value_offset < current_offset) max_ifd_offset = current_offset; else max_ifd_offset = max_value_offset; if(Debug & END_OF_SECTION_DEBUG) printf("mo=%lu, mvo=%lu, mio=%lu, nio=%lu, ol=%lu\n",max_offset,max_value_offset,max_ifd_offset,next_ifd_offset,offset_limit); /* If we made it through the first pass, we should be able to */ /* get some info from the second pass, so don't let a failure */ /* here stop us. It will fail later. */ if(ferror(inptr) || feof(inptr)) { chpr += printf("#========= WARNING: READ NEXT IFD OFFSET FAILED ========="); chpr = newline(chpr); why(stdout); clearerr(inptr); /* keep going... */ } else current_offset = ftell(inptr); value_offset = current_offset; if(use_second_pass) { if((PRINT_VALUE) && (PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(SECTION,value_offset,indent,prefix); chpr += printf("============= VALUES, "); if(ifdtype == TIFF_IFD) chpr += printf("IFD %d",ifdnum); else if(ifdtype == TIFF_SUBIFD) chpr += printf("SubIFD %d of IFD %d",subifdnum,ifdnum); else if(ifdtype == INTEROP_IFD) chpr += printf("Interoperability SubIFD"); else if(ifdtype == EXIF_IFD) /* shouldn't happen */ chpr += printf("EXIF IFD"); else if(ifdtype == MAKER_SUBIFD) chpr += printf("%s",ifdname); else chpr += printf("UNKNOWN IFD TYPE %d",ifdtype); chpr += printf(" ============"); chpr = newline(chpr); } /* Second pass, to evaluate entries which are stored */ /* indirectly (the value requires more than 4 bytes). */ /* This time we have to explicitly seek to each entry, */ /* since the value processing may send the file pointer */ /* off to exotic places. */ entry_offset = start_entry_offset; for(entry_num = 0; entry_num < num_entries; ++entry_num) { entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) { /* If the first pass made it through invalid */ /* entries, this pass should just ignore them and */ /* quietly continue. */ clearerr(inptr); entry_offset = current_offset = ftell(inptr); continue; } entry_offset = current_offset = ftell(inptr); value_is_offset = is_offset(entry_ptr); switch(entry_ptr->tag) { case TIFFTAG_SubIFDtag: value_offset = process_subifd(inptr,byteorder, entry_ptr, fileoffset_base,0L, summary_entry,listname, ifdnum,++subifdnum,TIFF_SUBIFD, indent); /* subifds are not part of the IFD; throw */ /* away this value for now. */ value_offset = 0; break; case EXIFTAG_ExifIFDPointer: value_start_offset = entry_ptr->value + fileoffset_base; value_offset = process_exif_ifd(inptr,byteorder, entry_ptr->value,fileoffset_base, next_ifd_offset,summary_entry,listname, ifdnum,indent); if(max_offset && (value_offset > max_offset)) offset_limit = value_offset; break; case EXIFTAG_GPSInfoIFDPointer: value_offset = process_gps_ifd(inptr,byteorder, entry_ptr->value,fileoffset_base, next_ifd_offset,summary_entry,listname, ifdnum,indent); break; case EXIFTAG_Interoperability: /* This doesn't belong in a TIFF IFD, but */ /* be prepared. */ /* Also we make sure we are not calling on */ /* the same ifd offset */ PUSHCOLOR(INTEROP_COLOR); if (entry_ptr->value != ifd_offset) { value_offset = process_tiff_ifd(inptr,byteorder, entry_ptr->value,fileoffset_base, next_ifd_offset,summary_entry, listname,INTEROP_IFD,ifdnum,0, indent); } value_offset = 0; POPCOLOR(); break; case TIFFTAG_StripOffsets: case TIFFTAG_TileOffsets: /* Update the summary values set in the first */ /* pass */ /* Bad strip offsets seem to be one of the */ /* more common errors, especially when images */ /* have been processed by editing software. */ /* Offsets greater than filesize are easy to */ /* detect, so check for them, and test to see */ /* if they're just written with the wrong */ /* byteorder. */ /* ###%%% need to record number of offsets */ /* and location of offsets for multi-tile */ /* (multi-strip?) images jpeg-compressed by */ /* tile (seen in DNG) */ if((value_is_offset) && summary_entry) { alt_byteorder = byteorder; summary_entry->chunkhow = entry_ptr->tag; summary_entry->chunktype = entry_ptr->value_type; /* ###%%% combine short and long cases; just switch read_xxx() */ if(entry_ptr->value_type == LONG) { unsigned long tmp_offset; tmp_offset = read_ulong(inptr,byteorder,entry_ptr->value + fileoffset_base); summary_entry->offset = tmp_offset; summary_entry->offset_loc = entry_ptr->value +fileoffset_base; summary_entry->noffsets = entry_ptr->count; if(tmp_offset > filesize) { chpr = newline(chpr); PUSHCOLOR(HI_RED); print_filename(); chpr += printf("# WARNING: initial stripoffset (%#lx/%lu) > filesize...wrong byteorder? ", tmp_offset,tmp_offset); print_byteorder(byteorder,1); chpr = newline(chpr); if(byteorder == TIFF_MOTOROLA) alt_byteorder = TIFF_INTEL; else alt_byteorder = TIFF_MOTOROLA; tmp_offset = read_ulong(inptr,alt_byteorder, entry_ptr->value + fileoffset_base); print_filename(); chpr += printf("# WARNING: initial stripoffset using alt byteorder ["); print_byteorder(alt_byteorder,1); chpr += printf("] is %#lx/%lu ", tmp_offset,tmp_offset); chpr = newline(chpr); if(tmp_offset < filesize) summary_entry->offset = tmp_offset; POPCOLOR(); } } else { unsigned short tmp_offset; tmp_offset = read_ushort(inptr,byteorder,entry_ptr->value + fileoffset_base); summary_entry->offset = tmp_offset; summary_entry->offset_loc = entry_ptr->value +fileoffset_base; summary_entry->noffsets = entry_ptr->count; if((unsigned long)tmp_offset > filesize) { chpr = newline(chpr); PUSHCOLOR(HI_RED); print_filename(); chpr += printf("# WARNING: initial stripoffset (%#x/%u) > filesize...wrong byteorder? ", tmp_offset,tmp_offset); print_byteorder(byteorder,1); chpr = newline(chpr); if(byteorder == TIFF_MOTOROLA) alt_byteorder = TIFF_INTEL; else alt_byteorder = TIFF_MOTOROLA; tmp_offset = read_ushort(inptr,alt_byteorder, entry_ptr->value + fileoffset_base); print_filename(); chpr += printf("# WARNING: initial stripoffset using alt byteorder ["); print_byteorder(alt_byteorder,1); chpr += printf("] is %#x/%u ", tmp_offset,tmp_offset); chpr = newline(chpr); if(tmp_offset < filesize) summary_entry->offset = tmp_offset; POPCOLOR(); } } } if((PRINT_VALUE) && ((PRINT_VALUE_AT_OFFSET) && value_is_offset)) { print_tag_address(ENTRY,fileoffset_base + entry_ptr->value, indent,prefix); print_tagid(entry_ptr,SMALLINDENT,ifdtype); value_offset = print_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,listname, ifdtype,indent,1); } break; case TIFFTAG_StripByteCounts: case TIFFTAG_TileByteCounts: if((value_is_offset) && summary_entry) { tmp_length = sum_strip_bytecounts(inptr,byteorder, entry_ptr->value + fileoffset_base, entry_ptr->count,entry_ptr->value_type); summary_entry->length = tmp_length; summary_entry->length_loc = entry_ptr->value + fileoffset_base; if(summary_entry->noffsets != entry_ptr->count) printred(" # Warning: number of bytecounts != number of offsets"); if(tmp_length > filesize) { chpr = newline(chpr); PUSHCOLOR(HI_RED); print_filename(); chpr += printf("# WARNING: total stripbytecount (%#lx/%lu) > filesize (%lu) ... wrong byteorder? ", tmp_length,tmp_length,filesize); print_byteorder(byteorder,1); chpr = newline(chpr); if(byteorder == TIFF_MOTOROLA) alt_byteorder = TIFF_INTEL; else alt_byteorder = TIFF_MOTOROLA; alt_length = sum_strip_bytecounts(inptr,alt_byteorder, entry_ptr->value + fileoffset_base, entry_ptr->count,entry_ptr->value_type); print_filename(); chpr += printf("# WARNING: total stripbytecount using alt byteorder ["); print_byteorder(alt_byteorder,1); chpr += printf("] is %#lx/%lu ", alt_length,alt_length); chpr = newline(chpr); if(alt_length < filesize) summary_entry->length = alt_length; else { print_filename(); chpr += printf("# WARNING: file may be truncated"); chpr = newline(chpr); } POPCOLOR(); } } if((PRINT_VALUE) && ((PRINT_VALUE_AT_OFFSET) && value_is_offset)) { print_tag_address(ENTRY,fileoffset_base + entry_ptr->value, indent,prefix); print_tagid(entry_ptr,SMALLINDENT,ifdtype); value_offset = print_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,listname, ifdtype,indent,1); /* ###%%% find a way to print total */ /* ByteCount, at least in LIST mode */ } break; case TIFFTAG_JPEGTables: nameoftag = tagname(entry_ptr->tag); if((PRINT_VALUE) && ((PRINT_VALUE_AT_OFFSET) && value_is_offset)) { if(PRINT_SECTION) { chpr = newline(chpr); print_tag_address(ENTRY,fileoffset_base + entry_ptr->value, indent,prefix); chpr += printf("# Start of %s length %lu",nameoftag, entry_ptr->count); chpr = newline(chpr); } } marker = read_ushort(inptr,TIFF_MOTOROLA,fileoffset_base + entry_ptr->value); /* Need a new entry; this IFD's entry may be */ /* used for an image, but may not be locked */ /* yet. */ tmp_summary_entry = new_summary_entry(summary_entry,0,IMGFMT_JPEG); value_offset = process_jpeg_segments(inptr, fileoffset_base + entry_ptr->value, marker,entry_ptr->count, tmp_summary_entry,listname, prefix,indent+SMALLINDENT); if(tmp_summary_entry) tmp_summary_entry->imagesubformat = TIFFTAG_JPEGTables; if((PRINT_VALUE) && ((PRINT_VALUE_AT_OFFSET) && value_is_offset)) { if((PRINT_SECTION)) { /* ###%% check for early EOI; */ if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(ENTRY,fileoffset_base + entry_ptr->value + entry_ptr->count + 1, indent,prefix); chpr += printf("# End of %s",nameoftag); print_jpeg_status(); chpr = newline(chpr); } } break; case TIFFTAG_PrintIM: if(next_ifd_offset && (cur_ifd_offset > next_ifd_offset)) prefix = "+"; else prefix = "@"; process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, entry_ptr->count,tagname(entry_ptr->tag), listname,prefix,indent); chpr = newline(0); break; default: if((PRINT_VALUE) && ((PRINT_VALUE_AT_OFFSET) && value_is_offset)) { print_tag_address(ENTRY,fileoffset_base + entry_ptr->value, indent,prefix); print_tagid(entry_ptr,SMALLINDENT,ifdtype); value_offset = print_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,listname, ifdtype,indent,1); } break; } if(value_offset == 0L) /* bad entry; try the next one */ clearerr(inptr); else if(value_offset > filesize) goto blewit; else if(value_offset > max_value_offset) max_value_offset = value_offset; } } else if(current_offset > max_value_offset) max_value_offset = current_offset; max_ifd_offset = max_value_offset; indent -= SMALLINDENT; /* max_ifd_offset is the maximum offset we've read so far; */ /* max_offset, if set, is the highest offset of this ifd, */ /* according to either the parent or the recently-read */ /* next_ifd_offset. */ if(max_offset && (max_ifd_offset > max_offset)) prefix = "?"; if(Debug & END_OF_SECTION_DEBUG) printf("mo=%lu, mvo=%lu, mio=%lu, nio=%lu, ol=%lu, prefix=%s\n", max_offset,max_value_offset,max_ifd_offset, next_ifd_offset,offset_limit,prefix); /* ================== show jpeg thumbnail =================== */ if(thn_offset || thn_length) { int startindent; if(Debug & END_OF_SECTION_DEBUG) printf("mo=%lu, ol=%lu, thno=%lu\n",max_offset,offset_limit,thn_offset); /* This will be set only if a JpegInterchangeFormat tag */ /* has been seen, so this must be a JPEG thumbnail. The */ /* Exif spec indicates that the data should be written */ /* within the values section of the IFD, so scan and */ /* report here. If it appears to be written outside the */ /* bounds of the IFD, mark it. "max_offset" is the */ /* parent's idea (if any) of the extent of the IFD. */ /* "offset_limit" is the beginning of the Exif section, */ /* if present. */ if(max_offset && (thn_offset > max_offset)) tprefix = ">"; else if(offset_limit && (thn_offset > offset_limit)) tprefix = "+"; else tprefix = prefix; startindent = charsprinted(); print_tag_address(SECTION,thn_offset,indent + SMALLINDENT,tprefix); if(PRINT_SECTION) { if(thn_length) chpr += printf("#### Start of JPEG thumbnail data for IFD %d",ifdnum); else { PUSHCOLOR(RED); chpr += printf("#### ZERO LENGTH JPEG thumbnail for IFD %d",ifdnum); POPCOLOR(); } if((ifdtype == TIFF_SUBIFD) || (subifdnum >= 0)) chpr += printf(" SubIFD %d",subifdnum); if(ifdtype == MAKER_IFD) chpr += printf(" %s",ifdname); else if(ifdtype == MAKER_SUBIFD) chpr += printf(" %s",ifdname); if(thn_length) chpr += printf(", length %lu ####",thn_length); else { if(summary_entry && (summary_entry->imageformat == IMGFMT_JPEG) && ((summary_entry->compression == 6) || (summary_entry->compression == 7))) { summary_entry->offset = thn_offset; } } chpr = newline(chpr); } if(thn_length) { unsigned short tmp_marker; marker = read_ushort(inptr,TIFF_MOTOROLA,thn_offset); if(marker != JPEG_SOI) { if((marker & 0xff) != 0xd) /* possibly BAD_SOI */ { tmp_marker = read_ushort(inptr,TIFF_MOTOROLA,thn_offset - fileoffset_base); if(tmp_marker == JPEG_SOI) { chpr = newline(chpr); print_filename(); putchar('#'); if((PRINT_SECTION)) putindent(startindent - 1); PUSHCOLOR(HI_RED); chpr += printf(" WARNING: JPEGInterChangeFormat offset is botched"); chpr = newline(chpr); if((PRINT_SECTION)) { print_filename(); putchar('#'); putindent(startindent - 1); chpr += printf(" WARNING: (possibly) correct offset follows:"); chpr = newline(chpr); } marker = tmp_marker; thn_offset -= fileoffset_base; print_tag_address(SECTION,thn_offset,indent + SMALLINDENT,tprefix); if((LIST_MODE)) { /* mock up the entry; the last read */ /* entry is finished, so it can be */ /* overwritten */ entry_ptr->tag = TIFFTAG_JPEGInterchangeFormat; entry_ptr->value_type = LONG; entry_ptr->count = 1; entry_ptr->value = thn_offset - fileoffset_base; value_offset = print_entry(inptr,byteorder,entry_ptr,fileoffset_base, summary_entry,parent_name,ifdtype, ifdnum, subifdnum,MEDIUMINDENT); } else if((PRINT_SECTION)) chpr += printf("#### Start of JPEG thumbnail data for IFD %d",ifdnum); POPCOLOR(); chpr = newline(chpr); } } } /* Is this the image described by this ifd, or an */ /* add-on? ...or both... */ if(summary_entry && ((summary_entry->compression == 7) || (summary_entry->compression == 6))) { /* If there's a length set in the summary, assume */ /* there's already an image associated with this */ /* entry. */ if((summary_entry->length == 0UL)) { /* Othersise, make sure the jpeg processor */ /* uses the current summary entry */ summary_entry->entry_lock = 0; summary_entry->imageformat = IMGFMT_NOIMAGE; if(Debug & SCAN_DEBUG) { chpr = newline(chpr); printred("DEBUG:"); chpr += printf(" UNLOCK **** "); chpr += printf(" offset=%lu, length=%lu ",summary_entry->offset, summary_entry->length); chpr = newline(chpr); } } } value_offset = 0; if(marker) value_offset = process_jpeg_segments(inptr,thn_offset,marker, thn_length,summary_entry,parent_name, tprefix,indent+SMALLINDENT); /* Even if the jpeg was bad, there will be a summary */ /* entry for it. It may not be the current one. */ tmp_summary_entry = last_summary_entry(summary_entry); tmp_summary_entry->ifdnum = ifdnum; tmp_summary_entry->subifdnum = subifdnum; tmp_summary_entry->datatype = ifdtype; if(PRINT_SECTION) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(SECTION,thn_offset + thn_length - 1,indent + SMALLINDENT,tprefix); chpr += printf("#### End of JPEG thumbnail data for IFD %d",ifdnum); if((ifdtype == TIFF_SUBIFD) || (subifdnum >= 0)) chpr += printf(" SubIFD %d",subifdnum); if(ifdtype == MAKER_IFD) chpr += printf(" %s",ifdname); else if(ifdtype == MAKER_SUBIFD) chpr += printf(" %s",ifdname); chpr += printf(", length %lu ####",thn_length); print_jpeg_status(); chpr = newline(chpr); } if(Debug & END_OF_SECTION_DEBUG) printf("vo=%lu, mo=%lu, mvo=%lu, mio=%lu, nio=%lu, ol=%lu\n",value_offset, max_offset,max_value_offset,max_ifd_offset,next_ifd_offset,offset_limit); if((value_offset == 0L) || (value_offset > (thn_offset + thn_length))) value_offset = thn_offset + thn_length; if(value_offset > max_value_offset) max_value_offset = value_offset; } /* done with this thumbnail */ thn_offset = thn_length = 0; if((max_value_offset > max_ifd_offset) && ((offset_limit == 0) || (max_value_offset < offset_limit))) { max_ifd_offset = max_value_offset; } } /* ================== end show jpeg thumbnail =============== */ /* The TIFF spec does not specify, directly, where an IFD */ /* ends. If there is a next IFD, the start of that IFD */ /* (next_ifd_offset) gives an upper bound for the current */ /* IFD, but for the last IFD, guessing is necessary. The IFD */ /* should end when the last offset value given in the */ /* directory entries is written; MANY camera files which use */ /* this format write items, particularly thumbnails, at */ /* arbitrary offsets, and the TIFF spec itself allows offsets */ /* to point anywhere in the file. The Exif spec declares that */ /* "thumbnails" should be written within the values section */ /* of the IFD, but (oddly) not the "primary". Add subifds, */ /* disagreements between TIFF and TIFFEP about which IFD */ /* should describe the primary, multiple "thumbnails" of */ /* various sizes, etc. and it is very difficult to think of */ /* an IFD as a "container" (as it should be) or to decide */ /* where it ends. */ /* The thumbnails written above should be a part of the IFD, */ /* according to the Exif spec and common sense. All other */ /* offset values for the IFD have been written, so it is time */ /* to declare that the IFD ends. If there is information */ /* giving the maximum size of this IFD, items outside the */ /* bounds have already been marked so. */ if(Debug & END_OF_SECTION_DEBUG) printf("vo=%lu, mo=%lu, mvo=%lu, mio=%lu, nio=%lu, ol=%lu\n",value_offset, max_offset,max_value_offset,max_ifd_offset,next_ifd_offset,offset_limit); /* ========= show end of ifd =========== */ if((prefix && (*prefix == '>')) || (max_offset == 0) || (max_ifd_offset < max_offset)) { display_end_of_ifd(max_ifd_offset,ifdtype,ifdnum,subifdnum,indent, ifdname,prefix); } else display_end_of_ifd(max_offset,ifdtype,ifdnum,subifdnum,indent, ifdname,prefix); /* = ================= show ifd image ======== =========== */ /* ###%%% not showing offset and length in LIST MODE */ if(summary_entry && ((summary_entry->fileformat == TIFF_MAGIC) || (summary_entry->fileformat == ORF1_MAGIC) || (summary_entry->fileformat == ORF2_MAGIC)) && ((ifdtype == TIFF_IFD) || (ifdtype == TIFF_SUBIFD)) && (summary_entry->length > 0)) { if(Debug & END_OF_SECTION_DEBUG) printf("mo=%lu, ol=%lu, seo=%lu\n",max_offset,offset_limit,summary_entry->offset); /* These are being displayed "inline" with the IFD that */ /* describes them; try to mark them as shown out of */ /* place. */ if(max_offset && (summary_entry->offset > max_offset)) tprefix = ">"; else if(offset_limit && (summary_entry->offset > offset_limit)) tprefix = "+"; else tprefix = prefix; /* Scan jpeg images and check for mismarked compression */ /* types */ switch(summary_entry->compression) { case 6: if(summary_entry->imagesubformat & IMGSUBFMT_RGB) { /* Perhaps this should be done unconditionally... */ max_value_offset = summary_entry->offset + summary_entry->length; if(summary_entry->filesubformat & FILESUBFMT_CR2) { /* Actually uncompressed RGB */ summary_entry->compression = 1; summary_entry->imageformat = IMGFMT_JPEG | IMGFMT_MISMARKED; } print_tag_address(SECTION,summary_entry->offset,indent,tprefix); if(PRINT_SECTION) { chpr += printf("<=-=-=> Start of RGB data for IFD %d,", summary_entry->ifdnum); if(summary_entry->datatype == TIFF_SUBIFD) chpr += printf(" SubIFD %d,",summary_entry->subifdnum); chpr += printf(" data length %lu",summary_entry->length); chpr = newline(chpr); chpr = newline(chpr); if((PRINT_VALUE)) dumpsection(inptr,summary_entry->offset,summary_entry->length, indent + SMALLINDENT); print_tag_address(SECTION,max_value_offset - 1,indent,"-"); chpr += printf(" End of RGB data"); if((max_value_offset - 1) > filesize) { PUSHCOLOR(RED); chpr += printf(" (TRUNCATED at %lu)",filesize); POPCOLOR(); summary_entry->imagesubformat |= IMGSUBFMT_TRUNCATED; } chpr = newline(chpr); } else if((PRINT_ENTRY)) { /* ###%%% pseudo-tags fpr LIST Mode here */ print_tag_address(ENTRY,HERE,indent,"*"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",listname); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"RGBImageData"); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%-9lu",summary_entry->offset,summary_entry->length); chpr = newline(chpr); } /* done */ break; } /* fall through */ case 7: print_tag_address(SECTION,summary_entry->offset,indent,tprefix); if(PRINT_SECTION) { chpr += printf("<=====> Start of JPEG data for IFD %d,",summary_entry->ifdnum); if(summary_entry->datatype == TIFF_SUBIFD) chpr += printf(" SubIFD %d,",summary_entry->subifdnum); chpr += printf(" data length %lu",summary_entry->length); chpr = newline(chpr); } else if((PRINT_ENTRY)) { /* ###%%% pseudo-tags fpr LIST Mode here */ print_tag_address(ENTRY,HERE,indent,"*"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",listname); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"JpegImageData"); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%-9lu",summary_entry->offset,summary_entry->length); chpr = newline(chpr); } /* If this IFD describes a JPEG image, the */ /* entry must go unlocked to the jpeg */ /* processor, which will lock it. This may */ /* cause problems if the IFD *also* contains */ /* JpegInterchangeFormat tags. It happens. */ if(Debug & SCAN_DEBUG) { chpr = newline(chpr); printred("DEBUG:"); chpr += printf(" UNLOCK **** "); chpr += printf(" offset=%lu, length=%lu ",summary_entry->offset, summary_entry->length); chpr = newline(chpr); } summary_entry->entry_lock = 0; summary_entry->imageformat = IMGFMT_NOIMAGE; value_offset = 0; /* If compression == 7, PMI is CFA, and there are */ /* multiple tile offsets, each tile may be separately */ /* compressed. */ marker = read_ushort(inptr,TIFF_MOTOROLA,summary_entry->offset); if((PRINT_SECTION) && (summary_entry->compression == 7) && (summary_entry->chunkhow == TIFFTAG_TileOffsets) && (summary_entry->noffsets > 1)) { unsigned long tmp_offset; unsigned long offset_loc; unsigned long length_loc; /* Individually compressed tiles Show the first */ /* and last, and just check for JPEG_SOI for */ /* those in the middle. There should be an option */ /* to display them all and/or dump the section */ /* (although '-O' can be used for that). */ offset_loc = summary_entry->offset_loc; length_loc = summary_entry->length_loc; if(marker) { tmp_length = read_ulong(inptr,byteorder,length_loc); value_offset = process_jpeg_segments(inptr,summary_entry->offset,marker, tmp_length,summary_entry,parent_name, tprefix,indent+MEDIUMINDENT); } for(i = 1; i < summary_entry->noffsets; ++i) { if(summary_entry->chunktype == LONG) { offset_loc += 4; length_loc += 4; tmp_offset = read_ulong(inptr,byteorder,offset_loc); tmp_length = read_ulong(inptr,byteorder,length_loc); } else { offset_loc += 2; length_loc += 2; tmp_offset = read_ushort(inptr,byteorder,offset_loc); tmp_length = read_ushort(inptr,byteorder,length_loc); } marker = read_ushort(inptr,TIFF_MOTOROLA,tmp_offset); if(feof(inptr) || ferror(inptr)) { value_offset = summary_entry->offset + summary_entry->length; clearerr(inptr); break; } if((i + 1) == summary_entry->noffsets) { /* Note that this one goes into the */ /* summary */ chpr = newline(chpr); value_offset = process_jpeg_segments(inptr,tmp_offset,marker, tmp_length,summary_entry,parent_name, tprefix,indent+MEDIUMINDENT); } else if(marker == JPEG_SOI) { /* This checks that there is at least an */ /* SOI where it is supposed to be, but */ /* avoids putting every tile in the */ /* summary, which would be very boring. */ if(i != 1) chpr += printf(","); if((i == 1) || ((i % 10) == 0)) { chpr = newline(chpr); print_tag_address(SECTION,HERE,indent + MEDIUMINDENT,"JPEG TILES"); } chpr += printf("[%d]",i + 1); } else { ; } if(feof(inptr) || ferror(inptr)) { clearerr(inptr); value_offset = summary_entry->offset + summary_entry->length; break; } } } else { if(marker) value_offset = process_jpeg_segments(inptr,summary_entry->offset,marker, summary_entry->length,summary_entry,parent_name, tprefix,indent+MEDIUMINDENT); } if(PRINT_SECTION) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(SECTION,summary_entry->offset + summary_entry->length - 1, indent,tprefix); chpr += printf(" End of JPEG data ===="); if(value_offset > (summary_entry->offset + summary_entry->length)) value_offset = summary_entry->offset + summary_entry->length; print_jpeg_status(); if((value_offset - 1) > filesize) { PUSHCOLOR(RED); chpr += printf(" (TRUNCATED at %lu)",filesize); POPCOLOR(); summary_entry->imagesubformat |= IMGSUBFMT_TRUNCATED; } chpr = newline(chpr); } if(value_offset == 0L) clearerr(inptr); else if(value_offset > max_value_offset) max_value_offset = value_offset; if((max_value_offset - 1) > filesize) summary_entry->imagesubformat |= IMGSUBFMT_TRUNCATED; break; case 0: /* this shouldn't happen... */ default: if((summary_entry) && (summary_entry->imageformat != IMGFMT_JPEG)) { max_value_offset = summary_entry->offset + summary_entry->length; if(PRINT_SECTION) { print_tag_address(SECTION,summary_entry->offset,indent,tprefix); chpr += printf("<=-=-=> Start of "); print_imageformat(summary_entry); print_imagesubformat(summary_entry); print_imagecompression(summary_entry); chpr += printf(" image data for IFD %d,", summary_entry->ifdnum); if(summary_entry->datatype == TIFF_SUBIFD) chpr += printf(" SubIFD %d,",summary_entry->subifdnum); chpr += printf(" data length %lu",summary_entry->length); chpr = newline(chpr); chpr = newline(chpr); if((PRINT_VALUE)) dumpsection(inptr,summary_entry->offset,summary_entry->length, indent + SMALLINDENT); print_tag_address(SECTION,max_value_offset - 1,indent,tprefix); chpr += printf(" End of image data"); if((max_value_offset - 1) > filesize) { PUSHCOLOR(RED); chpr += printf(" (TRUNCATED at %lu)",filesize); POPCOLOR(); summary_entry->imagesubformat |= IMGSUBFMT_TRUNCATED; } chpr = newline(chpr); } else if((PRINT_ENTRY)) { /* ###%%% pseudo-tags fpr LIST Mode here */ print_tag_address(ENTRY,HERE,indent,"*"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",listname); chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,"ImageData"); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%-9lu",summary_entry->offset,summary_entry->length); if((max_value_offset - 1) > filesize) { PUSHCOLOR(RED); chpr += printf(" # TRUNCATED at %lu",filesize); POPCOLOR(); summary_entry->imagesubformat |= IMGSUBFMT_TRUNCATED; } chpr = newline(chpr); } else if((max_value_offset -1) > filesize) summary_entry->imagesubformat |= IMGSUBFMT_TRUNCATED; } break; } if((max_value_offset > max_ifd_offset) && ((offset_limit == 0) || (max_value_offset < offset_limit))) max_ifd_offset = max_value_offset; } /* =========== end show ifd image ============ */ /* ###%%% temporary debug */ if(Debug & END_OF_SECTION_DEBUG) printf("mo=%lu, mvo=%lu, mio=%lu, nio=%lu, ol=%lu\n", max_offset,max_value_offset,max_ifd_offset,next_ifd_offset,offset_limit); /* lock the summary entry for this ifd, even if it doesn't */ /* describe an actual image */ if(summary_entry && (summary_entry->entry_lock <= 0)) summary_entry->entry_lock = lock_number(summary_entry); /* Prepare for the next ifd */ if(ifdtype == TIFF_IFD) { ++ifdnum; subifdnum = -1; } else if(ifdtype == TIFF_SUBIFD) ++subifdnum; if(fulldirname) free(fulldirname); fulldirname = CNULL; /* If there is a next ifd, "max_offset" must be reset. */ if(next_ifd_offset) max_offset = 0; } newline(chpr); return(max_ifd_offset); blewit: clearerr(inptr); if(PRINT_SECTION) { /* Indicate the end of the IFD */ indent -= SMALLINDENT; current_offset = ftell(inptr); if((prefix && (*prefix == '>')) || (max_offset == 0) || (max_ifd_offset < max_offset)) { display_end_of_ifd(max_ifd_offset,ifdtype,ifdnum,subifdnum,indent, ifdname,prefix); } else display_end_of_ifd(max_offset,ifdtype,ifdnum,subifdnum,indent, ifdname,prefix); } if(fulldirname) free(fulldirname); return(0L); } /* Create a summary entry and link it into a list of image */ /* descriptions to be printed at the end of the file output. */ struct image_summary * new_summary_entry(struct image_summary *prev_entry,int fileformat,int datatype) { struct image_summary *new = NULL; int chpr = 0; /* Make entries only for types which describe image data, i.e. */ /* not EXIF, Interop, etc. */ switch(datatype) { case EXIF_IFD: case INTEROP_IFD: case GPS_IFD: break; default: if(Debug & SCAN_DEBUG) { chpr = newline(1); printred("DEBUG: NEW SUMMARY "); } new = (struct image_summary *)malloc(sizeof(struct image_summary)); if(new) { if(Debug & SCAN_DEBUG) printf("%#lx\n",(unsigned long)new); memset(new,0,sizeof(struct image_summary)); new->datatype = datatype; new->ifdnum = -1; new->subifdnum = -1; new->length = 0; new->offset = 0; new->subfiletype = -1; memset(new->filesubformatAPPN,0,16); if(prev_entry) { if(Debug & SCAN_DEBUG) { printred("DEBUG: PREV ENTRY "); chpr += printf("%#x, next=%#x, offset=%ld, lock=%d", (unsigned int)prev_entry, (unsigned int)prev_entry->next_entry, prev_entry->offset,prev_entry->entry_lock); chpr = newline(chpr); } /* make sure to attach at the end of the chain */ while(prev_entry->next_entry) { prev_entry = prev_entry->next_entry; if(Debug & SCAN_DEBUG) { printred(" PREV ENTRY "); chpr += printf("%#x, next=%#x, offset=%ld, lock=%d", (unsigned int)prev_entry, (unsigned int)prev_entry->next_entry, prev_entry->offset,prev_entry->entry_lock); chpr = newline(chpr); } } new->prev_entry = prev_entry; if(Debug & SCAN_DEBUG) { printred("DEBUG: FOUND PREV ENTRY "); chpr += printf("%#x, next=%#x, offset=%ld, lock=%d", (unsigned int)prev_entry, (unsigned int)prev_entry->next_entry, prev_entry->offset,prev_entry->entry_lock); chpr = newline(chpr); } if(prev_entry->fileformat) new->fileformat = prev_entry->fileformat; prev_entry->next_entry = new; if(Debug & SCAN_DEBUG) { printred("DEBUG: NEW ENTRY "); chpr += printf(" next=%#x, prev offset=%d, prev lock=%d", (unsigned int)prev_entry->next_entry, (unsigned int)prev_entry->offset,prev_entry->entry_lock); chpr = newline(chpr); } } else new->fileformat = fileformat; } else { printred("Memory allocation for image summary failed"); if(prev_entry) chpr += printf(" summary will be incomplete"); else chpr += printf(" no summary will be printed"); newline(chpr); } if(Debug & SCAN_DEBUG) chpr = newline(1); break; } return(new); } /* Move to the end of the summary entry chain passed as argument */ struct image_summary * last_summary_entry(struct image_summary *summary_entry) { if(summary_entry) { while(summary_entry->next_entry) summary_entry = summary_entry->next_entry; } return(summary_entry); } /* Lock an entry with a sequence number, primarily so entries can be */ /* tracked while debugging. A locked entry is "in use', requiring */ /* creation of a new entry for a new image */ int lock_number(struct image_summary *summary_entry) { int number = 0; struct image_summary *prev_entry,*last_entry; if(summary_entry) { if(summary_entry->entry_lock) number = summary_entry->entry_lock; /* don't change it */ else if((last_entry = last_summary_entry(summary_entry))) { /* Find the highest existing lock number; go to the end */ /* and scan back to the head */ if(last_entry->entry_lock > 0) number = last_entry->entry_lock + 1; prev_entry = last_entry->prev_entry; while(prev_entry) { if(prev_entry->entry_lock >= number) number = prev_entry->entry_lock + 1; prev_entry = prev_entry->prev_entry; } if(number <= 0) number = 1; } else number = 1; } if(Debug & SCAN_DEBUG) { (void)newline(1); printred("DEBUG: LOCK SUMMARY"); printf(" %#x ==> %d",(unsigned int)summary_entry,number); (void)newline(1); (void)newline(1); } return(number); } struct image_summary * destroy_summary(struct image_summary *summary_entry) { struct image_summary *prev_entry = NULL; /* start at the end and work back to the head */ if(Debug & SCAN_DEBUG) printred("DEBUG: DESTROY SUMMARY "); if(summary_entry) { while(summary_entry->next_entry) summary_entry = summary_entry->next_entry; while(summary_entry) { prev_entry = summary_entry->prev_entry; free(summary_entry); summary_entry = prev_entry; } } return(prev_entry); } /* Read, decode, and print an EXIF IFD at 'exif_offset', noticing */ /* MakerNotes and "Interoperability" IFDs as they go by. The offset */ /* of each entry and offset value is recorded and printed, and the */ /* offset of the last byte read is reported as the end of the IFD. If */ /* all goes well, the offset at which the caller should next read */ /* (just past the end of the offset values) is returned. If an */ /* unrecoverable error occurs, 0UL is returned. */ /* This looks remoarkably like process_tiff_ifd(), except that it */ /* expects EXIF tags, and doesn't expect further IFDs to be chained */ /* from it. If it does find a chained IFD, it processes it as a */ /* normal IFD (not another EXIF IFD). It should probably just warn */ /* and ignore it. */ unsigned long process_exif_ifd(FILE *inptr,unsigned short byteorder, unsigned long exif_offset,unsigned long fileoffset_base, unsigned long max_offset,struct image_summary *summary_entry, char *parent_name,int ifdnum,int indent) { struct ifd_entry *entry_ptr; unsigned long max_value_offset = 0L; unsigned long next_ifd_offset,current_offset,max_exif_offset; unsigned long start_entry_offset,entry_offset,value_offset; unsigned long value_start_offset = 0UL; unsigned long next_max_offset = 0UL; int entry_num,num_entries,value_is_offset,use_second_pass; int chpr = 0; char *prefix; char *fulldirname = CNULL; if(inptr == (FILE *)0) { fprintf(stderr,"%s: no open file pointer to read EXIF IFD\n", Progname); return(0L); } PUSHCOLOR(EXIF_COLOR); /* If the exif segment appears to be beyond the end of the parent */ /* ifd, mark the start address to call attention. */ if(max_offset && (exif_offset > max_offset)) prefix = "+"; else prefix = "@"; if(summary_entry) summary_entry->filesubformat |= FILESUBFMT_EXIF; max_exif_offset = max_offset; print_tag_address(SECTION,exif_offset + fileoffset_base,indent,prefix); if(PRINT_SECTION) chpr += printf(" (in IFD %d)",ifdnum); num_entries = read_ushort(inptr,byteorder,exif_offset + fileoffset_base); if(ferror(inptr) || feof(inptr)) goto blewit; current_offset = entry_offset = start_entry_offset = ftell(inptr); if(PRINT_SECTION) { chpr += printf(" %d entries ",num_entries); chpr += printf("starting at file offset %#lx=%lu", current_offset,current_offset); chpr = newline(chpr); } use_second_pass = value_is_offset = 0; fulldirname = splice(parent_name,".","Exif"); indent += SMALLINDENT; /* The direct entries */ for(entry_num = 0; entry_num < num_entries; ++entry_num) { entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) { int invalid_entry = 0; unsigned long limit_offset = 0L; print_tag_address(ENTRY,entry_offset,indent,prefix); chpr += printf(" INVALID EXIF ENTRY (%lu)",entry_ptr->value); chpr = newline(chpr); clearerr(inptr); current_offset = ftell(inptr); if(max_offset > 0) limit_offset = max_offset; else { if(fseek(inptr,0L,SEEK_END) != -1) { limit_offset = ftell(inptr); fseek(inptr,current_offset,SEEK_SET); } } /* If there's an error on input, or we can't check */ /* for absurd num_entries, give up. */ if(!ferror(inptr) && !feof(inptr) && (limit_offset > 0)) { /* If the number of entries would read past the */ /* size of the IFD, or past EOF, give up */ if((entry_offset + (12 * num_entries)) < limit_offset) { /* Limit the number of consecutive failures. */ /* An apparently valid entry resets the count */ /* to 0. */ if(invalid_entry++ < MAX_INVALID_ENTRIES) { entry_offset = current_offset; continue; } } } chpr = newline(chpr); goto blewit; } current_offset = ftell(inptr); switch(entry_ptr->tag) { case EXIFTAG_PixelXDimension: if(summary_entry) summary_entry->primary_width = entry_ptr->value; break; case EXIFTAG_PixelYDimension: if(summary_entry) summary_entry->primary_height = entry_ptr->value; break; case EXIFTAG_Interoperability: case EXIFTAG_MakerNote: use_second_pass++; break; default: break; } print_tag_address(ENTRY,entry_offset,indent,prefix); value_offset = print_entry(inptr,byteorder,entry_ptr,fileoffset_base, summary_entry,fulldirname,EXIF_IFD, ifdnum,-1,SMALLINDENT); if(value_offset == 0UL) value_offset = current_offset; if(value_offset > max_value_offset) max_value_offset = value_offset; if((PRINT_VALUE_AT_OFFSET) && (is_offset(entry_ptr))) ++use_second_pass; entry_offset = current_offset; } next_ifd_offset = read_ulong(inptr,byteorder,current_offset); /* There should be no next_ifd_offset for the Exif Ifd. */ /* I am not confident, however, that someone won't eventually */ /* chain Exif ifds, so just handle them, and let the error */ /* messages fly. */ if(next_ifd_offset > 0L) { if((PRINT_VALUE) && (PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(SECTION,current_offset,indent + SMALLINDENT,prefix); chpr += printf("**** next IFD offset %lu ",next_ifd_offset); next_ifd_offset += fileoffset_base; if(next_ifd_offset < ftell(inptr)) { printred("BAD NEXT IFD OFFSET"); next_ifd_offset = 0L; } else chpr += printf("(+ %lu = %#lx/%lu)",fileoffset_base, next_ifd_offset,next_ifd_offset); chpr = newline(chpr); } else next_ifd_offset += fileoffset_base; /* This should never happen */ max_exif_offset = next_ifd_offset; } else { if((PRINT_VALUE) && (PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(SECTION,current_offset,indent,prefix); chpr += printf("**** next IFD offset 0"); chpr = newline(chpr); } } if(ferror(inptr) || feof(inptr)) { chpr += printf(" READ NEXT IFD OFFSET FAILED "); chpr = newline(chpr); why(stdout); clearerr(inptr); /* keep going... */ } else current_offset = ftell(inptr); value_offset = current_offset; /* Second pass, to evaluate entries which are stored indirectly. */ /* This occurs when the value requires more than 4 bytes, AND for */ /* certain LONG values which are intended to be used as offsets */ /* (and should have their own type defined in the spec), */ if(use_second_pass) { if((PRINT_VALUE) && (PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(SECTION,value_offset,indent,prefix); chpr += printf("============= VALUES, EXIF IFD ============"); chpr = newline(chpr); } entry_offset = start_entry_offset; for(entry_num = 0; entry_num < num_entries; ++entry_num) { entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) { /* If the first pass made it through invalid entries, */ /* this pass should just ignore them and quietly */ /* continue. */ entry_offset = current_offset = ftell(inptr); continue; } current_offset = entry_offset = ftell(inptr); switch(entry_ptr->tag) { case EXIFTAG_Interoperability: PUSHCOLOR(INTEROP_COLOR); value_offset = process_tiff_ifd(inptr,byteorder, entry_ptr->value,fileoffset_base, max_exif_offset,summary_entry, fulldirname,INTEROP_IFD,ifdnum,0, indent); POPCOLOR(); break; case EXIFTAG_MakerNote: /* ###%%% temporary debug */ if(Debug & END_OF_SECTION_DEBUG) printf("mo=%lu, mvo=%lu, ", max_offset,max_value_offset); value_start_offset = entry_ptr->value + fileoffset_base; if(max_offset && (value_start_offset > max_offset) && (entry_ptr->count > 4)) { next_max_offset = value_start_offset; } if(Debug & END_OF_SECTION_DEBUG) printf("vso=%lu, nmo=%lu\n",value_start_offset,next_max_offset); value_offset = process_makernote(inptr,byteorder, entry_ptr,fileoffset_base,max_exif_offset, summary_entry,fulldirname,indent); if(Debug & END_OF_SECTION_DEBUG) printf("mo=%lu, mvo=%lu, ",max_offset,max_value_offset); if(Debug & END_OF_SECTION_DEBUG) printf("MNvo=%lu, mo=%lu\n",value_offset,max_offset); break; default: if((PRINT_VALUE) && ((PRINT_VALUE_AT_OFFSET) && is_offset(entry_ptr))) { print_tag_address(ENTRY,fileoffset_base + entry_ptr->value, indent,prefix); print_tagid(entry_ptr,SMALLINDENT,EXIF_IFD); value_offset = print_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname, EXIF_IFD,indent,1); } break; } if(value_offset > max_value_offset) max_value_offset = value_offset; if(max_offset && (value_offset > max_offset)) { next_max_offset = value_start_offset; if(Debug & END_OF_SECTION_DEBUG) printf("nmo=%lu\n",next_max_offset); } } } else if(current_offset > max_value_offset) max_value_offset = current_offset; indent -= SMALLINDENT; if(max_offset && (max_value_offset > max_offset)) print_tag_address(SECTION,max_offset - 1,indent,"<"); else print_tag_address(SECTION,max_value_offset - 1,indent,"-"); if(PRINT_SECTION) { chpr += printf(""); chpr = newline(chpr); } POPCOLOR(); /* This shouldn't happen. */ if(next_ifd_offset) { printred("#========= WARNING! CHAINING NEXT IFD FROM EXIF IFD ========="); chpr = newline(1); value_offset = process_tiff_ifd(inptr,byteorder,next_ifd_offset, fileoffset_base,max_offset,summary_entry,fulldirname, EXIF_IFD,++ifdnum,-1,indent); if(value_offset > max_value_offset) max_value_offset = value_offset; } if(fulldirname) free(fulldirname); if(next_max_offset) max_value_offset = next_max_offset; if(Debug & END_OF_SECTION_DEBUG) printf("exmvo=%lu\n",max_value_offset); return(max_value_offset); blewit: clearerr(inptr); current_offset = ftell(inptr); print_tag_address(SECTION,current_offset - 1,indent,"-"); if(PRINT_SECTION) { chpr += printf(""); chpr = newline(chpr); } if(fulldirname) free(fulldirname); POPCOLOR(); return(0L); } /* Read an ifd entry describing one or more subifd offsets, and */ /* process the IFDs found at those offsets as TIFF image file */ /* directories. This is used for TIFF6/TIFFEP SubIFDtags. The return */ /* is 0L if something went wrong. */ unsigned long process_subifd(FILE *inptr,unsigned short byteorder, struct ifd_entry *subfile_entry, unsigned long fileoffset_base,unsigned long max_offset, struct image_summary *summary_entry,char *parent_name, int ifdnum,int subifdnum,int ifdtype,int indent) { unsigned long entry_offset; unsigned long subifd_offset; unsigned long max_value_offset = 0L; int chpr = 0; int nsubifds,num; if(inptr && subfile_entry) { entry_offset = subfile_entry->value + fileoffset_base; nsubifds = subfile_entry->count; if(subifdnum >= 0) { if(nsubifds > 1) { if((PRINT_VALUE_AT_OFFSET)) { if(max_offset && (entry_offset > max_offset)) print_tag_address(SECTION,entry_offset,indent,"+"); else print_tag_address(SECTION,entry_offset,indent,"@"); if(PRINT_SECTION) { chpr += printf("%s - %lu offsets: [max parent offset = %lu]", tagname(subfile_entry->tag),subfile_entry->count, max_offset); } for(num = 0; num < nsubifds; ++num) { subifd_offset = read_ulong(inptr,byteorder,entry_offset) + fileoffset_base; entry_offset = ftell(inptr); /* where to get next one */ if((PRINT_SECTION)) chpr += printf(" %lu",subifd_offset); if(ferror(inptr) || feof(inptr)) break; /* goto blewit; */ } if(PRINT_SECTION) chpr = newline(chpr); } entry_offset = subfile_entry->value + fileoffset_base; for(num = 0; num < nsubifds; ++num) { subifd_offset = read_ulong(inptr,byteorder,entry_offset) + fileoffset_base; /* where to get next one */ entry_offset = ftell(inptr); /* The next subifd offset suggests a maximum for */ /* this subifd; at least until some nitwit writes */ /* the second one first. Doesn't help for the */ /* last one, though. */ if(num < (nsubifds - 1)) max_offset = read_ulong(inptr,byteorder,HERE); else max_offset = 0; if(ferror(inptr) || feof(inptr)) goto blewit; max_value_offset = process_tiff_ifd(inptr,byteorder, subifd_offset,fileoffset_base, max_offset,summary_entry,parent_name, ifdtype,ifdnum,subifdnum + num, indent); /* ###%%% don't we check for errors here??? */ } } else { max_value_offset = process_tiff_ifd(inptr,byteorder, subfile_entry->value,fileoffset_base, max_offset,summary_entry,parent_name, ifdtype,ifdnum,subifdnum, indent); } } else { printred("Negative subifd number"); chpr += printf(" %d, ifdtype %d not processed for IFD %d",subifdnum,ifdtype,ifdnum); chpr = newline(chpr); goto blewit; } } else { fprintf(stderr,"%s: no open file pointer to read EXIF\n",Progname); max_value_offset = 0L; } setcharsprinted(chpr); return(max_value_offset); blewit: /* we're going to keep trying, because the caller's next offset */ /* may be ok. */ clearerr(inptr); return(0L); } /* Just a bare bones GPS routine; no interpretation is done. */ unsigned long process_gps_ifd(FILE *inptr,unsigned short byteorder, unsigned long gps_offset,unsigned long fileoffset_base, unsigned long max_offset,struct image_summary *summary_entry, char *parent_name,int ifdnum,int indent) { struct ifd_entry *entry_ptr; unsigned long max_value_offset = 0L; unsigned long next_ifd_offset,current_offset,max_gps_offset; unsigned long start_entry_offset,entry_offset,value_offset; int entry_num,num_entries,value_is_offset,use_second_pass; int chpr = 0; char *fulldirname = CNULL; if(inptr == (FILE *)0) { fprintf(stderr,"%s: no open file pointer to read GPS IFD\n", Progname); return(0L); } PUSHCOLOR(GPS_COLOR); /* If the gps segment appears to be beyond the start of the */ /* parent ifd, mark the start address funny. */ if(max_offset && (gps_offset > max_offset)) print_tag_address(SECTION,gps_offset + fileoffset_base,indent,"^"); else print_tag_address(SECTION,gps_offset + fileoffset_base,indent,"@"); if(PRINT_SECTION) chpr += printf(" (in IFD %d)",ifdnum); num_entries = read_ushort(inptr,byteorder,gps_offset + fileoffset_base); if(ferror(inptr) || feof(inptr)) goto blewit; current_offset = entry_offset = start_entry_offset = ftell(inptr); if(PRINT_SECTION) { chpr += printf(" %d entries ",num_entries); chpr += printf("starting at file offset %#lx=%lu", current_offset,current_offset); chpr = newline(chpr); } use_second_pass = value_is_offset = 0; fulldirname = splice(parent_name,".","Gps"); indent += SMALLINDENT; /* The direct entries */ for(entry_num = 0; entry_num < num_entries; ++entry_num) { print_tag_address(ENTRY,entry_offset,indent,"@"); entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) { print_tag_address(ENTRY,entry_offset,indent,"@"); chpr += printf(" INVALID (%lu)",entry_ptr->value); chpr = newline(chpr); /* ###%%% replace with check code from process_tiff_ifd() */ goto blewit; } entry_offset = current_offset = ftell(inptr); value_offset = print_entry(inptr,byteorder,entry_ptr,fileoffset_base, summary_entry,fulldirname,GPS_IFD, ifdnum,-1,SMALLINDENT); if(value_offset == 0UL) value_offset = entry_offset; if(value_offset > max_value_offset) max_value_offset = value_offset; if((PRINT_VALUE_AT_OFFSET) && (is_offset(entry_ptr))) ++use_second_pass; } next_ifd_offset = read_ulong(inptr,byteorder,current_offset); /* offsets found in the next pass should be within the bounds of */ /* the ifd. The following helps to detect chunks that are written */ /* "out of place". */ if(next_ifd_offset > 0L) { if((PRINT_VALUE) && (PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(SECTION,current_offset,indent,"@"); chpr += printf("**** next IFD offset %lu ",next_ifd_offset); next_ifd_offset += fileoffset_base; if(next_ifd_offset < ftell(inptr)) { printred("BAD NEXT IFD OFFSET"); next_ifd_offset = 0L; } else chpr += printf("(+ %lu = %#lx/%lu)",fileoffset_base, next_ifd_offset,next_ifd_offset); chpr = newline(chpr); } else next_ifd_offset += fileoffset_base; /* This should never happen */ max_gps_offset = next_ifd_offset; if(max_offset && (max_gps_offset > max_offset)) max_gps_offset = max_offset; } else { max_gps_offset = max_offset; if((PRINT_VALUE) && (PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(SECTION,current_offset,indent,"@"); chpr += printf("**** next IFD offset 0"); chpr = newline(chpr); } } if(ferror(inptr) || feof(inptr)) { chpr += printf(" READ NEXT IFD OFFSET FAILED "); chpr = newline(chpr); why(stdout); clearerr(inptr); /* keep going... */ } else current_offset = ftell(inptr); value_offset = current_offset; /* Make a second pass to print offset values. */ if(use_second_pass) { if((PRINT_VALUE) && (PRINT_SECTION) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(SECTION,value_offset,indent,"@"); chpr += printf("============= VALUES, GPS IFD ============"); chpr = newline(chpr); } /* Second pass, to evaluate entries which are stored */ /* indirectly (the value requires more than 4 bytes). */ entry_offset = start_entry_offset; for(entry_num = 0; entry_num < num_entries; ++entry_num) { entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) { print_tag_address(ENTRY,entry_offset,indent,"@"); chpr += printf(" INVALID (%lu)",entry_ptr->value); chpr = newline(chpr); goto blewit; } current_offset = entry_offset = ftell(inptr); switch(entry_ptr->tag) { default: if((PRINT_VALUE) && ((PRINT_VALUE_AT_OFFSET) && is_offset(entry_ptr))) { print_tag_address(ENTRY,fileoffset_base + entry_ptr->value, indent,"@"); print_tagid(entry_ptr,SMALLINDENT,GPS_IFD); value_offset = print_offset_value(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname, GPS_IFD,indent,1); } break; } if(value_offset > max_value_offset) max_value_offset = value_offset; } } else if(current_offset > max_value_offset) max_value_offset = current_offset; indent -= SMALLINDENT; if(max_offset && (gps_offset > max_offset)) { print_tag_address(SECTION,max_value_offset - 1,indent,">"); max_value_offset = 0L; /* let the caller know. */ } else print_tag_address(SECTION,max_value_offset - 1,indent,"-"); if(PRINT_SECTION) { chpr += printf(""); chpr = newline(chpr); } POPCOLOR(); if(next_ifd_offset) { printred("#========= WARNING! CHAINING NEXT IFD FROM GPS IFD ========="); chpr = newline(1); value_offset = process_tiff_ifd(inptr,byteorder,next_ifd_offset, fileoffset_base,max_offset,NULL,fulldirname, GPS_IFD,-1,-1,indent); if(value_offset > max_value_offset) max_value_offset = value_offset; } if(fulldirname) free(fulldirname); return(max_value_offset); blewit: clearerr(inptr); current_offset = ftell(inptr); print_tag_address(SECTION,current_offset - 1,indent,"-"); if(PRINT_SECTION) { chpr += printf(""); chpr = newline(chpr); } if(fulldirname) free(fulldirname); POPCOLOR(); return(0L); } /* Process JPEG the marker segments between JPEG SOI and EOI. */ /* For the moment, that means just printing them (offset, id, length) */ /* and then moving to the next tag. */ /* The first marker has been read, it's identity and offset are */ /* passed in as arguments. No assumptions are made about the current */ /* file pointer; the first read always begins at the passed */ /* marker_offset. */ /* APP section are noticed, and APP0, APP1, and APP12 section */ /* processed appropriately. Other APP section are reported without */ /* expansion of the section, but may be hex/ascii dumped by option. */ extern unsigned long forward_scan_for_eoi(FILE *,unsigned long, unsigned long,char *,int); unsigned long process_jpeg_segments(FILE *inptr,unsigned long marker_offset,unsigned short tag, unsigned long data_length,struct image_summary *summary_entry, char *parent_name,char *prefix,int indent) { static unsigned long img_pixels = 0L; unsigned long max_offset = 0L; unsigned long dumplength = 0L; unsigned long start_of_jpeg_data; unsigned long found_eoi_offset,after_sos,end_of_section,eof; unsigned short seg_length,tmp; unsigned short img_height = 0; unsigned short img_width = 0; unsigned short bad_soi = 0; int chpr = 0; int had_soi = 0; int status = 0; int i; char *name; static unsigned long max_eoi = 0UL; if(inptr) { start_of_jpeg_data = marker_offset; if(start_of_jpeg_data == 0UL) max_eoi = 0UL; if((summary_entry == NULL) || summary_entry->entry_lock || (summary_entry->imageformat != IMGFMT_NOIMAGE)) { summary_entry = new_summary_entry(summary_entry,0,IMGFMT_JPEG); } if(summary_entry) { if(summary_entry->length <= 0) summary_entry->length = data_length; if(summary_entry->offset <= 0) summary_entry->offset = start_of_jpeg_data; summary_entry->imageformat = IMGFMT_JPEG; summary_entry->entry_lock = lock_number(summary_entry); if(tag == 0) { clearerr(inptr); (void)jpeg_status(JPEG_NO_SOI); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_NO_JPEG; } } PUSHCOLOR(JPEG_COLOR); while(tag != 0) { switch(tag) { case JPEG_SOS: /* image data */ name = tagname(tag); if(PRINT_SEGMENT) { print_tag_address(SEGMENT,marker_offset,indent + SMALLINDENT,prefix); chpr += printf("<%s>",name); } seg_length = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 2); if(!ferror(inptr) && !feof(inptr)) { unsigned char ns,c,t,td,ta,ss,se,a,ah,al; int i; /* number of components in scan */ ns = read_ubyte(inptr,HERE); if(PRINT_SEGMENT) { chpr += printf(" length %u",seg_length); chpr += printf(" start of JPEG data, %d components %lu pixels", ns & 0xff,img_pixels); chpr = newline(chpr); } if(Debug & JPEG_MARKER_DEBUG) { for(i = 0; i < ns; ++i) { /* ###%%% */ putindent(6 + (2 * ADDRWIDTH) + indent + 16); /* component selector */ c = read_ubyte(inptr,HERE); t = read_ubyte(inptr,HERE); td = t & 0xf; ta = ((t & 0xf0) >> 4) & 0xf; if((ferror(inptr) == 0) && (feof(inptr) == 0) && (PRINT_SEGMENT)) { chpr += printf("Cs%d=%d, Td%d=%#04x, Ta%d=%#04x",i,c,i,td,i,ta); chpr = newline(chpr); } } ss = read_ubyte(inptr,HERE); se = read_ubyte(inptr,HERE); a = read_ubyte(inptr,HERE); ah = a & 0xf; al = ((a & 0xf0) >> 4) & 0xf; putindent(6 + (2 * ADDRWIDTH) + indent + 16); chpr += printf("Ss=%u, Se=%u, Ah=%u, Al=%u",ss,se,ah,al); chpr = newline(chpr); } } else { tag = 0; chpr += printf("ERROR reading length of SOS"); chpr = newline(chpr); why(stdout); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; continue; } if(data_length > 0L) { after_sos = marker_offset + 2 + seg_length; marker_offset = start_of_jpeg_data + data_length - 2L; tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); if(ferror(inptr) || feof(inptr)) { tag = 0; printred("# WARNING: ERROR reading JPEG_EOI at end of section"); chpr = newline(chpr); clearerr(inptr); /* Skip the backward scan and check */ /* forward from the end of the SOS */ /* section, to see where the file is */ /* truncated. */ status = JPEG_HAD_ERROR; (void)jpeg_status(status); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; #if 0 /* Wrong if multiple compressed tiles/strips in passed length; status */ /* set to HAD_ERROR allows skippping backward scan and going direct */ /* to forward scan. Should pass just tile/strip length and handle */ /* multiples in parent. */ continue; #endif } if(tag == JPEG_EOI) { max_offset = ftell(inptr); continue; } else /* Try a little harder to find EOI */ { int i; end_of_section = start_of_jpeg_data + data_length; if(status == 0) { /* Try a quick scan backward from the end */ /* of the section, in case there's just a */ /* little padding. */ for(i = 1; i < 512; ++i) { tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); if(Debug & JPEG_EOI_DEBUG) printf("DEBUG: %#lx/%ld: %#04x\n",marker_offset,marker_offset,tag); if(ferror(inptr) || feof(inptr)) break; status = 0; if(tag == JPEG_EOI) break; --marker_offset; } if(ferror(inptr) || feof(inptr)) { tag = 0; printred("# WARNING: ERROR reading JPEG data looking for JPEG_EOI"); chpr = newline(chpr); clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; continue; } if(tag == JPEG_EOI) { if(start_of_jpeg_data > 0UL) { if(feof(inptr) || ((end_of_section + 5) >= get_filesize(inptr))) max_eoi = start_of_jpeg_data; } max_offset = ftell(inptr); (void)jpeg_status(JPEG_EARLY_EOI); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEG_EARLY_EOI; if(Debug & JPEG_EOI_DEBUG) printf("DEBUG: start_of_jpeg_data=%lu, max_eoi=%lu\n",start_of_jpeg_data,max_eoi); continue; } } /* If the quick scan didn't work, try a */ /* forward scan from the offset given by */ /* the start of scan header. */ found_eoi_offset = forward_scan_for_eoi(inptr,after_sos, end_of_section,"!",indent); if(start_of_jpeg_data > 0UL) { if(feof(inptr) || ((found_eoi_offset + 5) >= get_filesize(inptr))) max_eoi = start_of_jpeg_data; } if(Debug & JPEG_EOI_DEBUG) printf("DEBUG: start_of_jpeg_data=%lu, max_eoi=%lu\n",start_of_jpeg_data,max_eoi); if(found_eoi_offset) { max_offset = found_eoi_offset + 2; (void)jpeg_status(JPEG_EARLY_EOI); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEG_EARLY_EOI; marker_offset = max_offset - 2UL; tag = JPEG_EOI; continue; } else { if(ferror(inptr) || feof(inptr)) { tag = 0; clearerr(inptr); (void)jpeg_status(status); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; continue; } else { max_offset = 0; (void)fseek(inptr,start_of_jpeg_data + data_length - 2L,SEEK_SET); (void)jpeg_status(JPEG_NO_EOI); } } } } else { /* See if there's a JPEG_EOI at (or somewhere */ /* near) EOF. If a previous subimage was */ /* found at or very near eof, indicating a */ /* thumbnail tacked on to the end of the */ /* file, use the start of that image as the */ /* limit for the search, */ if(Debug & JPEG_EOI_DEBUG) printf("DEBUG: max_eoi=%lu\n",max_eoi); if(fseek(inptr,0L,SEEK_END) == 0) { /* Values to use if a forward scan is */ /* required. */ after_sos = marker_offset + 2 + seg_length; eof = ftell(inptr); if(max_eoi) { end_of_section = max_eoi - 1; marker_offset = max_eoi - 2; } else { end_of_section = eof - 1; marker_offset = eof - 2; } tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); if(ferror(inptr) || feof(inptr)) { tag = 0; printred("# WARNING: ERROR reading JPEG data looking for JPEG_EOI"); chpr = newline(chpr); clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; continue; } if(Debug & JPEG_EOI_DEBUG) printf("DEBUG: %#lx/%ld: %#04x\n",marker_offset,marker_offset,tag); if(tag != JPEG_EOI) /* try harder */ { for(i = 1; i < 512; ++i) { --marker_offset; tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); if(ferror(inptr) || feof(inptr)) break; if(Debug & JPEG_EOI_DEBUG) printf("DEBUG: %#lx/%ld: %#04x\n",marker_offset,marker_offset,tag); if(tag == JPEG_EOI) break; } } if(ferror(inptr) || feof(inptr)) { tag = 0; printred("# WARNING: ERROR reading JPEG data looking for JPEG_EOI"); chpr = newline(chpr); clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; continue; } if(tag == JPEG_EOI) { max_offset = ftell(inptr); if(Debug & JPEG_EOI_DEBUG) printf("DEBUG: max_offset=%lu, eof=%lu, marker_offset=%lu\n",max_offset,eof,marker_offset); if(marker_offset < (eof - 2)) { (void)jpeg_status(JPEG_EARLY_EOI); if(summary_entry) { summary_entry->imagesubformat |= IMGSUBFMT_JPEG_EARLY_EOI; if(summary_entry->length <= 0) summary_entry->length = eof - start_of_jpeg_data; } } continue; } else { found_eoi_offset = forward_scan_for_eoi(inptr,after_sos,end_of_section, "!",indent); if(found_eoi_offset) { max_offset = found_eoi_offset + 2; marker_offset = found_eoi_offset; if(Debug & JPEG_EOI_DEBUG) { printf("DEBUG: max_offset=%lu, eof=%lu, marker_offset=%lu\n",max_offset,eof,marker_offset); printf("found_eof_offset=%lu, ftell=%lu\n",found_eoi_offset,ftell(inptr)); } if(found_eoi_offset < (eof - 2)) { (void)jpeg_status(JPEG_EARLY_EOI); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEG_EARLY_EOI; } if((summary_entry) && (summary_entry->length <= 0)) summary_entry->length = eof - start_of_jpeg_data; tag = JPEG_EOI; continue; } else { if((summary_entry) && (summary_entry->length <= 0)) summary_entry->length = eof - start_of_jpeg_data; print_tag_address(SEGMENT,eof - 1,indent + SMALLINDENT,prefix); printred(" # WARNING: at EOF: JPEG_EOI not found"); if(!(LIST_MODE)) chpr = newline(chpr); max_offset = 0; /* ###%%% this may not be needed, */ /* since it's already been */ /* reported */ (void)jpeg_status(JPEG_NO_EOI); } } } if(ferror(inptr) || feof(inptr)) { (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } } tag = 0; /* break the loop */ break; case JPEG_DHT: /* image data */ name = tagname(tag); if(PRINT_SEGMENT) { print_tag_address(SEGMENT,marker_offset,indent + SMALLINDENT,prefix); chpr += printf("<%s>",name); } seg_length = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 2); if(!ferror(inptr) && !feof(inptr)) { unsigned char t,tc,th,l; int i; t = read_ubyte(inptr,HERE); tc = t & 0xf; th = ((t & 0xf0) >> 4) & 0xf; if(PRINT_SEGMENT) { chpr += printf(" length %u",seg_length); chpr += printf(" table class = %u",tc & 0xff); chpr += printf(" table id = %u",th & 0xff); chpr = newline(chpr); } if(Debug & JPEG_MARKER_DEBUG) { for(i = 0; i < 16; ++i) { if((i % 5) == 0) { chpr = newline(chpr); putindent(6 + (2 * ADDRWIDTH) + indent + 16); } /* component selector */ l = read_ubyte(inptr,HERE); if((ferror(inptr) == 0) && (feof(inptr) == 0) && (PRINT_SEGMENT)) { chpr += printf("l%-2d=%u",i,l); if(i < 15) chpr += printf(", "); } } chpr = newline(chpr); } /* next tag */ marker_offset += seg_length + 2; if(marker_offset > 0L) tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); else tag = 0; if(ferror(inptr) || feof(inptr)) { tag = 0; clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; continue; } } else { chpr += printf("ERROR reading length of DHT"); chpr = newline(chpr); why(stdout); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; return 0; } break; case JPEG_COM: name = tagname(tag); if(PRINT_SEGMENT) { print_tag_address(SEGMENT,marker_offset,indent + SMALLINDENT,prefix); chpr += printf("<%s>",name); } seg_length = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 2); if(!ferror(inptr) && !feof(inptr)) { if(PRINT_SEGMENT) { chpr += printf(" length %u: \'",seg_length); (void)print_ascii(inptr,seg_length - 2,HERE); chpr += printf("\'"); chpr = newline(chpr); } marker_offset += seg_length + 2; /* next tag */ tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); if(ferror(inptr) || feof(inptr)) { tag = 0; clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } else max_offset = ftell(inptr); } else { tag = 0; clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } break; case JPEG_SOF_0: case JPEG_SOF_1: case JPEG_SOF_2: case JPEG_SOF_3: case JPEG_SOF_5: case JPEG_SOF_6: case JPEG_SOF_7: case JPEG_SOF_9: case JPEG_SOF_10: case JPEG_SOF_11: case JPEG_SOF_13: case JPEG_SOF_14: case JPEG_SOF_15: name = tagname(tag); /* If this is a TIFF format file, record the */ /* actual compression type as indicated by the */ /* SOF tag, for printing in the image summary at */ /* the end. */ if(summary_entry) summary_entry->compression = tag; if(PRINT_SEGMENT) { print_tag_address(SEGMENT,marker_offset,indent + SMALLINDENT,prefix); chpr += printf("<%s>",name); } seg_length = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 2); if(!ferror(inptr) && !feof(inptr)) { unsigned char nf = 0; unsigned char c,h,v,t,p; int i; int iserror = 0; if(PRINT_SEGMENT) chpr += printf(" length %u",seg_length); p = read_ubyte(inptr,HERE); /* precision */ if(!iserror && !ferror(inptr) && !feof(inptr)) img_height = read_ushort(inptr,TIFF_MOTOROLA,HERE); if(!iserror && !ferror(inptr) && !feof(inptr)) img_width = read_ushort(inptr,TIFF_MOTOROLA,HERE); if(!iserror && !ferror(inptr) && !feof(inptr)) img_pixels = img_height * img_width; if(!iserror && !ferror(inptr) && !feof(inptr)) { nf = read_ubyte(inptr,HERE); /* components */ if (nf > MAXSAMPLE) { // See https://github.com/hfiguiere/exifprobe/issues/2 // we shouldn't need to clamp nf value. nf = MAXSAMPLE; iserror = 1; } } if(!iserror && !ferror(inptr) && !feof(inptr)) { max_offset = ftell(inptr); if(PRINT_SEGMENT) chpr += printf(", %d bits/sample, components=%d, width=%d, height=%d", p,(int)nf,(int)img_width,(int)img_height); if(summary_entry) { summary_entry->spp = nf; for(i = 0; i < nf; i++) summary_entry->bps[i] = p; } } if(iserror || ferror(inptr) || feof(inptr)) { tag = 0; clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; continue; } if(PRINT_SEGMENT) chpr = newline(chpr); if(Debug & JPEG_MARKER_DEBUG) { for(i = 0; i < nf; ++i) { putindent(6 + (2 * ADDRWIDTH) + indent + 16); c = read_ubyte(inptr,HERE); /* component id */ tmp = read_ubyte(inptr,HERE); /* H | V */ h = tmp & 0xf; v = ((tmp & 0xf0) >> 4) & 0xf; t = read_ubyte(inptr,HERE); /* Q tbl sel */ if((ferror(inptr) == 0) && (PRINT_SEGMENT)) { chpr += printf("C%d=%d, H%d=%d, V%d=%d, T%d=%#04x",i,c,i,h,i,v,i,t); chpr = newline(chpr); } } } if(summary_entry && (img_height > 0) && (summary_entry->pixel_height < img_height)) { summary_entry->pixel_height = img_height; } if(summary_entry && (img_width > 0) && (summary_entry->pixel_width < img_width)) { summary_entry->pixel_width = img_width; } switch(tag) { /* lossless types are likely primary; */ /* mark them for scan_summary() */ case JPEG_SOF_3: case JPEG_SOF_7: case JPEG_SOF_11: case JPEG_SOF_15: summary_entry->subfiletype = POSSIBLE_PRIMARY_TYPE; break; default: break; } } if(!ferror(inptr) && !feof(inptr)) { max_offset = ftell(inptr); marker_offset += seg_length + 2; /* next tag */ tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); if(ferror(inptr) || feof(inptr)) { tag = 0; clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } else max_offset = ftell(inptr); } else { tag = 0; clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } break; case JPEG_BADSOI: /* minolta */ if(bad_soi == 0) bad_soi = tag; /* fall through */ case JPEG_SOI: name = tagname(tag); if((PRINT_SECTION) || (PRINT_SEGMENT)) { print_tag_address(SECTION|SEGMENT,marker_offset,indent,prefix); if(bad_soi) { printred(""); chpr += printf(" (%#06x)",bad_soi); } else chpr += printf("<%s>",name); chpr = newline(chpr); } start_of_jpeg_data = marker_offset; if(bad_soi == 0) ++had_soi; /* next tag */ tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 2); if(!ferror(inptr) && !feof(inptr)) { marker_offset += 2; max_offset = ftell(inptr); } else { tag = 0; clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } break; case JPEG_EOI: name = tagname(tag); max_offset = ftell(inptr); if((PRINT_SECTION) || (PRINT_SEGMENT)) { print_tag_address(SECTION|SEGMENT,marker_offset,indent,prefix); if((status = jpeg_status(0)) == JPEG_EARLY_EOI) { PUSHCOLOR(RED); chpr += printf("<%s> JPEG length %lu",name,max_offset - start_of_jpeg_data); POPCOLOR(); } else chpr += printf("<%s> JPEG length %lu",name,max_offset - start_of_jpeg_data); /* re-set the cleared status */ jpeg_status(status); if((PRINT_SECTION) && (status != JPEG_EARLY_EOI)) chpr = newline(chpr); } if((summary_entry) && (summary_entry->length <= 0)) { /* Use specified length, if any, even if */ /* early EOI */ if(data_length > 0) { summary_entry->length = data_length; max_offset = start_of_jpeg_data + data_length; } else summary_entry->length = max_offset - start_of_jpeg_data; } tag = 0; /* break the loop */ break; case JPEG_APP0: marker_offset = process_app0(inptr,marker_offset,tag,summary_entry, parent_name,indent + SMALLINDENT); /* next tag */ if(marker_offset > 0L) tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); else tag = 0; if(ferror(inptr) || feof(inptr)) { clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } else max_offset = ftell(inptr); break; case JPEG_APP1: marker_offset = process_app1(inptr,marker_offset,tag,summary_entry, parent_name,indent + SMALLINDENT); /* next tag */ if(marker_offset > 0L) tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); else tag = 0; if(ferror(inptr) || feof(inptr)) { clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } break; case JPEG_APP3: marker_offset = process_app3(inptr,marker_offset,tag,summary_entry, parent_name,indent + SMALLINDENT); /* next tag */ if(marker_offset > 0L) tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); else tag = 0; if(ferror(inptr) || feof(inptr)) { clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } break; case JPEG_APP12: marker_offset = process_app12(inptr,marker_offset,tag, summary_entry,parent_name,indent + SMALLINDENT); /* next tag */ if(marker_offset > 0L) tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); else tag = 0; if(ferror(inptr) || feof(inptr)) { clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } else max_offset = ftell(inptr); break; case JPEG_APP2: case JPEG_APP4: case JPEG_APP5: case JPEG_APP6: case JPEG_APP7: case JPEG_APP8: case JPEG_APP9: case JPEG_APP10: case JPEG_APP11: case JPEG_APP13: case JPEG_APP14: case JPEG_APP15: marker_offset = process_appn(inptr,marker_offset,tag, summary_entry,parent_name,indent + SMALLINDENT); /* next tag */ if(marker_offset > 0L) tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); else tag = 0; if(ferror(inptr) || feof(inptr)) { tag = 0; clearerr(inptr); } else max_offset = ftell(inptr); break; default: /* Minolta sometimes writes garbage in the high */ /* byte of SOI tags; assume that 0xd8 in the low */ /* byte is a bad SOI. */ if(((tag & 0xff00) != 0xff00) && ((tag & 0x00ff) == 0xd8)) { /* Only if no SOI yet */ if((had_soi == 0) && (bad_soi == 0)) { bad_soi = tag; tag &= 0x00ff; /* This will match */ /* JPEG_BADSOI above. */ continue; } else if(bad_soi) had_soi = 0; /* ###%%% this should be handled better; */ /* don't set had_soi on a bad_soi but set it */ /* after a legitimate marker is found NEXT; */ /* I.e. we have a legitimate jpeg only if a */ /* good marker is found, after which an error */ /* indicates corrupted jpeg data, otherwise */ /* an error should indicate no jpeg data */ /* found. */ } name = tagname(tag); if(PRINT_SEGMENT) { print_tag_address(SEGMENT,marker_offset,indent + SMALLINDENT,prefix); chpr += printf("<%s>",name); } if((tag & 0xff00) != 0xff00) { if(PRINT_SEGMENT) { printred(" INVALID JPEG TAG"); chpr = newline(chpr); } tag = 0; if(had_soi) (void)jpeg_status(JPEG_HAD_ERROR); else (void)jpeg_status(JPEG_NO_SOI); if(summary_entry) { /* If this is the first tag, we have no */ /* reason to believe that this is really */ /* jpeg data. If not, data is corrupted */ if(had_soi) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; else { summary_entry->imagesubformat |= IMGSUBFMT_NO_JPEG; /* ###%%% hmmm... */ /* summary_entry->compression = 0; */ } } else printred("JPEG: NO SUMMARY ENTRY "); clearerr(inptr); if(Max_imgdump > 0) { /* If the length of the data is unknown, */ /* limit the dump to something reasonable */ if(Max_imgdump == DUMPALL) { if(data_length > 0) dumplength = data_length; else data_length = dumplength = 1024; } else if(Max_imgdump > data_length) { if(data_length > 0) dumplength = data_length; else data_length = dumplength = 1024; } else dumplength = Max_imgdump; chpr = newline(0); hexdump(inptr,start_of_jpeg_data,data_length, dumplength,16,indent,SMALLINDENT); chpr = newline(1); } max_offset = start_of_jpeg_data + data_length; } else { seg_length = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 2); if(!ferror(inptr) && !feof(inptr)) { if(PRINT_SEGMENT) { chpr += printf(" length %u",seg_length); chpr = newline(chpr); } marker_offset = marker_offset + 2 + seg_length; tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); if(ferror(inptr) || feof(inptr)) { tag = 0; clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } else max_offset = ftell(inptr); } else { tag = 0; clearerr(inptr); (void)jpeg_status(JPEG_HAD_ERROR); if(summary_entry) summary_entry->imagesubformat |= IMGSUBFMT_JPEGFAILED; } } break; } } POPCOLOR(); } setcharsprinted(chpr); return(max_offset); } /* set and report errors in jpeg files "out of band". */ int jpeg_status(int setstatus) { static int status = 0; int retvalue; retvalue = status; status = setstatus; return(retvalue); } #define JPEG_HIBYTE 0xff #define EOI_LOBYTE 0xd9 unsigned long forward_scan_for_eoi(FILE *inptr,unsigned long start_of_data, unsigned long end_of_section,char *prefix,int indent) { int highbyte,lobyte; unsigned long eoi_offset = 0UL; unsigned long tagloc; int chpr = 0; if(inptr && (fseek(inptr,start_of_data,SEEK_SET) != -1)) { if(Debug & JPEG_EOI_DEBUG) printf("DEBUG: start scan at %lu\n",start_of_data); while(((highbyte = fgetc(inptr)) != EOF) && (highbyte != EOF) && (ftell(inptr) < end_of_section)) { if(highbyte != JPEG_HIBYTE) continue; tagloc = ftell(inptr) - 1; lobyte = fgetc(inptr); if(lobyte == EOI_LOBYTE) { eoi_offset = tagloc; if(Debug & JPEG_EOI_DEBUG) { if(!(LIST_MODE) && (PRINT_SEGMENT)) { print_tag_address(SEGMENT,eoi_offset,indent + SMALLINDENT,prefix); PUSHCOLOR(RED); putindent(2); chpr += printf("possible JPEG_EOI found at %lu",eoi_offset); } POPCOLOR(); chpr = newline(chpr); } break; } } } if(Debug & JPEG_EOI_DEBUG) printf("DEBUG: end scan at %lu\n",ftell(inptr)); return(eoi_offset); } /* JFIF format files */ unsigned long process_app0(FILE *inptr,unsigned long app0_offset,unsigned short tag, struct image_summary *summary_entry,char *parent_name, int indent) { unsigned long max_offset = 0L; unsigned long data_offset,dumplength; unsigned long filesize = 0UL; char *app_string,*name; unsigned short app_length = 0L; int status = 0; int chpr = 0; unsigned short marker,xt,yt,tmp; struct fileheader *header = NULL; char *fulldirname = CNULL; char *subdirname = CNULL; if(inptr) { filesize = get_filesize(inptr); if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_APPN; summary_entry->filesubformatAPPN[0] = 1; } name = tagname(tag); app_length = read_ushort(inptr,TIFF_MOTOROLA,app0_offset + 2); if((PRINT_SECTION)) print_tag_address(SECTION,app0_offset,indent,"@"); data_offset = app0_offset + 4L; app_string = read_appstring(inptr,JPEG_APP0,data_offset); app_string = app_string ? app_string : QSTRING; if(PRINT_SECTION) chpr += printf("<%s> %#x length %u, ",name,tag,app_length); else if((PRINT_ENTRY)) { /* ###%%% pseudo-tags fpr LIST Mode here */ print_tag_address(ENTRY,HERE,indent,"*"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-14.14s","APP0"); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%-9u",app0_offset,app_length); chpr = newline(chpr); } fulldirname = splice(parent_name,".","APP0"); if((strncmp(app_string,"JFIF",4) == 0) && (app_string[4] == '\0')) { if(summary_entry) summary_entry->filesubformat |= FILESUBFMT_JFIF; data_offset += 5; if((PRINT_SECTION)) { chpr += printf("\'%s\'",app_string); chpr = newline(chpr); } tmp = read_ushort(inptr,TIFF_MOTOROLA,data_offset); if((PRINT_APPENTRY) && (PRINT_ENTRY)) { print_tag_address(APP_ENTRY,data_offset,indent,"@"); if(PRINT_SECTION) extraindent(SMALLINDENT); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fulldirname); chpr += printf("%-14.14s","Version"); } if((PRINT_VALUE)) chpr += printf("= %d.%d",(int)((tmp >> 8) & 0xff),(int)(tmp & 0xff)); chpr = newline(chpr); } data_offset = ftell(inptr); tmp = read_ubyte(inptr,data_offset); if((PRINT_APPENTRY) && (PRINT_ENTRY)) { print_tag_address(APP_ENTRY,data_offset,indent,"@"); if(PRINT_SECTION) extraindent(SMALLINDENT); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fulldirname); chpr += printf("%-14.14s","Units"); } if((PRINT_VALUE)) chpr += printf("= %s",tmp? tmp == 1 ? "'dots/inch'" : "'dots/cm'" : "'aspect ratio'"); chpr = newline(chpr); } data_offset = ftell(inptr); tmp = read_ushort(inptr,TIFF_MOTOROLA,data_offset); if((PRINT_APPENTRY) && (PRINT_ENTRY)) { print_tag_address(APP_ENTRY,data_offset,indent,"@"); if(PRINT_SECTION) extraindent(SMALLINDENT); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fulldirname); chpr += printf("%-14.14s","Xdensity"); } if((PRINT_VALUE)) chpr += printf("= %u",tmp); chpr = newline(chpr); } data_offset = ftell(inptr); tmp = read_ushort(inptr,TIFF_MOTOROLA,data_offset); if((PRINT_APPENTRY) && (PRINT_ENTRY)) { print_tag_address(APP_ENTRY,data_offset,indent,"@"); if(PRINT_SECTION) extraindent(SMALLINDENT); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fulldirname); chpr += printf("%-14.14s","Ydensity"); } if((PRINT_VALUE)) chpr += printf("= %u",tmp); chpr = newline(chpr); } data_offset = ftell(inptr); xt = read_ubyte(inptr,data_offset); if((PRINT_APPENTRY) && (PRINT_ENTRY)) { print_tag_address(APP_ENTRY,data_offset,indent,"@"); if(PRINT_SECTION) extraindent(SMALLINDENT); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fulldirname); chpr += printf("%-14.14s","XThumbnail"); } if((PRINT_VALUE)) chpr += printf("= %d",(int)xt); chpr = newline(chpr); } data_offset = ftell(inptr); yt = read_ubyte(inptr,data_offset); if((PRINT_APPENTRY) && (PRINT_ENTRY)) { print_tag_address(APP_ENTRY,data_offset,indent,"@"); if(PRINT_SECTION) extraindent(SMALLINDENT); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fulldirname); chpr += printf("%-14.14s","YThumbnail"); } if((PRINT_VALUE)) chpr += printf("= %d",(int)yt); chpr = newline(chpr); } if(xt && yt) { data_offset = ftell(inptr); print_tag_address(APP_ENTRY,data_offset,indent,"@"); if((PRINT_APPENTRY) && (PRINT_SECTION)) extraindent(SMALLINDENT); if((PRINT_TAGINFO)) { if(PRINT_LONGNAMES) chpr += printf("%s.",fulldirname); chpr += printf("%-14.14s","Thumbnail"); } if((PRINT_VALUE)) { chpr += printf(" = '%u RGB bytes (%u) pixels'",3 * xt * yt,xt * yt); chpr = newline(chpr); } } max_offset = data_offset + 1 + (3 * xt * yt); } else if((strncmp(app_string,"JFXX",4) == 0) && (app_string[4] == '\0')) { if(summary_entry) summary_entry->filesubformat |= FILESUBFMT_JFXX; data_offset += 5; tmp = read_ubyte(inptr,data_offset); if((PRINT_SECTION)) { chpr += printf("\'%s\'",app_string); chpr = newline(chpr); print_tag_address(SECTION,data_offset,indent,"@"); if((PRINT_SECTION)) { extraindent(SMALLINDENT); chpr += printf(" extension code %#x",tmp); } } else chpr = newline(chpr); ++data_offset; switch(tmp) { case 0x10: if((PRINT_SECTION)) { chpr += printf(" - JPEG thumbnail"); chpr = newline(chpr); } marker = read_ushort(inptr,TIFF_MOTOROLA,HERE); summary_entry = new_summary_entry(summary_entry,0,IMGFMT_JPEG); if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_JFXX; summary_entry->subfiletype = REDUCED_RES_TYPE; } if((LIST_MODE)) { if((PRINT_SEGMENT)) chpr = newline(chpr); print_tag_address(ENTRY,data_offset,indent + SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if(PRINT_LONGNAMES) chpr += printf("%s.JFXX.",fulldirname); chpr += printf("%-14.14s","JpegThumbnail"); } if((PRINT_VALUE)) { max_offset = app0_offset + app_length + 2; chpr += printf(" = @%lu:%lu",data_offset,max_offset - data_offset); chpr = newline(chpr); } } max_offset = process_jpeg_segments(inptr,data_offset,marker, app_length - 8,summary_entry,parent_name, "@",indent + SMALLINDENT); if((max_offset - 1) > filesize) { PUSHCOLOR(RED); chpr += printf(" (TRUNCATED at %lu)",filesize); POPCOLOR(); summary_entry->imagesubformat |= IMGSUBFMT_TRUNCATED; } max_offset = app0_offset + app_length + 2; if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(SECTION,max_offset - 1,indent + SMALLINDENT,"@"); chpr += printf("#### End of JPEG thumbnail data for APP0"); chpr += printf(", length %lu ####",max_offset - data_offset); print_jpeg_status(); chpr = newline(chpr); } break; case 0x11: if((PRINT_APPENTRY) && (PRINT_SECTION)) chpr += printf(" - thumbnail stored using 1 byte/pixel"); xt = read_ubyte(inptr,data_offset++); yt = read_ubyte(inptr,data_offset++); /* The RGB palette is 768 bytes */ max_offset = data_offset + 768 + (xt * yt) ; summary_entry = new_summary_entry(summary_entry,0,IMGFMT_JPEG); if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_JFXX; summary_entry->subfiletype = REDUCED_RES_TYPE; summary_entry->imagesubformat = IMGSUBFMT_PALETTE; summary_entry->offset = data_offset; summary_entry->length = xt * yt + 768; summary_entry->pixel_width = xt; summary_entry->pixel_height = yt; summary_entry->compression = 1; summary_entry->spp = 1; summary_entry->sample_size = 8; summary_entry->datatype = JPEG_APP0; summary_entry->entry_lock = lock_number(summary_entry); } break; case 0x13: if((PRINT_APPENTRY) && (PRINT_SECTION)) chpr += printf(" - thumbnail stored using 3 bytes/pixel"); xt = read_ubyte(inptr,data_offset++); yt = read_ubyte(inptr,data_offset++); max_offset = data_offset + (3 * xt * yt) ; summary_entry = new_summary_entry(summary_entry,0,IMGFMT_JPEG); if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_JFXX; summary_entry->subfiletype = REDUCED_RES_TYPE; summary_entry->imagesubformat = IMGSUBFMT_RGB; summary_entry->offset = data_offset; summary_entry->length = xt * yt * 3; summary_entry->pixel_width = xt; summary_entry->pixel_height = yt; summary_entry->compression = 1; summary_entry->spp = 3; summary_entry->sample_size = 8; summary_entry->datatype = JPEG_APP0; summary_entry->entry_lock = lock_number(summary_entry); } break; default: if((PRINT_APPENTRY) && (PRINT_SECTION)) chpr += printf(" - UNKNOWN JFXX extension"); max_offset = data_offset; break; } chpr = newline(chpr); } else if(((strncmp(app_string,"II",2) == 0) || (strncmp(app_string,"MM",2) == 0)) && (app_string[2] == 0x1a)) /* maybe CIFF */ { if((header = read_imageheader(inptr,data_offset))) { if(summary_entry) summary_entry->filesubformat |= FILESUBFMT_CIFF; if((PRINT_APPENTRY) && (PRINT_SECTION)) chpr = newline(chpr); if((PRINT_SECTION)) { print_tag_address(SECTION,data_offset,indent+SMALLINDENT,"@"); print_header(header,SECTION); } if(header->probe_magic == PROBE_CIFFMAGIC) { subdirname = splice(fulldirname,".","CIFF"); if(!(PRINT_SECTION)) { print_tag_address(ENTRY|VALUE,data_offset,indent+SMALLINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",subdirname); chpr += printf("%-*.*s",CIFFTAGWIDTH,CIFFTAGWIDTH,"HeaderOffset"); } if((PRINT_VALUE)) { if(PRINT_BOTH_OFFSET) chpr += printf(" = @%#lx=%lu",data_offset,data_offset); else if(PRINT_HEX_OFFSET) chpr += printf(" = @%#lx",data_offset); else chpr += printf(" = @%lu",data_offset); } chpr = newline(chpr); } max_offset = process_ciff(inptr,header,data_offset,app_length - 2, summary_entry,subdirname,0,indent+SMALLINDENT); if(subdirname) free(subdirname); subdirname = CNULL; } else goto appdump; } else goto appdump; } else goto appdump; if(fulldirname) free(fulldirname); /* If there's data unaccounted for, allow the data that isn't */ /* accounted for to be dumped */ if(max_offset < (app0_offset + app_length + 2)) { print_tag_address(SEGMENT,max_offset,indent,"@"); extraindent(SMALLINDENT); dumplength = app0_offset + app_length + 1 - max_offset; chpr += printf("---- End of data before end of APP0 (%lu bytes)",dumplength); chpr = newline(chpr); /* dump at least the first couple of rows, just to see... */ if(PRINT_APPNDUMP) { if((Max_appdump == DUMPALL) || (Max_appdump > (app_length + 2))) dumplength = app_length - 2; else if(Max_appdump > 0L) dumplength = Max_appdump; else if(Max_undefined > 0L) dumplength = Max_undefined; else dumplength = app_length - 2; } else dumplength = dumplength > 48 ? 48 : dumplength; if(dumplength) { hexdump(inptr,app0_offset + 4,app_length - 2,dumplength,16, indent + SMALLINDENT,SMALLINDENT); chpr = newline(1); } } /* ###%%% if max_offset >, warn */ /* close off the section. */ if((PRINT_SECTION)) { print_tag_address(SECTION,app0_offset + app_length + 1,indent,"@"); chpr += printf("",name); chpr = newline(chpr); } } return(app0_offset + app_length + 2); appdump: /* Something went haywire...dump starting at the marker */ /* At the moment, this happens only for imaginative APP0 markers */ if(app_length > 0L) { if(PRINT_APPNDUMP) { if((Max_appdump == DUMPALL) || (Max_appdump > (app_length + 2))) dumplength = app_length + 2; else if(Max_appdump > 0L) dumplength = Max_appdump; else dumplength = Max_undefined; if(dumplength) { chpr = newline(1); hexdump(inptr,app0_offset,app_length + 2,dumplength,16, indent + SMALLINDENT,SMALLINDENT); chpr = newline(1); } } else { if(PRINT_SECTION) { chpr += printf(" - (not dumped: use -A)"); chpr = newline(chpr); } } max_offset = app0_offset + app_length + 2; /* close off the segment; a start "tag" was printed */ if(PRINT_SECTION) { print_tag_address(SECTION,app0_offset + app_length + 1,indent,"@"); chpr += printf("",name); chpr = newline(chpr); } } setcharsprinted(chpr); return(max_offset); } /* Process (print) an APP1 (EXIF) section */ unsigned long process_app1(FILE *inptr,unsigned long app1_offset,unsigned short tag, struct image_summary *summary_entry,char *parent_name, int indent) { unsigned long max_offset = 0UL; unsigned long ifd_offset,fileoffset_base; unsigned long dumplength = 0UL; unsigned short app_length = 0; int chpr = 0; struct fileheader *header; char *app_string,*name; char *fulldirname = CNULL; if(inptr) { if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_APPN; summary_entry->filesubformatAPPN[1] = 1; } /* display the APP1 header */ name = tagname(tag); /* never null */ if(PRINT_SECTION) { print_tag_address(SECTION,app1_offset,indent,"@"); chpr += printf("<%s> %#x ",name,tag); } app_length = read_ushort(inptr,TIFF_MOTOROLA,HERE); if(ferror(inptr) || feof(inptr)) { clearerr(inptr); goto appdump; } if(PRINT_SECTION) chpr += printf("length %u, ",app_length); else if((PRINT_ENTRY)) { /* ###%%% pseudo-tags fpr LIST Mode here */ print_tag_address(ENTRY,HERE,indent,"*"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-14.14s","APP1"); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%-9u",app1_offset,app_length); chpr = newline(chpr); } app_string = read_appstring(inptr,JPEG_APP1,HERE); if(ferror(inptr) || feof(inptr)) { clearerr(inptr); goto appdump; } if(app_string) { if(PRINT_SECTION) chpr += printf("\'%s\'",app_string); /* The next thing we see should be a TIFF header tag */ /* indicating byte order used in the IFD, followed by the */ /* offset from the start of the header to the start of */ /* the IFD (number of entries). */ fileoffset_base = ftell(inptr); /* If this is a valid Exif segment, skip the pad byte. */ if(strncmp(app_string,"Exif",4) == 0) { fulldirname = splice(parent_name,".","APP1"); ++fileoffset_base; if(PRINT_SECTION) { chpr = newline(chpr); print_tag_address(SECTION,fileoffset_base,indent + SMALLINDENT,"@"); } header = read_imageheader(inptr,fileoffset_base); if(header && (print_header(header,SECTION) == 0) && (header->probe_magic == TIFF_MAGIC)) { ifd_offset = read_ulong(inptr,header->file_marker,HERE); if(PRINT_SECTION) { chpr += printf(" ifd offset = %lu (+ %lu = %#lx/%lu)",ifd_offset, fileoffset_base,fileoffset_base + ifd_offset, fileoffset_base + ifd_offset); chpr = newline(chpr); } /* ###%%% maybe should unlock the summary entry, */ /* so that the tiff processor will use it? not */ /* sure if that's appropriate for APP1 found in */ /* jpeg sub-images. */ max_offset = process_tiff_ifd(inptr,header->file_marker,ifd_offset, fileoffset_base,0L,summary_entry,fulldirname, TIFF_IFD,0,-1,indent + SMALLINDENT); if(max_offset < app1_offset + app_length + 2) max_offset = app1_offset + app_length +2; } else { max_offset = app1_offset + app_length + 2; if(PRINT_SECTION) { extraindent(indent + ADDRWIDTH); if(header) { chpr += printf(" INVALID MAGIC %lu (%s) where TIFF header should be", header->probe_magic,tagname(header->probe_magic)); } else { chpr += printf(" INVALID HEADER for TIFF"); } #define PRINT_A_BIT 48 if(app_length > PRINT_A_BIT) dumplength = PRINT_A_BIT; else dumplength = app_length; goto appdump; } } if(fulldirname) free(fulldirname); } else { max_offset = app1_offset + app_length + 2; if(PRINT_SECTION) { chpr += printf(" - unknown format"); goto appdump; } } } else if(PRINT_SECTION) { chpr += printf(" No APP1 header name string found"); chpr = newline(chpr); } /* offset of last byte of segment */ if(PRINT_SECTION) { print_tag_address(SECTION,max_offset - 1,indent,"-"); chpr += printf("",name); chpr = newline(chpr); } } return(max_offset); appdump: if(app_length > 0L) { if((PRINT_APPNDUMP) || (dumplength > 0)) { if((Max_appdump == DUMPALL) || (Max_appdump > (app_length + 2))) dumplength = app_length + 2; else if(Max_appdump > 0L) dumplength = Max_appdump; else if(dumplength == 0) dumplength = Max_undefined; if(dumplength) { chpr = newline(1); hexdump(inptr,app1_offset,app_length + 2,dumplength,16, indent + SMALLINDENT,SMALLINDENT); chpr = newline(1); } } else { if(PRINT_SEGMENT) { chpr += printf(" - (not dumped: use -A)"); chpr = newline(chpr); } } max_offset = app1_offset + app_length + 2; /* close off the segment; a start "tag" was printed */ print_tag_address(SECTION,app1_offset + app_length + 1,indent,"-"); if(PRINT_SECTION) { chpr += printf("",name); chpr = newline(chpr); } } setcharsprinted(chpr); return(max_offset); } /* Process (print) an APP3 (Meta) section */ unsigned long process_app3(FILE *inptr,unsigned long app3_offset,unsigned short tag, struct image_summary *summary_entry,char *parent_name, int indent) { unsigned long max_offset = 0UL; unsigned long ifd_offset,fileoffset_base; unsigned long dumplength = 0UL; unsigned short app_length = 0; int chpr = 0; struct fileheader *header; char *app_string,*name; char *fulldirname = CNULL; if(inptr) { if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_APPN; summary_entry->filesubformatAPPN[3] = 1; } /* display the APP3 header */ name = tagname(tag); /* never null */ if(PRINT_SECTION) { print_tag_address(SECTION,app3_offset,indent,"@"); chpr += printf("<%s> %#x ",name,tag); } app_length = read_ushort(inptr,TIFF_MOTOROLA,HERE); if(ferror(inptr) || feof(inptr)) { clearerr(inptr); goto appdump; } if(PRINT_SECTION) chpr += printf("length %u, ",app_length); else if((PRINT_ENTRY)) { /* ###%%% pseudo-tags fpr LIST Mode here */ print_tag_address(ENTRY,HERE,indent,"*"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-14.14s","APP3"); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%-9u",app3_offset,app_length); chpr = newline(chpr); } app_string = read_appstring(inptr,JPEG_APP3,HERE); if(ferror(inptr) || feof(inptr)) { clearerr(inptr); goto appdump; } if(app_string) { if(PRINT_SECTION) chpr += printf("\'%s\'",app_string); /* The next thing we see should be a TIFF header tag */ /* indicating byte order used in the IFD, followed by the */ /* offset from the start of the header to the start of */ /* the IFD (number of entries). */ fileoffset_base = ftell(inptr); /* If this is a valid Meta segment, skip the pad byte. */ if(strncmp(app_string,"Meta",4) == 0) { fulldirname = splice(parent_name,".","APP3"); ++fileoffset_base; if(PRINT_SECTION) { chpr = newline(chpr); print_tag_address(SECTION,fileoffset_base,indent + SMALLINDENT,"@"); } header = read_imageheader(inptr,fileoffset_base); if(header && (print_header(header,SECTION) == 0) && (header->probe_magic == TIFF_MAGIC)) { ifd_offset = read_ulong(inptr,header->file_marker,HERE); if(PRINT_SECTION) { chpr += printf(" ifd offset = %lu (+ %lu = %#lx/%lu)",ifd_offset, fileoffset_base,fileoffset_base + ifd_offset, fileoffset_base + ifd_offset); chpr = newline(chpr); } max_offset = process_tiff_ifd(inptr,header->file_marker,ifd_offset, fileoffset_base,0L,summary_entry,fulldirname, TIFF_IFD,0,-1,indent + SMALLINDENT); if(max_offset < app3_offset + app_length + 2) max_offset = app3_offset + app_length +2; } else { max_offset = app3_offset + app_length + 2; if(PRINT_SECTION) { extraindent(indent + ADDRWIDTH); if(header) { chpr += printf(" INVALID MAGIC %lu (%s) where TIFF header should be", header->probe_magic,tagname(header->probe_magic)); } else { chpr += printf(" INVALID HEADER for TIFF"); } #define PRINT_A_BIT 48 if(app_length > PRINT_A_BIT) dumplength = PRINT_A_BIT; else dumplength = app_length; goto appdump; } } if(fulldirname) free(fulldirname); } else { max_offset = app3_offset + app_length + 2; if(PRINT_SECTION) { chpr += printf(" - unknown format"); goto appdump; } } } else if(PRINT_SECTION) { chpr += printf(" No APP3 header name string found"); chpr = newline(chpr); } /* offset of last byte of segment */ if(PRINT_SECTION) { print_tag_address(SECTION,max_offset - 1,indent,"-"); chpr += printf("",name); chpr = newline(chpr); } } return(max_offset); appdump: if(app_length > 0L) { if((PRINT_APPNDUMP) || (dumplength > 0)) { if((Max_appdump == DUMPALL) || (Max_appdump > (app_length + 2))) dumplength = app_length + 2; else if(Max_appdump > 0L) dumplength = Max_appdump; else if(dumplength == 0) dumplength = Max_undefined; if(dumplength) { chpr = newline(1); hexdump(inptr,app3_offset,app_length + 2,dumplength,16, indent + SMALLINDENT,SMALLINDENT); chpr = newline(1); } } else { if(PRINT_SEGMENT) { chpr += printf(" - (not dumped: use -A)"); chpr = newline(chpr); } } max_offset = app3_offset + app_length + 2; /* close off the segment; a start "tag" was printed */ print_tag_address(SECTION,app3_offset + app_length + 1,indent,"-"); if(PRINT_SECTION) { chpr += printf("",name); chpr = newline(chpr); } } setcharsprinted(chpr); return(max_offset); } #undef PRINT_A_BIT /* Unknown APPn markers; hex dump them and move on. */ unsigned long process_appn(FILE *inptr,unsigned long appn_offset,unsigned short tag, struct image_summary *summary_entry,char *parent_name, int indent) { char *app_string,*name; unsigned short app_length = 0; unsigned long dumplength = 0L; int chpr = 0; int tagwidth = 13; if(inptr) { if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_APPN; summary_entry->filesubformatAPPN[tag & 0xf] = 1; } name = tagname(tag); /* never null */ app_length = read_ushort(inptr,TIFF_MOTOROLA,appn_offset + 2); print_tag_address(SECTION,appn_offset,indent,"@"); if(PRINT_SECTION) chpr += printf("<%s> %#x length %u, ",name,tag,app_length); app_string = read_appstring(inptr,tag,HERE); if(PRINT_SECTION) chpr += printf("%s",app_string ? app_string : "NULL ID"); else if((PRINT_ENTRY)) { /* ###%%% pseudo-tags fpr LIST Mode here */ print_tag_address(ENTRY,HERE,indent,"*"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); tagwidth = 13; if((tag & 0xf) > 9) --tagwidth; chpr += printf("%-*.*s%d",tagwidth,tagwidth,"APP",tag & 0xf); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%-9u",appn_offset,app_length); chpr = newline(chpr); } if(PRINT_APPNDUMP) { if((Max_appdump == DUMPALL) || (Max_appdump > (app_length + 2))) dumplength = app_length + 2; else if(Max_appdump > 0L) dumplength = Max_appdump; else dumplength = Max_undefined; if(dumplength) { chpr = newline(1); hexdump(inptr,appn_offset,app_length + 2,dumplength,16, indent,SMALLINDENT); chpr = newline(1); } } else if(PRINT_SECTION) { chpr += printf(" - unknown format (not dumped: use -A)"); chpr = newline(chpr); } print_tag_address(SECTION,appn_offset + app_length + 1,indent,"-"); if(PRINT_SECTION) { chpr += printf("",name); chpr = newline(chpr); } fseek(inptr,appn_offset + app_length,SEEK_SET); } setcharsprinted(chpr); return(appn_offset + app_length + 2); } /* Print the string data from an APP12 segment, if hexdump hasn't */ /* been asked. The "[fileinfo]" stuff is unknown format, but this */ /* part should be useful. */ unsigned long process_app12(FILE *inptr,unsigned long app12_offset,unsigned short tag, struct image_summary *summary_entry,char *parent_name, int indent) { char *app_string,*name; unsigned short app_length = 0; unsigned long dumplength = 0UL; unsigned long offset = 0UL; unsigned long end_offset = 0UL; unsigned long size = 0UL; int chpr = 0; int nextch; if(inptr) { if(summary_entry) { summary_entry->filesubformat |= FILESUBFMT_APPN; summary_entry->filesubformatAPPN[12] = 1; } name = tagname(tag); /* never null */ app_length = read_ushort(inptr,TIFF_MOTOROLA,app12_offset + 2); print_tag_address(SECTION,app12_offset,indent,"@"); if(PRINT_SECTION) chpr += printf("<%s> %#x length %u, ",name,tag,app_length); else if((PRINT_ENTRY)) { /* ###%%% pseudo-tags fpr LIST Mode here */ print_tag_address(ENTRY,HERE,indent,"*"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%-14.14s","APP12"); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%-9u",app12_offset,app_length); chpr = newline(chpr); } app_string = read_appstring(inptr,tag,HERE); if(PRINT_SECTION) chpr += printf("\'%s\'",app_string ? app_string : "NULL ID"); if(PRINT_APPNDUMP) { if((Max_appdump == DUMPALL) || (Max_appdump > (app_length + 2))) dumplength = app_length + 2; else if(Max_appdump > 0L) dumplength = Max_appdump; else dumplength = Max_undefined; if(dumplength) { if(PRINT_SECTION) chpr = newline(chpr); hexdump(inptr,app12_offset,app_length + 2,dumplength,16, indent + SMALLINDENT,SMALLINDENT); chpr = newline(1); } } else if((PRINT_APPENTRY) && (PRINT_ENTRY)) { /* ###%%% in LIST mode, these should get an "APP12." prefix */ end_offset = app12_offset + app_length + 1; offset = ftell(inptr); nextch = skip_past_newline(inptr,end_offset); offset = ftell(inptr); if(PRINT_SECTION) chpr = newline(chpr); if(offset < end_offset); nextch = putword(inptr,nextch,end_offset,indent); chpr = newline(chpr); offset = ftell(inptr); while(nextch && (nextch != EOF) && (offset < end_offset)) { nextch = putword(inptr,nextch,end_offset,indent); if(nextch) chpr = newline(chpr); offset = ftell(inptr); } while(offset < end_offset) { nextch = skip_to_bracket(inptr,end_offset); if(nextch == EOF) { break; } size = ftell(inptr) - offset; if(nextch == '[') --size; if(size > 1) { chpr += printf(" length %lu",size); if(Max_undefined) { chpr = newline(chpr); hexdump(inptr,offset,size, Max_undefined,16, indent + SMALLINDENT, SMALLINDENT); chpr = newline(1); nextch = fgetc(inptr); if((nextch == EOF) || (ftell(inptr) >= end_offset)) break; } else { printred(" (not dumped; use -U)"); chpr = newline(chpr); } } else chpr = newline(chpr); if(nextch) nextch = putword(inptr,nextch,end_offset,indent); offset = ftell(inptr); } } print_tag_address(SECTION,app12_offset + app_length + 1,indent,"-"); if(PRINT_SECTION) { chpr += printf("",name); chpr = newline(chpr); } } setcharsprinted(chpr); return(app12_offset + app_length + 2); } /* Read and discard until the next newline in the input stream, or */ /* until 'max_offset' is reached. Return the last character read. */ int skip_past_newline(FILE *inptr,unsigned long max_offset) { int ch; while(((unsigned long)ftell(inptr) < max_offset) && ((ch = fgetc(inptr)) != '\n') && ch != EOF) continue; return(fgetc(inptr)); } /* Read and discard until the next '[' in the input stream, or until */ /* 'max_offset' is reached. Return the last character read. */ int skip_to_bracket(FILE *inptr,unsigned long max_offset) { int ch = EOF; while(((unsigned long)ftell(inptr) < max_offset) && ((ch = fgetc(inptr)) != '[') && ch != EOF) continue; if(ftell(inptr) >= max_offset) ch = 0; return(ch); } /* Print a word from an APP12 segment. The first character of the */ /* word is passed in by the caller; if it's a left square bracket, it */ /* is assumed to start a "section" and is indented a little less. */ /* This can print a lone open-bracket, but what the heck. */ /* CRs are stripped out and nulls end a word. Newlines are stripped */ /* as well, but cause the next character to be read and passed back */ /* to the caller, to be used as the start of a new word. Otherwise */ /* the last character read is returned. */ /* The routine is not allowed to read past 'max_offset', which should */ /* be the end of the segment. */ int putword(FILE *inptr,int firstch,unsigned long max_offset,int indent) { int eol = 0; int chpr = 0; int ch = firstch; if(firstch) print_tag_address(APP_ENTRY,ftell(inptr),indent + SMALLINDENT,"@"); if(firstch) { if(firstch != '[') extraindent(SMALLINDENT); putchar(firstch); ++chpr; } else ++eol; while(((unsigned long)ftell(inptr) < max_offset) && !eol) { ch = fgetc(inptr); switch(ch) { case '\r': break; case 0: ++eol; break; case '\n': ++eol; ch = fgetc(inptr); break; case EOF: ++eol; break; default: if(isprint(ch)) putchar(ch); ++chpr; break; } } setcharsprinted(chpr); return(ch); } /* Determine if the values for an IFD entry are recorded at an */ /* offset. Returns 0 if the value is recorded directly in the entry, */ /* 1 if the value is offset. */ int is_offset(struct ifd_entry *entry_ptr) { if((value_type_size(entry_ptr->value_type) * entry_ptr->count) > 4) return(1); return(0); } /* Process an Epson Print Image Matching section, included in many */ /* cameras for the purpose of adjusting image parameters when */ /* printing the image, according to values pre-determined by the */ /* device manufacturer. According to Epson, parametes which may be */ /* adjusted include: */ /* Gamma Level */ /* Color Space */ /* Color Balance */ /* Contrast */ /* Brightness */ /* Sharpness */ /* Saturation */ /* Shadow */ /* Highlight */ /* Pim version 2 also handles: */ /* Noise Reduction */ /* Custom Scene setting */ /* This routine knows just enough about the structure of PIM to print */ /* tag numbers and values, but interpretation of tags is not known. */ /* Values are printed in decimal and hex. */ unsigned long process_pim(FILE *inptr,unsigned short byteorder,unsigned long pim_offset, unsigned long fileoffset_base, unsigned long count, char *tagname,char *dirname,char *prefix, int indent) { unsigned long entry_offset,extra,value; unsigned long max_offset = 0L; unsigned long max_value_offset = 0L; unsigned char *pim_id,*pim_version,*valueptr; unsigned short tag; int tagwidth = PIMTAGWIDTH; int chpr = 0; int entry_num,num_entries; if(inptr == (FILE *)0) { fprintf(stderr,"%s: no open file pointer to read Print Image data\n", Progname); max_offset = 0L; return(0L); } entry_offset = pim_offset + fileoffset_base; max_offset = entry_offset + count; /* Always starts with "PrintIM\0"; read it as a sanity check */ pim_id = read_bytes(inptr,8,entry_offset); if((pim_id == (unsigned char *)0) || strncasecmp((char *)pim_id,"PrintIM",8) != 0) { /* Print the value as a comment here, since we are processing */ /* no further. */ if(PRINT_SECTION) { print_tag_address(SECTION,entry_offset,indent,prefix); chpr += printf("%s",tagname); if((PRINT_VALUE)) chpr += printf(": length %lu",count); } if(!(PRINT_SECTION)) { chpr = newline(chpr); printred("# WARNING:"); } printred(" INVALID PrintImage data..."); return(0L); } chpr = newline(0); pim_version = read_bytes(inptr,6,HERE); num_entries = read_ushort(inptr,byteorder,HERE); if(PRINT_SECTION) { print_tag_address(SECTION,entry_offset,indent,prefix); chpr += printf("<%s> Version %s, size %lu, %d entries",tagname,pim_version, count,num_entries); if((num_entries * 6) > (count - 16)) { chpr = newline(chpr); num_entries = (count - 16) / 6; PUSHCOLOR(HI_RED); chpr += printf("# WARNING: PIM claims too many entries for section size, printing %d",num_entries); POPCOLOR(); } } else { /* Make pseudo-tags for these */ if((PRINT_TAGINFO) || (PRINT_VALUE)) print_tag_address(ENTRY,HERE,indent+SMALLINDENT,"*"); if(PRINT_TAGINFO) { if((PRINT_LONGNAMES)) chpr += printf("%s.",dirname); chpr += printf("%s.",tagname); chpr += printf("%-*.*s",tagwidth,tagwidth,"Offset"); } if((PRINT_VALUE)) chpr += printf(" = @%lu",entry_offset); chpr = newline(chpr); if((PRINT_TAGINFO) || (PRINT_VALUE)) print_tag_address(ENTRY,HERE,indent+SMALLINDENT,"*"); if(PRINT_TAGINFO) { if((PRINT_LONGNAMES)) chpr += printf("%s.",dirname); chpr += printf("%s.",tagname); chpr += printf("%-*.*s",tagwidth,tagwidth,"Length"); } if((PRINT_VALUE)) chpr += printf(" = %lu",count); chpr = newline(chpr); if((PRINT_TAGINFO) || (PRINT_VALUE)) print_tag_address(ENTRY,HERE,indent+SMALLINDENT,"*"); if(PRINT_TAGINFO) { if((PRINT_LONGNAMES)) chpr += printf("%s.",dirname); chpr += printf("%s.",tagname); chpr += printf("%-*.*s",tagwidth,tagwidth,"Version"); } if((PRINT_VALUE)) chpr += printf(" = %s",pim_version); chpr = newline(chpr); if((num_entries * 6) > (count - 16)) { chpr = newline(chpr); chpr += printf("# WARNING: PIM claims too many entries (%d) for section size; ",num_entries); num_entries = (count - 16) / 6; PUSHCOLOR(HI_RED); chpr += printf("printing %d",num_entries); POPCOLOR(); } } max_value_offset = entry_offset = ftell(inptr); indent += SMALLINDENT; for(entry_num = 0; entry_num < num_entries; ++entry_num) { int i; chpr = newline(chpr); tag = read_ushort(inptr,byteorder,HERE); if(ferror(inptr) || feof(inptr)) goto blewit; if((PRINT_ENTRY)) { print_tag_address(ENTRY,entry_offset,indent,prefix); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.%s.",dirname,tagname); else if((LIST_MODE)) chpr += printf("%s.",tagname); chpr += printf("PIM_%#06X",(int)tag); if((PRINT_VALUE)) { putindent(tagwidth - 10); chpr += printf(" = "); } } } valueptr = read_bytes(inptr,4,HERE); value = read_ulong(inptr,byteorder,entry_offset + 2); if(PRINT_SECTION) { if((PRINT_VALUE)) { for(i = 0; i < 4; ++i) chpr += printf("%02x ",(unsigned int)(valueptr[i] & 0xff)); chpr += printf(" |"); for(i = 0; i < 4; ++i) { if(isprint(valueptr[i])) putchar(valueptr[i]); else putchar('.'); /* can't win 'em all */ } chpr += printf("| = %#lx/%lu",value,value); } } else if((PRINT_VALUE)) chpr += printf("%#lx/%lu",value,value); max_value_offset = entry_offset = ftell(inptr); } if(PRINT_SECTION) { chpr = newline(chpr); if((max_value_offset < max_offset) && PRINT_VALUE_AT_OFFSET) { int printlength = 0; print_tag_address(SECTION,max_value_offset,indent,"*"); PUSHCOLOR(RED); chpr += printf("---- End of values before end of %s section",tagname); POPCOLOR(); chpr = newline(chpr); extra = max_offset - max_value_offset; /* dump the extra as UNDEFINED */ if(Max_undefined) { if((Max_undefined == DUMPALL) || (Max_undefined > extra)) printlength = extra; else if(Max_undefined > 0L) printlength = Max_undefined; hexdump(inptr,max_value_offset,extra,printlength,6,indent, SMALLINDENT+8); } chpr = newline(chpr); } indent -= SMALLINDENT; print_tag_address(SECTION,max_offset - 1,indent,"-"); chpr += printf("",tagname); } setcharsprinted(chpr); return(max_value_offset - 1); blewit: clearerr(inptr); return(0L); } exifprobe-2.0.1+git20170416-3c2b76/misc.h0000644000000000000000000000454313074742216015623 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: misc.h,v 1.4 2005/06/09 02:21:30 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Miscellaneous definitions */ #ifndef MISC_INCLUDED #define MISC_INCLUDED /* These magic numbers are defined by well-known specification */ #define TIFF_MAGIC 0x2a #define TIFF_INTEL 0x4949 #define TIFF_MOTOROLA 0x4d4d #define ORF1_MAGIC 0x4f52 /* "RO" 16 bits/sample PMI=1 res=314 */ #define ORF2_MAGIC 0x5352 /* "RS" 12 bits/sample PMI=2 res=72 */ #define RW2_MAGIC 0x0055 /* "U\0" for Panasonic RAW and RW2 */ /* Some of these magic numbers are private to this program, used to */ /* id file formats which have no unique magic number. */ #define PROBE_NOMAGIC 0x0000 #define PROBE_TIFFMAGIC TIFF_MAGIC #define PROBE_ORF1MAGIC ORF1_MAGIC #define PROBE_ORF2MAGIC ORF2_MAGIC #define PROBE_JPEGMAGIC 0xffd8 /* JPEG_SOI */ #define PROBE_CIFFMAGIC 0x1a #define PROBE_JP2MAGIC 0x0d0a870a #define PROBE_MRWMAGIC 0x004d524d /* "MRM" (ANY byte order) */ #define PROBE_RAFMAGIC 0x4655 /* "FU"JIFILM-CCDRAW (MOT) */ #define PROBE_X3FMAGIC 0x62564f46 /* "FOVb" (INTEL) */ #define PROBE_RW2MAGIC RW2_MAGIC /* TIFF entry type id */ #define BYTE 1 #define ASCII 2 #define SHORT 3 #define LONG 4 #define RATIONAL 5 #define SBYTE 6 #define SSHORT 8 #define UNDEFINED 7 #define SLONG 9 #define FLOAT 11 #define SRATIONAL 10 #define DOUBLE 12 char * strdup_value(struct ifd_entry *entry, FILE *inptr, unsigned long fileoffset_base); #endif /* MISC_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/tifftags.h0000644000000000000000000001325113074742216016473 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: tifftags.h,v 1.2 2005/05/30 15:53:10 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* All tags defined in TIFF6 spec */ #ifndef TIFFTAGS_INCLUDED #define TIFFTAGS_INCLUDED #define TIFFTAG_NewSubFileType 0x00FE /* 254 */ #define TIFFTAG_OldSubFileType 0x00FF /* 255 */ #define TIFFTAG_ImageWidth 0x0100 /* 256 */ #define TIFFTAG_ImageLength 0x0101 /* 257 */ #define TIFFTAG_BitsPerSample 0x0102 /* 258 */ #define TIFFTAG_Compression 0x0103 /* 259 */ #define TIFFTAG_PhotometricInterpretation 0x0106 /* 262 */ #define TIFFTAG_Thresholding 0x0107 /* 263 */ #define TIFFTAG_CellWidth 0x0108 /* 264 */ #define TIFFTAG_CellLength 0x0109 /* 265 */ #define TIFFTAG_FillOrder 0x010A /* 266 */ #define TIFFTAG_DocumentName 0x010D /* 269 */ #define TIFFTAG_ImageDescription 0x010E /* 270 */ #define TIFFTAG_Make 0x010F /* 271 */ #define TIFFTAG_Model 0x0110 /* 272 */ #define TIFFTAG_StripOffsets 0x0111 /* 273 */ #define TIFFTAG_Orientation 0x0112 /* 274 */ #define TIFFTAG_SamplesPerPixel 0x0115 /* 277 */ #define TIFFTAG_RowsPerStrip 0x0116 /* 278 */ #define TIFFTAG_StripByteCounts 0x0117 /* 279 */ #define TIFFTAG_MinSampleValue 0x0118 /* 280 */ #define TIFFTAG_MaxSampleValue 0x0119 /* 281 */ #define TIFFTAG_XResolution 0x011A /* 282 */ #define TIFFTAG_YResolution 0x011B /* 283 */ #define TIFFTAG_PlanarConfiguration 0x011C /* 284 */ #define TIFFTAG_PageName 0x011D /* 285 */ #define TIFFTAG_XPosition 0x011E /* 286 */ #define TIFFTAG_YPosition 0x011F /* 287 */ #define TIFFTAG_FreeOffsets 0x0120 /* 288 */ #define TIFFTAG_FreeByteCounts 0x0121 /* 289 */ #define TIFFTAG_GrayResponseUnit 0x0122 /* 290 */ #define TIFFTAG_GrayResponseCurve 0x0123 /* 291 */ #define TIFFTAG_T4Options 0x0124 /* 292 */ #define TIFFTAG_T6Options 0x0125 /* 293 */ #define TIFFTAG_ResolutionUnit 0x0128 /* 296 */ #define TIFFTAG_PageNumber 0x0129 /* 297 */ #define TIFFTAG_TransferFunction 0x012D /* 301 */ #define TIFFTAG_Software 0x0131 /* 305 */ #define TIFFTAG_DateTime 0x0132 /* 306 */ #define TIFFTAG_Artist 0x013B /* 315 */ #define TIFFTAG_HostComputer 0x013C /* 316 */ #define TIFFTAG_Predictor 0x013D /* 317 */ #define TIFFTAG_WhitePoint 0x013E /* 318 */ #define TIFFTAG_PrimaryChromaticities 0x013F /* 319 */ #define TIFFTAG_ColorMap 0x0140 /* 320 */ #define TIFFTAG_HalftoneHints 0x0141 /* 321 */ #define TIFFTAG_TileWidth 0x0142 /* 322 */ #define TIFFTAG_TileLength 0x0143 /* 323 */ #define TIFFTAG_TileOffsets 0x0144 /* 324 */ #define TIFFTAG_TileByteCounts 0x0145 /* 325 */ #define TIFFTAG_SubIFDtag 0x014A /* 330 */ #define TIFFTAG_InkSet 0x014C /* 332 */ #define TIFFTAG_InkNames 0x014D /* 333 */ #define TIFFTAG_NumberOfInks 0x014E /* 334 */ #define TIFFTAG_DotRange 0x0150 /* 336 */ #define TIFFTAG_TargetPrinter 0x0151 /* 337 */ #define TIFFTAG_ExtraSamples 0x0152 /* 338 */ #define TIFFTAG_SampleFOrmat 0x0153 /* 339 */ #define TIFFTAG_SMinSampleValue 0x0154 /* 340 */ #define TIFFTAG_SMaxSampleValue 0x0155 /* 341 */ #define TIFFTAG_TransferRange 0x0156 /* 342 */ #define TIFFTAG_JPEGTables 0x015B /* 347 */ #define TIFFTAG_JpegProc 0x0200 /* 512 */ #define TIFFTAG_JPEGInterchangeFormat 0x0201 /* 513 */ #define TIFFTAG_JPEGInterchangeFormatLength 0x0202 /* 514 */ #define TIFFTAG_JPEGRestartInterval 0x0203 /* 515 */ #define TIFFTAG_JPEGLosslessPredictor 0x0205 /* 517 */ #define TIFFTAG_JPEGPointTransforms 0x0206 /* 518 */ #define TIFFTAG_JPEGQTables 0x0207 /* 519 */ #define TIFFTAG_JPEGDCTables 0x0208 /* 520 */ #define TIFFTAG_JPEGACTables 0x0209 /* 521 */ #define TIFFTAG_YCbCrCoefficients 0x0211 /* 529 */ #define TIFFTAG_YCbCrSubSampling 0x0212 /* 530 */ #define TIFFTAG_YcbCrPositioning 0x0213 /* 531 */ #define TIFFTAG_ReferenceBlackWhite 0x0214 /* 532 */ #define TIFFTAG_Copyright 0x8298 /* 32432 */ #endif exifprobe-2.0.1+git20170416-3c2b76/kyocera_datadefs.h0000644000000000000000000000171313074742216020154 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: kyocera_datadefs.h,v 1.2 2005/06/21 15:11:21 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef KYOCERA #define KYOCERA #include "maker_datadefs.h" struct camera_id kyocera_model_id[] = { { "FC-S3",6, KYOCERA_FCS3, 1, 1 }, { "Finecam S5 ",11, KYOCERA_FINECAMS5, 1, 1 }, { 0, 0, 0, 0, 0 } }; #endif /* KYOCERA */ exifprobe-2.0.1+git20170416-3c2b76/CHANGES_2.00000644000000000000000000002133713074742216016071 0ustar rootroot2.1.0: * Fix crashers: - https://github.com/hfiguiere/exifprobe/issues/5 - https://github.com/hfiguiere/exifprobe/issues/9 * Fix infinite loop due to premature end-of-file (Issue https://github.com/hfiguiere/exifprobe/issues/3) * Fix and infinite recursion for the Interop IFD parsing. * Fix other fuzzing crashers (https://github.com/hfiguiere/exifprobe/issues/2). * Added SRAW Type and Slice tags for CR2 files. * Fix build on Windows (Issue https://github.com/hfiguiere/exifprobe/pull/1) * Fix EXIFPROBE_OPTIONS (https://github.com/hfiguiere/exifprobe/issues/8) * Added basic parsing of Panasonic RAW and RW2 * Updated DNG for 1.3 and 1.4 spec. * Added Cinema DNG. * Fixed RAF header parsing. * Fix printing Software/Make/Model if it is less than 4 bytes (Found in Sony and iPhone generated files). * More Canon MakerNote decoding. * Allow overriding CC at build time * Various misc fixes. 2.0.1: The following changes have been made since version 2.0.0: General code cleanup and bug-fixes for variables which could be used before being set. Fixed some missing 'break' statements in 'default' branches of several switch statements in print_filetype(). These apparently caused gcc 3.4.3 to abort under Linux. Updates to Minolta MakerNotes for A1 and A2 models, contributed by Stanislav Brabec. Also added an identifier for the DiMAGE 5, and updated the CamerSettings ImageSize. Now catches and flags the 'count' bug in the 'ImageByteSize' makernote tag, rather than printing spurious multiple values at the ImageByteSize value used as an offset. In jp2000.c, 'mark' characters for file offsets were inconsistent. Now '@' is used for all box tags, and '=' for untagged entries. Also added a missing initialization for 'max_offset' in process_jp2_de(). APP sections and image data was omitted from output in LIST mode; now printed as 'pseudo-tags' in "@offset:length" format. Also print_offset_makervalue() was not printing @offset:length for UNDEFINED sections in REPORT mode. All 'pseudo-tags' are now marked with '*' in the address field (these only appear in LIST mode, where the address field is not enabled by default). 'Tiled' jpeg images included in tiff IFDs can be compressed tile-by-tile. This has been seen in a few DNG images. It caused report of "early EOI" when the first tile EOI was found, and the remaining tiles ignored. The program now expands the first and last tile, with just tile numbers in between. The TIFF 'XML' tag now has a name. In main(), the file close was handled outside check for null file pointer, and would cause a core dump if no file was open. I hate it when that happens. ExposureInfo was not printed in CIFF directories due to an hidden 'break' statement which caused the following code to be ignored. Also in CIFF, some directory entries would print with empty values in REPORT mode if no option was selected for output format of offsets. Now defaults to decimal offset. ================================================================= 2.0.0: The following changes have been made since version 1.2.6: Support has been added for several "raw" camera file/image formats: MRW,CIFF/CRW,X3F,RAF,JP2/JPEG2000,DNG,CR2,NEF,ORF,PEF,KDC,K25, and TIFF and JPEG support has been improved and generalized. In particular, TIFF routines have fewer expectations that interfere with handling of derived formats, and more information is extracted from JPEG markers. Image summaries have been improved and are now provided for all supported formats (not just TIFF). The new summary scheme avoids problems which occurred in TIFF summaries when IFD chains were longer than two IFDs. Summary entries are provided for all sub-images found in the file. Subtle and not-so-subtle improvements have been made in program output. All image sections (not just JPEG) are now reported "in place" with a brief hex dump of the beginning of data, and an option to dump more. More checks and alerts about "suspicious" file format elements are provided, e.g reports of JPEG_EOI found before the announced end of the section. LIST mode output now uses "long names" consisting of the entire list of parent sections of the current tag, separated by dots. This is more informative, and necessary to avoid duplicate names, but may require post-processing if the output is consumed by a script (most shells don't allow '.' in variable names). Short names in list mode are typically not useful (but suit yourself). Long names can be enabled in structural mode, if you like that sort of thing. Bug fixes: The program is now prepared to handle image summaries for chained TIFF IFDs of any length. Chained IFDs have always been handled, but the image summary mechanism was not prepared to handle chains longer than the 'usual' 2 IFDs. Thumbnails found in the first two IFDs would not be "forgotten" when processing later IFDs and would be reported repeatedly; confused data would appear in the summary. The mechanism would report only JPEG thumbnails and image blobs found in TIFF IFDs. The new summary mechanism displays and records all image sections found, in all supported file formats, and reports useful (and usually more accurate) summary information about each at the end of processing, including a count of images found and where they are located. Expanded MakerNote coverage: Much new data, particularly for Olympus (more tags, MakerNote subifds, etc), and Nikon (including preview subifd). Most of the new information is taken from Phil Harvey's 'ExifTool' web pages at http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/index.html Improved MakerNote handling: The program now defines "noteversions" for makers that use multiple versions, and will attempt to choose the correct version for unknown models. Canon CustomFunctions have been fixed so that D30 CustomFunctions, previously displayed for all models containing CustomFunctions tags, are now displayed only for D30, with additional noteversions for some additional models. An unrecognized Canon model with the CustomFunctions tag will display only the contents, with no attempt at interpretation. New options: Several new options have been added (see the manual page); -B len|a print 'len' (or all) bytes of binary image data or failed JPEG data -C [make]+[model] print known makes and models -n print filename on each line of output (toggle) -pl print long names (default for LIST mode) (toggle) -t disable color by default if output is not to a tty (effective ONLY if set in EXIFPROBE_OPTIONS) -O offset start processing at 'offset' -N noteversion force use of MakerNote version 'noteversion' [a maker-specific number] -u print raw 'unicode' data. Default output assumes data labeled as 'UNICODE' is really ascii in a bigger box, and prints just the low bytes. This option enables raw printing of both bytes (no translations attempted). (toggle) Auxilliary programs: Some crude but sometimes useful auxiliary programs are now included with the distribution. extract_section - extracts a section of a file given start offset and length, or start and end offset (which you can get from exifprobe output). An easy way to extract embedded JPEGs. findjpeg - scan a file for valid jpeg streams. VERY crude, and not useful on mostly binary files. dump_section - print a specified chunk of a file as bytes, shorts, longs, or short or long rationals. probetohtml - a simple shell script which uses 'sed' to convert color escape sequences to font color tags and generate an HTML file for the output of exifprobe. reformat.sh - script to reformat LIST output to change dots to underscores, remove comments, etc. to make the output acceptable to a shell for sourcing. The '-var' and '-export' options of exifgrep are no longer adequate for that purpose. convert_rgb_to_tiff - convert the RGB section of a Canon CR2 file to a 384x256 TIFF image that anybody can see. Uses ImageMagick 'convert' utility on extracted d.ata convert_rgb_to_jpeg - convert the RGB section of a Canon CR2 file to a 384x256 JPEG image that anybody can see. Uses ImageMagick 'convert' utility on extracted data. exifprobe-2.0.1+git20170416-3c2b76/main.c0000644000000000000000000003435413074742216015612 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: main.c,v 1.30 2005/07/24 15:58:05 alex Exp $"; #endif /* This program reads and reports the structure of and auxilliary */ /* data contained within images produced by digital cameras or */ /* similar devices. The program understands several file formats, */ /* including TIFF, JPEG, MRW, CIFF, JP2, RAF, and X3F, and will read */ /* most TIFF-derived formats such as EXIF, ORF, CR2, NEF, K25, KDC, */ /* DNG, and PEF. The RAF code is "preliminary". */ /* MakerNote sections found in Exif IFDs are reported and expanded if */ /* the note is in a semblance of TIFF IFD format (determined */ /* automatically, without reference to device make or model). */ /* Information which has been published on the internet is used to */ /* interpret notes where possible. */ /* The default output attempts to describe the structure of the file, */ /* showing location, size and content of auxilliary data and image */ /* sections. Multiple images contained in a single file are noted */ /* (and JPEG sub-image markers examined for useful data). A summary */ /* of images found is printed at the end of output for each file, */ /* including a report of "file format" composed of the major sections */ /* found, and the size of the file. */ /* Many options are provided for detail control of output format. For */ /* convenience, two pre-set formats (in addition to the default */ /* 'structural' format) provide a "report" format (which shows */ /* "structure" of TIFF ifds, but with values printed inline), and a */ /* "list" format which eliminates structural elements and presents */ /* data in a human (or script) readable format for possible use in */ /* gallery applications. */ #include #include #include #include #include "defs.h" #include "summary.h" #include "global.h" #include "datadefs.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "ciff_extern.h" #include "x3f_extern.h" #include "jp2_extern.h" #include "mrw_extern.h" #include "maker_extern.h" int main(int argc,char **argv) { char *file; char *name = CNULL; FILE *inptr; int status = -1; unsigned long max_offset = 0UL; unsigned long ifd_offset = 0UL; unsigned long dumplength = 0UL; struct fileheader *header = NULL; struct image_summary *summary_entry = NULL; unsigned long filesize = 0UL; int chpr = 0; Progname = *argv; /* Gather options from EXIFPROBE_OPTIONS first */ env_options(); /* Now the command line */ argv += process_options(argc,argv); while((file = *argv++)) { inptr = fopen(file,"rb"); if(inptr == FNULL) { fprintf(stderr,"%s: failed to open file %s\n",Progname,file); why(stderr); max_offset = 0L; } else { PUSHCOLOR(BLACK); setfilename(file); /* for '-n' option */ filesize = get_filesize(inptr); if(Start_offset > filesize) { PUSHCOLOR(RED); print_filename(); chpr += printf(" start offset %lu > filesize %lu\n", Start_offset,filesize); POPCOLOR(); continue; } else if(Start_offset) { if(fseek(inptr,Start_offset,SEEK_SET) == -1) { fprintf(stderr,"%s: FAILED to seek to start offset %lu\n", Progname,Start_offset); why(stdout); continue; } printf("# Start at %ld\n",ftell(inptr)); } print_filename(); /* for '-n' option */ if((LIST_MODE)) chpr += printf("FileName = %s",file); else chpr += printf("File Name = %s",file); chpr = newline(chpr); header = read_imageheader(inptr,Start_offset); if(ferror(inptr)) continue; print_filename(); if((LIST_MODE)) chpr += printf("FileType = "); else chpr += printf("File Type = "); status = print_filetype(header->probe_magic,header->file_marker); chpr = newline(chpr); print_filename(); if((LIST_MODE)) chpr += printf("FileSize = %lu",filesize); else chpr += printf("File Size = %lu",filesize); chpr = newline(chpr); if(status == 0) { switch(header->probe_magic) { case ORF1_MAGIC: case ORF2_MAGIC: case RW2_MAGIC: case TIFF_MAGIC: ifd_offset = read_ulong(inptr,header->file_marker,HERE); if(ifd_offset > filesize) { hexdump(inptr,Start_offset,10,10,12,0,0); chpr = newline(chpr); if(Max_undefined > 0L) dumplength = Max_undefined - 10; else dumplength = 60; if(dumplength) { hexdump(inptr,Start_offset + 10, filesize - 10 - Start_offset, dumplength,12,0,0); chpr = newline(1); } status = -1; break; } summary_entry = new_summary_entry(NULL,header->probe_magic,TIFF_IFD); name = "TIFF"; switch(header->probe_magic) { case ORF1_MAGIC: name = "ORF1"; break; case ORF2_MAGIC: name = "ORF2"; break; case RW2_MAGIC: name = "RW2"; break; case TIFF_MAGIC: default: break; } if(PRINT_SECTION) { print_tag_address(SECTION,Start_offset,0,"@"); status = print_header(header,SECTION); chpr += printf(" ifd offset = %#lx/%lu",ifd_offset,ifd_offset); if(Start_offset) { chpr += printf(" (+ %lu = %#lx/%lu)",Start_offset, Start_offset + ifd_offset, Start_offset + ifd_offset); } chpr = newline(chpr); } max_offset = process_tiff_ifd(inptr,header->file_marker, ifd_offset,Start_offset,0L,summary_entry,name, TIFF_IFD,0,-1,0); if(max_offset > 0L) status = 0; fflush(stdout); break; case JPEG_SOI: summary_entry = new_summary_entry(NULL,FILEFMT_JPEG,IMGFMT_JPEG); if(summary_entry) summary_entry->subfiletype = PRIMARY_TYPE; max_offset = process_jpeg_segments(inptr,Start_offset,JPEG_SOI,0L,summary_entry, "JPEG","@",0); status = jpeg_status(0); fflush(stdout); break; case PROBE_CIFFMAGIC: summary_entry = new_summary_entry(NULL,FILEFMT_CIFF,IMGFMT_CRW); if(PRINT_SECTION) { print_tag_address(SECTION,Start_offset,0,"@"); status = print_header(header,SECTION); } max_offset = process_ciff(inptr,header,Start_offset,0L,summary_entry,"CIFF",0,0); if(max_offset > 0L) status = 0; fflush(stdout); break; case PROBE_JP2MAGIC: summary_entry = new_summary_entry(NULL,FILEFMT_JP2,IMGFMT_JPEG2000); if(PRINT_SECTION) { print_tag_address(SECTION,Start_offset,0,"@"); status = print_header(header,SECTION); } max_offset = process_jp2(inptr,Start_offset + 12L,summary_entry,"JP2",0L); if(max_offset > 0L) status = 0; fflush(stdout); break; case PROBE_MRWMAGIC: summary_entry = new_summary_entry(NULL,FILEFMT_MRW,IMGFMT_MRW); if(PRINT_SECTION) { print_tag_address(SECTION,Start_offset,0,"@"); status = print_header(header,SECTION); } max_offset = process_mrw(inptr,Start_offset + 8L, header->mrw_header.mrw_dataoffset, filesize - header->mrw_header.mrw_dataoffset, summary_entry,"MRW",0L); if(max_offset > 0L) status = 0; fflush(stdout); break; case PROBE_RAFMAGIC: summary_entry = new_summary_entry(NULL,FILEFMT_RAF,IMGFMT_RAF); if(PRINT_SECTION) { print_tag_address(SECTION,Start_offset,0,"@"); status = print_raf_header(inptr,header,SECTION); } if(status == 0) { max_offset = process_raf(inptr,Start_offset + 60,summary_entry,"RAF",0L); if(max_offset > 0L) status = 0; } fflush(stdout); break; case PROBE_X3FMAGIC: summary_entry = new_summary_entry(NULL,FILEFMT_X3F,IMGFMT_X3F); if(PRINT_SECTION) { print_tag_address(SECTION,Start_offset,0,"@"); status = print_x3f_header(inptr,header,SECTION); } if(status == 0) { max_offset = process_x3f(inptr,header,Start_offset,summary_entry, "X3F",0,0); if(max_offset > 0L) status = 0; } break; default: status = -1; break; } if(status == JPEG_EARLY_EOI) chpr = newline(chpr); print_tag_address(SECTION,filesize - 1,0,"-"); if(PRINT_SECTION) { chpr += printf("END OF FILE"); if(status == JPEG_EARLY_EOI) { jpeg_status(status); print_jpeg_status(); } } chpr = newline(chpr); /* Print a summary of image sections found */ print_summary(summary_entry); } else { /* Allow hex/ascii dump of unregcognized file */ /* formats. In fact, always dump a little bit. */ if(Max_undefined == DUMPALL) dumplength = filesize; else if(Max_undefined > 0L) dumplength = Max_undefined; else dumplength = DEF_DUMPLENGTH; if(dumplength) { hexdump(inptr,Start_offset,filesize,dumplength,16,0,0); chpr = newline(chpr); } } print_fileformat(summary_entry); summary_entry = destroy_summary(summary_entry); chpr = newline(1); if(inptr && fclose(inptr)) { fprintf(stderr,"%s: FAILED to close stream for file \"%s\"\n",Progname,file); why(stderr); } } clear_memory(); /* Make, Model, Software... */ chpr = newline(1); } if(PRINT_CAMERA_NAMES) print_camera_makes(); return(status); } exifprobe-2.0.1+git20170416-3c2b76/maker_casio.c0000644000000000000000000010627713074742216017147 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_casio.c,v 1.19 2005/07/24 22:56:26 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Casio camera maker-specific routines. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Most of the information coded here is due to Eckhard Henkel */ /* (eckhard.henkel@t-online.de) as shown by TsuruZoh Tachibanaya at: */ /* http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html */ /* (now found at: */ /* http://landscapeimage.com/ThumbHTML/help/exif_file_format.html) */ /* Additional information: */ /* http://www.dicasoft.de/casiomn.htm */ /* EP-600 info: (added Jan 05) */ /* evan@ozhiker.com */ /* http://www.ozhiker.com/electronics/pjmt/jpeg_info/casio_mn.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id casio_model_id[]; int casio_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &casio_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Determine and set note version from detected scheme. */ /* Notes with ID scheme use noteversion 2 */ /* Notes with Plain use noteversion 1 */ int set_casio_noteversion() { struct maker_scheme *scheme; int noteversion = 0; int tagset = 0; scheme = retrieve_makerscheme(); if(scheme->note_version <= 0) { noteversion = -1; tagset = -1; switch(scheme->scheme_type) { case HAS_ID_SCHEME: /* "QVC" */ tagset = 2; noteversion = 2; break; case PLAIN_IFD_SCHEME: tagset = 1; noteversion = 1; break; case UNKNOWN_SCHEME: break; default: break; } setnotetagset(tagset); setnoteversion(noteversion); } else noteversion = scheme->note_version; return(noteversion); } /* Dispatch a Casio print routine based upon noteversion */ void print_casio_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 2: print_casio1_makervalue(entry_ptr,make,model,prefix); casio2_interpret_value(entry_ptr); break; case 1: print_casio1_makervalue(entry_ptr,make,model,prefix); casio1_interpret_value(entry_ptr); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Casio cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_casio1_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for Casio */ /* cameras. */ void print_casio_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) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 1: casio1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case 2: casio2_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix, indent,make,model,at_offset); break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in Casio makernotes. */ void casio1_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) { char *nameoftag; unsigned long value_offset,current_offset; unsigned long count; int chpr = 0; char *fulldirname = NULL; if(entry_ptr) { value_offset = fileoffset_base + entry_ptr->value; nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0e00: /* PrintIM (Epson Print Image matching) */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) { chpr += printf("@%lu:%lu",value_offset,count); chpr = newline(chpr); } } current_offset = ftell(inptr); if(process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent) == 0) { /* At least one QV4000 image uses a PIM offset */ /* relative to the entry address, even though */ /* other entries in the note are TIFF-relative; */ /* check for a PIM entry at that location if the */ /* previous one failed. GROSS HACK! */ fileoffset_base = current_offset - 12; PUSHCOLOR(HI_BLACK); chpr += printf(" checking for entry-relative offset bug"); POPCOLOR(); if(process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name, prefix,indent)) { if(!(PRINT_SECTION)) { chpr = newline(chpr); printred("# WARNING:"); } PUSHCOLOR(HI_BLACK); chpr += printf(" %s data found at offset %lu - ",nameoftag, entry_ptr->value + fileoffset_base); printred("start offset is incorrect!"); POPCOLOR(); if(!(PRINT_SECTION)) { chpr = newline(chpr); print_filename(); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fulldirname); chpr += printf("%-*.*s",MAKERTAGWIDTH,MAKERTAGWIDTH,nameoftag); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%lu",entry_ptr->value + fileoffset_base, count); } } } break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } void casio2_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) { unsigned long value_offset,current_offset; unsigned long count; unsigned short marker; char *nameoftag; char *fulldirname = NULL; unsigned long max_offset = 0; int status = 0; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0004: /* JpegThumbnailOffset */ /* When this tag is present, the 0x2000 tag is */ /* present as well. Both entries point to the same */ /* thumbnail, so just print values for length and */ /* offset tags, and display the thumbnail on the */ /* (self-contained) 0x2000 tag */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",value_offset); } break; case 0x2000: /* JpegThumbnail */ if(at_offset && (PRINT_SECTION)) { print_tag_address(SECTION,value_offset,indent,prefix); chpr += printf("# Start of JPEG Thumbnail from MakerNote"); chpr += printf(" length %ld",count); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,entry_ptr->count); else chpr += printf("length %lu", entry_ptr->count); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); max_offset = process_jpeg_segments(inptr,value_offset,marker, count,summary_entry,fulldirname, prefix,indent+SMALLINDENT); if(at_offset) { if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1, indent,prefix); chpr += printf("# End of JPEG Thumbnail from MakerNote"); if((PRINT_ENTRY) && !(PRINT_VALUE)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_IFD; summary_entry->subfiletype = THUMBNAIL_TYPE; } } /* make certain we're at the end */ clearerr(inptr); fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0e00: /* PrintIM (Epson Print Image matching) */ nameoftag = maker_tagname(entry_ptr->tag,make,model); if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",value_offset); } current_offset = ftell(inptr); if(process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, entry_ptr->count,nameoftag,parent_name,prefix,indent) == 0) { /* At least one QV4000 image uses a PIM offset */ /* relative to the entry address, even though */ /* other entries in the note are TIFF-relative; */ /* check for a PIM entry at that location if the */ /* previous one failed. GROSS HACK! */ fileoffset_base = current_offset - 12; PUSHCOLOR(HI_BLACK); /* We've already seen an error message */ chpr += printf(" checking for entry-relative offset bug"); POPCOLOR(); if(process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, entry_ptr->count,nameoftag,parent_name, prefix,indent)) { if(!(PRINT_OFFSET)) { chpr = newline(chpr); chpr += printf("# WARNING:"); } PUSHCOLOR(HI_BLACK); chpr += printf(" PrintImage data found at offset %lu - ", entry_ptr->value + fileoffset_base); printred("start offset is incorrect!"); POPCOLOR(); if(!(PRINT_SECTION)) { chpr = newline(chpr); print_tag_address(VALUE_AT_OFFSET,entry_ptr->value + fileoffset_base, indent,"-"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fulldirname); chpr += printf("%-*.*s",MAKERTAGWIDTH,MAKERTAGWIDTH,nameoftag); } if((PRINT_VALUE)) chpr += printf(" = @%lu",entry_ptr->value + fileoffset_base); } } } break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Casio-specific tagnames for makernotes. */ /* The tagname routine is the first place in the code path which */ /* requires knowledge of the note version. If the version is not */ /* given in the model table (e.g. the model is unknown), then switch */ /* code in find_maker_scheme() should have set it. This routine */ /* repeats the check for non-zero noteversion and is prepared to set */ /* the noteversion first time through, but should never need to do */ /* so. Noteversion should always be non-zero; it should be set to -1 */ /* if generic processing is required. */ char * maker_casio_tagname(unsigned short tag,int model) { char *tagname = (char *)0; int noteversion = 0; if((noteversion = getnoteversion()) == 0) { noteversion = set_casio_noteversion(); setnoteversion(noteversion); } /* Check noteversions first */ switch(noteversion) { case 1: tagname = maker_casio1_tagname(tag,model); break; case 2: tagname = maker_casio2_tagname(tag,model); break; default: break; } /* If no version-specific tag is found, check "generic" tags */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } char * maker_casio1_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0001: tagname = "RecordingMode"; break; case 0x0002: tagname = "Quality"; break; case 0x0003: tagname = "FocusingMode"; break; case 0x0004: tagname = "FlashMode"; break; case 0x0005: tagname = "FlashIntensity"; break; case 0x0006: tagname = "ObjectDistance"; break; case 0x0007: tagname = "WhiteBalance"; break; case 0x000a: tagname = "DigitalZoom"; break; case 0x000b: tagname = "Sharpness"; break; case 0x000c: tagname = "Contrast"; break; case 0x000d: tagname = "Saturation"; break; case 0x0014: tagname = "CCDSensitivity"; break; default: break; } setnotetagset(1); return(tagname); } char * maker_casio2_tagname(unsigned short tag,int model) { char *tagname = CNULL; /* This is the same as Asahi/Pentax note version 2 */ switch(tag) { case 0x0002: tagname = "JpegThumbnailDimensions"; break; case 0x0003: tagname = "JpegThumbnailLength"; break; case 0x0004: tagname = "JpegThumbnailOffset"; break; case 0x0008: tagname = "QualityMode"; break; case 0x0009: tagname = "ImageSize"; break; case 0x000D: tagname = "FocusMode"; break; case 0x0014: tagname = "IsoSensitivity"; break; case 0x0019: tagname = "WhiteBalance"; break; case 0x001D: tagname = "FocalLength"; break; /* units .1mm */ case 0x001F: tagname = "Saturation"; break; case 0x0020: tagname = "Contrast"; break; case 0x0021: tagname = "Sharpness"; break; case 0x2000: tagname = "JpegThumbnail"; break; case 0x2011: tagname = "WhiteBalanceBias"; break; case 0x2012: tagname = "WhiteBalance"; break; case 0x2022: tagname = "ObjectDistance"; break; case 0x2034: tagname = "FlashDistance"; break; case 0x3000: tagname = "RecordMode"; break; case 0x3001: tagname = "SelfTimer?"; break; case 0x3002: tagname = "Quality"; break; case 0x3003: tagname = "FocusMode"; break; case 0x3006: tagname = "TimeZone"; break; case 0x3007: tagname = "BestshotMode"; break; case 0x3014: tagname = "CCDSensitivity"; break; case 0x3015: tagname = "ColorMode"; break; case 0x3016: tagname = "Enhancement"; break; case 0x3017: tagname = "Filter"; break; default: break; } setnotetagset(2); return(tagname); } /* Report the "meaning" of tag values found directly in a Casio */ /* MakerNote IFD entry (not at an offset). */ void casio1_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0001: /* RecordingMode */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Single Shutter"); break; case 2: chpr += printf("Panorama"); break; case 3: chpr += printf("Night Scene"); break; case 4: chpr += printf("Portrait"); break; case 5: chpr += printf("Landscape"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0002: /* Quality */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Economy"); break; case 2: chpr += printf("Normal"); break; case 3: chpr += printf("Fine"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0003: /* Focusing Mode */ print_startvalue(); switch(entry_ptr->value) { case 2: chpr += printf("Macro"); break; case 3: chpr += printf("Auto"); break; case 4: chpr += printf("Manual"); break; case 5: chpr += printf("Infinity"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0004: /* Flash Mode */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Auto"); break; case 2: chpr += printf("On"); break; case 3: chpr += printf("Off"); break; case 4: chpr += printf("Redeye"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0005: /* Flash Intensity */ print_startvalue(); switch(entry_ptr->value) { case 11: chpr += printf("Weak"); break; case 13: chpr += printf("Normal"); break; case 15: chpr += printf("Strong"); break; default: printred("undefined"); } break; case 0x0006: /* Object Distance */ PUSHCOLOR(UNCERTAIN_COLOR); chpr += printf(" mm"); POPCOLOR(); break; case 0x0007: /* White Balance */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Auto"); break; case 2: chpr += printf("Tungsten"); break; case 3: chpr += printf("Daylight"); break; case 4: chpr += printf("Fluorescent"); break; case 5: chpr += printf("Shade"); break; case 129: chpr += printf("Manual"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x000a: /* Digital Zoom */ print_startvalue(); switch(entry_ptr->value) { case 0x10000: chpr += printf("Off"); break; case 0x10001: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x000b: /* Sharpness */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Soft"); break; case 2: chpr += printf("Hard"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x000c: /* Contrast */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Low"); break; case 2: chpr += printf("High"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x000d: /* Saturation */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Low"); break; case 2: chpr += printf("High"); break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } void casio2_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0002: /* ThumbnailDimensions" */ chpr += printf(" pixels"); break; case 0x0008: /* QualityMode" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Fine"); break; case 2: chpr += printf("Super Fine"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0009: /* ImageSize" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("640x480"); break; case 4: chpr += printf("1600x1200"); break; case 5: chpr += printf("2048x1536"); break; case 20: chpr += printf("2288x1712"); break; case 21: chpr += printf("2592x1944"); break; case 22: chpr += printf("2304x1728"); break; case 36: chpr += printf("3008x2008"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x000D: /* FocusMode" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Normal"); break; case 2: chpr += printf("Macro"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0014: /* IsoSensitivity" */ print_startvalue(); switch(entry_ptr->value) { case 3: chpr += printf("50"); break; case 4: chpr += printf("64"); break; case 6: chpr += printf("100"); break; case 9: chpr += printf("200"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0019: /* WhiteBalance" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Fine"); break; case 2: chpr += printf("Shade"); break; case 3: chpr += printf("Tungsten"); break; case 4: chpr += printf("Fluorescent"); break; case 5: chpr += printf("Manual"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; /* rational? case 0x001D: tagname = "FocalLength"; break; units .1mm */ case 0x001F: /* Saturation" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("-1"); break; case 1: chpr += printf("Normal"); break; case 2: chpr += printf("+1"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0020: /* Contrast" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("-1"); break; case 1: chpr += printf("Normal"); break; case 2: chpr += printf("+1"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0021: /* Sharpness" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("-1"); break; case 1: chpr += printf("Normal"); break; case 2: chpr += printf("+1"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x2012: /* WhiteBalance" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Manual"); break; case 1: chpr += printf("Auto"); break; case 4: chpr += printf("Flash"); break; case 12: chpr += printf("Flash"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x2022: /* ObjectDistance" */ chpr += printf("mm"); break; case 0x2034: /* FlashDistance" */ #if 0 Off? if(entry_ptr->value == 0) { print_startvalue(); chpr += printf("Off"); print_endvalue(); } #endif break; case 0x3000: /* RecordMode" */ print_startvalue(); switch(entry_ptr->value) { case 2: chpr += printf("Normal"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3001: /* SelfTimer?" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Off"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3002: /* Quality" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Economy"); break; case 2: chpr += printf("Normal"); break; case 3: chpr += printf("Fine"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3003: /* FocusMode" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Fixed"); break; case 3: chpr += printf("Single-Area Auto"); break; case 6: chpr += printf("Multi-Area Auto"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3007: /* BestshotMode" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3015: /* ColorMode" */ #if 0 Off??? print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; default: chpr += printf("unknown"); break; } print_endvalue(); #endif break; case 0x3016: /* Enhancement" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3017: /* Filter" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } /* Some makernotes record offsets as LONG values rather than simply */ /* using UNDEFINED with a size; the same technique used for */ /* the ExifIFDPointer itself, or JpegInterchangeFormat, etc. */ /* This routine hardcodes such tags so that the print_makerentry() */ /* routine will present them as offsets. */ int maker_casio_value_is_offset(struct ifd_entry *entry_ptr,int model) { int is_offset = 0; int noteversion = 0; if(entry_ptr) { noteversion = getnoteversion(); switch(noteversion) { case 2: switch(entry_ptr->tag) { case 0x0004: is_offset = 1; break; default: break; } break; default: break; } } return(is_offset); } exifprobe-2.0.1+git20170416-3c2b76/olympus_datadefs.h0000644000000000000000000000260013074742216020223 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: olympus_datadefs.h,v 1.4 2005/07/08 15:02:00 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef OLYMPUS_DATADEFS_INCLUDED #define OLYMPUS_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id olympus_model_id[] = { { "C700UZ", 7, OLYMPUS_700UZ, 1, 1 }, { "C70Z,C7000Z",12, OLYMPUS_C70ZC7000Z, 1, 1 }, { "C960Z",5, OLYMPUS_960Z, 1, 1 }, { "C2040Z", 7, OLYMPUS_2040Z, 1, 1 }, { "C2500L ",7, OLYMPUS_C2500L, 1, 1 }, { "C3030Z", 7, OLYMPUS_3030Z, 1, 1 }, { "C3040Z", 7, OLYMPUS_3040Z, 1, 1 }, { "C8080WZ",8, OLYMPUS_C8080WZ, 1, 1 }, { "E-1 ",4, OLYMPUS_E_1, 1, 1 }, { "E-300",5, OLYMPUS_E_300, 1, 1 }, { "u40D,S500,uD500 ",4, OLYMPUS_u40D, 1, 1 }, { 0, 0, 0, 0, 0 } }; #endif /* OLYMPUS_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/maker_sanyo.c0000644000000000000000000006050113074742216017167 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_sanyo.c,v 1.23 2005/07/24 22:56:27 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* sanyo camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* The information coded here is largely due to John Hawkins as shown */ /* at: */ /* http://www.exif.org/makernotes/SanyoMakerNote.html */ /* (John even lists the JPEG thumbnail in TIFF makernotes and the */ /* Epson PrintIM tag!) */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id sanyo_model_id[]; /* Find the identifying number assigned to known Sanyo camera models. */ /* This number is used to dispatch print and interpret routines */ /* approopriate to the current image. */ int sanyo_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &sanyo_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine based upon model */ void print_sanyo_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 1: print_sanyo1_makervalue(entry_ptr,make,model,prefix); sanyo1_interpret_value(entry_ptr); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for sanyo cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_sanyo1_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for sanyo */ /* cameras. */ 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) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 1: sanyo1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); sanyo1_interpret_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in sanyo makernotes. One of these may be supplied for each model */ /* with unique UNDEFINED tags. */ 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) { unsigned long value_offset; unsigned long dumplength; unsigned long count; unsigned short marker; unsigned long max_offset = 0; char *nameoftag; char *fulldirname = NULL; int status = 0; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0100: /* Jpeg Thumbnail in TIFF MakerNote */ if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix); extraindent(4); chpr += printf("# Start of JPEG Thumbnail from MakerNote"); chpr += printf(" length %ld",count); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,entry_ptr->count); else chpr += printf(":%lu", entry_ptr->count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); max_offset = process_jpeg_segments(inptr,value_offset,marker, count,summary_entry,fulldirname, prefix,indent+(SUBINDENT * 2)); if(at_offset) { if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1, indent,"-"); extraindent(SUBINDENT); chpr += printf("# End of JPEG Thumbnail from MakerNote"); if((PRINT_ENTRY) && !(PRINT_VALUE)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_IFD; summary_entry->subfiletype = THUMBNAIL_TYPE; } } /* make certain we're at the end */ clearerr(inptr); fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0e00: /* PrintIM (Epson Print Image matching) */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) { chpr += printf("@%lu:%lu",value_offset,count); chpr = newline(chpr); } } process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent); break; case 0x0f00: /* Data */ if(at_offset && (PRINT_ENTRY)) { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,23," : ",make,model); chpr += printf("length %-9lu # UNDEFINED", count); if(Max_undefined == 0) { if(chpr) printred(" (not dumped, use -U)"); } else { if((Max_undefined == DUMPALL) || (Max_undefined > count)) dumplength = count; else dumplength = Max_undefined; chpr = newline(chpr); hexdump(inptr,value_offset,count,dumplength,12, indent,SUBINDENT); chpr = newline(1); } } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,entry_ptr->count); else chpr += printf(":%lu", entry_ptr->count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } /* make certain we're at the end */ fseek(inptr,value_offset + count,SEEK_SET); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* sanyo-specific tagnames for makernotes. */ /* The tagname routine is the first place in the code path which */ /* requires knowledge of the note version. If the version is not */ /* given in the model table (e.g. the model is unknown), then switch */ /* code in find_maker_scheme() should have set it. This routine */ /* repeats the check for non-zero noteversion and is prepared to set */ /* the noteversion first time through, but should never need to do */ /* so. Noteversion should always be non-zero; it should be set to -1 */ /* if generic processing is required. */ char * maker_sanyo_tagname(unsigned short tag,int model) { char *tagname = CNULL; int noteversion = 0; if(((noteversion = getnoteversion()) == 0)) { /* Need more model samples before it is safe to assume a */ /* default */ noteversion = 1; setnoteversion(1); } switch(noteversion) { case 1: tagname = maker_sanyo1_tagname(tag,model); break; default: break; } /* If no model-specific tag is found, check "generic" tags */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } char * maker_sanyo1_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0100: tagname = "JpegThumbnail"; break; case 0x0200: tagname = "SpecialMode"; break; case 0x0201: tagname = "Quality"; break; case 0x0202: tagname = "Macro"; break; case 0x0204: tagname = "DigiZoom"; break; case 0x0207: tagname = "SoftwareRelease"; break; case 0x0208: tagname = "PictureInfo"; break; case 0x0209: tagname = "CameraID"; break; case 0x020e: tagname = "SeqShotMethod"; break; case 0x020f: tagname = "WideRange"; break; case 0x0210: tagname = "ColorAdjMode"; break; case 0x0213: tagname = "QuickShot"; break; case 0x0214: tagname = "SelfTImer"; break; case 0x0216: tagname = "VoiceMemo"; break; case 0x0217: tagname = "RecordShutterRel"; break; case 0x0218: tagname = "FlickerReduce"; break; case 0x0219: tagname = "OpticalZoom"; break; case 0x021b: tagname = "DigitalZoom"; break; case 0x021d: tagname = "LightSourceSpecial"; break; case 0x021e: tagname = "Resaved"; break; case 0x021f: tagname = "SceneSelect"; break; case 0x0223: tagname = "ManualFocalDist"; break; case 0x0224: tagname = "SeqShotIntvl"; break; case 0x0225: tagname = "FlashMode"; break; case 0x0e00: tagname = "PrintIM"; break; case 0x0f00: tagname = "Data"; break; default: break; } setnotetagset(1); return(tagname); } void sanyo1_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0201: /* Quality */ print_startvalue(); /* ###%%% is this related to image size, e.g. 640x480? */ /* This tag is the same tag number as used by the */ /* Olympus, Epson, and Minolta F100, except that "super */ /* high" + "super fine" would give a (short) value of 34, */ /* which is the value used for uncompressed tiff in the */ /* Epson at 2048x1536. */ switch(entry_ptr->value & 0xff) { case 0: chpr += printf("very low res,"); break; case 1: chpr += printf("low res,"); break; case 2: chpr += printf("medium low res,"); /* 640 x 480 */ break; case 3: chpr += printf("medium res,"); break; case 4: chpr += printf("medium high res,"); break; case 5: chpr += printf("high res,"); break; case 6: chpr += printf("very high res,"); break; case 7: chpr += printf("super high"); break; default: printred("undefined"); break; } /* ###%%% is this related to compression, e.g TIFF vs */ /* JPEG ??? */ switch((entry_ptr->value >> 8) & 0xff) { case 0: chpr += printf(" normal"); break; case 1: chpr += printf(" fine"); break; case 2: chpr += printf(" super fine"); break; } print_endvalue(); break; case 0x0202: /* Macro */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Macro"); break; case 2: chpr += printf("View"); break; case 3: chpr += printf("Manual"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x020e: /* Sequential Shot Method */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("none"); break; case 1: chpr += printf("Standard"); break; case 2: chpr += printf("Best"); break; case 3: chpr += printf("Exposure Adjust"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x020f: /* Wide Range */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0210: /* Color Adjustment Mode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0213: /* Quick Shot */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0214: /* Self Timer */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0216: /* Voice Memo */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0217: /* Record Shutter Release */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Held"); break; case 1: chpr += printf("Start/Stop"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0218: /* Flicker Reduce */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0219: /* Optical Zoom */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Disabled"); break; case 1: chpr += printf("Enabled"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x021b: /* Digital Zoom */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Disabled"); break; case 1: chpr += printf("Enabled"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x021d: /* Light Source Special */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x021e: /* Resaved */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("No"); break; case 1: chpr += printf("Yes"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x021f: /* Scene Select */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("Sport"); break; case 2: chpr += printf("TV?"); break; case 3: chpr += printf("Night"); break; case 4: chpr += printf("User 1"); break; case 5: chpr += printf("User 2"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0224: /* Sequential Shot Interval */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("5 frames/sec"); break; case 1: chpr += printf("10 frames/sec"); break; case 2: chpr += printf("15 frames/sec?"); break; case 3: chpr += printf("20 frames/sec"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0225: /* Flash Mode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Force"); break; case 2: chpr += printf("Disabled"); break; case 3: chpr += printf("Redeye"); break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } void sanyo1_interpret_offset_makervalue(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base) { unsigned long offset,value; int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { offset = entry_ptr->value + fileoffset_base; switch(entry_ptr->tag) { case 0x0200: /* SpecialMode */ value = read_ulong(inptr,byteorder,offset); print_startvalue(); switch(value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Unkown"); break; case 2: chpr += printf("Fast"); break; case 3: chpr += printf("Panorama,"); value = read_ulong(inptr,byteorder,HERE); chpr += printf("#%lu,",value); value = read_ulong(inptr,byteorder,HERE); switch(value) { case 1: chpr += printf(" Left to Right"); break; case 2: chpr += printf(" Right to Left"); break; case 3: chpr += printf(" Bottom to Top"); break; case 4: chpr += printf(" Top to Bottom"); break; default: printred(" undefined"); break; } break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } exifprobe-2.0.1+git20170416-3c2b76/misc.c0000644000000000000000000014015413074742216015615 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: misc.c,v 1.22 2005/07/24 16:01:17 alex Exp $"; #endif #include #include #include #include #include "defs.h" #include "datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "ciff.h" /* Return the size in bytes of a TIFF type */ int value_type_size(unsigned short value_type) { int size = 0; switch(value_type) { case BYTE: case ASCII: case SBYTE: case UNDEFINED: size = 1; break; case SHORT: case SSHORT: size = 2; break; case LONG: case SLONG: case FLOAT: size = 4; break; case RATIONAL: case SRATIONAL: case DOUBLE: size = 8; break; default: break; } return(size); } /* Return a string naming the TIFF type of a TIFF entry */ char * value_type_name(unsigned short value_type) { char *name; switch(value_type) { case BYTE: name = "BYTE"; break; case ASCII: name = "ASCII"; break; case SBYTE: name = "SBYTE"; break; case UNDEFINED: name = "UNDEFINED"; break; case SHORT: name = "SHORT"; break; case SSHORT: name = "SSHORT"; break; case LONG: name = "LONG"; break; case SLONG: name = "SLONG"; break; case FLOAT: name = "FLOAT"; break; case RATIONAL: name = "RATIONAL"; break; case SRATIONAL: name = "SRATIONAL"; break; case DOUBLE: name = "DOUBLE"; break; default: name = "INVALID"; break; } return(name); } /* caller must call free() */ /* return NULL on error / buffer overflow */ char * strdup_value(struct ifd_entry *entry, FILE *inptr, unsigned long fileoffset_base) { char *val = NULL; if (is_offset(entry)) { char *buf = (char *)read_bytes(inptr, entry->count, fileoffset_base + entry->value); if (buf) { val = strndup(buf, entry->count); } return val; } else { char *buf = (char *)&(entry->value); val = (char*)calloc(entry->count + 1, sizeof(char)); for (int i = 0; i < entry->count; i++) { val[i] = buf[i]; } return val; } } /* Print a summary of all of the images found in the file. This will */ /* include thumbnail images stored by the unpleasant but ubiquitous */ /* JPEFThumbnailFormat method as well as images described by TIFF */ /* IFDs and SubIFDS, APP0 thumbnails, CIFF subimages, etc. */ /* Even formats such as MRW or JP2 which might be considered */ /* single-image formats can harbor TIFF IFDs (in a TTW block or uuid */ /* box) which can in turn describe thumbnails or reduced resolution */ /* images, so almost any image file can harbor this kind of overhead. */ /* The summary attempts to report the image format, location, size, */ /* and compression type of each block of image data found. For JPEG */ /* subimages claimed by the file, missing or corrupted data may be */ /* reported. */ /* A count of apparently legitimate images found is given at the end, */ /* as well as a count of missing images. */ void print_summary(struct image_summary *summary_entry) { int number_of_images = 0; int images_found = 0; int chpr = 0; char *plural; /* Pre-process the summary list; marks primary, reduced-res image */ /* types and attempts to avoid kruft from imcomplete summary */ /* entries. */ number_of_images = scan_summary(summary_entry); for( ; summary_entry; summary_entry = summary_entry->next_entry) { PUSHCOLOR(SUMMARY_COLOR); images_found += print_image_summary_entry(summary_entry,"@"); POPCOLOR(); } chpr = newline(chpr); plural = NULLSTRING; print_filename(); if(LIST_MODE) chpr += printf("NumberOfImages = %d",number_of_images); else chpr += printf("Number of images = %d",number_of_images); if(number_of_images - images_found) { chpr = newline(chpr); print_filename(); if(LIST_MODE) chpr += printf("ImagesNotFound = %d",number_of_images - images_found); else chpr += printf("Images not found = %d",number_of_images - images_found); } chpr = newline(chpr); } /* Print one entry of the image summary. */ int print_image_summary_entry(struct image_summary *entry,char *prefix) { int chpr = 0; int image_found = 0; if(entry && (entry->entry_lock > 0) && (entry->imageformat != IMGFMT_NOIMAGE)) { /* Make shell comments out of these if addresses are not */ /* printed */ if(!(PRINT_ADDRESS)) chpr += printf("# "); else print_tag_address(SECTION|ENTRY|SEGMENT,entry->offset,0,"@"); if(Debug & 0x4) chpr += printf("#%d: ",entry->entry_lock); chpr += printf("Start of"); print_imageformat(entry); if((entry->imagesubformat & ~IMGSUBFMT_ERRORMASK) != IMGSUBFMT_JPEGTABLES) { print_imagesubformat(entry); print_imagecompression(entry); print_imagesubtype(entry); print_imagesize(entry); print_location(entry); ++image_found; } else chpr += printf(" length %lu",entry->length); if(entry->imagesubformat & IMGSUBFMT_NO_JPEG) { printred(" (NO SOI)"); image_found = 0; } else if(entry->imagesubformat & IMGSUBFMT_JPEGFAILED) printred(" (CORRUPTED)"); else if(entry->imagesubformat & IMGSUBFMT_TRUNCATED) printred(" (TRUNCATED)"); if(entry->length > 0) { if((PRINT_ADDRESS) == 0) /* print_tag_address didn't do it */ chpr += printf(" at offset %#lx/%lu",entry->offset,entry->offset); chpr = newline(chpr); if((PRINT_ADDRESS) == 0) chpr += printf("# "); else print_tag_address(SECTION|ENTRY|SEGMENT, entry->offset + entry->length - 1, 0,"-"); chpr += printf(" End of"); print_imageformat(entry); if(entry->imagesubformat != IMGSUBFMT_JPEGTABLES) { print_imagesubtype(entry); if((PRINT_ADDRESS) == 0) /* print_tag_address didn't do it */ chpr += printf(" image data at offset %#lx/%lu", entry->offset + entry->length - 1, entry->offset + entry->length - 1); else chpr += printf(" image data"); } if(entry->imageformat & IMGFMT_MISMARKED) { PUSHCOLOR(RED); chpr += printf(" *uncompressed data marked as JPEG"); POPCOLOR(); } chpr = newline(chpr); } else { printred(" (no image)"); image_found = 0; } } chpr = newline(chpr); return(image_found); } /* Scan the summary entry chain in an attempt to identify primary and */ /* reduced-resolution images. TIFF/EP marks types in NewSubfileType, */ /* but bare TIFF does not. Exif sometimes writes the primary image */ /* size (which is recorded in the summary entry passed to it), but */ /* many cameras write abbreviated Exif sections. */ /* This routine scans the image summary chain forward and back again, */ /* attempting to write any found primary image size to all entries */ /* and/or deduce which entry represents the primary image if none */ /* have been marked by TIFF/EP. This is easy when there are only one */ /* or two images, but a bit more trouble when there are 4 or 5. */ /* During the scan, the maximum image size encountered is recorded, */ /* and may be used to deduce the primary. It is assumed that the */ /* primary will be maximum size (in pixels); when there are ties, the */ /* image type and/or compression may be checked. Uncompressed, "raw" */ /* or "lossless" compression at maximum image size is likely the */ /* primary. */ /* ###%%% This routine is a work in progress; it will likely change */ /* and improve as more is learned about the ways in which */ /* manufacturers are mangling the specifications. The routine */ /* currently performs a useful and necessary task, and some largely */ /* useless work. It is heavily dependent upon the code 'out there' */ /* gathering and recording the proper information. */ /* This is called by the print_summary() routine just before printing */ /* the summary. It returns the number of images which are represented */ /* by summary entries. */ int scan_summary(struct image_summary *summary_entry) { struct image_summary *next_entry = NULL; struct image_summary *prev_entry = NULL; unsigned long long image_size = 0ULL; unsigned long long max_image_size = 0ULL; unsigned long marked_primary_image_length = 0ULL; unsigned long long marked_primary_image_size = 0ULL; unsigned long long primary_image_size = 0ULL; unsigned long long next_primary_size = 0ULL; unsigned long max_image_width = 0UL; unsigned long max_image_height = 0UL; unsigned long max_image_length = 0UL; unsigned long image_length = 0UL; int primary_found = 0; int number_of_images = 0; if(Debug & 0x4) (void)newline(1); /* The passed entry should be the head; scan forward merging data */ while(summary_entry/* && next_entry */) { if(summary_entry->entry_lock <= 0) { summary_entry = summary_entry->next_entry; continue; } if(summary_entry) next_entry = summary_entry->next_entry; if(Debug & 0x4) { printred("DEBUG:"); printf(" %d: ffm=%#x, fsf=%#x",summary_entry->entry_lock, summary_entry->fileformat,summary_entry->filesubformat); printf(", spp=%d, bps[0]=%d",summary_entry->spp,summary_entry->bps[0]); } /* 'image_size' in pixels */ image_size = summary_entry->pixel_width * summary_entry->pixel_height; /* image_length vs summary length: compressed? how much? */ /* ###%%% this is "experimental" and shows up only in Debug */ if(summary_entry->bps[0] && summary_entry->spp) { int i; int spp = summary_entry->spp; float total_bits,bytes_per_pixel; total_bits = 0; if (spp > MAXSAMPLE) { spp = MAXSAMPLE; if(Debug & 0x4) { printf("CLAMPING spp\n"); } } for(i = 0; i < spp; ++i) total_bits += summary_entry->bps[i]; bytes_per_pixel = total_bits / 8.0; if(Debug & 0x4) printf(", bytesperpixel=%.1f",bytes_per_pixel); image_length = image_size * bytes_per_pixel; summary_entry->compress_percent = (float)summary_entry->length / (float)image_length; summary_entry->compress_percent *= 100.0; } if(Debug & 0x4) printf(" c=%lu/%lu=%.0f%%\n",summary_entry->length,image_length, summary_entry->compress_percent); if(summary_entry->subfiletype == PRIMARY_TYPE) { ++primary_found; /* marked in a TIFF/EP IFD */ marked_primary_image_size = image_size; marked_primary_image_length = summary_entry->length; if(summary_entry->primary_height == 0UL) summary_entry->primary_height = summary_entry->pixel_height; if(summary_entry->primary_width == 0UL) summary_entry->primary_width = summary_entry->pixel_width; } /* maintain max values independently of primary */ if(image_size > max_image_size) { max_image_height = summary_entry->pixel_height; max_image_width = summary_entry->pixel_width; max_image_size = image_size; } /* The largest chunk of image data; could be very important */ if(summary_entry->length > max_image_length) max_image_length = summary_entry->length; /* If a primary size was found, e.g. in an exif ifd, carry */ /* it forward. If more than one was found, keep the largest. */ /* Then carry it back down to the head in the backward loop. */ /* Should wind up with all entries the same (and possibly */ /* zero). */ if(summary_entry->primary_height || summary_entry->primary_width) { primary_image_size = summary_entry->primary_width * summary_entry->primary_height; if(next_entry && (next_entry->primary_height || next_entry->primary_width)) { next_primary_size = next_entry->primary_width * next_entry->primary_height; if(next_primary_size > primary_image_size) { summary_entry->primary_width = next_entry->primary_width; summary_entry->primary_height = next_entry->primary_height; primary_image_size = next_primary_size; } else { next_entry->primary_width = summary_entry->primary_width; next_entry->primary_height = summary_entry->primary_height; } } else if(next_entry) { next_entry->primary_width = summary_entry->primary_width; next_entry->primary_height = summary_entry->primary_height; } } /* In JPEG format files, it's almost certain that the primary */ /* begins at the beginning of the file; "almost" only because */ /* I've seen some strange things... */ if((summary_entry->fileformat == FILEFMT_JPEG) && (summary_entry->subfiletype == UNKNOWN_TYPE)) { if(summary_entry->offset == 0) summary_entry->subfiletype = POSSIBLE_PRIMARY_TYPE; } prev_entry = summary_entry; summary_entry = next_entry; } summary_entry = prev_entry; if((Debug & 0x4) && summary_entry) { printred("DEBUG:"); printf(" Exif Primary=%lux%lu = %llu\n",summary_entry->primary_width,summary_entry->primary_height,primary_image_size); printred("DEBUG:"); printf(" Maxsize=%lux%lu = %llu\n",max_image_width,max_image_height,max_image_size); printred("DEBUG:"); printf(" Marked Primary size = %llu",marked_primary_image_size); printf(" Marked Primary length=%lu, max length = %lu\n",marked_primary_image_length,max_image_length); } /* now walk back to the head */ /* If a marked primary has been found, the primary job is to mark */ /* reduced resolution images which haven't been defined as */ /* thumbnails in the main code. If no marked primary, it is also */ /* necessary to deduce the identity of the primary image, using */ /* size, length and/or image and compression type. */ /* ###%%% at this point, after all the futzing around with */ /* primary_width, etc., it never gets used. max_* are used */ /* (and primary_image_size may not have been set if the last */ /* entry contained the values) */ if(summary_entry) prev_entry = summary_entry->prev_entry; while(summary_entry) { if(Debug & 0x4) { printred("DEBUG:"); printf(" #%d se=%#-9x, pe=%#-9x",summary_entry->entry_lock, (unsigned int)summary_entry,(unsigned int)prev_entry); } image_size = summary_entry->pixel_width * summary_entry->pixel_height; image_length = summary_entry->length; if(summary_entry->entry_lock <= 0) { summary_entry = prev_entry; if(summary_entry) prev_entry = summary_entry->prev_entry; continue; } if(Debug & 0x4) { printf(" ffm=%#x, fsf=%#-3x",summary_entry->fileformat,summary_entry->filesubformat); printf(", ifm=%#lx, isf=%#lx",summary_entry->imageformat,summary_entry->imagesubformat); printf(", offs=%lu, len=%lu",summary_entry->offset,summary_entry->length); printf(", pw=%lu, ph=%lu",summary_entry->pixel_width,summary_entry->pixel_height); } if(prev_entry && (prev_entry->subfiletype != PRIMARY_TYPE)) { /* The primary size was carried up to the last entry in */ /* the forward scan; now copy it back down. */ /* ###%%% is this used? ...no, never */ prev_entry->primary_width = summary_entry->primary_width; prev_entry->primary_height = summary_entry->primary_height; } if(Debug & 0x4) printf(" sft=%d\n",summary_entry->subfiletype); if(primary_found >= 1) /* should never be greater than 1 */ { if(summary_entry->subfiletype == POSSIBLE_PRIMARY_TYPE) summary_entry->subfiletype = REDUCED_RES_TYPE; } else if(primary_found == 0) { if(summary_entry->subfiletype == POSSIBLE_PRIMARY_TYPE) { if((summary_entry->fileformat == FILEFMT_TIFF) || (summary_entry->fileformat == FILEFMT_ORF1) || (summary_entry->fileformat == FILEFMT_ORF2)) { switch(summary_entry->compression) { case 1: case 34712: /* JPEG 2000 */ case 34713: /* NEF compressed */ case JPEG_SOF_3: case JPEG_SOF_7: case JPEG_SOF_11: case JPEG_SOF_15: if(image_size >= max_image_size) { summary_entry->subfiletype = PRIMARY_TYPE; ++primary_found; } break; default: if((image_size < max_image_size) || (image_length < max_image_length)) summary_entry->subfiletype = REDUCED_RES_TYPE; break; } } else if(summary_entry->fileformat == FILEFMT_JP2) { summary_entry->subfiletype = PRIMARY_TYPE; ++primary_found; } else if(summary_entry->fileformat == FILEFMT_JPEG) { if(summary_entry->offset == 0) { summary_entry->subfiletype = PRIMARY_TYPE; ++primary_found; } else if(summary_entry->filesubformat & (FILESUBFMT_TIFF|FILESUBFMT_TIFFEP)) { switch(summary_entry->compression) { case JPEG_SOF_3: case JPEG_SOF_7: case JPEG_SOF_11: case JPEG_SOF_15: /* lossless compression */ if(image_size >= max_image_size) { summary_entry->subfiletype = PRIMARY_TYPE; ++primary_found; } break; default: if((image_size < max_image_size) || (image_length < max_image_length)) summary_entry->subfiletype = REDUCED_RES_TYPE; break; } } } else if(summary_entry->imagesubformat == IMGSUBFMT_CFA) { /* fileformat may be MRW; other fileformats? */ if(image_size >= max_image_size) { summary_entry->subfiletype = PRIMARY_TYPE; ++primary_found; } else summary_entry->subfiletype = REDUCED_RES_TYPE; } else summary_entry->subfiletype = REDUCED_RES_TYPE; } } if(primary_found) { if(summary_entry->subfiletype <= POSSIBLE_PRIMARY_TYPE) summary_entry->subfiletype = REDUCED_RES_TYPE; } else if(image_size >= max_image_size) { if(summary_entry->subfiletype == POSSIBLE_PRIMARY_TYPE) { summary_entry->subfiletype = PRIMARY_TYPE; ++primary_found; } } else if(summary_entry->subfiletype <= POSSIBLE_PRIMARY_TYPE) summary_entry->subfiletype = REDUCED_RES_TYPE; if(((summary_entry->imageformat) != IMGFMT_NOIMAGE) && ((summary_entry->imagesubformat & ~IMGSUBFMT_ERRORMASK) != IMGSUBFMT_JPEGTABLES)) ++number_of_images; if(Debug & 0x4) { printred("DEBUG:"); printf(" #%d se=%#-9x, pe=%#-9x",summary_entry->entry_lock, (unsigned int)summary_entry,(unsigned int)prev_entry); printf(" ffm=%#x, fsf=%#-3x",summary_entry->fileformat,summary_entry->filesubformat); printf(", ifm=%#lx, isf=%#lx",summary_entry->imageformat,summary_entry->imagesubformat); printf(", offs=%lu, len=%lu",summary_entry->offset,summary_entry->length); printf(", pw=%lu, ph=%lu",summary_entry->pixel_width,summary_entry->pixel_height); printf(" sft=%d\n",summary_entry->subfiletype); } summary_entry = prev_entry; if(summary_entry) prev_entry = summary_entry->prev_entry; else prev_entry = NULL; } if(Debug & 0x4) (void)newline(1); return(number_of_images); } #include "maker_datadefs.h" extern struct maker_scheme *retrieve_makerscheme(); /* Print a "file format" as a listing of major sections used in the */ /* file. It would be nice (perhaps) to print a single file format for */ /* TIFF-derived formats such as CR2, NEF, K25, DNG, etc. but it is */ /* difficult to say, in the absence of specifications, what makes */ /* e.g. a CR2 file a CR2 file. */ /* Filename extensions and vendor names do not characterize the */ /* internal format of the file, and may be applied (erroneously) to */ /* any file. */ /* At present, the program keeps watch for certain tag numbers in */ /* TIFF Ifds which seem to be unique to a particular format, and */ /* writes a qualifier (e.g. [NEF]) for TIFF-derived types. */ /* ORF files can be marked reliably because Olympus was clever enough */ /* to change the magic number in the header, a trivial but important */ /* change which probably should have been done for DNG (and CR and */ /* NEF). There are even separate magic numbers for the two variants */ /* of ORF. */ /* File formats with specific magic numbers in the file header, such */ /* as MRW, CIFF, and ORF (and TIFF) will show up at the beginning of */ /* output as that file 'type'. This routine will characterize the */ /* "file format" by the major sections found in the summary entries. */ /* Identifiable derived formats (e.g. a NEF compression tag) will be */ /* indicated. The presence of MakerNotes and subifds in MakerNotes */ /* will be shown. */ void print_fileformat(struct image_summary *entry) { struct maker_scheme *scheme; char *sep,*camera_name; int chpr = 0; int filesubformat_shown = 0; int with_filesubformat = 0; int vendor_filesubformat = 0; int has_appn[16]; int i; print_filename(); if((PRINT_LONGNAMES)) chpr += printf("FileFormat = "); else chpr += printf("File Format = "); if(entry) { memset(has_appn,0,sizeof(has_appn)); print_filetype(entry->fileformat,0); if(entry->filesubformat & FILESUBFMT_TIFFEP) chpr += printf("EP"); if(entry->fileformat == FILEFMT_TIFF) filesubformat_shown |= FILESUBFMT_TIFF; if(entry->filesubformat & FILESUBFMT_TIFFEP) filesubformat_shown |= FILESUBFMT_TIFFEP; sep = "/"; for( ; entry; entry = entry->next_entry) { if((entry->filesubformat & (FILESUBFMT_TIFF|FILESUBFMT_TIFFOLD)) && !(filesubformat_shown & (FILESUBFMT_TIFF|FILESUBFMT_TIFFOLD))) chpr += printf("%sTIFF",sep); if((entry->filesubformat & FILESUBFMT_JPEG) && !(filesubformat_shown & FILESUBFMT_JPEG)) chpr += printf("%sJPEG",sep); if((entry->filesubformat & FILESUBFMT_GEOTIFF) && !(filesubformat_shown & FILESUBFMT_GEOTIFF)) chpr += printf("%sGEOTIFF",sep); if((entry->filesubformat & FILESUBFMT_TIFFEP) && !(filesubformat_shown & FILESUBFMT_TIFFEP)) chpr += printf("%sEP",sep); if((entry->filesubformat & FILESUBFMT_APPN) && !(filesubformat_shown & FILESUBFMT_APPN)) { if(entry->filesubformatAPPN[0]) { chpr += printf("%sAPP0",sep); if(entry->filesubformat & FILESUBFMT_JFIF) chpr += printf("%sJFIF",sep); if(entry->filesubformat & FILESUBFMT_JFXX) chpr += printf("%sJFXX",sep); } if(entry->filesubformatAPPN[1]) { chpr += printf("%sAPP1",sep); if(entry->filesubformat & (FILESUBFMT_TIFF|FILESUBFMT_TIFFOLD)) { entry->filesubformat &= ~(FILESUBFMT_TIFF|FILESUBFMT_TIFFOLD); chpr += printf("%sTIFF",sep); } if(entry->filesubformat & FILESUBFMT_EXIF) { entry->filesubformat &= ~FILESUBFMT_EXIF; chpr += printf("%sEXIF",sep); } } if(entry->filesubformatAPPN[2]) { chpr += printf("%sAPP2",sep); if(entry->filesubformat & FILESUBFMT_FPIX) { entry->filesubformat &= ~FILESUBFMT_FPIX; chpr += printf("%sFPIX",sep); } } for(i = 3; i < 16; ++i) { if(entry->filesubformatAPPN[i]) has_appn[i] = entry->filesubformatAPPN[i]; } } if((entry->filesubformat & FILESUBFMT_CIFF) && !(filesubformat_shown & FILESUBFMT_CIFF)) chpr += printf("%sCIFF",sep); if((entry->filesubformat & FILESUBFMT_EXIF) && !(filesubformat_shown & FILESUBFMT_EXIF)) chpr += printf("%sEXIF",sep); if((entry->filesubformat & FILESUBFMT_FPIX) && !(filesubformat_shown & FILESUBFMT_FPIX)) chpr += printf("%sFPIX",sep); filesubformat_shown |= entry->filesubformat; if(entry->filesubformat & FILESUBFMT_NEF) vendor_filesubformat |= FILESUBFMT_NEF; if(entry->filesubformat & FILESUBFMT_CR2) vendor_filesubformat |= FILESUBFMT_CR2; if(entry->filesubformat & FILESUBFMT_DNG) vendor_filesubformat |= FILESUBFMT_DNG; if(entry->filesubformat & FILESUBFMT_MNOTE) with_filesubformat |= FILESUBFMT_MNOTE; if(entry->filesubformat & FILESUBFMT_MNSUBIFD) with_filesubformat |= FILESUBFMT_MNSUBIFD; } for(i = 3; i < 16; ++i) { if(has_appn[i]) chpr += printf("%sAPP%d",sep,i); } if(vendor_filesubformat & FILESUBFMT_NEF) chpr += printf(" [NEF]"); if(vendor_filesubformat & FILESUBFMT_CR2) chpr += printf(" [CR2]"); if(vendor_filesubformat & FILESUBFMT_DNG) chpr += printf(" [DNG]"); if(with_filesubformat) chpr += printf(" #"); if(with_filesubformat & FILESUBFMT_MNOTE) { chpr += printf(" with MakerNote"); scheme = retrieve_makerscheme(); if(scheme->make) { camera_name = find_camera_name(scheme->make); if(scheme->scheme_type != UNKNOWN_SCHEME) printf(" (%s [%d])",camera_name,scheme->note_version); else printf(" (%s - unknown makernote format)",camera_name); } if(with_filesubformat & FILESUBFMT_MNSUBIFD) chpr += printf(" and MakerNote-SubIFD"); } } else chpr += printf("unknown"); chpr = newline(chpr); } /* Find the name of a device (usually a camera) identified by the */ /* internal id number 'make'. */ extern struct camera_name Camera_make[]; char * find_camera_name(int make) { struct camera_name *maker_id; char *camera_name = UNKNOWN_CAMERA_STRING; /* 'Camera_make' is a global parameter */ for(maker_id = Camera_make; maker_id && maker_id->name; ++maker_id) { if(make == maker_id->id) { camera_name = maker_id->name; break; } } return(camera_name); } void print_imageformat(struct image_summary *entry) { int chpr = 0; if(entry) { switch(entry->imageformat & ~IMGFMT_MISMARKED) { case IMGFMT_TIFF: if(entry->fileformat == FILEFMT_ORF1) { chpr += printf(" ORF1 16bps"); /* ###%%% this is the wrong place to do this */ entry->imagesubformat = IMGSUBFMT_CFA; } else if(entry->fileformat == FILEFMT_ORF2) { chpr += printf(" ORF2 12bps"); entry->imagesubformat = IMGSUBFMT_CFA; } else if(entry->fileformat == FILEFMT_RW2) { chpr += printf(" RW2"); entry->imagesubformat = IMGSUBFMT_CFA; } else chpr += printf(" TIFF"); break; case IMGFMT_JPEG: if(entry->imagesubformat == IMGSUBFMT_JPEGTABLES) chpr += printf("JPEGTables"); else chpr += printf(" JPEG"); if(entry->imageformat & IMGFMT_MISMARKED) chpr += printf("*"); break; case IMGFMT_JPEG2000: chpr += printf(" JPEG2000"); break; case IMGFMT_CRW: chpr += printf(" CRW"); break; case IMGFMT_MRW: chpr += printf(" MRW"); chpr += printf(" %d/%d",entry->bps[0],entry->sample_size); break; case IMGFMT_RAF: chpr += printf(" RAF"); break; case IMGFMT_X3F: chpr += printf(" X3F"); break; default: chpr += printf(" UNKNOWN format"); break; } } setcharsprinted(chpr); } void print_tiff_compression(struct image_summary *entry) { char *compression; int chpr = 0; compression = tiff_compression_string(entry->compression); chpr += printf(" %s",compression); setcharsprinted(chpr); } char * tiff_compression_string(unsigned long compvalue) { char *compression; compression = NULLSTRING; switch(compvalue) { /* will be 0 only if compression tag does not appear */ case 0: compression = "unknown format"; break; case 1: compression = "uncompressed"; break; /* TIFF6/TIFF_EP */ case 2: compression = "Modifed Huffman RLE compressed"; break; /* TIFF6 */ case 3: compression = "T4 fax encoded"; break; /* TIFF6 */ case 4: compression = "T6 fax encoded"; break; /* TIFF6 */ case 5: compression = "LZW compressed"; break; /* TIFF6 */ case 6: compression = "Exif/old JPEG"; break; /* TIFF6 pre TechNote 2 */ /* required by Exif! */ case 7: compression = "JPEG"; break; /* TIFF6 current/TIFF_EP/DNG */ case 32773: compression = "Packbits RLE compressed"; break; /* TIFF6 */ /* These are all from "libtiff -- tiff.h" */ case 8: compression="Adobe Deflate compressed"; break; case 32771: compression="NeXT 2-bit RLE compressed"; break; case 32809: compression="ThunderScan RLE compressed"; break; case 32895: compression="IT8 CT compressed with padding"; break; case 32896: compression="IT8 Linework compressed"; break; case 32897: compression="IT8 Monochromecompressed"; break; case 32898: compression="IT8 Binary line art compressed"; break; case 32908: compression="Pixar companded 10bit LZW compressed"; break; case 32909: compression="Pixar companded 11bit ZIP compressed"; break; case 32946: compression="Deflate compressed"; break; case 32947: compression="Kodak DCS encoded"; break; case 34661: compression="ISO JBIG compressed"; break; case 34676: compression="SGI Log Luminance RLE compressed"; break; case 34677: compression="SGI Log 24-bit compressed"; break; /* Noted in images */ case 32867: compression="Kodak KDC compressed"; break; case 34712: compression="Jpeg2000 compressed"; break; case 34713: compression="NEF compressed"; break; case 65000: compression="Kodak DCR compressed"; break; default: compression = "(UNKNOWN TIFF compression)"; break; } return(compression); } void print_jpeg_compression(struct image_summary *entry) { char *compression; int chpr = 0; compression = NULLSTRING; if(entry) { switch(entry->compression) { case JPEG_SOF_0: compression="baseline DCT compressed"; break; case JPEG_SOF_1: compression="extended seq DCT Huffman"; break; case JPEG_SOF_2: compression="progressive DCT Huffman"; break; case JPEG_SOF_3: compression="lossless seq Huffman"; break; case JPEG_SOF_5: compression="differential seq DCT Huffman"; break; case JPEG_SOF_6: compression="differential progressive DCT Huffman"; break; case JPEG_SOF_7: compression="differential lossless Huffman"; break; case JPEG_SOF_9: compression="extended seq DCT arithmetic"; break; case JPEG_SOF_10: compression="progressive seq arithmetic"; break; case JPEG_SOF_11: compression="lossless seq arithmetic"; break; case JPEG_SOF_13: compression="differential seq DCT arithmetic"; break; case JPEG_SOF_14: compression="differential progressive DCT arithmetic"; break; case JPEG_SOF_15: compression="differential lossless arithmetic"; break; default: compression = "(UNKNOWN JPEG compression)"; break; } } chpr += printf(" %s",compression); setcharsprinted(chpr); } void print_jp2c_compression(struct image_summary *entry) { char *transform; char *quantization; int chpr = 0; transform = quantization = NULLSTRING; if(entry) { if((entry->compression & 0xff) == 1) transform = "5/3 reversible"; else transform = "9/7 irreversible"; switch((entry->compression & 0xff00) >> 8) { case 0: quantization = "no quantization"; break; case 1: quantization = "implicit quantization"; break; case 2: quantization = "explicit quantization"; break; default: quantization = "unknown quantization"; break; } } chpr += printf(" (%s compression with %s)",transform,quantization); setcharsprinted(chpr); } void print_crw_compression(struct image_summary *entry) { char *compression; int chpr = 0; compression = NULLSTRING; if(entry) { switch(entry->compression) { case 0: compression = "uncompressed"; break; case 1: compression = "compressed"; break; default: break; } } chpr += printf(" %s",compression); setcharsprinted(chpr); } void print_raf_compression(struct image_summary *entry) { char *compression; int chpr = 0; compression = NULLSTRING; if(entry) { switch(entry->compression) { case 0: compression = "uncompressed"; break; case 1: compression = "uncompressed (with secondary)"; break; default: break; } } chpr += printf(" %s",compression); setcharsprinted(chpr); } void print_x3f_compression(struct image_summary *entry) { char *compression; int chpr = 0; compression = NULLSTRING; if(entry) { switch(entry->imagesubformat) { case IMGSUBFMT_HUFF_COMPRESSED_RGB: compression = "Huffman compressed"; break; case IMGSUBFMT_JPEG_COMPRESSED_RGB: compression = "Jpeg compressed"; break; case IMGSUBFMT_X3F_COMPRESSED: compression = "compressed"; break; case IMGSUBFMT_RGB: compression = "uncompressed"; break; default: break; } } chpr += printf(" %s",compression); setcharsprinted(chpr); } void print_imagecompression(struct image_summary *entry) { if(entry) { switch(entry->imageformat) { case IMGFMT_MRW: /* gets it from a TIFF IFD */ case IMGFMT_TIFF: print_tiff_compression(entry); break; case IMGFMT_JPEG: print_jpeg_compression(entry); break; case IMGFMT_JPEG2000: print_jp2c_compression(entry); break; case IMGFMT_CRW: print_crw_compression(entry); break; case IMGFMT_RAF: print_raf_compression(entry); break; case IMGFMT_X3F: print_x3f_compression(entry); break; default: break; } } } void print_imagesubformat(struct image_summary *entry) { char *subformat; unsigned long imagesubformat = 0; int chpr = 0; subformat = NULLSTRING; if(entry) { imagesubformat = entry->imagesubformat & ~IMGSUBFMT_ERRORMASK; switch(imagesubformat) { case IMGSUBFMT_CFA: subformat = "CFA"; break; case IMGSUBFMT_RGB: subformat = "RGB"; break; case IMGSUBFMT_YCBCR: subformat = "YCBCR"; break; case IMGSUBFMT_PALETTE: subformat = "PALETTE"; break; case IMGSUBFMT_LINEARRAW: subformat = "LinearRaw"; break; case IMGSUBFMT_JPEGTABLES: subformat = "JPEGTables"; break; case IMGSUBFMT_HUFF_COMPRESSED_RGB: subformat = "RGB"; break; case IMGSUBFMT_JPEG_COMPRESSED_RGB: subformat = "RGB"; break; case IMGSUBFMT_X3F_COMPRESSED: subformat = "RAW"; break; case IMGSUBFMT_X3F_UNSPECIFIED: subformat = "Unspecified"; break; default: break; } } if(*subformat) chpr += printf(" %s",subformat); setcharsprinted(chpr); } void print_imagesubtype(struct image_summary *entry) { char *type_of_image = UNKNOWN_STRING; int chpr = 0; switch(entry->subfiletype) { case THUMBNAIL_TYPE: type_of_image = THUMBNAIL_STRING; break; case PRIMARY_TYPE: type_of_image = PRIMARY_STRING; break; case PAGE_TYPE: type_of_image = PAGE_STRING; break; case MASK_TYPE: type_of_image = MASK_STRING; break; case REDUCED_RES_TYPE: type_of_image = REDUCED_RES_STRING; /* if not marked THUMBNAIL */ break; default: type_of_image = UNSPECIFIED_STRING; break; } if(*type_of_image) chpr += printf(" %s",type_of_image); setcharsprinted(chpr); } void print_imagesize(struct image_summary *entry) { int chpr = 0; char *maybeshort = NULLSTRING; if(entry) { if(entry->imagesubformat & IMGSUBFMT_JPEG_EARLY_EOI) maybeshort = "<= "; chpr += printf(" image [%ldx%ld",entry->pixel_width,entry->pixel_height); if(entry->subfiletype == PRIMARY_TYPE) { if((entry->primary_width > entry->pixel_width) || (entry->primary_height > entry->pixel_height)) { chpr += printf("<=%ldx%ld",entry->primary_width,entry->primary_height); } } chpr += printf("] length %s%lu",maybeshort,entry->length); } setcharsprinted(chpr); } /* Indicate where the image was found; the information is contained */ /* in the filesubformat bits and/or datatype recorded for this */ /* particular entry. */ void print_location(struct image_summary *entry) { char *space = NULL; int chpr = 0; if(entry) { space = " ("; if((entry->fileformat == FILEFMT_TIFF) || entry->filesubformat & FILESUBFMT_TIFFUSED || entry->filesubformatAPPN[1]) { if(entry->ifdnum >= 0) chpr += printf("%sIFD %d",space,entry->ifdnum),space = " "; if(entry->subifdnum >= 0) chpr += printf("%sSubIFD %d",space,entry->subifdnum),space = " "; /* could use filesubformat here? */ if(entry->datatype == MAKER_IFD) chpr += printf("%sMakerNote",space),space = " "; if(entry->datatype == MAKER_SUBIFD) chpr += printf("%sMakerNote SubIFD",space),space = " "; } else if(entry->fileformat == FILEFMT_JPEG) { if(entry->filesubformatAPPN[0]) { chpr += printf("%sAPP0",space),space = " "; if(entry->filesubformat & FILESUBFMT_JFXX) chpr += printf("%sJFXX",space),space = " "; } } if(chpr) chpr += printf(")"); } } /* Sum the strip or type bytecounts from a TIFF header to yield the */ /* size of the image data. The bytecounts may be short or long, so */ /* the value_type must be checked. */ unsigned long sum_strip_bytecounts(FILE *inptr,unsigned short byteorder,unsigned long offset, unsigned long count,unsigned short value_type) { int i; unsigned long sum = 0L; if(count) { /* Some use SHORT, some use LONG. If anyone uses some other */ /* type, just ignore 'em. */ if(value_type == SHORT) { sum = read_ushort(inptr,byteorder,offset); for(i = 1; i < count; ++i) sum += read_ushort(inptr,byteorder,HERE); } else if(value_type == LONG) { sum = read_ulong(inptr,byteorder,offset); for(i = 1; i < count; ++i) sum += read_ulong(inptr,byteorder,HERE); } } return(sum); } void why(FILE *outptr) { fprintf(outptr,"\t because: %s\n",strerror(errno)); errno = 0; } unsigned long toggle(unsigned long options,unsigned long bits) { if(options & bits) options &= ~bits; else options |= bits; return(options); } /* Clean up memory used to save Make_name, etc. */ void clear_memory() { if(Make_name) free(Make_name); if(Model_name) free(Model_name); if(Software_name) free(Software_name); Make_name = Model_name = Software_name = (char *)0; } /* splice two strings together with a separator between. The result */ /* is placed in dynamic memory. Free it when done with it. */ char * splice(char *string1,char *sep,char *string2) { char splicebuf[1024]; char *result = NULL; if(string1 == NULL) sep = string1 = NULLSTRING; if(string2 == NULL) string2 = NULLSTRING; snprintf(splicebuf,1024,"%s%s%s",string1,sep,string2); result = strdup(splicebuf); return(result); } /* The following routines attempt to keep track of unterminated */ /* output lines and see that newlines are output as necessary, and */ /* never more than necessary. */ /* This requires keeping track of the count of characters printed and */ /* calling either setcharsprinted(xxx) to register them, or */ /* newline(xxx) to force a newline. "newline(0)" will print a newline */ /* only if Charsprinted is non-zero. */ /* This will work properly only if all functions which produce output */ /* cooperate. */ static int Charsprinted = 0; int newline(int charsprinted) { if((charsprinted != 0) || (Charsprinted != 0)) putchar('\n'); Charsprinted = 0; return(Charsprinted); } void setcharsprinted(int charsprinted) { Charsprinted += charsprinted; } int charsprinted() { return(Charsprinted); } /* Record the filename and optionally prepend the filename to each */ /* output line. Useful e.g. when multiple files are being LISTed and */ /* grepped (exifgrep). */ static char *Current_filename = CNULL; void setfilename(char *filename) { Current_filename = filename; } void print_filename() { int chpr = 0; if(((PRINT_FILENAMES)) && (Current_filename)) { PUSHCOLOR(BLACK); chpr = printf("%s: ",Current_filename); POPCOLOR(); } setcharsprinted(chpr); } exifprobe-2.0.1+git20170416-3c2b76/epson_datadefs.h0000644000000000000000000000212413074742216017640 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: epson_datadefs.h,v 1.1 2005/05/25 15:38:07 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef EPSON_DATADEFS_INCLUDED #define EPSON_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id epson_model_id[] = { { "PhotoPC 850Z", 13, EPSON_850Z, 1, 1 }, { "PhotoPC 3000Z", 14, EPSON_3000Z, 1, 1 }, { "PhotoPC 3100Z", 14, EPSON_3100Z, 1, 1 }, { "L-500V ", 8, EPSON_L500V, 1, 1 }, { 0, 0, 0, 0, 0 } }; #endif /* EPSON_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/datadefs.h0000644000000000000000000000274213074742216016442 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: datadefs.h,v 1.2 2005/06/09 03:00:25 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef DATADEFS_INCLUDED #define DATADEFS_INCLUDED struct ifd_entry { unsigned short tag; unsigned short value_type; unsigned long count; unsigned long value; }; #include "ciff_datadefs.h" #include "mrw_datadefs.h" #include "jp2_datadefs.h" #include "x3f_datadefs.h" struct fileheader { unsigned short file_marker; /* initial ushort from file */ unsigned long probe_magic; /* magic number assigned (misc.h) */ struct ciff_header *ciff_header; /* iff found to be CIFF */ struct jp2_header jp2_header; /* JPEG2000 JP2 format */ struct mrw_header mrw_header; /* Minolta MRW "raw" format */ struct x3f_header *x3f_header; /* Sigma/Fovenon X3F */ }; #endif /* DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/panasonic_datadefs.h0000644000000000000000000000266713074742216020503 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: panasonic_datadefs.h,v 1.2 2005/06/21 15:16:22 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef PANASONIC_DATADEFS_INCLUDED #define PANASONIC_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id panasonic_model_id[] = { { "DMC-FX7", 7, PANASONIC_DMCFX7, 1, 1 }, { "DMC-FZ1", 7, PANASONIC_DMCFZ1, 1, 1 }, { "DMC-FZ2", 7, PANASONIC_DMCFZ2, 1, 0 }, { "DMC-FZ3", 7, PANASONIC_DMCFZ3, 1, 1 }, { "DMC-FZ10", 8, PANASONIC_DMCFZ10, 1, 1 }, { "DMC-FZ15", 8, PANASONIC_DMCFZ15, 1, 1 }, { "DMC-FZ20", 8, PANASONIC_DMCFZ20, 1, 1 }, { "DMC-LC5", 7, PANASONIC_DMCLC5, 1, 1 }, { "DMC-LC33", 8, PANASONIC_DMCLC33, 1, 1 }, { "DMC-LC40", 8, PANASONIC_DMCLC40, 1, 1 }, { "DMC-LC43", 8, PANASONIC_DMCLC43, 1, 1 }, { 0, 0, 0, 0, 0 } }; #endif /* PANASONIC_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/maker_template0000644000000000000000000003125213074742216017431 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef WALL static char *ModuleId = "@(#) $Id: maker_template,v 1.4 2005/01/27 02:27:32 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* THIS_MAKE camera maker-specific routines. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Template file for maker-specific routines. */ /* 1. Copy this to a file maker_XXX.c and edit as necessary. */ /* a. Replace the string "THIS_MAKE" with the maker name. */ /* b. assign numbers to make and model names as reqd in maker.h */ /* (required iff more than one style of MakerNote exists across */ /* models) /* c. edit THIS_MAKE_model_number to decode the MODEL, using the */ /* SOFTWARE name as well if necessary. The returned number */ /* will be used to select the print and interpret routines for */ /* the model. */ /* d. Edit print_THIS_MAKE_value() and */ /* print_THIS_MAKE_value_at_offset() to select the correct */ /* print and interpret routines for each note style */ /* e. code the specific print and interpret routines. */ /* f. remove any unnecessary template material. */ /* 2. Move the function prototypes to extern.h */ /* 3. Edit print_maker.c to add a case for THIS_MAKER to */ /* print_makervalue() and print_offset_makervalue(). */ /* 4. Edit maker_generic.c to add a case for THIS_MAKER to */ /* maker_number() and model_number(). */ /* 5. Edit maker_tagnames.c to add a case for THIS_MAKER to */ /* maker_tagname(). */ /* 6. Replace this comment with something appropriate. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include "defs.h" #include "extern.h" #include "misc.h" #include "maker.h" /* Find the id number assigned to known THIS_MAKE camera models. */ /* This number is used to dispatch print and interpret routines */ /* apporopriate to the current image. */ int THIS_MAKE_model_number(char *model,char *software) { int number = GENERIC; switch(*model) { default: number = GENERIC; break; } return(number); } /* Dispatch a print routine based upon model */ void print_THIS_MAKE_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { switch(model) { case MODEL1: print_THIS_MAKE1_makervalue(entry_ptr,make,model,prefix); THIS_MAKE1_interpret_value(entry_ptr); break; case MODEL2: case MODEL3: print_THIS_MAKE2_makervalue(entry_ptr,make,model,prefix); THIS_MAKE2_interpret_value(entry_ptr); break; case GENERIC: default: print_THIS_MAKE1_makervalue(entry_ptr,make,model,prefix); THIS_MAKE2_interpret_value(entry_ptr); break; } } /* Model-specific print routine for THIS_MAKE cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_THIS_MAKE1_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { if(entry_ptr) { switch(entry_ptr->tag) { /* pick off values that need special handling in cases */ /* here */ default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for THIS_MAKE */ /* cameras. */ void print_THIS_MAKE_offset_makervalue(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long offset_ref,char *prefix, int indent,int addrwidth,int make,int model,int at_offset) { switch(model) { case MODEL1: THIS_MAKE1_offset_makervalue(inptr,byteorder,entry_ptr, offset_ref,prefix,indent, addrwidth,make,model,int at_offset); break; case MODEL2: default: THIS_MAKE2_offset_makervalue(inptr,byteorder,entry_ptr, offset_ref,prefix,indent, addrwidth,make,model,int at_offset); break; } } /* Model-specific routine to print values found at an offset from the */ /* IFD entry in THIS_MAKE makernotes. */ /* One of these may be supplied for each model if necessary */ void THIS_MAKE1_offset_makervalue(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long offset_ref,char *prefix, int indent,int addrwidth,int make,int model,int at_offset) { unsigned long value_offset; unsigned long dumplength; unsigned short marker; char *nameoftag; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); value_offset = offset_ref + entry_ptr->value; /* Pick off UNDEFINED tag types. The rest can be handled by */ /* the generic routine. */ switch(entry_ptr->tag) { case 0x0100: /* JPEG Thumbnail in TIFF MakerNote */ print_tag_address(value_offset,indent,prefix,addrwidth); putindent(SUBINDENT); printf("Start of %s length %ld\n",nameoftag,entry_ptr->count); marker = read_imagemarker(inptr,value_offset); (void)process_jpeg_segments(inptr,value_offset, marker,entry_ptr->count,indent+2, addrwidth); STARTCOLOR(MAKER_COLOR); print_tag_address(value_offset + entry_ptr->count,indent,"-", addrwidth); putindent(SUBINDENT); printf("End of %s",nameoftag); /* make certain we're at the end unless 'inptr' bad */ fseek(inptr,value_offset + entry_ptr->count,SEEK_SET); break; case 0x0e00: /* PrintIM (Epson Print Image matching) */ case 0x0f00: /* Data */ print_tag_address(value_offset,indent,prefix,addrwidth); putindent(SUBINDENT); printf("%s: length %lu",nameoftag,entry_ptr->count); if(Max_undefined == 0) printf(" (not dumped, use -U)"); else { if((Max_undefined == DUMPALL) || (Max_undefined > entry_ptr->count)) dumplength = entry_ptr->count; else dumplength = Max_undefined; putchar('\n'); hexdump(inptr,value_offset,entry_ptr->count,dumplength,12, indent,SUBINDENT,addrwidth); } /* make certain we're at the end unless 'inptr' bad */ fseek(inptr,value_offset + entry_ptr->count,SEEK_SET); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, offset_ref,prefix,indent, addrwidth,make,model,at_offset); break; } } } void THIS_MAKE2_offset_makervalue(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long offset_ref,char *prefix, int indent,int addrwidth,int make,int model,int at_offset) { unsigned long value_offset; unsigned long dumplength; unsigned short marker; char *nameoftag; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); value_offset = offset_ref + entry_ptr->value; switch(entry_ptr->tag) { case 0x0100: /* JPEG Thumbnail in TIFF MakerNote, for */ print_tag_address(value_offset,indent,prefix,addrwidth); putindent(SUBINDENT); printf("Start of %s length %ld\n",nameoftag,entry_ptr->count); marker = read_imagemarker(inptr,value_offset); (void)process_jpeg_segments(inptr,value_offset, marker,entry_ptr->count,indent+2, addrwidth); STARTCOLOR(MAKER_COLOR); print_tag_address(value_offset + entry_ptr->count,indent,"-", addrwidth); putindent(SUBINDENT); printf("End of %s",nameoftag); /* make certain we're at the end unless 'inptr' bad */ fseek(inptr,value_offset + entry_ptr->count,SEEK_SET); break; case 0x0010: /* Data */ print_tag_address(value_offset,indent,prefix,addrwidth); putindent(SUBINDENT); printf("%s: length %lu",nameoftag,entry_ptr->count); if(Max_undefined == 0) printf(" (not dumped, use -U)"); else { if((Max_undefined == DUMPALL) || (Max_undefined > entry_ptr->count)) dumplength = entry_ptr->count; else dumplength = Max_undefined; putchar('\n'); hexdump(inptr,value_offset,entry_ptr->count,dumplength,12, indent,SUBINDENT,addrwidth); } /* make certain we're at the end */ fseek(inptr,value_offset + entry_ptr->count,SEEK_SET); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, offset_ref,prefix,indent, addrwidth,make,model,int at_offset); break; } } } char * maker_THIS_MAKE_tagname(unsigned short tag,int model) { char *tagname = (char *)0; /* Check specific models first */ switch(model) { case MODEL1: tagname = maker_THIS_MAKE1_tagname(tag,model); break; case MODEL2: tagname = maker_THIS_MAKE2_tagname(tag,model); break; default: /* Call a specific routine here, or leave it blank to */ /* just call the generic tag maker. */ break; } return(tagname); } /* Tags for the older cameras. */ char * maker_THIS_MAKE1_tagname(unsigned short tag,int model) { char *tagname = (char *)0; switch(tag) { /* ###%%% be sure to change these */ case 0x0003: tagname = "Quality"; break; case 0x0004: tagname = "Color Mode"; break; case 0x0005: tagname = "Image Adjustment"; break; case 0x0006: tagname = "ISO Setting"; break; case 0x0007: tagname = "White Balance"; break; case 0x0008: tagname = "Focus"; break; case 0x000a: tagname = "Digital Zoom"; break; case 0x000b: tagname = "LensConverter"; break; case 0x0f00: tagname = "Data"; break; case 0x0100: tagname = "JPEG Thumbnail"; break; default: break; } return(tagname); } char * maker_THIS_MAKE2_tagname(unsigned short tag,int model) { char *tagname = (char *)0; switch(tag) { /* ###%%% be sure to change these */ case 0x0001: tagname = "Version"; break; case 0x0002: tagname = "ISO Setting"; break; case 0x0003: tagname = "Color Mode"; break; case 0x0004: tagname = "Quality"; break; case 0x0005: tagname = "White Balance"; break; case 0x0006: tagname = "Image Sharpening"; break; case 0x0007: tagname = "Focus Mode"; break; case 0x0008: tagname = "Flash Setting"; break; case 0x000f: tagname = "ISO Selection"; break; case 0x0010: tagname = "Data"; break; case 0x0080: tagname = "Image Adjustment"; break; case 0x0082: tagname = "Adapter"; break; case 0x0085: tagname = "Manual Focus Distance"; break; case 0x0086: tagname = "Digital Zoom"; break; case 0x0088: tagname = "Auto Focus Position"; break; case 0x0e00: tagname = "PrintIM Data"; break; case 0x0100: tagname = "JPEG Thumbnail"; break; default: break; } return(tagname); } void THIS_MAKE1_interpret_value(struct ifd_entry *entry_ptr) { switch(entry_ptr->tag) { case 0xQUALITY: /* Quality */ switch(entry_ptr->value) { default: printred(" [???]",MAKER_COLOR); break; } break; case 0xCOLOR: /* Color Mode */ if(entry_ptr->value == COLOR) printf(" [color]"); else if(entry_ptr->value == MONOCHROME) printf(" [monochrome]"); else printred(" [???]",MAKER_COLOR); break; case 0xADJUST: /* Image Adjustment */ switch(entry_ptr->value) { default: printred(" [???]",MAKER_COLOR); break; } break; default: break; } } void THIS_MAKE2_interpret_value(struct ifd_entry *entry_ptr) { switch(entry_ptr->tag) { case 0x000b: case 0x000d: case 0x000e: case 0x0011: case 0x0083: case 0x0087: case 0x0089: case 0x008a: case 0x008b: case 0x0092: case 0x0094: printred(" [???]",MAKER_COLOR); break; default: printred(" [???]",MAKER_COLOR); break; } } exifprobe-2.0.1+git20170416-3c2b76/jp2000.c0000644000000000000000000023634113074742216015601 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: jp2000.c,v 1.10 2005/07/24 19:54:04 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* JP2/Jpeg2000 routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* The information coded here is derived from the public version of */ /* the Jpeg2000 specification (badly outdated) and from the jasper */ /* code at */ /* http://www.ece.uvic.ca/~mdadams/jasper/ */ /* Some items, such as the ipr, xml, uuid, and uinf boxes, are not */ /* exposed in the jasper implementation, and are implemented from the */ /* public version of the spec. A few test images containing xml and */ /* uuid boxes have been found; the rest are thoroughly untested. */ /* 64-bit addressing is not yet supported */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include #include "defs.h" #include "datadefs.h" #include "summary.h" #include "misc.h" #include "tags.h" #include "jp2.h" #include "jp2_extern.h" #include "jpegtags.h" #include "jp2tags.h" #include "extern.h" struct jp2box * read_jp2box(FILE *inptr,unsigned long offset) { static struct jp2box box; struct jp2box *newbox = NULL; if(inptr) { box.boxoffset = offset; box.lbox = read_ulong(inptr,TIFF_MOTOROLA,offset); if(!feof(inptr) && !(ferror(inptr))) { box.tbox = read_ulong(inptr,TIFF_MOTOROLA,HERE); if(!feof(inptr) && !(ferror(inptr))) { if(box.lbox == 1) { #if 0 box.boxlength = read_ulong64(inptr,TIFF_MOTOROLA,HERE); box.dataoffset = 16; #else PUSHCOLOR(RED); printf("%s: cannot read 64 bit sizes/offsets yet",Progname); POPCOLOR(); newbox = NULL; #endif } else { box.boxlength = box.lbox; box.dataoffset = 8; } newbox = &box; } else newbox = NULL; } else newbox = NULL; } return(newbox); } /* Print the content of the JP2 file signature box iff allowed by */ /* print options. */ int print_jp2_header(struct fileheader *fileheader,unsigned long section_id) { struct jp2_header jp2header; int status = -1; int chpr = 0; if(Print_options & section_id) { if(fileheader && (fileheader->probe_magic == PROBE_JP2MAGIC)) { jp2header = fileheader->jp2_header; if(jp2header.magic == PROBE_JP2MAGIC) { /* Ok, I'm convinced... */ print_jp2type(jp2header.type,0); chpr += printf(" <%#lx> magic %#lx, length %lu",jp2header.type, jp2header.magic,jp2header.length); chpr = newline(chpr); status = 0; } else chpr += printf(" NOT A JP2 HEADER"); } else chpr += printf(" NOT A JP2 HEADER"); } chpr = newline(chpr); return(status); } /* Print a jp2 box identifier, with its length and offset to the box */ /* data, if SECTIONS are enabled in print options. */ void print_jp2box(FILE *inptr,struct jp2box *box,int indent) { unsigned long boxlength = 0UL; int chpr = 0; if(box) { if(box->boxlength == 0UL) box->boxlength = get_filesize(inptr) - box->boxoffset; else boxlength = box->boxlength; if(PRINT_SECTION) { print_tag_address(SECTION,box->boxoffset,indent,"@"); print_jp2type(box->tbox,0); chpr += printf(" <%#lx>",box->tbox); chpr += printf(" length %lu",boxlength); /* Indicate that this is lastbox */ if(box->boxlength == 0UL) chpr += printf(" (0)"); chpr += printf(" data offset %lu",box->dataoffset); } } chpr = newline(chpr); } int list_jp2box(FILE *inptr,struct jp2box *box,char *parent_name,int indent,int donl) { unsigned long boxlength = 0UL; int chpr = 0; if(box) { if(box->boxlength == 0UL) boxlength = get_filesize(inptr) - box->boxoffset; else boxlength = box->boxlength; if((LIST_MODE)) { print_tag_address(ENTRY,box->boxoffset,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) printf("%s",parent_name); print_jp2type(box->tbox,0); } if((PRINT_VALUE)) { chpr += printf(" = @%lu:%-4lu",box->boxoffset,boxlength); /* Indicate that this is lastbox */ if(box->boxlength == 0UL) chpr += printf(":0"); } } } if(donl) chpr = newline(chpr); return(chpr); } /* Report the type of a JP2 box. Types are normally printable ascii */ /* (stored in 4 byte unsigned integers), but this routine is prepared */ /* to print garbled 'types', which may indicate that the program has */ /* gone astray, or that the file is garbled. Unprintable bytes, */ /* including newlines and such, are printed in escaped octal */ /* notation. */ /* Box type names are enclosed in []. */ void print_jp2type(unsigned long type,int atend) { int i; char *p; int chpr = 0; p = (char *)&type + 3; if(!(LIST_MODE)) { putchar('['); ++chpr; } /* 'atend' declares that the output marks the last byte of the */ /* box; this is indicated by prepending a '/' to the box name */ if(atend) { putchar('/'); ++chpr; } for(i = 0; i < 4; ++i,--p) { if(isascii(*p) && isprint(*p)) { putchar(*p); ++chpr; } else if(*p) chpr += printf("\\%03u",*p & 0xff); else chpr += printf("\\0"); } if(!(LIST_MODE)) { putchar(']'); ++chpr; } setcharsprinted(chpr); } /* The top level JP2 processor. */ unsigned long process_jp2(FILE *inptr,unsigned long offset,struct image_summary *summary_entry, char *parent_name,int indent) { struct jp2box *box; unsigned long max_offset = 0L; unsigned long lastbox = 0L; unsigned long dumplength; while(!feof(inptr) && !lastbox) { box = read_jp2box(inptr,offset); if(box) { /* This routine is currently called only from main(), */ /* where the summary_entry will already have been created */ /* nonetheless... */ if((summary_entry == NULL) || summary_entry->entry_lock) summary_entry = new_summary_entry(summary_entry,0,IMGFMT_JPEG2000); switch(box->tbox) { case JP2_FTYP: max_offset = process_jp2_ftyp(inptr,box,summary_entry,indent); break; case JP2_XML: max_offset = process_jp2_xml(inptr,box,indent); break; case JP2_JP2I: max_offset = process_jp2_jp2i(inptr,box,indent); break; case JP2_JP2H: max_offset = process_jp2_jp2h(inptr,box,summary_entry,indent); break; case JP2_UUID: max_offset = process_jp2_uuid(inptr,box,summary_entry,indent); break; case JP2_JP2C: if(box->boxlength == 0) ++lastbox; max_offset = process_jp2_jp2c(inptr,box,summary_entry,indent); break; case JP2_UINF: max_offset = process_jp2_uinf(inptr,box,summary_entry,indent); break; case JP2_PRFL: /* apparently not in the final spec */ default: if((box->boxlength == 0) || ateof(inptr)) ++lastbox; if((LIST_MODE)) setcharsprinted(list_jp2box(inptr,box,"JP2.",indent,1)); else print_jp2box(inptr,box,indent); max_offset = box->boxoffset + box->boxlength; if((PRINT_SECTION)) { /* Dump unrecognized boxes. */ if(Max_undefined > 0) { if(Max_undefined == DUMPALL) dumplength = box->boxlength; else if(Max_undefined > box->boxlength) dumplength = box->boxlength; else dumplength = Max_undefined; } else { /* Always dump a little of undefined */ /* boxes */ if(box->boxlength < 48) dumplength = box->boxlength; else dumplength = 48; } (void)newline(0); hexdump(inptr,box->boxoffset,dumplength,dumplength, 16,indent,SUBINDENT); (void)newline(1); } if((PRINT_SECTION)) { (void)newline(0); print_tag_address(SECTION,max_offset - 1,indent,"@"); print_jp2type(box->tbox,1); } break; } (void)newline(0); offset = max_offset; if(ateof(inptr)) ++lastbox; } else break; } return(max_offset); } unsigned long process_jp2_ftyp(FILE *inptr,struct jp2box *box,struct image_summary *summary_entry, int indent) { unsigned long boxoffset,max_offset,dataoffset; unsigned long boxlength; unsigned long mjv,mnv,cl,ncl; int compat = 0; int chpr = 0; int i; if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.",indent,1); else print_jp2box(inptr,box,indent); boxoffset = box->boxoffset; boxlength = box->boxlength; dataoffset = boxoffset + box->dataoffset; max_offset = boxoffset + boxlength; mjv = read_ulong(inptr,TIFF_MOTOROLA,dataoffset); dataoffset += 4; print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.ftyp."); chpr += printf("MajorVersion"); } if((PRINT_VALUE)) { chpr += printf(" = %#-10lx = ",mjv); print_jp2type(mjv,0); if(mjv != JP2_BR) printred( " (INVALID MAJOR VERSION"); } chpr = newline(chpr); print_tag_address(ENTRY,dataoffset,indent + 8,"="); mnv = read_ulong(inptr,TIFF_MOTOROLA,dataoffset); dataoffset += 4; if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.ftyp."); chpr += printf("MinorVersion"); } if((PRINT_VALUE)) { chpr += printf(" = %#-10lx = ",mnv); print_jp2type(mnv,0); } chpr = newline(chpr); ncl = box->boxlength - box->dataoffset - 8; ncl /= 4; for(i = 0; i < ncl; ++i) { print_tag_address(ENTRY,dataoffset,indent + 8,"="); cl = read_ulong(inptr,TIFF_MOTOROLA,dataoffset); dataoffset += 4; if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.ftyp."); chpr += printf("Compat"); } if((PRINT_VALUE)) { chpr += printf(" = %#-10lx = ",cl); print_jp2type(cl,0); } chpr = newline(chpr); if(cl == JP2_BR) compat++; } if((PRINT_SECTION)) { chpr = newline(chpr); print_tag_address(SECTION,dataoffset - 1,indent,"@"); print_jp2type(box->tbox,1); } chpr = newline(chpr); return(max_offset); } /* The xml box. The xml is printed if Print_options includes SECTION, */ /* but the text is not examined for information which might go in the */ /* image summary. Even though image information may be recorded in */ /* the xml, the information need not be correct or pertain to the */ /* current image (the original image may have been modified without */ /* updating the xml. */ unsigned long process_jp2_xml(FILE *inptr,struct jp2box *box,int indent) { unsigned long boxoffset,max_offset,dataoffset; unsigned long readsize; unsigned long boxlength,size; int chpr = 0; print_jp2box(inptr,box,indent); boxoffset = box->boxoffset; boxlength = box->boxlength; dataoffset = boxoffset + box->dataoffset; max_offset = box->boxoffset + box->boxlength; size = boxlength - 8; if((PRINT_SECTION)) { print_tag_address(VALUE,dataoffset,indent + 10,"="); if((PRINT_VALUE)) { if((inptr && (fseek(inptr,dataoffset,SEEK_SET)) != -1)) { while(size > 0ULL) { if(size > READSIZE) readsize = READSIZE; else readsize = size; /* Print as ascii */ setcharsprinted(chpr); print_ascii(inptr,readsize,dataoffset); dataoffset += readsize; size -= readsize; } } } chpr = newline(chpr); print_tag_address(SECTION,dataoffset - 1,indent,"="); print_jp2type(box->tbox,1); } else if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.",indent,1); chpr = newline(chpr); return(max_offset); } /* The "Intellectual Property Rights" box, which records information */ /* which may have nothing to do with intellect, property, or any */ /* logical concept of rights. */ unsigned long process_jp2_jp2i(FILE *inptr,struct jp2box *box,int indent) { unsigned long boxoffset,max_offset,dataoffset; unsigned long readsize; unsigned long boxlength,size; int chpr = 0; print_jp2box(inptr,box,indent); boxoffset = box->boxoffset; boxlength = box->boxlength; dataoffset = boxoffset + box->dataoffset; max_offset = boxoffset + boxlength; if((PRINT_SECTION)) { print_tag_address(SECTION,dataoffset,indent + 8,"="); size = boxlength - 8; if((inptr && (fseek(inptr,dataoffset,SEEK_SET)) != -1)) { while(size > 0ULL) { if(size > READSIZE) readsize = READSIZE; else readsize = size; /* Print as ascii... */ setcharsprinted(chpr); print_ascii(inptr,readsize,dataoffset); dataoffset += readsize; size -= readsize; } } chpr = newline(chpr); print_tag_address(SECTION,dataoffset - 1,indent,"="); print_jp2type(box->tbox,1); } else if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.",indent,1); chpr = newline(chpr); return(max_offset); } /* The header superbox; this box has lots of human-interest stuff */ unsigned long process_jp2_jp2h(FILE *inptr,struct jp2box *box,struct image_summary *summary_entry, int indent) { unsigned long lastbox = 0L; unsigned long boxoffset,max_offset,dataoffset,tbox; unsigned long boxlength; int chpr = 0; if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.",indent,1); else print_jp2box(inptr,box,indent); boxoffset = box->boxoffset; boxlength = box->boxlength; tbox = box->tbox; dataoffset = boxoffset + box->dataoffset; max_offset = boxoffset + boxlength; while(!feof(inptr) && !lastbox && (dataoffset < max_offset)) { box = read_jp2box(inptr,dataoffset); if(box) { switch(box->tbox) { case JP2_ihdr: dataoffset = process_jp2_ihdr(inptr,box,summary_entry,indent + SUBINDENT); break; case JP2_colr: dataoffset = process_jp2_colr(inptr,box,indent + SUBINDENT); break; case JP2_res: dataoffset = process_jp2_res(inptr,box,indent + SUBINDENT); break; case JP2_bpcc: case JP2_pclr: case JP2_cdef: case JP2_resc: /* handled in process_jp2_res(). */ case JP2_resd: /* handled in process_jp2_res(). */ /* These fields are reported but not expanded */ print_jp2box(inptr,box,indent + SUBINDENT); if(boxlength) dataoffset += boxlength; else ++lastbox; chpr = newline(chpr); break; default: /* report the unknown box and try to continue. If */ /* the box is properly constructed, that may be */ /* possible; most likely this is garbled data. */ print_jp2box(inptr,box,indent + SUBINDENT); if(ferror(inptr) || feof(inptr)) { clearerr(inptr); ++lastbox; } if(boxlength) dataoffset += boxlength; else ++lastbox; chpr = newline(chpr); break; } } } if((PRINT_SECTION)) { chpr = newline(chpr); print_tag_address(SECTION,dataoffset - 1,indent,"@"); print_jp2type(tbox,1); } chpr = newline(chpr); return(max_offset); } /* The ihdr box, within the jp2h box, wherein we find the image size. */ unsigned long process_jp2_ihdr(FILE *inptr,struct jp2box *box,struct image_summary *summary_entry, int indent) { unsigned long boxoffset,max_offset,dataoffset; unsigned long boxlength; unsigned long imgheight = 0UL; unsigned long imgwidth = 0UL; unsigned short nc = 0; unsigned short bpc = 0; unsigned short comp = 0; unsigned short hasUNK = 0; unsigned short hasIPR = 0; int chpr = 0; if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.jp2h.",indent,1); else print_jp2box(inptr,box,indent); boxoffset = box->boxoffset; boxlength = box->boxlength; dataoffset = boxoffset + box->dataoffset; max_offset = boxoffset + boxlength; imgheight = read_ulong(inptr,TIFF_MOTOROLA,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.ihdr."); chpr += printf("ImageHeight"); } if((PRINT_VALUE)) chpr += printf(" = %lu",imgheight); chpr = newline(chpr); dataoffset += 4; imgwidth = read_ulong(inptr,TIFF_MOTOROLA,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.ihdr."); chpr += printf("ImageWidth"); } if((PRINT_VALUE)) chpr += printf(" = %lu",imgwidth); chpr = newline(chpr); dataoffset += 4; if(summary_entry && (imgheight > 0) && (summary_entry->pixel_height < imgheight)) { summary_entry->pixel_height = imgheight; } if(summary_entry && (imgwidth > 0) && (summary_entry->pixel_width < imgwidth)) { summary_entry->pixel_width = imgwidth; } nc = read_ushort(inptr,TIFF_MOTOROLA,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.ihdr."); chpr += printf("NumberOfComponents"); } if((PRINT_VALUE)) chpr += printf(" = %u",nc); chpr = newline(chpr); dataoffset += 2; bpc = read_ubyte(inptr,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.ihdr."); chpr += printf("BitsPerComponent"); } if((PRINT_VALUE)) chpr += printf(" = %u",bpc); chpr = newline(chpr); dataoffset++; comp = read_ubyte(inptr,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.ihdr."); chpr += printf("Compression"); } if((PRINT_VALUE)) chpr += printf(" = %u",comp); chpr = newline(chpr); /* This is always 7 according to spec, and tells us nothing; */ /* it will be over-written with the transform type from a COD */ /* segement, if one is found. I imagine that "extensions" to */ /* the spec will quickly overwhelm this. */ if((summary_entry) && (summary_entry->compression <= 0)) summary_entry->compression = comp; dataoffset++; hasUNK = read_ubyte(inptr,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.ihdr."); chpr += printf("Colorspace"); } if((PRINT_VALUE)) chpr += printf(" = %#x = %sknown",hasUNK,hasUNK ? "un" : ""); chpr = newline(chpr); dataoffset++; hasIPR = read_ubyte(inptr,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.ihdr."); chpr += printf("IPRbox"); } if((PRINT_VALUE)) chpr += printf(" = %#x = %s",hasIPR,hasIPR ? "yes" : "no"); chpr = newline(chpr); dataoffset++; if((PRINT_SECTION)) { print_tag_address(SECTION,dataoffset - 1,indent,"@"); print_jp2type(box->tbox,1); chpr = newline(chpr); } return(max_offset); } unsigned long process_jp2_uuid(FILE *inptr,struct jp2box *box,struct image_summary *summary_entry, int indent) { unsigned long boxoffset,max_offset,dataoffset; unsigned long boxlength,dumplength; unsigned long ifd_offset = 0UL; unsigned short idbyte,byte; struct fileheader *header = NULL; int chpr = 0; int i; if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.",indent,0); else print_jp2box(inptr,box,indent); boxoffset = box->boxoffset; boxlength = box->boxlength; dataoffset = boxoffset + box->dataoffset; max_offset = boxoffset + boxlength; idbyte = byte = read_ubyte(inptr,dataoffset); print_tag_address(SECTION,dataoffset,indent + 4,"*"); if((LIST_MODE)) { if((PRINT_VALUE)) chpr += printf(" # ID: "); } else chpr += printf("ID: "); if(!(LIST_MODE) || (PRINT_VALUE)) { if(!feof(inptr) && !ferror(inptr)) { chpr += printf("%02x",(unsigned int)byte & 0xff); for(i = 1; i < 16; ++i) { byte = read_ubyte(inptr,HERE); if(feof(inptr) || ferror(inptr)) break; chpr += printf(",%02x",(unsigned int)byte & 0xff); } chpr = newline(chpr); } } dataoffset += 16; /* No idea what the 16 "ID" bytes mean, or how to track */ /* registered types through the OID register. For now, a leading */ /* byte of 0x5 seems to signal a TIFF IFD. Dump a little bit of */ /* anything else. Probably need to check more of the ID... */ /* ...ok, now I've seen *two* ids that introduce TIFF sections... */ if((idbyte != 5) && (idbyte != 0xb1)) { if((PRINT_SECTION)) { dumplength = max_offset - dataoffset; if(dumplength > 48) dumplength = 48; chpr = newline(chpr); hexdump(inptr,dataoffset,dumplength,dumplength,16,indent,SUBINDENT); chpr = newline(1); } } /* So far I've seen these with recognizable "magic" */ /* 96,a9,f1,f1,... MSIG - ??? what is this? */ /* 2c,4c,01,00,... 8BIM Adobe PhotoShop - should handle this... */ /* 05,37,cd,ab,... TIFF - this we can do... */ /* b1,4b,f8,bd.... also TIFF */ header = read_imageheader(inptr,dataoffset); if(header && (header->probe_magic == PROBE_TIFFMAGIC)) { if((PRINT_SECTION)) { chpr = newline(chpr); print_tag_address(SECTION,dataoffset,indent + 4,"@"); print_header(header,SECTION); ifd_offset = read_ulong(inptr,header->file_marker,HERE); chpr += printf(" ifd offset = %#lx/%lu",ifd_offset,ifd_offset); chpr += printf(" (+ %lu = %#lx/%lu)",dataoffset, dataoffset + ifd_offset, dataoffset + ifd_offset); chpr = newline(0); } dataoffset = process_tiff_ifd(inptr,header->file_marker, 8,dataoffset,max_offset,summary_entry,"JP2.uuid", TIFF_IFD,0,-1,indent + 4); } dataoffset = boxoffset + boxlength; if((PRINT_SECTION)) { chpr = newline(0); print_tag_address(SECTION,dataoffset - 1,indent,"@"); print_jp2type(box->tbox,1); chpr = newline(chpr); } return(max_offset); } /* The uinf superbox, presumably containing a list of uuids and urls */ /* pointing to data to describe them. */ /* This is from the outdated public Jpeg2000 spec; jasper doesn't */ /* appear to handle it. Haven't seen one in the wild yet. */ unsigned long process_jp2_uinf(FILE *inptr,struct jp2box *box,struct image_summary *summary_entry, int indent) { unsigned long boxoffset,max_offset,dataoffset,tbox; unsigned long boxlength; int chpr = 0; if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.",indent,1); else print_jp2box(inptr,box,indent); boxoffset = box->boxoffset; boxlength = box->boxlength; tbox = box->tbox; dataoffset = boxoffset + box->dataoffset; max_offset = boxoffset + boxlength; box = read_jp2box(inptr,dataoffset); if(box) { if((box->tbox) == JP2_ulst) dataoffset = process_jp2_ulst(inptr,box,indent); else { print_jp2box(inptr,box,indent); chpr += printf(" NOT a ULST box!"); dataoffset += box->boxlength; } box = read_jp2box(inptr,dataoffset); if(box) dataoffset = process_jp2_de(inptr,box,indent); else { print_jp2box(inptr,box,indent); chpr += printf(" NOT a DE box!"); dataoffset += box->boxlength; } } if((PRINT_SECTION)) { chpr = newline(chpr); print_tag_address(SECTION,dataoffset - 1,indent,"@"); print_jp2type(box->tbox,1); } chpr = newline(chpr); return(max_offset); } /* The uuid list (ulst) box of the uinf superbox. */ unsigned long process_jp2_ulst(FILE *inptr,struct jp2box *box,int indent) { unsigned long boxoffset,max_offset,dataoffset,tbox; unsigned long boxlength; unsigned short nuuid,byte; int chpr = 0; int i,j; if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.uinf.",indent,1); else print_jp2box(inptr,box,indent); boxoffset = box->boxoffset; boxlength = box->boxlength; tbox = box->tbox; dataoffset = boxoffset + box->dataoffset; max_offset = boxoffset + boxlength; nuuid = read_ushort(inptr,TIFF_MOTOROLA,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.uinf.ulst."); chpr += printf("NumberOfUuids"); } if((PRINT_VALUE)) chpr += printf(" = %u",nuuid); chpr = newline(chpr); dataoffset += 2; /* Print the uuid list, in hex */ for(i = 0; i < nuuid; ++i) { print_tag_address(SECTION|ENTRY,dataoffset,indent + 4,"*"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.uinf.ulst."); chpr += printf("ID%d = ",i); } if((PRINT_VALUE)) chpr += printf(" = "); if(!feof(inptr) && !ferror(inptr)) { for(j = 0; j < 16; ++i) { byte = read_ubyte(inptr,dataoffset++); if(feof(inptr) || ferror(inptr)) break; if((PRINT_VALUE)) chpr += printf(",%02x",(unsigned int)byte & 0xff); } } else break; chpr = newline(chpr); } if((PRINT_SECTION)) { chpr = newline(chpr); print_tag_address(SECTION,dataoffset - 1,indent,"@"); print_jp2type(box->tbox,1); } chpr = newline(chpr); return(max_offset); } /* The data entry URL box of the uinf superbox. */ unsigned long process_jp2_de(FILE *inptr,struct jp2box *box,int indent) { unsigned long boxoffset,max_offset,dataoffset,tbox; unsigned long boxlength; unsigned short vers; unsigned long flag; int chpr = 0; if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.uinf.",indent,1); else print_jp2box(inptr,box,indent); boxoffset = box->boxoffset; boxlength = box->boxlength; tbox = box->tbox; dataoffset = boxoffset + box->dataoffset; max_offset = boxoffset + boxlength; vers = read_ubyte(inptr,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.uinf.de."); chpr += printf("Version"); } if((PRINT_VALUE)) chpr += printf(" = %u",vers); chpr = newline(chpr); dataoffset ++; flag = read_ulong(inptr,TIFF_MOTOROLA,dataoffset); flag = (flag >> 8) & 0xfff; print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.uinf.de."); chpr += printf("flags"); } if((PRINT_VALUE)) chpr += printf(" = %lu",flag); chpr = newline(chpr); dataoffset += 3; print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.uinf.de."); chpr += printf("Location"); } if((PRINT_VALUE)) { chpr += printf(" (length %lu) = ",max_offset - dataoffset); /* This should be UTF-8 ###%%% */ setcharsprinted(chpr); print_ascii(inptr,max_offset - dataoffset,dataoffset); } if((PRINT_SECTION)) { chpr = newline(chpr); print_tag_address(SECTION,dataoffset - 1,indent,"@"); print_jp2type(tbox,1); } chpr = newline(chpr); return(max_offset); } /* The colorspace (colr) of the jp2h superbox. */ unsigned long process_jp2_colr(FILE *inptr,struct jp2box *box,int indent) { unsigned long boxoffset,dataoffset; unsigned long boxlength,proflength; unsigned short meth = 0; unsigned short prec = 0; unsigned short approx = 0; unsigned short csenum = 0; int chpr = 0; if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.jp2h.",indent,1); else print_jp2box(inptr,box,indent); boxoffset = box->boxoffset; dataoffset = boxoffset + box->dataoffset; boxlength = box->boxlength; meth = read_ubyte(inptr,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.colr."); chpr += printf("Method"); } if((PRINT_VALUE)) chpr += printf(" = %u",meth); chpr = newline(chpr); dataoffset ++; prec = read_ubyte(inptr,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.colr."); chpr += printf("Precedence"); } if((PRINT_VALUE)) chpr += printf(" = %u",prec); chpr = newline(chpr); dataoffset ++; approx = read_ubyte(inptr,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.colr."); chpr += printf("ColorSpaceAproximation"); } if((PRINT_VALUE)) chpr += printf(" = %u",approx); chpr = newline(chpr); dataoffset ++; if(meth == 1) { csenum = read_ulong(inptr,TIFF_MOTOROLA,dataoffset); print_tag_address(ENTRY,dataoffset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.colr."); chpr += printf("EnumeratedColorSpace"); } if((PRINT_VALUE)) { chpr += printf(" = %u",csenum); switch(csenum) { case 16: chpr += printf(" = sRGB"); break; case 17: chpr += printf(" = greyscale"); break; default: chpr += printf(" = undefined"); break; } } chpr = newline(chpr); dataoffset += 4; } else { print_tag_address(ENTRY,dataoffset,indent + 8,"="); proflength = boxoffset + boxlength - dataoffset; if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2h.colr."); chpr += printf("ICCProfileLength"); } if((PRINT_VALUE)) chpr += printf(" = %lu",proflength); chpr = newline(chpr); /* ###%%% display this as soon as we have some ICC routines */ dataoffset = boxoffset + boxlength; } dataoffset = boxoffset + boxlength; if((PRINT_SECTION)) { chpr = newline(chpr); print_tag_address(SECTION,dataoffset - 1,indent,"@"); print_jp2type(box->tbox,1); } chpr = newline(chpr); return(dataoffset); } /* The resolution superbox (res ). May contain one or two sub-boxes. */ /* This routine handles the sub-boxes directly. */ unsigned long process_jp2_res(FILE *inptr,struct jp2box *box,int indent) { unsigned long boxoffset,max_offset,resboxoffset; unsigned long dataoffset,resdataoffset; unsigned long resboxlength = 0UL; unsigned long boxlength; unsigned long tbox; unsigned short vrcn = 0; unsigned short vrcd = 0; unsigned short hrcn = 0; unsigned short hrcd = 0; unsigned short vrce = 0; unsigned short hrce = 0; double vrc = 0.0; double hrc = 0.0; char *rtype; char id; int chpr = 0; if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.jp2h.",indent,1); else print_jp2box(inptr,box,indent); /* Save the parent box params. */ boxoffset = box->boxoffset; dataoffset = boxoffset + box->dataoffset; boxlength = box->boxlength; tbox = box->tbox; max_offset = boxoffset + boxlength; /* There may be one or two sub-boxes, resc, and resd. */ boxlength -= box->dataoffset; indent += SUBINDENT; if(boxlength >= 14ULL) /* sub-box must be this long */ { box = read_jp2box(inptr,dataoffset); if((PRINT_LONGNAMES)) chpr = list_jp2box(inptr,box,"JP2.jp2h.res.",indent,1); else print_jp2box(inptr,box,indent + SUBINDENT); resboxoffset = box->boxoffset; resdataoffset = resboxoffset + box->dataoffset; resboxlength = box->boxlength; boxlength -= resboxlength; id = box->tbox & 0xff; vrcn = read_ushort(inptr,TIFF_MOTOROLA,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("vr%cn",id); if((PRINT_VALUE)) chpr += printf(" = %u",vrcn); } chpr = newline(chpr); resdataoffset += 2; vrcd = read_ushort(inptr,TIFF_MOTOROLA,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("vr%cd",id); if((PRINT_VALUE)) chpr += printf(" = %u",vrcd); } chpr = newline(chpr); resdataoffset += 2; hrcn = read_ushort(inptr,TIFF_MOTOROLA,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("hr%cn",id); if((PRINT_VALUE)) chpr += printf(" = %u",hrcn); } chpr = newline(chpr); resdataoffset += 2; hrcd = read_ushort(inptr,TIFF_MOTOROLA,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("hr%cd",id); if((PRINT_VALUE)) chpr += printf(" = %u",hrcd); } chpr = newline(chpr); resdataoffset += 2; vrce = read_ubyte(inptr,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("vr%ce",id); if((PRINT_VALUE)) chpr += printf(" = %u",vrce); } resdataoffset ++; if(id == 'c') rtype = "Capture"; else if(id == 'd') rtype = "Display"; else rtype = "Illegitimate"; vrc = (double)vrcn * pow(10.0,(double)vrce) / (double)vrcd ; if((LIST_MODE)) print_tag_address(ENTRY,HERE,indent + 8,"*"); if((PRINT_TAGINFO)) { if((LIST_MODE)) { if((PRINT_LONGNAMES)) { chpr += printf("JP2.jp2h.res."); print_jp2type(box->tbox,0); chpr += printf("."); } chpr += printf("Vertical%sResolution",rtype); } else chpr += printf(" ==> Vertical %s Resolution",rtype); } if((PRINT_VALUE)) chpr += printf(" = %3.2f samples/meter",vrc); chpr = newline(chpr); hrce = read_ubyte(inptr,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("hr%ce",id); if((PRINT_VALUE)) chpr += printf(" = %u",hrce); } resdataoffset ++; hrc = (double)hrcn * pow(10.0,(double)hrce) / (double)hrcd ; if((LIST_MODE)) print_tag_address(ENTRY,HERE,indent + 8,"*"); if((PRINT_TAGINFO)) { if((LIST_MODE)) { if((PRINT_LONGNAMES)) { chpr += printf("JP2.jp2h.res."); print_jp2type(box->tbox,0); chpr += printf("."); } chpr += printf("Horizontal%sResolution",rtype); } else chpr += printf(" ==> Horizontal %s resolution",rtype); } if((PRINT_VALUE)) chpr += printf(" = %3.2f samples/meter",vrc); chpr = newline(chpr); if((PRINT_SECTION)) { print_tag_address(SECTION,resdataoffset - 1,indent + SUBINDENT,"="); print_jp2type(box->tbox,1); chpr = newline(chpr); } } chpr = newline(chpr); dataoffset += resboxlength; /* Sometimes both sub-boxes are present; do it again. */ if(boxlength >= 14ULL) { box = read_jp2box(inptr,dataoffset); if((PRINT_LONGNAMES)) chpr = list_jp2box(inptr,box,"JP2.jp2h.res.",indent,1); else print_jp2box(inptr,box,indent + SUBINDENT); resboxoffset = box->boxoffset; resdataoffset = resboxoffset + box->dataoffset; resboxlength = box->boxlength; boxlength -= resboxlength; id = box->tbox & 0xff; vrcn = read_ushort(inptr,TIFF_MOTOROLA,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("vr%cn",id); if((PRINT_VALUE)) chpr += printf(" = %u",vrcn); } chpr = newline(chpr); resdataoffset += 2; vrcd = read_ushort(inptr,TIFF_MOTOROLA,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("vr%cd",id); if((PRINT_VALUE)) chpr += printf(" = %u",vrcd); } chpr = newline(chpr); resdataoffset += 2; hrcn = read_ushort(inptr,TIFF_MOTOROLA,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("hr%cn",id); if((PRINT_VALUE)) chpr += printf(" = %u",hrcn); } chpr = newline(chpr); resdataoffset += 2; hrcd = read_ushort(inptr,TIFF_MOTOROLA,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("hr%cd",id); if((PRINT_VALUE)) chpr += printf(" = %u",hrcd); } chpr = newline(chpr); resdataoffset += 2; vrce = read_ubyte(inptr,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("vr%ce",id); if((PRINT_VALUE)) chpr += printf(" = %u",vrce); } resdataoffset ++; if(id == 'c') rtype = "Capture"; else if(id == 'd') rtype = "Display"; else rtype = "Illegitimate"; vrc = (double)vrcn * pow(10.0,(double)vrce) / (double)vrcd ; if((PRINT_TAGINFO)) { if((LIST_MODE)) { if((PRINT_LONGNAMES)) { chpr += printf("JP2.jp2h.res."); print_jp2type(box->tbox,0); chpr += printf("."); } chpr += printf("Vertical%sResolution",rtype); } else chpr += printf(" ==> Vertical %s Resolution",rtype); } if((PRINT_VALUE)) chpr += printf(" = %3.2f samples/meter",vrc); chpr = newline(chpr); hrce = read_ubyte(inptr,resdataoffset); if(!(LIST_MODE)) { print_tag_address(ENTRY,resdataoffset,indent + 8,"="); if((PRINT_TAGINFO)) chpr += printf("hr%ce",id); if((PRINT_VALUE)) chpr += printf(" = %u",hrce); } resdataoffset ++; hrc = (double)hrcn * pow(10.0,(double)hrce) / (double)hrcd ; if((PRINT_TAGINFO)) { if((LIST_MODE)) { if((PRINT_LONGNAMES)) { chpr += printf("JP2.jp2h.res."); print_jp2type(box->tbox,0); chpr += printf("."); } chpr += printf("Horizontal%sResolution",rtype); } else chpr += printf(" ==> Horizontal %s resolution",rtype); } if((PRINT_VALUE)) chpr += printf(" = %3.2f samples/meter",vrc); chpr = newline(chpr); if((PRINT_SECTION)) { print_tag_address(SECTION,resdataoffset - 1,indent + SUBINDENT,"@"); print_jp2type(box->tbox,1); chpr = newline(chpr); } } indent -= SUBINDENT; if((PRINT_SECTION)) { chpr = newline(chpr); print_tag_address(SECTION|ENTRY,max_offset - 1,indent,"="); print_jp2type(tbox,1); } chpr = newline(chpr); return(max_offset); } /* Process the jp2 codestream box. */ unsigned long process_jp2_jp2c(FILE *inptr,struct jp2box *box,struct image_summary *summary_entry, int indent) { unsigned long boxoffset,dataoffset; unsigned long boxlength; unsigned long tbox; int chpr = 0; if((LIST_MODE)) chpr = list_jp2box(inptr,box,"JP2.",indent,1); else print_jp2box(inptr,box,indent); boxoffset = box->boxoffset; dataoffset = boxoffset + box->dataoffset; boxlength = box->boxlength; tbox = box->tbox; dataoffset = process_jpeg2000_codestream(inptr,dataoffset,boxlength, summary_entry,indent + 8); chpr = newline(chpr); if((PRINT_SECTION)) { print_tag_address(SECTION,dataoffset - 1,indent,"@"); print_jp2type(tbox,1); } chpr = newline(chpr); return(dataoffset); } /* Process the jpeg2000 codestream itself */ unsigned long process_jpeg2000_codestream(FILE *inptr,unsigned long marker_offset, unsigned long data_length, struct image_summary *summary_entry, int indent) { unsigned long max_offset = 0L; unsigned long start_of_jp2c_data = marker_offset; unsigned long start_of_tile = 0; unsigned long tile_length = 0; unsigned short seg_length,tmp; unsigned short tilenum = 0; unsigned short part_index = 0; unsigned short nparts = 0; unsigned short regvalue = 0; unsigned short tag = 0; int chpr = 0; int tagindent,dataindent; char *name; if(inptr) { PUSHCOLOR(JPEG_COLOR); tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); tagindent = indent; while(tag != 0) { switch(tag) { case JP2C_SOC: /* Start of code stream */ start_of_jp2c_data = marker_offset; if((summary_entry == NULL) || summary_entry->entry_lock) summary_entry = new_summary_entry(summary_entry,0,IMGFMT_JPEG2000); if(summary_entry) { if(summary_entry->length <= 0) summary_entry->length = data_length; if(summary_entry->offset <= 0) summary_entry->offset = start_of_jp2c_data; summary_entry->imageformat = IMGFMT_JPEG2000; summary_entry->entry_lock = lock_number(summary_entry); } name = jp2000tagname(tag); print_tag_address(SECTION|ENTRY,marker_offset,tagindent,"@"); dataindent = charsprinted(); if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c."); chpr += printf("%s",name); } if((PRINT_VALUE)) chpr += printf(" = @%lu",marker_offset); chpr = newline(chpr); } else chpr += printf("<%#x=%s> Start of codestream",tag,name); chpr = newline(chpr); marker_offset += 2; break; case JP2C_SOT: /* Start of tile-part */ name = jp2000tagname(tag); start_of_tile = marker_offset; seg_length = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 2); print_tag_address(SEGMENT,marker_offset,tagindent,"@"); if((PRINT_SEGMENT) && (PRINT_SECTION)) { if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c."); chpr += printf("%s",name); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%u",marker_offset,seg_length); chpr = newline(chpr); } else chpr += printf("<%#x=%s> length %u",tag,name,seg_length); } tilenum = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 4); if((PRINT_SEGMENT) && (PRINT_ENTRY) && !(LIST_MODE)) chpr += printf(" tile number %u",tilenum); tile_length = read_ulong(inptr,TIFF_MOTOROLA,marker_offset + 6); if((PRINT_SEGMENT) && (PRINT_ENTRY) && !(LIST_MODE)) chpr += printf(" tile_length = %lu",tile_length); part_index = read_ubyte(inptr,HERE); if((PRINT_SEGMENT) && (PRINT_ENTRY) && !(LIST_MODE)) chpr += printf(" tile index = %u",part_index); nparts = read_ubyte(inptr,HERE); if((PRINT_SEGMENT) && (PRINT_ENTRY) && !(LIST_MODE)) chpr += printf(" [of %u tile parts]",nparts); chpr = newline(chpr); if(ferror(inptr)) { tag = 0; continue; } marker_offset += seg_length + 2; break; case JP2C_EPH: /* End of packet header */ case JP2C_SOD: /* Start of data */ name = jp2000tagname(tag); if((PRINT_SEGMENT) && (PRINT_SECTION)) { print_tag_address(SEGMENT,marker_offset,tagindent,"@"); if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c."); chpr += printf("%s",name); } if((PRINT_VALUE)) chpr += printf(" = @%lu",marker_offset); chpr = newline(chpr); } else chpr += printf("<%#x=%s>",tag,name); chpr = newline(chpr); } marker_offset = start_of_tile + tile_length; break; case JP2C_COM: name = jp2000tagname(tag); print_tag_address(SECTION|ENTRY,marker_offset,tagindent,"@"); if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jpc."); chpr += printf("Comment"); } } else chpr += printf("<%#x=%s>",tag,name); seg_length = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 2); tmp = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 4); if(ferror(inptr) == 0) { if(!(LIST_MODE)) chpr += printf(" length %u, reg %u",seg_length, regvalue); if((PRINT_VALUE)) { chpr += printf(" = "); setcharsprinted(chpr); (void)print_ascii(inptr,seg_length - 6,marker_offset + 6); } chpr = newline(chpr); marker_offset += seg_length + 2; } else { tag = 0; clearerr(inptr); } break; case JP2C_SIZ: marker_offset = process_jpc_siz(inptr,marker_offset,tag, summary_entry,tagindent); break; case JP2C_COD: marker_offset = process_jpc_cod(inptr,marker_offset,tag, summary_entry,tagindent); break; case JP2C_QCD: marker_offset = process_jpc_qcd(inptr,marker_offset,tag, summary_entry,tagindent); break; case JP2C_EOC: name = jp2000tagname(tag); print_tag_address(SECTION|ENTRY,marker_offset,tagindent,"@"); if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c."); chpr += printf("%s",name); } if((PRINT_VALUE)) chpr += printf(" = @%lu",marker_offset); chpr = newline(chpr); } else chpr += printf("<%#x=%s> End of codestream",tag,name); chpr = newline(chpr); tag = 0; continue; break; /* All of these fall through to the default */ case JP2C_CRG: case JP2C_SOP: case JP2C_POC: case JP2C_QCC: case JP2C_TLM: /* Tile-part lengths, main header */ case JP2C_PLM: /* Packet length, main header */ case JP2C_PLT: /* Packet length, tile-part header */ case JP2C_PPM: /* Packed packet headers; main header */ case JP2C_PPT: /* Packed packet headers; part header */ default: name = jp2000tagname(tag); print_tag_address(SEGMENT,marker_offset,tagindent,"@"); /* These are exclude from LIST mode unless */ /* SEGMENTS are explicitly enabled */ if((PRINT_SEGMENT)) { if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c."); chpr += printf("%s",name); } if((PRINT_VALUE)) chpr += printf(" = @%lu",marker_offset); } else chpr += printf("<%#x=%s>",tag,name); } if((tag & 0xff00) != 0xff00) { tag = 0; continue; } seg_length = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 2); if(ferror(inptr) == 0) { if((PRINT_SEGMENT)) { if((LIST_MODE)) chpr += printf(":%u",seg_length); else chpr += printf(" length %u",seg_length); chpr = newline(chpr); } marker_offset += seg_length + 2; } else { tag = 0; clearerr(inptr); } break; } tag = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); if(ferror(inptr) == 0) { max_offset = ftell(inptr); } else { tag = 0; clearerr(inptr); } } POPCOLOR(); if((summary_entry) && (summary_entry->length <= 0)) summary_entry->length = max_offset - start_of_jp2c_data; } setcharsprinted(chpr); return(max_offset); } /* SIZ header. Prints everything. */ unsigned long process_jpc_siz(FILE *inptr,unsigned long marker_offset,unsigned short tag, struct image_summary *summary_entry, int indent) { unsigned long max_offset; unsigned long gridwidth; unsigned long gridheight; unsigned long Ximgoffset; unsigned long Yimgoffset; unsigned long tilewidth; unsigned long tileheight; unsigned long Xtileoffset; unsigned long Ytileoffset; unsigned short seg_length; unsigned short caps; unsigned short ncomps; unsigned short precision; unsigned short hsep; unsigned short vsep; int chpr = 0; int i; char *name,*uns; name = jp2000tagname(tag); seg_length = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 2); print_tag_address(SECTION|ENTRY,marker_offset,indent,"@"); if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c."); chpr += printf("%s",name); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%u",marker_offset,seg_length + 2); } else chpr += printf("<%#x=%s> length %u",tag,name,seg_length); max_offset = marker_offset + seg_length + 2; marker_offset += 4; caps = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.siz."); chpr += printf("Capabilities"); } if((PRINT_VALUE)) chpr += printf(" = %u",caps); marker_offset += 2; gridwidth = read_ulong(inptr,TIFF_MOTOROLA,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.siz."); chpr += printf("GridWidth"); } if((PRINT_VALUE)) chpr += printf(" = %lu",gridwidth); marker_offset += 4; gridheight = read_ulong(inptr,TIFF_MOTOROLA,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.siz."); chpr += printf("GridHeight"); } if((PRINT_VALUE)) chpr += printf(" = %lu",gridheight); marker_offset += 4; Ximgoffset = read_ulong(inptr,TIFF_MOTOROLA,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.siz."); chpr += printf("XImageOffset"); } if((PRINT_VALUE)) chpr += printf(" = %lu",Ximgoffset); /* Image height and width are normally taken from the ihdr box; */ /* if this is a bare codestream encapsulated in e.g. a TIFF file, */ /* compute image size from grid size and offset */ if(summary_entry && (summary_entry->pixel_width <= 0) && (gridwidth > Ximgoffset)) { summary_entry->pixel_width = gridwidth - Ximgoffset; } marker_offset += 4; Yimgoffset = read_ulong(inptr,TIFF_MOTOROLA,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.siz."); chpr += printf("YImageOffset"); } if((PRINT_VALUE)) chpr += printf(" = %lu",Yimgoffset); /* Image height and width are normally taken from the ihdr box; */ /* if this is a bare codestream encapsulated in e.g. a TIFF file, */ /* compute image size from grid size and offset */ if(summary_entry && (summary_entry->pixel_height <= 0) && (gridheight > Yimgoffset)) { summary_entry->pixel_height = gridheight - Yimgoffset; } marker_offset += 4; tilewidth = read_ulong(inptr,TIFF_MOTOROLA,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.siz."); chpr += printf("TileWidth"); } if((PRINT_VALUE)) chpr += printf(" = %lu",tilewidth); marker_offset += 4; tileheight = read_ulong(inptr,TIFF_MOTOROLA,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.siz."); chpr += printf("TileHeight"); } if((PRINT_VALUE)) chpr += printf(" = %lu",tileheight); marker_offset += 4; Xtileoffset = read_ulong(inptr,TIFF_MOTOROLA,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.siz."); chpr += printf("Xtileoffset"); } if((PRINT_VALUE)) chpr += printf(" = %lu",Xtileoffset); marker_offset += 4; Ytileoffset = read_ulong(inptr,TIFF_MOTOROLA,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.siz."); chpr += printf("Ytileoffset"); } if((PRINT_VALUE)) chpr += printf(" = %lu",Ytileoffset); marker_offset += 4; ncomps = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); if(summary_entry) summary_entry->spp = ncomps; chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.siz."); chpr += printf("NumberOfComponents"); } if((PRINT_VALUE)) chpr += printf(" = %u",ncomps); marker_offset += 2; for(i = 0; i < ncomps; ++i) { precision = read_ubyte(inptr,marker_offset); if(summary_entry) summary_entry->bps[i] = precision; chpr = newline(chpr); if(precision & 0x80) uns = NULLSTRING; else uns = "un"; print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.siz."); chpr += printf("Component%dPrecision",i); } if((PRINT_VALUE)) chpr += printf(" = %#x = %u bits %ssigned",precision, (precision & 0x7f) + 1,uns); marker_offset++; /* ###%%% print these as separate lines? */ hsep = read_ubyte(inptr,marker_offset); if((PRINT_SEGMENT) && (PRINT_VALUE) && !(LIST_MODE)) chpr += printf(", hsep = %u",hsep); marker_offset++; vsep = read_ubyte(inptr,marker_offset); if((PRINT_SEGMENT) && (PRINT_VALUE) && !(LIST_MODE)) chpr += printf(", vsep = %u",vsep); marker_offset++; } if(!(LIST_MODE)) { chpr = newline(chpr); print_tag_address(SECTION|ENTRY,marker_offset - 1,indent,"@"); chpr += printf(" ",tag,name); } if(marker_offset > max_offset) printred(" READ PAST END OF BOX"); chpr = newline(chpr); return(max_offset); } /* Coding style header. Prints pretty much everything */ /* The public spec is way out of date and utterly wrong on this one; */ /* this is from jasper. */ unsigned long process_jpc_cod(FILE *inptr,unsigned long marker_offset,unsigned short tag, struct image_summary *summary_entry, int indent) { unsigned long max_offset; unsigned short seg_length; unsigned short cstyle; unsigned short decomp; unsigned short progorder; unsigned short nlayers; unsigned short cbw; unsigned short cbh; unsigned short cbstyle; unsigned short transform; unsigned short qmfbid; unsigned short part_wh; char *name; int chpr = 0; int i; name = jp2000tagname(tag); seg_length = read_ushort(inptr,TIFF_MOTOROLA,marker_offset + 2); print_tag_address(SECTION|ENTRY,marker_offset,indent,"@"); if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c."); chpr += printf("%s",name); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%u",marker_offset,seg_length + 2); } else chpr += printf("<%#x=%s> length %u",tag,name,seg_length); max_offset = marker_offset + seg_length + 2; marker_offset += 4; cstyle = read_ubyte(inptr,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("codingStyle"); } if((PRINT_VALUE)) { chpr += printf(" = %#x",cstyle & 0xff); chpr += printf(" = entropy coder with"); if((cstyle & 1) == 0) chpr += printf("out"); chpr += printf(" partitions,"); if(cstyle & 2) chpr += printf(" with SOP markers and"); else chpr += printf(" without SOP markers and"); if(cstyle & 4) chpr += printf(" with EPH markers"); else chpr += printf(" without EPH markers"); } marker_offset++; progorder = read_ubyte(inptr,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("ProgressionOrder"); } if((PRINT_VALUE)) chpr += printf(" = %#x",progorder & 0xff); marker_offset++; nlayers = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("NumberOfLayers"); } if((PRINT_VALUE)) chpr += printf(" = %#x",nlayers & 0xff); marker_offset += 2; transform = read_ubyte(inptr,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("MultiComponentTransform"); } if((PRINT_VALUE)) { chpr += printf(" = %#x",transform & 0xff); if(transform & 1) chpr += printf(" = 5/3 reversible"); else chpr += printf(" = 9/7 irreversible"); } /* Record transform in the first byte of */ /* summary_entry->compression; quantization will be recorded */ /* in the second byte. This overwrites the useless */ /* "compression" indicator in ihdr. */ if(summary_entry) summary_entry->compression = transform & 1; marker_offset++; decomp = read_ubyte(inptr,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("DecompLevels"); } if((PRINT_VALUE)) chpr += printf(" = %u",decomp & 0xff); marker_offset++; cbw = read_ubyte(inptr,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("CodeBlockWidthExponent"); } if((PRINT_VALUE)) { if((LIST_MODE)) { chpr += printf(" = %#x",(cbw & 0xff) + 2); chpr = newline(chpr); /* pseudotag */ print_tag_address(ENTRY,HERE,indent + 8,"*"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("CodeBlockWidth"); } if((PRINT_VALUE)) chpr += printf(" = %g",pow(2.0,(double)(cbw + 2))); } else chpr += printf(" = %#x + 2 # cbw -> %g",cbw & 0xff, pow(2.0,(double)(cbw + 2))); } marker_offset++; cbh = read_ubyte(inptr,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("CodeBlockHeightExponent"); } if((PRINT_VALUE)) { if((LIST_MODE)) { chpr += printf(" = %#x",(cbh & 0xff) + 2); chpr = newline(chpr); /* pseudotag */ print_tag_address(ENTRY,HERE,indent + 8,"*"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("CodeBlockHeight"); } if((PRINT_VALUE)) chpr += printf(" = %g",pow(2.0,(double)(cbh + 2))); } else chpr += printf(" = %#x + 2 # cbh -> %g",cbh & 0xff, pow(2.0,(double)(cbh + 2))); } marker_offset++; cbstyle = read_ubyte(inptr,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("CodeBLockStyle"); } if((PRINT_VALUE)) chpr += printf(" = %#x",cbstyle & 0xff); marker_offset++; qmfbid = read_ubyte(inptr,marker_offset); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("QMIFBankId"); } if((PRINT_VALUE)) chpr += printf(" = %#x",qmfbid & 0xff); marker_offset++; if(cstyle & 1) { for(i = 0; i <= decomp; ++i) { part_wh = read_ubyte(inptr,marker_offset++); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("Partition%dWidth",i); } if((PRINT_VALUE)) chpr += printf(" = %u",part_wh & 0xf); chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.cod."); chpr += printf("Partition%dHeight",i); } if((PRINT_VALUE)) chpr += printf(" = %u",(part_wh >> 4) & 0xf); } else { if((PRINT_TAGINFO)) chpr += printf("partition %d width",i); if((PRINT_VALUE)) chpr += printf(" = %u,",part_wh & 0xf); if((PRINT_TAGINFO)) chpr += printf(" height = "); if((PRINT_VALUE)) chpr += printf(" = %u",(part_wh >> 4) & 0xf); } } } if(!(LIST_MODE)) { chpr = newline(chpr); print_tag_address(SECTION|ENTRY,marker_offset - 1,indent,"@"); chpr += printf(" ",tag,name); } if(marker_offset > max_offset) printred(" READ PAST END OF BOX"); chpr = newline(chpr); return(max_offset); } /* Main quantization header. Prints just the quantization style. */ unsigned long process_jpc_qcd(FILE *inptr,unsigned long marker_offset,unsigned short tag, struct image_summary *summary_entry, int indent) { unsigned long max_offset; unsigned short seg_length; unsigned short qstyle; unsigned short guardbits; unsigned short stepsize,rawstepsize; char *name; int chpr = 0; int i; name = jp2000tagname(tag); seg_length = read_ushort(inptr,TIFF_MOTOROLA,marker_offset +2 ); print_tag_address(SECTION|ENTRY,marker_offset,indent,"@"); if((LIST_MODE)) { if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c."); chpr += printf("%s",name); } if((PRINT_VALUE)) chpr += printf(" = @%lu:%u",marker_offset,seg_length + 2); } else chpr += printf("<%#x=%s> length %u",tag,name,seg_length); max_offset = marker_offset + seg_length + 2; marker_offset += 4; qstyle = read_ubyte(inptr,marker_offset); ++marker_offset; chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.qcd."); chpr += printf("QuantizationStyle"); } if((PRINT_VALUE)) { chpr += printf(" = %#x",qstyle & 0xff); chpr += printf(" = "); if((qstyle & 0x1f) == 0) chpr += printf("no quantization"); else if((qstyle & 0x1f) == 1) chpr += printf("implicit quantization"); else if((qstyle & 0x1f) == 2) chpr += printf("explicit quantization"); guardbits = (qstyle >> 5) & 0x7; chpr += printf(", %u guard bit%s",guardbits,guardbits > 1 ? "s" : ""); } /* Record quantization in the second byte of the summary */ /* compression */ if(summary_entry) summary_entry->compression |= (((qstyle & 3) << 8) & 0xff00); for(i = 0;marker_offset < (max_offset - 1); ++i) { chpr = newline(chpr); print_tag_address(ENTRY,marker_offset,indent + 8,"="); if((qstyle & 0x1f) == 0) { rawstepsize = read_ubyte(inptr,marker_offset); stepsize = rawstepsize >> 3; if(stepsize & ~0x1f) { PUSHCOLOR(RED); print_tag_address(ENTRY,marker_offset,indent + SUBINDENT,"@"); chpr += printf("# WARNING: stepsize exponent %d out of range (%#x => %#x)", i,rawstepsize,stepsize); POPCOLOR(); marker_offset++; continue; break; } stepsize <<= 11; if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c."); chpr += printf("qcd.Stepsize[%d]",i); } if((PRINT_VALUE)) chpr += printf(" = %#x -> %u",rawstepsize,stepsize); marker_offset++; } else { stepsize = read_ushort(inptr,TIFF_MOTOROLA,marker_offset); marker_offset += 2; if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("JP2.jp2c.qcd."); chpr += printf("Stepsize[%d]",i); } if((PRINT_VALUE)) chpr += printf(" = %u",stepsize); } } if(!(LIST_MODE)) { chpr = newline(chpr); print_tag_address(SECTION|ENTRY,marker_offset - 1,indent,"@"); chpr += printf(" ",tag,name); } if(marker_offset > max_offset) printred(" READ PAST END OF BOX"); chpr = newline(chpr); return(max_offset); } exifprobe-2.0.1+git20170416-3c2b76/maker_nikon.c0000644000000000000000000014365013074742216017163 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_nikon.c,v 1.30 2005/07/24 22:56:26 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Nikon camera maker-specific routines. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Much of the information coded here is due to TsuruZoh Tachibanaya */ /* at: */ /* http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html */ /* and Max Lyons (E990 data) at: */ /* http://www.tawbaware.com/ */ /* Some information is taken from Eugene Crosser's "photopc" program: */ /* http://photopc.sourceforge.net/ */ /* (as modified by John Bowman: http://www.math.ualberta.ca/imaging/) */ /* The presence of JPEG thumbnails in TIFF format makernotes, */ /* extension of (some) E990 tags to the E995 and later models, the */ /* extra TIFF header in D100s, and the PrintIM data in some models, */ /* is due to examination (by earlier versions of this program) of */ /* images from my Nikon 990, and sample images obtained */ /* from: */ /* http://www.imaging-resource.com/ */ /* and */ /* http://www.dpreview.com/ */ /* April, 2005: */ /* Much of the new information for later model Nikons is taken from */ /* information provided by a Phil Harvey (author of 'exiftool') at: */ /* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/index.html */ /* and/or Evan Hunter ("The PHP JPEG Metadata Toolkit"), at: */ /* http://www.ozhiker.com/electronics/pjmt/jpeg_info/nikon_mn.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id nikon_model_id[]; /* Find the identifying number assigned to known Nikon camera models. */ /* This number is used to dispatch print and interpret routines */ /* apporopriate to the current image. At the moment, the "software" */ /* string is not used. */ int nikon_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &nikon_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Determine and set note version from detected scheme. */ /* Notes with ID scheme use tagset 1, offset routine 1, interp 1 */ /* Notes with Plain and ID/TIFFhdr use tagset 2, offset 2, interp 2 */ /* first tag is also distinctive (v2 has 0x1 (UNDEFINED count 4, */ /* ascii version), v1 has 0x2 (ASCII count 6, "08.00") although TIFF */ /* files will have a thumbnail (0x100) which displaces the first tag */ /* (placed out of numerical sort order). */ /* For now, it does not seem necessary to check first tag. */ int set_nikon_noteversion() { struct maker_scheme *scheme; int noteversion = 0; int tagset = 0; scheme = retrieve_makerscheme(); if(scheme->note_version <= 0) { noteversion = -1; tagset = -1; switch(scheme->scheme_type) { case HAS_ID_SCHEME: tagset = 1; noteversion = 1; break; case PLAIN_IFD_SCHEME: case HAS_ID_PLUS_TIFFHDR_SCHEME: tagset = 2; noteversion = 2; break; case UNKNOWN_SCHEME: break; default: break; } setnotetagset(tagset); setnoteversion(noteversion); } else noteversion = scheme->note_version; return(noteversion); } void print_nikon_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 1: print_value(entry_ptr,PREFIX); nikon1_interpret_value(entry_ptr); break; case 2: print_value(entry_ptr,PREFIX); nikon2_interpret_value(entry_ptr); break; default: print_value(entry_ptr,PREFIX); break; } } } void print_nikon_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) { int noteversion = 0; char *nameoftag; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 1: nikon1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case 2: nikon2_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); nameoftag = maker_tagname(entry_ptr->tag,make,model); nikon2_interpret_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name, nameoftag,indent); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix, indent,make,model,at_offset); break; } } } void nikon1_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) { unsigned long max_offset = 0; unsigned long value_offset; unsigned long count; unsigned long dumplength; unsigned short marker; int status = 0; int chpr = 0; char *nameoftag; char *fulldirname = NULL; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0100: /* Jpeg Thumbnail */ if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix); chpr += printf("# Start of JPEG Thumbnail from MakerNote"); chpr += printf(" length %lu",count); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%-9lu",value_offset,count); else chpr += printf(":%-9lu", count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); max_offset = process_jpeg_segments(inptr,value_offset,marker, count,summary_entry,fulldirname, prefix,indent+SMALLINDENT); if(at_offset) { if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1, indent,"-"); chpr += printf("# End of JPEG Thumbnail from MakerNote"); chpr += printf(" length %ld",count); if((PRINT_ENTRY) && !(PRINT_VALUE)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_IFD; summary_entry->subfiletype = THUMBNAIL_TYPE; } } /* make certain we're at the end */ clearerr(inptr); fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0f00: /* Data */ if(at_offset && (PRINT_ENTRY)) { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,25," : ",make,model); chpr += printf("length %-9lu # UNDEFINED", count); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,count); else chpr += printf(":%lu", count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } if(Max_undefined == 0) { if(chpr) printred(" (not dumped, use -U)"); } else { if((Max_undefined == DUMPALL) || (Max_undefined > count)) dumplength = count; else dumplength = Max_undefined; chpr = newline(chpr); hexdump(inptr,value_offset,count,dumplength,12, indent,SUBINDENT); chpr = newline(1); } /* make certain we're at the end */ fseek(inptr,value_offset + count,SEEK_SET); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } void nikon2_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) { unsigned long max_offset = 0; unsigned long value_offset; unsigned long count; unsigned long dumplength; unsigned long orig_print_options; unsigned short marker; char *nameoftag; char *fulldirname = NULL; int status = 0; int chpr = 0; int ifdnum = -1; int subifdnum = -1; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0011: /* "NikonPreviewImage" */ if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix); chpr += printf("# Start of Nikon Preview Image SubIFD from MakerNote"); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",value_offset); } chpr = newline(chpr); if(summary_entry) { ifdnum = summary_entry->ifdnum; subifdnum = summary_entry->subifdnum; } value_offset = process_tiff_ifd(inptr,byteorder,entry_ptr->value, fileoffset_base,0,summary_entry,fulldirname, MAKER_SUBIFD,ifdnum,subifdnum, indent+SMALLINDENT); if(at_offset && (PRINT_SECTION)) { chpr = newline(chpr); if(value_offset == 0) PUSHCOLOR(RED); print_tag_address(VALUE_AT_OFFSET,value_offset - 1, indent,"-"); if(value_offset == 0) POPCOLOR(); chpr += printf("# End of Nikon Preview Image SubIFD from MakerNote"); if(value_offset == 0) printred(" (INVALID)"); } if(summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNSUBIFD; summary_entry->datatype = MAKER_SUBIFD; summary_entry->subfiletype = REDUCED_RES_TYPE; } } break; case 0x0100: /* Jpeg Thumbnail */ if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix); chpr += printf("# Start of JPEG Thumbnail from MakerNote"); chpr += printf(" length %lu",count); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,count); else chpr += printf(":%lu", count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); max_offset = process_jpeg_segments(inptr,value_offset,marker, count,summary_entry,fulldirname, prefix,indent+SMALLINDENT); #if 0 /* an alternate place to look */ if((status = jpeg_status(status)) == JPEG_NO_SOI) { marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset - fileoffset_base); max_offset = process_jpeg_segments(inptr,value_offset - fileoffset_base, marker,count,summary_entry, prefix,indent+SMALLINDENT); if(max_offset) value_offset -= fileoffset_base; } #endif if(at_offset) { if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1, indent,"-"); chpr += printf("# End of JPEG Thumbnail from MakerNote"); chpr += printf(" length %lu",count); if((PRINT_ENTRY) && !(PRINT_VALUE)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_IFD; summary_entry->subfiletype = THUMBNAIL_TYPE; } } /* make certain we're at the end unless 'inptr' bad */ clearerr(inptr); fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0e00: /* PrintIM (Epson Print Image matching) */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); chpr = newline(chpr); } process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent); break; case 0x0010: /* Data */ if(at_offset && (PRINT_ENTRY)) { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,25," : ",make,model); chpr += printf("length %-9lu # UNDEFINED", count); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,count); else chpr += printf(":%lu",count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } if(Max_undefined == 0) { if(chpr) printred(" (not dumped, use -U)"); } else { if((Max_undefined == DUMPALL) || (Max_undefined > count)) dumplength = count; else dumplength = Max_undefined; chpr = newline(chpr); hexdump(inptr,value_offset,count,dumplength,12, indent,SUBINDENT); chpr = newline(1); } /* make certain we're at the end */ fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0097: /* Color Balance ???? */ /* Most models show this as an UNDEFINED section; the */ /* SQ provides it as ASCII, with the value an "array" */ /* of ascii strings (including newlines). Can these */ /* both have the same function? */ if(entry_ptr->value_type == UNDEFINED) { #if 1 if(at_offset && (PRINT_ENTRY)) /* PRINT_VALUE? */ { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,MAKERTAGWIDTH," = ",make,model); } if(at_offset && (PRINT_VALUE) && (PRINT_VALUE_AT_OFFSET)) nikon_colorbalance(inptr,entry_ptr,byteorder,fileoffset_base,indent); else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%-9lu",value_offset,count); else chpr = printf("length %-9lu", entry_ptr->count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } #else print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix, indent,make,model,at_offset); #endif } else { /* This is an unpleasant hack to show all of the */ /* null-separated strings, even in LIST mode, */ /* where IGNORE_LENGTH is usually on. */ orig_print_options = Print_options; Print_options &=~(PRINT_ASCII_IGNORE_LENGTH); print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix, indent,make,model,at_offset); Print_options = orig_print_options; } break; case 0x008c: /* NEFDecodeTable1 */ case 0x0096: /* NEFDecodeTable2 */ if((summary_entry) && (summary_entry->fileformat == FILEFMT_TIFF)) summary_entry->filesubformat |= FILESUBFMT_NEF; print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix, indent,make,model,at_offset); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix, indent,make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* The tagname routine is the first place in the code path which */ /* requires knowledge of the note version. If the version is not */ /* given in the model table (e.g. the model is unknown), then switch */ /* code in find_maker_scheme() should have set it. This routine */ /* repeats the check for non-zero noteversion and is prepared to set */ /* the noteversion first time through, but should never need to do */ /* so. Noteversion should always be non-zero; it should be set to -1 */ /* if generic processing is required. */ char * maker_nikon_tagname(unsigned short tag,int model) { char *tagname = CNULL; int noteversion = 0; if((noteversion = getnoteversion()) == 0) noteversion = set_nikon_noteversion(); switch(noteversion) { case 1: tagname = maker_nikon1_tagname(tag,model); break; case 2: tagname = maker_nikon2_tagname(tag,model); break; default: break; } return(tagname); } /* Tags for the older cameras. */ char * maker_nikon1_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0003: tagname = "Quality"; break; case 0x0004: tagname = "ColorMode"; break; case 0x0005: tagname = "ImageAdjustment"; break; case 0x0006: tagname = "ISOSetting"; break; case 0x0007: tagname = "WhiteBalance"; break; case 0x0008: tagname = "Focus"; break; case 0x000a: tagname = "DigitalZoom"; break; case 0x000b: tagname = "LensConverter"; break; case 0x0100: tagname = "JpegThumbnail"; break; case 0x0f00: tagname = "Data"; break; default: break; } setnotetagset(1); return(tagname); } char * maker_nikon2_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0001: tagname = "Version"; break; case 0x0002: tagname = "ISO"; break; case 0x0003: tagname = "ColorMode"; break; case 0x0004: tagname = "Quality"; break; case 0x0005: tagname = "WhiteBalance"; break; case 0x0006: tagname = "ImageSharpening"; break; case 0x0007: tagname = "FocusMode"; break; case 0x0008: tagname = "FlashSetting"; break; case 0x0009: tagname = "FlashType"; break; /* Harvey */ #if 0 case 0x000a: break; /* WhiteBal Bias ??? */ case 0x000d: break; /* WhiteBal coeff ??? */ case 0x000e: break; /* ISOSel? ??? */ #endif case 0x000b: tagname = "WhiteBalanceBias"; break; case 0x000c: tagname = "WhiteBalance"; break; case 0x000f: tagname = "ISOSelection"; break; case 0x0010: tagname = "Data"; break; case 0x0011: tagname = "NikonPreviewImage"; break; case 0x0012: tagname = "FlashExposureCompensation*"; break; case 0x0013: tagname = "ISOSetting"; break; case 0x0016: tagname = "ImageBoundary"; break; case 0x0018: tagname = "FlashExposureBracketValue*"; break; case 0x0019: tagname = "ExposureBracketValue"; break; case 0x0080: tagname = "ImageAdjustment"; break; case 0x0081: tagname = "ToneCompensation"; break; case 0x0082: tagname = "LensAdapter"; break; case 0x0083: tagname = "LensType"; break; case 0x0084: tagname = "LensInfo"; break; case 0x0085: tagname = "ManualFocusDistance"; break; case 0x0086: tagname = "DigitalZoom"; break; case 0x0087: tagname = "FlashMode*"; break; case 0x0088: tagname = "AutoFocusArea*"; break; case 0x0089: tagname = "ShootingMode"; break; case 0x008c: tagname = "NEFDecodeTable1"; break; case 0x008d: tagname = "ColorMode"; break; case 0x008f: tagname = "SceneMode"; break; case 0x0090: tagname = "Lightsource"; break; case 0x0092: tagname = "HueAdjustment"; break; case 0x0094: tagname = "Saturation"; break; case 0x0095: tagname = "NoiseReduction"; break; case 0x0096: tagname = "NEFDecodeTable2"; break; case 0x0097: tagname = "ColorBalance**"; break; case 0x0099: tagname = "NEFThumbnailSize*"; break; case 0x00a0: tagname = "SerialNumber"; break; case 0x00a7: tagname = "ShutterCount"; break; case 0x00a9: tagname = "ImageOptimization"; break; case 0x00aa: tagname = "Saturation"; break; case 0x00ab: tagname = "VariProgram"; break; case 0x0100: tagname = "JpegThumbnail"; break; case 0x0e00: tagname = "PrintIM"; break; case 0x0e0e: tagname = "NikonCaptureOffsets"; break; default: break; } setnotetagset(2); return(tagname); } void nikon1_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; switch(entry_ptr->tag) { case 0x0003: /* Quality */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("VGA Basic - 640x480 (1/16)"); break; case 2: chpr += printf("VGA Normal - 640x480 (1/8)"); break; case 3: chpr += printf("VGA Fine - 640x480 (1/4)"); break; case 4: chpr += printf("XGA Basic - 1024x768 (1/16)"); break; case 5: chpr += printf("XGA Normal - 1024x768 (1/8)"); break; case 6: chpr += printf("XGA Fine - 1024x768 (1/4)"); break; case 7: chpr += printf("SXGA Basic*"); break; case 8: chpr += printf("SXGA Normal*"); break; case 9: chpr += printf("SXGA Fine*"); break; case 10: chpr += printf("Basic - 1600x1200 (1/16)"); break; case 11: chpr += printf("Normal - 1600x1200 (1/8)"); break; case 12: chpr += printf("Fine - 1600x1200 (1/4)"); break; case 20: chpr += printf("Hi - 1600x1200"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0004: /* Color Mode */ print_startvalue(); if(entry_ptr->value == 1) chpr += printf("color"); else if(entry_ptr->value == 2) chpr += printf("monochrome"); else printred("undefined"); print_endvalue(); break; case 0x0005: /* Image Adjustment */ print_startvalue(); /* The data from Crosser's "photopc" conflicts with that */ /* from Tachibanaya for contrast and brightness (they're */ /* swapped). These are Tachibanaya's values. Somebody please */ /* tell me which is right. */ switch(entry_ptr->value) { case 0: chpr += printf("Standard"); break; case 1: chpr += printf("Brightness+?"); /* ###%%% Contrast? */ break; case 2: chpr += printf("Brightness-?"); /* ###%%% Contrast? */ break; case 3: chpr += printf("Contrast+?"); /* ###%%% Brightness? */ break; case 4: chpr += printf("Contrast-?"); /* ###%%% Brightness? */ break; case 5: /* Is this right? */ chpr += printf("Auto?"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0006: /* CCD Sensitivity (ISO) */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("80"); break; case 2: chpr += printf("160"); break; case 4: chpr += printf("320"); break; case 5: chpr += printf("100"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0007: /* White Balance */ print_startvalue(); /* These values, taken from "photopc", conflict with */ /* values given by Tachibanaya */ switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Preset"); break; case 2: chpr += printf("Daylight"); break; case 3: chpr += printf("Incandescent"); break; case 4: chpr += printf("Fluorescent"); break; case 5: chpr += printf("Cloudy"); break; case 6: chpr += printf("Flash"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x000b: /* Lens Converter */ print_startvalue(); if(entry_ptr->value == 0) chpr += printf("none"); else if(entry_ptr->value == 1) chpr += printf("fisheye"); else printred("undefined"); print_endvalue(); break; default: break; } setcharsprinted(chpr); } void nikon2_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; switch(entry_ptr->tag) { case 0x0002: /* CCD Sensitivity (ISO) */ print_startvalue(); if(entry_ptr->value & 0xffff) chpr += printf("%u",(unsigned short)(entry_ptr->value & 0xffff)); else if((entry_ptr->value >> 16) & 0xffff) chpr += printf("%u",(unsigned short)((entry_ptr->value >> 16) & 0xffff)); else chpr += printf("Auto"); print_endvalue(); break; case 0x000b: case 0x000d: case 0x000e: case 0x0011: case 0x008a: case 0x008b: case 0x0092: case 0x0094: /* print_startvalue(); printred("unknown"); print_endvalue(); */ break; case 0x0087: /* Flash Used */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("did not fire"); break; case 8: chpr += printf("fired, commander mode"); break; case 9: chpr += printf("fired, TTL mode"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0088: /* Auto Focus Position */ #if 0 print_startvalue(); /* updated from PHP Metadata Toolkit & exiftool */ /* ###%%% don't think these are right: */ /* The two sources conflict. */ /* AFPosition can be tied to metering, which isn't */ /* mentioned... There are 4 bytes here that might have */ /* significance. Hold off on this. Asterisk the tag. */ switch(entry_ptr->value & 0xff) { case 0: chpr += printf("Single area - "); break; case 0x1: chpr += printf("Dynamic area - "); break; case 0x2: chpr += printf("Closest subject - "); break; default: printred("undefined area -"); break; } #endif /* It appears that this byte describes autofocus */ /* position. */ /* It is not clear what the other bytes are for. */ /* Possibilities are: */ /* metering lock to the focus area */ /* auto vs manual focus area select or "off" */ /* continuous AF vs single AF */ /* auto focus on closest subject */ /* actual area used */ /* ...what *is* "dynamic area"? */ print_startvalue(); switch((entry_ptr->value >> 8) & 0xff) { case 0: chpr += printf("Center"); break; case 0x1: chpr += printf("Top"); break; case 0x2: chpr += printf("Bottom"); break; case 0x3: chpr += printf("Left"); break; case 0x4: chpr += printf("Right"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0089: /* Shooting Mode */ print_startvalue(); switch(entry_ptr->value & 0x3) { case 0: chpr += printf("single frame"); break; case 1: chpr += printf("continuous"); break; case 2: chpr += printf("timer"); break; case 3: chpr += printf("remote timer?"); break; case 4: chpr += printf("remote?"); break; default: chpr += printf("(undefined)"); break; } if(entry_ptr->value & 0x8) chpr += printf(", bracketing on"); else chpr += printf(", bracketing off"); if(entry_ptr->value & 0x20) chpr += printf(", WB bracketing on"); else chpr += printf(", WB bracketing off"); print_endvalue(); break; default: break; } setcharsprinted(chpr); } void nikon2_interpret_offset_makervalue(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base, char *parent_name,char *nameoftag,int indent) { unsigned long offset; int chpr = 0; char *fullnameoftag = CNULL; int entrywidth; double minfl,maxfl,minmaxap,maxmaxap; unsigned long num,denom; if(entry_ptr && (PRINT_VALUE)) { fullnameoftag = splice(parent_name,".",nameoftag); offset = entry_ptr->value + fileoffset_base; switch(entry_ptr->tag) { case 0x0084: /* Assume no read errors here, since it's been */ /* read once before; if there are, we'll hear */ /* about it (but do nothing). */ num = read_ulong(inptr,byteorder,offset); denom = read_ulong(inptr,byteorder,HERE); if(num == 0UL) minfl = 0.0; else minfl = (double)((double)num/(double)denom); num = read_ulong(inptr,byteorder,HERE); denom = read_ulong(inptr,byteorder,HERE); if(num == 0UL) maxfl = 0.0; else maxfl = (double)((double)num/(double)denom); num = read_ulong(inptr,byteorder,HERE); denom = read_ulong(inptr,byteorder,HERE); if(num == 0UL) minmaxap = 0.0; else minmaxap = (double)((double)num/(double)denom); num = read_ulong(inptr,byteorder,HERE); denom = read_ulong(inptr,byteorder,HERE); if(num == 0UL) maxmaxap = 0.0; else maxmaxap = (double)((double)num/(double)denom); if((PRINT_SECTION)) { chpr = printf(" = {"); chpr = newline(chpr); indent += MEDIUMINDENT + MAKERTAGWIDTH + 3; print_tag_address(ENTRY,offset,indent,"@"); } else { chpr = newline(chpr); print_tag_address(ENTRY,offset,indent,"@"); } if(PRINT_ENTRY) { entrywidth = sizeof("MaxApertureAtMinFocalLength"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth,"MinFocalLength"); } if((PRINT_VALUE)) { print_startvalue(); printf("%.0f mm",minfl); print_endvalue(); chpr = newline(chpr); } print_tag_address(ENTRY,offset + 8,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth,"MaxFocalLength"); } if((PRINT_VALUE)) { print_startvalue(); chpr += printf("%.0f mm",maxfl); print_endvalue(); chpr = newline(chpr); } print_tag_address(ENTRY,offset + 16,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth, "MaxApertureAtMinFocalLength"); } if((PRINT_VALUE)) { /* ###%%% APEX? */ chpr += printf(" = %3.2f APEX",minmaxap); minmaxap = pow(2.0,minmaxap/2.0); print_startvalue(); chpr += printf("f%.1f",minmaxap); print_endvalue(); chpr = newline(chpr); } print_tag_address(ENTRY,offset + 24,indent,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth, "MaxApertureAtMaxFocalLength"); } if((PRINT_VALUE)) { /* ###%%% APEX? */ chpr += printf(" = %3.2f APEX",maxmaxap); maxmaxap = pow(2.0,maxmaxap/2.0); print_startvalue(); chpr += printf("f%.1f",maxmaxap); print_endvalue(); if(PRINT_SECTION) { chpr = newline(chpr); print_tag_address(ENTRY,offset + 31,0,"@"); putindent(indent - MEDIUMINDENT); chpr = printf("}"); } } } break; default: break; } } setcharsprinted(chpr); } /* ###%%% Phil Harvey's ExifTool pages seem to indicate that these are tables of 'rational16' values after an initial 4 character identifier, except that the values for identifier 0100 are 'int16'. I dunno; the values I see do not look reasonable for color balance values (i.e. 'Infinity', '17.2143', ...). There must be more than he's saying. Exiftool picks out two values at model-dependent offsets for red and blue balance, but doesn't address the rest of the section. Print those values here, then call dumpsection so that users can look at the rest. */ void nikon_colorbalance(FILE *inptr,struct ifd_entry *entry_ptr,unsigned short byteorder, unsigned long fileoffset_base,int indent) { unsigned long offset; unsigned short numerator,denominator; double value; int chpr = 0; int unknown = 0; char *id; if(entry_ptr && (PRINT_VALUE)) { offset = entry_ptr->value + fileoffset_base; #if 1 id = read_string(inptr,offset,4); chpr += printf("'ID:"); show_string(id,4,1); if(strncmp(id,"0100",4) == 0) offset += 72; else if(strncmp(id,"0102",4) == 0) offset += 10; else if(strncmp(id,"0103",4) == 0) offset += 20; else ++unknown; if(!unknown) { if((PRINT_SECTION)) { indent += MAKERTAGWIDTH + 3; chpr += printf("' = {"); chpr = newline(chpr); print_tag_address(ENTRY,offset,indent + MEDIUMINDENT,"?"); chpr += printf("RedBalance** = "); numerator = read_ushort(inptr,byteorder,offset); offset += 2; if(strncmp(id,"0100",4)) { denominator = read_ushort(inptr,byteorder,offset); offset += 2; } else denominator = 256; value = (double)numerator / (double)denominator; chpr += printf("%.6f (%u/%u)",value,numerator,denominator); chpr = newline(chpr); print_tag_address(ENTRY,offset,indent + MEDIUMINDENT,"?"); chpr += printf("BlueBalance** = "); numerator = read_ushort(inptr,byteorder,offset); offset += 2; if(strncmp(id,"0100",4)) { denominator = read_ushort(inptr,byteorder,offset); offset += 2; } else denominator = 256; value = (double)numerator / (double)denominator; chpr += printf("%.6f (%u/%u)",value,numerator,denominator); chpr = newline(chpr); print_tag_address(ENTRY,offset + entry_ptr->count - 1,indent,"?"); chpr += printf("} = {"); indent -= MAKERTAGWIDTH + 3; } chpr = newline(chpr); } else { chpr += printf(" = unknown = {"); chpr = newline(chpr); } offset = entry_ptr->value + fileoffset_base; PUSHCOLOR(RED); dumpsection(inptr,offset,entry_ptr->count,indent); POPCOLOR(); print_tag_address(ENTRY,offset + entry_ptr->count - 1,indent,"?"); chpr += printf("}"); } #else /* This just prints everything after the idstring as short rationals, */ /* in the same fashion as print_ushort(); */ count = entry_ptr->count / 4; /* two unsigned shorts */ print_ascii(inptr,4,offset); count--; offset += 4; chpr = newline(chpr); for(i = 0; i < count; ++i) { int rowlength; if((count -i) >= 4) rowlength = 4; else rowlength = count - i; print_tag_address(ENTRY,offset,indent,"?"); for(j = 0; j < rowlength; ++j,++i) { numerator = read_ushort(inptr,byteorder,offset); denominator = read_ushort(inptr,byteorder,HERE); offset += 4; if(j) chpr += printf(", "); if(j == 2) chpr += printf(" "); if(numerator == 0) chpr += printf("0 "); else if(denominator == 0) chpr += printf("Inf "); else { value = (double)numerator / (double)denominator; chpr += printf("%.4f",value); } } chpr = newline(chpr); } } if(Max_undefined > 0) { unsigned long dumplength; offset = entry_ptr->value + fileoffset_base; if((Max_undefined == DUMPALL) || (Max_undefined > entry_ptr->count)) dumplength = entry_ptr->count; else dumplength = Max_undefined; chpr = newline(chpr); hexdump(inptr,offset,entry_ptr->count,dumplength,16, 4,SUBINDENT); chpr = newline(1); } #endif setcharsprinted(chpr); } /* Mark items (usually LONG) which should be treated as offsets. */ int maker_nikon_value_is_offset(struct ifd_entry *entry_ptr,int model) { int is_offset = 0; /* There is currently no need for a switch on noteversion */ if(entry_ptr) { switch(entry_ptr->tag) { case 0x0011: is_offset = 1; break; case 0x0097: is_offset = 1; break; case 0x0100: is_offset = 1; break; default: break; } } return(is_offset); } exifprobe-2.0.1+git20170416-3c2b76/CAMERA_makes_and_models0000644000000000000000000002464613074742216020745 0ustar rootrootThe full list of "known" camera models is available using the '-C+' option of exifprobe (see the manual page for details) and is included below for reference. Most of the images used in testing exifprobe are from the following sites: http://www.imaging-resource.com/ http://www.dpreview.com/ http://www.steves-digicams.com/ http://www.exif.org/samples.html http://www.jojotsch.de/downloads/jojothumb/ http://www.casio.co.jp/QV/Info/ http://drewnoakes.com/code/exif/exifImages/ http://www.pbase.com/sigmasd9/x3f_raw_files The following model appears as a 'Type' in an APP12 section: Agfa Gevaert model SR84 The following models are due to user reports, but I do not have the specific "Model" strings for the cameras, so they are not included in the list produced by '-C+'. Canon model Canon PowerShot A40 OLYMPUS OPTICAL CO.,LTD model C740UZ FUJIFILM model 1300 Motorola Model A920 (camera phone, JFIF only) Note that it is not essential that a camera model is recognized in order for exifprobe to produce useful output. In some cases MakerNote recognition or expansion may not succeed for unrecognized models. =-=-==-=-==-=-==-=-==-=-==-=-==-=-==-=-==-=-==-=-==-=-=--=-=-=-=-=-= The numbers in square brackets following 'makes' in the list are the numbers assigned internally to that make by exifprobe. The numbers in square brackets following 'models' are the model number and 'noteversion' assigned internally to that model. These numbers will not normally be of particular interest, but do serve to indicate the number of noteversions supported for a model, and can be of use to advanced users. The names given are the precise strings included in the 'Make' and 'Model' tags of TIFF files and the included TIFF IFDs of other image file formats. Some file formats do not include TIFF or EXIF sections. X3F files use a "property list" containing "CAMMANUF" and "CAMMODEL" properties. JP2 files do not normally contain this information in a specific location, although some files do contain TIFF IFDs embedded in "uuid" boxes, and other boxes are available which could be used to identify make and model. No camera or device I know of yet produces JP2, so... =-=-==-=-==-=-==-=-==-=-==-=-==-=-==-=-==-=-==-=-==-=-=--=-=-=-=-=-= Camera Makes: Agfa Gevaert [1] SR841 [ 1,1] Asahi Optical Co.,Ltd [2] PENTAX Optio 330 [ 1,1] PENTAX Optio330RS [ 2,2] PENTAX Optio 430 [ 3,1] PENTAX Optio430RS [ 4,2] PENTAX Optio 550 [ 5,3] PENTAX Optio 750Z [ 6,3] PENTAX Optio S [ 7,3] PENTAX Optio S5i [ 8,3] PENTAX *ist D [ 9,3] PENTAX *ist DS [10,3] Canon [3] Canon DIGITAL IXUS [ 1,1] Canon EOS-1D [ 2,5] Canon EOS-1D Mark II [ 3,5] Canon EOS-1DS [ 4,5] Canon EOS-1Ds Mark II [ 5,5] Canon EOS 10D [ 6,3] Canon EOS 20D [ 7,4] Canon EOS D30 [ 8,2] Canon EOS D60 [ 9,1] Canon EOS 350 [10,1] Canon EOS DIGITAL REBEL [11,1] Canon PowerShot A400 [13,1] Canon PowerShot A5 [14,1] Canon PowerShot G2 [15,1] Canon PowerShot Pro1 [16,1] Canon PowerShot S70 [17,1] CASIO [4] QV-2000UX [ 1,1] QV-3000EX [ 2,1] QV-4000 [ 3,1] QV-8000SX [ 4,1] QV-R51 [ 5,2] EX-P505 [ 6,2] EX-P600 [ 7,2] EX-P700 [ 8,2] EX-S100 [ 9,2] EX-Z55 [10,2] GV-20 [11,2] Eastman Kodak Company [5] DC200 Zoom (V05.00) [ 1,0] DC210 Zoom (V05.00) [ 2,0] DCS720X [ 3,0] DCS760C [ 4,0] Kodak DC120 ZOOM Digital Camera [ 5,0] Kodak DC240 ZOOM Digital Camera [ 6,0] Kodak DC4800 ZOOM Digital Camera [ 7,0] KODAK DC25 DIGITAL CAMERA [ 8,0] KODAK LS443 ZOOM DIGITAL CAMERA [ 9,0] Kodak Digital Science DC50 Zoom [10,0] Fujifilm [6] DX-10 [ 1,1] FUJIFILM FinePixA204 [ 2,1] FinePix40i [ 3,1] FinePix4900ZOOM [ 4,1] FinePix E550 [ 5,1] FinePix F601 ZOOM [ 6,1] FinePixS1Pro [ 7,1] FinePixS2Pro [ 8,1] FinePix S20Pro [ 9,1] FinePix S5000 [10,1] MX-1700ZOOM [11,1] SP-2000 [12,0] Hewlett-Packard [7] HP PhotoSmart C912 [ 1,0] HP PhotoSmart R707 [ 2,0] Konica Minolta Camera [8] DiMAGE 5 [ 1,1] DiMAGE 7 [ 2,1] DiMAGE 7Hi [ 3,1] DiMAGE 7i [ 4,1] DiMAGE A1 [ 5,1] DiMAGE A2 [ 6,1] DiMAGE A200 [ 7,1] DiMAGE EX [ 8,1] DiMAGE F100 [ 9,1] DiMAGE F200 [10,1] DiMAGE F300 [11,1] DiMAGE S404 [12,1] DiMAGE S414 [13,1] DiMAGE X [14,1] DiMAGE X20 [15,1] DYNAX 7D [16,1] MAXXUM 7D [17,1] Konica Corporation [9] Konica Digital Camera Q-M100 [ 1,1] Konica Digital Camera KD-400Z [ 2,1] Kyocera [10] FC-S3 [ 1,1] Finecam S5 [ 2,1] Leica [11] DIGILUX 2 [ 1,0] digilux 4.3 [ 2,1] R9 - Digital Back DMR [ 3,0] Minolta [8] DiMAGE 5 [ 1,1] DiMAGE 7 [ 2,1] DiMAGE 7Hi [ 3,1] DiMAGE 7i [ 4,1] DiMAGE A1 [ 5,1] DiMAGE A2 [ 6,1] DiMAGE A200 [ 7,1] DiMAGE EX [ 8,1] DiMAGE F100 [ 9,1] DiMAGE F200 [10,1] DiMAGE F300 [11,1] DiMAGE S404 [12,1] DiMAGE S414 [13,1] DiMAGE X [14,1] DiMAGE X20 [15,1] DYNAX 7D [16,1] MAXXUM 7D [17,1] Panasonic [14] DMC-FX7 [ 1,1] DMC-FZ1 [ 2,1] DMC-FZ2 [ 3,1] DMC-FZ3 [ 4,1] DMC-FZ10 [ 5,1] DMC-FZ15 [ 6,1] DMC-FZ20 [ 7,1] DMC-LC5 [ 8,1] DMC-LC33 [ 9,1] DMC-LC40 [10,1] DMC-LC43 [11,1] Pentax Corporation [15] PENTAX Optio 330 [ 1,1] PENTAX Optio330RS [ 2,2] PENTAX Optio 430 [ 3,1] PENTAX Optio430RS [ 4,2] PENTAX Optio 550 [ 5,3] PENTAX Optio 750Z [ 6,3] PENTAX Optio S [ 7,3] PENTAX Optio S5i [ 8,3] PENTAX *ist D [ 9,3] PENTAX *ist DS [10,3] Nikon Corporation [12] E700 [ 1,1] E775 [ 2,2] E800 [ 3,1] E885 [ 4,2] E900 [ 5,1] E950 [ 6,1] E990 [ 7,2] E995 [ 8,2] E3700 [ 9,2] E5000 [10,2] E5200 [11,2] E5700 [12,2] E8700 [13,2] E8800 [14,2] NIKON D1 [15,2] NIKON D1X [16,2] NIKON D70 [17,2] NIKON D100 [18,2] NIKON D2H [19,2] NIKON D2X [20,2] SQ [21,2] Olympus Optical Co.,Ltd [13] C700UZ [ 1,1] C70Z,C7000Z [ 2,1] C960Z [ 3,1] C2040Z [ 4,1] C2500L [ 5,1] C3030Z [ 6,1] C3040Z [ 7,1] C8080WZ [ 8,1] E-1 [ 9,1] E-300 [10,1] u40D,S500,uD500 [11,1] Ricoh [16] RDC-5300 [ 1,0] RDC-6000 [ 2,0] Sanyo Electric Co.,Ltd. [17] SR6 [ 1,1] SX113 [ 2,1] SX215 [ 3,1] Seiko Epson Corp. [18] PhotoPC 850Z [ 1,1] PhotoPC 3000Z [ 2,1] PhotoPC 3100Z [ 3,1] L-500V [ 4,1] Sigma [19] SIGMA SD9 [ 1,1] SIGMA SD10 [ 2,1] Sony [20] CYBERSHOT [ 1,1] DIGITALMAVICA [ 2,1] DSC-D700 [ 3,1] DSC-V3 [ 4,1] MAVICA [ 5,1] Toshiba [21] PDR-3300 [ 1,1] Traveler Optical Co,Ltd [22] SX330Z [ 1,0] exifprobe-2.0.1+git20170416-3c2b76/jp2_extern.h0000644000000000000000000000646413074742216016754 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: jp2_extern.h,v 1.3 2005/07/24 21:30:11 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef JP2_EXTERN_INCLUDED #define JP2_EXTERN_INCLUDED extern void print_jp2type(unsigned long,int); extern void print_jp2box(FILE *,struct jp2box *,int); extern int print_jp2_header(struct fileheader *,unsigned long); extern int list_jp2box(FILE *,struct jp2box *,char *,int,int); extern char *jp2000tagname(unsigned short); extern struct jp2box *read_jp2box(FILE *,unsigned long); extern unsigned long process_jp2(FILE *,unsigned long,struct image_summary *, char *,int); extern unsigned long process_jp2_ftyp(FILE *,struct jp2box *, struct image_summary *,int); extern unsigned long process_jp2_jp2h(FILE *,struct jp2box *, struct image_summary *,int); extern unsigned long process_jp2_ihdr(FILE *,struct jp2box *, struct image_summary *,int); extern unsigned long process_jp2_uuid(FILE *,struct jp2box *, struct image_summary *,int); extern unsigned long process_jp2_uinf(FILE *,struct jp2box *, struct image_summary *,int); extern unsigned long process_jp2_jp2c(FILE *,struct jp2box *, struct image_summary *,int); extern unsigned long process_jp2_colr(FILE *,struct jp2box *,int); extern unsigned long process_jp2_res(FILE *,struct jp2box *,int); extern unsigned long process_jp2_xml(FILE *,struct jp2box *,int); extern unsigned long process_jp2_jp2i(FILE *,struct jp2box *,int); extern unsigned long process_jp2_ulst(FILE *,struct jp2box *,int); extern unsigned long process_jp2_de(FILE *,struct jp2box *,int); extern unsigned long process_jpeg2000_codestream(FILE *,unsigned long, unsigned long, struct image_summary *, int); extern unsigned long process_jpc_siz(FILE *,unsigned long,unsigned short, struct image_summary *, int); extern unsigned long process_jpc_cod(FILE *,unsigned long,unsigned short, struct image_summary *, int); extern unsigned long process_jpc_qcd(FILE *,unsigned long,unsigned short, struct image_summary *, int); #endif /* JP2_EXTERN_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/mrw_datadefs.h0000644000000000000000000000215213074742216017322 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: mrw_datadefs.h,v 1.1 2005/05/25 00:53:56 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef MRW_DATADEFSINCLUDED #define MRW_DATADEFSINCLUDED /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Minolta MRW-specific external definitions */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ struct mrw_header { unsigned long mrw_magic; unsigned long mrw_dataoffset; }; #endif /* MRW_DATADEFSINCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/pentax_datadefs.h0000644000000000000000000000270713074742216020022 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: pentax_datadefs.h,v 1.2 2005/06/21 15:19:20 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef PENTAX_DATADEFS_INCLUDED #define PENTAX_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id pentax_model_id[] = { { "PENTAX Optio 330 ",17, ASAHI_PENTAX330, 1, 1 }, { "PENTAX Optio330RS",18, ASAHI_PENTAX330RS, 2, 2 }, { "PENTAX Optio 430 ",17, ASAHI_PENTAX430, 1, 1 }, { "PENTAX Optio430RS",18, ASAHI_PENTAX430RS, 2, 2 }, { "PENTAX Optio 550",17, PENTAX_OPTIO550, 3, 3 }, { "PENTAX Optio 750Z",18, PENTAX_OPTIO750Z, 3, 3 }, { "PENTAX Optio S ",15, PENTAX_OPTIOS, 3, 3 }, { "PENTAX Optio S5i ",17, PENTAX_OPTIOS5i, 3, 3 }, { "PENTAX *ist D ",14, PENTAX_STARIST_D, 3, 3 }, { "PENTAX *ist DS ",15, PENTAX_STARIST_DS, 3, 3 }, { 0, 0, 0, 0, 0 } }; #endif /* PENTAX_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/minolta_datadefs.h0000644000000000000000000000337013074742216020163 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: minolta_datadefs.h,v 1.4 2005/07/24 21:15:46 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef MINOLTA_DATADEFS_INCLUDED #define MINOLTA_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id minolta_model_id[] = { { "DiMAGE 5", 9, MINOLTA_DIMAGE5, 1, 1 }, { "DiMAGE 7", 9, MINOLTA_DIMAGE7, 1, 1 }, { "DiMAGE 7Hi", 11, MINOLTA_DIMAGE7Hi, 1, 1 }, { "DiMAGE 7i", 10, MINOLTA_DIMAGE7i, 1, 1 }, { "DiMAGE A1", 10, MINOLTA_DIMAGEA1, 1, 1 }, { "DiMAGE A2", 10, MINOLTA_DIMAGEA2, 1, 1 }, { "DiMAGE A200", 12, MINOLTA_DIMAGEA200, 1, 1 }, { "DiMAGE EX", 10, MINOLTA_DIMAGEEX, 1, 1 }, { "DiMAGE F100", 12, MINOLTA_DIMAGEF100, 1, 1 }, { "DiMAGE F200", 12, MINOLTA_DIMAGEF200, 1, 1 }, { "DiMAGE F300", 12, MINOLTA_DIMAGEF300, 1, 1 }, { "DiMAGE S404", 12, MINOLTA_DIMAGES404, 1, 1 }, { "DiMAGE S414", 12, MINOLTA_DIMAGES414, 1, 1 }, { "DiMAGE X", 9, MINOLTA_DIMAGEX, 1, 1 }, { "DiMAGE X20", 11, MINOLTA_DIMAGEX20, 1, 1 }, { "DYNAX 7D", 9, MINOLTA_DYNAX7D, 1, 1 }, { "MAXXUM 7D", 10, MINOLTA_MAXXUM7D, 1, 1 }, { 0, 0, 0, 0, 0 } }; #endif /* MINOLTA_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/ciff_extern.h0000644000000000000000000000551713074742216017166 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: ciff_extern.h,v 1.3 2005/06/06 18:50:04 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef CIFF_EXTERN_INCLUDED #define CIFF_EXTERN_INCLUDED /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Canon CIFF-specific external definitions */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ extern char *cifftagname(unsigned short); extern int print_ciff_header(struct fileheader *,unsigned long); extern unsigned long process_ciff(FILE *,struct fileheader *,unsigned long, unsigned long,struct image_summary *, char *,int,int); extern unsigned long process_ciff_dir(FILE *,unsigned long,unsigned long, char *,char *,struct image_summary *, unsigned short,int,int); extern unsigned long process_ciff_direntry(FILE *,unsigned short,unsigned short, struct ciff_direntry *, unsigned long, char *,struct image_summary *,int,int); extern struct ciff_direntry *read_ciff_direntry(FILE *, struct ciff_direntry *, unsigned short,unsigned long); extern struct ciff_header *read_ciffheader(FILE *,unsigned short,unsigned long); extern void print_ciff_value(FILE *,struct ciff_direntry *,unsigned short, unsigned long,unsigned long, char *,struct image_summary *, int,int); extern void print_ciff_taginfo(struct ciff_direntry *,unsigned long); extern int is_compressed_crw(FILE *,unsigned long,unsigned long); extern unsigned long print_ciffinheapdata(FILE *,unsigned short,char *,char *, unsigned long, unsigned long, unsigned short,int); extern unsigned long print_ciffinrecdata(FILE *,unsigned short,char *, unsigned long, unsigned long, unsigned short,int); #endif /* CIFF_EXTERN_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/ciff.h0000644000000000000000000000222713074742216015574 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: ciff.h,v 1.1 2005/05/25 16:03:03 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef CIFF_INCLUDED #define CIFF_INCLUDED /* CIFF type and locacation masks and types */ #define CIFF_TYPEMASK 0x3fff #define CIFF_FORMATMASK 0x3800 #define CIFF_LOCATIONMASK 0xc000 #define CIFF_INHEAP 0x0000 #define CIFF_INREC 0x4000 #define CIFFTAGWIDTH 23 #define CIFF_MAXLEVELS 16 #include "ciff_datadefs.h" #include "cifftags.h" #include "ciff_extern.h" #endif /* CIFF_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/maker_generic.c0000644000000000000000000020311313074742216017450 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_generic.c,v 1.40 2005/07/24 21:34:37 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* "Generic" routines for makernotes which use TIFF IFD structure */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include #include "defs.h" #include "summary.h" #include "maker.h" #include "datadefs.h" #include "maker_datadefs.h" #include "camera_names.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" /* Read a makernote at the offset given in the passed maker_entry. */ /* Checks for data with a TIFF IFD structure at the makernote offset, */ /* possibly offset by a maker name string and/or a new TIFF header */ /* (e.g. some later Nikons). Notes which pass the test are scanned */ /* and printed. If the note is in IFD format but the maker is */ /* unknown, a "bare bones" entry will be printed, with tag numbers, */ /* type, etc. If the maker is known, tag names, undefined values and */ /* "interpretations" of the data may be printed. MakerNotes with */ /* unknown/non-ifd structures could be dispatched to specialized */ /* routines, but at this time I do not have information on any of */ /* those. Unknown notes (or notes with invalid IFD entries) can be */ /* dumped in hex/ascii by user option (-M). 'Undefined" data may be */ /* similarly dumped by the -U option, if maker-specific routines */ /* don't handle it. */ /* The return is the offset of the end of the note; if the note */ /* cannot be read, return is 0L. */ /* end_of_note: calculated from start offset and 'count' in parent */ /* entry */ /* max_value_offset: maximum offset reached by an entry value which */ /* begins within the note, as defined by the count. Used... */ /* max_end_offset: maximum offset reached by data referenced by any */ /* entry, even if 'outside' the note */ /* value_end_offset: maximum offset reached by the current entry's */ /* offset value */ /* max_in_note_tagoffset: the starting offset of the last tag value */ /* that begins within the note boundaries. */ /* min_out_of_note_tagoffset: the start offset of the first tag with */ /* value which starts beyond the end of the note. */ /* The only rule is that thre are no rules... */ unsigned long process_makernote(FILE *inptr,unsigned short byteorder, struct ifd_entry *maker_entry,unsigned long fileoffset_base, unsigned long max_offset,struct image_summary *summary_entry, char *parent_name,int indent) { struct ifd_entry *entry_ptr; struct maker_scheme *maker_scheme; unsigned long maker_offset = 0UL; unsigned long maker_count = 0UL; unsigned long max_value_offset = 0UL; unsigned long max_end_offset = 0UL; unsigned long value_end_offset = 0UL; unsigned long max_in_note_tagoffset = 0UL; unsigned long min_out_of_note_tagoffset = 0UL; unsigned long start_offset = 0UL; unsigned long dumplength = 0UL; unsigned long end_of_note = 0UL; unsigned long next_ifd_offset = 0UL; unsigned long current_offset; unsigned long start_entry_offset; unsigned long entry_offset,value_offset; char *prefix,*tprefix,*swname; char *nameoftag = CNULL; char *fulldirname = CNULL; int entry_num,num_entries,make,model; int tagindent = 0; int tagwidth = 0; int invalid = 0; int scheme_indent = 0; int value_is_offset = 0; int use_second_pass = 0; int chpr = 0; if(inptr && maker_entry) { PUSHCOLOR(MAKER_COLOR); if(summary_entry) summary_entry->filesubformat |= FILESUBFMT_MNOTE; /* Save these; they're in static storage in the maker_entry */ /* and will be overwritten when entry reading starts. */ maker_offset = maker_entry->value; maker_count = maker_entry->count; if(maker_count > 4UL) end_of_note = maker_offset + maker_count + fileoffset_base; else if(maker_count == 4UL) { /* special case, for certain Casio MakerNotes which use */ /* 4-byte UNDEFINED as though it were a LONG offset */ if(maker_entry->value_type == UNDEFINED) maker_offset = to_ulong((unsigned char *)&maker_entry->value,byteorder); /* This pretty much forces maker_scheme to PLAIN */ maker_count=0L; } else goto cant_dumpit; /* Clear any previous scheme structure */ /* This must be done before model() number is called. */ clear_makerscheme(); /* Get make and model from the global names saved from IFD0 */ /* Override real names if -m, -l, -s */ if(Use_Make_name) make = maker_number(Use_Make_name); else make = maker_number(Make_name); if(Use_Software_name) swname = Use_Software_name; else swname = Software_name; /* The camera-specific model number routine may fill in the */ /* note_version field in the scheme structure if the model is */ /* recognized and has more than 1 note version. Unknown */ /* models will be tested later or defaulted */ if(Use_Model_name) model = model_number(make,Use_Model_name,swname); else model = model_number(make,Model_name,swname); /* start_offset is where the note begins, relative to the */ /* start of the file. */ start_offset = start_entry_offset = maker_offset + fileoffset_base; nameoftag = tagname(maker_entry->tag); fulldirname = splice(parent_name,".",nameoftag); /* The MakerNote should be written within the values section */ /* of the Exif ifd, but sometimes is not. 'max_offset', if */ /* set, will be the end of the parent ifd (Exif). Mark it to */ /* indicate that the MakerNote is out of place. */ if(max_offset && (start_offset > max_offset)) prefix = ">"; else prefix = "@"; if(PRINT_SECTION) { print_tag_address(SECTION,start_offset,indent,prefix); chpr = printf("<%s> length %lu, ",nameoftag, maker_count ? maker_count: maker_entry->count); } else if(!(PRINT_VALUE_AT_OFFSET)) { tagwidth = MAKERTAGWIDTH; if(!(PRINT_LONGNAMES)) tagwidth -= strlen(nameoftag) + 1; /* When SECTIONS are not printed, provide these items as */ /* "pseudotags". */ if((PRINT_TAGINFO) || (PRINT_VALUE)) print_tag_address(ENTRY,HERE,indent+SMALLINDENT,"*"); if(PRINT_TAGINFO) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%s.",nameoftag); chpr += printf("%-*.*s",tagwidth,tagwidth,"Offset"); } if((PRINT_VALUE)) chpr += printf(" = @%lu",start_offset); chpr = newline(chpr); if((PRINT_TAGINFO) || (PRINT_VALUE)) print_tag_address(ENTRY,HERE,indent+SMALLINDENT,"*"); if(PRINT_TAGINFO) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%s.",nameoftag); chpr += printf("%-*.*s",tagwidth,tagwidth,"Length"); } if((PRINT_VALUE)) chpr += printf(" = %lu",maker_count ? maker_count: maker_entry->count); chpr = newline(chpr); if((PRINT_TAGINFO) || (PRINT_VALUE)) print_tag_address(ENTRY,HERE,indent+SMALLINDENT,"*"); if(PRINT_TAGINFO) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%s.",nameoftag); chpr += printf("%-*.*s",tagwidth,tagwidth,"Scheme"); } } /* Discover, if possible, the 'scheme' by which the MakerNote */ /* is stored. */ scheme_indent = charsprinted(); maker_scheme = find_makerscheme(inptr,maker_offset,fileoffset_base, byteorder,maker_count,make,model); /* If scheme debugging is in effect, the type info below */ /* needs to be indented a bit, since the debug output splits */ /* the starting line. */ if(PRINT_SCHEME_DEBUG) putindent(scheme_indent + chpr + 2); /* Print a brief description of the scheme found. Enclose it */ /* in quotes if not in a SECTION line */ if((PRINT_SECTION) || ((PRINT_VALUE) && !(PRINT_VALUE_AT_OFFSET))) { if(!(PRINT_SECTION)) chpr += printf(" = '"); switch(maker_scheme->scheme_type) { case HAS_ID_SCHEME: if(maker_scheme->offsets_relative_to == START_OF_NOTE) chpr += printf("Note-relative offset "); else if(maker_scheme->offsets_relative_to == START_OF_ENTRY) chpr += printf("Entry-relative offset "); chpr += printf("ID"); break; case HAS_ID_PLUS_TIFFHDR_SCHEME: chpr += printf("ID+TIFFheader"); break; case PLAIN_IFD_SCHEME: if(maker_scheme->offsets_relative_to == START_OF_NOTE) chpr += printf("Note-relative offset "); else if(maker_scheme->offsets_relative_to == START_OF_ENTRY) chpr += printf("Entry-relative offset "); else chpr += printf("Plain "); chpr += printf("IFD"); if(maker_count == 0) /* some old Casio */ chpr += printf(" (from UNDEFINED offset)"); break; /* New schemes can be added here. */ case UNKNOWN_SCHEME: default: /* dump a couple of lines, unless user says otherwise */ next_ifd_offset = 0UL; chpr += printf("unknown"); if(PRINT_SECTION) chpr += printf(" scheme"); if(PRINT_SECTION && !(PRINT_MAKERDUMP)) { chpr = newline(1); if(maker_count < DEF_SHORTDUMP) dumplength = maker_count; else dumplength = DEF_SHORTDUMP; hexdump(inptr,start_offset,maker_count,dumplength,12, indent,SUBINDENT); if(maker_count > dumplength) { printred(" (use -M to see more)"); chpr = newline(1); } } else if((PRINT_VALUE)) printf("'"); chpr = newline(chpr); if(PRINT_MAKERNOTE_SCHEME) print_scheme(inptr,maker_scheme); goto dumpit; break; } if(!(PRINT_SECTION)) chpr = printf("'"); } else chpr = newline(chpr); /* If printing a value in LIST mode, it's done; if in the */ /* middle of a section heading in SECTION mode, there's more */ /* heading to print. */ if(PRINT_SECTION) chpr += printf(" scheme,"); else if((PRINT_VALUE)) chpr = newline(chpr); num_entries = maker_scheme->num_entries; byteorder = maker_scheme->note_byteorder; if((maker_scheme->scheme_type == HAS_ID_PLUS_TIFFHDR_SCHEME) || (maker_scheme->offsets_relative_to == START_OF_NOTE)) { fileoffset_base = maker_scheme->fileoffset_base; start_entry_offset = fileoffset_base + maker_scheme->ifd_offset + 2; } else start_entry_offset = start_offset + maker_scheme->ifd_offset + 2; if(PRINT_SECTION) { chpr = printf(" %d entries starting at offset %#lx/%lu",num_entries, start_entry_offset,start_entry_offset); chpr = newline(chpr); } if(PRINT_MAKERNOTE_SCHEME) print_scheme(inptr,maker_scheme); if((maker_scheme->id_length > 0) && (PRINT_ENTRY)) { print_tag_address(ENTRY,start_offset, indent,prefix); extraindent(SUBINDENT); if((PRINT_LONGNAMES)) chpr += printf("%s.%s.",parent_name,nameoftag); chpr = printf("%sId",nameoftag); if((PRINT_VALUE)) { tagwidth = MAKERTAGWIDTH - strlen(nameoftag) - 2; putindent(tagwidth); chpr += printf(" = '%s'",maker_scheme->id); } chpr = newline(chpr); } if(((maker_scheme->scheme_type == HAS_ID_PLUS_TIFFHDR_SCHEME)) && (PRINT_SECTION)) { print_tag_address(SECTION,fileoffset_base,indent + SMALLINDENT,prefix); if(print_tiff_header(TIFF_MAGIC,maker_scheme->note_byteorder,SECTION) == 0) { chpr = printf(" ifd offset = %#x/%d)",maker_scheme->ifd_offset, maker_scheme->ifd_offset); if(fileoffset_base) { chpr += printf(" (+ %lu = %#lx/%lu)",fileoffset_base, fileoffset_base + maker_scheme->ifd_offset, fileoffset_base + maker_scheme->ifd_offset); } } chpr = newline(chpr); } /* At this point, the note has been "verified" to be in TIFF */ /* IFD format, and can be read normally in that fashion. */ /* Maker-specific information is handled in the print_maker */ /* routines, according to the noteversion derived from the */ /* make and model numbers. */ /* Scheme validation is not entirely robust, however, so the */ /* code below bails out at the first sign of an invalid */ /* entry, and hexdumps the data if wanted. */ indent += SMALLINDENT; current_offset = entry_offset = start_entry_offset; value_is_offset = 0; for(entry_num = 0; entry_num < num_entries; ++entry_num) { print_tag_address(ENTRY,entry_offset,indent,prefix); tagindent = charsprinted(); /* in case error msg needed */ entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) { ++invalid; } else invalid = 0; if(maker_scheme->offsets_relative_to == START_OF_ENTRY) fileoffset_base = entry_offset; entry_offset = current_offset = ftell(inptr); value_offset = print_makerentry(inptr,byteorder, entry_ptr,fileoffset_base, summary_entry,fulldirname, indent,make,model); if(invalid > 5) { if((PRINT_SECTION)) { PUSHCOLOR(RED); chpr += printf(" TOO MANY INVALID ENTRIES"); if((PRINT_MAKERDUMP)) chpr += printf(" (hexdump follows)"); else chpr += printf(" (Use -M to hex/ascii dump)"); POPCOLOR(); chpr = newline(chpr); } else { chpr = newline(chpr); PUSHCOLOR(RED); chpr += printf("# WARNING: TOO MANY INVALID MAKERNOTE ENTRIES"); chpr += printf(" (note processing aborted)"); POPCOLOR(); chpr = newline(chpr); } goto dumpit; } if(value_offset == 0UL) value_offset = entry_offset; if(end_of_note) { if((value_offset < end_of_note) && (value_offset > max_value_offset)) max_value_offset = value_offset; } else if(value_offset > max_value_offset) { max_value_offset = value_offset; } if((is_offset(entry_ptr) || maker_value_is_offset(entry_ptr,make,model))) ++use_second_pass; } /* Some makers write the next ifd offset as 0, as is normal */ /* for an IFD. Some write nothing. */ if(maker_scheme->no_nextifd_offset) { next_ifd_offset = 0L; if((PRINT_SECTION) && (PRINT_ENTRY)) { /* Since it isn't needed, just note it and move on. */ print_tag_address(SECTION,current_offset,indent,prefix); printred("no next IFD offset used"); chpr = newline(1); } } else { next_ifd_offset = read_ulong(inptr,byteorder,current_offset); if(next_ifd_offset > 0L) { /* This should not happen, of course. */ if((PRINT_ADDRESS) && (PRINT_VALUE) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(ENTRY,current_offset,indent,prefix); chpr += printf("**** next IFD offset %lu ",next_ifd_offset); next_ifd_offset += fileoffset_base; chpr += printf("(+ %lu = %#lx/%lu)",fileoffset_base, next_ifd_offset,next_ifd_offset); if(next_ifd_offset < ftell(inptr)) { printred(" # BAD NEXT IFD OFFSET"); next_ifd_offset = 0L; } chpr = newline(chpr); } else next_ifd_offset += fileoffset_base; } else { if((PRINT_ADDRESS) && (PRINT_VALUE) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(ENTRY,current_offset,indent,prefix); chpr = printf("**** next IFD offset 0"); chpr = newline(chpr); } } } if(ferror(inptr)) { chpr = printf(" READ NEXT IFD OFFSET FAILED "); why(stdout); clearerr(inptr); /* keep going... */ chpr = newline(1); } else current_offset = ftell(inptr); value_offset = current_offset; if((max_value_offset == 0) || (current_offset > max_value_offset)) max_value_offset = current_offset; /* Make a second pass over the entries, to print values of */ /* entries whose values are indirect. */ if(use_second_pass) { if((PRINT_VALUE) && (PRINT_ADDRESS) && (PRINT_VALUE_AT_OFFSET)) { print_tag_address(ENTRY,value_offset,indent,prefix); chpr = printf("============= VALUES, %s ============",nameoftag); chpr = newline(chpr); } entry_offset = start_entry_offset; for(entry_num = 0; entry_num < num_entries; ++entry_num) { entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset); if(ferror(inptr)) /* why didn't this happen above? */ goto dumpit; if(maker_scheme->offsets_relative_to == START_OF_ENTRY) fileoffset_base = entry_offset; entry_offset = current_offset = ftell(inptr); if(is_offset(entry_ptr) || maker_value_is_offset(entry_ptr,make,model)) { /* If this is negative, it is assumed to be a */ /* length value which is intended to trigger */ /* processing of the previous entry, which is an */ /* offset (usually of a thumbnail which is */ /* specified by two tags)...so use the previous */ /* value_offset. Don't violate this convention! */ if(maker_value_is_offset(entry_ptr,make,model) >= 0) value_offset = fileoffset_base + entry_ptr->value; if(Debug & 0x10) printf("SL:mvo=%lu,vo=%lu,veo=%lu, en=%lu ### prefix='%s'\n", max_value_offset,value_offset,value_end_offset,end_of_note,prefix); if((value_type_size(entry_ptr->value_type) * entry_ptr->count) <= 4UL) value_end_offset = 0; else value_end_offset = value_offset + (value_type_size(entry_ptr->value_type) * entry_ptr->count); if(value_offset > end_of_note) { if(*prefix == '>') tprefix = "+"; else tprefix = ">"; } else tprefix = prefix; if(Debug & 0x10) printf("BP:mvo=%lu,vo=%lu,veo=%lu, meo=%lu, en=%lu ### prefix=%s\n", max_value_offset,value_offset,value_end_offset, max_end_offset,end_of_note,prefix); if((PRINT_VALUE_AT_OFFSET)) { value_end_offset = print_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry,fulldirname, tprefix,indent,make,model,1); } if(Debug & 0x10) printf("AP:mvo=%lu,vo=%lu,veo=%lu, meo=%lu, en=%lu ### prefix=%s\n", max_value_offset,value_offset,value_end_offset, max_end_offset,end_of_note,prefix); /* If the value is a section which STARTS past */ /* the announced end of the makernote it should */ /* not be regarded as part of the makernote, and */ /* should not contribute to the offset returned */ /* from this routine. */ if(end_of_note) { if((value_offset < end_of_note) && (value_end_offset > max_value_offset)) { max_value_offset = value_end_offset; max_in_note_tagoffset = value_offset; } } else if((value_end_offset > max_value_offset)) max_value_offset = value_end_offset; /* Keep track of actual maximum; tattle later */ if(value_end_offset > max_end_offset) max_end_offset = value_end_offset; if(end_of_note) { if((value_offset > end_of_note) && (min_out_of_note_tagoffset == 0)) min_out_of_note_tagoffset = value_offset; } if(Debug & 0x10) printf("EL:mvo=%lu,vo=%lu,veo=%lu, meo=%lu, en=%lu ### prefix=%s\n", max_value_offset,value_offset,value_end_offset, max_end_offset,end_of_note,prefix); } current_offset = ftell(inptr); } } else if(current_offset > max_value_offset) max_value_offset = current_offset; indent -= SMALLINDENT; /* If the note is incompletely specified, point that out. If */ /* IFD entries are not being printed this message is not */ /* wanted. */ if((end_of_note && (max_value_offset < end_of_note)) && (PRINT_SECTION) && (PRINT_ENTRY) && !(LIST_MODE)) { unsigned long printlength = 0; print_tag_address(ENTRY,max_value_offset - 1,indent + SMALLINDENT, "*"); chpr = printf("---- End of values before end of %s",nameoftag); chpr = newline(chpr); dumplength = end_of_note - max_value_offset; /* dump at least the first couple of rows, just to see... */ if(PRINT_MAKERDUMP) { if((Max_makerdump == DUMPALL) || (Max_makerdump > dumplength)) printlength = dumplength; else if(Max_makerdump > 0L) printlength = Max_makerdump; else if(Max_undefined > 0L) printlength = Max_undefined > dumplength ? Max_undefined : dumplength; } else /* always print a little bit in this case */ { if(dumplength > DEF_SHORTDUMP) printlength = DEF_SHORTDUMP; else printlength = dumplength; } hexdump(inptr,max_value_offset,dumplength,printlength,12, indent,SUBINDENT); if(dumplength > printlength) printred(" (use -M to see more)"); chpr = newline(1); } else if(maker_count == 0L) { end_of_note = max_value_offset - 1; maker_count = end_of_note - start_offset; if(!(PRINT_SECTION) && !(PRINT_VALUE_AT_OFFSET) && (PRINT_ENTRY)) { tagwidth = MAKERTAGWIDTH; if(!(PRINT_LONGNAMES)) tagwidth -= strlen(nameoftag) - 1; /* rewrite this pseudotag, since the first one was */ /* wrong */ chpr = newline(chpr); if((PRINT_TAGINFO) || (PRINT_VALUE)) print_tag_address(ENTRY,HERE,indent+SMALLINDENT,prefix); if(PRINT_TAGINFO) { if((PRINT_LONGNAMES)) chpr += printf("%s.",parent_name); chpr += printf("%s.",nameoftag); chpr += printf("%-*.*s",tagwidth,tagwidth,"Length"); } if((PRINT_VALUE)) chpr += printf(" = %lu",maker_count); } } if(Debug & 0x10) printf("END: mvo=%lu, en=%lu, meo=%lu\n",max_value_offset,end_of_note,max_end_offset); if(end_of_note && (max_value_offset > (end_of_note + 1)) && max_in_note_tagoffset) { print_tag_address(SECTION,max_in_note_tagoffset,indent + SMALLINDENT,"!"); printred("# WARNING: values extend past end of MakerNote"); chpr = newline(chpr); } if(end_of_note && (max_end_offset > (end_of_note + 1)) && min_out_of_note_tagoffset) { print_tag_address(SECTION,min_out_of_note_tagoffset,indent + SMALLINDENT,"!"); printred("# WARNING: values referenced outside of MakerNote"); chpr = newline(chpr); } print_tag_address(SECTION,end_of_note - 1,indent,prefix); if(PRINT_SECTION) chpr = printf("",nameoftag); if(next_ifd_offset) { if((PRINT_SECTION)) chpr += printf(" "); PUSHCOLOR(RED); chpr = printf("# WARNING! MakerNote has next ifd offset %lu",next_ifd_offset); POPCOLOR(); } chpr = newline(chpr); POPCOLOR(); if(fulldirname) free(fulldirname); fulldirname = CNULL; } /* The offset passed back to the caller may be higher than the */ /* offset written above for the end of the note, if values are */ /* referenced past advertised end of note in a chunk that began */ /* before end of note. */ if(max_value_offset > end_of_note) end_of_note = max_value_offset; return(end_of_note); dumpit: if(PRINT_MAKERDUMP) { /* If no specific length is given for makernote data, limit */ /* the dump length to the length specified for undefined */ /* data. */ if(Max_makerdump == DUMPALL) dumplength = maker_count; else if(Max_makerdump > 0L) { dumplength = Max_makerdump; /* In case the maker_count is botched, dump as much as */ /* asked */ if(maker_count < dumplength) maker_count = dumplength; } else dumplength = Max_undefined; if(dumplength > 0L) { chpr = newline(chpr); hexdump(inptr,start_offset,maker_count,dumplength,12, indent,SUBINDENT); chpr = newline(1); } } if(PRINT_SECTION) { print_tag_address(SECTION,end_of_note - 1,indent,"-"); chpr = printf(""); } POPCOLOR(); chpr = newline(chpr); clearerr(inptr); if(maker_count) return(end_of_note); return(0L); cant_dumpit: clearerr(inptr); chpr = printf(" INVALID MakerNote offset %lu",maker_offset); chpr = newline(chpr); return(0L); } /* Return a unique number for a given maker, (assigned in "maker.h") */ /* based upon a string, usually taken from a "Make" tag. This "magic */ /* number" will be used to select routines to print tagnames and to */ /* interpret data from MakerNotes for that maker. */ int maker_number(char *make) { struct camera_name *maker_id; int number = NO_MAKE; if(make) { /* 'Camera_make' is a global parameter */ for(maker_id = Camera_make; maker_id && maker_id->name; ++maker_id) { if(strncasecmp(make,maker_id->name,maker_id->namelen) == 0) { number = maker_id->id; break; } } } return(number); } /* Call a maker-specific routine to assign an identifying number for */ /* a specific model of a given maker's camera. The camera make is */ /* identified by the number assigned by make_number(), and is used to */ /* dispatch the maker-specific routine, which is then free to pick an */ /* identifying number based upon the "Model" tag and possibly the */ /* "Software" tag. The numbers are assigned in "maker.h". Model */ /* numbers are used only to determine 'quirks' in some notes which */ /* cannot reliably be discovered by examining the note scheme, */ /* The softwarename field has proven unreliable for any purpose, is */ /* not used anywhere in the program (other than to print it), and */ /* could disappear from these argument lists. Some image edit */ /* software will change this field, some won't; in any case, */ /* maker-supplied versions do not appear to tell us much. */ int model_number(int make,char *modelstring,char *softwarename) { int number = NO_MODEL; if(modelstring == NULL) modelstring = NULLSTRING; if(softwarename == NULL) softwarename = NULLSTRING; switch(make) { case MAKER_AGFA: number = agfa_model_number(modelstring,softwarename); break; case MAKER_ASAHI: /* PENTAX */ case MAKER_PENTAX: /* PENTAX */ number = asahi_model_number(modelstring,softwarename); break; case MAKER_CANON: number = canon_model_number(modelstring,softwarename); break; case MAKER_CASIO: number = casio_model_number(modelstring,softwarename); break; case MAKER_EPSON: number = epson_model_number(modelstring,softwarename); break; case MAKER_FUJIFILM: number = fujifilm_model_number(modelstring,softwarename); break; case MAKER_HP: /* proprietary makernotes */ number = hp_model_number(modelstring,softwarename); break; case MAKER_KODAK: /* proprietary makernotes */ number = kodak_model_number(modelstring,softwarename); break; case MAKER_KONICA: /* proprietary notes: old Konica models */ number = konica_model_number(modelstring,softwarename); break; case MAKER_KYOCERA: number = kyocera_model_number(modelstring,softwarename); break; case MAKER_LEICA: number = leica_model_number(modelstring,softwarename); break; case MAKER_MINOLTA: number = minolta_model_number(modelstring,softwarename); break; case MAKER_NIKON: number = nikon_model_number(modelstring,softwarename); break; case MAKER_OLYMPUS: number = olympus_model_number(modelstring,softwarename); break; case MAKER_PANASONIC: number = panasonic_model_number(modelstring,softwarename); break; case MAKER_RICOH: /* no or non-IFD makernote data */ number = ricoh_model_number(modelstring,softwarename); break; case MAKER_SANYO: number = sanyo_model_number(modelstring,softwarename); break; case MAKER_SIGMA: number = sigma_model_number(modelstring,softwarename); break; case MAKER_SONY: /* no makernote data */ /* DSC-V3 has makernote in IFD format, but nothing is */ /* known about meaning (there are no maker-specific */ /* routines here yet) */ number = sony_model_number(modelstring,softwarename); break; case MAKER_TOSHIBA: number = toshiba_model_number(modelstring,softwarename); break; case MAKER_TRAVELER: /* proprietary makernote */ number = traveler_model_number(modelstring,softwarename); break; default: /* NO_MODEL */ break; } return(number); } /* ********************************************************************/ /* Attempt to discover the format of a MakerNote. Some notes are in */ /* normal TIFF IFD format, with tags assigned by the maker, and */ /* values interpreted in maker-specific ways. Some makers begin with */ /* a few bytes containing an ascii string identifying the maker, with */ /* a normal IFD following at a specific offset. One camera I've seen */ /* begins with such an ascii id, followed by an actual TIFF header, */ /* with the following IFD offsets then relative to that TIFF header. */ /* This latter scheme seems the most sensible, since it allows image */ /* editting software to move the MakerNote with little effort, and */ /* allows standard TIFF machinery to read them. */ /* Within the three schemes above, all of which include the basic */ /* format of a TIFF Image File Directory, makers have devised several */ /* ways to express their individuality. */ /* The most harmless is the length of the ID string, and the */ /* resulting offset from the start of the MakerNote blob to the start */ /* of the actual IFD. Some makers prove their independence by writing */ /* "offset" entries in the IFD (required when a value won't fit in */ /* the 12-byte entry) relative to the start of the MakerNote or even */ /* the start of the current entry. The TIFF specification requires */ /* that such offsets are relative to the beginning of the last */ /* in-scope TIFF header. */ /* At least one maker thumbs it's nose at the software world by */ /* gratuitously changing the byte order used when writing the */ /* MakerNote, compared to the remainder of the image file. */ /* Some makers write MakerNotes, but in a purely private, proprietary */ /* format. We cannot read those, except as a blob of useless junk. */ /* This routine uses some simple heuristics to attempt to intuit the */ /* format of a note, rather than a table of known make/model formats. */ /* If an Id string is found, an attempt is made to find a TIFF header */ /* or an apparently valid IFD. If found, the offset from the start of */ /* the blob is recorded, and if the byteorder is changed, that is */ /* noted as well */ /* Offset to the start of the IFD and byteorder are sufficient to */ /* read the directory entries (and print them) but the reference */ /* point for offsets to indirect data is difficult to determine if it */ /* differs from the TIFF specification. Specific information, */ /* according to camera make and model, is added for cameras which are */ /* known to write note- or entry-relative offsets. Some cameras also */ /* fail to write zeros for the "next IFD offset" normally included at */ /* the end of a TIFF IFD, so that fact is noted as well. */ /* If the note just doesn't look presentable, a (currently dummy) */ /* routine can be used to check for known sports. */ /* The information recorded in the maker_scheme structure at this */ /* point is sufficient to read and print the structure of the note */ /* (except for UNKNOWN schemes, of course). Interpreting the */ /* *meaning* of the tags and values is the responsibility of */ /* maker-specific routines. */ /* ********************************************************************/ /* ********************************************************************/ /* The maker_scheme structure may be of interest to maker-specific */ /* routines, but is not passed around, and should not be modified */ /* outside find_makerscheme. retrieve_makerscheme is provided to */ /* allow a *copy* of the structure to be retrieved after it has been */ /* filled. */ /* ********************************************************************/ /* Allow only find_makerscheme() to muck with the original scheme. */ /* Spcific routines are provided to alter note_version and/or tagset */ /* from anywhere in the program, although this is not currently */ /* required. */ static struct maker_scheme maker_scheme; /* Clear the structure and mark it clear for process_makernote() */ void clear_makerscheme() { memset(&maker_scheme,'\0',sizeof(struct maker_scheme)); maker_scheme.make = -1; } struct maker_scheme * find_makerscheme(FILE *inptr,unsigned long note_offset, unsigned long fileoffset_base, unsigned short byteorder, unsigned long maker_size,int make,int model) { struct ifd_entry *ifdentry; int length_read,id_length,num_entries,start,maxchk_offset; int tiffhdr_offset = 0; unsigned long note_fileoffset = 0L; unsigned long num_entry_offset = 0L; unsigned long ifd_offset = 0L; unsigned long scheme_type = UNKNOWN_SCHEME; unsigned short alt_byteorder; unsigned short note_byteorder = byteorder; int chpr = 0; char *id; if(maker_scheme.make >= 0) clear_makerscheme(); note_fileoffset = note_offset + fileoffset_base; id= (char *)read_bytes(inptr,MAX_IDLEN,note_fileoffset); length_read = id ? strlen(id) : 0; /* check that string is printable, adjust id_length if nexessary */ if(PRINT_SCHEME_DEBUG) { PUSHCOLOR(HI_RED); PUSHCOLOR(BG_WHITE); chpr = newline(1); chpr += printf("Scheme debug:"); chpr = newline(chpr); chpr += printf("Initial id length = %d, ID=",length_read); chpr += print_ascii(inptr,length_read,note_fileoffset); chpr += printf(" at file offset %lu",note_fileoffset); chpr = newline(chpr); } /* Check that the string is printable, and truncate at the first */ /* non-printable found */ id = check_printable(id,MAX_IDLEN); id_length = strlen(id); if((PRINT_SCHEME_DEBUG) && (id_length != length_read)) { chpr += printf("\tchecked id length = %d",id_length); chpr = newline(chpr); } switch(id_length) { case -1: /* read failed */ case 0: /* normal or unknown */ case 1: case 2: /* ###% allow 1 and 2 to be checked? */ scheme_type = PLAIN_IFD_SCHEME; note_byteorder = byteorder; #if 0 /* This is unwise */ if(PRINT_SCHEME_DEBUG) { chpr += printf(" force PLAIN IFD with no offset"); chpr = newline(chpr); chpr += printf(" entry check offset 0: "); } num_entry_offset = note_fileoffset; num_entries = read_ushort(inptr,byteorder,num_entry_offset); if(((num_entries > 0) && (maker_size > 0L) && (num_entries <= (maker_size / 12))) && (invalid_ifd_entry(inptr,num_entry_offset + 2, maker_size,num_entries, byteorder) == 0)) { if(PRINT_SCHEME_DEBUG) { chpr += printf(" FOUND entry, num_entries=%d",num_entries); chpr = newline(chpr); } note_byteorder = byteorder; } else { if(PRINT_SCHEME_DEBUG) { chpr += printf(", num_entries=%d\t(INVALID)",num_entries); chpr = newline(chpr); chpr += printf(" alt byteorder entry check offset 0: "); } if(byteorder == TIFF_MOTOROLA) alt_byteorder = TIFF_INTEL; else alt_byteorder = TIFF_MOTOROLA; num_entries = read_ushort(inptr,alt_byteorder,num_entry_offset); if(((num_entries > 0) && (maker_size > 0L) && (num_entries <= (maker_size / 12))) && (invalid_ifd_entry(inptr,num_entry_offset + 2,maker_size,num_entries,alt_byteorder) == 0)) { if(PRINT_SCHEME_DEBUG) { chpr += printf(" num_entries=%d, VALID entry found, byteorder=",num_entries); print_byteorder(alt_byteorder,1); chpr = newline(chpr); } note_byteorder = alt_byteorder; } else if(PRINT_SCHEME_DEBUG) { chpr += printf(" , num_entries=%d\t(INVALID)",num_entries); chpr = newline(chpr); } } #endif break; default: ifd_offset = 0L; start = ((id_length + 3) * 2) / 2; maxchk_offset = start + 8; /* look for TIFF header first. */ /* At least one maker uses odd offsets, so we can't */ /* increment by two */ for( ; start < maxchk_offset; ++start) { int print_marker = 0; if(PRINT_SCHEME_DEBUG) { chpr += printf(" header check offset %d",start); print_marker++; } alt_byteorder = valid_tiffhdr(inptr,note_fileoffset + start,print_marker); if(alt_byteorder) { scheme_type = HAS_ID_PLUS_TIFFHDR_SCHEME; tiffhdr_offset = start; fileoffset_base = note_fileoffset + tiffhdr_offset; ifd_offset = read_ulong(inptr,alt_byteorder,HERE); note_byteorder = alt_byteorder; if(PRINT_SCHEME_DEBUG) { chpr += printf(" found TIFF header af file offset %lu",fileoffset_base); chpr = newline(chpr); chpr += printf(" note_fileoffset = %lu, tifhdr_offset = %u, ifd_offset = %lu", note_fileoffset,tiffhdr_offset,ifd_offset); chpr = newline(chpr); } break; } else if(PRINT_SCHEME_DEBUG) { chpr += printf("\t (NO VALID MARKER)"); chpr = newline(chpr); } } if(ifd_offset == 0) /* No TIFF header */ { start = ((id_length + 1) * 2) / 2; for( ; start < maxchk_offset; ++start) { if(PRINT_SCHEME_DEBUG) chpr += printf(" entry check offset %d",start); num_entry_offset = note_fileoffset + start; num_entries = read_ushort(inptr,byteorder,num_entry_offset); if(((num_entries > 0) && (maker_size > 0L) && (num_entries <= (maker_size / 12))) && (invalid_ifd_entry(inptr,num_entry_offset + 2, maker_size,num_entries, byteorder) == 0)) { if(PRINT_SCHEME_DEBUG) { chpr += printf(" FOUND entry, num_entries=%d",num_entries); chpr = newline(chpr); } scheme_type = HAS_ID_SCHEME; ifd_offset = start; note_byteorder = byteorder; break; } else if(PRINT_SCHEME_DEBUG) { chpr += printf(" , num_entries=%d\t(INVALID)",num_entries); chpr = newline(chpr); } } } if(ifd_offset == 0) /* Try the other byte order */ { if(byteorder == TIFF_MOTOROLA) alt_byteorder = TIFF_INTEL; else alt_byteorder = TIFF_MOTOROLA; start = ((id_length + 3) * 2) / 2; for( ; start < maxchk_offset; ++start) { if(PRINT_SCHEME_DEBUG) chpr += printf(" alt byteorder entry check offset %d",start); num_entry_offset = note_fileoffset + start; num_entries = read_ushort(inptr,alt_byteorder,num_entry_offset); if(((num_entries > 0) && (maker_size > 0L) && (num_entries <= (maker_size / 12))) && (invalid_ifd_entry(inptr,num_entry_offset + 2,maker_size,num_entries,alt_byteorder) == 0)) { if(PRINT_SCHEME_DEBUG) { chpr += printf(" num_entries=%d, VALID entry found, byteorder=",num_entries); print_byteorder(alt_byteorder,1); chpr = newline(chpr); } note_byteorder = alt_byteorder; scheme_type = HAS_ID_SCHEME; ifd_offset = start; break; } else if(PRINT_SCHEME_DEBUG) { chpr += printf(" , num_entries=%d\t(INVALID)",num_entries); chpr = newline(chpr); } } } break; } if(PRINT_SCHEME_DEBUG) { chpr = newline(chpr); chpr += printf(" reading num_entries at offset %lu, byteorder=", note_fileoffset + tiffhdr_offset + ifd_offset); print_byteorder(note_byteorder,1); chpr = newline(chpr); } if(ifd_offset >= 0) { num_entries = read_ushort(inptr,note_byteorder,note_fileoffset + tiffhdr_offset + ifd_offset); /* read and save first entry (in scheme structure) as an aid */ /* to selecting version of note processor to use for unknown */ /* models */ /* ### this probably shouldn't be done until the scheme has */ /* been validated. It's not used much anyway. */ /* ###%%% better yet, read it here and pass it to */ /* invalid_ifd_entry() rather than reading it again there. */ ifdentry = read_ifd_entry(inptr,note_byteorder,HERE); memcpy(&(maker_scheme.first_entry),ifdentry,sizeof(struct ifd_entry)); } else num_entries = 0; /* read failed */ if(PRINT_SCHEME_DEBUG) { chpr += printf(" num_entries=%d",num_entries); chpr = newline(chpr); } if(((maker_size > 0L) && (num_entries > (maker_size / 12))) || invalid_ifd_entry(inptr,note_fileoffset + tiffhdr_offset + ifd_offset + 2, maker_size,num_entries,note_byteorder)) { /* Record what we know */ maker_scheme.make = make; maker_scheme.model = model; maker_scheme.note_version = -1; maker_scheme.scheme_type = UNKNOWN_SCHEME; maker_scheme.note_fileoffset = note_fileoffset; maker_scheme.note_length = maker_size; maker_scheme.id = id; /* ...could be one */ maker_scheme.id_length = id_length; maker_scheme.tiffhdr_offset = 0L; maker_scheme.ifd_offset = 0L; maker_scheme.fileoffset_base = fileoffset_base; maker_scheme.num_entries = 0; maker_scheme.offsets_relative_to = 0; maker_scheme.no_nextifd_offset = 1; maker_scheme.tiff_byteorder = byteorder; maker_scheme.note_byteorder = 0; find_maker_model(&maker_scheme,make,model); /* If find_maker_model() is changed to succeed at anything, */ /* this will have to change... */ if(PRINT_SCHEME_DEBUG) { PUSHCOLOR(GREEN); chpr = printf(" No valid scheme found "); POPCOLOR(); POPCOLOR(); } } else { if(PRINT_SCHEME_DEBUG) { PUSHCOLOR(GREEN); chpr = printf(" Found valid scheme "); POPCOLOR(); POPCOLOR(); } /* We seem to have a winner... */ if(scheme_type == UNKNOWN_SCHEME) maker_scheme.scheme_type = PLAIN_IFD_SCHEME; else maker_scheme.scheme_type = scheme_type; maker_scheme.make = make; maker_scheme.model = model; /* note_version may already be set by maker_number() */ maker_scheme.note_fileoffset = note_fileoffset; maker_scheme.note_length = maker_size; maker_scheme.id = id; maker_scheme.id_length = id_length; maker_scheme.ifd_offset = ifd_offset; maker_scheme.tiffhdr_offset = tiffhdr_offset; maker_scheme.num_entries = num_entries; maker_scheme.no_nextifd_offset = 0; maker_scheme.offsets_relative_to = START_OF_TIFFHEADER; maker_scheme.fileoffset_base = fileoffset_base; /* The two entries allow print_scheme() to make it plain when */ /* the note byte order gratuitously differs from the rest of */ /* the file. */ maker_scheme.tiff_byteorder = byteorder; maker_scheme.note_byteorder = note_byteorder; /* Maker-specific adjustments */ switch(make) { case MAKER_AGFA: if((maker_scheme.note_version == 0)) setnoteversion(1); break; case MAKER_ASAHI: /* fall through */ case MAKER_PENTAX: if(maker_scheme.scheme_type == PLAIN_IFD_SCHEME) maker_scheme.offsets_relative_to = START_OF_ENTRY; if((maker_scheme.note_version == 0)) (void)set_asahi_noteversion(); break; case MAKER_CANON: if((maker_scheme.note_version == 0)) setnoteversion(1); break; case MAKER_CASIO: if((maker_scheme.note_version == 0)) (void)set_casio_noteversion(); break; case MAKER_EPSON: if((maker_scheme.note_version == 0)) setnoteversion(1); break; case MAKER_FUJIFILM: maker_scheme.offsets_relative_to = START_OF_NOTE; maker_scheme.fileoffset_base = note_fileoffset; if((maker_scheme.note_version == 0)) setnoteversion(1); break; case MAKER_HP: /* proprietary makernote */ if((maker_scheme.note_version == 0)) setnoteversion(-1); break; case MAKER_KODAK: /* proprietary makernote */ if((maker_scheme.note_version == 0)) setnoteversion(-1); break; case MAKER_KONICA: /* no makernote data */ if((maker_scheme.note_version == 0)) setnoteversion(-1); break; case MAKER_LEICA: if(strncasecmp(id,"FUJIFILM",8) == 0) { maker_scheme.offsets_relative_to = START_OF_NOTE; maker_scheme.fileoffset_base = note_fileoffset; /* maker_scheme.no_nextifd_offset = 1; */ } if((maker_scheme.note_version == 0)) setnoteversion(1); break; case MAKER_MINOLTA: if((maker_scheme.note_version == 0)) setnoteversion(1); break; case MAKER_KYOCERA: maker_scheme.offsets_relative_to = START_OF_ENTRY; maker_scheme.no_nextifd_offset = 1; break; case MAKER_NIKON: if((maker_scheme.note_version == 0)) (void)set_nikon_noteversion(); break; case MAKER_OLYMPUS: if((maker_scheme.note_version == 0)) setnoteversion(1); break; case MAKER_PANASONIC: maker_scheme.no_nextifd_offset = 1; if((maker_scheme.note_version == 0)) setnoteversion(1); break; case MAKER_TOSHIBA: if((maker_scheme.note_version == 0)) setnoteversion(1); maker_scheme.no_nextifd_offset = 1; break; case MAKER_RICOH: /* no or non-IFD makernote data */ if((maker_scheme.note_version == 0)) setnoteversion(-1); break; case MAKER_SANYO: if((maker_scheme.note_version == 0)) setnoteversion(1); break; case MAKER_SIGMA: if(model == SIGMA_SD9) maker_scheme.no_nextifd_offset = 1; if((maker_scheme.note_version == 0)) setnoteversion(1); break; case MAKER_SONY: if((maker_scheme.note_version == 0)) setnoteversion(-1); maker_scheme.no_nextifd_offset = 1; break; case MAKER_TRAVELER: /* proprietary makernote */ if((maker_scheme.note_version == 0)) setnoteversion(-1); break; default: break; } } if(PRINT_SCHEME_DEBUG) { POPCOLOR(); chpr = newline(chpr); } return(&maker_scheme); } /* Look up a make and model in a table of known sports. This is */ /* currently just a dummy, but might be used to handle non-ifd notes */ /* by setting a new type here and revising the generic code to */ /* dispatch a specialized routine. I have no information on such */ /* notes now. */ void find_maker_model(struct maker_scheme *maker_scheme,int make,int model) { /* do a lookup here on make and model */ /* This should probably return a scheme structure, or some */ /* indication of success or failure, but since it's not used */ /* now (except to initialize the structure)... */ } /* Check for a valid TIFF header at the argument offset */ unsigned short valid_tiffhdr(FILE *inptr,unsigned long offset,int print_marker) { struct fileheader *header; unsigned short marker = 0; int chpr = 0; if(inptr && offset) { if(print_marker) chpr = printf(" read at offset %lu ",offset); header = read_imageheader(inptr,offset); if(header) { if(print_marker) chpr += printf(" %#x ",header->file_marker); switch(header->probe_magic) { case TIFF_MAGIC: marker = header->file_marker; break; default: marker = 0; break; } } } setcharsprinted(chpr); return(marker); } /* Check for an apparently valid TIFF IFD entry at the argumrnt */ /* offset. */ int invalid_ifd_entry(FILE *inptr,unsigned long offset,unsigned long segment_size, int nentries,unsigned short byteorder) { struct ifd_entry *entry_ptr; int invalid = 0; if(inptr && offset && byteorder) { /* Read an entry at the given offset and see if has a valid */ /* type, and non-zero count. */ entry_ptr = read_ifd_entry(inptr,byteorder,offset); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) ++invalid; else if(entry_ptr->count == 0) ++invalid; /* If there is more than one entry, and the first appears */ /* valid, check the second entry. */ /* If there is only one entry, and it appears valid, make */ /* sure that it's size fits within the note. This size check */ /* can fail on multi-entry notes when moronic makers write a */ /* thumbnail offset, then write the thumbnail outside the */ /* note...so we don't check size for multi. */ if(nentries > 1) { if(invalid == 0) /* double check */ { entry_ptr = read_ifd_entry(inptr,byteorder,HERE); if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) || ferror(inptr) || feof(inptr)) ++invalid; else if(entry_ptr->count == 0) ++invalid; } } else if(entry_ptr->count > segment_size) ++invalid; } else ++invalid; return(invalid); } /* Call a maker-specific routine to identify LONG values which must */ /* be interpreted as offsets. */ int maker_value_is_offset(struct ifd_entry *entry,int make,int model) { int is_offset = 0; if(entry) { switch(make) { case MAKER_ASAHI: case MAKER_PENTAX: is_offset = maker_asahi_value_is_offset(entry,model); break; case MAKER_CANON: is_offset = maker_canon_value_is_offset(entry,model); break; case MAKER_CASIO: is_offset = maker_casio_value_is_offset(entry,model); break; case MAKER_NIKON: is_offset = maker_nikon_value_is_offset(entry,model); break; case MAKER_MINOLTA: is_offset = maker_minolta_value_is_offset(entry,model); break; default: break; } } return(is_offset); } /* Copy the argument string into static storage, stopping at any */ /* unprintable byte which may be found. */ /* Return the null-terminated result string. */ char * check_printable(char *id, int maxlen) { static char buffer[MAX_IDLEN]; char *idval,*bufval; int i = 0; memset(buffer,'\0',MAX_IDLEN); if(maxlen > MAX_IDLEN) maxlen = MAX_IDLEN; bufval = buffer; for(idval = id; idval && (i < maxlen - 1); ++idval,++bufval,++i) if(!isprint(*idval)) { *bufval = '\0'; break; } else *bufval = *idval; return(buffer); } /* Record the "version" of the makernote as recognized by exifprobe. */ /* Note that the version number is arbitrary and does not correspond */ /* to any manufacturer numbering scheme; it is used for internal */ /* identification in order to identify or determine which routine is */ /* to be used for each model. */ int option_noteversion = 0; /* This function may be called from the option processing code to */ /* allow a user to override the noteversion which would otherwise be */ /* set. This is primarily intended to permit trying an existing */ /* noteversion on an unrecognized model. */ void setoptionnoteversion(int note_vers) { option_noteversion = note_vers; } void setnoteversion(int note_vers) { if(option_noteversion != 0) maker_scheme.note_version = option_noteversion; else maker_scheme.note_version = note_vers; } int getnoteversion() { if(option_noteversion != 0) maker_scheme.note_version = option_noteversion; return(maker_scheme.note_version); } /* Tagset number is usually the same as note version; however, some */ /* models may have fewer tagsets than note versions. The two are set */ /* separately. Tagset number is provided for info/debug only (it is */ /* not used by the selection code); */ void setnotetagset(int tagset) { maker_scheme.tagset = tagset; } int getnotetagset() { return(maker_scheme.tagset); } /* Provide maker-specific files access to a copy of the scheme. */ struct maker_scheme * retrieve_makerscheme() { static struct maker_scheme maker_scheme_copy; /* structure assignment */ maker_scheme_copy = maker_scheme; return(&maker_scheme_copy); } exifprobe-2.0.1+git20170416-3c2b76/maker_sigma.c0000644000000000000000000001732313074742216017142 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_sigma.c,v 1.4 2005/07/24 22:56:27 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Sigma camera maker-specific routines. */ /* Tag information from; */ /* http://www.x3f.info/technotes/FileDocs/MakerNoteDoc.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id sigma_model_id[]; /* Find the id number assigned to known Sigma camera models. */ /* This number is used to dispatch print and interpret routines */ /* apporopriate to the current image. */ int sigma_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &sigma_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine based upon model */ void print_sigma_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { int noteversion = 0; if(entry_ptr && (PRINT_VALUE)) { noteversion = getnoteversion(); switch(noteversion) { case 1: print_sigma1_makervalue(entry_ptr,make,model,prefix); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for sigma cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_sigma1_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for sigma */ /* cameras. */ void print_sigma_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) { int noteversion = 0; if(entry_ptr) { noteversion = getnoteversion(); switch(noteversion) { case 1: sigma1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix, indent,make,model,at_offset); break; } } } /* Model-specific routine to print values found at an offset from the */ /* IFD entry in sigma makernotes. */ void sigma1_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) { char *nameoftag; char *fulldirname = NULL; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); switch(entry_ptr->tag) { default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } } /* The tagname routine is the first place in the code path which */ /* requires knowledge of the note version. If the version is not */ /* given in the model table (e.g. the model is unknown), then switch */ /* code in find_maker_scheme() should have set it. This routine */ /* repeats the check for non-zero noteversion and is prepared to set */ /* the noteversion first time through, but should never need to do */ /* so. Noteversion should always be non-zero; it should be set to -1 */ /* if generic processing is required. */ char * maker_sigma_tagname(unsigned short tag,int model) { char *tagname = CNULL; int noteversion = 0; if((noteversion = getnoteversion()) == 0) { /* Need more model samples before it is safe to assume a */ /* default */ noteversion = 1; setnoteversion(1); } switch(noteversion) { case 1: tagname = maker_sigma1_tagname(tag,model); break; default: break; } /* If no model-specific tag is found, check "generic" tags */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } char * maker_sigma1_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0002: tagname = "CameraSerialNumber"; break; case 0x0003: tagname = "DriveMode"; break; case 0x0004: tagname = "ResolutionMode"; break; case 0x0005: tagname = "AutofocusMode"; break; case 0x0006: tagname = "FocusSetting"; break; case 0x0007: tagname = "WhiteBalance"; break; case 0x0008: tagname = "ExposureMode"; break; case 0x0009: tagname = "MeteringMode"; break; case 0x000A: tagname = "LensFocalLengthRange"; break; case 0x000B: tagname = "ColorSpace"; break; case 0x000C: tagname = "Exposure"; break; case 0x000D: tagname = "Contrast"; break; case 0x000E: tagname = "Shadow"; break; case 0x000F: tagname = "Highlight"; break; case 0x0010: tagname = "Saturation"; break; case 0x0011: tagname = "Sharpness"; break; case 0x0012: tagname = "X3FillLight"; break; case 0x0014: tagname = "ColorAdjustment"; break; case 0x0015: tagname = "AdjustmentMode"; break; case 0x0016: tagname = "Quality"; break; case 0x0017: tagname = "Firmware"; break; case 0x0018: tagname = "Software"; break; case 0x0019: tagname = "AutoBracket"; break; default: break; } return(tagname); } exifprobe-2.0.1+git20170416-3c2b76/LICENSE.EXIFPROBE0000755000000000000000000000311313074742216017041 0ustar rootroot# @(#) $Id: LICENSE.EXIFPROBE,v 1.5 2005/01/30 17:15:57 alex Exp $ All of the files included in the EXIFPROBE distribution are: Copyright (C) 2005 by Duane H. Hesser. All rights reserved. Portions: Copyright (C) 2011-2014 by Hubert Figuiere. Some individual files may be covered by other copyrights. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Authors: Duane H. Hesser Hubert Figuière exifprobe-2.0.1+git20170416-3c2b76/maker_minolta.c0000644000000000000000000021305613074742216017506 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_minolta.c,v 1.28 2005/07/24 21:57:28 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* minolta camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Most of the information used here is due to Dalibor Jelinek at: */ /* http://www.dalibor.cz/minolta/makernote.htm */ /* */ /* The F100 and "X" models *appear* to use the same MakerNote tagset */ /* as used for Sanyo models, as decoded by John Hawkins */ /* http://www.exif.org/makernotes/SanyoMakerNote.html */ /* */ /* NOTE that this is guesswork. Test images I have found for these */ /* models appear to decode properly using the tag numbers from */ /* Hawkinn's Sanyo data. Send mail if you can confirm or deny. */ /* */ /* The EX model MakerNote format is indecipherable. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id minolta_model_id[]; /* Find the identifying number assigned to known Minolta camera */ /* models, and record the noteversion and tagset assigned to that */ /* model. The noteversion is used to dispatch print and interpret */ /* routines approopriate to the current image. */ int minolta_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &minolta_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine based upon the noteversion which has been */ /* assigned. */ void print_minolta_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 1: print_minolta1_makervalue(entry_ptr,make,model,prefix); minolta1_interpret_value(entry_ptr,model); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Maker-specific print routine for minolta cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and might not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_minolta1_makervalue(struct ifd_entry *entry_ptr,int make, int model, char *prefix) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0040: /* ImageByteSize */ chpr += printf("%lu ",entry_ptr->value); if(entry_ptr->count > 1) { printred("# BAD COUNT"); setcharsprinted(chpr); } break; default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for minolta */ /* cameras. */ void print_minolta_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) { int noteversion = 0; if(entry_ptr) { noteversion = getnoteversion(); switch(noteversion) { case 1: minolta1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); minolta1_interpret_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix,indent, make,model,at_offset); break; } } } /* Maker-specific routine to print UNDEFINED values found at offsets */ /* in minolta makernotes. One of these may be supplied for each model */ /* with unique UNDEFINED tags. */ void minolta1_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) { static unsigned long jpegthumbnailoffset = 0UL; unsigned long value_offset; unsigned long dumplength; unsigned long count; unsigned long max_offset = 0; unsigned short marker; char *nameoftag,*tagprefix; char *fulldirname = NULL; int status = 0; int chpr = 0; if(entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0001: /* Camera Settings, old */ case 0x0003: /* Camera Settings, new */ if(at_offset) { if((PRINT_SECTION)) { print_tag_address(SECTION,value_offset,indent,prefix); chpr += printf("<%s> ",nameoftag); chpr += printf("%lu entries",count / 4); } } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",value_offset); } if((PRINT_LONGNAMES)) tagprefix = fulldirname; else tagprefix = nameoftag; max_offset = minolta_camerasetting(inptr,byteorder,model,tagprefix, entry_ptr,value_offset,indent + MEDIUMINDENT); if(PRINT_SECTION) { chpr = newline(0); print_tag_address(SECTION,max_offset - 1,indent,prefix); chpr += printf(" ",nameoftag); } setcharsprinted(chpr); break; case 0x0040: /* ImageByteSize */ break; /* should have a count of 1 */ case 0x0088: /* JpegThumbnailOffset */ /* It's not magic, there's a trick to it. The offset */ /* length will normally be the next entry tag in the */ /* IFD, and this will work iff it is. Remember the */ /* offset and handle it when the length tag is seen. */ /* This is necessary because we do not save entries. */ jpegthumbnailoffset = value_offset; if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",jpegthumbnailoffset); } break; case 0x0089: /* JpegThumbnailLength */ if(jpegthumbnailoffset == 0UL) { printred("# WARNING: JpegThumbnailLength encountered with 0 offset"); break; /* must have the offset. */ } value_offset = jpegthumbnailoffset; count = entry_ptr->value; jpegthumbnailoffset = 0L; /* fall through */ case 0x0081: /* Jpeg Thumbnail */ /* Minolta seems to use EITHER 0x0088/0x0089 OR */ /* 0x0081, not both. */ if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent, prefix); chpr += printf("# Start of JPEG Thumbnail from MakerNote"); chpr += printf(" length %lu",count); } else if(!at_offset && (PRINT_VALUE) && (entry_ptr->tag == 0x0081)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,count); else chpr = printf(":%lu",count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); max_offset = process_jpeg_segments(inptr,value_offset,marker, count,summary_entry,fulldirname, prefix,indent+SMALLINDENT); if(at_offset) { if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1, indent,"-"); chpr += printf("# End of JPEG Thumbnail from MakerNote"); if((PRINT_ENTRY) && !(PRINT_VALUE)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_IFD; summary_entry->subfiletype = THUMBNAIL_TYPE; } } /* make certain we're at the end */ clearerr(inptr); fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0e00: /* PrintIM */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) { chpr += printf("@%lu:%lu",value_offset,count); chpr = newline(chpr); } } process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent); break; case 0x0f00: /* Data */ if(at_offset && (PRINT_ENTRY)) { print_tag_address(ENTRY,value_offset,indent,prefix); print_makertagid(entry_ptr,23," : ",make,model); chpr += printf(" length %-9lu", count); if(Max_undefined == 0) { if(chpr) printred(" (not dumped, use -U)"); } else { if((Max_undefined == DUMPALL) || (Max_undefined > count)) dumplength = count; else dumplength = Max_undefined; chpr = newline(chpr); hexdump(inptr,value_offset,count,dumplength,12, indent,SUBINDENT); chpr = newline(1); } } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,count); else chpr += printf(":%lu", count); if(!(PRINT_VALUE_AT_OFFSET)) chpr += printf(" # UNDEFINED"); } /* make certain we're at the end */ fseek(inptr,value_offset + count,SEEK_SET); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } /* Minolta-specific tagnames for makernotes. */ /* Minolta models sport at least 9 different MakerNote tagsets that I */ /* have seen. However, the various tagsets do not overlap (if a given */ /* tag number is used in more than 1 model, it is assigned the same */ /* meaning everywhere). This makes it possible to use a single */ /* routine for tagnames, values, interpretations, etc. */ char * maker_minolta_tagname(unsigned short tag,int model) { char *tagname = (char *)0; int noteversion = 0; /* Should have to do this only once, and only for unrecognized */ /* models. If the model is recognized (or the user has forced a */ /* noteversion) noteversion will already be set. */ if((noteversion = getnoteversion()) == 0) { noteversion = 1; setnoteversion(1); } switch(noteversion) { case 1: tagname = maker_minolta1_tagname(tag,model); break; default: break; } /* If no model-specific tag is found, check "generic" tags */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } /* Although several versions of Minolta MakerNotes have been seen in */ /* the wild, there appears to be no duplication of tag numbers (i.e. */ /* no tag number is used for different purposes in one note version */ /* than in another vesion. This makes it possible to treat the notes */ /* as a single version. */ /* For now... */ char * maker_minolta1_tagname(unsigned short tag,int model) { char *tagname = CNULL; /* The Minolta MakerNote of TIFF format images have a JPEG */ /* thumbnail with a defective SOI marker (0x00f8). In fact, */ /* Minolta JPEG_SOI is often missing the high "0xff". */ if(tagname == NULL) { switch(tag) { case 0x0000: tagname = "Version"; break; case 0x0001: tagname = "CameraSettings"; break; case 0x0003: tagname = "CameraSettings"; break; case 0x0040: tagname = "ImageByteSize"; break; case 0x0081: tagname = "JpegThumbnail"; break; case 0x0088: tagname = "JpegThumbnailOffset"; break; case 0x0089: tagname = "JpegThumbnailLength"; break; case 0x0101: tagname = "ColorMode"; break; case 0x0102: tagname = "ImageQuality"; break; case 0x0103: if(model == MINOLTA_DIMAGE7Hi) tagname = "ImageQuality"; else tagname = "ImageSize"; break; /* The following tagname appears valid for at least the */ /* F200, thanks to Harald Puhl (h.puhl@ki-ag.com) */ case 0x0104: tagname = "FlashCompensation"; break; case 0x0200: tagname = "SpecialMode"; break; /* The following tag names appear valid for the F100 and "X" but */ /* do not appear to be used for any other Minolta model. They are */ /* essentially the Sanyo tag set, used here based upon guesswork; */ /* some Minolta and Sanyo cameras are said to use the same chip, */ /* and some F100 and "X" images I've seen contain almost exactly */ /* this set of tags (as described by John Hawkins for Sanyo */ /* DSC-MZ2 notes). The Quality, Macro, SpecialMode and PrintIM */ /* tags are reasonably certain to be correct (they "decode" */ /* properly). The remaining names are less certain, and no */ /* attempt is made to decode them in minolta1_interpret_value()/ */ case 0x0201: tagname = "Quality"; break; case 0x0202: tagname = "Macro"; break; case 0x0204: tagname = "DigiZoom"; break; case 0x0207: tagname = "SoftwareRelease"; break; case 0x0208: tagname = "PictInfo"; break; case 0x0209: tagname = "CameraID"; break; case 0x020e: tagname = "SeqShotMethod"; break; case 0x020f: tagname = "WideRange"; break; case 0x0210: tagname = "ColorAdjMode"; break; case 0x0213: tagname = "QuickShot"; break; case 0x0214: tagname = "SelfTimer"; break; case 0x0216: tagname = "VoiceMemo"; break; case 0x0217: tagname = "RecordShutterRel"; break; case 0x0218: tagname = "FlickerReduce"; break; case 0x0219: tagname = "OpticalZoom"; break; case 0x021b: tagname = "DigitalZoom"; break; case 0x021d: tagname = "LightSourceSpecial"; break; case 0x021e: tagname = "Resaved"; break; case 0x021f: tagname = "SceneSelect"; break; case 0x0223: tagname = "ManualFocusDist"; break; /* ###%%% not seen */ case 0x0224: tagname = "SeqShotIntvl"; break; /* ###%%% not seen */ case 0x0225: tagname = "FlashMode"; break; /* ###%%% not seen */ case 0x0e00: tagname = "PrintIM"; break; case 0x0f00: tagname = "Data"; break; default: break; } } setnotetagset(1); return(tagname); } void minolta1_interpret_value(struct ifd_entry *entry_ptr,int model) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0101: /* ColorMode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Natural"); break; case 1: chpr += printf("Black/White*"); break; case 2: chpr += printf("Vivid"); break; case 3: chpr += printf("Solarize"); break; case 4: chpr += printf("Adobe RGB"); break; case 9: chpr += printf("unknown"); break; case 132: chpr += printf("Adobe RGB Embedded Profile"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0102: /* CameraSettings ImageQuality, 7, 7Hi, F300 */ minolta_7Hi_botch: print_startvalue(); switch(entry_ptr->value) { /* ###%%% jpeg quality/compression? check this */ case 0: chpr += printf("Raw"); break; case 1: chpr += printf("Uncompressed"); break; /* superfine, raw? tiff? */ case 2: chpr += printf("Fine(1/2)"); break; case 3: chpr += printf("Normal(1/3)"); break; /* ###%%% */ case 4: chpr += printf("Economy(1/4)"); break; /* ###%%% */ case 5: chpr += printf("ExtraFine(1/1)"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0103: /* CameraSettings ImageSize*, 7Hi, F300 */ /* The 7Hi appears to get this wrong, printing the same */ /* value for this as for 0x0102; the F300 seems to do it */ /* right. The ImageSize entry in "Camera Settings" */ /* appears correct in both cases. For the 7Hi, it would */ /* be wrong to report this as image size, so just don't */ /* do it. */ if(model == MINOLTA_DIMAGE7Hi) goto minolta_7Hi_botch; print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("1600x1200"); break; case 2: chpr += printf("unknown"); break; /* 1280x960? */ case 3: chpr += printf("640x480"); break; case 4: chpr += printf("unknown"); break; case 5: chpr += printf("2560x1920"); break; case 6: chpr += printf("2272x1704"); break; case 7: chpr += printf("2048x1536"); break; case 13: chpr += printf("3264x2448"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0201: /* Quality, X, F100 */ print_startvalue(); /* ###%%% jpeg quality/compression? check this, same as 0x0102? */ switch(entry_ptr->value) { case 0: chpr += printf("Raw*"); break; case 1: chpr += printf("Economy(1/8)"); break; case 2: chpr += printf("Normal(1/4)"); break; case 3: chpr += printf("Fine(1/2)"); break; case 4: chpr += printf("Uncompressed"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x0202: /* Macro */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Macro"); break; case 2: chpr += printf("View"); break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } void minolta1_interpret_offset_makervalue(FILE *inptr,unsigned short byteorder, struct ifd_entry *entry_ptr,unsigned long fileoffset_base) { unsigned long offset,value; int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { offset = entry_ptr->value + fileoffset_base; switch(entry_ptr->tag) { case 0x0200: /* SpecialMode */ value = read_ulong(inptr,byteorder,offset); print_startvalue(); switch(value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Unkown"); break; case 2: chpr += printf("Fast"); break; case 3: chpr += printf("Panorama,"); value = read_ulong(inptr,byteorder,HERE); chpr += printf("#%lu,",value); value = read_ulong(inptr,byteorder,HERE); switch(value) { case 1: chpr += printf(" Left to Right"); break; case 2: chpr += printf(" Right to Left"); break; case 3: chpr += printf(" Bottom to Top"); break; case 4: chpr += printf(" Top to Bottom"); break; default: printred(" undefined"); break; } break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } /* Interpret the "Camera Settings" tag data from Minolta MakerNotes. */ #include unsigned long minolta_camerasetting(FILE *inptr,unsigned short byteorder,int model, char *tagprefix,struct ifd_entry *entry_ptr,unsigned long offset,int indent) { unsigned long value,end_offset; double fvalue; int i,corr_i,entries; signed char wcorr; int chpr = 0; end_offset = offset + entry_ptr->count; if((PRINT_SECTION)) chpr += printf(" length %lu",entry_ptr->count); if((PRINT_ENTRY)) { entries = entry_ptr->count / 4; for(i = 0; i < entries; ++i) { chpr = newline(chpr); value = read_ulong(inptr,TIFF_MOTOROLA,offset); print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_TAGINFO)) chpr += printf("%s.",tagprefix); offset += 4; /* Very oddly new values are inserted after value 51. */ corr_i=i; if((model != MINOLTA_DIMAGE7Hi) && (model != MINOLTA_DIMAGEA1)) { if (i > 50) corr_i++; } if((model != MINOLTA_DIMAGEA1) && (model != MINOLTA_DIMAGEA2) && (model != MINOLTA_DIMAGEA200)) { if (i > 51) corr_i++; } switch(corr_i) { case 0: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 1: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"ExposureMode"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Programmed Auto"); break; case 1: chpr += printf("Aperture Priority Auto"); break; case 2: chpr += printf("Shuttter Priority Auto"); break; case 3: chpr += printf("Manual"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 2: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"FlashMode"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Fill-Flash"); break; case 1: chpr += printf("Red Eye Reduction"); break; case 2: chpr += printf("Rear Flash Sync"); break; case 3: chpr += printf("Wireless"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 3: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"WhiteBalance"); if((PRINT_VALUE)) { chpr += printf(" = %#lx",value); print_startvalue(); if (value & 0x00ff0000) { /* New style white balance values */ switch(value >> 24) { case 0: printf("Auto"); break; case 1: printf("Daylight"); break; case 2: printf("Cloudy"); break; case 3: printf("Incandescent"); break; case 5: printf("Fluorescent"); break; case 6: printf("Shadow"); break; case 7: printf("Memory1"); break; case 8: printf("Memory2"); break; case 9: printf("Memory3"); break; default: printred("unknown"); break; } wcorr = ((value & 0x00ffffff) >> 16) - 0x80; switch(wcorr) { case 0: break; default: printf(" %+hd", wcorr); break; } } else { /* Old style white balance values */ switch(value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Daylight"); break; case 2: chpr += printf("Cloudy"); break; case 3: chpr += printf("Incandescent"); break; case 5: chpr += printf("Custom"); break; case 7: chpr += printf("Fluorescent"); break; case 8: chpr += printf("Fluorescent2"); break; case 11: chpr += printf("Custom2"); break; case 12: chpr += printf("Custom3"); break; default: printred("unknown"); break; } } print_endvalue(); } break; case 4: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"ImageSize"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { /* ###%%% There should also be a */ /* 2080x1560 size, at least for the A1 */ case 0: switch(model) { case MINOLTA_DIMAGEA2: chpr += printf("3264x2448"); break; case MINOLTA_DIMAGES404: case MINOLTA_DIMAGES414: chpr += printf("2272x1704"); break; case MINOLTA_DIMAGE5: chpr += printf("2048x1536"); break; case MINOLTA_DIMAGEA1: case MINOLTA_DIMAGE7Hi: case MINOLTA_DIMAGE7i: default: chpr += printf("2560x1920"); break; } break; case 1: chpr += printf("1600x1200"); break; case 2: chpr += printf("1280x960"); break; case 3: chpr += printf("640x480"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 5: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"ImageQuality"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("RAW"); break; case 1: chpr += printf("Super Fine"); break; case 2: chpr += printf("Fine"); break; case 3: chpr += printf("Standard"); break; case 4: chpr += printf("Economy"); break; case 5: chpr += printf("Extra Fine"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 6: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"DriveMode"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Single"); break; case 1: chpr += printf("Continuous"); break; case 2: chpr += printf("Self Timer"); break; case 4: chpr += printf("Bracketing"); break; case 5: chpr += printf("Interval"); break; case 6: chpr += printf("UHS Continuous"); break; case 7: chpr += printf("HS Continuous"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 7: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"MeteringMode"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Multi-Segment"); break; case 1: chpr += printf("Center Weighted"); break; case 2: chpr += printf("Spot"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 8: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"CCDSentitivity"); if((PRINT_VALUE)) { if(PRINT_RAW_VALUES) chpr += printf(" = %lu",value); fvalue = ((double)value/8.0) - 1.0; chpr += printf(" = %.3g APEX",fvalue); fvalue = pow(2.0,fvalue) * 3.125; print_startvalue(); chpr += printf("%.3g ISO",fvalue); print_endvalue(); } break; case 9: if((PRINT_TAGINFO)) chpr += printf("%02d_%-21.21s",i,"ShutterSpeed"); if((PRINT_VALUE)) { if(PRINT_RAW_VALUES) chpr += printf(" = %lu",value); if (value == 8) fvalue = 30.0; /* Due to rounding error x=8 should be displayed as 30 sec. */ else { fvalue = ((double)value / 8.0) - 6.0; chpr += printf(" = %.3g APEX",fvalue); fvalue = pow(2.0,-fvalue); } print_startvalue(); chpr += printf("%.3g sec",fvalue); print_endvalue(); } break; case 10: if((PRINT_TAGINFO)) chpr += printf("%02d_%-21.21s",i,"Aperture"); if((PRINT_VALUE)) { if(PRINT_RAW_VALUES) chpr += printf(" = %lu",value); fvalue = (double)value/8.0 - 1.0; chpr += printf(" = %.3g APEX",fvalue); fvalue = pow(2.0,fvalue/2.0); print_startvalue(); chpr += printf("f%.2g",fvalue); print_endvalue(); } break; case 11: if((PRINT_TAGINFO)) chpr += printf("%02d_%-21.21s",i,"MacroMode"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("On"); break; case 1: chpr += printf("Off"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 12: if((PRINT_TAGINFO)) chpr += printf("%02d_%-21.21s",i,"DigitalZoom"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("Electronic"); break; case 2: chpr += printf("2x"); break; /* FIXME: http://www.dalibor.cz/minolta/makernote.htm says 2 */ case 0xffff: chpr += printf("2x"); break; default: printred("Undefined"); break; } print_endvalue(); } break; case 13: if((PRINT_TAGINFO)) chpr += printf("%02d_%-21.21s",i,"ExposureCompensation"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); chpr += printf("%g EV",(double)value/3.0 - 2); print_endvalue(); } break; case 14: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"BracketStep"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("1/3"); break; case 1: chpr += printf("2/3"); break; case 2: chpr += printf("1"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 15: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 16: if((PRINT_TAGINFO)) /* FIXME: Values don't fit on A1 */ chpr += printf("%02d_%-21.21s",i,"IntervalLength"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value + 1); chpr += printf(" minutes"); } break; case 17: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"IntervalNumber"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 18: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"FocalLength"); if((PRINT_VALUE)) { /* This value is not equal to FocalLength in public EXIF as the public one is tweaked to get 7x zoom to comply with marketing specification. The real zoom is 6.51x. * 3.9333 is 35mm equivalent */ chpr += printf(" = %lu",value); fvalue = (double)value/256.0; print_startvalue(); chpr += printf("%g mm",fvalue); print_endvalue(); } break; case 19: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"FocalDistance"); if((PRINT_VALUE)) { if (value == 0) { chpr += printf(" = infinity"); } else { chpr += printf(" = %lu",value); chpr += printf(" mm"); } } break; case 20: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"FlashFired"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); if(value == 0UL) chpr += printf("No"); else chpr += printf("Yes"); print_endvalue(); } break; case 21: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"Date"); if((PRINT_VALUE)) { chpr += printf(" = %#010lx",value); print_startvalue(); chpr += printf("%02ld:%02ld:%02ld",(value & 0xffff0000) >> 16, (value & 0xff00) >> 8,value & 0xff); print_endvalue(); } break; case 22: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"Time"); if((PRINT_VALUE)) { chpr += printf(" = %#010lx",value); print_startvalue(); chpr += printf("%02ld:%02ld:%02ld",(value & 0xffff0000) >> 16, (value & 0xff00) >> 8,value & 0xff); print_endvalue(); } break; case 23: if((PRINT_TAGINFO)) chpr += printf("%02d_%-21.21s",i,"MaxAperture"); if((PRINT_VALUE)) { if(PRINT_RAW_VALUES) chpr += printf(" = %lu",value); fvalue = (double)value/8.0 - 1.0; chpr += printf(" = %.3g APEX",fvalue); fvalue = pow(2.0,fvalue/2.0); print_startvalue(); chpr += printf("f%.2g",fvalue); print_endvalue(); } break; case 24: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 25: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 26: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"FileNumberMemory"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); if(value == 0UL) chpr += printf("Off"); else chpr += printf("On"); print_endvalue(); } break; case 27: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"LastFileNumber"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); /* 0 if FileNumberMemory is off */ if(value == 0) { print_startvalue(); chpr += printf("(FileNumberMemory Off)"); print_endvalue(); } } break; case 28: if((PRINT_TAGINFO)) chpr += printf("%02d_%-21.21s",i,"WhiteBalanceRed"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); chpr += printf("%.3f",value/256.0); print_endvalue(); } break; case 29: /* Warning! Green white balance coefficient in */ /* raw file may not be equal to one and in this */ /* case WB coefficients stored in raw file will */ /* not match those stored here. */ if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"WhiteBalanceGreen"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); chpr += printf("%.3f",value/256.0); print_endvalue(); } break; case 30: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"WhiteBalanceBlue"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); chpr += printf("%.3f",value/256.0); print_endvalue(); } break; case 31: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"Saturation"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); if ((model == MINOLTA_DIMAGEA1) || (model == MINOLTA_DIMAGEA2) || (model == MINOLTA_DIMAGEA200)) chpr += printf("%+ld",value-5); else chpr += printf("%+ld",value-3); print_endvalue(); } break; case 32: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"Contrast"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); if ((model == MINOLTA_DIMAGEA1) || (model == MINOLTA_DIMAGEA2) || (model == MINOLTA_DIMAGEA200)) chpr += printf("%+ld",value-5); else chpr += printf("%+ld",value-3); print_endvalue(); } break; case 33: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"Sharpness"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Hard"); break; case 1: chpr += printf("Normal"); break; case 2: chpr += printf("Soft"); break; case 3: chpr += printf("None"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 34: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"Subject Program"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("None"); break; case 1: chpr += printf("Portrait"); break; case 2: chpr += printf("Text"); break; case 3: chpr += printf("Night Portrait"); break; case 4: chpr += printf("Sunset"); break; case 5: chpr += printf("Sports Action"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 35: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"FlashCompensation"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); fvalue = ((double)value - 6.0) / 3.0; print_startvalue(); chpr += printf("%g EV",fvalue); print_endvalue(); } break; case 36: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"ISO Setting"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("100"); break; case 1: chpr += printf("200"); break; case 2: chpr += printf("200"); break; case 3: chpr += printf("800"); break; case 4: chpr += printf("Auto"); break; case 5: chpr += printf("64"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 37: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"CameraModel"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("DiMAGE 7"); break; case 1: chpr += printf("DiMAGE 5"); break; case 2: chpr += printf("DiMAGE S304"); break; case 3: chpr += printf("DiMAGE S404"); break; case 4: chpr += printf("DiMAGE 7i"); break; case 5: chpr += printf("DiMAGE 7Hi"); break; case 6: chpr += printf("DiMAGE A1"); break; case 7: chpr += printf("DiMAGE (A2 or S414)"); break; /* A200 doesn't appear to have */ /* CameraSettings */ default: printred("unknown"); break; } print_endvalue(); } break; case 38: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"IntervalMode*"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) /* FIXME: verify it */ { case 0: chpr += printf("Still Image"); break; case 1: chpr += printf("Time Lapse"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 39: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"FolderName"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Standard Form"); break; case 1: chpr += printf("Data Form"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 40: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"ColorMode"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Natural Color"); break; case 1: chpr += printf("Black and White"); break; case 2: chpr += printf("Vivid Color"); break; case 3: chpr += printf("Solarization"); break; case 4: chpr += printf("Adobe RGB"); break; case 9: chpr += printf("unknown"); break; case 132: chpr += printf("Adobe RGB Embedded Profile"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 41: /* FIXME: assign values */ if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"ColorFilter"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); switch(model) { case MINOLTA_DIMAGEA2: case MINOLTA_DIMAGEA1: print_startvalue(); switch(value) { case 0: chpr += printf("cool 100%%"); break; case 1: chpr += printf("cool 80%%"); break; case 2: chpr += printf("cool 60%%"); break; case 3: chpr += printf("cool 40%%"); break; case 4: chpr += printf("cool 20%%"); break; case 5: chpr += printf("no cool/warm adjustment"); break; case 6: chpr += printf("warm 20%%"); break; case 7: chpr += printf("warm 40%%"); break; case 8: chpr += printf("warm 60%%"); break; case 9: chpr += printf("warm 80%%"); break; case 10: chpr += printf("warm 100%%"); break; default: chpr += printf("undefined"); break; } print_endvalue(); break; case MINOLTA_DIMAGE7Hi: case MINOLTA_DIMAGE7i: print_startvalue(); switch(value) { case 0: chpr += printf("cool 100%%"); break; case 1: chpr += printf("cool 67%%"); break; case 2: chpr += printf("cool 33%%"); break; case 3: chpr += printf("no cool/warm adjustment"); break; case 4: chpr += printf("warm 33%%"); break; case 5: chpr += printf("warm 67%%"); break; case 6: chpr += printf("warm 100%%"); break; default: chpr += printf("undefined"); break; } print_endvalue(); break; default: /* Print nothing unless the model is */ /* known */ break; } } break; case 42: /* FIXME: assign values */ if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"BWFilter"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 43: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"InternalFlashFired"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("No"); break; case 1: chpr += printf("Yes"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 44: if((PRINT_TAGINFO)) chpr += printf("%02d_%-21.21s",i,"BrightnessValue"); if((PRINT_VALUE)) { if(PRINT_RAW_VALUES) chpr += printf(" = %lu",value); fvalue = ((double)value/ 8.0) - 6.0; chpr += printf(" = %g APEX",fvalue); fvalue = pow(2.0,fvalue); print_startvalue(); chpr += printf("%.3f foot lambert",fvalue); print_endvalue(); } break; case 45: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"SpotFocusPointX"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 46: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"SpotFocusPointY"); if((PRINT_VALUE)) chpr += printf(" = %lu",value); break; case 47: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"WideFocusZone"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); /* FIXME: Different for A1 */ if(model == MINOLTA_DIMAGEA1) chpr += printf("Unknown"); else { switch(value) { case 0: chpr += printf("no zone"); break; case 1: chpr += printf("center zone (horizontal)"); break; case 2: chpr += printf("center zone (vertical)"); break; case 3: chpr += printf("left zone"); break; case 4: chpr += printf("right zone"); break; default: printred("undefined"); break; } } print_endvalue(); } break; case 48: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"FocusMode"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Manual"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 49: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"FocusArea"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Wide"); break; case 1: chpr += printf("Spot"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 50: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"DECPosition"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Exposure"); break; case 1: chpr += printf("Contrast"); break; case 2: chpr += printf("Saturation"); break; case 3: chpr += printf("Filter"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 51: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"ColorProfileEmbedded"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("No"); break; case 1: chpr += printf("Yes"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 52: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"AntiShake"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); } break; case 53: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"DataImprint"); if((PRINT_VALUE)) { chpr += printf(" = %lu",value); print_startvalue(); switch(value) { case 0: chpr += printf("None"); break; case 1: chpr += printf("YYYY/MM/DD"); break; case 2: chpr += printf("MM/DD/HR.MIN"); break; case 3: chpr += printf("Text"); break; case 4: chpr += printf("Text + Id#"); break; default: printred("undefined"); break; } print_endvalue(); } break; default: if((PRINT_TAGINFO)) chpr += printf("%02d:%-21.21s",i,"Unknown"); if((PRINT_VALUE)) chpr += printf(" = %#lx/%lu",value,value); break; } } } setcharsprinted(chpr); return(end_offset); } int maker_minolta_value_is_offset(struct ifd_entry *entry_ptr,int model) { int is_offset = 0; if(entry_ptr) { switch(entry_ptr->tag) { case 0x0040: is_offset = -1; break; /* cancel */ case 0x0088: is_offset = 1; break; case 0x0089: is_offset = -1; break; default: break; } } return(is_offset); } /* I have seen at least 9 Minolta versions, as shown below. */ /* Fortunately, some of the variations are minor, and the tagsets do */ /* not overlap, so it is possible to service all of them with just */ /* one tagset and one set of processing routines. The version strings */ /* in the notes have no apparent meaning. */ /* tagsets: HEX 0,1,10,20,40,81,e00 MLT0 0,1,10,20,40,E00 mlt0 0,3,10,20,40,88,89,E00 MLT0 0,3,10,20,40,88,89,100-103 MLT0 0,4,10,18,20,40,88,89,100-107,10A-10D (MRW) MLT0 0,88,89,100-103,F00 MLY0 0,88,89,100-103,F00,18 (MRW) MLY0 0,200-21F,E00,F00 MLT0 0,81,200-21F,E00,F00 MLT0 */ exifprobe-2.0.1+git20170416-3c2b76/defs.h0000644000000000000000000002513413074742216015610 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: defs.h,v 1.29 2005/07/24 17:04:17 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* General defines, used everywhere */ #ifndef DEFS_INCLUDED #define DEFS_INCLUDED #define HERE (unsigned long)0xffffffff #define FNULL (FILE *)0 #define CNULL (char *)0 #define NULLSTRING "" #define MAXBUFLEN 8192 #define MAXIFDS 1024 #define MAXINDENT 80 #define NOINDENT 0 #define SUBINDENT 2 #define SMALLINDENT 2 #define MEDIUMINDENT 4 #define LARGEINDENT 8 #define ADDRWIDTH 8 #define DUMPALL 0xffffffffUL #define DEF_DUMPLENGTH 64 /* Used for unknown files */ #define DEF_SHORTDUMP 36 /* Used for automatic dumps */ #define HEXTAGNO 0x00000001UL #define DECTAGNO 0x00000002UL #define TAGNO 0x00000003UL #define HEXVALUE 0x00000010UL #define DECVALUE 0x00000020UL #define VALUE 0x00000030UL #define CAMERA_NAMES 0x00000400UL #define FILENAMES 0x00000800UL #define HEXOFFSET 0x00000100UL #define DECOFFSET 0x00000200UL #define OFFSET 0x00000300UL #define TAGNAME 0x00001000UL #define TYPE 0x00002000UL #define TAG_OPTIONS (TAGNO|TAGNAME|TYPE) #define MAKERNOTE_SCHEME 0x00000004UL #define SCHEME_DEBUG 0x00000008UL #define HEXADDRESS 0x00010000UL #define DECADDRESS 0x00020000UL #define ADDRESS 0x00030000UL #define SECTION 0x00040000UL #define SEGMENT 0x00080000UL #define APP_ENTRY 0x00100000UL #define MAKERDUMP 0x00200000UL #define APPNDUMP 0x00400000UL #define IMAGEDUMP 0x00800000UL #define VALUE_AT_OFFSET 0x01000000UL #define RAW_VALUES 0x02000000UL #define RELOFFSET 0x04000000UL #define MULTIVAL_PRINT_ALL 0x08000000UL #define INDENT_AFTER_ADDRESS 0x10000000UL #define INDENT_BEFORE_ADDRESS 0x20000000UL #define ASCII_IGNORE_LENGTH 0x40000000UL #define TTY_COLOR_CHECK 0x00000080UL #define UNICODE_FLAG 0x00004000UL /* write both bytes */ #define ENTRY (TAG_OPTIONS|VALUE|OFFSET|TYPE|RELOFFSET) #define DEF_ENTRY (TAG_OPTIONS|DECVALUE|OFFSET|TYPE) #define LONGNAMES_FLAG 0x00000040UL #define LIST_OPTIONS (TAGNAME|DECVALUE|ASCII_IGNORE_LENGTH|LONGNAMES_FLAG|APP_ENTRY) #define DEFAULT_OPTIONS (SECTION|SEGMENT|DEF_ENTRY|APP_ENTRY|VALUE_AT_OFFSET|DECADDRESS|HEXADDRESS|PCOLOR|INDENT_AFTER_ADDRESS) #define REPORT_OPTIONS (TAGNAME|DECVALUE|PCOLOR|SECTION|SEGMENT|APP_ENTRY|ASCII_IGNORE_LENGTH|INDENT_AFTER_ADDRESS) #define HEX_ONLY (HEXTAGNO|HEXOFFSET|HEXVALUE|HEXADDRESS) #define DECIMAL_ONLY (DECTAGNO|DECOFFSET|DECVALUE|DECADDRESS) #define LIST_MODE ((Print_options & (SECTION|VALUE_AT_OFFSET)) == 0) #define PRINT_ADDRESS (Print_options & (ADDRESS)) #define PRINT_HEX_ADDRESS (Print_options & HEXADDRESS) #define PRINT_DEC_ADDRESS (Print_options & DECADDRESS) #define PRINT_BOTH_ADDRESS ((PRINT_ADDRESS) == (ADDRESS)) #define PRINT_TAGNO (Print_options & (HEXTAGNO|DECTAGNO)) #define PRINT_HEX_TAGNO (Print_options & HEXTAGNO) #define PRINT_DEC_TAGNO (Print_options & DECTAGNO) #define PRINT_BOTH_TAGNO ((PRINT_TAGNO) == (HEXTAGNO|DECTAGNO)) #define PRINT_VALUE (Print_options & (HEXVALUE|DECVALUE)) #define PRINT_HEX_VALUE (Print_options & HEXVALUE) #define PRINT_DEC_VALUE (Print_options & DECVALUE) #define PRINT_BOTH_VALUE ((PRINT_VALUE) == (HEXVALUE|DECVALUE)) #define PRINT_OFFSET (Print_options & (HEXOFFSET|DECOFFSET)) #define PRINT_HEX_OFFSET (Print_options & HEXOFFSET) #define PRINT_DEC_OFFSET (Print_options & DECOFFSET) #define PRINT_BOTH_OFFSET ((PRINT_OFFSET) == (HEXOFFSET|DECOFFSET)) #define PRINT_TAGNAME (Print_options & TAGNAME) #define PRINT_TYPE (Print_options & TYPE) #define PRINT_TAGINFO (Print_options & TAG_OPTIONS) #define PRINT_LONGNAMES (Print_options & LONGNAMES_FLAG) #define PRINT_UNICODE (Print_options & UNICODE_FLAG) #define PRINT_ENTRY (Print_options & ENTRY) #define PRINT_SEGMENT (Print_options & SEGMENT) #define PRINT_SECTION (Print_options & SECTION ) #define PRINT_APPENTRY (Print_options & APP_ENTRY) #define PRINT_ANYTHING (Print_options & (ENTRY|SEGMENT|SECTION)) #define PRINT_INDENT_BEFORE_ADDRESS (Print_options & INDENT_BEFORE_ADDRESS) #define PRINT_INDENT_AFTER_ADDRESS (Print_options & INDENT_AFTER_ADDRESS) #define PRINT_INDENT (Print_options & (INDENT_BEFORE_ADDRESS|INDENT_AFTER_ADDRESS)) #define PRINT_RAW_VALUES (Print_options & RAW_VALUES) #define PRINT_ENTRY_RELOFFSET (Print_options & RELOFFSET) #define PRINT_VALUE_AT_OFFSET (Print_options & VALUE_AT_OFFSET) #define PRINT_ASCII_IGNORE_LENGTH (Print_options & ASCII_IGNORE_LENGTH) #define PRINT_MAKERNOTE_SCHEME (Print_options & MAKERNOTE_SCHEME) #define PRINT_SCHEME_DEBUG (Print_options & SCHEME_DEBUG) #define PRINT_MAKERDUMP (Print_options & MAKERDUMP) #define PRINT_APPNDUMP (Print_options & APPNDUMP) #define PRINT_MULTIVAL_ALL (Print_options & MULTIVAL_PRINT_ALL) #define PRINT_CAMERA_NAMES (Print_options & CAMERA_NAMES) #define PRINT_FILENAMES (Print_options & FILENAMES) #define USE_COLOR (Print_options & PCOLOR) #define CHECK_TTY_FOR_COLOR (Print_options & TTY_COLOR_CHECK) #define PREFIX "" #define UNKNOWN_TYPE -1 #define POSSIBLE_PRIMARY_TYPE 0 /* can't be sure which is primary */ #define PRIMARY_TYPE 1 #define THUMBNAIL_TYPE 2 #define PAGE_TYPE 3 #define MASK_TYPE 4 #define REDUCED_RES_TYPE 5 /* not full size or marked thumbnail */ #define UNKNOWN_STRING NULLSTRING #define POSSIBLE_PRIMARY_STRING "primary?" #define PRIMARY_STRING "primary" #define THUMBNAIL_STRING "thumbnail" #define PAGE_STRING "image page" #define MASK_STRING "image mask" #define REDUCED_RES_STRING "reduced-resolution" #define UNSPECIFIED_STRING "" #define QSTRING "???" #define UNKNOWN_CAMERA_STRING "unknown camera" /* Status of the jpeg processor */ #define JPEG_NO_ERROR 0x0 #define JPEG_EARLY_EOI 0x1 /* found eoi before end of section */ #define JPEG_NO_EOI 0x2 /* soft error */ #define JPEG_NO_SOI 0x4 /* didn't find jpeg */ #define JPEG_HAD_ERROR 0x8 /* failed somewhere after SOI */ /* How many consecutive invalid IFD entries will be tolerated before */ /* admitting that a TIFF IFD is unreadable? */ #define MAX_INVALID_ENTRIES 6 #define TAGWIDTH 27 #define PIMTAGWIDTH 17 /* IFD types */ #define TIFF_IFD 0 #define TIFF_SUBIFD 1 #define EXIF_IFD 2 #define INTEROP_IFD 3 #define GPS_IFD 4 #define MAKER_IFD 5 #define MAKER_SUBIFD 6 #ifdef COLOR #define PCOLOR 0x80000000UL #define PUSHCOLOR(a) pushcolor(a) #define POPCOLOR() popcolor() #else #define PCOLOR 0UL #define PUSHCOLOR(a) #define POPCOLOR() #endif #ifdef COLOR /* numerical values for ANSI color print sequences */ #define GREEN 32 /* "\033[32m" */ #define HI_GREEN 92 /* "\033[92m" */ #define BLUE 34 /* "\033[34m" */ #define HI_BLUE 94 /* "\033[94m" */ #define RED 31 /* "\033[31m" */ #define HI_RED 91 /* "\033[91m" */ #define MAGENTA 35 /* "\033[35m" */ #define HI_MAGENTA 95 /* "\033[95m" */ #define BLACK 30 /* "\033[30m" */ #define HI_BLACK 90 /* "\033[90m" */ #define BG_BLACK 40 /* "\033[40m" */ #define BG_HI_BLACK 100 /* "\033[100m" */ #define BG_WHITE 47 /* "\033[47m" */ #define BG_HI_WHITE 107 /* "\033[107m" */ #define END_COLOR 0 /* "\033[m" */ #define BOLD_COLOR 1 /* "\033[1m" */ /* select colors for file sections */ #define SUMMARY_COLOR HI_BLACK #define EXIF_COLOR MAGENTA #define GPS_COLOR BLACK #define MAKER_COLOR HI_BLUE #define INTEROP_COLOR GREEN #define JPEG_COLOR BLACK #define UNCERTAIN_COLOR HI_BLACK #else #define GREEN 0 #define HI_GREEN 0 #define BLUE 0 #define HI_BLUE 0 #define BOLD_BLUE 0 #define RED 0 #define HI_RED 0 #define BOLD_RED 0 #define BLACK 0 #define HI_BLACK 0 #define BOLD_BLACK 0 #define BG_WHITE 0 #define BG_HI_WHITE 0 #define END_COLOR 0 #define IM_COLOR 0 #define MAKER_COLOR 0 #define EXIF_COLOR 0 #define GPS_COLOR 0 #define INTEROP_COLOR 0 #define JPEG_COLOR 0 #endif /* COLOR */ /* ###%%% temporary? */ #define JPEG_MARKER_DEBUG 0x01 #define JPEG_EOI_DEBUG 0x02 #define SCAN_DEBUG 0x04 #define NOTE_DEBUG 0x08 #define END_OF_SECTION_DEBUG 0x10 #define OUT_DEBUG 0x20 #endif /* DEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/maker_hp.c0000644000000000000000000000260613074742216016447 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_hp.c,v 1.2 2005/07/24 22:56:26 alex Exp $"; #endif #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "maker_extern.h" extern struct camera_id hp_model_id[]; /* Find the identifying number assigned to known Hp camera models. */ int hp_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &hp_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } exifprobe-2.0.1+git20170416-3c2b76/sony_datadefs.h0000644000000000000000000000216713074742216017513 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: sony_datadefs.h,v 1.2 2005/06/21 15:19:54 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef SONY_DATADEFS_INCLUDED #define SONY_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id sony_model_id[] = { { "CYBERSHOT", 9, SONY_CYBERSHOT, 1, 0 }, { "DIGITALMAVICA", 13, SONY_DIGITALMAVICA, 1, 0 }, { "DSC-D700", 7, SONY_DSCD700, 1, 0 }, { "DSC-V3", 6, SONY_DSCV3, 1, 0 }, { "MAVICA", 6, SONY_MAVICA, 1, 0 }, { 0, 0, 0, 0, 0 } }; #endif /* SONY_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/maker_leica.c0000644000000000000000000003533213074742216017117 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_leica.c,v 1.9 2005/07/24 22:56:26 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Leica camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* This information is from a page by Johannes Tschebisch at: */ /* http://www.jojotsch.de/downloads/jojothumb/beispiele/ */ /* html_exif/bilder/leica-digilux4.3.html */ /* */ /* Note that the tags are identical to the fujifilm tags, the format */ /* is the same wierd format as the fuji, and the note even begins */ /* with the string "FUJIFILM". */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id leica_model_id[]; /* Find the identifying number assigned to known Leica camera */ /* models. This number is used to dispatch print and interpret */ /* routines approopriate to the current image. */ int leica_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &leica_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* Dispatch a print routine for direct values in Leica cameras, */ /* based upon model */ void print_leica_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr && (PRINT_VALUE)) { switch(noteversion) { case 1: print_leica1_makervalue(entry_ptr,make,model,PREFIX); leica1_interpret_value(entry_ptr); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Leica cameras. This routine is */ /* responsible for picking off any direct entry tags which are */ /* peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_leica1_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for Leica */ /* cameras. */ void print_leica_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) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 1: leica1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix, indent,make,model,at_offset); break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in Leica makernotes. */ void leica1_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) { if(entry_ptr) { switch(entry_ptr->tag) { default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,parent_name,prefix, indent,make,model,at_offset); break; } } } /* Leica-specific tagnames for makernotes. */ char * maker_leica_tagname(unsigned short tag,int model) { char *tagname = CNULL; int noteversion = 0; /* Should have to do this only once, and only for unrecognized */ /* models. If the model is recognized (or the user has forced a */ /* noteversion) noteversion will already be set. */ if((noteversion = getnoteversion()) == 0) { /* Need more model samples before it is safe to assume a */ /* default */ noteversion = 1; setnoteversion(1); } switch(noteversion) { case 1: tagname = maker_leica1_tagname(tag,model); break; default: break; } /* If no model-specific tag is found, check "generic" tags */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } char * maker_leica1_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0000: tagname = "Version"; break; case 0x1000: tagname = "Quality"; break; case 0x1001: tagname = "Sharpness"; break; case 0x1002: tagname = "WhiteBalance"; break; case 0x1003: tagname = "Color"; break; case 0x1004: tagname = "Tone"; break; case 0x1010: tagname = "FlashMode"; break; case 0x1011: tagname = "FlashStrength"; break; case 0x1020: tagname = "Macro"; break; case 0x1021: tagname = "FocusMode"; break; case 0x1030: tagname = "SlowSync"; break; case 0x1031: tagname = "PictureMode"; break; case 0x1100: tagname = "ContTake-Bracket"; break; case 0x1300: tagname = "BlurWarning"; break; case 0x1301: tagname = "FocusWarning"; break; case 0x1302: tagname = "AEWarning"; break; default: break; } setnotetagset(1); return(tagname); } /* Report the "meaning" of tag values found at offsets in a Leica */ /* MakerNote IFD entry (not at an offset). */ void leica1_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x1001: /* Sharpness */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Soft"); break; case 2: chpr += printf("Soft"); break; case 3: chpr += printf("Normal"); break; case 4: chpr += printf("Hard"); break; case 5: chpr += printf("Hard"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1002: /* White Balance */ print_startvalue(); /* I think we're looking at a bit mask here, but I have */ /* no way to check; this is the way Tachibanaya */ /* characterizes it. */ switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 256: chpr += printf("Daylight"); break; case 512: chpr += printf("Cloudy"); break; case 768: /* ???? */ chpr += printf("DaylightColor-Fluorescent"); break; case 769: /* ???? */ chpr += printf("DaywhiteColor-Fluorescent"); break; case 770: /* ???? */ chpr += printf("White-Fluorescent"); break; case 1024: chpr += printf("Incandescent"); break; case 3840: chpr += printf("Custom"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1003: /* Color Saturation */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Standard"); break; case 256: chpr += printf("High"); break; case 512: chpr += printf("Low"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1004: /* Tone */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Standard"); break; case 256: chpr += printf("High"); break; case 512: chpr += printf("Low"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1010: /* Flash Mode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("On"); break; case 2: chpr += printf("Off"); break; case 3: chpr += printf("Redeye"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1020: /* Macro Mode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1021: /* Focusing Mode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Manual"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1030: /* Slow Sync */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1031: /* Picture Mode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Portrait"); break; case 2: chpr += printf("Landscape"); break; case 4: chpr += printf("Sports"); break; case 5: chpr += printf("Night"); break; case 6: chpr += printf("Program Normal"); break; case 256: chpr += printf("Aperture Priority"); break; case 512: chpr += printf("Shutter Priority"); break; case 768: chpr += printf("Manual"); break; default: printred("undefined"); } print_endvalue(); break; case 0x1100: /* Continuous Take/Bracket */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; case 1: chpr += printf("On"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1300: /* Blur Warning */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Ok"); break; case 1: chpr += printf("Blurred"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1301: /* Focus Warning */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Ok"); break; case 1: chpr += printf("Out of focus"); break; default: printred("undefined"); break; } print_endvalue(); break; case 0x1302: /* AE Warning */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Ok"); break; case 1: chpr += printf("Overexposed"); break; default: printred("undefined"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } /* ID "Leica" tags 0x01-0x2c,0x4449; similar to Panasonic (matches types) (check exiftool) Plain (R9 DMR) tags 0x01-0x10 */ exifprobe-2.0.1+git20170416-3c2b76/maker_asahi.c0000644000000000000000000013043113074742216017123 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_asahi.c,v 1.10 2005/07/24 22:56:26 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Asahi/Pentax camera maker-specific routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* This information is from an image by Johannes Tschebisch at: */ /* http://www.jojotsch.de/downloads/jojothumb/beispiele/ */ /* html_exif/bilder/bilder.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* New info (Jan 05) from Evan Hunter: */ /* http://www.ozhiker.com/electronics/pjmt/jpeg_info/pentax_mn.html */ /* April 05: tagset 3 largely due to Phil Harvey's pages at: */ /* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/index.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "maker_extern.h" #include "extern.h" extern struct camera_id pentax_model_id[]; /* Find the identifying number assigned to known Asahi/Pentax camera */ /* models. This number is used to dispatch print and interpret */ /* routines approopriate to the current image. */ int asahi_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &pentax_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } /* If an unknown model is seen, use the makernote scheme to select a */ /* noteversion to use */ /* There are some assumptions involved in doing this, but there seems */ /* sufficient difference (and distinctive difference) between */ /* Asahi/Pentax schemes to make this reasonable. */ /* v3 has first tag 0x01 (1 SHORT) ID scheme, "PENTAX Corporation" */ /* v2 has first tag 0x02 (2 SHORT) ID scheme, "Asahi Optical" */ /* second tag 0x02 (2 SHORT) */ /* v1 has first tag 0x01 (1 SHORT) ER scheme (no ID), "Asahi Optical" */ /* second tag 0x02 (1 SHORT) */ int set_asahi_noteversion() { struct maker_scheme *scheme; int noteversion = 0; int tagset = 0; scheme = retrieve_makerscheme(); if(scheme->note_version <= 0) { switch(scheme->scheme_type) { case HAS_ID_SCHEME: if(scheme->first_entry.tag == 0x1) { tagset = 3; noteversion = 3; } else { tagset = 2; noteversion = 2; } break; case PLAIN_IFD_SCHEME: tagset = 1; noteversion = 1; break; } setnotetagset(tagset); setnoteversion(noteversion); } else noteversion = scheme->note_version; return(noteversion); } /* Dispatch print routines for direct values in Asahi/Pentax cameras, */ /* based upon previously set noteversion */ void print_asahi_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 3: print_asahi1_makervalue(entry_ptr,make,model,prefix); asahi3_interpret_value(entry_ptr); break; case 2: print_asahi1_makervalue(entry_ptr,make,model,prefix); asahi2_interpret_value(entry_ptr); break; case 1: print_asahi1_makervalue(entry_ptr,make,model,prefix); asahi1_interpret_value(entry_ptr); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific print routine for Asahi/Pentax cameras. This */ /* routine is responsible for picking off any direct entry tags which */ /* are peculiar and will not be handled properly by print_value() */ /* (usually UNDEFINED values which fit in the 4-byte entry value). If */ /* there are no such entries, this function simply calls */ /* print_value(). */ void print_asahi1_makervalue(struct ifd_entry *entry_ptr,int make,int model, char *prefix) { if(entry_ptr) { switch(entry_ptr->tag) { default: print_value(entry_ptr,PREFIX); break; } } } /* Dispatch a routine to decode and print offset values for Asahi/Pentax */ /* cameras. */ void print_asahi_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) { int noteversion = 0; noteversion = getnoteversion(); if(entry_ptr) { switch(noteversion) { case 3: asahi2_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case 2: asahi1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; case 1: asahi1_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base,summary_entry, parent_name,prefix,indent, make,model,at_offset); break; default: print_value(entry_ptr,PREFIX); break; } } } /* Model-specific routine to print UNDEFINED values found at offsets */ /* in Asahi/Pentax makernotes. */ void asahi1_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) { unsigned long value_offset,max_offset; unsigned short marker; unsigned long count; char *nameoftag; char *fulldirname = CNULL; int status = 0; int chpr = 0; if(inptr && entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0004: /* JpegThumbnailOffset */ /* These models provide the 0x2000 tag as well as the */ /* 0x0003/0x0004 tags. Both entries point to the same */ /* thumbnail, so just print values for length and */ /* offset tags, and display the thumbnail on the */ /* (self-contained) 0x2000 tag */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",value_offset); } break; case 0x2000: /* Jpeg Thumbnail as UNDEFINED section */ if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix); chpr += printf("# Start of JPEG Thumbnail from MakerNote"); chpr += printf(" length %lu",count); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu # UNDEFINED",value_offset,count); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); max_offset = process_jpeg_segments(inptr,value_offset,marker, count,summary_entry,fulldirname, prefix,indent+SMALLINDENT); if(at_offset) { if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1, indent,"-"); chpr += printf("# End of JPEG Thumbnail from MakerNote"); if((PRINT_ENTRY) && !(PRINT_VALUE)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_IFD; summary_entry->subfiletype = THUMBNAIL_TYPE; } } /* make certain we're at the end */ clearerr(inptr); fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0e00: /* PrintIM (Epson Print Image matching) */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) { chpr += printf("@%lu:%lu",value_offset,count); chpr = newline(chpr); } } process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr,fileoffset_base, fulldirname,prefix,indent, make,model,at_offset); break; } if(fulldirname) free(fulldirname); } setcharsprinted(chpr); } void asahi2_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) { static unsigned long jpegthumbnaillength = 0UL; unsigned long value_offset,max_offset; unsigned short marker; unsigned long count; char *nameoftag; char *fulldirname = CNULL; int status = 0; int chpr = 0; if(inptr && entry_ptr) { nameoftag = maker_tagname(entry_ptr->tag,make,model); fulldirname = splice(parent_name,".",nameoftag); value_offset = fileoffset_base + entry_ptr->value; count = entry_ptr->count; switch(entry_ptr->tag) { case 0x0003: /* JpegThumbnailLength */ /* Just record it */ jpegthumbnaillength = entry_ptr->value; break; case 0x0004: /* JpegThumbnailOffset */ if(jpegthumbnaillength) { count = jpegthumbnaillength; jpegthumbnaillength = 0; } if(at_offset && (PRINT_SECTION)) { print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix); chpr += printf("# Start of JPEG Thumbnail from MakerNote"); chpr += printf(" length %ld",count); } else if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu:%lu",value_offset,count); else chpr = printf("length %lu",count); } if((PRINT_SECTION) || (PRINT_SEGMENT)) chpr = newline(chpr); marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset); max_offset = process_jpeg_segments(inptr,value_offset,marker, count,summary_entry,fulldirname, prefix,indent+SMALLINDENT); if(at_offset) { if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1, indent,"-"); chpr += printf("# End of JPEG Thumbnail from MakerNote"); if((PRINT_ENTRY) && !(PRINT_VALUE)) chpr = newline(chpr); } } print_jpeg_status(); if(marker && summary_entry) { /* The new one is on the end of the chain */ if((summary_entry = last_summary_entry(summary_entry))) { summary_entry->filesubformat |= FILESUBFMT_MNOTE; summary_entry->datatype = MAKER_IFD; summary_entry->subfiletype = THUMBNAIL_TYPE; } } /* make certain we're at the end */ clearerr(inptr); fseek(inptr,value_offset + count,SEEK_SET); break; case 0x0e00: /* PrintIM (Epson Print Image matching) */ if(!at_offset && (PRINT_VALUE)) { if(!(PRINT_OFFSET)) chpr += printf("@%lu",value_offset); } process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base, count,nameoftag,parent_name,prefix,indent); break; default: print_generic_offset_makervalue(inptr,byteorder,entry_ptr, fileoffset_base, fulldirname,prefix,indent, make,model,at_offset); break; } } setcharsprinted(chpr); } /* Asahi/Pentax-specific tagnames for makernotes. */ char * maker_asahi_tagname(unsigned short tag,int model) { char *tagname = (char *)0; int noteversion = 0; /* Should have to do this only once, and only for unrecognized */ /* models. If the model is recognized (or the user has forced a */ /* noteversion) noteversion will already be set. */ /* This should already have been done in find_maker_scheme(), but */ /* there is no harm in checking noteversion after retrieving it. */ if(((noteversion = getnoteversion()) == 0)) noteversion = set_asahi_noteversion(); switch(noteversion) { case 1: tagname = maker_asahi1_tagname(tag,model); break; case 2: tagname = maker_asahi2_tagname(tag,model); break; case 3: tagname = maker_asahi3_tagname(tag,model); break; default: break; } /* If no model-specific tag is found, check "generic" tags */ if(tagname == NULL) { switch(tag) { case 0x0e00: tagname = "PrintIM"; break; default: break; } } return(tagname); } char * maker_asahi1_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0001: tagname = "CaptureMode"; break; case 0x0002: tagname = "Quality"; break; case 0x0003: tagname = "FocusMode"; break; case 0x0004: tagname = "FlashMode"; break; case 0x0007: tagname = "WhiteBalance"; break; case 0x000a: tagname = "DigitalZoom"; break; case 0x000b: tagname = "Sharpness"; break; case 0x000c: tagname = "Contrast"; break; case 0x000d: tagname = "Saturation"; break; case 0x0014: tagname = "ISOSpeedSetting"; break; case 0x0017: tagname = "Color"; break; case 0x1000: tagname = "TimeZone"; break; case 0x1001: tagname = "DaylightSavings"; break; } setnotetagset(1); return(tagname); } char * maker_asahi2_tagname(unsigned short tag,int model) { char *tagname = CNULL; /* This is the same as Casio note version 2 */ switch(tag) { case 0x0002: tagname = "JpegThumbnailDimensions"; break; case 0x0003: tagname = "JpegThumbnailLength"; break; case 0x0004: tagname = "JpegThumbnailOffset"; break; case 0x0008: tagname = "QualityMode"; break; case 0x0009: tagname = "ImageSize"; break; case 0x000D: tagname = "FocusMode"; break; case 0x0014: tagname = "IsoSensitivity"; break; case 0x0019: tagname = "WhiteBalance"; break; case 0x001D: tagname = "FocalLength"; break; /* units .1mm */ case 0x001F: tagname = "Saturation"; break; case 0x0020: tagname = "Contrast"; break; case 0x0021: tagname = "Sharpness"; break; case 0x2000: tagname = "JpegThumbnail"; break; case 0x2011: tagname = "WhiteBalanceBias"; break; case 0x2012: tagname = "WhiteBalance"; break; case 0x2022: tagname = "ObjectDistance"; break; case 0x2034: tagname = "FlashDistance"; break; case 0x3000: tagname = "RecordMode"; break; case 0x3001: tagname = "SelfTimer?"; break; case 0x3002: tagname = "Quality"; break; case 0x3003: tagname = "FocusMode"; break; case 0x3006: tagname = "TimeZone"; break; case 0x3007: tagname = "BestshotMode"; break; case 0x3014: tagname = "CCDSensitivity"; break; case 0x3015: tagname = "ColorMode"; break; case 0x3016: tagname = "Enhancement"; break; case 0x3017: tagname = "Filter"; break; default: break; } setnotetagset(2); return(tagname); } char * maker_asahi3_tagname(unsigned short tag,int model) { char *tagname = CNULL; switch(tag) { case 0x0001: tagname = "CaptureMode"; break; case 0x0002: tagname = "JpegThumbnailDimensions"; break; case 0x0003: tagname = "JpegThumbnailLength"; break; case 0x0004: tagname = "JpegThumbnailOffset"; break; case 0x0006: tagname = "Date"; break; case 0x0007: tagname = "Time"; break; case 0x0008: tagname = "QualityMode"; break; case 0x0009: tagname = "ImageSize"; break; case 0x000B: tagname = "PictureMode"; break; case 0x000D: tagname = "FocusMode"; break; case 0x0014: tagname = "IsoSensitivity"; break; case 0x0017: tagname = "MeteringMode"; break; case 0x0019: tagname = "WhiteBalance"; break; case 0x001D: tagname = "FocalLength"; break; case 0x001E: tagname = "DigitalZoom"; break; case 0x001F: tagname = "Saturation"; break; case 0x0020: tagname = "Contrast"; break; case 0x0021: tagname = "Sharpness"; break; case 0x0029: tagname = "FrameNumber"; break; case 0x0039: tagname = "RawImageSize"; break; case 0x003F: tagname = "LensType"; break; case 0x0200: tagname = "BlackPoint"; break; case 0x0201: tagname = "WhitePoint"; break; case 0x0402: tagname = "ToneCurve"; break; case 0x0403: tagname = "ToneCurves"; break; default: break; } setnotetagset(3); return(tagname); } /* Report the "meaning" of tag values found at offsets in an */ /* Asahi/Pentax MakerNote IFD entry (not at an offset). */ void asahi1_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0001: /* CaptureMode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Night-scene"); break; case 2: chpr += printf("Manual"); break; case 4: chpr += printf("Multiple"); break; default: break; } print_endvalue(); break; case 0x0002: /* Quality */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Good"); break; case 1: chpr += printf("Better"); break; case 2: chpr += printf("Best"); break; default: break; } print_endvalue(); break; case 0x0003: /* Focus Mode */ print_startvalue(); switch(entry_ptr->value) { case 2: chpr += printf("Custom"); break; case 3: chpr += printf("Auto"); break; default: break; } print_endvalue(); break; case 0x0004: /* Flash Mode */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Auto"); break; case 2: chpr += printf("On"); break; case 4: chpr += printf("Off"); break; case 6: chpr += printf("Red-eye"); break; default: break; } print_endvalue(); break; case 0x0007: /* White Balance */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Daylight"); break; case 2: chpr += printf("Shade"); break; case 3: chpr += printf("Tungsten"); break; case 4: chpr += printf("Fluorescent"); break; case 5: chpr += printf("Manual"); break; default: break; } print_endvalue(); break; case 0x000a: /* Digital Zoom */ if(entry_ptr->value == 0) { print_startvalue(); chpr += printf("Off"); print_endvalue(); } break; case 0x000b: /* Sharpness */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Soft"); break; case 2: chpr += printf("Hard"); break; default: break; } print_endvalue(); break; case 0x000c: /* Contrast */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Low"); break; case 2: chpr += printf("High"); break; default: break; } print_endvalue(); break; case 0x000d: /* Saturation */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Low"); break; case 2: chpr += printf("High"); break; default: break; } print_endvalue(); break; case 0x0014: /* ISO Speed Setting */ print_startvalue(); switch(entry_ptr->value) { case 10: chpr += printf("ISO 100"); break; case 16: chpr += printf("ISO 200"); break; case 100: chpr += printf("ISO 100"); break; case 200: chpr += printf("ISO 200"); break; default: break; } print_endvalue(); break; case 0x0017: /* Color */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Normal"); break; case 2: chpr += printf("Black & White"); break; case 3: chpr += printf("Sepia"); break; default: break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } void asahi2_interpret_value(struct ifd_entry *entry_ptr) { int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0002: /* ThumbnailDimensions" */ chpr += printf(" pixels"); break; case 0x0008: /* QualityMode" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Fine"); break; case 2: chpr += printf("Super Fine"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0009: /* ImageSize" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("640x480"); break; case 4: chpr += printf("1600x1200"); break; case 5: chpr += printf("2048x1536"); break; case 8: chpr += printf("2560x1920"); break; case 20: chpr += printf("2288x1712"); break; case 21: chpr += printf("2592x1944"); break; case 22: chpr += printf("2304x1728"); break; case 23: chpr += printf("2296x3056"); break; case 36: chpr += printf("3008x2008"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x000D: /* FocusMode" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Normal"); break; case 2: chpr += printf("Macro"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0014: /* IsoSensitivity" */ print_startvalue(); switch(entry_ptr->value) { case 3: chpr += printf("50"); break; case 4: chpr += printf("64"); break; case 6: chpr += printf("100"); break; case 9: chpr += printf("200"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0019: /* WhiteBalance" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Daylight"); break; case 2: chpr += printf("Shade"); break; case 3: chpr += printf("Tungsten"); break; case 4: chpr += printf("Fluorescent"); break; case 5: chpr += printf("Manual"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x001D: chpr += printf(" x .1 mm"); break; case 0x001F: /* Saturation" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("-1"); break; case 1: chpr += printf("Normal"); break; case 2: chpr += printf("+1"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0020: /* Contrast" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("-1"); break; case 1: chpr += printf("Normal"); break; case 2: chpr += printf("+1"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0021: /* Sharpness" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("-1"); break; case 1: chpr += printf("Normal"); break; case 2: chpr += printf("+1"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x2012: /* WhiteBalance" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Manual"); break; case 1: chpr += printf("Auto"); break; case 4: chpr += printf("Flash"); break; case 12: chpr += printf("Flash"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x2022: /* ObjectDistance" */ chpr += printf("mm"); break; case 0x2034: /* FlashDistance" */ #if 0 Off? if(entry_ptr->value == 0) { print_startvalue(); chpr += printf("Off"); print_endvalue(); } #endif break; case 0x3000: /* RecordMode" */ print_startvalue(); switch(entry_ptr->value) { case 2: chpr += printf("Normal"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3001: /* SelfTimer?" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Off"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3002: /* Quality" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Economy"); break; case 2: chpr += printf("Normal"); break; case 3: chpr += printf("Fine"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3003: /* FocusMode" */ print_startvalue(); switch(entry_ptr->value) { case 1: chpr += printf("Fixed"); break; case 3: chpr += printf("Single-Area Auto"); break; case 6: chpr += printf("Multi-Area Auto"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3007: /* BestshotMode" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3015: /* ColorMode" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off*"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3016: /* Enhancement" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x3017: /* Filter" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Off"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } void asahi3_interpret_value(struct ifd_entry *entry_ptr) { int year,month,day; int chpr = 0; if(entry_ptr && (PRINT_VALUE)) { switch(entry_ptr->tag) { case 0x0001: /* CaptureMode */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Night-scene"); break; case 2: chpr += printf("Manual"); break; case 4: chpr += printf("Multiple"); break; default: break; } print_endvalue(); break; case 0x0002: /* ThumbnailDimensions" */ chpr += printf(" pixels"); break; case 0x0006: year = ((entry_ptr->value & 0xff) << 8) | ((entry_ptr->value & 0xff00) >> 8); month = ((entry_ptr->value & 0xff0000) >> 16) & 0x7f; day = ((entry_ptr->value & 0xff000000) >> 24) & 0x7f; chpr += printf(" = %4d:%02d:%02d",year,month,day); break; case 0x0008: /* QualityMode" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Good"); break; case 1: chpr += printf("Better"); break; case 2: chpr += printf("Best"); break; case 3: chpr += printf("TIFF"); break; case 4: chpr += printf("RAW"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0009: /* ImageSize" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("640x480"); break; case 1: chpr += printf("Full"); break; case 2: chpr += printf("1024x768"); break; case 4: chpr += printf("1600x1200"); break; case 5: chpr += printf("2048x1536"); break; case 20: chpr += printf("2288x1712"); break; case 21: chpr += printf("2592x1944"); break; case 22: chpr += printf("2304x1728"); break; case 36: chpr += printf("3008x2008"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x000D: /* FocusMode" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Macro(1)"); break; case 2: chpr += printf("Macro(2)"); break; case 3: chpr += printf("Infinity"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0014: /* IsoSensitivity" */ print_startvalue(); switch(entry_ptr->value) { case 3: chpr += printf("50"); break; case 4: chpr += printf("64"); break; case 6: chpr += printf("100"); break; case 9: chpr += printf("200"); break; case 12: chpr += printf("400"); break; case 15: chpr += printf("800"); break; case 18: chpr += printf("1600"); break; case 21: chpr += printf("3200"); break; case 50: chpr += printf("50"); break; case 100: chpr += printf("100"); break; case 200: chpr += printf("200"); break; case 400: chpr += printf("400"); break; case 800: chpr += printf("800"); break; case 1600: chpr += printf("1600"); break; case 3200: chpr += printf("3200"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0017: /* MeteringMode" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Multi Segment"); break; case 1: chpr += printf("Center Weighted"); break; case 2: chpr += printf("Spot"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0019: /* WhiteBalance" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Auto"); break; case 1: chpr += printf("Daylight"); break; case 2: chpr += printf("Shade"); break; case 3: chpr += printf("Fluorescent"); break; case 4: chpr += printf("Tungsten"); break; case 5: chpr += printf("Manual"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x001D: chpr += printf(" x .1 mm"); break; case 0x001F: /* Saturation" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Low"); break; case 2: chpr += printf("High"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0020: /* Contrast" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Low"); break; case 0x10: chpr += printf("Low"); break; case 2: chpr += printf("High"); break; case 0x20: chpr += printf("High"); break; case 3: chpr += printf("Medium Low"); break; case 0x30: chpr += printf("Medium High"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; case 0x0021: /* Sharpness" */ print_startvalue(); switch(entry_ptr->value) { case 0: chpr += printf("Normal"); break; case 1: chpr += printf("Soft"); break; case 0x10: chpr += printf("Soft"); break; case 2: chpr += printf("Hard"); break; case 0x20: chpr += printf("Hard"); break; case 3: chpr += printf("Medium Soft"); break; case 0x30: chpr += printf("Medium Hard"); break; default: chpr += printf("unknown"); break; } print_endvalue(); break; default: break; } } setcharsprinted(chpr); } /* Some makernotes record offsets as LONG values rather than simply */ /* using UNDEFINED with a size; the same technique used for */ /* the ExifIFDPointer itself, or JpegInterchangeFormat, etc. */ /* This routine hardcodes such tags so that the print_makerentry() */ /* routine will present them as offsets. */ /* Asahi has the unfortunate characteristic that tag numbers are */ /* re-used for different purposes in the second version, and one of */ /* those tags is an offset masquerading as a long. */ int maker_asahi_value_is_offset(struct ifd_entry *entry_ptr,int model) { int is_offset = 0; int noteversion = 0; if(entry_ptr) { noteversion = getnoteversion(); switch(noteversion) { case 2: switch(entry_ptr->tag) { case 0x0004: is_offset = 1; break; default: break; } break; case 3: /* A negative value here forces call of the maker offset */ /* value routine, so that the routine may record */ /* information it will need later; the value is not */ /* treated as an offset. */ switch(entry_ptr->tag) { case 0x0003: is_offset = -1; break; case 0x0004: is_offset = 1; break; default: break; } break; case 1: default: break; } } return(is_offset); } /* Tagset 1: 0x01-0x19,0xE00,0x1000,0x1001 330,430 Tagset 2: 0x02-0x04,0x2000-0x2003,0x2011-0x2013,0x2021-0x2023,0x2031-0x2034,03000-0x3007,0x3011-0x3018 (first 4 tags thumbnail, even jpeg, both methods) 330RS,430RS Tagset 3: 0x01-0x0029,0x0E00,0x002E,...,0x002A,0x002C,0x0031,0x0032 Optio550 Tagset 3: 0x01-0x0029,....0x0049,0x0200-0x0216,0x03FF,0x0402 starist (CaptureMode, next 3 thumbnail, dim/length/offset), date & time (6,7) */ exifprobe-2.0.1+git20170416-3c2b76/maker_extern.h0000644000000000000000000007234013074742216017354 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: maker_extern.h,v 1.3 2005/06/25 15:11:43 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* General definitions for makernotes */ #ifndef MAKER_EXTERN_INCLUDED #define MAKER_EXTERN_INCLUDED #include "maker_datadefs.h" /* ====================== Maker functions ========================== */ /* Generic */ extern void print_makertagid(struct ifd_entry *,int,char *,int,int); extern void print_makertaginfo(struct ifd_entry *,char *,int,int,int); extern int maker_value_is_offset(struct ifd_entry *,int,int); extern char *maker_tagname(unsigned short,int,int); extern int check_makernote(FILE*,unsigned long); extern void print_scheme(FILE *,struct maker_scheme *); extern struct maker_scheme *retrieve_makerscheme(); extern void clear_makerscheme(); extern int maker_number(char *); extern int model_number(int,char *,char *); extern struct maker_scheme *find_makerscheme(FILE *,unsigned long, unsigned long, unsigned short, unsigned long, int,int); extern unsigned long print_makerentry(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,int,int,int); extern void print_makervalue(struct ifd_entry *,int,int,char *); extern unsigned long print_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void print_generic_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, char *,char *, int,int,int,int); extern void print_camera_makes(); extern void print_camera_models(struct camera_id *,char *); extern void find_maker_model(struct maker_scheme *,int,int); extern void setnoteversion(int); extern void setoptionnoteversion(int); extern void setnotetagset(int); extern int getnoteversion(); extern int getnotetagset(); /* Agfa */ extern char *maker_agfa_tagname(unsigned short,int); extern char *maker_agfa1_tagname(unsigned short); extern void print_agfa_makervalue(struct ifd_entry *,int,int,char *); extern void print_agfa1_makervalue(struct ifd_entry *,int,int,char *); extern void print_agfa_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void agfa1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char*, int,int,int,int); extern void agfa1_interpret_value(struct ifd_entry *); extern void agfa1_interpret_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long); extern int agfa_model_number(char *,char *); /* Asahi/Pentax */ extern char *maker_asahi_tagname(unsigned short,int); extern char *maker_asahi1_tagname(unsigned short,int); extern char *maker_asahi2_tagname(unsigned short,int); extern char *maker_asahi3_tagname(unsigned short,int); extern void print_asahi_makervalue(struct ifd_entry *,int,int,char *); extern void print_asahi1_makervalue(struct ifd_entry *,int,int,char *); extern void print_asahi_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void asahi1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char*,char *, int,int,int,int); extern void asahi2_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char*,char *, int,int,int,int); extern void asahi1_interpret_value(struct ifd_entry *); extern void asahi2_interpret_value(struct ifd_entry *); extern void asahi3_interpret_value(struct ifd_entry *); extern int asahi_model_number(char *,char *); extern int set_asahi_noteversion(); extern int maker_asahi_value_is_offset(struct ifd_entry *,int ); #include "canon_extern.h" /* Casio */ extern char *maker_casio_tagname(unsigned short,int); extern char *maker_casio1_tagname(unsigned short,int); extern char *maker_casio2_tagname(unsigned short,int); extern int set_casio_noteversion(); extern void print_casio_makervalue(struct ifd_entry *,int,int,char *); extern void print_casio1_makervalue(struct ifd_entry *,int,int,char *); extern void print_casio_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void casio1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void casio2_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void casio1_interpret_value(struct ifd_entry *); extern void casio2_interpret_value(struct ifd_entry *); extern int casio_model_number(char *,char *); extern int maker_casio_value_is_offset(struct ifd_entry *,int ); /* Epson */ extern char *maker_epson_tagname(unsigned short,int); extern char *maker_epson1_tagname(unsigned short,int); extern void print_epson_makervalue(struct ifd_entry *,int,int,char *); extern void print_epson1_makervalue(struct ifd_entry *,int,int,char *); extern void print_epson_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void epson1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void epson1_interpret_value(struct ifd_entry *); extern void epson1_interpret_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long); extern int epson_model_number(char *,char *); /* Fujifilm */ extern char *maker_fujifilm_tagname(unsigned short,int); extern char *maker_fujifilm1_tagname(unsigned short,int); extern void print_fujifilm_makervalue(struct ifd_entry *,int,int,char *); extern void print_fujifilm1_makervalue(struct ifd_entry *,int,int,char *); extern void print_fujifilm_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void fujifilm1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void fujifilm1_interpret_value(struct ifd_entry *); extern int fujifilm_model_number(char *,char *); /* HP */ extern int hp_model_number(char *,char *); /* Kodak */ extern int kodak_model_number(char *,char *); /* Konica */ extern char *maker_konica_tagname(unsigned short,int); /* extern char *maker_konica1_tagname(unsigned short,int); */ extern void print_konica_makervalue(struct ifd_entry *,int,int,char *); extern void print_konica1_makervalue(struct ifd_entry *,int,int,char *); extern void print_konica_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void konica1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern int konica_model_number(char *,char *); /* Kyocera */ extern char *maker_kyocera_tagname(unsigned short,int); extern void print_kyocera_makervalue(struct ifd_entry *,int,int,char *); extern void print_kyocera1_makervalue(struct ifd_entry *,int,int,char *); extern void print_kyocera_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void kyocera1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern int kyocera_model_number(char *,char *); /* Leica */ extern char *maker_leica_tagname(unsigned short,int); extern char *maker_leica1_tagname(unsigned short,int); extern void print_leica_makervalue(struct ifd_entry *,int,int,char *); extern void print_leica1_makervalue(struct ifd_entry *,int,int,char *); extern void print_leica_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void leica1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void leica1_interpret_value(struct ifd_entry *); extern int leica_model_number(char *,char *); /* Minolta */ extern char *maker_minolta_tagname(unsigned short,int); extern char *maker_minolta1_tagname(unsigned short,int); extern void print_minolta_makervalue(struct ifd_entry *,int,int,char *); extern void print_minolta1_makervalue(struct ifd_entry *,int,int,char *); extern void print_minolta_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void minolta1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void minolta1_interpret_value(struct ifd_entry *,int model); extern void minolta1_interpret_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long); extern int minolta_model_number(char *,char *); extern int maker_minolta_value_is_offset(struct ifd_entry *,int ); extern unsigned long minolta_camerasetting(FILE *,unsigned short,int,char *, struct ifd_entry *, unsigned long,int); /* Nikon */ extern char *maker_nikon_tagname(unsigned short,int); extern char *maker_nikon1_tagname(unsigned short,int); extern char *maker_nikon2_tagname(unsigned short,int); extern int set_nikon_noteversion(); extern void print_nikon_makervalue(struct ifd_entry *,int,int,char *); extern void print_nikon_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void nikon1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void nikon2_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void nikon1_interpret_value(struct ifd_entry *); extern void nikon2_interpret_value(struct ifd_entry *); extern void nikon2_interpret_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long,char *, char *,int); extern void nikon_colorbalance(FILE *,struct ifd_entry *,unsigned short, unsigned long,int); extern int nikon_model_number(char *,char *); extern int maker_nikon_value_is_offset(struct ifd_entry *,int ); /* Olympus */ extern char *maker_olympus_tagname(unsigned short,int); extern char *maker_olympus1_tagname(unsigned short,int); extern void print_olympus_makervalue(struct ifd_entry *,int,int,char *); extern void print_olympus1_makervalue(struct ifd_entry *,int,int,char *); extern void print_olympus_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void olympus1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void olympus1_interpret_value(struct ifd_entry *); extern void olympus1_interpret_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long); extern int olympus_model_number(char *,char *); extern void olympus_interpret_pe_value(struct ifd_entry *,unsigned short,char *); extern void olympus2010_interpret_value(struct ifd_entry *,char *); extern void olympus2020_interpret_value(struct ifd_entry *,char *); extern void olympus2030_interpret_value(struct ifd_entry *,char *); extern void olympus2040_interpret_value(struct ifd_entry *,char *); extern void olympus2050_interpret_value(struct ifd_entry *,char *); extern void olympus_offset_pe_value(FILE *,unsigned short,struct ifd_entry *, unsigned long,unsigned short, struct image_summary *, char *,char*,int,int,int,int); extern void olympus1_offset_pe_value(FILE *,unsigned short,struct ifd_entry *, unsigned long,unsigned short, struct image_summary *, char *,char*,int,int,int,int); extern void olympus2010_offset_value(FILE *,unsigned short,struct ifd_entry *, unsigned long, struct image_summary *, char *,char*, int,int,int,int); extern void olympus2020_offset_value(FILE *,unsigned short,struct ifd_entry *, unsigned long, struct image_summary *, char *,char*, int,int,int,int); extern void olympus2030_offset_value(FILE *,unsigned short,struct ifd_entry *, unsigned long, struct image_summary *, char *,char*, int,int,int,int); extern void olympus2040_offset_value(FILE *,unsigned short,struct ifd_entry *, unsigned long, struct image_summary *, char *,char*, int,int,int,int); extern void olympus2050_offset_value(FILE *,unsigned short,struct ifd_entry *, unsigned long, struct image_summary *, char *,char*, int,int,int,int); extern void olympus1_interpret_offset_pe_value(FILE *,unsigned short, struct ifd_entry *,unsigned long, unsigned short); extern void olympus2010_interpret_offset_value(FILE *,unsigned short, struct ifd_entry *,unsigned long); extern void olympus2020_interpret_offset_value(FILE *,unsigned short, struct ifd_entry *,unsigned long); extern void olympus2030_interpret_offset_value(FILE *,unsigned short, struct ifd_entry *,unsigned long); extern void olympus2040_interpret_offset_value(FILE *,unsigned short, struct ifd_entry *,unsigned long); extern void olympus2050_interpret_offset_value(FILE *,unsigned short, struct ifd_entry *,unsigned long); extern char *olympus_private_tagname(unsigned short,unsigned short); extern char *olympus_private_2010_tagname(unsigned short); extern char *olympus_private_2020_tagname(unsigned short); extern char *olympus_private_2030_tagname(unsigned short); extern char *olympus_private_2040_tagname(unsigned short); extern char *olympus_private_2050_tagname(unsigned short); extern int olympus_private_value_is_offset(unsigned short,unsigned short); extern int olympus2020_value_is_offset(unsigned short); /* Panasonic */ extern char *maker_panasonic_tagname(unsigned short,int); extern char *maker_panasonic1_tagname(unsigned short,int); extern void print_panasonic_makervalue(struct ifd_entry *,int,int,char *); extern void print_panasonic1_makervalue(struct ifd_entry *,int,int,char *); extern void print_panasonic_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void panasonic1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void panasonic1_interpret_value(struct ifd_entry *); extern void panasonic1_interpret_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long); extern int panasonic_model_number(char *,char *); /* Ricoh */ extern int ricoh_model_number(char *,char *); /* Sanyo */ extern char *maker_sanyo_tagname(unsigned short,int); extern char *maker_sanyo1_tagname(unsigned short,int); extern void print_sanyo_makervalue(struct ifd_entry *,int,int,char *); extern void print_sanyo1_makervalue(struct ifd_entry *,int,int,char *); extern void print_sanyo_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void sanyo1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void sanyo1_interpret_value(struct ifd_entry *); extern void sanyo1_interpret_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long); extern int sanyo_model_number(char *,char *); /* Sigma */ extern char *maker_sigma_tagname(unsigned short,int); extern char *maker_sigma1_tagname(unsigned short,int); extern void print_sigma_makervalue(struct ifd_entry *,int,int,char *); extern void print_sigma1_makervalue(struct ifd_entry *,int,int,char *); extern void print_sigma_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void sigma1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern int sigma_model_number(char *,char *); /* Sony */ extern char *maker_sony_tagname(unsigned short,int); /* extern char *maker_sony1_tagname(unsigned short,int); */ extern void print_sony_makervalue(struct ifd_entry *,int,int,char *); extern void print_sony1_makervalue(struct ifd_entry *,int,int,char *); extern void print_sony_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void sony1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern int sony_model_number(char *,char *); /* Toshiba */ extern char *maker_toshiba_tagname(unsigned short,int); /* extern char *maker_toshiba1_tagname(unsigned short,int); */ extern void print_toshiba_makervalue(struct ifd_entry *,int,int,char *); extern void print_toshiba1_makervalue(struct ifd_entry *,int,int,char *); extern void print_toshiba_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void toshiba1_offset_makervalue(FILE *,unsigned short, struct ifd_entry *, unsigned long, struct image_summary *, char *,char *, int,int,int,int); extern void toshiba1_interpret_value(struct ifd_entry *); extern int toshiba_model_number(char *,char *); /* Traveler */ extern int traveler_model_number(char *,char *); #endif /* MAKER_EXTERN_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/maker_ricoh.c0000644000000000000000000000262213074742216017142 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_ricoh.c,v 1.2 2005/07/24 22:56:27 alex Exp $"; #endif #include #include #include #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "maker_extern.h" extern struct camera_id ricoh_model_id[]; /* Find the identifying number assigned to known Ricoh camera models. */ int ricoh_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &ricoh_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } exifprobe-2.0.1+git20170416-3c2b76/version.h0000644000000000000000000000043213074742216016346 0ustar rootroot/* Version information for exifprobe */ /* @(#) $Id: version.h,v 1.17 2005/07/24 23:07:57 alex Exp $ */ char *Copyright = "Copyright (C) 2005 Duane H. Hesser, (C) 2011-2015 Hubert Figuiere"; char *Program_version = "2.1.0"; #define PATCHLEVEL 0 exifprobe-2.0.1+git20170416-3c2b76/maker_datadefs.h0000644000000000000000000000441013074742216017613 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: maker_datadefs.h,v 1.1 2005/05/25 15:38:08 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef MAKER_DATADEFS_INCLUDED #define MAKER_DATADEFS_INCLUDED #include "maker.h" struct maker_scheme { unsigned long scheme_type; unsigned long note_fileoffset; unsigned long note_length; char *id; /* Initial id string, if present */ int id_length; /* length of ID string, if present */ int tiffhdr_offset; /* from start of section, if present */ int ifd_offset; /* from start of section or tiff hdr */ int num_entries; /* read from the start of the IFD */ int offsets_relative_to; /* tiffheader, start of note, entry */ int no_nextifd_offset; /* some don't include nextifd_offset */ int make; /* the internal identifier for make */ int model; /* the internal identifier for model */ int note_version; /* for makes with multiple note versions */ int tagset; /* usually same as model_version... */ unsigned long fileoffset_base; /* entry offsets relative to this */ /* if not entry-relative */ unsigned short tiff_byteorder; /* main file byte order */ unsigned short note_byteorder; /* may be different */ struct ifd_entry first_entry; }; struct camera_id { char *name; int namelen; int id; int noteversion; int notetagset; }; struct camera_name { char *name; int namelen; int id; struct camera_id *model; }; #endif /* MAKER_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/README.md0000644000000000000000000000066113074742216015773 0ustar rootroot This is a “fork” of exifprobe, a tool to probe Exif and other digital camera RAW files. Based on the 2.0.1 tarball as found in Debian. Current maintainer: Hubert Figuière Original maintainer: Duane H. Hesser See file LICENSE.EXIFPROBE for the license (basically a 3 clause BSD). SECURITY NOTE ============= This software hasn't been reviewed for security. Don't run it as root. Beware running it on untrusted source data.exifprobe-2.0.1+git20170416-3c2b76/x3f.h0000644000000000000000000000204613074742216015364 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: x3f.h,v 1.2 2005/07/09 15:31:22 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef X3F_INCLUDED #define X3F_INCLUDED /* X3F */ #define X3F_IMAG 0x47414d49 #define X3F_IMA2 0x32414d49 #define X3F_CAMF 0x464d4143 #define X3F_PROP 0x504f5250 #define X3FTAGWIDTH 18 #include "x3f_datadefs.h" #include "x3f_extern.h" #endif /* X3F_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/ciff.c0000644000000000000000000023027413074742216015574 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: ciff.c,v 1.8 2005/07/24 17:03:18 alex Exp $"; #endif /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Canon CIFF/CRW routines */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* The information coded here is derived from the CIFF specification */ /* found at */ /* http://xyrion.org/ciff/CIFFspecV1R04.pdf */ /* with additional information from Phil Harvey's website at: */ /* http://www.sno.phy.queensu.ca/~phil/exiftool/canon_raw.html */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include #include #include #include #include "defs.h" #include "datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "tags.h" #include "extern.h" #include "ciff.h" #include "canon_extern.h" #include "maker_extern.h" unsigned long process_ciff(FILE *inptr,struct fileheader *header,unsigned long fileoffset_base, unsigned long heaplength,struct image_summary *summary_entry, char *parent_name,int level,int indent) { struct ciff_header *ciffheader; unsigned long max_offset = 0UL; unsigned short byteorder = 0; unsigned long heap_start = 0UL; unsigned long offset_table_end = 0UL; if(inptr) { if(header) { if(header->ciff_header) { ciffheader = header->ciff_header; byteorder = ciffheader->byteorder; heap_start = fileoffset_base + ciffheader->headerlength; if(heaplength) offset_table_end = fileoffset_base + heaplength; else if(fseek(inptr,0L,SEEK_END) == 0) offset_table_end = ftell(inptr); if(ferror(inptr) == 0) { max_offset = process_ciff_dir(inptr,heap_start,offset_table_end, ciffheader->subtype,parent_name, summary_entry,byteorder, level,indent); if(max_offset > 0L) max_offset += 4; } else fprintf(stderr,"%s: cannot read offset table\n",Progname); } else fprintf(stderr,"%s: null ciffheader to process_ciff()\n",Progname); } else fprintf(stderr,"%s: null fileheader to process_ciff()\n",Progname); } else fprintf(stderr,"%s: no open file pointer to read Print Image data\n", Progname); return(max_offset); } unsigned long process_ciff_dir(FILE *inptr,unsigned long start_offset,unsigned long end_offset, char *subtype,char *dirname,struct image_summary * summary_entry, unsigned short byteorder,int level,int indent) { struct ciff_direntry *entry; unsigned long dircount_loc; unsigned long max_dir_offset = 0L; unsigned long entry_offset,entry_offset_start; unsigned long next_entry_offset,dir_offset; unsigned short num_entries; char *tablename = CNULL; int i; int chpr = 0; dircount_loc = read_ulong(inptr,byteorder,end_offset - 4) + start_offset; num_entries = read_ushort(inptr,byteorder,dircount_loc); entry_offset = entry_offset_start = dircount_loc + 2; entry = NULL; max_dir_offset = start_offset; /* Show where this directory is in the heap */ print_tag_address(SECTION|ENTRY,start_offset,indent,"@"); if((PRINT_SECTION && dirname)) { chpr += printf("<%s> HEAP, length %lu",dirname,end_offset - start_offset); chpr = newline(chpr); } else { if((PRINT_TAGINFO)) { /* Always want to know WHICH heap offset */ chpr += printf("%s.",dirname); chpr += printf("%-*.*s",CIFFTAGWIDTH,CIFFTAGWIDTH,"HeapOffset"); } if((PRINT_VALUE)) { if(PRINT_BOTH_OFFSET) chpr += printf(" = @%#lx=%lu",start_offset,start_offset); else if(PRINT_HEX_OFFSET) chpr += printf(" = @%#lx",start_offset); else chpr += printf(" = @%lu",start_offset); } chpr = newline(chpr); } /* Now burrow down to the bottom, recursively. This will show the */ /* lower level directories and entries first. */ for(i = 0; i < num_entries; ++i) { entry = read_ciff_direntry(inptr,entry,byteorder,entry_offset); if(ferror(inptr)) { fprintf(stderr,"%s: error reading directory entry at %lu\n", Progname,entry_offset); break; } if(entry == NULL) { fprintf(stderr,"%s: null entry %d\n",Progname,i); break; } next_entry_offset = ftell(inptr); dir_offset = process_ciff_direntry(inptr,CIFF_INHEAP,byteorder,entry,start_offset, dirname,summary_entry,level,indent); entry_offset = next_entry_offset; } /* Next show the directory info; this will display higher level */ /* directories and their direct entry values as the recursive */ /* calls unwind back to the top. */ if(PRINT_SECTION) { if(level == 0) { if(subtype && (strncmp(subtype,"JPGM",4) == 0)) tablename = splice(dirname,".","ImageProperties"); else tablename = splice(dirname," ","offset table"); print_tag_address(SECTION,dircount_loc,indent,"@"); chpr += printf("<%s> %u entries",tablename,num_entries); } else { dirname = dirname ? dirname : QSTRING; print_tag_address(SECTION,dircount_loc,indent+MEDIUMINDENT,"@"); chpr += printf("<%s DIRECTORY>, %u entries",dirname,num_entries); indent += MEDIUMINDENT; } chpr = newline(chpr); } entry_offset = entry_offset_start; max_dir_offset = start_offset; for(i = 0; i < num_entries; ++i) { entry = read_ciff_direntry(inptr,entry,byteorder,entry_offset); next_entry_offset = ftell(inptr); if((PRINT_SECTION)) { print_tag_address(ENTRY,entry_offset,indent + MEDIUMINDENT,"@"); print_ciff_taginfo(entry,start_offset); } if(PRINT_VALUE) { print_ciff_value(inptr,entry,byteorder,start_offset,entry_offset, dirname,summary_entry ,level,indent); } entry_offset = next_entry_offset; if(entry_offset > max_dir_offset) max_dir_offset = entry_offset; } /* Close off the directory; at the top, report the location of */ /* the offset table (or top level directory if JPGM) and loction */ /* where its location was found (at the end of the file). */ if(PRINT_SECTION) { if(level > 0) { print_tag_address(SECTION|ENTRY,max_dir_offset - 1,indent,"-"); dirname = dirname ? dirname : QSTRING; chpr += printf("\n",dirname); print_tag_address(SECTION|ENTRY,end_offset - 4,indent,"-"); chpr += printf("%s DIRECTORY offset = %lu\n",dirname,dircount_loc); print_tag_address(SECTION|ENTRY,end_offset - 1,indent-MEDIUMINDENT,"-"); chpr += printf("",dirname); } else { print_tag_address(SECTION|ENTRY,max_dir_offset - 1,indent,"-"); /* tablename is dynamically allocated */ tablename = tablename ? tablename : strdup(QSTRING); chpr += printf("\n",tablename); print_tag_address(SECTION|ENTRY,end_offset - 4,indent,"-"); chpr += printf("%s location = @%lu",tablename,dircount_loc); } } else if(level == 0) { print_tag_address(SECTION|ENTRY,end_offset - 1,indent,"-"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",dirname); chpr += printf("OffsetTableOffset"); } if((PRINT_VALUE)) chpr += printf(" = @%lu",dircount_loc); } chpr = newline(chpr); if(entry) free(entry); if(tablename) free(tablename); return(max_dir_offset); } /* Print the part of a CIFF entry describing the entry tag, including */ /* it's tag number, name and type. Only the items enabled in */ /* "Print_options" are printed. */ void print_ciff_taginfo(struct ciff_direntry *entry,unsigned long fileoffset_base) { char *nameoftag = NULL; int tagwidth = CIFFTAGWIDTH; unsigned short tag,format,location; int chpr = 0; if(entry && (PRINT_ENTRY)) { tag = entry->type & CIFF_TYPEMASK; format = entry->type & CIFF_FORMATMASK; location = entry->type & CIFF_LOCATIONMASK; if(PRINT_BOTH_TAGNO) chpr += printf("<%#06x=%5u> ",tag,tag); else if(PRINT_DEC_TAGNO) chpr += printf("<%5u> ",tag); else if(PRINT_HEX_TAGNO) chpr += printf("<%#06x> ",tag); if((PRINT_TAGNAME)) { nameoftag = cifftagname(tag); if(nameoftag) { chpr += printf("%-*.*s",tagwidth,tagwidth,nameoftag); free(nameoftag); } } if(PRINT_TYPE) { chpr += printf(" [%#06x ",format); switch(format) { case 0x0000: chpr += printf("BYTE "); break; case 0x0800: chpr += printf("ASCII "); break; case 0x1000: chpr += printf("SHORT "); break; case 0x1800: chpr += printf("LONG "); break; case 0x2000: chpr += printf("STRUCT"); break; case 0x2800: chpr += printf("SUBDIR"); break; case 0x3000: chpr += printf("SUBDIR"); break; case 0x3800: default: chpr += printf("UNDEFINED"); break; } switch(location) { case 0x0000: chpr += printf(" INHEAP %10lu %10lu",entry->length,entry->offset); break; case 0x4000: chpr += printf(" INREC %10lu %10lu",entry->length,entry->offset); break; case 0x8000: chpr += printf(" X8000 %10lu %10lu",entry->length,entry->offset); break; case 0xc000: chpr += printf(" XC000 %10lu %10lu",entry->length,entry->offset); break; default: chpr += printf(" UNKNOWNLOC"); break; } chpr += printf("] "); } /* ###%%% should be done immediately before value is printed; */ /* not here */ if(PRINT_VALUE) chpr += printf(" = "); } setcharsprinted(chpr); } /* Print the "value" portion of a directory entry. If the value is */ /* contained fully within the entry, the direntry processor is needed */ /* to decode the tag value, otherwise, just print the address in the */ /* heap where things have already been handled. */ void print_ciff_value(FILE *inptr,struct ciff_direntry *entry, unsigned short byteorder, unsigned long fileoffset_base,unsigned long entry_offset, char *dirname,struct image_summary *summary_entry, int level,int indent) { unsigned short location; unsigned long max_dir_offset = 0; int chpr = 0; location = entry->type & CIFF_LOCATIONMASK; if(location == CIFF_INREC) { /* chpr += printf("INREC"); */ max_dir_offset = process_ciff_direntry(inptr,CIFF_INREC,byteorder,entry, entry_offset,dirname,summary_entry,level, indent); } else if(PRINT_SECTION) { if(PRINT_BOTH_OFFSET) chpr += printf("@%#lx=%lu",entry->offset + fileoffset_base, entry->offset + fileoffset_base); else if(PRINT_HEX_OFFSET) chpr += printf("@%#lx",entry->offset + fileoffset_base); else /* default to decimal offset if nothing is selected */ chpr += printf("@%lu",entry->offset + fileoffset_base); if(fileoffset_base && (PRINT_ENTRY_RELOFFSET)) chpr += printf(" (%lu) ",entry->offset); chpr = newline(chpr); } setcharsprinted(chpr); } unsigned long canon_colorspace(FILE *inptr,unsigned short byteorder,char *tagprefix, unsigned long offset,unsigned long dirlength,int indent) { unsigned long count,value; unsigned long end_offset; int i; int chpr = 0; if(PRINT_SECTION) { chpr += printf(", length %lu",dirlength); chpr = newline(chpr); } end_offset = offset + dirlength; count = (dirlength / sizeof(unsigned short)); /* There should be just one (no idea why they didn't do it */ /* INRECORD), and there is no 2-byte count */ for(i = 0; i < count; ++i) { value = read_ushort(inptr,byteorder,offset); print_tag_address(ENTRY,offset,indent,"@"); if((PRINT_TAGINFO)) { if(tagprefix && (PRINT_LONGNAMES)) chpr = printf("%s.",tagprefix); chpr = printf("%-*.*s",CIFFTAGWIDTH,CIFFTAGWIDTH,"type"); } if((PRINT_VALUE)) { chpr += printf(" = %lu ",value); if(value == 1) chpr += printf(" = \"real-world\""); else if(value == 2) chpr += printf(" = \"document\""); else if(value == 0xfff) chpr += printf(" = \"uncalibrated\""); else chpr += printf(" = \"undefined\""); } chpr = newline(chpr); offset += 2; } setcharsprinted(chpr); return(end_offset); } /* Decode the "capture time"; print in the Exif "DateTimeOriginal" */ /* format. */ unsigned long canon_ct_to_datetime(FILE *inptr,unsigned short byteorder,char *tagname,unsigned long offset, unsigned long dirlength,int indent) { unsigned long end_offset = 0UL; unsigned long count; unsigned long timezone; unsigned long zoneinfo; struct tm *ts_time; long timestamp; int chpr = 0; if(PRINT_SECTION) { chpr += printf(", length %lu",dirlength); chpr = newline(chpr); } count = dirlength / sizeof(unsigned long); end_offset = offset + dirlength; print_tag_address(ENTRY,offset,indent+MEDIUMINDENT,"@"); tagname = tagname ? tagname : QSTRING; if(PRINT_TAGNAME) chpr += printf("%s",tagname); if(PRINT_VALUE) { chpr += printf(" = "); print_ulong(inptr,count,byteorder,offset); } timestamp = read_ulong(inptr,byteorder,offset); timezone = read_ulong(inptr,byteorder,HERE); zoneinfo = read_ulong(inptr,byteorder,HERE); if(PRINT_VALUE) { ts_time = gmtime(×tamp); chpr += printf(" = %02d:%02d:%02d %02d:%02d:%02d GMT",ts_time->tm_year+1900,ts_time->tm_mon+1, ts_time->tm_mday,ts_time->tm_hour,ts_time->tm_min,ts_time->tm_sec); if((zoneinfo & 0x80000000) && timezone) chpr += printf(" + %lu",timezone); } chpr = newline(chpr); return(end_offset); } /* Print a "value" from a CIFF structure entry, according to the CIFF */ /* type recorded in the entry. Print in hex or decimal (or both) */ /* according to the global Print_options variable. */ /* This is generally undefined data, usually with unknown tagname or */ /* data interpretation. It may be large, so line-by-line output is */ /* avoided in favor of the abbreviated 'print_TYPE()' routines, and */ /* an opportunity is provided to hex/ascii dump the section . */ unsigned long print_ciffinheapdata(FILE *inptr,unsigned short byteorder,char *dirname, char *tagname,unsigned long offset,unsigned long dirlength, unsigned short data_format,int indent) { unsigned long end_offset = 0UL; unsigned long dumplength; unsigned short count; int chpr = 0; if(inptr) { end_offset = offset + dirlength; switch(data_format) { case 0x0000: count = dirlength; break; case 0x0800: count = dirlength; break; case 0x1000: count = dirlength/2; break; case 0x1800: count = dirlength/4; break; default: count = dirlength; break; /* handle as bytes? */ } dirname = dirname ? dirname : QSTRING; tagname = tagname ? tagname : QSTRING; if((PRINT_SECTION)) { print_tag_address(SECTION|ENTRY,offset, indent,"@"); chpr += printf("<%s.%s> data, %u entries, length %lu",dirname,tagname,count,dirlength); chpr = newline(chpr); } if((PRINT_TAGINFO)) { print_tag_address(ENTRY,offset,indent+MEDIUMINDENT,"@"); if((PRINT_LONGNAMES)) chpr += printf("%s.",dirname); chpr += printf("%-*.*s",CIFFTAGWIDTH,CIFFTAGWIDTH,tagname); } if(PRINT_VALUE) { chpr += printf(" = "); switch(data_format) { case 0x1000: /* DC_USHORT */ print_ushort(inptr,count,byteorder,offset); break; case 0x1800: /* DC_UINT32: */ print_ulong(inptr,count,byteorder,offset); break; case 0x0800: /* DC_ASCII: */ print_ascii(inptr,count,offset); break; case 0x0000: /* DC_BYTE: */ print_ubytes(inptr,count,offset); break; default: chpr += printf("(data format %#x)",data_format); break; } if(Max_undefined > 0L) { if((Max_undefined == DUMPALL) || (Max_undefined > dirlength)) dumplength = dirlength; else dumplength = Max_undefined; chpr = newline(chpr); hexdump(inptr,offset,dirlength,dumplength,16,indent+MEDIUMINDENT, MEDIUMINDENT); chpr = newline(chpr); } } if(PRINT_SECTION) { chpr = newline(chpr); print_tag_address(SECTION|ENTRY,end_offset - 1, indent,"-"); dirname = dirname ? dirname : QSTRING; chpr += printf("",dirname,tagname); } setcharsprinted(chpr); } return(end_offset); } /* Print a "value" from a CIFF directory entry when the value is */ /* contained within the record, rather than INHEAP. The data is */ /* printed according to the CIFF type recorded in the entry, in hex */ /* or decimal (or both) according to the global Print_options */ /* variable. */ /* This is generally undefined data, usually with unknown tagname or */ /* data interpretation. */ unsigned long print_ciffinrecdata(FILE *inptr,unsigned short byteorder,char *tagname, unsigned long offset,unsigned long dirlength, unsigned short data_format,int indent) { unsigned long end_offset = 0UL; unsigned short count; int chpr = 0; if(inptr) { end_offset = offset + dirlength; if((PRINT_VALUE)) { count = dirlength; chpr = count; switch(data_format) { case 0x1000: /* DC_USHORT */ print_ushort(inptr,count/2,byteorder,offset); break; case 0x1800: /* DC_UINT32: */ print_ulong(inptr,count/4,byteorder,offset); break; case 0x0800: /* DC_ASCII: */ print_ascii(inptr,count,offset); break; case 0x0000: /* DC_BYTE: */ print_ubytes(inptr,count,offset); break; default: chpr += printf("(data format %#x)",data_format); break; } setcharsprinted(chpr); } } return(end_offset); } unsigned long process_ciff_direntry(FILE *inptr,unsigned short location,unsigned short byteorder, struct ciff_direntry *entry, unsigned long fileoffset_base, char *dirname,struct image_summary *summary_entry,int level, int indent) { unsigned long max_offset = 0; unsigned long endofdir; unsigned short tag,marker,shvalue; char *nameoftag = NULL; char *fullnameoftag = NULL; char *tagname,*makename; int entrywidth = CIFFTAGWIDTH; int status = 0; int chpr = 0; int parindent = 0; int make,model,tagwidth; int makelen; float fvalue; if(entry) { if((entry->type & CIFF_LOCATIONMASK) == location) { chpr = 0; max_offset = fileoffset_base; /* ###%%% if((entry->type & CIFF_LOCATIONMASK) == CIFF_INHEAP) chpr += printf("INHEAP"); */ tag = entry->type & CIFF_TYPEMASK; nameoftag = cifftagname(tag); fullnameoftag = splice(dirname,".",nameoftag); if(PRINT_LONGNAMES) { tagname = fullnameoftag; if(dirname) entrywidth += strlen(dirname) + 1; } else tagname = nameoftag; switch(tag) { case CIFFTAG_COLORINFO2: /* fall through */ case CIFFTAG_COLORINFO1: /* INHEAPDATA */ if((PRINT_SECTION)) indent += MEDIUMINDENT; max_offset = print_ciffinheapdata(inptr,byteorder,dirname, nameoftag,entry->offset + fileoffset_base,entry->length, entry->type&CIFF_FORMATMASK,indent/* +MEDIUMINDENT*/); break; case CIFFTAG_ROMOPERATIONMODE: /* ASCII INREC */ if(!(PRINT_SECTION) && (PRINT_TAGINFO)) { print_tag_address(ENTRY,fileoffset_base + 2,indent+MEDIUMINDENT,"@"); chpr = printf("%-*.*s",entrywidth,entrywidth,tagname); } if(PRINT_VALUE) { print_ascii(inptr,8,fileoffset_base + 2); max_offset = fileoffset_base + 2 + 8; } break; case CIFFTAG_RAWMAKEMODEL: /* ###%%% ASCII SPECIAL */ print_tag_address(ENTRY,entry->offset + fileoffset_base,indent+MEDIUMINDENT, "@"); makename = (char *)read_bytes(inptr, entry->length, entry->offset + fileoffset_base); max_offset = ftell(inptr); Make_name = strdup(makename); makelen = strlen(makename); Model_name = strdup(makename + makelen + 1); dirname = dirname ? dirname : QSTRING; if((LIST_MODE)) { /* Make pseudo-tags and separate Make and */ /* Model */ if(PRINT_TAGNAME) chpr += printf("%s.%-*.*s",dirname,CIFFTAGWIDTH,CIFFTAGWIDTH,"Make"); if(PRINT_VALUE) { chpr += printf(" = \"%s\"",Make_name); if(Use_Make_name) chpr += printf(" (Using: Make=%s)",Use_Make_name); } chpr = newline(chpr); print_tag_address(ENTRY,entry->offset + fileoffset_base + strlen(Make_name) + 1, indent+MEDIUMINDENT,"@"); if(PRINT_TAGNAME) chpr += printf("%s.%-*.*s",dirname,CIFFTAGWIDTH,CIFFTAGWIDTH,"Model"); if(PRINT_VALUE) { chpr += printf(" = \"%s\"",Model_name); if(Use_Make_name) chpr += printf(" (Using: Model=%s)",Use_Model_name); } } else { if(PRINT_TAGNAME) { if((PRINT_SECTION)) chpr += printf("%s.%-*.*s",dirname,CIFFTAGWIDTH,CIFFTAGWIDTH,nameoftag); else chpr += printf("%-*.*s",CIFFTAGWIDTH,CIFFTAGWIDTH,nameoftag); } if(PRINT_VALUE) { chpr += printf(" = "); if((PRINT_ASCII_IGNORE_LENGTH)) chpr += printf("%s\\0%s",Make_name,Model_name); else print_ascii(inptr,entry->length,entry->offset + fileoffset_base); if(Use_Make_name) chpr += printf(" Using: Make=%s",Use_Make_name); if(Use_Model_name) chpr += printf(" Using: Model=%s",Use_Model_name); } } break; case CIFFTAG_FILEDESCRIPTION: /* ASCII INHEAP */ case CIFFTAG_FIRMWAREVERSION: /* ASCII INHEAP */ case CIFFTAG_OWNERNAME: /* ASCII INHEAP */ case CIFFTAG_IMAGETYPE: /* ASCII INHEAP */ case CIFFTAG_ORIGINALFILENAME: /* ASCII INHEAP */ case CIFFTAG_THUMBNAILFILENAME: /* ASCII INHEAP */ print_tag_address(ENTRY,entry->offset + fileoffset_base,indent+MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) chpr = printf("%-*.*s",entrywidth,entrywidth,tagname); if(PRINT_VALUE) { chpr += printf(" = "); print_ascii(inptr,entry->length,entry->offset + fileoffset_base); max_offset = ftell(inptr); } break; case CIFFTAG_BASEISO: /* INREC */ if(!(PRINT_SECTION) && (PRINT_TAGINFO)) { print_tag_address(ENTRY,fileoffset_base + 2,indent+MEDIUMINDENT,"@"); chpr = printf("%-*.*s",entrywidth,entrywidth,tagname); } if(PRINT_VALUE) chpr += printf("%lu",entry->length); max_offset = ftell(inptr); break; case CIFFTAG_FOCALLENGTH: /* INREC */ /* length mm, xy size in .001 inch ###%%% ??? */ if((PRINT_VALUE) && (PRINT_SECTION)) { indent += 19; chpr = printf("{"); chpr = newline(chpr); parindent = charsprinted() - LARGEINDENT; indent += MEDIUMINDENT; } if(PRINT_ENTRY) { entrywidth = strlen("TargetCompressionRatio"); print_tag_address(ENTRY,fileoffset_base + 2,indent + MEDIUMINDENT,"@"); parindent = charsprinted() - LARGEINDENT; if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth,"Undefined"); } if((PRINT_VALUE)) { shvalue = read_ushort(inptr,byteorder,fileoffset_base + 2); printf(" = %u",shvalue); chpr = newline(chpr); } print_tag_address(ENTRY,fileoffset_base + 4,indent + MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth, "FocalLength"); } if((PRINT_VALUE)) { shvalue = read_ushort(inptr,byteorder,fileoffset_base + 4); chpr += printf(" = %u mm",shvalue); chpr = newline(chpr); } print_tag_address(ENTRY,fileoffset_base + 6,indent + MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth, "FocalPlaneXDim"); } if((PRINT_VALUE)) { shvalue = read_ushort(inptr,byteorder,fileoffset_base + 6); chpr += printf(" = %u inches/1000",shvalue); chpr = newline(chpr); } print_tag_address(ENTRY,fileoffset_base + 8,indent + MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth, "FocalPlaneYDim"); } if((PRINT_VALUE)) { shvalue = read_ushort(inptr,byteorder,fileoffset_base + 8); chpr += printf(" = %u inches/1000",shvalue); if(PRINT_SECTION) { chpr = newline(chpr); print_tag_address(ENTRY,fileoffset_base + 9,0,"@"); parindent -= charsprinted(); putindent(parindent); chpr = printf("}"); indent -= MEDIUMINDENT; } } } break; case CIFFTAG_SHOTINFO: /* INHEAP subroutine */ if((PRINT_SECTION)) { PUSHCOLOR(MAKER_COLOR); print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base, indent+MEDIUMINDENT,"@"); chpr += printf("<%s> data, %lu entries",fullnameoftag,(entry->length/sizeof(short)) - 1); indent += MEDIUMINDENT; } max_offset = canon_shotinfo(inptr,byteorder,tagname, entry->offset + fileoffset_base, entry->length,indent+MEDIUMINDENT); if((PRINT_SECTION)) { indent -= MEDIUMINDENT; print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base + entry->length - 1, indent+MEDIUMINDENT,"-"); chpr += printf("",fullnameoftag); POPCOLOR(); } break; case CIFFTAG_CAMERASETTINGS: /* INHEAP subroutine */ if((PRINT_SECTION)) { PUSHCOLOR(MAKER_COLOR); print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base, indent+MEDIUMINDENT,"@"); chpr += printf("<%s> data, %lu entries",fullnameoftag, (entry->length/sizeof(short)) - 1); indent += MEDIUMINDENT; } max_offset = canon_camera_settings(inptr,byteorder, tagname,entry->offset + fileoffset_base, entry->length,indent+MEDIUMINDENT); if((PRINT_SECTION)) { indent -= MEDIUMINDENT; print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base + entry->length - 1, indent+MEDIUMINDENT,"-"); chpr += printf("",fullnameoftag); POPCOLOR(); } break; case CIFFTAG_SENSORINFO: /* INHEAP subroutine */ if((PRINT_SECTION)) { PUSHCOLOR(MAKER_COLOR); print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base, indent+MEDIUMINDENT,"@"); chpr += printf("<%s> data, %lu entries",fullnameoftag,(entry->length/sizeof(short)) - 1); indent += MEDIUMINDENT; } max_offset = canon_sensorinfo(inptr,byteorder,tagname,entry->offset + fileoffset_base, entry->length,indent+MEDIUMINDENT); if((PRINT_SECTION)) { indent -= MEDIUMINDENT; print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base + entry->length - 1, indent+MEDIUMINDENT,"-"); chpr += printf("",fullnameoftag); POPCOLOR(); } break; case CIFFTAG_CUSTOMFUNCTIONS: /* INHEAP subroutine */ if(Use_Make_name) make = maker_number(Use_Make_name); else make = maker_number(Make_name); if(Use_Model_name) model = model_number(make,Use_Model_name,NULLSTRING); else model = model_number(make,Model_name,NULLSTRING); if((PRINT_SECTION)) { PUSHCOLOR(MAKER_COLOR); print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base, indent+MEDIUMINDENT,"@"); chpr += printf("<%s> data, %lu entries",fullnameoftag, (entry->length/sizeof(short)) - 1); indent += MEDIUMINDENT; } max_offset = canon_customfunctions(inptr,byteorder, tagname,entry->offset + fileoffset_base, entry->length,model,indent+MEDIUMINDENT); if((PRINT_SECTION)) { indent -= MEDIUMINDENT; print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base + entry->length - 1, indent+MEDIUMINDENT,"-"); chpr += printf("",fullnameoftag); POPCOLOR(); } break; case CIFFTAG_PICTUREINFO: /* INHEAP subroutine */ if((PRINT_SECTION)) { PUSHCOLOR(MAKER_COLOR); print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base, indent+MEDIUMINDENT,"@"); chpr += printf("<%s> data, %lu entries",fullnameoftag,(entry->length/sizeof(short)) - 1); indent += MEDIUMINDENT; } max_offset = canon_pictureinfo(inptr,byteorder, tagname,entry->offset + fileoffset_base, entry->length,indent+MEDIUMINDENT); if((PRINT_SECTION)) { indent -= MEDIUMINDENT; print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base + entry->length - 1, indent+MEDIUMINDENT,"-"); chpr += printf("",fullnameoftag); POPCOLOR(); } break; case CIFFTAG_WHITEBALANCETABLE: /* INHEAP subroutine */ if((PRINT_SECTION)) { PUSHCOLOR(MAKER_COLOR); print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base, indent+MEDIUMINDENT,"@"); chpr += printf("<%s> data, %lu entries",fullnameoftag, (entry->length - sizeof(unsigned short))/sizeof(float)); indent += MEDIUMINDENT; } max_offset = canon_whitebalancetable(inptr,byteorder,tagname, entry->offset + fileoffset_base,entry->length,indent+MEDIUMINDENT); if((PRINT_SECTION)) { indent -= MEDIUMINDENT; print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base + entry->length - 1, indent+MEDIUMINDENT,"-"); chpr += printf("",fullnameoftag); POPCOLOR(); } break; case CIFFTAG_IMAGESPEC: /* INREC */ if((PRINT_VALUE) && (PRINT_SECTION)) { indent += 19; chpr = printf("{"); chpr = newline(chpr); parindent = charsprinted(); } if(PRINT_ENTRY) { entrywidth = strlen("TargetCompressionRatio"); dirname = dirname ? dirname : QSTRING; print_tag_address(ENTRY,fileoffset_base + 2,indent + LARGEINDENT,"@"); parindent = charsprinted() - LARGEINDENT; if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth,"FileFormat"); } if((PRINT_VALUE)) { chpr += printf(" = "); switch(entry->length) { case 0x10000: chpr += printf("JPEG quantized\n"); break; case 0x10002: chpr += printf("JPEG non-quantized\n"); break; case 0x10003: chpr += printf("JPEG nq picture/q text\n"); break; case 0x20001: chpr += printf("CRW\n"); break; default: chpr += printf("unknown\n"); break; } } print_tag_address(ENTRY,fileoffset_base + 6,indent + LARGEINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth,"TargetCompressionRatio"); } if((PRINT_VALUE)) { fvalue = to_float(entry->offset); chpr += printf(" = %f",fvalue); if(PRINT_SECTION) { chpr = newline(chpr); print_tag_address(ENTRY,fileoffset_base + 9,0,"@"); parindent -= charsprinted(); putindent(parindent); chpr = printf("}"); } } } break; case CIFFTAG_SHUTTERRELEASEMETHOD: /* INREC */ if(!(PRINT_SECTION) && (PRINT_TAGINFO)) { print_tag_address(ENTRY,fileoffset_base + 2,indent + MEDIUMINDENT,"@"); chpr = printf("%-*.*s",entrywidth,entrywidth,tagname); if(PRINT_VALUE) chpr += printf(" = "); } if(PRINT_VALUE) { print_ushort(inptr,4,byteorder,fileoffset_base + 2); chpr += printf("%lu = ",entry->length & 0xffff); if((entry->length & 0xffff) == 0) chpr += printf("single-shot"); else if((entry->length & 0xffff) == 1) chpr += printf("continuous"); else chpr += printf("undefined"); } break; case CIFFTAG_SHUTTERRELEASETIMING: /* INREC */ if(!(PRINT_SECTION) && (PRINT_TAGINFO)) { print_tag_address(ENTRY,fileoffset_base + 2,indent + MEDIUMINDENT,"@"); chpr = printf("%-*.*s",entrywidth,entrywidth,tagname); if(PRINT_VALUE) chpr += printf(" = "); } if(PRINT_VALUE) { print_ushort(inptr,4,byteorder,fileoffset_base + 2); chpr += printf(" = %lu = ",entry->length & 0xffff); if((entry->length & 0xffff) == 0) chpr += printf("shutter-priority"); else if((entry->length & 0xffff) == 1) chpr += printf("aperture-priority"); else chpr += printf("undefined"); } break; case CIFFTAG_SELFTIMERTIME: /* INREC */ if(!(PRINT_SECTION) && (PRINT_TAGINFO)) { print_tag_address(ENTRY,fileoffset_base + 2,indent + MEDIUMINDENT,"@"); chpr = printf("%-*.*s",entrywidth,entrywidth,tagname); } if(PRINT_VALUE) chpr += printf(" = %lu msec ",entry->length & 0xffff); break; case CIFFTAG_TARGETDISTANCESETTING: /* INREC */ if(!(PRINT_SECTION) && (PRINT_TAGINFO)) { print_tag_address(ENTRY,fileoffset_base + 2,indent + MEDIUMINDENT,"@"); chpr = printf("%-*.*s",entrywidth,entrywidth,tagname); } if(PRINT_VALUE) { float fvalue; fvalue = to_float(entry->length); chpr += printf("%f mm",fvalue); } break; case CIFFTAG_COLORSPACE: /* INHEAP subroutine */ if((PRINT_SECTION)) { PUSHCOLOR(MAKER_COLOR); print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base, indent+MEDIUMINDENT,"@"); chpr += printf("<%s> data, %lu entries",fullnameoftag,(entry->length/sizeof(unsigned short))); indent += MEDIUMINDENT; } max_offset = canon_colorspace(inptr,byteorder, tagname,entry->offset + fileoffset_base, entry->length,indent+MEDIUMINDENT); if((PRINT_SECTION)) { indent -= MEDIUMINDENT; print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base + entry->length - 1, indent+MEDIUMINDENT,"-"); chpr += printf("",fullnameoftag); POPCOLOR(); } break; case CIFFTAG_TARGETIMAGETYPE: /* INREC */ if(!(PRINT_SECTION) && (PRINT_TAGINFO)) { print_tag_address(ENTRY,fileoffset_base + 2,indent + MEDIUMINDENT,"@"); chpr = printf("%-*.*s",entrywidth,entrywidth,tagname); if(PRINT_VALUE) chpr += printf(" = "); } if(PRINT_VALUE) { print_ushort(inptr,4,byteorder,fileoffset_base + 2); chpr += printf(" = %lu = ",entry->length & 0xffff); if((entry->length & 0xffff) == 0) chpr += printf("real-world"); else if((entry->length & 0xffff) == 1) chpr += printf("document"); else chpr += printf("undefined"); } break; case CIFFTAG_SERIALNUMBER: /* INREC */ if(!(PRINT_SECTION) && (PRINT_TAGINFO)) { print_tag_address(ENTRY,fileoffset_base + 2,indent + MEDIUMINDENT,"@"); chpr = printf("%-*.*s",entrywidth,entrywidth,tagname); if(PRINT_VALUE) chpr += printf(" = "); } if(PRINT_VALUE) { chpr += printf("%lu",entry->length); print_canon_serialno(entry->length); } break; case CIFFTAG_CAPTUREDTIME: /* INHEAP subroutine */ if((PRINT_SECTION)) { print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base,indent+MEDIUMINDENT, "@"); chpr += printf("<%s> data, %lu entries",fullnameoftag,(entry->length/sizeof(unsigned long))); } max_offset = canon_ct_to_datetime(inptr,byteorder, tagname,entry->offset + fileoffset_base, entry->length,indent+MEDIUMINDENT); if((PRINT_SECTION)) { print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base + entry->length - 1, indent+MEDIUMINDENT,"-"); chpr += printf("",fullnameoftag); POPCOLOR(); } break; case CIFFTAG_EXPOSUREINFO: /* INHEAP, 3 floats; EC, Tv, Av */ if((PRINT_SECTION)) { print_tag_address(SECTION,entry->offset + fileoffset_base,indent+MEDIUMINDENT, "@"); chpr = printf("<%s> data, %lu entries",fullnameoftag,(entry->length/sizeof(unsigned long))); indent += MEDIUMINDENT; } max_offset = canon_exposureinfo(inptr,byteorder,tagname, entry->offset + fileoffset_base, entry->length,indent+MEDIUMINDENT, summary_entry); indent -= MEDIUMINDENT; if((PRINT_SECTION)) { print_tag_address(SECTION,entry->offset + fileoffset_base + entry->length - 1, indent+MEDIUMINDENT,"-"); chpr += printf("",fullnameoftag); POPCOLOR(); } break; case CIFFTAG_IMAGEINFO: /* INHEAP subroutine */ if((PRINT_SECTION)) { print_tag_address(SECTION,entry->offset + fileoffset_base,indent+MEDIUMINDENT, "@"); chpr = printf("<%s> data, %lu entries",fullnameoftag,(entry->length/sizeof(unsigned long))); } max_offset = canon_imageinfo(inptr,byteorder,tagname, entry->offset + fileoffset_base, entry->length,indent+MEDIUMINDENT, summary_entry); if((PRINT_SECTION)) { print_tag_address(SECTION,entry->offset + fileoffset_base + entry->length - 1, indent+MEDIUMINDENT,"-"); chpr += printf("",fullnameoftag); POPCOLOR(); } break; case CIFFTAG_FLASHINFO: /* INREC two floats, flash Guidenumber & Threshold */ if((PRINT_VALUE) && (PRINT_SECTION)) { indent += 19; chpr = printf("{"); chpr = newline(chpr); parindent = charsprinted(); } if(PRINT_ENTRY) { float fvalue; entrywidth = strlen("FlashGuideNumber"); dirname = dirname ? dirname : QSTRING; print_tag_address(ENTRY,fileoffset_base + 2,indent+MEDIUMINDENT,"@"); parindent = charsprinted() - MEDIUMINDENT; if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth,"FlashGuideNumber"); } if((PRINT_VALUE)) { fvalue = to_float(entry->length); chpr += printf(" = %f",fvalue); } chpr = newline(chpr); print_tag_address(ENTRY,fileoffset_base + 6,indent+MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { if((PRINT_LONGNAMES)) chpr += printf("%s.",fullnameoftag); chpr += printf("%-*.*s",entrywidth,entrywidth, "FlashThreshold"); } if((PRINT_VALUE)) { fvalue = to_float(entry->offset); chpr += printf(" = %f",fvalue); } } if(PRINT_SECTION) { chpr = newline(chpr); print_tag_address(ENTRY,fileoffset_base + 9,0,"@"); parindent -= charsprinted(); putindent(parindent); chpr = printf("}"); } break; case CIFFTAG_MEASUREDEV: /* INREC */ if(!(PRINT_SECTION) && (PRINT_TAGINFO)) { print_tag_address(ENTRY,fileoffset_base + 2,indent+MEDIUMINDENT,"@"); chpr = printf("%-*.*s",entrywidth,entrywidth,tagname); } if(PRINT_VALUE) { float fvalue; fvalue = to_float(entry->length); chpr += printf("%f",fvalue); } break; case CIFFTAG_RAWIMAGEDATA: /* INHEAP */ if(PRINT_SECTION) { print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base, indent,"@"); chpr += printf("Start of %s, length %lu\n",nameoftag,entry->length); if((PRINT_VALUE)) dumpsection(inptr,entry->offset + fileoffset_base,entry->length,indent + SMALLINDENT); print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base + entry->length - 1, indent,"@"); chpr += printf("End of %s",nameoftag); } else { print_tag_address(ENTRY,entry->offset + fileoffset_base, indent+MEDIUMINDENT,"@"); /* pseudo-tags */ if(PRINT_TAGINFO) chpr += printf("%s.%-*.*s",dirname,CIFFTAGWIDTH,CIFFTAGWIDTH,nameoftag); if((PRINT_ENTRY)) { if((PRINT_VALUE)) { if(PRINT_BOTH_OFFSET) chpr += printf(" = @%#lx=%lu",entry->offset + fileoffset_base, entry->offset + fileoffset_base); else if(PRINT_HEX_OFFSET) chpr += printf(" = @%#lx",entry->offset + fileoffset_base); else chpr += printf(" = @%lu",entry->offset + fileoffset_base); if(fileoffset_base && (PRINT_ENTRY_RELOFFSET)) chpr += printf(" (%lu)",entry->offset); } chpr = newline(chpr); print_tag_address(ENTRY,0,indent+MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { tagwidth = CIFFTAGWIDTH - strlen(nameoftag) - 1; chpr += printf("%s.%s.%-*.*s",dirname,nameoftag,tagwidth, tagwidth,"length"); } if((PRINT_VALUE)) chpr += printf(" = %lu",entry->length); } } max_offset = entry->offset + fileoffset_base + entry->length; summary_entry->offset = entry->offset + fileoffset_base; summary_entry->length = entry->length; summary_entry->subfiletype = PRIMARY_TYPE; summary_entry->imageformat = IMGFMT_CRW; summary_entry->compression = is_compressed_crw(inptr, entry->offset + fileoffset_base, entry->length); summary_entry->entry_lock = lock_number(summary_entry); break; case CIFFTAG_JPEGIMAGE: /* INHEAP */ if((PRINT_SECTION)) { print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base, indent,"@"); chpr += printf("Start of %s length %lu\n",nameoftag,entry->length); } summary_entry = new_summary_entry(summary_entry,JPEG_SOI,JPEG_SOI); if(summary_entry) summary_entry->subfiletype = REDUCED_RES_TYPE; marker = read_ushort(inptr,TIFF_MOTOROLA,entry->offset + fileoffset_base); max_offset = process_jpeg_segments(inptr,entry->offset + fileoffset_base, marker, entry->length,summary_entry,fullnameoftag, "@",indent+MEDIUMINDENT); if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base + entry->length - 1, indent,"@"); chpr += printf("End of %s",nameoftag); } else { print_tag_address(ENTRY,entry->offset + fileoffset_base, indent+MEDIUMINDENT,"@"); /* pseudo-tags */ if((PRINT_TAGINFO)) chpr += printf("%s.%-*.*s",dirname,CIFFTAGWIDTH,CIFFTAGWIDTH,nameoftag); if((PRINT_ENTRY)) { if((PRINT_VALUE)) { if(PRINT_BOTH_OFFSET) chpr += printf(" = @%#lx/%lu",entry->offset + fileoffset_base, entry->offset + fileoffset_base); else if(PRINT_HEX_OFFSET) chpr += printf(" = @%#lx",entry->offset + fileoffset_base); else chpr += printf(" = @%lu",entry->offset + fileoffset_base); if(fileoffset_base && (PRINT_ENTRY_RELOFFSET)) chpr += printf(" (%lu)",entry->offset); } chpr = newline(chpr); print_tag_address(ENTRY,0,indent+MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { tagwidth = CIFFTAGWIDTH - strlen(nameoftag) - 1; chpr += printf("%s.%s.%-*.*s",dirname,nameoftag,tagwidth, tagwidth,"length"); } if((PRINT_VALUE)) chpr += printf(" = %lu",entry->length); } } print_jpeg_status(); break; case CIFFTAG_JPEGTHUMBNAIL: /* INHEAP */ if((PRINT_SECTION)) { print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base, indent,"-"); chpr += printf("Start of %s length %lu\n",nameoftag,entry->length); } summary_entry = new_summary_entry(summary_entry,FILEFMT_CIFF,IMGFMT_JPEG); if(summary_entry) summary_entry->subfiletype = THUMBNAIL_TYPE; marker = read_ushort(inptr,TIFF_MOTOROLA,entry->offset + fileoffset_base); max_offset = process_jpeg_segments(inptr,entry->offset + fileoffset_base,marker, entry->length,summary_entry,fullnameoftag, "@",indent+MEDIUMINDENT); if((PRINT_SECTION)) { if((status = jpeg_status(0) == JPEG_EARLY_EOI)) chpr = newline(chpr); jpeg_status(status); print_tag_address(SECTION|ENTRY,entry->offset + fileoffset_base + entry->length - 1, indent,"-"); chpr += printf("End of %s",nameoftag); } else { print_tag_address(ENTRY,entry->offset + fileoffset_base, indent+MEDIUMINDENT,"@"); /* pseudo-tags */ if((PRINT_TAGINFO)) chpr += printf("%s.%-*.*s",dirname,CIFFTAGWIDTH,CIFFTAGWIDTH,nameoftag); if((PRINT_ENTRY)) { if((PRINT_VALUE)) { if(PRINT_BOTH_OFFSET) chpr += printf(" = @%#lx/%lu",entry->offset + fileoffset_base, entry->offset + fileoffset_base); else if(PRINT_HEX_OFFSET) chpr += printf(" = @%#lx",entry->offset + fileoffset_base); else chpr += printf(" = @%lu",entry->offset + fileoffset_base); if(fileoffset_base && (PRINT_ENTRY_RELOFFSET)) chpr += printf(" (%lu)",entry->offset); } chpr = newline(chpr); print_tag_address(ENTRY,0,indent+MEDIUMINDENT,"@"); if((PRINT_TAGINFO)) { tagwidth = CIFFTAGWIDTH - strlen(nameoftag) - 1; chpr += printf("%s.%s.%-*.*s",dirname,nameoftag,tagwidth, tagwidth,"length"); } if((PRINT_VALUE)) chpr += printf(" = %lu",entry->length); } } print_jpeg_status(); break; case CIFFTAG_IMAGEDESCRIPTION: /* SUBDIR */ endofdir = entry->offset+fileoffset_base+entry->length; if((PRINT_SECTION)) tagname = fullnameoftag; max_offset = process_ciff_dir(inptr,entry->offset + fileoffset_base, endofdir,CNULL,tagname,summary_entry, byteorder,level+1,indent+MEDIUMINDENT); break; case CIFFTAG_CAMERAOBJECT: /* SUBDIR */ endofdir = entry->offset+fileoffset_base+entry->length; if((PRINT_SECTION)) tagname = fullnameoftag; max_offset = process_ciff_dir(inptr,entry->offset + fileoffset_base, endofdir,CNULL,tagname,summary_entry, byteorder,level+1,indent+MEDIUMINDENT); break; case CIFFTAG_SHOOTINGRECORD: /* SUBDIR */ endofdir = entry->offset+fileoffset_base+entry->length; if((PRINT_SECTION)) tagname = fullnameoftag; max_offset = process_ciff_dir(inptr,entry->offset + fileoffset_base, endofdir,CNULL,tagname,summary_entry, byteorder,level+1,indent+MEDIUMINDENT); break; case CIFFTAG_MEASUREDINFO: /* SUBDIR */ endofdir = entry->offset+fileoffset_base+entry->length; if((PRINT_SECTION)) tagname = fullnameoftag; max_offset = process_ciff_dir(inptr,entry->offset + fileoffset_base, endofdir,CNULL,tagname,summary_entry, byteorder,level+1,indent+MEDIUMINDENT); break; case CIFFTAG_CAMERASPECIFICATION: /* SUBDIR */ endofdir = entry->offset+fileoffset_base+entry->length; if((PRINT_SECTION)) tagname = fullnameoftag; max_offset = process_ciff_dir(inptr,entry->offset + fileoffset_base, endofdir,CNULL,tagname,summary_entry, byteorder,level+1,indent+MEDIUMINDENT); break; case CIFFTAG_IMAGEPROPS: /* SUBDIR */ endofdir = entry->offset+fileoffset_base+entry->length; if((PRINT_SECTION)) tagname = fullnameoftag; max_offset = process_ciff_dir(inptr,entry->offset + fileoffset_base, endofdir,CNULL,tagname,summary_entry, byteorder,level+1,indent); break; case CIFFTAG_EXIFINFORMATION: /* SUBDIR */ endofdir = entry->offset+fileoffset_base+entry->length; if((PRINT_SECTION)) tagname = fullnameoftag; PUSHCOLOR(EXIF_COLOR); max_offset = process_ciff_dir(inptr,entry->offset + fileoffset_base, endofdir,CNULL,tagname,summary_entry, byteorder,level+1,indent+MEDIUMINDENT); POPCOLOR(); break; #if 0 case CIFFTAG_FILENUMBER: break; /* no interp reqd, use default */ case CIFFTAG_DECODERTABLE: break; /* 4 values; unknown, use default */ case CIFFTAG_COMPONENTVERSION: break; /* unknown, use default */ case CIFFTAG_RELEASESETTING: break; /* spec lists but doesn't define */ case CIFFTAG_0X1834: break; /* seen in ExifInformation; unknown, use default */ case CIFFTAG_0x183B: break; /* seen in ExifInformation; unknown, use default */ case CIFFTAG_RECORDID: break; /* no conversion reqd */ #endif case CIFFTAG_NULLRECORD: /* fall thru to default */ case CIFFTAG_FREEBYTES: /* fall thru to default */ default: if(location == CIFF_INHEAP) { if((PRINT_SECTION)) indent += MEDIUMINDENT; max_offset = print_ciffinheapdata(inptr,byteorder,dirname, nameoftag,entry->offset + fileoffset_base,entry->length, entry->type&CIFF_FORMATMASK,indent); } else if(location == CIFF_INREC) { if(!(PRINT_SECTION) && (PRINT_TAGINFO)) { print_tag_address(ENTRY,fileoffset_base + 2,indent+MEDIUMINDENT,"@"); chpr += printf("%-*.*s",entrywidth,entrywidth,tagname); if(PRINT_VALUE) chpr += printf(" = "); } max_offset = print_ciffinrecdata(inptr,byteorder,tagname, fileoffset_base + 2,8,entry->type&CIFF_FORMATMASK, indent+MEDIUMINDENT); } else max_offset = 0; break; } chpr = newline(chpr); if(fullnameoftag) free(fullnameoftag); if(nameoftag) free(nameoftag); fullnameoftag = nameoftag = CNULL; } } return(max_offset); } /* This checks for compression in "raw" CRW files in the manner */ /* suggested by Dave Coffin's "dcraw" program. The ImageInfo data */ /* doesn't seem to say. */ /* A return value of 0 indicates uncompressed data. A return value of */ /* 1 indicates compressed. */ int is_compressed_crw(FILE *inptr,unsigned long start_offset,unsigned long imagelength) { int is_compressed = 0; int maxcheck = 16384; /* 0x4000 */ int count = 0; int ch,lastch; if((inptr) && (fseek(inptr,start_offset + 512,SEEK_SET) != -1)) { if(imagelength < maxcheck) maxcheck = imagelength; lastch = 0; while(((ch = fgetc(inptr)) != EOF) && (count++ < maxcheck)) { if(lastch == 0xff) { is_compressed = 1; if(ch) { is_compressed = 0; break; } } lastch = ch; } } return(is_compressed); } /* Print CIFF header information if options permit. Return 0 if */ /* information is valid to print, or -1 if the header is invalid */ int print_ciff_header(struct fileheader *header,unsigned long section_id) { struct ciff_header *ciffheader = NULL; unsigned short byteorder = 0; int status = -1; int chpr = 0; if(header) { byteorder = header->file_marker; if(header->ciff_header) { ciffheader = header->ciff_header; if(header->probe_magic == PROBE_CIFFMAGIC) { if(Print_options & section_id) chpr += printf("CIFF"); switch(byteorder) { case TIFF_INTEL: case TIFF_MOTOROLA: if(Print_options & section_id) { print_byteorder(byteorder,1); chpr += printf(" \"%s%s\", version %#lx, heap offset = %#lx/%lu", ciffheader->type,ciffheader->subtype, ciffheader->version,ciffheader->headerlength, ciffheader->headerlength); } status = 0; break; default: if(Print_options & section_id) chpr += printf("INVALID CIFF BYTEORDER "); print_byteorder(byteorder,1); chpr += printf(" (CIFF type \"%s%s\")",ciffheader->type, ciffheader->subtype); break; } } else if(Print_options & section_id) { chpr += printf("INVALID CIFF IDENTIFIER "); print_magic(header->probe_magic,4); chpr += printf(" byteorder "); print_byteorder(byteorder,1); } } else fprintf(stderr,"%s: null ciffheader to print_ciff_header()\n",Progname); } else fprintf(stderr,"%s: null fileheader to print_ciff_header()\n",Progname); chpr = newline(chpr); return(status); } struct ciff_header * read_ciffheader(FILE *inptr,unsigned short byteorder,unsigned long offset) { static struct ciff_header header; struct ciff_header *headerptr = NULL; unsigned char *string; memset(&header,0,sizeof(struct ciff_header)); if(inptr) { header.byteorder = read_ushort(inptr,byteorder,offset); header.headerlength = read_ulong(inptr,byteorder,HERE); string = read_bytes(inptr,4,HERE); if(string) { strncpy(header.type,(char *)string,4); string = read_bytes(inptr,4,HERE); if(string) strncpy(header.subtype,(char *)string,4); } header.version = read_ulong(inptr,byteorder,HERE); header.reserved1 = read_ulong(inptr,byteorder,HERE); header.reserved2 = read_ulong(inptr,byteorder,HERE); if((header.byteorder == byteorder) && (strncmp(header.type,"HEAP",4) == 0) && (header.headerlength > 0)) { headerptr = &header; } } return(headerptr); } struct ciff_direntry * read_ciff_direntry(FILE *inptr,struct ciff_direntry *entry,unsigned short byteorder,unsigned long offset) { if(inptr) { if(entry == NULL) entry = (struct ciff_direntry *)malloc(sizeof(struct ciff_direntry)); if(entry) { memset(entry,0,sizeof(struct ciff_direntry)); entry->type = read_ushort(inptr,byteorder,offset); entry->length = read_ulong(inptr,byteorder,offset + 2); entry->offset = read_ulong(inptr,byteorder,offset + 6); } } return(entry); } exifprobe-2.0.1+git20170416-3c2b76/sanyo_datadefs.h0000644000000000000000000000206513074742216017651 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: sanyo_datadefs.h,v 1.1 2005/05/25 15:38:08 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef SANYO_DATADEFS_INCLUDED #define SANYO_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id sanyo_model_id[] = { /* ###%%% more models, SX215, */ { "SR6 ", 4, SANYO_SR6, 1, 1 }, { "SX113", 5, SANYO_SX113, 1, 1 }, { "SX215", 5, SANYO_SX215, 1, 1 }, { 0, 0, 0, 0, 0 } }; #endif /* SANYO_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/casio_datadefs.h0000644000000000000000000000257113074742216017620 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: casio_datadefs.h,v 1.2 2005/06/21 14:53:24 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef CASIO_DATADEFS_INCLUDED #define CASIO_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id casio_model_id[] = { { "QV-2000UX", 9, CASIO_QV2000UX, 1, 1 }, { "QV-3000EX", 9, CASIO_QV3000EX, 1, 1 }, { "QV-4000 ", 9, CASIO_QV4000, 1, 1 }, { "QV-8000SX", 9, CASIO_QV8000SX, 1, 1 }, { "QV-R51 ", 7, CASIO_QVR51, 2, 2 }, { "EX-P505", 7, CASIO_EX_P505, 2, 2 }, { "EX-P600", 7, CASIO_EX_P600, 2, 2 }, { "EX-P700", 7, CASIO_EX_P700, 2, 2 }, { "EX-S100", 7, CASIO_EX_S100, 2, 2 }, { "EX-Z55 ", 7, CASIO_EX_Z55, 2, 2 }, { "GV-20", 5, CASIO_GV_20, 2, 2 }, { 0, 0, 0, 0, 0 } }; #endif /* CASIO_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/cifftags.h0000644000000000000000000000712113074742216016451 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* All tags defined in CIFF spec */ #ifndef CIFFTAGS_INCLUDED #define CIFFTAGS_INCLUDED #define CIFFTAG_NULLRECORD 0x0000 #define CIFFTAG_FREEBYTES 0x0001 #define CIFFTAG_COLORINFO1 0x0032 #define CIFFTAG_FILEDESCRIPTION 0x0805 /* 0x000d */ #define CIFFTAG_RAWMAKEMODEL 0x080a /* 0x0007 */ #define CIFFTAG_FIRMWAREVERSION 0x080b #define CIFFTAG_COMPONENTVERSION 0x080c #define CIFFTAG_ROMOPERATIONMODE 0x080d /* 0x000? */ #define CIFFTAG_OWNERNAME 0x0810 /* 0x0009 */ #define CIFFTAG_IMAGETYPE 0x0815 /* 0x0006 */ #define CIFFTAG_ORIGINALFILENAME 0x0816 #define CIFFTAG_THUMBNAILFILENAME 0x0817 #define CIFFTAG_TARGETIMAGETYPE 0x100a #define CIFFTAG_SHUTTERRELEASEMETHOD 0x1010 #define CIFFTAG_SHUTTERRELEASETIMING 0x1011 #define CIFFTAG_RELEASESETTING 0x1016 #define CIFFTAG_BASEISO 0x101c #define CIFFTAG_0X1028 0x1028 /* 0x0003 */ #define CIFFTAG_FOCALLENGTH 0x1029 /* 0x0002 */ #define CIFFTAG_SHOTINFO 0x102a /* 0x0004 */ #define CIFFTAG_COLORINFO2 0x102c #define CIFFTAG_CAMERASETTINGS 0x102d /* 0x0001 */ #define CIFFTAG_SENSORINFO 0x1031 #define CIFFTAG_CUSTOMFUNCTIONS 0x1033 /* 0x000f */ #define CIFFTAG_PICTUREINFO 0x1038 /* 0x0012 */ #define CIFFTAG_WHITEBALANCETABLE 0x10a9 /* 0x00a9 */ #define CIFFTAG_COLORSPACE 0x10b4 /* 0x00b4 */ #define CIFFTAG_IMAGESPEC 0x1803 #define CIFFTAG_RECORDID 0x1804 #define CIFFTAG_SELFTIMERTIME 0x1806 #define CIFFTAG_TARGETDISTANCESETTING 0x1807 #define CIFFTAG_SERIALNUMBER 0x180b /* 0x000c */ #define CIFFTAG_CAPTUREDTIME 0x180e #define CIFFTAG_IMAGEINFO 0x1810 #define CIFFTAG_FLASHINFO 0x1813 #define CIFFTAG_MEASUREDEV 0x1814 #define CIFFTAG_FILENUMBER 0x1817 /* 0x0008 */ #define CIFFTAG_EXPOSUREINFO 0x1818 #define CIFFTAG_0X1834 0x1834 /* 0x0010 */ #define CIFFTAG_DECODERTABLE 0x1835 #define CIFFTAG_RAWIMAGEDATA 0x2005 #define CIFFTAG_JPEGIMAGE 0x2007 #define CIFFTAG_JPEGTHUMBNAIL 0x2008 #define CIFFTAG_IMAGEDESCRIPTION 0x2804 #define CIFFTAG_CAMERAOBJECT 0x2807 #define CIFFTAG_SHOOTINGRECORD 0x3002 #define CIFFTAG_MEASUREDINFO 0x3003 #define CIFFTAG_CAMERASPECIFICATION 0x3004 #define CIFFTAG_IMAGEPROPS 0x300a #define CIFFTAG_EXIFINFORMATION 0x300b #endif /* CIFFTAGS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/canon_datadefs.h0000644000000000000000000000343413074742216017617 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: canon_datadefs.h,v 1.2 2005/06/21 14:52:06 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef CANON_DATADEFS_INCLUDED #define CANON_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id canon_model_id[] = { { "Canon DIGITAL IXUS", 18, CANON_IXUS, 1, 1 }, { "Canon EOS-1D", 13, CANON_EOS1D, 5, 1 }, { "Canon EOS-1D Mark II", 20, CANON_EOS1DMARKII, 5, 1 }, { "Canon EOS-1DS", 13, CANON_EOS1DS, 5, 1 }, { "Canon EOS-1Ds Mark II", 21, CANON_EOS1DSMARKII, 5, 1 }, { "Canon EOS 10D", 13, CANON_EOS10D, 3, 1 }, { "Canon EOS 20D", 13, CANON_EOS20D, 4, 1 }, { "Canon EOS D30", 13, CANON_EOSD30, 2, 1 }, { "Canon EOS D60", 13, CANON_EOSD60, 1, 1 }, { "Canon EOS 350", 13, CANON_EOS350, 1, 1 }, { "Canon EOS DIGITAL REBEL", 23, CANON_EOSDIGITALREBEL, 1, 1 }, { "Canon PowerShot A400", 21, CANON_POWERSHOT_A400, 1, 1 }, { "Canon PowerShot A5", 19, CANON_POWERSHOT_A5, 1, 1 }, { "Canon PowerShot G2", 18, CANON_POWERSHOT_G2, 1, 1 }, { "Canon PowerShot Pro1", 20, CANON_POWERSHOT_PRO1, 1, 1 }, { "Canon PowerShot S70", 19, CANON_POWERSHOT_S70, 1, 1 }, { 0, 0, 0, 0, 0 } }; #endif /* CANON_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/Makefile0000644000000000000000000000657113074742216016162 0ustar rootroot# @(#) $Id: Makefile,v 1.33 2005/07/25 19:41:06 alex Exp $ # Makefile for EXIFPROBE image file probe # Any compiler should do CC?=cc CFLAGS=-DCOLOR -O -std=c99 # You probably don't need these # CFLAGS=-DCOLOR -g -O -Dlint -Wall -Wno-long-long # SPLINTCFLAGS=-DCOLOR -Dlint -showsummary # If your system has strcasestr(3) you can use this if you like. # If not defined a fake routine is used (which should be good enough, # this is used only for the -C option) # CFLAGS+=-DSTRCASESTR=strcasestr #Solaris; cultural differences #CFLAGS += -Du_int32_t=uint32_t # You'll need this on big-endian machines if (and ONLY if) "byteorder.h" # is not created properly on first invocation. #CFLAGS += -DNATIVE_BYTEORDER_BIGENDIAN # or add to ./byteorder.h # On Solaris, you may need to use 'gmake', or edit the next line. PREFIX ?= /usr/local BINDIR=$(PREFIX)/bin MANDIR=$(PREFIX)/man/man1 INCLUDES=defs.h extern.h misc.h tifftags.h exiftags.h \ tiffeptags.h jpegtags.h global.h MAKERSRCS=maker_nikon.c maker_epson.c maker_olympus.c maker_fujifilm.c \ maker_casio.c maker_minolta.c maker_sanyo.c maker_canon.c \ maker_leica.c maker_agfa.c maker_asahi.c maker_panasonic.c \ maker_kyocera.c maker_toshiba.c maker_sigma.c maker_sony.c \ maker_konica.c maker_hp.c maker_kodak.c maker_ricoh.c \ maker_traveler.c MAKEROBJS=maker_nikon.o maker_epson.o maker_olympus.o maker_fujifilm.o \ maker_casio.o maker_minolta.o maker_sanyo.o maker_canon.o \ maker_leica.o maker_agfa.o maker_asahi.o maker_panasonic.o \ maker_kyocera.o maker_toshiba.o maker_sigma.o maker_sony.o \ maker_konica.o maker_hp.o maker_kodak.o maker_ricoh.o \ maker_traveler.o SRCS=main.c readfile.c print.c tagnames.c process.c misc.c interpret.c \ print_maker.c maker_generic.c maker_tagnames.c options.c ciff.c\ jp2000.c mrw.c raf.c x3f.c \ $(MAKERSRCS) OBJS=main.o readfile.o print.o tagnames.o process.o misc.o interpret.o \ print_maker.o maker_generic.o maker_tagnames.o options.o ciff.o \ jp2000.o mrw.o veclib.o raf.o x3f.o \ $(MAKEROBJS) all: byteorder.h exifprobe byteorder.h: @echo -n "Creating byteorder.h: " @sh makebyteorder.sh @cat byteorder.h @echo veclib.o: lib/veclib.c $(CC) -o veclib.o -c $(CFLAGS) lib/veclib.c # Need the math library to calculate some APEX things... exifprobe: $(OBJS) $(INCLUDES) Makefile ./mkcomptime > comptime.c $(CC) -o exifprobe $(CFLAGS) $(OBJS) comptime.c -lm install: all cp exifprobe $(BINDIR) cp exifgrep $(BINDIR) cp exifprobe.1 $(MANDIR) cp exifgrep.1 $(MANDIR) # if you want HTML man pages, pick a target; I prefer man2html rman: exifprobe.1 exifgrep.1 # edit at
& APP0...APPn; rman gets it wrong rman -f HTML exifprobe.1 > exifprobe-rman.html rman -f HTML exifgrep.1 > exifgrep-rman.html man: exifprobe.1 exifgrep.1 groff -man -Thtml exifprobe.1 > exifprobe-man.html groff -man -Thtml exifgrep.1 > exifgrep-man.html man2html: nroff -man exifprobe.1 | man2html -pgsize 1024 -topm 0 -botm 2 -noheads > exifprobe.1.html nroff -man exifgrep.1 | man2html -pgsize 1024 -topm 0 -botm 2 -noheads > exifgrep.1.html clean: rm -f exifprobe *.o comptime.c distclean: clean undepend rm -f byteorder.h MANIFEST.* Makefile.bak exifprobe-*.tar.gz depend: byteorder.h makedepend -- $(CFLAGS) -- $(SRCS) undepend: makedepend splint: $(SRCS) $(INCLUDES) Makefile splint $(SPLINTCFLAGS) $(SRCS) # DO NOT DELETE THIS LINE -- make depend depends on it. exifprobe-2.0.1+git20170416-3c2b76/jp2.h0000644000000000000000000000373013074742216015360 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: jp2.h,v 1.1 2005/05/24 19:06:11 alex Exp $ */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef JP2_INCLUDED #define JP2_INCLUDED /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* JP2/JPEG2000-specific value definitions */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #define JP2_PRFL 0x7072666c #define JP2_FTYP 0x66747970 #define JP2_JP2H 0x6a703268 #define JP2_JP2C 0x6a703263 #define JP2_JP2I 0x6a703269 #define JP2_XML 0x786d6c20 #define JP2_UUID 0x75756964 #define JP2_UINF 0x75696e66 /* JP2H sub-boxes */ #define JP2_ihdr 0x69686472 #define JP2_bpcc 0x62706363 #define JP2_colr 0x636f6c72 #define JP2_pclr 0x70636c72 #define JP2_cdef 0x63646566 #define JP2_res 0x72657320 #define JP2_resc 0x72657363 #define JP2_resd 0x72657364 /* uinf sub-boxes */ #define JP2_ulst 0x75637374 #define JP2_url 0x75726c20 /* magic values */ #define JP2_BR 0x6a703220 /* "brand" */ #define READSIZE 8192 /* used when reading text chunks */ #include "jp2_datadefs.h" #include "jp2tags.h" #include "jp2_extern.h" #endif /* JP2_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/maker_traveler.c0000644000000000000000000000274713074742216017672 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef lint static char *ModuleId = "@(#) $Id: maker_traveler.c,v 1.2 2005/07/24 22:56:27 alex Exp $"; #endif #include #include #include #include "datadefs.h" #include "maker_datadefs.h" #include "summary.h" #include "maker.h" #include "misc.h" #include "maker_extern.h" extern struct camera_id traveler_model_id[]; /* Find the identifying number assigned to known Traveler camera */ /* models. */ int traveler_model_number(char *model,char *software) { struct camera_id *model_id; int number = NO_MODEL; for(model_id = &traveler_model_id[0]; model_id && model_id->name; ++model_id) { if(strncasecmp(model,model_id->name,model_id->namelen) == 0) { number = model_id->id; setnoteversion(model_id->noteversion); setnotetagset(model_id->notetagset); /* info only */ break; } } return(number); } exifprobe-2.0.1+git20170416-3c2b76/traveler_datadefs.h0000644000000000000000000000172513074742216020346 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: traveler_datadefs.h,v 1.1 2005/06/21 15:34:51 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef TRAVELER_DATADEFS_INCLUDED #define TRAVELER_DATADEFS_INCLUDED #include "maker_datadefs.h" struct camera_id traveler_model_id[] = { { "SX330Z", 6, TRAVELER_SX330Z, 0, 0 }, { 0, 0, 0, 0, 0 } }; #endif /* TRAVELER_DATADEFS_INCLUDED */ exifprobe-2.0.1+git20170416-3c2b76/camera_names.h0000644000000000000000000000540513074742216017301 0ustar rootroot/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* Copyright (C) 2002 by Duane H. Hesser. All rights reserved. */ /* */ /* See the file LICENSE.EXIFPROBE for terms of use. */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ /* @(#) $Id: camera_names.h,v 1.2 2005/06/15 21:55:20 alex Exp $" */ /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #ifndef CAMERA_NAMES_INCLUDED #define CAMERA_NAMES_INCLUDED #include "maker_datadefs.h" #include "agfa_datadefs.h" #include "pentax_datadefs.h" #include "canon_datadefs.h" #include "casio_datadefs.h" #include "epson_datadefs.h" #include "fujifilm_datadefs.h" #include "hp_datadefs.h" #include "konica_datadefs.h" #include "kodak_datadefs.h" #include "kyocera_datadefs.h" #include "leica_datadefs.h" #include "minolta_datadefs.h" #include "nikon_datadefs.h" #include "olympus_datadefs.h" #include "panasonic_datadefs.h" #include "ricoh_datadefs.h" #include "sanyo_datadefs.h" #include "sigma_datadefs.h" #include "sony_datadefs.h" #include "toshiba_datadefs.h" #include "traveler_datadefs.h" struct camera_name Camera_make[] = { { "Agfa Gevaert",4, MAKER_AGFA, agfa_model_id }, { "Asahi Optical Co.,Ltd",5, MAKER_ASAHI, pentax_model_id}, { "Canon",5, MAKER_CANON, canon_model_id}, { "CASIO",5, MAKER_CASIO, casio_model_id}, { "Eastman Kodak Company",7, MAKER_KODAK, kodak_model_id }, { "Fujifilm",4, MAKER_FUJIFILM, fujifilm_model_id}, { "Hewlett-Packard",7, MAKER_HP, hp_model_id }, { "Konica Minolta Camera",14, MAKER_MINOLTA, minolta_model_id}, { "Konica Corporation",6, MAKER_KONICA, konica_model_id}, { "Kyocera",7, MAKER_KYOCERA, kyocera_model_id}, { "Leica",5, MAKER_LEICA, leica_model_id}, { "Minolta",7, MAKER_MINOLTA, minolta_model_id}, { "Panasonic",9, MAKER_PANASONIC, panasonic_model_id}, { "Pentax Corporation",6, MAKER_PENTAX, pentax_model_id}, { "Nikon Corporation",5, MAKER_NIKON, nikon_model_id}, { "Olympus Optical Co.,Ltd",7, MAKER_OLYMPUS, olympus_model_id}, { "Ricoh",5, MAKER_RICOH, ricoh_model_id }, { "Sanyo Electric Co.,Ltd.",5, MAKER_SANYO, sanyo_model_id}, { "Seiko Epson Corp.",5, MAKER_EPSON, epson_model_id}, { "Sigma",5, MAKER_SIGMA, sigma_model_id}, { "Sony",4, MAKER_SONY, sony_model_id}, { "Toshiba",8, MAKER_TOSHIBA, toshiba_model_id }, { "Traveler Optical Co,Ltd",8, MAKER_TRAVELER, traveler_model_id}, { 0, 0, 0,0 } }; #endif /* CAMERA_NAMES_INCLUDED */