rjhead 0.2.88

Sign up to get free protection for your applications and to get access to all the features.
data/ext/extconf.rb ADDED
File without changes
data/ext/gpsinfo.c ADDED
@@ -0,0 +1,217 @@
1
+ //--------------------------------------------------------------------------
2
+ // Parsing of GPS info from exif header.
3
+ //
4
+ // Matthias Wandel, Dec 1999 - Dec 2002
5
+ //--------------------------------------------------------------------------
6
+ #include "jhead.h"
7
+
8
+ #define MAX_GPS_TAG 0x1e
9
+
10
+
11
+ #define TAG_GPS_LAT_REF 1
12
+ #define TAG_GPS_LAT 2
13
+ #define TAG_GPS_LONG_REF 3
14
+ #define TAG_GPS_LONG 4
15
+ #define TAG_GPS_ALT_REF 5
16
+ #define TAG_GPS_ALT 6
17
+
18
+
19
+ static const char * GpsTags[MAX_GPS_TAG+1]= {
20
+ "VersionID ",//0x00
21
+ "LatitudeRef ",//0x01
22
+ "Latitude ",//0x02
23
+ "LongitudeRef ",//0x03
24
+ "Longitude ",//0x04
25
+ "AltitudeRef ",//0x05
26
+ "Altitude ",//0x06
27
+ "TimeStamp ",//0x07
28
+ "Satellites ",//0x08
29
+ "Status ",//0x09
30
+ "MeasureMode ",//0x0A
31
+ "DOP ",//0x0B
32
+ "SpeedRef ",//0x0C
33
+ "Speed ",//0x0D
34
+ "TrackRef ",//0x0E
35
+ "Track ",//0x0F
36
+ "ImgDirectionRef ",//0x10
37
+ "ImgDirection ",//0x11
38
+ "MapDatum ",//0x12
39
+ "DestLatitudeRef ",//0x13
40
+ "DestLatitude ",//0x14
41
+ "DestLongitudeRef",//0x15
42
+ "DestLongitude ",//0x16
43
+ "DestBearingRef ",//0x17
44
+ "DestBearing ",//0x18
45
+ "DestDistanceRef ",//0x19
46
+ "DestDistance ",//0x1A
47
+ "ProcessingMethod",//0x1B
48
+ "AreaInformation ",//0x1C
49
+ "DateStamp ",//0x1D
50
+ "Differential ",//0x1E
51
+ };
52
+
53
+ //--------------------------------------------------------------------------
54
+ // Process GPS info directory
55
+ //--------------------------------------------------------------------------
56
+ void ProcessGpsInfo(unsigned char * DirStart, int ByteCountUnused, unsigned char * OffsetBase, unsigned ExifLength)
57
+ {
58
+ int de;
59
+ unsigned a;
60
+ int NumDirEntries;
61
+
62
+ NumDirEntries = Get16u(DirStart);
63
+ #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
64
+
65
+ if (ShowTags){
66
+ printf("(dir has %d entries)\n",NumDirEntries);
67
+ }
68
+
69
+ ImageInfo.GpsInfoPresent = TRUE;
70
+ strcpy(ImageInfo.GpsLat, "? ?");
71
+ strcpy(ImageInfo.GpsLong, "? ?");
72
+ ImageInfo.GpsAlt[0] = 0;
73
+
74
+ for (de=0;de<NumDirEntries;de++){
75
+ unsigned Tag, Format, Components;
76
+ unsigned char * ValuePtr;
77
+ int ComponentSize;
78
+ unsigned ByteCount;
79
+ unsigned char * DirEntry;
80
+ DirEntry = DIR_ENTRY_ADDR(DirStart, de);
81
+
82
+ if (DirEntry+12 > OffsetBase+ExifLength){
83
+ ErrNonfatal("GPS info directory goes past end of exif",0,0);
84
+ return;
85
+ }
86
+
87
+ Tag = Get16u(DirEntry);
88
+ Format = Get16u(DirEntry+2);
89
+ Components = Get32u(DirEntry+4);
90
+
91
+ if ((Format-1) >= NUM_FORMATS) {
92
+ // (-1) catches illegal zero case as unsigned underflows to positive large.
93
+ ErrNonfatal("Illegal number format %d for Exif gps tag %04x", Format, Tag);
94
+ continue;
95
+ }
96
+
97
+ ComponentSize = BytesPerFormat[Format];
98
+ ByteCount = Components * ComponentSize;
99
+
100
+ if (ByteCount > 4){
101
+ unsigned OffsetVal;
102
+ OffsetVal = Get32u(DirEntry+8);
103
+ // If its bigger than 4 bytes, the dir entry contains an offset.
104
+ if (OffsetVal+ByteCount > ExifLength){
105
+ // Bogus pointer offset and / or bytecount value
106
+ ErrNonfatal("Illegal value pointer for Exif gps tag %04x", Tag,0);
107
+ continue;
108
+ }
109
+ ValuePtr = OffsetBase+OffsetVal;
110
+ }else{
111
+ // 4 bytes or less and value is in the dir entry itself
112
+ ValuePtr = DirEntry+8;
113
+ }
114
+
115
+ switch(Tag){
116
+ char FmtString[21];
117
+ char TempString[50];
118
+ double Values[3];
119
+
120
+ case TAG_GPS_LAT_REF:
121
+ ImageInfo.GpsLat[0] = ValuePtr[0];
122
+ break;
123
+
124
+ case TAG_GPS_LONG_REF:
125
+ ImageInfo.GpsLong[0] = ValuePtr[0];
126
+ break;
127
+
128
+ case TAG_GPS_LAT:
129
+ case TAG_GPS_LONG:
130
+ if (Format != FMT_URATIONAL){
131
+ ErrNonfatal("Inappropriate format (%d) for Exif GPS coordinates!", Format, 0);
132
+ }
133
+ strcpy(FmtString, "%0.0fd %0.0fm %0.0fs");
134
+ for (a=0;a<3;a++){
135
+ int den, digits;
136
+
137
+ den = Get32s(ValuePtr+4+a*ComponentSize);
138
+ digits = 0;
139
+ while (den > 1 && digits <= 6){
140
+ den = den / 10;
141
+ digits += 1;
142
+ }
143
+ if (digits > 6) digits = 6;
144
+ FmtString[1+a*7] = (char)('2'+digits+(digits ? 1 : 0));
145
+ FmtString[3+a*7] = (char)('0'+digits);
146
+
147
+ Values[a] = ConvertAnyFormat(ValuePtr+a*ComponentSize, Format);
148
+ }
149
+
150
+ sprintf(TempString, FmtString, Values[0], Values[1], Values[2]);
151
+
152
+ if (Tag == TAG_GPS_LAT){
153
+ strncpy(ImageInfo.GpsLat+2, TempString, 29);
154
+ }else{
155
+ strncpy(ImageInfo.GpsLong+2, TempString, 29);
156
+ }
157
+ break;
158
+
159
+ case TAG_GPS_ALT_REF:
160
+ ImageInfo.GpsAlt[0] = (char)(ValuePtr[0] ? '-' : ' ');
161
+ break;
162
+
163
+ case TAG_GPS_ALT:
164
+ sprintf(ImageInfo.GpsAlt + 1, "%.2fm",
165
+ ConvertAnyFormat(ValuePtr, Format));
166
+ break;
167
+ }
168
+
169
+ if (ShowTags){
170
+ // Show tag value.
171
+ if (Tag < MAX_GPS_TAG){
172
+ printf(" GPS%s =", GpsTags[Tag]);
173
+ }else{
174
+ // Show unknown tag
175
+ printf(" Illegal GPS tag %04x=", Tag);
176
+ }
177
+
178
+ switch(Format){
179
+ case FMT_UNDEFINED:
180
+ // Undefined is typically an ascii string.
181
+
182
+ case FMT_STRING:
183
+ // String arrays printed without function call (different from int arrays)
184
+ {
185
+ printf("\"");
186
+ for (a=0;a<ByteCount;a++){
187
+ int ZeroSkipped = 0;
188
+ if (ValuePtr[a] >= 32){
189
+ if (ZeroSkipped){
190
+ printf("?");
191
+ ZeroSkipped = 0;
192
+ }
193
+ putchar(ValuePtr[a]);
194
+ }else{
195
+ if (ValuePtr[a] == 0){
196
+ ZeroSkipped = 1;
197
+ }
198
+ }
199
+ }
200
+ printf("\"\n");
201
+ }
202
+ break;
203
+
204
+ default:
205
+ // Handle arrays of numbers later (will there ever be?)
206
+ for (a=0;;){
207
+ PrintFormatNumber(ValuePtr+a*ComponentSize, Format, ByteCount);
208
+ if (++a >= Components) break;
209
+ printf(", ");
210
+ }
211
+ printf("\n");
212
+ }
213
+ }
214
+ }
215
+ }
216
+
217
+
data/ext/iptc.c ADDED
@@ -0,0 +1,205 @@
1
+ //--------------------------------------------------------------------------
2
+ // Process IPTC data and XMP data.
3
+ //--------------------------------------------------------------------------
4
+ #include "jhead.h"
5
+
6
+ // IPTC entry types known to Jhead (there's many more defined)
7
+ #define IPTC_RECORD_VERSION 0x00
8
+ #define IPTC_SUPLEMENTAL_CATEGORIES 0x14
9
+ #define IPTC_KEYWORDS 0x19
10
+ #define IPTC_CAPTION 0x78
11
+ #define IPTC_AUTHOR 0x7A
12
+ #define IPTC_HEADLINE 0x69
13
+ #define IPTC_SPECIAL_INSTRUCTIONS 0x28
14
+ #define IPTC_CATEGORY 0x0F
15
+ #define IPTC_BYLINE 0x50
16
+ #define IPTC_BYLINE_TITLE 0x55
17
+ #define IPTC_CREDIT 0x6E
18
+ #define IPTC_SOURCE 0x73
19
+ #define IPTC_COPYRIGHT_NOTICE 0x74
20
+ #define IPTC_OBJECT_NAME 0x05
21
+ #define IPTC_CITY 0x5A
22
+ #define IPTC_STATE 0x5F
23
+ #define IPTC_COUNTRY 0x65
24
+ #define IPTC_TRANSMISSION_REFERENCE 0x67
25
+ #define IPTC_DATE 0x37
26
+ #define IPTC_COPYRIGHT 0x0A
27
+ #define IPTC_COUNTRY_CODE 0x64
28
+ #define IPTC_REFERENCE_SERVICE 0x2D
29
+ #define IPTC_TIME_CREATED 0x3C
30
+ #define IPTC_SUB_LOCATION 0x5C
31
+ #define IPTC_IMAGE_TYPE 0x82
32
+
33
+ //--------------------------------------------------------------------------
34
+ // Process and display IPTC marker.
35
+ //
36
+ // IPTC block consists of:
37
+ // - Marker: 1 byte (0xED)
38
+ // - Block length: 2 bytes
39
+ // - IPTC Signature: 14 bytes ("Photoshop 3.0\0")
40
+ // - 8BIM Signature 4 bytes ("8BIM")
41
+ // - IPTC Block start 2 bytes (0x04, 0x04)
42
+ // - IPTC Header length 1 byte
43
+ // - IPTC header Header is padded to even length, counting the length byte
44
+ // - Length 4 bytes
45
+ // - IPTC Data which consists of a number of entries, each of which has the following format:
46
+ // - Signature 2 bytes (0x1C02)
47
+ // - Entry type 1 byte (for defined entry types, see #defines above)
48
+ // - entry length 2 bytes
49
+ // - entry data 'entry length' bytes
50
+ //
51
+ //--------------------------------------------------------------------------
52
+ void show_IPTC (unsigned char* Data, unsigned int itemlen)
53
+ {
54
+ const char IptcSig1[] = "Photoshop 3.0";
55
+ const char IptcSig2[] = "8BIM";
56
+ const char IptcSig3[] = {0x04, 0x04};
57
+
58
+ unsigned char * pos = Data + sizeof(short); // position data pointer after length field
59
+ unsigned char * maxpos = Data+itemlen;
60
+ char headerLen = 0;
61
+
62
+ if (itemlen < 25) goto corrupt;
63
+
64
+ // Check IPTC signatures
65
+ if (memcmp(pos, IptcSig1, sizeof(IptcSig1)-1) != 0) goto badsig;
66
+ pos += sizeof(IptcSig1); // move data pointer to the next field
67
+
68
+ if (memcmp(pos, IptcSig2, sizeof(IptcSig2)-1) != 0) goto badsig;
69
+ pos += sizeof(IptcSig2)-1; // move data pointer to the next field
70
+
71
+ if (memcmp(pos, IptcSig3, sizeof(IptcSig3)) != 0){
72
+ badsig:
73
+ if (ShowTags){
74
+ ErrNonfatal("IPTC type signature mismatch\n",0,0);
75
+ }
76
+ return;
77
+ }
78
+ pos += sizeof(IptcSig3); // move data pointer to the next field
79
+
80
+ if (pos >= maxpos) goto corrupt;
81
+
82
+ // IPTC section found
83
+
84
+ // Skip header
85
+ headerLen = *pos++; // get header length and move data pointer to the next field
86
+ pos += headerLen + 1 - (headerLen % 2); // move data pointer to the next field (Header is padded to even length, counting the length byte)
87
+
88
+ if (pos+4 >= maxpos) goto corrupt;
89
+
90
+ // Get length (from motorola format)
91
+ //length = (*pos << 24) | (*(pos+1) << 16) | (*(pos+2) << 8) | *(pos+3);
92
+
93
+ pos += 4; // move data pointer to the next field
94
+
95
+ printf("======= IPTC data: =======\n");
96
+
97
+ // Now read IPTC data
98
+ while (pos < (Data + itemlen-5)) {
99
+ short signature;
100
+ unsigned char type = 0;
101
+ short length = 0;
102
+ char * description = NULL;
103
+
104
+ if (pos+5 > maxpos) goto corrupt;
105
+
106
+ signature = (*pos << 8) + (*(pos+1));
107
+ pos += 2;
108
+
109
+ if (signature != 0x1C02){
110
+ break;
111
+ }
112
+
113
+ type = *pos++;
114
+ length = (*pos << 8) + (*(pos+1));
115
+ pos += 2; // Skip tag length
116
+
117
+ if (pos+length > maxpos) goto corrupt;
118
+ // Process tag here
119
+ switch (type) {
120
+ case IPTC_RECORD_VERSION:
121
+ printf("Record vers. : %d\n", (*pos << 8) + (*(pos+1)));
122
+ break;
123
+
124
+ case IPTC_SUPLEMENTAL_CATEGORIES: description = "SuplementalCategories"; break;
125
+ case IPTC_KEYWORDS: description = "Keywords"; break;
126
+ case IPTC_CAPTION: description = "Caption"; break;
127
+ case IPTC_AUTHOR: description = "Author"; break;
128
+ case IPTC_HEADLINE: description = "Headline"; break;
129
+ case IPTC_SPECIAL_INSTRUCTIONS: description = "Spec. Instr."; break;
130
+ case IPTC_CATEGORY: description = "Category"; break;
131
+ case IPTC_BYLINE: description = "Byline"; break;
132
+ case IPTC_BYLINE_TITLE: description = "Byline Title"; break;
133
+ case IPTC_CREDIT: description = "Credit"; break;
134
+ case IPTC_SOURCE: description = "Source"; break;
135
+ case IPTC_COPYRIGHT_NOTICE: description = "(C)Notice"; break;
136
+ case IPTC_OBJECT_NAME: description = "Object Name"; break;
137
+ case IPTC_CITY: description = "City"; break;
138
+ case IPTC_STATE: description = "State"; break;
139
+ case IPTC_COUNTRY: description = "Country"; break;
140
+ case IPTC_TRANSMISSION_REFERENCE: description = "OriginalTransmissionReference"; break;
141
+ case IPTC_DATE: description = "DateCreated"; break;
142
+ case IPTC_COPYRIGHT: description = "(C)Flag"; break;
143
+ case IPTC_REFERENCE_SERVICE: description = "Country Code"; break;
144
+ case IPTC_COUNTRY_CODE: description = "Ref. Service"; break;
145
+ case IPTC_TIME_CREATED: description = "Time Created"; break;
146
+ case IPTC_SUB_LOCATION: description = "Sub Location"; break;
147
+ case IPTC_IMAGE_TYPE: description = "Image type"; break;
148
+
149
+ default:
150
+ if (ShowTags){
151
+ printf("Unrecognised IPTC tag: %d\n", type );
152
+ }
153
+ break;
154
+ }
155
+ if (description != NULL) {
156
+ char TempBuf[32];
157
+ memset(TempBuf, 0, sizeof(TempBuf));
158
+ memset(TempBuf, ' ', 14);
159
+ memcpy(TempBuf, description, strlen(description));
160
+ strcat(TempBuf, ":");
161
+ printf("%s %*.*s\n", TempBuf, length, length, pos);
162
+ }
163
+ pos += length;
164
+ }
165
+ return;
166
+ corrupt:
167
+ ErrNonfatal("Pointer corruption in IPTC\n",0,0);
168
+ }
169
+
170
+
171
+
172
+ //--------------------------------------------------------------------------
173
+ // Dump contents of XMP section
174
+ //--------------------------------------------------------------------------
175
+ void ShowXmp(Section_t XmpSection)
176
+ {
177
+ unsigned char * Data;
178
+ char OutLine[101];
179
+ int OutLineChars;
180
+ int NonBlank;
181
+ unsigned a;
182
+ NonBlank = 0;
183
+ Data = XmpSection.Data;
184
+ OutLineChars = 0;
185
+
186
+
187
+ for (a=0;a<XmpSection.Size;a++){
188
+ if (Data[a] >= 32 && Data[a] < 128){
189
+ OutLine[OutLineChars++] = Data[a];
190
+ if (Data[a] != ' ') NonBlank |= 1;
191
+ }else{
192
+ if (Data[a] != '\n'){
193
+ OutLine[OutLineChars++] = '?';
194
+ }
195
+ }
196
+ if (Data[a] == '\n' || OutLineChars >= 100){
197
+ OutLine[OutLineChars] = 0;
198
+ if (NonBlank){
199
+ puts(OutLine);
200
+ }
201
+ NonBlank = (NonBlank & 1) << 1;
202
+ OutLineChars = 0;
203
+ }
204
+ }
205
+ }
data/ext/jhead.1 ADDED
@@ -0,0 +1,409 @@
1
+ .TH JHEAD 1 "06 Nov 2009" "jhead 2.88"
2
+ .SH NAME
3
+ jhead \- Digicam JPEG Exif header manipulation tool
4
+ .SH SYNOPSIS
5
+ .B jhead
6
+ [
7
+ .I options
8
+ ]
9
+ [
10
+ .I file\.\.\.
11
+ ]
12
+
13
+ .LP
14
+ .SH DESCRIPTION
15
+ .LP
16
+ .B jhead
17
+ is used to display and manipulate data contained in the Exif header of JPEG
18
+ images from digital cameras. By default, jhead displays the more useful
19
+ camera settings from the file in a user-friendly format.
20
+ .PP
21
+ .B jhead
22
+ can also be used to manipulate some aspects of the image relating to JPEG and
23
+ Exif headers, such as changing the internal timestamps, removing the thumbnail,
24
+ or transferring Exif headers back into edited images after graphical editors
25
+ deleted the Exif header.
26
+ .B jhead
27
+ can also be used to launch other programs, similar in style to the UNIX
28
+ .B find
29
+ command, but much simpler.
30
+
31
+
32
+ .SH GENERAL METADATA OPTIONS
33
+ .TP
34
+ .BI \-\^te \ file
35
+ Transplant Exif header from a JPEG (with Exif header) in
36
+ .I file
37
+ into the image that is manipulated. This option is
38
+ useful if you like to edit the photos but still want the Exif header on your photos.
39
+ As most photo editing programs will wipe out the Exif header, this option can be used
40
+ to re-copy them back from original copies after editing the photos.
41
+
42
+
43
+ This feature has an interesting 'relative path' option for specifying the
44
+ thumbnail name. Whenever the <name> contains the characters '&i',
45
+ will substitute the original filename for this name. This allows creating a
46
+ jhead 'relative name' when doing a whole batch of files. For example, the
47
+ incantation:
48
+
49
+ .B jhead -te "originals\&i" *.jpg
50
+
51
+ would transfer the exif header for each .jpg file in the originals directory by
52
+ the same name, Both Win32 and most Unix shells treat the '&' character in a
53
+ special way, so you have to put quotes around that command line option for
54
+ the '&' to even be passed to the program.
55
+
56
+ .TP
57
+ .B \-dc
58
+ Delete comment field from the JPEG header. Note that the comment
59
+ is not part of the Exif header.
60
+ .TP
61
+ .B \-de
62
+ Delete the Exif header entirely. Leaves other metadata sections intact.
63
+ .TP
64
+ .B \-di
65
+ Delete the IPTC section, if present. Leaves other metadata sections intact.
66
+ .TP
67
+ .B \-dx
68
+ Delete the XMP section, if present. Leaves other metadata sections intact.
69
+ .TP
70
+ .B \-du
71
+ Delete sections of jpeg that are not Exif, not comment, and otherwise not
72
+ contributing to the image either - such as data that photoshop might leave in the image.
73
+ .TP
74
+ .B \-purejpg
75
+ Delete all JPEG sections that aren't necessary for rendering the image. Strips any
76
+ metadata that various applications may have left in the image. A combination of
77
+ the -de -dc and -du options.
78
+ .TP
79
+ .B \-mkexif
80
+ Creates minimal exif header. Exif header contains date/time, and empty thumbnail
81
+ fields only. Date/time set to file time by default. Use with -rgt option if you
82
+ want the exif header to contain a thumbnail. Note that exif header creation is
83
+ very limited at this time, and no other fields can be added to the exif header
84
+ this way.
85
+ .TP
86
+ .B \-ce
87
+ Edit the JPEG header comment field (note, this comment field is outside the Exif structure
88
+ and can be part of Exif and non Exif style JPEG images).
89
+
90
+ A temporary file containing the comment is created and a text editor is launched to edit
91
+ the file. The editor is specified in the EDITOR environment variable. If none is specified
92
+ notepad or vi are used under Windows and Unix respectively. After the editor exits,
93
+ the data is transferred back into the image, and the temporary file deleted.
94
+ .TP
95
+ .BI \-\^cs \ file
96
+ Save comment section to a
97
+ .I file
98
+ .TP
99
+ .BI \-\^ci \ file
100
+ Replace comment with text from
101
+ .I file
102
+ .TP
103
+ .BI \-\^cl \ string
104
+ Replace comment with specified string from command line
105
+ .IR file
106
+
107
+
108
+
109
+ .SH DATE / TIME MANIPULATION OPTIONS
110
+
111
+ .TP
112
+ .B \-ft
113
+ Sets the file's system time stamp to what is stored in the Exif header.
114
+ .TP
115
+ .B \-dsft
116
+ Sets the Exif timestamp to the file's timestamp. Requires an Exif header to
117
+ pre-exist. Use -mkexif option to create one if needed.
118
+ .TP
119
+ .BI \-\^n [format_string]
120
+ This option causes files to be renamed and/ or mmoved using the date information from the Exif header
121
+ "DateTimeOriginal" field.
122
+ If the file is not an Exif file, or the DateTimeOriginal does not contain a valid value,
123
+ the file date is used.
124
+ Renaming is by default restricted to files whose names consist largely of digits.
125
+ This effectively restricts renaming to files that have not already been manually renamed, as
126
+ the default sequential names from digital cameras consist largely of digits.
127
+ Use the
128
+ .B -nf
129
+ option to force renaming of all files.
130
+ If the new name contains a '/', this will be interpreted as a new path, and the file will be
131
+ moved accordingly.
132
+
133
+
134
+ If the
135
+ .I format_string
136
+ is omitted, the file will be renamed to MMDD-HHMMSS. Note that
137
+ this scheme doesn't include the year (I never have photos from different years together anyway).
138
+
139
+ If a
140
+ .I format_string
141
+ is provided, it will be passed to the strftime function as the format string.
142
+ In addition, if the format string contains '%f', this will
143
+ substitute the original name of the file (minus extension). '%i' will substitute a sequence
144
+ number. Leading zeros can be specified like with printf - i.e. '%04i' pads the number to 4
145
+ digits using leading zeros.
146
+
147
+ If the name includes '/', this is interpreted as a new path for the file.
148
+ If the new path does not exist, the path will be created.
149
+
150
+ If the target name already exists, the name will be appended with "a", "b", "c", etc,
151
+ unless the name ends with a letter, in which case it will be appended with "0", "1", "2", etc.
152
+
153
+ This feature is especially useful if more than one digital camera was used to take pictures
154
+ of an event. By renaming them to a scheme according to date, they will automatically
155
+ appear in order of taking in most directory listings and image browsers. Alternatively,
156
+ if your image browser supports listing by file time, you can use the -ft option to set
157
+ the file time to the time the photo was taken.
158
+
159
+ Some of the more useful arguments for strftime are:
160
+
161
+ .BR %H \ Hour\ in\ 24-hour\ format\ (00\ -\ 23)
162
+ .br
163
+ .BR %j \ Day\ of\ year\ as\ decimal\ number\ (001\ -\ 366)
164
+ .br
165
+ .BR %m \ Month\ as\ decimal\ number\ (01\ -\ 12)
166
+ .br
167
+ .BR %M \ Minute\ as\ decimal\ number\ (00\ -\ 59)
168
+ .br
169
+ .BR %S \ Second\ as\ decimal\ number\ (00\ -\ 59)
170
+ .br
171
+ .BR %w \ Weekday\ as\ decimal\ number\ (0\ -\ 6;\ Sunday\ is\ 0)
172
+ .br
173
+ .BR %y \ Year\ without\ century,\ as\ decimal\ number\ (00\ -\ 99)
174
+ .br
175
+ .BR %Y \ Year\ with\ century,\ as\ decimal\ number
176
+
177
+ Example:
178
+
179
+ .B jhead -n%Y%m%d-%H%M%S *.jpg
180
+ This will rename files matched by *.jpg in the format YYYYMMDD-HHMMSS
181
+
182
+ For a full listing of strftime arguments, look up the strftime in them man pages.
183
+ Note that some arguments
184
+ to the strftime function (not listed here) produce strings with characters such as ':' that
185
+ may not be valid as part of a filename on some systems.
186
+
187
+ .TP
188
+ .B \-nf
189
+ Same as '-n' but renames files regardless of original file name.
190
+
191
+
192
+ .TP
193
+ .B \-ta<+|-><timediff>
194
+ Adjust time stored in the Exif header by h:mm backwards or forwards. Useful when having
195
+ taken pictures with the wrong time set on the camera, such as after travelling across
196
+ time zones, or when daylight savings time has changed.
197
+
198
+ This option changes all Date/time fields in the exif header, including "DateTimeOriginal" (tag 0x9003)
199
+ and "DateTimeDigitized" (tag 0x9004).
200
+ .TP
201
+ .B \-da<newdate>-<olddate>
202
+
203
+ Works like -ta, but for specifying large date offsets, to be used when fixing dates from
204
+ cameras where the date was set incorrectly, such as having date and time reset by battery
205
+ removal on some cameras
206
+
207
+ Because different months and years have different numbers of days in them, a simple offset
208
+ for months, days, years would lead to unexpected results at times. The time offset is
209
+ thus specified as a difference between two dates, so that jhead can figure out exactly
210
+ how many days the timestamp needs to be adjusted by, including leap years and daylight
211
+ savings time changes.
212
+ The dates are specified as yyyy:mm:dd. For sub-day adjustments, a time of day can also
213
+ be included, by specifying yyyy:nn:dd/hh:mm or yyyy:mm:dd/hh:mm:ss
214
+
215
+ Examples:
216
+
217
+ Year on camera was set to 2005 instead of 2004 for pictures taken in April
218
+ .br
219
+ jhead -da2004:03:01-2005:03:01
220
+
221
+ Default camera date is 2002:01:01, and date was reset on 2005:05:29 at 11:21 am
222
+ .br
223
+ jhead -da2005:05:29/11:21-2002:01:01
224
+ .TP
225
+ .B \-ts
226
+ Sets the time stored in the Exif header to what is specified on the command line.
227
+ Time must be specified as:
228
+ .I yyyy:mm:dd-hh:mm:ss
229
+ .TP
230
+ .B \-ds
231
+ Sets the date stored in the Exif header to what is specified on the command line.
232
+ Can be used to set date, just year and month, or just year.
233
+ Date is specified as:
234
+ .I yyyy:mm:dd, yyyy:mm, or yyyy
235
+
236
+
237
+ .SH THUMBNAIL MANIPULATION OPTIONS
238
+
239
+ .TP
240
+ .B \-dt
241
+ Delete thumbnails from the Exif header, but leave the
242
+ interesting parts intact. This option truncates the thumbnail from the Exif header, provided
243
+ that the thumbnail is the last part of the Exif header (which so far as I know is always the case).
244
+ Exif headers have a built-in thumbnail, which typically
245
+ occupies around 10k of space. This thumbnail is used by digital cameras. Windows XP may also
246
+ use this thumbnail if present (but it doesn't need it). The
247
+ thumbnails are too small to use even full screen on the digicam's LCD.
248
+ I have not encountered any adverse side effects of deleting the thumbnails, even from the
249
+ software provided with my old Olympus digicam. Use with caution.
250
+
251
+ .TP
252
+ .BI \-\^st \ file
253
+ Save the integral thumbnail to
254
+ .I file
255
+ The thumbnail lives
256
+ inside the Exif header, and is a very low-res JPEG image. Note that making
257
+ any changes to a photo, except for with some programs, generally wipes out the Exif header
258
+ and with it the thumbnail.
259
+
260
+ The thumbnail is too low res to really use for very much.
261
+
262
+ This feature has an interesting 'relative path' option for specifying the thumbnail name.
263
+ Whenever the name for
264
+ .I file
265
+ contains the characters '&i',
266
+ .B jhead
267
+ will substitute the original
268
+ filename for this name. This allows creating a 'relative name' when doing a whole
269
+ batch of files. For example, the incantation:
270
+
271
+ .B jhead -st "thumbnails/&i" *.jpg
272
+
273
+ would create a thumbnail for each .jpg file in the thumbnails directory by the same name,
274
+ (provided that the thumbnails directory exists, of course).
275
+ Both Win32 and UNIX shells treat the '&'character in a special way, so you have to
276
+ put quotes around that command line option for the '&' to even be passed to the program.
277
+
278
+ If a '-' is specified for the output file, the thumbnail is sent to stdout. (UNIX build only)
279
+
280
+ .TP
281
+ .B \-rt
282
+ Replace thumbnails from the Exif header.
283
+ This only works if the exif header already contains a thumbnail, and the thumbnail is at the
284
+ end of the header (both always the case if the photo came from a digital camera)
285
+ .TP
286
+ .BI \-\^rgt \ size
287
+ Regenerate exif thumbnail. 'size' specifies maximum height or width of thumbnail.
288
+ Relies on 'mogrify' program (from ImageMagick) to regenerate the thumbnail.
289
+ This only works if the image already contains a thumbnail.
290
+
291
+ .SH ROTATION OPTIONS
292
+ .TP
293
+ .B \-autorot
294
+ Using the 'Orientation' tag of the Exif header, rotate the image so that it is upright.
295
+ The program
296
+ .B jpegtran
297
+ is used to perform the rotation. This program is present in most
298
+ Linux distributions. For windows, you need to get a copy of it. After rotation, the
299
+ orientation tag of the Exif header is set to '1' (normal orientation). The thumbnail
300
+ is also rotated. Other fields of the Exif header, including
301
+ dimensions are untouched, but the JPEG height/width are adjusted.
302
+ This feature is especially useful with newer Canon cameras, that set the orientation
303
+ tag automatically using a gravity sensor.
304
+ .TP
305
+ .B \-norot
306
+ Clears the rotation field in the Exif header without altering the image. Useful if
307
+ the images were previously rotated without clearing the Exif rotation tag, as some
308
+ image browsers will auto rotate images when the rotation tag is set.
309
+ Sometimes, thumbnails and rotation tags can get very out of sync from manipulation
310
+ with various tools. To reset it all use -norot with -rgt to clear this out.
311
+
312
+ .SH OUTPUT VERBOSITY CONTROL
313
+ .TP
314
+ .B \-h
315
+ Displays summary of command line options.
316
+ .TP
317
+ .B \-v
318
+ Makes the program even more verbose than it already is. Like DOS programs, and unlike
319
+ UNIX programs, Jhead gives feedback as to what it is doing, even when nothing goes wrong.
320
+ Windows user that I am, when something doesn't give me feedback for 20 seconds, I assume
321
+ its crashed.
322
+ .TP
323
+ .B \-q
324
+ No output on success, more like Unix programs.
325
+ .TP
326
+ .B \-V
327
+ Print version info and compilation date.
328
+ .B \-exifmap
329
+ Show a map of the bytes in the exif header. Useful when analyzing strange exif headers,
330
+ not of much use to non software developers.
331
+ .TP
332
+ .B \-se
333
+ Suppress error messages relating to corrupt Exif header structure.
334
+ .TP
335
+ .B \-c
336
+ Concise output. This causes picture info to be summarized on one line instead of several.
337
+ Useful for grep-ing through images, as well as importing into spread sheets (data is space
338
+ delimited with quotes as text qualifier).
339
+
340
+ .SH FILE MATCHING OPTIONS
341
+ .TP
342
+ .B \-model
343
+ Restricts processing of files to those whose camera model, as indicated by the Exif image
344
+ information, contains the substring specified in the argument after '-model'.
345
+ For example, the following command will list only images that are from an S100 camera:
346
+
347
+ .B jhead -model S100 *.jpg
348
+
349
+ .B jhead -model S100 *.jpg
350
+
351
+ I use this option to restrict my JPEG recompensing to those images that came from my
352
+ Canon S100 digicam, (see the -cmd option).
353
+ .TP
354
+ .B \-exonly
355
+ Skip all files that don't have an Exif header. Photos straight from a digital camera
356
+ have an Exif header, whereas many photo manipulation tools discard the Exif header.
357
+ .TP
358
+ .B \-cmd
359
+ Executes the specified command on each JPEG file to be processed.
360
+
361
+ The Exif section of each file is read before running the command, and reinserted
362
+ after the command finishes.
363
+
364
+ The specified command invoked separately for each JPEG that is processed, even if
365
+ multiple files are specified (explicitly or by wild card).
366
+
367
+ Example use:
368
+
369
+ Having a whole directory of photos from my S100, I run the following commands:
370
+
371
+ .B jhead -cmd "mogrify -quality 80 &i" -model S100 -r *.jpg
372
+ .br
373
+ .B jhead -cmd "jpegtran -progressive &i > &o" -r *.jpg
374
+
375
+ The first command mogrifies all JPEGs in the tree that indicate that they are from a
376
+ Canon S100 in their Exif header to 80% quality at the same resolution. This is a 'lossy'
377
+ process, so I only run it on files that are from the Canon, and only run it once.
378
+ The next command then takes a JPEGs and converts them to progressive JPEGs. The result
379
+ is the same images, with no discernible differences, stored in half the space. This
380
+ produces substantial savings on some cameras.
381
+
382
+ .SH SEE ALSO
383
+ .BR jpegtran (1),
384
+ .BR mogrify (1),
385
+ .BR rdjpgcom (1),
386
+ .BR wrjpgcom (1)
387
+ .SH AUTHOR
388
+ Matthias Wandel
389
+ .SH BUGS
390
+ After jhead runs a program to rotate or resize an image, the image dimensions and thumbnail
391
+ in the Exif header are not adjusted.
392
+ .PP
393
+ Modifying of Exif header data is very limited, as Jhead internally only has a read only
394
+ implementation of the file system contained in the Exif header. For example, there is no way
395
+ to replace the thumbnail or edit the Exif comment in the Exif header. There is also no way
396
+ to create minimal exif headers.
397
+ .PP
398
+ Some Canon digital SLR cameras fail to adjust the effective sensor resolution when shooting at less
399
+ than full resolution, causing jhead to incorrectly miscalculate the sensor width and 35mm equivalent
400
+ focal length. The same can result from resizing photos with Photoshop, which will manipulate
401
+ parts of the exif header.
402
+ This is often reported as a bug in Jhead, but Jhead can't do much about incorrect data.
403
+ .PP
404
+ Send bug reports to mwandel at sentex dot net.
405
+
406
+ .SH COPYING PERMISSIONS
407
+ Jhead is 'public domain'. You may freely copy jhead, and reuse part or all of its code
408
+ in free or proprietary programs. I do however request that you do not post my e-mail
409
+ address in ways that spam robots can harvest it.