299 lines
9.6 KiB
C
299 lines
9.6 KiB
C
//--------------------------------------------------------------------------
|
||
// Include file for jhead program.
|
||
//
|
||
// This include file only defines stuff that goes across modules.
|
||
// I like to keep the definitions for macros and structures as close to
|
||
// where they get used as possible, so include files only get stuff that
|
||
// gets used in more than one file.
|
||
//--------------------------------------------------------------------------
|
||
#define _CRT_SECURE_NO_DEPRECATE 1
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <time.h>
|
||
#include <errno.h>
|
||
#include <ctype.h>
|
||
#include <stdint.h>
|
||
|
||
//--------------------------------------------------------------------------
|
||
|
||
#ifdef _WIN32
|
||
#include <sys/utime.h>
|
||
#else
|
||
#include <utime.h>
|
||
#include <sys/types.h>
|
||
#include <unistd.h>
|
||
#include <errno.h>
|
||
#include <limits.h>
|
||
#endif
|
||
|
||
|
||
typedef unsigned char uchar;
|
||
|
||
#ifndef TRUE
|
||
#define TRUE 1
|
||
#define FALSE 0
|
||
#endif
|
||
|
||
#define MAX_COMMENT_SIZE 2000
|
||
#define GPS_PROCESSING_METHOD_LEN 100
|
||
|
||
#ifdef _WIN32
|
||
#define PATH_MAX _MAX_PATH
|
||
#define SLASH '\\'
|
||
#else
|
||
#define SLASH '/'
|
||
#endif
|
||
|
||
|
||
//--------------------------------------------------------------------------
|
||
// This structure is used to store jpeg file sections in memory.
|
||
typedef struct {
|
||
uchar * Data;
|
||
int Type;
|
||
unsigned Offset;
|
||
unsigned Size;
|
||
}Section_t;
|
||
|
||
extern int ExifSectionIndex;
|
||
|
||
extern int DumpExifMap;
|
||
|
||
#define MAX_DATE_COPIES 10
|
||
|
||
// Buffer size must large enough to hold maximum location string
|
||
// containing six signed integers plus delimeters and terminator,
|
||
// i.e.: 11 * 6 + 3(‘/’) + 2(’,’) + 1(\0) = 72
|
||
#define MAX_BUF_SIZE 72
|
||
|
||
// Sub second tag string length (including null termination character), with
|
||
// nano-second precision. e.g. 0.123456789s is represented as a null terminated
|
||
// string "123456789". Although it can be any length, it is limited to 9 digits
|
||
// here as we limit the precision to nano-second.
|
||
#define SUB_SEC_SIZE 10
|
||
|
||
typedef struct {
|
||
uint32_t num;
|
||
uint32_t denom;
|
||
} rat_t;
|
||
|
||
//--------------------------------------------------------------------------
|
||
// This structure stores Exif header image elements in a simple manner
|
||
// Used to store camera data as extracted from the various ways that it can be
|
||
// stored in an exif header
|
||
typedef struct {
|
||
char FileName [PATH_MAX+1];
|
||
time_t FileDateTime;
|
||
unsigned FileSize;
|
||
char CameraMake [32];
|
||
char CameraModel [40];
|
||
char DateTime [20];
|
||
char DigitizedTime[20];
|
||
// Fractions of seconds for DateTime tag, with milisecond precision.
|
||
char SubSecTime[SUB_SEC_SIZE];
|
||
// Fractions of seconds for DateTimeOriginal tag, with milisecond precision.
|
||
char SubSecTimeOrig[SUB_SEC_SIZE];
|
||
// Fractions of seconds for DateTimeDigitized tag, with milisecond precision.
|
||
char SubSecTimeDig[SUB_SEC_SIZE];
|
||
int Height, Width;
|
||
int Orientation;
|
||
int IsColor;
|
||
int Process;
|
||
int FlashUsed;
|
||
rat_t FocalLength;
|
||
float ExposureTime;
|
||
float ApertureFNumber;
|
||
float Distance;
|
||
float CCDWidth;
|
||
float ExposureBias;
|
||
float DigitalZoomRatio;
|
||
int FocalLength35mmEquiv; // Exif 2.2 tag - usually not present.
|
||
int Whitebalance;
|
||
int MeteringMode;
|
||
int ExposureProgram;
|
||
int ExposureMode;
|
||
int ISOequivalent;
|
||
int LightSource;
|
||
int DistanceRange;
|
||
|
||
char Comments[MAX_COMMENT_SIZE];
|
||
int CommentWidchars; // If nonzer, widechar comment, indicates number of chars.
|
||
|
||
unsigned ThumbnailOffset; // Exif offset to thumbnail
|
||
unsigned ThumbnailSize; // Size of thumbnail.
|
||
unsigned LargestExifOffset; // Last exif data referenced (to check if thumbnail is at end)
|
||
|
||
char ThumbnailAtEnd; // Exif header ends with the thumbnail
|
||
// (we can only modify the thumbnail if its at the end)
|
||
int ThumbnailSizeOffset;
|
||
|
||
int DateTimeOffsets[MAX_DATE_COPIES];
|
||
int numDateTimeTags;
|
||
|
||
int GpsInfoPresent;
|
||
char GpsLat[31];
|
||
char GpsLatRaw[MAX_BUF_SIZE];
|
||
char GpsLatRef[2];
|
||
char GpsLong[31];
|
||
char GpsLongRaw[MAX_BUF_SIZE];
|
||
char GpsLongRef[2];
|
||
char GpsAlt[20];
|
||
rat_t GpsAltRaw;
|
||
char GpsAltRef;
|
||
// gps-datestamp is 11 bytes ascii in EXIF 2.2
|
||
char GpsDateStamp[11];
|
||
char GpsTimeStamp[11];
|
||
char GpsProcessingMethod[GPS_PROCESSING_METHOD_LEN + 1];
|
||
}ImageInfo_t;
|
||
|
||
|
||
|
||
#define EXIT_FAILURE 1
|
||
#define EXIT_SUCCESS 0
|
||
|
||
// jpgfile.c functions
|
||
typedef enum {
|
||
READ_METADATA = 1,
|
||
READ_IMAGE = 2,
|
||
READ_ALL = 3
|
||
}ReadMode_t;
|
||
|
||
|
||
typedef struct {
|
||
unsigned short Tag; // tag value, i.e. TAG_MODEL
|
||
int Format; // format of data
|
||
char* Value; // value of data in string format
|
||
int DataLength; // length of string when format says Value is a string
|
||
int GpsTag; // bool - the tag is related to GPS info
|
||
} ExifElement_t;
|
||
|
||
|
||
typedef struct {
|
||
unsigned short Tag;
|
||
char * Desc;
|
||
int Format;
|
||
int DataLength; // Number of elements in Format. -1 means any length.
|
||
} TagTable_t;
|
||
|
||
|
||
// prototypes for jhead.c functions
|
||
void ErrFatal(char * msg);
|
||
void ErrNonfatal(char * msg, int a1, int a2);
|
||
void FileTimeAsString(char * TimeStr);
|
||
|
||
// Prototypes for exif.c functions.
|
||
int Exif2tm(struct tm * timeptr, char * ExifTime);
|
||
void process_EXIF (unsigned char * CharBuf, unsigned int length);
|
||
int RemoveThumbnail(unsigned char * ExifSection);
|
||
void ShowImageInfo(int ShowFileInfo);
|
||
void ShowConciseImageInfo(void);
|
||
const char * ClearOrientation(void);
|
||
void PrintFormatNumber(void * ValuePtr, int Format, int ByteCount);
|
||
double ConvertAnyFormat(void * ValuePtr, int Format);
|
||
int Get16u(void * Short);
|
||
unsigned Get32u(void * Long);
|
||
int Get32s(void * Long);
|
||
void Put32u(void * Value, unsigned PutValue);
|
||
void create_EXIF(ExifElement_t* elements, int exifTagCount, int gpsTagCount, int hasDateTimeTag);
|
||
int TagNameToValue(const char* tagName);
|
||
int IsDateTimeTag(unsigned short tag);
|
||
|
||
//--------------------------------------------------------------------------
|
||
// Exif format descriptor stuff
|
||
extern const int BytesPerFormat[];
|
||
#define NUM_FORMATS 12
|
||
|
||
#define FMT_BYTE 1
|
||
#define FMT_STRING 2
|
||
#define FMT_USHORT 3
|
||
#define FMT_ULONG 4
|
||
#define FMT_URATIONAL 5
|
||
#define FMT_SBYTE 6
|
||
#define FMT_UNDEFINED 7
|
||
#define FMT_SSHORT 8
|
||
#define FMT_SLONG 9
|
||
#define FMT_SRATIONAL 10
|
||
#define FMT_SINGLE 11
|
||
#define FMT_DOUBLE 12
|
||
|
||
|
||
// makernote.c prototypes
|
||
extern void ProcessMakerNote(unsigned char * DirStart, int ByteCount,
|
||
unsigned char * OffsetBase, unsigned ExifLength);
|
||
|
||
// gpsinfo.c prototypes
|
||
void ProcessGpsInfo(unsigned char * ValuePtr, int ByteCount,
|
||
unsigned char * OffsetBase, unsigned ExifLength);
|
||
int IsGpsTag(const char* tag);
|
||
int GpsTagToFormatType(unsigned short tag);
|
||
int GpsTagNameToValue(const char* tagName);
|
||
TagTable_t* GpsTagToTagTableEntry(unsigned short tag);
|
||
static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };
|
||
|
||
// iptc.c prototpyes
|
||
void show_IPTC (unsigned char * CharBuf, unsigned int length);
|
||
void ShowXmp(Section_t XmpSection);
|
||
|
||
// Prototypes for myglob.c module
|
||
#ifdef _WIN32
|
||
void MyGlob(const char * Pattern , void (*FileFuncParm)(const char * FileName));
|
||
void SlashToNative(char * Path);
|
||
#endif
|
||
|
||
// Prototypes for paths.c module
|
||
int EnsurePathExists(const char * FileName);
|
||
void CatPath(char * BasePath, const char * FilePath);
|
||
|
||
// Prototypes from jpgfile.c
|
||
int ReadJpegSections (FILE * infile, ReadMode_t ReadMode);
|
||
void DiscardData(void);
|
||
void DiscardAllButExif(void);
|
||
int ReadJpegFile(const char * FileName, ReadMode_t ReadMode);
|
||
int ReplaceThumbnail(const char * ThumbFileName);
|
||
int ReplaceThumbnailFromBuffer(const char* Thumb, int ThumbLen);
|
||
int SaveThumbnail(char * ThumbFileName);
|
||
int RemoveSectionType(int SectionType);
|
||
int RemoveUnknownSections(void);
|
||
int WriteJpegFile(const char * FileName);
|
||
Section_t * FindSection(int SectionType);
|
||
Section_t * CreateSection(int SectionType, unsigned char * Data, int size);
|
||
void ResetJpgfile(void);
|
||
int ReadJpegSectionsFromBuffer (unsigned char* buffer, unsigned int buffer_size, ReadMode_t ReadMode);
|
||
int WriteJpegToBuffer(unsigned char* buffer, unsigned int buffer_size);
|
||
|
||
// Variables from jhead.c used by exif.c
|
||
extern ImageInfo_t ImageInfo;
|
||
extern int ShowTags;
|
||
extern char* formatStr(int format);
|
||
|
||
//--------------------------------------------------------------------------
|
||
// JPEG markers consist of one or more 0xFF bytes, followed by a marker
|
||
// code byte (which is not an FF). Here are the marker codes of interest
|
||
// in this program. (See jdmarker.c for a more complete list.)
|
||
//--------------------------------------------------------------------------
|
||
|
||
#define M_SOF0 0xC0 // Start Of Frame N
|
||
#define M_SOF1 0xC1 // N indicates which compression process
|
||
#define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use
|
||
#define M_SOF3 0xC3
|
||
#define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers
|
||
#define M_SOF6 0xC6
|
||
#define M_SOF7 0xC7
|
||
#define M_SOF9 0xC9
|
||
#define M_SOF10 0xCA
|
||
#define M_SOF11 0xCB
|
||
#define M_SOF13 0xCD
|
||
#define M_SOF14 0xCE
|
||
#define M_SOF15 0xCF
|
||
#define M_SOI 0xD8 // Start Of Image (beginning of datastream)
|
||
#define M_EOI 0xD9 // End Of Image (end of datastream)
|
||
#define M_SOS 0xDA // Start Of Scan (begins compressed data)
|
||
#define M_JFIF 0xE0 // Jfif marker
|
||
#define M_EXIF 0xE1 // Exif marker. Also used for XMP data!
|
||
#define M_XMP 0x10E1 // Not a real tag (same value in file as Exif!)
|
||
#define M_COM 0xFE // COMment
|
||
#define M_DQT 0xDB
|
||
#define M_DHT 0xC4
|
||
#define M_DRI 0xDD
|
||
#define M_IPTC 0xED // IPTC marker
|