📄 tiff_support.hpp
字号:
kTIFF_ImageLength, // 257 kTIFF_Compression, // 259 kTIFF_JPEGInterchangeFormat, // 513 kTIFF_JPEGInterchangeFormatLength, // 514 0xFFFF // Must be last as a sentinel.};static const XMP_Uns16 sKnownExifIFDTags[] ={ kTIFF_ExposureTime, // 33434 kTIFF_FNumber, // 33437 kTIFF_ExposureProgram, // 34850 kTIFF_SpectralSensitivity, // 34852 kTIFF_ISOSpeedRatings, // 34855 kTIFF_OECF, // 34856 kTIFF_ExifVersion, // 36864 kTIFF_DateTimeOriginal, // 36867 kTIFF_DateTimeDigitized, // 36868 kTIFF_ComponentsConfiguration, // 37121 kTIFF_CompressedBitsPerPixel, // 37122 kTIFF_ShutterSpeedValue, // 37377 kTIFF_ApertureValue, // 37378 kTIFF_BrightnessValue, // 37379 kTIFF_ExposureBiasValue, // 37380 kTIFF_MaxApertureValue, // 37381 kTIFF_SubjectDistance, // 37382 kTIFF_MeteringMode, // 37383 kTIFF_LightSource, // 37384 kTIFF_Flash, // 37385 kTIFF_FocalLength, // 37386 kTIFF_SubjectArea, // 37396 kTIFF_UserComment, // 37510 kTIFF_SubSecTime, // 37520 kTIFF_SubSecTimeOriginal, // 37521 kTIFF_SubSecTimeDigitized, // 37522 kTIFF_FlashpixVersion, // 40960 kTIFF_ColorSpace, // 40961 kTIFF_PixelXDimension, // 40962 kTIFF_PixelYDimension, // 40963 kTIFF_RelatedSoundFile, // 40964 kTIFF_FlashEnergy, // 41483 kTIFF_SpatialFrequencyResponse, // 41484 kTIFF_FocalPlaneXResolution, // 41486 kTIFF_FocalPlaneYResolution, // 41487 kTIFF_FocalPlaneResolutionUnit, // 41488 kTIFF_SubjectLocation, // 41492 kTIFF_ExposureIndex, // 41493 kTIFF_SensingMethod, // 41495 kTIFF_FileSource, // 41728 kTIFF_SceneType, // 41729 kTIFF_CFAPattern, // 41730 kTIFF_CustomRendered, // 41985 kTIFF_ExposureMode, // 41986 kTIFF_WhiteBalance, // 41987 kTIFF_DigitalZoomRatio, // 41988 kTIFF_FocalLengthIn35mmFilm, // 41989 kTIFF_SceneCaptureType, // 41990 kTIFF_GainControl, // 41991 kTIFF_Contrast, // 41992 kTIFF_Saturation, // 41993 kTIFF_Sharpness, // 41994 kTIFF_DeviceSettingDescription, // 41995 kTIFF_SubjectDistanceRange, // 41996 kTIFF_ImageUniqueID, // 42016 0xFFFF // Must be last as a sentinel.};static const XMP_Uns16 sKnownGPSInfoIFDTags[] ={ kTIFF_GPSVersionID, // 0 kTIFF_GPSLatitudeRef, // 1 kTIFF_GPSLatitude, // 2 kTIFF_GPSLongitudeRef, // 3 kTIFF_GPSLongitude, // 4 kTIFF_GPSAltitudeRef, // 5 kTIFF_GPSAltitude, // 6 kTIFF_GPSTimeStamp, // 7 kTIFF_GPSSatellites, // 8 kTIFF_GPSStatus, // 9 kTIFF_GPSMeasureMode, // 10 kTIFF_GPSDOP, // 11 kTIFF_GPSSpeedRef, // 12 kTIFF_GPSSpeed, // 13 kTIFF_GPSTrackRef, // 14 kTIFF_GPSTrack, // 15 kTIFF_GPSImgDirectionRef, // 16 kTIFF_GPSImgDirection, // 17 kTIFF_GPSMapDatum, // 18 kTIFF_GPSDestLatitudeRef, // 19 kTIFF_GPSDestLatitude, // 20 kTIFF_GPSDestLongitudeRef, // 21 kTIFF_GPSDestLongitude, // 22 kTIFF_GPSDestBearingRef, // 23 kTIFF_GPSDestBearing, // 24 kTIFF_GPSDestDistanceRef, // 25 kTIFF_GPSDestDistance, // 26 kTIFF_GPSProcessingMethod, // 27 kTIFF_GPSAreaInformation, // 28 kTIFF_GPSDateStamp, // 29 kTIFF_GPSDifferential, // 30 0xFFFF // Must be last as a sentinel.};static const XMP_Uns16 sKnownInteroperabilityIFDTags[] ={ // ! Yes, there are none at present. 0xFFFF // Must be last as a sentinel.};// ! Make sure these are in the same order as the IFD enum!static const XMP_Uns16* sKnownTags[kTIFF_KnownIFDCount] = { sKnownPrimaryIFDTags, sKnownThumbnailIFDTags, sKnownExifIFDTags, sKnownGPSInfoIFDTags, sKnownInteroperabilityIFDTags };// =================================================================================================// =================================================================================================// =================================================================================================// TIFF_Manager// ============class TIFF_Manager { // The abstract base class.public: // --------------------------------------------------------------------------------------------- // Types and constants static const XMP_Uns32 kBigEndianPrefix = 0x4D4D002AUL; static const XMP_Uns32 kLittleEndianPrefix = 0x49492A00UL; static const size_t kEmptyTIFFLength = 8; // Just the header. static const size_t kEmptyIFDLength = 2 + 4; // Entry count and next-IFD offset. static const size_t kIFDEntryLength = 12; struct TagInfo { XMP_Uns16 id; XMP_Uns16 type; XMP_Uns32 count; const void* dataPtr; // ! The data must not be changed! Stream endian format! XMP_Uns32 dataLen; // The length in bytes. TagInfo() : id(0), type(0), count(0), dataPtr(0), dataLen(0) {}; TagInfo ( XMP_Uns16 _id, XMP_Uns16 _type, XMP_Uns32 _count, const void* _dataPtr, XMP_Uns32 _dataLen ) : id(_id), type(_type), count(_count), dataPtr(_dataPtr), dataLen(_dataLen) {}; }; typedef std::map<XMP_Uns16,TagInfo> TagInfoMap; struct Rational { XMP_Uns32 num, denom; }; struct SRational { XMP_Int32 num, denom; }; // --------------------------------------------------------------------------------------------- // The IsXyzEndian methods return the external endianness of the original parsed TIFF stream. // The \c GetTag methods return native endian values, the \c SetTag methods take native values. // The original endianness is preserved in output. bool IsBigEndian() const { return this->bigEndian; }; bool IsLittleEndian() const { return (! this->bigEndian); }; bool IsNativeEndian() const { return this->nativeEndian; }; // --------------------------------------------------------------------------------------------- // The TIFF_Manager only keeps explicit knowledge of up to 5 IFDs: // - The primary image IFD, also known as the 0th IFD. This must be present. // - A possible thumbnail IFD, also known as the 1st IFD, chained from the primary image IFD. // - A possible Exif general metadata IFD, found from tag 34665 in the primary image IFD. // - A possible Exif GPS metadata IFD, found from tag 34853 in the primary image IFD. // - A possible Exif Interoperability IFD, found from tag 40965 in the Exif general metadata IFD. // // Parsing will silently forget about certain aspects of ill-formed streams. If any tags are // repeated in an IFD, only the last is kept. Any known tags that are in the wrong IFD are // removed. Parsing will sort the tags into ascending order, AppendTIFF and ComposeTIFF will // preserve the sorted order. These fixes do not cause IsChanged to return true, that only // happens if the client makes explicit changes using SetTag or DeleteTag. virtual bool HasThumbnailIFD() const = 0; virtual bool HasExifIFD() const = 0; virtual bool HasGPSInfoIFD() const = 0; // --------------------------------------------------------------------------------------------- // These are the basic methods to get a map of all of the tags in an IFD, to get or set a tag, // or to delete a tag. The dataPtr returned by \c GetTag is consided read-only, the client must // not change it. The ifd parameter to \c GetIFD must be for one of the recognized actual IFDs. // The ifd parameter for the GetTag or SetTag methods can be a specific IFD of kTIFF_KnownIFD. // Using the specific IFD will be slightly faster, saving a lookup in the known tag map. An // exception is thrown if kTIFF_KnownIFD is passed to GetTag or SetTag and the tag is not known. // \c SetTag replaces an existing tag regardless of type or count. \c DeleteTag deletes a tag, // it is a no-op if the tag does not exist. \c GetValueOffset returns the offset within the // parsed stream of the tag's value. It returns 0 if the tag was not in the parsed input. virtual bool GetIFD ( XMP_Uns8 ifd, TagInfoMap* ifdMap ) const = 0; virtual bool GetTag ( XMP_Uns8 ifd, XMP_Uns16 id, TagInfo* info ) const = 0; virtual void SetTag ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns16 type, XMP_Uns32 count, const void* dataPtr ) = 0; virtual void DeleteTag ( XMP_Uns8 ifd, XMP_Uns16 id ) = 0; virtual XMP_Uns32 GetValueOffset ( XMP_Uns8 ifd, XMP_Uns16 id ) const = 0; // --------------------------------------------------------------------------------------------- // These methods are for tags whose type can be short or long, depending on the actual value. // \c GetTag_Integer returns false if an existing tag's type is not short, or long, or if the // count is not 1. \c SetTag_Integer replaces an existing tag regardless of type or count, the // new tag will have type short or long. virtual bool GetTag_Integer ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32* data ) const = 0; void SetTag_Integer ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32 data ); // --------------------------------------------------------------------------------------------- // These are customized forms of GetTag that verify the type and return a typed value. False is // returned if the type does not match or if the count is not 1. // *** Should also add support for ASCII multi-strings? virtual bool GetTag_Byte ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns8* data ) const = 0; virtual bool GetTag_SByte ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int8* data ) const = 0; virtual bool GetTag_Short ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns16* data ) const = 0; virtual bool GetTag_SShort ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int16* data ) const = 0; virtual bool GetTag_Long ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32* data ) const = 0; virtual bool GetTag_SLong ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int32* data ) const = 0; virtual bool GetTag_Rational ( XMP_Uns8 ifd, XMP_Uns16 id, Rational* data ) const = 0; virtual bool GetTag_SRational ( XMP_Uns8 ifd, XMP_Uns16 id, SRational* data ) const = 0; virtual bool GetTag_Float ( XMP_Uns8 ifd, XMP_Uns16 id, float* data ) const = 0; virtual bool GetTag_Double ( XMP_Uns8 ifd, XMP_Uns16 id, double* data ) const = 0; virtual bool GetTag_ASCII ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_StringPtr* dataPtr, XMP_StringLen* dataLen ) const = 0; // --------------------------------------------------------------------------------------------- void SetTag_Byte ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns8 data ); void SetTag_SByte ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int8 data ); void SetTag_Short ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns16 data ); void SetTag_SShort ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int16 data ); void SetTag_Long ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32 data ); void SetTag_SLong ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int32 data ); void SetTag_Rational ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32 num, XMP_Uns32 denom ); void SetTag_SRational ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int32 num, XMP_Int32 denom ); void SetTag_Float ( XMP_Uns8 ifd, XMP_Uns16 id, float data ); void SetTag_Double ( XMP_Uns8 ifd, XMP_Uns16 id, double data ); void SetTag_ASCII ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_StringPtr dataPtr ); // --------------------------------------------------------------------------------------------- virtual bool GetTag_EncodedString ( XMP_Uns8 ifd, XMP_Uns16 id, std::string* utf8Str ) const = 0; virtual void SetTag_EncodedString ( XMP_Uns8 ifd, XMP_Uns16 id, const std::string& utf8Str, XMP_Uns8 encoding ) = 0; bool DecodeString ( const void * encodedPtr, size_t encodedLen, std::string* utf8Str ) const; bool EncodeString ( const std::string& utf8Str, XMP_Uns8 encoding, std::string* encodedStr ); // --------------------------------------------------------------------------------------------- bool GetTNailInfo ( XMP_ThumbnailInfo * tnailInfo ) const; // --------------------------------------------------------------------------------------------- // \c IsChanged returns true if a read-write stream has changes that need to be saved. This is // only the case when a \c SetTag method has been called. It is not true for changes related to // parsing normalization such as sorting of tags. \c IsChanged returns false for read-only streams. virtual bool IsChanged() = 0; // --------------------------------------------------------------------------------------------- // \c IsLegacyChanged returns true if a read-write stream has changes that need to be saved to // tags other than the XMP (tag 700). This only the case when a \c SetTag method has been // called. It is not true for changes related to parsing normalization such as sorting of tags. // \c IsLegacyChanged returns false for read-only streams. virtual bool IsLegacyChanged() = 0; // --------------------------------------------------------------------------------------------- // \c UpdateMemoryStream is mainly applicable to memory-based read-write streams. It recomposes // the memory stream to incorporate all changes. The new length and data pointer are returned. // \c UpdateMemoryStream can be used with a read-only memory stream to get the raw stream info. // // \c UpdateFileStream updates file-based TIFF. The client must guarantee that the TIFF portion // of the file matches that from the parse in the file-based constructor. Offsets saved from that // parse must still be valid. The open file reference need not be the same, e.g. the client can // be doing a crash-safe update into a temporary copy. // // Both \c UpdateMemoryStream and \c UpdateFileStream use an update-by-append model. Changes are // written in-place where they fit, anything requiring growth is appended to the end and the old // space is abandoned. The end for memory-based TIFF is the end of the data block, the end for // file-based TIFF is the end of the file. This update-by-append model has the advantage of not // perturbing any hidden offsets, a common feature of proprietary MakerNotes. // // The condenseStream parameter to UpdateMemoryStream can be used to rewrite the full stream // instead of appending. This will discard any MakerNote tags and risks breaking offsets that // are hidden. This can be necessary though to try to make the TIFF fit in a JPEG file.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -