mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-28 07:47:02 -05:00
Add Tags for DNG and TIFF extensions References: https://www.loc.gov/preservation/digital/formats/content/tiff_tags.shtml https://helpx.adobe.com/camera-raw/digital-negative.html Co-authored-by: Nik <werwolv98@gmail.com>
484 lines
18 KiB
Rust
484 lines
18 KiB
Rust
#pragma description Tag Image File Format (TIFF)
|
|
|
|
#pragma MIME image/tiff
|
|
|
|
#pragma eval_depth 100
|
|
|
|
import std.io;
|
|
import std.mem;
|
|
import std.string;
|
|
import std.core;
|
|
|
|
char Magic[2] @ 0 [[hidden]];
|
|
match (Magic) {
|
|
("II"): std::core::set_endian(std::mem::Endian::Little);
|
|
("MM"): std::core::set_endian(std::mem::Endian::Big);
|
|
(_): std::error(std::format("Unrecognized magic number: {}", Magic));
|
|
}
|
|
|
|
u16 Version @ 2 [[hidden]];
|
|
u32 ValueOffsetSize;
|
|
match (Version) {
|
|
(42): ValueOffsetSize = 4;
|
|
(43): ValueOffsetSize = 8;
|
|
(_): std::error(std::format("Unrecognized version: {}", Version));
|
|
}
|
|
struct Big<T> {
|
|
match (Version) {
|
|
(42): T V;
|
|
(43): u64 V;
|
|
(_): std::error(std::format("Unrecognized version: {}", Version));
|
|
}
|
|
} [[sealed, format_read("format_read_big"), format_write("format_write_big"), transform("transform_big")]];
|
|
fn format_read_big(auto v) {
|
|
return std::format("{} (0x{:X})", v, v);
|
|
};
|
|
fn format_write_big(str v) {
|
|
return std::string::parse_int(v, 0);
|
|
};
|
|
fn transform_big(auto v) {
|
|
return v.V;
|
|
};
|
|
|
|
struct TIFFHeader {
|
|
char Magic[2];
|
|
u16 Version;
|
|
if (Version > 42) {
|
|
u16 OffsetSize;
|
|
padding[2];
|
|
}
|
|
Big<u32> Offset;
|
|
};
|
|
|
|
enum TIFFFieldType : u16 {
|
|
BYTE = 1,
|
|
ASCII = 2,
|
|
SHORT = 3,
|
|
LONG = 4,
|
|
RATIONAL = 5,
|
|
SBYTE = 6,
|
|
UNDEFINED = 7,
|
|
SSHORT = 8,
|
|
SLONG = 9,
|
|
SRATIONAL = 10,
|
|
FLOAT = 11,
|
|
DOUBLE = 12,
|
|
LONG8 = 16,
|
|
SLONG8 = 17,
|
|
};
|
|
|
|
struct TIFFRational<T> {
|
|
T Numerator;
|
|
T Denominator;
|
|
} [[format_read("format_read_rational")]];
|
|
|
|
fn format_read_rational(auto r) {
|
|
return std::format("{}/{}", r.Numerator, r.Denominator);
|
|
};
|
|
|
|
enum TIFFTag : u16 {
|
|
NewSubfileType = 0x00FE,
|
|
SubfileType = 0x00FF,
|
|
ImageWidth = 0x0100,
|
|
ImageLength = 0x0101,
|
|
BitsPerSample = 0x0102,
|
|
Compression = 0x0103,
|
|
PhotometricInterpretation = 0x0106,
|
|
Threshholding = 0x0107,
|
|
CellWidth = 0x0108,
|
|
CellLength = 0x0109,
|
|
FillOrder = 0x010A,
|
|
DocumentName = 0x010D,
|
|
ImageDescription = 0x010E,
|
|
Make = 0x010F,
|
|
Model = 0x0110,
|
|
StripOffsets = 0x0111,
|
|
Orientation = 0x0112,
|
|
SamplesPerPixel = 0x0115,
|
|
RowsPerStrip = 0x0116,
|
|
StripByteCounts = 0x0117,
|
|
MinSampleValue = 0x0118,
|
|
MaxSampleValue = 0x0119,
|
|
XResolution = 0x011A,
|
|
YResolution = 0x011B,
|
|
PlanarConfiguration = 0x011C,
|
|
PageName = 0x011D,
|
|
XPosition = 0x011E,
|
|
YPosition = 0x011F,
|
|
FreeOffsets = 0x0120,
|
|
FreeByteCounts = 0x0121,
|
|
GrayResponseUnit = 0x0122,
|
|
GrayResponseCurve = 0x0123,
|
|
T4Options = 0x0124,
|
|
T6Options = 0x0125,
|
|
ResolutionUnit = 0x0128,
|
|
PageNumber = 0x0129,
|
|
TransferFunction = 0x012D,
|
|
Software = 0x0131,
|
|
DateTime = 0x0132,
|
|
Artist = 0x013B,
|
|
HostComputer = 0x013C,
|
|
Predictor = 0x013D,
|
|
WhitePoint = 0x013E,
|
|
PrimaryChromaticities = 0x013F,
|
|
ColorMap = 0x0140,
|
|
HalftoneHints = 0x0141,
|
|
TileWidth = 0x0142,
|
|
TileLength = 0x0143,
|
|
TileOffsets = 0x0144,
|
|
TileByteCounts = 0x0145,
|
|
InkSet = 0x014C,
|
|
InkNames = 0x014D,
|
|
NumberOfInks = 0x014E,
|
|
DotRange = 0x0150,
|
|
TargetPrinter = 0x0151,
|
|
ExtraSamples = 0x0152,
|
|
SampleFormat = 0x0153,
|
|
SMinSampleValue = 0x0154,
|
|
SMaxSampleValue = 0x0155,
|
|
TransferRange = 0x0156,
|
|
JPEGTables = 0x015B,
|
|
JPEGProc = 0x0200,
|
|
JPEGInterchangeFormat = 0x0201,
|
|
JPEGInterchangeFormatLngth = 0x0202,
|
|
JPEGRestartInterval = 0x0203,
|
|
JPEGLosslessPredictors = 0x0205,
|
|
JPEGPointTransforms = 0x0206,
|
|
JPEGQTables = 0x0207,
|
|
JPEGDCTables = 0x0208,
|
|
JPEGACTables = 0x0209,
|
|
YCbCrCoefficients = 0x0211,
|
|
YCbCrSubSampling = 0x0212,
|
|
YCbCrPositioning = 0x0213,
|
|
ReferenceBlackWhite = 0x0214,
|
|
StripRowCounts = 0x022F, // 559
|
|
XMP = 0x02BC, // 700
|
|
ImageRating = 0x4746, // 18246
|
|
ImageRatingPercent = 0x4749, // 18249
|
|
ImageID = 0x800D, // 32781
|
|
WangAnnotation = 0x80A4, // 32932
|
|
CFARepeatPatternDim = 0x828D, // 33421
|
|
CFAPattern = 0x828E, // 33422
|
|
BatteryLevel = 0x828F, // 33423
|
|
Copyright = 0x8298,
|
|
ExposureTime = 0x829A, // 33434
|
|
FNumber = 0x829D, // 33437
|
|
MDFileTag = 0x82A5, // 33445
|
|
MDScalePixel = 0x82A6, // 33446
|
|
MDColorTable = 0x82A7, // 33447
|
|
MDLabName = 0x82A8, // 33448
|
|
MDSampleInfo = 0x82A9, // 33449
|
|
MDPrepDate = 0x82AA, // 33450
|
|
MDPrepTime = 0x82AB, // 33451
|
|
MDFileUnits = 0x82AC, // 33452
|
|
ModelPixelScaleTag = 0x830E, // 33550
|
|
IPTCNAA = 0x83BB, // 33723
|
|
INGRPacketDataTag = 0x847E, // 33918
|
|
INGRFlagRegisters = 0x847F, // 33919
|
|
IrasBTransformationMatrix = 0x8480, // 33920
|
|
ModelTiepointTag = 0x8482, // 33922
|
|
Site = 0x84E0, // 34016
|
|
ColorSequence = 0x84E1, // 34017
|
|
IT8Header = 0x84E2, // 34018
|
|
RasterPadding = 0x84E3, // 34019
|
|
BitsPerRunLength = 0x84E4, // 34020
|
|
BitsPerExtendedRunLength = 0x84E5, // 34021
|
|
ColorTable = 0x84E6, // 34022
|
|
ImageColorIndicator = 0x84E7, // 34023
|
|
BackgroundColorIndicator = 0x84E8, // 34024
|
|
ImageColorValue = 0x84E9, // 34025
|
|
BackgroundColorValue = 0x84EA, // 34026
|
|
PixelIntensityRange = 0x84EB, // 34027
|
|
TransparencyIndicator = 0x84EC, // 34028
|
|
ColorCharacterization = 0x84ED, // 34029
|
|
HCUsage = 0x84EE, // 34030
|
|
TrapIndicator = 0x84EF, // 34031
|
|
CMYKEquivalent = 0x84F0, // 34032
|
|
Reserved1 = 0x84F1, // 34033
|
|
Reserved2 = 0x84F2, // 34034
|
|
Reserved3 = 0x84F3, // 34035
|
|
ModelTransformationTag = 0x85D8, // 34264
|
|
Photoshop = 0x8649, // 34377
|
|
ExifIFD = 0x8769, // 34665
|
|
ICCProfile = 0x8773,
|
|
ImageLayer = 0x87AC, // 34732
|
|
GeoKeyDirectoryTag = 0x87AF, // 34735
|
|
GeoDoubleParamsTag = 0x87B0, // 34736
|
|
GeoAsciiParamsTag = 0x87B1, // 34737
|
|
ExposureProgram = 0x8822, // 34850
|
|
SpectralSensitivity = 0x8824, // 34852
|
|
GPSInfo = 0x8825, // 34853
|
|
ISOSpeedRatings = 0x8827, // 34855
|
|
OECF = 0x8828, // 34856
|
|
Interlace = 0x8829, // 34857
|
|
TimeZoneOffset = 0x882A, // 34858
|
|
SelfTimeMode = 0x882B, // 34859
|
|
SensitivityType = 0x8830, // 34864
|
|
StandardOutputSensitivity = 0x8831, // 34865
|
|
RecommendedExposureIndex = 0x8832, // 34866
|
|
ISOSpeed = 0x8833, // 34867
|
|
ISOSpeedLatitudeyyy = 0x8834, // 34868
|
|
ISOSpeedLatitudezzz = 0x8835, // 34869
|
|
HylaFAXFaxRecvParams = 0x885C, // 34908
|
|
HylaFAXFaxSubAddress = 0x885D, // 34909
|
|
HylaFAXFaxRecvTime = 0x885E, // 34910
|
|
ExifVersion = 0x9000, // 36864
|
|
DateTimeOriginal = 0x9003, // 36867
|
|
DateTimeDigitized = 0x9004, // 36868
|
|
ComponentsConfiguration = 0x9101, // 37121
|
|
CompressedBitsPerPixel = 0x9102, // 37122
|
|
ShutterSpeedValue = 0x9201, // 37377
|
|
ApertureValue = 0x9202, // 37378
|
|
BrightnessValue = 0x9203, // 37379
|
|
ExposureBiasValue = 0x9204, // 37380
|
|
MaxApertureValue = 0x9205, // 37381
|
|
SubjectDistance = 0x9206, // 37382
|
|
MeteringMode = 0x9207, // 37383
|
|
LightSource = 0x9208, // 37384
|
|
Flash = 0x9209, // 37385
|
|
FocalLength = 0x920A, // 37386
|
|
FlashEnergy = 0x920B, // 37387
|
|
SpatialFrequencyResponse = 0x920C, // 37388
|
|
Noise = 0x920D, // 37389
|
|
FocalPlaneXResolution = 0x920E, // 37390
|
|
FocalPlaneYResolution = 0x920F, // 37391
|
|
FocalPlaneResolutionUnit = 0x9210, // 37392
|
|
ImageNumber = 0x9211, // 37393
|
|
SecurityClassification = 0x9212, // 37394
|
|
ImageHistory = 0x9213, // 37395
|
|
SubjectLocation = 0x9214, // 37396
|
|
ExposureIndex = 0x9215, // 37397
|
|
TIFFEPStandardID = 0x9216, // 37398
|
|
SensingMethod = 0x9217, // 37399
|
|
MakerNote = 0x927C, // 37500
|
|
UserComment = 0x9286, // 37510
|
|
SubsecTime = 0x9290, // 37520
|
|
SubsecTimeOriginal = 0x9291, // 37521
|
|
SubsecTimeDigitized = 0x9292, // 37522
|
|
ImageSourceData = 0x935C, // 37724
|
|
XPTitle = 0x9C9B, // 40091
|
|
XPComment = 0x9C9C, // 40092
|
|
XPAuthor = 0x9C9D, // 40093
|
|
XPKeywords = 0x9C9E, // 40094
|
|
XPSubject = 0x9C9F, // 40095
|
|
FlashpixVersion = 0xA000, // 40960
|
|
ColorSpace = 0xA001, // 40961
|
|
PixelXDimension = 0xA002, // 40962
|
|
PixelYDimension = 0xA003, // 40963
|
|
RelatedSoundFile = 0xA004, // 40964
|
|
InteroperabilityIFD = 0xA005, // 40965
|
|
FlashEnergyExif = 0xA20B, // 41483
|
|
SpatialFrequencyResponseExif = 0xA20C,// 41484
|
|
FocalPlaneXResolutionExif = 0xA20E, // 41486
|
|
FocalPlaneYResolutionExif = 0xA20F, // 41487
|
|
FocalPlaneResolutionUnitExif = 0xA210,// 41488
|
|
SubjectLocationExif = 0xA214, // 41492
|
|
ExposureIndexExif = 0xA215, // 41493
|
|
SensingMethodExif = 0xA217, // 41495
|
|
FileSource = 0xA300, // 41728
|
|
SceneType = 0xA301, // 41729
|
|
CFAPatternExif = 0xA302, // 41730
|
|
CustomRendered = 0xA401, // 41985
|
|
ExposureMode = 0xA402, // 41986
|
|
WhiteBalance = 0xA403, // 41987
|
|
|
|
// Adobe DNG and cDNG Extensions (0xC6, 0xc7)
|
|
DNGVersion = 0xC612, // 50706
|
|
DNGBackwardVersion = 0xC613, // 50707
|
|
UniqueCameraModel = 0xC614, // 50708
|
|
LocalizedCameraModel = 0xC615, // 50709
|
|
CFALayout = 0xC617, // 50711
|
|
LinearizationTable = 0xC618, // 50712
|
|
BlackLevelRepeatDim = 0xC619, // 50713
|
|
BlackLevel = 0xC61A, // 50714
|
|
BlackLevelDeltaH = 0xC61B, // 50715
|
|
BlackLevelDeltaV = 0xC61C, // 50716
|
|
WhiteLevel = 0xC61D, // 50717
|
|
DefaultScale = 0xC61E, // 50718
|
|
DefaultCropOrigin = 0xC61F, // 50719
|
|
DefaultCropSize = 0xC620, // 50720
|
|
ColorMatrix1 = 0xC621, // 50721
|
|
ColorMatrix2 = 0xC622, // 50722
|
|
CameraCalibration1 = 0xC623, // 50723
|
|
CameraCalibration2 = 0xC624, // 50724
|
|
ReductionMatrix1 = 0xC625, // 50725
|
|
ReductionMatrix2 = 0xC626, // 50726
|
|
AnalogBalance = 0xC627, // 50727
|
|
AsShotNeutral = 0xC628, // 50728
|
|
AsShotWhiteXY = 0xC629, // 50729
|
|
BaselineExposure = 0xC62A, // 50730
|
|
BaselineNoise = 0xC62B, // 50731
|
|
BaselineSharpness = 0xC62C, // 50732
|
|
BayerGreenSplit = 0xC62D, // 50733
|
|
LinearResponseLimit = 0xC62E, // 50734
|
|
CameraSerialNumber = 0xC62F, // 50735
|
|
LensInfo = 0xC630, // 50736
|
|
ChromaBlurRadius = 0xC631, // 50737
|
|
AntiAliasStrength = 0xC632, // 50738
|
|
ShadowScale = 0xC633, // 50739
|
|
DNGPrivateData = 0xC634, // 50740
|
|
MakerNoteSafety = 0xC635, // 50741
|
|
CalibrationIlluminant1 = 0xC65A, // 50778
|
|
CalibrationIlluminant2 = 0xC65B, // 50779
|
|
BestQualityScale = 0xC65C, // 50780
|
|
RawDataUniqueID = 0xC65D, // 50781
|
|
OriginalRawFileName = 0xC68B, // 50827
|
|
OriginalRawFileData = 0xC68C, // 50828
|
|
ActiveArea = 0xC68D, // 50829
|
|
MaskedAreas = 0xC68E, // 50830
|
|
AsShotICCProfile = 0xC68F, // 50831
|
|
AsShotPreProfileMatrix = 0xC690, // 50832
|
|
CurrentICCProfile = 0xC691, // 50833
|
|
CurrentPreProfileMatrix = 0xC692, // 50834
|
|
ColorimetricReference = 0xC6BF, // 50879
|
|
CameraCalibrationSignature = 0xC6F3, // 50931
|
|
ProfileCalibrationSignature = 0xC6F4, // 50932
|
|
ExtraCameraProfiles = 0xC6F6, // 50934
|
|
AsShotProfileName = 0xC6F8, // 50936
|
|
NoiseReductionApplied = 0xC6F9, // 50937
|
|
ProfileName = 0xC6FA, // 50938
|
|
ProfileHueSatMapDims = 0xC6FB, // 50939
|
|
ProfileHueSatMapData1 = 0xC6FC, // 50940
|
|
ProfileHueSatMapData2 = 0xC6FD, // 50941
|
|
ProfileToneCurve = 0xC6FE, // 50942
|
|
ProfileEmbedPolicy = 0xC6FF, // 50943
|
|
ProfileCopyright = 0xC700, // 50944
|
|
ForwardMatrix1 = 0xC714, // 50964
|
|
ForwardMatrix2 = 0xC715, // 50965
|
|
PreviewApplicationName = 0xC716, // 50966
|
|
PreviewApplicationVersion = 0xC717, // 50967
|
|
PreviewSettingsName = 0xC718, // 50968
|
|
PreviewSettingsDigest = 0xC719, // 50969
|
|
PreviewColorSpace = 0xC71A, // 50970
|
|
PreviewDateTime = 0xC71B, // 50971
|
|
RawImageDigest = 0xC71C, // 50972
|
|
OriginalRawFileDigest = 0xC71D, // 50973
|
|
SubTileBlockSize = 0xC71E, // 50974
|
|
RowInterleaveFactor = 0xC71F, // 50975
|
|
ProfileLookTableDims = 0xC725, // 50981
|
|
ProfileLookTableData = 0xC726, // 50982
|
|
OpcodeList1 = 0xC740, // 51008
|
|
OpcodeList2 = 0xC741, // 51009
|
|
OpcodeList3 = 0xC74E, // 51022
|
|
NoiseProfile = 0xC761, // 51041
|
|
TimeCodes = 0xC763, // 51043
|
|
FrameRate = 0xc764, // 51044
|
|
TStop = 0xc772, // 51058
|
|
OriginalDefaultFinalSize = 0xC791, // 51089
|
|
OriginalBestQualityFinalSize = 0xC792,// 51090
|
|
OriginalDefaultCropSize = 0xC793, // 51091
|
|
ProfileHueSatMapEncoding = 0xC7A3, // 51107
|
|
ProfileLookTableEncoding = 0xC7A4, // 51108
|
|
BaselineExposureOffset = 0xC7A5, // 51109
|
|
DefaultBlackRender = 0xC7A6, // 51110
|
|
NewRawImageDigest = 0xC7A7, // 51111
|
|
RawToPreviewGain = 0xC7A8, // 51112
|
|
DefaultUserCrop = 0xC7B5, // 51125
|
|
DepthFormat = 0xC7E9, // 51177
|
|
DepthNear = 0xC7EA, // 51178
|
|
DepthFar = 0xC7EB, // 51179
|
|
DepthUnits = 0xC7EC, // 51180
|
|
DepthMeasureType = 0xC7ED, // 51181
|
|
EnhanceParams = 0xC7EE // 51182
|
|
};
|
|
|
|
struct ValueArray<T, auto Count> {
|
|
if (Count > 1) {
|
|
T Values[Count];
|
|
} else {
|
|
T Values[Count] [[hidden, no_unique_address]];
|
|
T Value;
|
|
}
|
|
} [[inline]];
|
|
|
|
struct ValueOffset<T, auto Count> {
|
|
u64 Size = sizeof(T) * Count;
|
|
if (Size <= ValueOffsetSize) {
|
|
ValueArray<T, Count> ValueArray;
|
|
padding[ValueOffsetSize - Size];
|
|
} else {
|
|
Big<u32> Offset;
|
|
ValueArray<T, Count> ValueArray @ Offset;
|
|
}
|
|
} [[inline]];
|
|
|
|
struct IFDEntry {
|
|
TIFFTag Tag;
|
|
TIFFFieldType Type;
|
|
Big<u32> Count;
|
|
|
|
match (Type) {
|
|
(TIFFFieldType::BYTE): ValueOffset<u8, Count> ValueOffset;
|
|
(TIFFFieldType::ASCII): ValueOffset<char, Count> ValueOffset;
|
|
(TIFFFieldType::SHORT): ValueOffset<u16, Count> ValueOffset;
|
|
(TIFFFieldType::LONG): ValueOffset<u32, Count> ValueOffset;
|
|
(TIFFFieldType::RATIONAL): ValueOffset<TIFFRational<u32>, Count> ValueOffset;
|
|
(TIFFFieldType::SBYTE): ValueOffset<s8, Count> ValueOffset;
|
|
(TIFFFieldType::UNDEFINED): ValueOffset<u8, Count> ValueOffset;
|
|
(TIFFFieldType::SSHORT): ValueOffset<s16, Count> ValueOffset;
|
|
(TIFFFieldType::SLONG): ValueOffset<s32, Count> ValueOffset;
|
|
(TIFFFieldType::SRATIONAL): ValueOffset<TIFFRational<s32>, Count> ValueOffset;
|
|
(TIFFFieldType::FLOAT): ValueOffset<float, Count> ValueOffset;
|
|
(TIFFFieldType::DOUBLE): ValueOffset<double, Count> ValueOffset;
|
|
(TIFFFieldType::LONG8): ValueOffset<u64, Count> ValueOffset;
|
|
(TIFFFieldType::SLONG8): ValueOffset<s64, Count> ValueOffset;
|
|
(_): {
|
|
padding[ValueOffsetSize];
|
|
std::print(std::format("TIFFFieldType {} not supported", u16(Type)));
|
|
}
|
|
}
|
|
} [[name(std::string::replace(std::core::formatted_value(Tag), "TIFFTag::", ""))]];
|
|
|
|
fn get_field(ref auto entries, TIFFTag tag) {
|
|
for (u64 i = 0, i < std::core::member_count(entries), i = i + 1) {
|
|
if (entries[i].Tag == tag) {
|
|
return i;
|
|
}
|
|
}
|
|
std::error(std::format("Tag {} not found in directory", tag));
|
|
};
|
|
|
|
struct ImageData<auto Desc> {
|
|
u64 Index = std::core::array_index();
|
|
u64 Offset = parent.DirectoryEntry[parent.OffsetField].ValueOffset.ValueArray.Values[Index];
|
|
u64 ByteCount = parent.DirectoryEntry[parent.ByteCountField].ValueOffset.ValueArray.Values[Index];
|
|
std::mem::Bytes<ByteCount> ImageData @ Offset [[name(std::format("{} {}", Desc, Index))]];
|
|
} [[inline]];
|
|
|
|
u64 currentIFD = 0;
|
|
struct IFD {
|
|
u64 Number = currentIFD;
|
|
Big<u16> NumberDirectoryEntries;
|
|
IFDEntry DirectoryEntry[NumberDirectoryEntries];
|
|
Big<u32> NextIFD;
|
|
|
|
try {
|
|
u64 OffsetField = get_field(DirectoryEntry, TIFFTag::StripOffsets);
|
|
u64 ByteCountField = get_field(DirectoryEntry, TIFFTag::StripByteCounts);
|
|
u64 Count = std::core::member_count(DirectoryEntry[OffsetField].ValueOffset.ValueArray.Values);
|
|
ImageData<"Strip"> Strips[Count];
|
|
} catch {}
|
|
|
|
try {
|
|
u64 OffsetField = get_field(DirectoryEntry, TIFFTag::TileOffsets);
|
|
u64 ByteCountField = get_field(DirectoryEntry, TIFFTag::TileByteCounts);
|
|
u64 Count = std::core::member_count(DirectoryEntry[OffsetField].ValueOffset.ValueArray.Values);
|
|
ImageData<"Tile"> Tiles[Count];
|
|
} catch {}
|
|
} [[name(std::format("IFD {}", Number))]];
|
|
|
|
struct IFDS {
|
|
IFD IFD;
|
|
if (IFD.NextIFD > 0) {
|
|
currentIFD += 1;
|
|
IFDS IFD_tmp @ IFD.NextIFD;
|
|
}
|
|
} [[inline]];
|
|
|
|
struct TIFFFile {
|
|
TIFFHeader Header;
|
|
IFDS @ Header.Offset;
|
|
};
|
|
|
|
TIFFFile File @ 0x00;
|