📄 ximaexif.cpp
字号:
}
break;
case TAG_FOCALPLANEUNITS:
switch((int)ConvertAnyFormat(ValuePtr, Format)){
case 1: m_exifinfo->FocalplaneUnits = 1.0f; break; /* 1 inch */
case 2: m_exifinfo->FocalplaneUnits = 1.0f; break;
case 3: m_exifinfo->FocalplaneUnits = 0.3937007874f; break; /* 1 centimeter*/
case 4: m_exifinfo->FocalplaneUnits = 0.03937007874f; break; /* 1 millimeter*/
case 5: m_exifinfo->FocalplaneUnits = 0.00003937007874f; /* 1 micrometer*/
}
break;
// Remaining cases contributed by: Volker C. Schoech <schoech(at)gmx(dot)de>
case TAG_EXPOSURE_BIAS:
m_exifinfo->ExposureBias = (float) ConvertAnyFormat(ValuePtr, Format);
break;
case TAG_WHITEBALANCE:
m_exifinfo->Whitebalance = (int)ConvertAnyFormat(ValuePtr, Format);
break;
case TAG_METERING_MODE:
m_exifinfo->MeteringMode = (int)ConvertAnyFormat(ValuePtr, Format);
break;
case TAG_EXPOSURE_PROGRAM:
m_exifinfo->ExposureProgram = (int)ConvertAnyFormat(ValuePtr, Format);
break;
case TAG_ISO_EQUIVALENT:
m_exifinfo->ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format);
if ( m_exifinfo->ISOequivalent < 50 ) m_exifinfo->ISOequivalent *= 200;
break;
case TAG_COMPRESSION_LEVEL:
m_exifinfo->CompressionLevel = (int)ConvertAnyFormat(ValuePtr, Format);
break;
case TAG_XRESOLUTION:
m_exifinfo->Xresolution = (float)ConvertAnyFormat(ValuePtr, Format);
break;
case TAG_YRESOLUTION:
m_exifinfo->Yresolution = (float)ConvertAnyFormat(ValuePtr, Format);
break;
case TAG_THUMBNAIL_OFFSET:
ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format);
break;
case TAG_THUMBNAIL_LENGTH:
ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format);
break;
}
if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET){
unsigned char * SubdirStart;
unsigned Offset = Get32u(ValuePtr);
if (Offset>8){
SubdirStart = OffsetBase + Offset;
if (SubdirStart < OffsetBase ||
SubdirStart > OffsetBase+ExifLength){
strcpy(m_szLastError,"Illegal subdirectory link");
return false;
}
ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP);
}
continue;
}
}
{
/* In addition to linking to subdirectories via exif tags,
there's also a potential link to another directory at the end
of each directory. This has got to be the result of a
committee!
*/
unsigned char * SubdirStart;
unsigned Offset;
Offset = Get16u(DirStart+2+12*NumDirEntries);
if (Offset){
SubdirStart = OffsetBase + Offset;
if (SubdirStart < OffsetBase
|| SubdirStart > OffsetBase+ExifLength){
strcpy(m_szLastError,"Illegal subdirectory link");
return false;
}
ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP);
}
}
if (ThumbnailSize && ThumbnailOffset){
if (ThumbnailSize + ThumbnailOffset <= ExifLength){
/* The thumbnail pointer appears to be valid. Store it. */
m_exifinfo->ThumbnailPointer = OffsetBase + ThumbnailOffset;
m_exifinfo->ThumbnailSize = ThumbnailSize;
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/*--------------------------------------------------------------------------
Evaluate number, be it int, rational, or float from directory.
--------------------------------------------------------------------------*/
double CJzImageJPG::CxExifInfo::ConvertAnyFormat(void * ValuePtr, int Format)
{
double Value;
Value = 0;
switch(Format){
case FMT_SBYTE: Value = *(signed char *)ValuePtr; break;
case FMT_BYTE: Value = *(unsigned char *)ValuePtr; break;
case FMT_USHORT: Value = Get16u(ValuePtr); break;
case FMT_ULONG: Value = Get32u(ValuePtr); break;
case FMT_URATIONAL:
case FMT_SRATIONAL:
{
int Num,Den;
Num = Get32s(ValuePtr);
Den = Get32s(4+(char *)ValuePtr);
if (Den == 0){
Value = 0;
}else{
Value = (double)Num/Den;
}
break;
}
case FMT_SSHORT: Value = (signed short)Get16u(ValuePtr); break;
case FMT_SLONG: Value = Get32s(ValuePtr); break;
/* Not sure if this is correct (never seen float used in Exif format)
*/
case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break;
case FMT_DOUBLE: Value = *(double *)ValuePtr; break;
}
return Value;
}
////////////////////////////////////////////////////////////////////////////////
void CJzImageJPG::CxExifInfo::process_COM (const BYTE * Data, int length)
{
int ch;
char Comment[MAX_COMMENT+1];
int nch;
int a;
nch = 0;
if (length > MAX_COMMENT) length = MAX_COMMENT; // Truncate if it won't fit in our structure.
for (a=2;a<length;a++){
ch = Data[a];
if (ch == '\r' && Data[a+1] == '\n') continue; // Remove cr followed by lf.
if (isprint(ch) || ch == '\n' || ch == '\t'){
Comment[nch++] = (char)ch;
}else{
Comment[nch++] = '?';
}
}
Comment[nch] = '\0'; // Null terminate
//if (ShowTags) printf("COM marker comment: %s\n",Comment);
strcpy(m_exifinfo->Comments,Comment);
}
////////////////////////////////////////////////////////////////////////////////
void CJzImageJPG::CxExifInfo::process_SOFn (const BYTE * Data, int marker)
{
int data_precision, num_components;
data_precision = Data[2];
m_exifinfo->Height = Get16m((void*)(Data+3));
m_exifinfo->Width = Get16m((void*)(Data+5));
num_components = Data[7];
if (num_components == 3){
m_exifinfo->IsColor = 1;
}else{
m_exifinfo->IsColor = 0;
}
m_exifinfo->Process = marker;
//if (ShowTags) printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",
// ImageInfo.Width, ImageInfo.Height, num_components, data_precision);
}
////////////////////////////////////////////////////////////////////////////////
/**
* this will work only on a CJzImageJPG object, if the image originally has valid EXIF data
\verbatim
CJzImageJPG jpg;
CxIOFile in,out;
in.Open("D:\\exif_in.jpg","rb");
out.Open("D:\\exif_out.jpg","w+b");
jpg.Decode(&in);
if (jpg.IsValid()){
jpg.RotateLeft();
jpg.Encode(&out);
}
\endverbatim
*/
bool CJzImageJPG::CxExifInfo::EncodeExif(CxFile * hFile)
{
int a;
if (FindSection(M_SOS)==NULL){
strcpy(m_szLastError,"Can't write exif : didn't read all");
return false;
}
// Initial static jpeg marker.
hFile->PutC(0xff);
hFile->PutC(0xd8);
if (Sections[0].Type != M_EXIF && Sections[0].Type != M_JFIF){
// The image must start with an exif or jfif marker. If we threw those away, create one.
static BYTE JfifHead[18] = {
0xff, M_JFIF,
0x00, 0x10, 'J' , 'F' , 'I' , 'F' , 0x00, 0x01,
0x01, 0x01, 0x01, 0x2C, 0x01, 0x2C, 0x00, 0x00
};
hFile->Write(JfifHead, 18, 1);
}
// Write all the misc sections
for (a=0;a<SectionsRead-1;a++){
hFile->PutC(0xff);
hFile->PutC(Sections[a].Type);
hFile->Write(Sections[a].Data, Sections[a].Size, 1);
}
// Write the remaining image data.
hFile->Write(Sections[a].Data, Sections[a].Size, 1);
return true;
}
////////////////////////////////////////////////////////////////////////////////
void CJzImageJPG::CxExifInfo::DiscardAllButExif()
{
Section_t ExifKeeper;
Section_t CommentKeeper;
int a;
memset(&ExifKeeper, 0, sizeof(ExifKeeper));
memset(&CommentKeeper, 0, sizeof(ExifKeeper));
for (a=0;a<SectionsRead;a++){
if (Sections[a].Type == M_EXIF && ExifKeeper.Type == 0){
ExifKeeper = Sections[a];
}else if (Sections[a].Type == M_COM && CommentKeeper.Type == 0){
CommentKeeper = Sections[a];
}else{
free(Sections[a].Data);
Sections[a].Data = 0;
}
}
SectionsRead = 0;
if (ExifKeeper.Type){
Sections[SectionsRead++] = ExifKeeper;
}
if (CommentKeeper.Type){
Sections[SectionsRead++] = CommentKeeper;
}
}
////////////////////////////////////////////////////////////////////////////////
void* CJzImageJPG::CxExifInfo::FindSection(int SectionType)
{
int a;
for (a=0;a<SectionsRead-1;a++){
if (Sections[a].Type == SectionType){
return &Sections[a];
}
}
// Could not be found.
return NULL;
}
////////////////////////////////////////////////////////////////////////////////
#endif // CXIMAGEJPG_SUPPORT_EXIF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -