⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ximaexif.cpp

📁 It s a tool designed to extract as much information as possible from Bluetooth devices without the r
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * File:	ximaexif.cpp * Purpose:	EXIF reader * 18/Aug/2002 Davide Pizzolato - www.xdp.it * CxImage version 5.99c 17/Oct/2004 * based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net> */#include "ximajpg.h"#if CXIMAGEJPG_SUPPORT_EXIF////////////////////////////////////////////////////////////////////////////////CxImageJPG::CxExifInfo::CxExifInfo(EXIFINFO* info){	if (info) {		m_exifinfo = info;		freeinfo = false;	} else {		m_exifinfo = new EXIFINFO;		memset(m_exifinfo,0,sizeof(EXIFINFO));		freeinfo = true;	}	m_szLastError[0]='\0';	ExifImageWidth = MotorolaOrder = 0;	SectionsRead=0;	memset(&Sections, 0, MAX_SECTIONS * sizeof(Section_t));}////////////////////////////////////////////////////////////////////////////////CxImageJPG::CxExifInfo::~CxExifInfo(){	for(int i=0;i<MAX_SECTIONS;i++) if(Sections[i].Data) free(Sections[i].Data);	if (freeinfo) delete m_exifinfo;}////////////////////////////////////////////////////////////////////////////////bool CxImageJPG::CxExifInfo::DecodeExif(CxFile * hFile, int nReadMode){    int a;    int HaveCom = FALSE;    a = hFile->GetC();    if (a != 0xff || hFile->GetC() != M_SOI){        return FALSE;    }    for(;;){        int itemlen;        int marker = 0;        int ll,lh, got;        BYTE * Data;        if (SectionsRead >= MAX_SECTIONS){			strcpy(m_szLastError,"Too many sections in jpg file");			return false;        }        for (a=0;a<7;a++){            marker = hFile->GetC();            if (marker != 0xff) break;            if (a >= 6){                printf("too many padding bytes\n");                return false;            }        }        if (marker == 0xff){            // 0xff is legal padding, but if we get that many, something's wrong.            strcpy(m_szLastError,"too many padding bytes!");			return false;        }        Sections[SectionsRead].Type = marker;        // Read the length of the section.        lh = hFile->GetC();        ll = hFile->GetC();        itemlen = (lh << 8) | ll;        if (itemlen < 2){            strcpy(m_szLastError,"invalid marker");			return false;        }        Sections[SectionsRead].Size = itemlen;        Data = (BYTE *)malloc(itemlen);        if (Data == NULL){            strcpy(m_szLastError,"Could not allocate memory");			return false;        }        Sections[SectionsRead].Data = Data;        // Store first two pre-read bytes.        Data[0] = (BYTE)lh;        Data[1] = (BYTE)ll;        got = hFile->Read(Data+2, 1, itemlen-2); // Read the whole section.        if (got != itemlen-2){            strcpy(m_szLastError,"Premature end of file?");			return false;        }        SectionsRead += 1;        switch(marker){            case M_SOS:   // stop before hitting compressed data                 // If reading entire image is requested, read the rest of the data.                if (nReadMode & EXIF_READ_IMAGE){                    int cp, ep, size;                    // Determine how much file is left.                    cp = hFile->Tell();                    hFile->Seek(0, SEEK_END);                    ep = hFile->Tell();                    hFile->Seek(cp, SEEK_SET);                    size = ep-cp;                    Data = (BYTE *)malloc(size);                    if (Data == NULL){                        strcpy(m_szLastError,"could not allocate data for entire image");						return false;                    }                    got = hFile->Read(Data, 1, size);                    if (got != size){                        strcpy(m_szLastError,"could not read the rest of the image");						return false;                    }                    Sections[SectionsRead].Data = Data;                    Sections[SectionsRead].Size = size;                    Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER;                    SectionsRead ++;                }                return true;            case M_EOI:   // in case it's a tables-only JPEG stream                printf("No image in jpeg!\n");                return FALSE;            case M_COM: // Comment section                if (HaveCom || ((nReadMode & EXIF_READ_EXIF) == 0)){                    // Discard this section.                    free(Sections[--SectionsRead].Data);					Sections[SectionsRead].Data=0;                }else{                    process_COM(Data, itemlen);                    HaveCom = TRUE;                }                break;            case M_JFIF:                // Regular jpegs always have this tag, exif images have the exif                // marker instead, althogh ACDsee will write images with both markers.                // this program will re-create this marker on absence of exif marker.                // hence no need to keep the copy from the file.                free(Sections[--SectionsRead].Data);				Sections[SectionsRead].Data=0;                break;            case M_EXIF:                // Seen files from some 'U-lead' software with Vivitar scanner                // that uses marker 31 for non exif stuff.  Thus make sure                 // it says 'Exif' in the section before treating it as exif.                if ((nReadMode & EXIF_READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){                    m_exifinfo->IsExif = process_EXIF((BYTE *)Data+2, itemlen);                }else{                    // Discard this section.                    free(Sections[--SectionsRead].Data);					Sections[SectionsRead].Data=0;                }                break;            case M_SOF0:             case M_SOF1:             case M_SOF2:             case M_SOF3:             case M_SOF5:             case M_SOF6:             case M_SOF7:             case M_SOF9:             case M_SOF10:            case M_SOF11:            case M_SOF13:            case M_SOF14:            case M_SOF15:                process_SOFn(Data, marker);                break;            default:                // Skip any other sections.                //if (ShowTags) printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen);                break;        }    }	return true;}/////////////////////////////////////////////////////////////////////////////////*--------------------------------------------------------------------------   Process a EXIF marker   Describes all the drivel that most digital cameras include...--------------------------------------------------------------------------*/bool CxImageJPG::CxExifInfo::process_EXIF(unsigned char * CharBuf, unsigned int length){    m_exifinfo->FlashUsed = 0;     /* If it's from a digicam, and it used flash, it says so. */    m_exifinfo->Comments[0] = '\0';  /* Initial value - null string */    ExifImageWidth = 0;    {   /* Check the EXIF header component */        static const unsigned char ExifHeader[] = "Exif\0\0";        if (memcmp(CharBuf+0, ExifHeader,6)){			strcpy(m_szLastError,"Incorrect Exif header");			return false;		}    }    if (memcmp(CharBuf+6,"II",2) == 0){        MotorolaOrder = 0;    }else{        if (memcmp(CharBuf+6,"MM",2) == 0){            MotorolaOrder = 1;        }else{            strcpy(m_szLastError,"Invalid Exif alignment marker.");			return false;        }    }    /* Check the next two values for correctness. */    if (Get16u(CharBuf+8) != 0x2a){        strcpy(m_szLastError,"Invalid Exif start (1)");		return false;    }	int FirstOffset = Get32u(CharBuf+10);    /* <Richard Collins> 	if (FirstOffset < 8 || FirstOffset > 16){        // I used to ensure this was set to 8 (website I used indicated its 8)        // but PENTAX Optio 230 has it set differently, and uses it as offset. (Sept 11 2002)        strcpy(m_szLastError,"Suspicious offset of first IFD value");		return false;    }*/    unsigned char * LastExifRefd = CharBuf;    /* First directory starts 16 bytes in.  Offsets start at 8 bytes in. */    if (!ProcessExifDir(CharBuf+14, CharBuf+6, length-6, m_exifinfo, &LastExifRefd))		return false;	/* <Richard Collins> give a chance for a second directory */	if (FirstOffset > 8) {		if (!ProcessExifDir(CharBuf+14+FirstOffset-8, CharBuf+6, length-6, m_exifinfo, &LastExifRefd))			return false;	}    /* This is how far the interesting (non thumbnail) part of the exif went. */    // int ExifSettingsLength = LastExifRefd - CharBuf;    /* Compute the CCD width, in milimeters. */    if (m_exifinfo->FocalplaneXRes != 0){        m_exifinfo->CCDWidth = (float)(ExifImageWidth * m_exifinfo->FocalplaneUnits / m_exifinfo->FocalplaneXRes);    }	return true;}//--------------------------------------------------------------------------// Get 16 bits motorola order (always) for jpeg header stuff.//--------------------------------------------------------------------------int CxImageJPG::CxExifInfo::Get16m(void * Short){    return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1];}/////////////////////////////////////////////////////////////////////////////////*--------------------------------------------------------------------------   Convert a 16 bit unsigned value from file's native byte order--------------------------------------------------------------------------*/int CxImageJPG::CxExifInfo::Get16u(void * Short){    if (MotorolaOrder){        return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1];    }else{        return (((unsigned char *)Short)[1] << 8) | ((unsigned char *)Short)[0];    }}/////////////////////////////////////////////////////////////////////////////////*--------------------------------------------------------------------------   Convert a 32 bit signed value from file's native byte order--------------------------------------------------------------------------*/long CxImageJPG::CxExifInfo::Get32s(void * Long){    if (MotorolaOrder){        return  ((( char *)Long)[0] << 24) | (((unsigned char *)Long)[1] << 16)              | (((unsigned char *)Long)[2] << 8 ) | (((unsigned char *)Long)[3] << 0 );    }else{        return  ((( char *)Long)[3] << 24) | (((unsigned char *)Long)[2] << 16)              | (((unsigned char *)Long)[1] << 8 ) | (((unsigned char *)Long)[0] << 0 );    }}/////////////////////////////////////////////////////////////////////////////////*--------------------------------------------------------------------------   Convert a 32 bit unsigned value from file's native byte order--------------------------------------------------------------------------*/unsigned long CxImageJPG::CxExifInfo::Get32u(void * Long){    return (unsigned long)Get32s(Long) & 0xffffffff;}/////////////////////////////////////////////////////////////////////////////////* Describes format descriptor */static const int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};#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/* Describes tag values */#define TAG_EXIF_VERSION      0x9000#define TAG_EXIF_OFFSET       0x8769#define TAG_INTEROP_OFFSET    0xa005#define TAG_MAKE              0x010F#define TAG_MODEL             0x0110#define TAG_ORIENTATION       0x0112#define TAG_XRESOLUTION       0x011A#define TAG_YRESOLUTION       0x011B#define TAG_RESOLUTIONUNIT    0x0128#define TAG_EXPOSURETIME      0x829A#define TAG_FNUMBER           0x829D#define TAG_SHUTTERSPEED      0x9201#define TAG_APERTURE          0x9202#define TAG_BRIGHTNESS        0x9203#define TAG_MAXAPERTURE       0x9205#define TAG_FOCALLENGTH       0x920A#define TAG_DATETIME_ORIGINAL 0x9003#define TAG_USERCOMMENT       0x9286#define TAG_SUBJECT_DISTANCE  0x9206#define TAG_FLASH             0x9209#define TAG_FOCALPLANEXRES    0xa20E#define TAG_FOCALPLANEYRES    0xa20F#define TAG_FOCALPLANEUNITS   0xa210#define TAG_EXIF_IMAGEWIDTH   0xA002#define TAG_EXIF_IMAGELENGTH  0xA003/* the following is added 05-jan-2001 vcs */#define TAG_EXPOSURE_BIAS     0x9204#define TAG_WHITEBALANCE      0x9208#define TAG_METERING_MODE     0x9207#define TAG_EXPOSURE_PROGRAM  0x8822#define TAG_ISO_EQUIVALENT    0x8827#define TAG_COMPRESSION_LEVEL 0x9102#define TAG_THUMBNAIL_OFFSET  0x0201#define TAG_THUMBNAIL_LENGTH  0x0202/*--------------------------------------------------------------------------   Process one of the nested EXIF directories.--------------------------------------------------------------------------*/bool CxImageJPG::CxExifInfo::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength,                           EXIFINFO * const m_exifinfo, unsigned char ** const LastExifRefdP ){    int de;    int a;    int NumDirEntries;    unsigned ThumbnailOffset = 0;    unsigned ThumbnailSize = 0;    NumDirEntries = Get16u(DirStart);    if ((DirStart+2+NumDirEntries*12) > (OffsetBase+ExifLength)){        strcpy(m_szLastError,"Illegally sized directory");		return false;    }    for (de=0;de<NumDirEntries;de++){        int Tag, Format, Components;        unsigned char * ValuePtr;            /* This actually can point to a variety of things; it must be               cast to other types when used.  But we use it as a byte-by-byte               cursor, so we declare it as a pointer to a generic byte here.            */        int ByteCount;        unsigned char * DirEntry;        DirEntry = DirStart+2+12*de;        Tag = Get16u(DirEntry);        Format = Get16u(DirEntry+2);        Components = Get32u(DirEntry+4);        if ((Format-1) >= NUM_FORMATS) {            /* (-1) catches illegal zero case as unsigned underflows to positive large */            strcpy(m_szLastError,"Illegal format code in EXIF dir");			return false;		}        ByteCount = Components * BytesPerFormat[Format];        if (ByteCount > 4){            unsigned OffsetVal;            OffsetVal = Get32u(DirEntry+8);            /* If its bigger than 4 bytes, the dir entry contains an offset.*/            if (OffsetVal+ByteCount > ExifLength){                /* Bogus pointer offset and / or bytecount value */                strcpy(m_szLastError,"Illegal pointer offset value in EXIF.");				return false;            }            ValuePtr = OffsetBase+OffsetVal;        }else{            /* 4 bytes or less and value is in the dir entry itself */            ValuePtr = DirEntry+8;        }        if (*LastExifRefdP < ValuePtr+ByteCount){            /* Keep track of last byte in the exif header that was               actually referenced.  That way, we know where the               discardable thumbnail data begins.            */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -