📄 ximaexif.cpp
字号:
*LastExifRefdP = ValuePtr+ByteCount; } /* Extract useful components of tag */ switch(Tag){ case TAG_MAKE: strncpy(m_exifinfo->CameraMake, (char*)ValuePtr, 31); break; case TAG_MODEL: strncpy(m_exifinfo->CameraModel, (char*)ValuePtr, 39); break; case TAG_EXIF_VERSION: strncpy(m_exifinfo->Version,(char*)ValuePtr, 4); break; case TAG_DATETIME_ORIGINAL: strncpy(m_exifinfo->DateTime, (char*)ValuePtr, 19); break; case TAG_USERCOMMENT: // Olympus has this padded with trailing spaces. Remove these first. for (a=ByteCount;;){ a--; if (((char*)ValuePtr)[a] == ' '){ ((char*)ValuePtr)[a] = '\0'; }else{ break; } if (a == 0) break; } /* Copy the comment */ if (memcmp(ValuePtr, "ASCII",5) == 0){ for (a=5;a<10;a++){ char c; c = ((char*)ValuePtr)[a]; if (c != '\0' && c != ' '){ strncpy(m_exifinfo->Comments, (char*)ValuePtr+a, 199); break; } } }else{ strncpy(m_exifinfo->Comments, (char*)ValuePtr, 199); } break; case TAG_FNUMBER: /* Simplest way of expressing aperture, so I trust it the most. (overwrite previously computd value if there is one) */ m_exifinfo->ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format); break; case TAG_APERTURE: case TAG_MAXAPERTURE: /* More relevant info always comes earlier, so only use this field if we don't have appropriate aperture information yet. */ if (m_exifinfo->ApertureFNumber == 0){ m_exifinfo->ApertureFNumber = (float)exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0f)*0.5); } break; case TAG_BRIGHTNESS: m_exifinfo->Brightness = (float)ConvertAnyFormat(ValuePtr, Format); break; case TAG_FOCALLENGTH: /* Nice digital cameras actually save the focal length as a function of how farthey are zoomed in. */ m_exifinfo->FocalLength = (float)ConvertAnyFormat(ValuePtr, Format); break; case TAG_SUBJECT_DISTANCE: /* Inidcates the distacne the autofocus camera is focused to. Tends to be less accurate as distance increases. */ m_exifinfo->Distance = (float)ConvertAnyFormat(ValuePtr, Format); break; case TAG_EXPOSURETIME: /* Simplest way of expressing exposure time, so I trust it most. (overwrite previously computd value if there is one) */ m_exifinfo->ExposureTime = (float)ConvertAnyFormat(ValuePtr, Format); break; case TAG_SHUTTERSPEED: /* More complicated way of expressing exposure time, so only use this value if we don't already have it from somewhere else. */ if (m_exifinfo->ExposureTime == 0){ m_exifinfo->ExposureTime = (float) (1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0f))); } break; case TAG_FLASH: if ((int)ConvertAnyFormat(ValuePtr, Format) & 7){ m_exifinfo->FlashUsed = 1; }else{ m_exifinfo->FlashUsed = 0; } break; case TAG_ORIENTATION: m_exifinfo->Orientation = (int)ConvertAnyFormat(ValuePtr, Format); if (m_exifinfo->Orientation < 1 || m_exifinfo->Orientation > 8){ strcpy(m_szLastError,"Undefined rotation value"); m_exifinfo->Orientation = 0; } break; case TAG_EXIF_IMAGELENGTH: case TAG_EXIF_IMAGEWIDTH: /* Use largest of height and width to deal with images that have been rotated to portrait format. */ a = (int)ConvertAnyFormat(ValuePtr, Format); if (ExifImageWidth < a) ExifImageWidth = a; break; case TAG_FOCALPLANEXRES: m_exifinfo->FocalplaneXRes = (float)ConvertAnyFormat(ValuePtr, Format); break; case TAG_FOCALPLANEYRES: m_exifinfo->FocalplaneYRes = (float)ConvertAnyFormat(ValuePtr, Format); break; case TAG_RESOLUTIONUNIT: switch((int)ConvertAnyFormat(ValuePtr, Format)){ case 1: m_exifinfo->ResolutionUnit = 1.0f; break; /* 1 inch */ case 2: m_exifinfo->ResolutionUnit = 1.0f; break; case 3: m_exifinfo->ResolutionUnit = 0.3937007874f; break; /* 1 centimeter*/ case 4: m_exifinfo->ResolutionUnit = 0.03937007874f; break; /* 1 millimeter*/ case 5: m_exifinfo->ResolutionUnit = 0.00003937007874f; /* 1 micrometer*/ } 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 CxImageJPG::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 CxImageJPG::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 CxImageJPG::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 CxImageJPG object, if the image originally has valid EXIF data \verbatim CxImageJPG 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 CxImageJPG::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 CxImageJPG::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* CxImageJPG::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 + -