The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 1 | //-------------------------------------------------------------------------- |
| 2 | // Include file for jhead program. |
| 3 | // |
Ray Chen | a39920c | 2010-01-15 13:58:10 -0800 | [diff] [blame] | 4 | // This include file only defines stuff that goes across modules. |
| 5 | // I like to keep the definitions for macros and structures as close to |
| 6 | // where they get used as possible, so include files only get stuff that |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 7 | // gets used in more than one file. |
| 8 | //-------------------------------------------------------------------------- |
| 9 | #define _CRT_SECURE_NO_DEPRECATE 1 |
| 10 | |
| 11 | #include <stdio.h> |
| 12 | #include <stdlib.h> |
| 13 | #include <string.h> |
| 14 | #include <time.h> |
| 15 | #include <errno.h> |
| 16 | #include <ctype.h> |
Wu-cheng Li | 661f963 | 2010-02-04 17:19:42 +0800 | [diff] [blame] | 17 | #include <stdint.h> |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 18 | |
| 19 | //-------------------------------------------------------------------------- |
| 20 | |
| 21 | #ifdef _WIN32 |
| 22 | #include <sys/utime.h> |
| 23 | #else |
| 24 | #include <utime.h> |
| 25 | #include <sys/types.h> |
| 26 | #include <unistd.h> |
| 27 | #include <errno.h> |
| 28 | #include <limits.h> |
| 29 | #endif |
| 30 | |
| 31 | |
| 32 | typedef unsigned char uchar; |
| 33 | |
| 34 | #ifndef TRUE |
| 35 | #define TRUE 1 |
| 36 | #define FALSE 0 |
| 37 | #endif |
| 38 | |
Chih-Chung Chang | d6a02c3 | 2009-03-24 20:34:28 -0700 | [diff] [blame] | 39 | #define MAX_COMMENT_SIZE 2000 |
Ray Chen | 434623a | 2010-03-10 14:59:44 -0800 | [diff] [blame] | 40 | #define GPS_PROCESSING_METHOD_LEN 100 |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 41 | |
| 42 | #ifdef _WIN32 |
| 43 | #define PATH_MAX _MAX_PATH |
Chih-Chung Chang | d6a02c3 | 2009-03-24 20:34:28 -0700 | [diff] [blame] | 44 | #define SLASH '\\' |
| 45 | #else |
| 46 | #define SLASH '/' |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 47 | #endif |
| 48 | |
Chih-Chung Chang | d6a02c3 | 2009-03-24 20:34:28 -0700 | [diff] [blame] | 49 | |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 50 | //-------------------------------------------------------------------------- |
| 51 | // This structure is used to store jpeg file sections in memory. |
| 52 | typedef struct { |
| 53 | uchar * Data; |
| 54 | int Type; |
Jeff Sharkey | 31b17e6 | 2013-08-21 11:27:36 -0700 | [diff] [blame] | 55 | unsigned Offset; |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 56 | unsigned Size; |
| 57 | }Section_t; |
| 58 | |
| 59 | extern int ExifSectionIndex; |
| 60 | |
| 61 | extern int DumpExifMap; |
| 62 | |
| 63 | #define MAX_DATE_COPIES 10 |
| 64 | |
Wang Kun2 | 2bfc190 | 2010-11-24 13:27:17 +0100 | [diff] [blame] | 65 | // Buffer size must large enough to hold maximum location string |
| 66 | // containing six signed integers plus delimeters and terminator, |
| 67 | // i.e.: 11 * 6 + 3(‘/’) + 2(’,’) + 1(\0) = 72 |
| 68 | #define MAX_BUF_SIZE 72 |
| 69 | |
Zhijun He | 76aba45 | 2013-11-22 18:09:28 -0800 | [diff] [blame] | 70 | // Sub second tag string length (including null termination character), with |
| 71 | // nano-second precision. e.g. 0.123456789s is represented as a null terminated |
| 72 | // string "123456789". Although it can be any length, it is limited to 9 digits |
| 73 | // here as we limit the precision to nano-second. |
| 74 | #define SUB_SEC_SIZE 10 |
| 75 | |
Wu-cheng Li | 574d52d | 2010-01-31 22:34:33 +0800 | [diff] [blame] | 76 | typedef struct { |
| 77 | uint32_t num; |
| 78 | uint32_t denom; |
| 79 | } rat_t; |
| 80 | |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 81 | //-------------------------------------------------------------------------- |
| 82 | // This structure stores Exif header image elements in a simple manner |
| 83 | // Used to store camera data as extracted from the various ways that it can be |
| 84 | // stored in an exif header |
| 85 | typedef struct { |
| 86 | char FileName [PATH_MAX+1]; |
| 87 | time_t FileDateTime; |
| 88 | unsigned FileSize; |
| 89 | char CameraMake [32]; |
| 90 | char CameraModel [40]; |
| 91 | char DateTime [20]; |
Zhijun He | 76aba45 | 2013-11-22 18:09:28 -0800 | [diff] [blame] | 92 | char DigitizedTime[20]; |
| 93 | // Fractions of seconds for DateTime tag, with milisecond precision. |
| 94 | char SubSecTime[SUB_SEC_SIZE]; |
| 95 | // Fractions of seconds for DateTimeOriginal tag, with milisecond precision. |
| 96 | char SubSecTimeOrig[SUB_SEC_SIZE]; |
| 97 | // Fractions of seconds for DateTimeDigitized tag, with milisecond precision. |
| 98 | char SubSecTimeDig[SUB_SEC_SIZE]; |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 99 | int Height, Width; |
| 100 | int Orientation; |
| 101 | int IsColor; |
| 102 | int Process; |
| 103 | int FlashUsed; |
Wu-cheng Li | 574d52d | 2010-01-31 22:34:33 +0800 | [diff] [blame] | 104 | rat_t FocalLength; |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 105 | float ExposureTime; |
| 106 | float ApertureFNumber; |
| 107 | float Distance; |
| 108 | float CCDWidth; |
| 109 | float ExposureBias; |
| 110 | float DigitalZoomRatio; |
| 111 | int FocalLength35mmEquiv; // Exif 2.2 tag - usually not present. |
| 112 | int Whitebalance; |
| 113 | int MeteringMode; |
| 114 | int ExposureProgram; |
| 115 | int ExposureMode; |
| 116 | int ISOequivalent; |
| 117 | int LightSource; |
Chih-Chung Chang | d6a02c3 | 2009-03-24 20:34:28 -0700 | [diff] [blame] | 118 | int DistanceRange; |
| 119 | |
| 120 | char Comments[MAX_COMMENT_SIZE]; |
| 121 | int CommentWidchars; // If nonzer, widechar comment, indicates number of chars. |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 122 | |
| 123 | unsigned ThumbnailOffset; // Exif offset to thumbnail |
| 124 | unsigned ThumbnailSize; // Size of thumbnail. |
| 125 | unsigned LargestExifOffset; // Last exif data referenced (to check if thumbnail is at end) |
| 126 | |
| 127 | char ThumbnailAtEnd; // Exif header ends with the thumbnail |
| 128 | // (we can only modify the thumbnail if its at the end) |
| 129 | int ThumbnailSizeOffset; |
| 130 | |
| 131 | int DateTimeOffsets[MAX_DATE_COPIES]; |
| 132 | int numDateTimeTags; |
| 133 | |
| 134 | int GpsInfoPresent; |
| 135 | char GpsLat[31]; |
Wang Kun2 | 2bfc190 | 2010-11-24 13:27:17 +0100 | [diff] [blame] | 136 | char GpsLatRaw[MAX_BUF_SIZE]; |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 137 | char GpsLatRef[2]; |
| 138 | char GpsLong[31]; |
Wang Kun2 | 2bfc190 | 2010-11-24 13:27:17 +0100 | [diff] [blame] | 139 | char GpsLongRaw[MAX_BUF_SIZE]; |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 140 | char GpsLongRef[2]; |
| 141 | char GpsAlt[20]; |
Wu-cheng Li | 1ed8197 | 2010-05-21 12:02:32 +0800 | [diff] [blame] | 142 | rat_t GpsAltRaw; |
| 143 | char GpsAltRef; |
Ray Chen | a39920c | 2010-01-15 13:58:10 -0800 | [diff] [blame] | 144 | // gps-datestamp is 11 bytes ascii in EXIF 2.2 |
| 145 | char GpsDateStamp[11]; |
| 146 | char GpsTimeStamp[11]; |
Ray Chen | 434623a | 2010-03-10 14:59:44 -0800 | [diff] [blame] | 147 | char GpsProcessingMethod[GPS_PROCESSING_METHOD_LEN + 1]; |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 148 | }ImageInfo_t; |
| 149 | |
| 150 | |
| 151 | |
| 152 | #define EXIT_FAILURE 1 |
| 153 | #define EXIT_SUCCESS 0 |
| 154 | |
| 155 | // jpgfile.c functions |
| 156 | typedef enum { |
| 157 | READ_METADATA = 1, |
| 158 | READ_IMAGE = 2, |
| 159 | READ_ALL = 3 |
| 160 | }ReadMode_t; |
| 161 | |
| 162 | |
| 163 | typedef struct { |
| 164 | unsigned short Tag; // tag value, i.e. TAG_MODEL |
| 165 | int Format; // format of data |
| 166 | char* Value; // value of data in string format |
| 167 | int DataLength; // length of string when format says Value is a string |
| 168 | int GpsTag; // bool - the tag is related to GPS info |
| 169 | } ExifElement_t; |
| 170 | |
| 171 | |
| 172 | typedef struct { |
| 173 | unsigned short Tag; |
| 174 | char * Desc; |
| 175 | int Format; |
| 176 | int DataLength; // Number of elements in Format. -1 means any length. |
| 177 | } TagTable_t; |
| 178 | |
| 179 | |
| 180 | // prototypes for jhead.c functions |
| 181 | void ErrFatal(char * msg); |
| 182 | void ErrNonfatal(char * msg, int a1, int a2); |
| 183 | void FileTimeAsString(char * TimeStr); |
| 184 | |
| 185 | // Prototypes for exif.c functions. |
| 186 | int Exif2tm(struct tm * timeptr, char * ExifTime); |
| 187 | void process_EXIF (unsigned char * CharBuf, unsigned int length); |
| 188 | int RemoveThumbnail(unsigned char * ExifSection); |
| 189 | void ShowImageInfo(int ShowFileInfo); |
| 190 | void ShowConciseImageInfo(void); |
| 191 | const char * ClearOrientation(void); |
| 192 | void PrintFormatNumber(void * ValuePtr, int Format, int ByteCount); |
| 193 | double ConvertAnyFormat(void * ValuePtr, int Format); |
| 194 | int Get16u(void * Short); |
| 195 | unsigned Get32u(void * Long); |
| 196 | int Get32s(void * Long); |
| 197 | void Put32u(void * Value, unsigned PutValue); |
Angus Kong | 482486a | 2012-01-19 15:56:10 +0800 | [diff] [blame] | 198 | void create_EXIF(ExifElement_t* elements, int exifTagCount, int gpsTagCount, int hasDateTimeTag); |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 199 | int TagNameToValue(const char* tagName); |
Angus Kong | 482486a | 2012-01-19 15:56:10 +0800 | [diff] [blame] | 200 | int IsDateTimeTag(unsigned short tag); |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 201 | |
| 202 | //-------------------------------------------------------------------------- |
| 203 | // Exif format descriptor stuff |
| 204 | extern const int BytesPerFormat[]; |
| 205 | #define NUM_FORMATS 12 |
| 206 | |
Ray Chen | a39920c | 2010-01-15 13:58:10 -0800 | [diff] [blame] | 207 | #define FMT_BYTE 1 |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 208 | #define FMT_STRING 2 |
| 209 | #define FMT_USHORT 3 |
| 210 | #define FMT_ULONG 4 |
| 211 | #define FMT_URATIONAL 5 |
| 212 | #define FMT_SBYTE 6 |
| 213 | #define FMT_UNDEFINED 7 |
| 214 | #define FMT_SSHORT 8 |
| 215 | #define FMT_SLONG 9 |
| 216 | #define FMT_SRATIONAL 10 |
| 217 | #define FMT_SINGLE 11 |
| 218 | #define FMT_DOUBLE 12 |
| 219 | |
| 220 | |
| 221 | // makernote.c prototypes |
| 222 | extern void ProcessMakerNote(unsigned char * DirStart, int ByteCount, |
| 223 | unsigned char * OffsetBase, unsigned ExifLength); |
| 224 | |
| 225 | // gpsinfo.c prototypes |
Ray Chen | a39920c | 2010-01-15 13:58:10 -0800 | [diff] [blame] | 226 | void ProcessGpsInfo(unsigned char * ValuePtr, int ByteCount, |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 227 | unsigned char * OffsetBase, unsigned ExifLength); |
| 228 | int IsGpsTag(const char* tag); |
| 229 | int GpsTagToFormatType(unsigned short tag); |
| 230 | int GpsTagNameToValue(const char* tagName); |
| 231 | TagTable_t* GpsTagToTagTableEntry(unsigned short tag); |
Tyler Luu | bd90094 | 2011-10-12 17:46:32 -0500 | [diff] [blame] | 232 | static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 233 | |
| 234 | // iptc.c prototpyes |
Chih-Chung Chang | d6a02c3 | 2009-03-24 20:34:28 -0700 | [diff] [blame] | 235 | void show_IPTC (unsigned char * CharBuf, unsigned int length); |
| 236 | void ShowXmp(Section_t XmpSection); |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 237 | |
| 238 | // Prototypes for myglob.c module |
Chih-Chung Chang | d6a02c3 | 2009-03-24 20:34:28 -0700 | [diff] [blame] | 239 | #ifdef _WIN32 |
| 240 | void MyGlob(const char * Pattern , void (*FileFuncParm)(const char * FileName)); |
| 241 | void SlashToNative(char * Path); |
| 242 | #endif |
| 243 | |
| 244 | // Prototypes for paths.c module |
| 245 | int EnsurePathExists(const char * FileName); |
| 246 | void CatPath(char * BasePath, const char * FilePath); |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 247 | |
| 248 | // Prototypes from jpgfile.c |
| 249 | int ReadJpegSections (FILE * infile, ReadMode_t ReadMode); |
| 250 | void DiscardData(void); |
| 251 | void DiscardAllButExif(void); |
| 252 | int ReadJpegFile(const char * FileName, ReadMode_t ReadMode); |
| 253 | int ReplaceThumbnail(const char * ThumbFileName); |
Tyler Luu | 13714f2 | 2011-09-27 20:04:35 -0500 | [diff] [blame] | 254 | int ReplaceThumbnailFromBuffer(const char* Thumb, int ThumbLen); |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 255 | int SaveThumbnail(char * ThumbFileName); |
| 256 | int RemoveSectionType(int SectionType); |
| 257 | int RemoveUnknownSections(void); |
| 258 | int WriteJpegFile(const char * FileName); |
| 259 | Section_t * FindSection(int SectionType); |
| 260 | Section_t * CreateSection(int SectionType, unsigned char * Data, int size); |
| 261 | void ResetJpgfile(void); |
Tyler Luu | 24757b4 | 2011-08-24 20:53:34 -0500 | [diff] [blame] | 262 | int ReadJpegSectionsFromBuffer (unsigned char* buffer, unsigned int buffer_size, ReadMode_t ReadMode); |
| 263 | int WriteJpegToBuffer(unsigned char* buffer, unsigned int buffer_size); |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 264 | |
| 265 | // Variables from jhead.c used by exif.c |
| 266 | extern ImageInfo_t ImageInfo; |
| 267 | extern int ShowTags; |
| 268 | extern char* formatStr(int format); |
| 269 | |
| 270 | //-------------------------------------------------------------------------- |
| 271 | // JPEG markers consist of one or more 0xFF bytes, followed by a marker |
| 272 | // code byte (which is not an FF). Here are the marker codes of interest |
| 273 | // in this program. (See jdmarker.c for a more complete list.) |
| 274 | //-------------------------------------------------------------------------- |
| 275 | |
Chih-Chung Chang | d6a02c3 | 2009-03-24 20:34:28 -0700 | [diff] [blame] | 276 | #define M_SOF0 0xC0 // Start Of Frame N |
| 277 | #define M_SOF1 0xC1 // N indicates which compression process |
| 278 | #define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 279 | #define M_SOF3 0xC3 |
Chih-Chung Chang | d6a02c3 | 2009-03-24 20:34:28 -0700 | [diff] [blame] | 280 | #define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 281 | #define M_SOF6 0xC6 |
| 282 | #define M_SOF7 0xC7 |
| 283 | #define M_SOF9 0xC9 |
| 284 | #define M_SOF10 0xCA |
| 285 | #define M_SOF11 0xCB |
| 286 | #define M_SOF13 0xCD |
| 287 | #define M_SOF14 0xCE |
| 288 | #define M_SOF15 0xCF |
Chih-Chung Chang | d6a02c3 | 2009-03-24 20:34:28 -0700 | [diff] [blame] | 289 | #define M_SOI 0xD8 // Start Of Image (beginning of datastream) |
| 290 | #define M_EOI 0xD9 // End Of Image (end of datastream) |
| 291 | #define M_SOS 0xDA // Start Of Scan (begins compressed data) |
| 292 | #define M_JFIF 0xE0 // Jfif marker |
| 293 | #define M_EXIF 0xE1 // Exif marker. Also used for XMP data! |
| 294 | #define M_XMP 0x10E1 // Not a real tag (same value in file as Exif!) |
Ray Chen | a39920c | 2010-01-15 13:58:10 -0800 | [diff] [blame] | 295 | #define M_COM 0xFE // COMment |
The Android Open Source Project | 34a2564 | 2009-03-03 19:30:03 -0800 | [diff] [blame] | 296 | #define M_DQT 0xDB |
| 297 | #define M_DHT 0xC4 |
| 298 | #define M_DRI 0xDD |
Chih-Chung Chang | d6a02c3 | 2009-03-24 20:34:28 -0700 | [diff] [blame] | 299 | #define M_IPTC 0xED // IPTC marker |