Skip to content

Instantly share code, notes, and snippets.

@VelocityRa
Created April 20, 2020 16:34
Show Gist options
  • Save VelocityRa/f8be309650929ea409d108f103fbf728 to your computer and use it in GitHub Desktop.
Save VelocityRa/f8be309650929ea409d108f103fbf728 to your computer and use it in GitHub Desktop.
010 Editor Template for .DNG files. Based on TIF.v1.7 template.
//------------------------------------------------
//--- 010 Editor v2.1 Binary Template
//
// File: TIF.bt
// Authors: Kevin O. Grover
// E-mail: kevin@kevingrover.net
// Version: 1.7
// Purpose: A template for parsing TIFF (Tagged Image File Format) files. Also now handles GeoTIFF files.
// Category: Image
// File Mask: *.tif,*.tiff
// ID Bytes: 49 49 2A 00, 4D 4D 00 2A
// History:
// 1.7 2016-01-27 SweetScape: Updated header for repository submission.
// 1.6 2014-08-11 KOG: Merged in ELB's GeoTIFF (many tags), some cleanup
// 1.5 2012-09 ELB: add GeoTIFF rev 1.8.2
// 1.4 2007-02-28 KOG: Updated for 010 2.1 (uses EnumToString)
// 1.3 2005-06-30 KOG: Updated MSFax Tag list
// 1.2 2005-05-19 KOG: Added new iFax tags and best guess for MS Fax Tags
// 1.1 2005-05-11 KOG: *Many* more TIFF Tag IDs (generated with a Perl script)
// 1.0 2005-05-09 KOG: Initial version
//
// This template was written to the TIFF6 specification. You can get
// the TIFF documentation from Adobe (http://www.adobe.com) after
// registering, or from the libtiff home page: http://www.libtiff.org.
//
// GeoTiff template written to GeoTIFF specification 1.8.2, which can
// be found at the following address:
// http://www.remotesensing.org/geotiff/spec/geotiffhome.html
//
// NOTE: This is NOT a comprehensive list of TIFF tags. Many tags are
// registered as private and not reported anywhere. If you run
// across any definitions, forward them to me and I'll add them
// to this template.
//------------------------------------------------
// Check the Byte Order Mark to determine if file is Little or Big Endian
local uint16 tbom;
tbom = ReadUShort(0);
if (tbom == 0x4949) {
LittleEndian();
}
else if (tbom == 0x4D4D) {
BigEndian();
}
else {
Warning("Invalid TIFF File: Bad BOM (Byte Order Mark). Template Terminated.");
return -1;
}
local quad nextIFD = 0; // Pointer to next IFD (or 0)
// DO NOT EDIT. This structure is generated from TIFF_Tags.pl
// enum of TAG ids
typedef enum <uint16> eTAG {
GPSVersionID=0,GPSLatitudeRef,GPSLatitude,GPSLongitudeRef,GPSLongitude,GPSAltitudeRef,GPSAltitude,GPSTimeStamp,GPSSatellites,GPSStatus,GPSMeasureMode,GPSDOP,GPSSpeedRef,GPSSpeed,GPSTrackRef,GPSTrack,GPSImgDirectionRef,GPSImgDirection,GPSMapDatum,GPSDestLatitudeRef,GPSDestLatitude,GPSDestLongitudeRef,GPSDestLongitude,GPSDestBearingRef,GPSDestBearing,GPSDestDistanceRef,GPSDestDistance,GPSProcessingMethod,GPSAreaInformation,GPSDateStamp,GPSDifferential,
NewSubFileType=254,SubFileType,ImageWidth,ImageLength,BitsPerSample,Compression,
PhotometricInterpretation=262,Thresholding,CellWidth,CellLength,FillOrder,
DocumentName=269,ImageDescription,Make,Model,StripOffsets,Orientation,
SamplesPerPixel=277,RowsPerStrip,StripByteCounts,MinSampleValue,MaxSampleValue,XResolution,YResolution,PlanarConfiguration,PageName,XPosition,YPosition,FreeOffsets,FreeByteCounts,GrayResponseUnit,GrayResponseCurve,Group3Options,Group4Options,
ResolutionUnit=296,PageNumber,
ColorResponseUnit=300,TransferFunction,
Software=305,DateTime,
Artist=315,HostComputer,Predictor,WhitePoint,PrimaryChromacities,ColorMap,HalftoneHints,TileWidth,TileLength,TileOffsets,TileByteCounts,BadFaxLines,CleanFaxData,ConsecutiveBadFaxLines,
SubIFDs=330,
InkSet=332,InkNames,NumberOfInks,
DotRange=336,TargetPrinter,ExtraSamples,SampleFormat,SMinSampleValue,SMaxSampleValue,TransferRange,ClipPath,XClipPathUnits,YClipPathUnits,Indexed,JPEGTables,
OPIProxy=351,
GlobalParametersIFD=400,ProfileType,FaxProfile,CodingMethods,VersionYear,ModeNumber,
JPEGProc=512,JPEGInterchangeFormat,JPEGInterchangeFormatLength,JPEGRestartInterval,
JPEGLosslessPredictors=517,JPEGPointTransforms,JPEGQTables,JPEGDCTables,JPEGACTables,
YCbCrCoefficients=529,YCbCrSubsampling,YCbCrPositioning,ReferenceBlackWhite,
XMP=700,
ImageID=32781,
Wang_Annotation=32932,
Matteing=32995,DataType,ImageDepth,TileDepth,
CFARepeatPatternDim=33421,CFAPattern,BatteryLevel,
Copyright=33432,
ExposureTime=33434,
FNumber=33437,
ModelPixelScaleTag=33550,
IPTC_NAA=33723,
INGR_Packet_Data_Tag=33918,INGR_Flag_Registers,IntergraphMatrixTag,
ModelTiepointTag=33922,
Site=34016,ColorSequence,IT8Header,RasterPadding,BitsPerRunLength,BitsPerExtendedRunLength,ColorTable,ImageColorIndicator,BackgroundColorIndicator,ImageColorValue,BackgroundColorValue,PixelInensityRange,TransparencyIndicator,ColorCharacterization,HCUsage,
ModelTransformationTag=34264,
PhotoshopImageResources=34377,
ExifIFD=34665,
InterColourProfile=34675,
GeoKeyDirectoryTag=34735,GeoDoubleParamsTag,GeoAsciiParamsTag,
ExposureProgram=34850,
SpectralSensitibity=34852,GPSInfo,
ISOSpeedRatings=34855,OECF,Interlace,TimeZoneOffset,SelfTimerMode,
FaxRecvParams=34908,FaxSubAddress,FaxRecvTime,
ExifVersion=36864,
DateTimeOriginal=36867,DateTimeDigitized,
ComponentsConfiguration=37121,CompressedBitsPerPixel,
ShutterSpeedValue=37377,ApertureValue,BrightnessValue,ExposureBiasValue,MaxApertureValue,SubjectDistance,MeteringMode,LightSource,Flash,FocalLength,FlashEnergy,SpatialFrequencyResponse,Noise,FocalPlaneXResolution,FocalPlaneYResolution,FocalPlaneResolutionUnit,ImageNumber,SecurityClassification,ImageHistory,SubjectArea,ExposureIndex,TIFF_EPStandardID,SensingMethod,
StoNits=37439,
MakerNote=37500,
UserComment=37510,
SubSecTime=37520,SubSecTimeOriginal,SubSecTimeDigitized,
ImageSourceData=37724,
MSFax_CSID=40001,MSFax_TSID,MSFax_Device,MSFax_RoutingInfo,MSFax_CallerID,MSFax_RecipientName,MSFax_RecipientFaxNumber,MSFax_RecipientCompany,MSFax_RecipientAddress,MSFax_RecipientStreet,MSFax_RecipientCity,MSFax_RecipientZipCode,MSFax_RecipientCountry,MSFax_RecipientTitle,MSFax_RecipientDepartment,MSFax_RecipientOffice,MSFax_RecipientOfficePhone,MSFax_RecipientHomePhone,MSFax_Recipient40019,MSFax_RecipientEmail,MSFax_SenderName,MSFax_SenderFaxNumber,MSFax_SenderCompany,MSFax_SenderAddress,MSFax_SenderStreet,MSFax_SenderCity,MSFax_SenderZipCode,MSFax_SenderCountry,MSFax_SenderTitle,MSFax_SenderDepartment,MSFax_SenderOffice,MSFax_SenderOfficePhone,MSFax_SenderHomePhone,MSFax_Sender40034,MSFax_SenderEmail,MSFax_BillingCode,MSFax_UserName,MSFax_40038,MSFax_Document,MSFax_CoverPageSubject,MSFax_Retries,MSFax_Priority,MSFax_ParentJobID,MSFax_SubmissionTime,MSFax_Scheduled,MSFax_TotalPages,MSFax_Type,MSFax_40048,MSFax_ErrorCode,MSFax_40050,MSFax_StartTime,MSFax_EndTime,MSFax_40053,
FlashpixVersion=40960,ColorSpace,PixelXDimension,PixelYDimension,RelatedSoundFile,InteroperabilityIFD,
FlashEnergy_Exif=41483,SpatialFrequencyResponse_Exif,
FocalPlaneXResolution_Exif=41486,FocalPlaneYResolution_Exif,FocalPlaneResolutionUnit_Exif,
SubjectLocation_Exif=41492,ExposureIndex_Exif,
SensingMethod_Exif=41495,
FileSource=41728,SceneType,CFAPattern_Exif,
CustomRendered=41985,ExposureMode,WhiteBalance,DigitalZoomRatio,FocalLengthIn35mmFilm,SceneCaptureType,GainControl,Contrast,Saturation,Sharpness,DeviceSettingDescription,SubjectDistanceRange,
GDAL_METADATA=42112,GDAL_NODATA,
Oce_Scanjob_Description=50215,Oce_Application_Selector,Oce_Identification_Number,Oce_ImageLogic_Characteristics,
PhotoshopAnnotations=50255,
DNGVersion=50706,DNGBackwardVersion,UniqueCameraModel,LocalizedCameraModel,CFAPlaneColor,CFALayout,LinearizationTable,BlackLevelRepeatDim,BlackLevel,BlackLevelDeltaH,BlackLevelDeltaV,WhiteLevel,DefaultScale,DefaultCropOrigin,DefaultCropSize,ColorMatrix1,ColorMatrix2,CameraCalibration1,CameraCalibration2,ReductionMatrix1,ReductionMatrix2,AnalogBalnace,AsShortNeutral,AsShortWhiteXY,BaselineExposure,BaselineNoise,BaselineSharpness,BayerGreenSplit,LinearResponseLimit,CameraSerialNumber,LensInfo,ChromaBlurRadius,AntiAliasStrength,
DNGPrivateDatea=50740,MakerNoteSafety,
CalibrationIlluminant1=50778,CalibrationIlluminant2,BestQualityScale,
Alias_Layer_Metadata=50784,
RawDataUniqueID = 50781,
OriginalRawFileName = 50827,
OriginalRawFileData = 50828,
ActiveArea = 50829,
MaskedAreas = 50830,
AsShotICCProfile = 50831,
AsShotPreProfileMatrix = 50832,
CurrentICCProfile = 50833,
CurrentPreProfileMatrix = 50834,
ColorimetricReference = 50879,
CameraCalibrationSignature = 50931,
ProfileCalibrationSignature = 50932,
ExtraCameraProfiles = 50933,
AsShotProfileName = 50934,
NoiseReductionApplied = 50935,
ProfileName = 50936,
ProfileHueSatMapDims = 50937,
ProfileHueSatMapData1 = 50938,
ProfileHueSatMapData2 = 50939,
ProfileToneCurve = 50940,
ProfileEmbedPolicy = 50941,
ProfileCopyright = 50942,
ForwardMatrix1 = 50964,
ForwardMatrix2 = 50965,
PreviewApplicationName = 50966,
PreviewApplicationVersion = 50967,
PreviewSettingsName = 50968,
PreviewSettingsDigest = 50969,
PreviewColorSpace = 50970,
PreviewDateTime = 50971,
RawImageDigest = 50972,
OriginalRawFileDigest = 50973,
SubTileBlockSize = 50974,
RowInterleaveFactor = 50975,
ProfileLookTableDims = 50981,
ProfileLookTableData = 50982,
OpcodeList1 = 51008,
OpcodeList2 = 51009,
OpcodeList3 = 51022,
NoiseProfile = 51041,
OriginalDefaultFinalSize = 51089,
OriginalBestQualityFinalSize = 51090,
OriginalDefaultCropSize = 51091,
ProfileHueSatMapEncoding = 51107,
ProfileLookTableEncoding = 51108,
BaselineExposureOffset = 51109,
DefaultBlackRender = 51110,
NewRawImageDigest = 51111,
RawToPreviewGain = 51112,
CacheBlob = 51113,
CacheVersion = 51114,
DefaultUserCrop = 51125,
KodakKDCPrivateIFD = 65024,
TimeCodes = 0xC763,
FrameRate = 0xC764,
TStop = 0xC772,
ReelName = 0xC789,
CameraLabel= 0xC7A1,
} TAG;
// enum of TAG types
typedef enum <uint16> eTAGTYPE {
eBYTE=1, eASCII, eSHORT, eLONG, eRATIONAL,
eSBYTE, eUNDEF, eSSHORT, eSLONG, eSRATIONAL,
eFLOAT, eDOUBLE
} TAGTYPE;
//enum for Compression types
typedef enum <uint16> eCOMP {
Uncompressed=1,CCITT_1D,Group3Fax,Group4Fax,LZW,JPEG,JPEG2,
Deflate=8,
NeXT2Bit=32766,CCITT_RLE=32771,PackBits=32773,
ThunderScan4bit=32809,cRasterPadding=32895,
RLEforLW=32896,RLEforHC,RLEforBL,
Pixar10bitLZW=32908,PixarCompanded11bitZIP,
PKZIP_Deflate=32946,
Kodak_DCS=32947,
JBIG=34661,
SGI32LogLum=34676,
SIG24LogLum=34677,
JPEG_2000=34712
} COMP;
//enum for PhotometricInterpretation
typedef enum <uint16> ePHOTO {
WhiteIsZero,BlackIsZero,RGB,RGB_Palette,Transparency_Mask,CMYK,YCbCr,
CIELab=8,ICCLab,ITULab,CFA=32803,CIELog2L=32844,CIELog2Luv,LinearRaw=34892
} PHOTO;
//enum for ResolutionUnit
typedef enum <uint16> eRES {
None=1,Inch,Centimeter
} RES;
// enum of GeoKEYs for GeoTiff
typedef enum <uint16> eKEYGeoTiff {
undefinedGeoKey=1,
/* GeoTIFF GeoKey Database */
/* Note: Any changes/additions to this database require */
/* a change in the revision value in geokeys.h */
/* Revised 28 Sep 1995 NDR -- Added Rev. 1.0 aliases. */
/* 6.2.1 GeoTIFF Configuration Keys */
GTModelTypeGeoKey= 1024, /* Section 6.3.1.1 Codes */
GTRasterTypeGeoKey= 1025, /* Section 6.3.1.2 Codes */
GTCitationGeoKey= 1026, /* documentation */
/* 6.2.2 Geographic CS Parameter Keys */
GeographicTypeGeoKey= 2048, /* Section 6.3.2.1 Codes */
GeogCitationGeoKey= 2049, /* documentation */
GeogGeodeticDatumGeoKey= 2050, /* Section 6.3.2.2 Codes */
GeogPrimeMeridianGeoKey= 2051, /* Section 6.3.2.4 codes */
GeogLinearUnitsGeoKey= 2052, /* Section 6.3.1.3 Codes */
GeogLinearUnitSizeGeoKey= 2053, /* meters */
GeogAngularUnitsGeoKey= 2054, /* Section 6.3.1.4 Codes */
GeogAngularUnitSizeGeoKey= 2055, /* radians */
GeogEllipsoidGeoKey= 2056, /* Section 6.3.2.3 Codes */
GeogSemiMajorAxisGeoKey= 2057, /* GeogLinearUnits */
GeogSemiMinorAxisGeoKey= 2058, /* GeogLinearUnits */
GeogInvFlatteningGeoKey= 2059, /* ratio */
GeogAzimuthUnitsGeoKey= 2060, /* Section 6.3.1.4 Codes */
GeogPrimeMeridianLongGeoKey= 2061, /* GeoAngularUnit */
GeogTOWGS84GeoKey= 2062, /* 2011 - proposed addition */
/* 6.2.3 Projected CS Parameter Keys */
/* Several keys have been renamed,*/
/* and the deprecated names aliased for backward compatibility */
ProjectedCSTypeGeoKey= 3072, /* Section 6.3.3.1 codes */
PCSCitationGeoKey= 3073, /* documentation */
ProjectionGeoKey= 3074, /* Section 6.3.3.2 codes */
ProjCoordTransGeoKey= 3075, /* Section 6.3.3.3 codes */
ProjLinearUnitsGeoKey= 3076, /* Section 6.3.1.3 codes */
ProjLinearUnitSizeGeoKey= 3077, /* meters */
ProjStdParallel1GeoKey= 3078, /* GeogAngularUnit */
/* ProjStdParallelGeoKey=ProjStdParallel1GeoKey, alias ** */
ProjStdParallel2GeoKey= 3079, /* GeogAngularUnit */
ProjNatOriginLongGeoKey= 3080, /* GeogAngularUnit */
/* ProjOriginLongGeoKey=ProjNatOriginLongGeoKey, alias ** */
ProjNatOriginLatGeoKey= 3081, /* GeogAngularUnit */
/* ProjOriginLatGeoKey=ProjNatOriginLatGeoKey, alias ** */
ProjFalseEastingGeoKey= 3082, /* ProjLinearUnits */
ProjFalseNorthingGeoKey= 3083, /* ProjLinearUnits */
ProjFalseOriginLongGeoKey= 3084, /* GeogAngularUnit */
ProjFalseOriginLatGeoKey= 3085, /* GeogAngularUnit */
ProjFalseOriginEastingGeoKey= 3086, /* ProjLinearUnits */
ProjFalseOriginNorthingGeoKey= 3087, /* ProjLinearUnits */
ProjCenterLongGeoKey= 3088, /* GeogAngularUnit */
ProjCenterLatGeoKey= 3089, /* GeogAngularUnit */
ProjCenterEastingGeoKey= 3090, /* ProjLinearUnits */
ProjCenterNorthingGeoKey= 3091, /* ProjLinearUnits */
ProjScaleAtNatOriginGeoKey= 3092, /* ratio */
/* ProjScaleAtOriginGeoKey=ProjScaleAtNatOriginGeoKey, alias ** */
ProjScaleAtCenterGeoKey= 3093, /* ratio */
ProjAzimuthAngleGeoKey= 3094, /* GeogAzimuthUnit */
ProjStraightVertPoleLongGeoKey= 3095, /* GeogAngularUnit */
ProjRectifiedGridAngleGeoKey= 3096, /* GeogAngularUnit */
/* 6.2.4 Vertical CS Keys */
VerticalCSTypeGeoKey= 4096, /* Section 6.3.4.1 codes */
VerticalCitationGeoKey= 4097, /* documentation */
VerticalDatumGeoKey= 4098, /* Section 6.3.4.2 codes */
VerticalUnitsGeoKey= 4099, /* Section 6.3.1 (.x, codes */
/* End of Data base */
userDefinedGeoKey = 32767
} GeoKEYlabel;
/************************************************************
* 6.3.1 GeoTIFF General Codes
************************************************************/
/* 6.3.1.1 Model Type Codes */
typedef enum <short> {
ModelTypeProjected = 1, /* Projection Coordinate System */
ModelTypeGeographic = 2, /* Geographic latitude-longitude System */
ModelTypeGeocentric = 3, /* Geocentric (X,Y,Z) Coordinate System */
// ModelProjected = ModelTypeProjected, /* alias */
// ModelGeographic = ModelTypeGeographic, /* alias */
// ModelGeocentric = ModelTypeGeocentric /* alias */
} modeltype_t;
/* 6.3.1.2 Raster Type Codes */
typedef enum <short> {
RasterPixelIsArea = 1, /* Standard pixel-fills-grid-cell */
RasterPixelIsPoint = 2 /* Pixel-at-grid-vertex */
} rastertype_t;
/* 6.3.1.3 Linear Units Codes */
typedef enum <short> {
Linear_Meter= 9001,
Linear_Foot= 9002,
Linear_Foot_US_Survey= 9003,
Linear_Foot_Modified_American= 9004,
Linear_Foot_Clarke= 9005,
Linear_Foot_Indian= 9006,
Linear_Link= 9007,
Linear_Link_Benoit= 9008,
Linear_Link_Sears= 9009,
Linear_Chain_Benoit= 9010,
Linear_Chain_Sears= 9011,
Linear_Yard_Sears= 9012,
Linear_Yard_Indian= 9013,
Linear_Fathom= 9014,
Linear_Mile_International_Nautical= 9015
} LinearUnitCode_t;
/* 6.3.1.4 Angular Units Codes */
typedef enum <short> {
Angular_Radian= 9101,
Angular_Degree= 9102,
Angular_Arc_Minute= 9103,
Angular_Arc_Second= 9104,
Angular_Grad= 9105,
Angular_Gon= 9106,
Angular_DMS= 9107,
Angular_DMS_Hemisphere= 9108
} AngularUnitCode_t;
/* 6.3.2.1 Geographic CS Type Codes */
typedef enum <short> {
GCS_Adindan = 4201,
GCS_AGD66 = 4202,
GCS_AGD84 = 4203,
GCS_Ain_el_Abd = 4204,
GCS_Afgooye = 4205,
GCS_Agadez = 4206,
GCS_Lisbon = 4207,
GCS_Aratu = 4208,
GCS_Arc_1950 = 4209,
GCS_Arc_1960 = 4210,
GCS_Batavia = 4211,
GCS_Barbados = 4212,
GCS_Beduaram = 4213,
GCS_Beijing_1954 = 4214,
GCS_Belge_1950 = 4215,
GCS_Bermuda_1957 = 4216,
GCS_Bern_1898 = 4217,
GCS_Bogota = 4218,
GCS_Bukit_Rimpah = 4219,
GCS_Camacupa = 4220,
GCS_Campo_Inchauspe = 4221,
GCS_Cape = 4222,
GCS_Carthage = 4223,
GCS_Chua = 4224,
GCS_Corrego_Alegre = 4225,
GCS_Cote_d_Ivoire = 4226,
GCS_Deir_ez_Zor = 4227,
GCS_Douala = 4228,
GCS_Egypt_1907 = 4229,
GCS_ED50 = 4230,
GCS_ED87 = 4231,
GCS_Fahud = 4232,
GCS_Gandajika_1970 = 4233,
GCS_Garoua = 4234,
GCS_Guyane_Francaise = 4235,
GCS_Hu_Tzu_Shan = 4236,
GCS_HD72 = 4237,
GCS_ID74 = 4238,
GCS_Indian_1954 = 4239,
GCS_Indian_1975 = 4240,
GCS_Jamaica_1875 = 4241,
GCS_JAD69 = 4242,
GCS_Kalianpur = 4243,
GCS_Kandawala = 4244,
GCS_Kertau = 4245,
GCS_KOC = 4246,
GCS_La_Canoa = 4247,
GCS_PSAD56 = 4248,
GCS_Lake = 4249,
GCS_Leigon = 4250,
GCS_Liberia_1964 = 4251,
GCS_Lome = 4252,
GCS_Luzon_1911 = 4253,
GCS_Hito_XVIII_1963 = 4254,
GCS_Herat_North = 4255,
GCS_Mahe_1971 = 4256,
GCS_Makassar = 4257,
GCS_EUREF89 = 4258,
GCS_Malongo_1987 = 4259,
GCS_Manoca = 4260,
GCS_Merchich = 4261,
GCS_Massawa = 4262,
GCS_Minna = 4263,
GCS_Mhast = 4264,
GCS_Monte_Mario = 4265,
GCS_M_poraloko = 4266,
GCS_NAD27 = 4267,
GCS_NAD_Michigan = 4268,
GCS_NAD83 = 4269,
GCS_Nahrwan_1967 = 4270,
GCS_Naparima_1972 = 4271,
GCS_GD49 = 4272,
GCS_NGO_1948 = 4273,
GCS_Datum_73 = 4274,
GCS_NTF = 4275,
GCS_NSWC_9Z_2 = 4276,
GCS_OSGB_1936 = 4277,
GCS_OSGB70 = 4278,
GCS_OS_SN80 = 4279,
GCS_Padang = 4280,
GCS_Palestine_1923 = 4281,
GCS_Pointe_Noire = 4282,
GCS_GDA94 = 4283,
GCS_Pulkovo_1942 = 4284,
GCS_Qatar = 4285,
GCS_Qatar_1948 = 4286,
GCS_Qornoq = 4287,
GCS_Loma_Quintana = 4288,
GCS_Amersfoort = 4289,
GCS_RT38 = 4290,
GCS_SAD69 = 4291,
GCS_Sapper_Hill_1943 = 4292,
GCS_Schwarzeck = 4293,
GCS_Segora = 4294,
GCS_Serindung = 4295,
GCS_Sudan = 4296,
GCS_Tananarive = 4297,
GCS_Timbalai_1948 = 4298,
GCS_TM65 = 4299,
GCS_TM75 = 4300,
GCS_Tokyo = 4301,
GCS_Trinidad_1903 = 4302,
GCS_TC_1948 = 4303,
GCS_Voirol_1875 = 4304,
GCS_Voirol_Unifie = 4305,
GCS_Bern_1938 = 4306,
GCS_Nord_Sahara_1959 = 4307,
GCS_Stockholm_1938 = 4308,
GCS_Yacare = 4309,
GCS_Yoff = 4310,
GCS_Zanderij = 4311,
GCS_MGI = 4312,
GCS_Belge_1972 = 4313,
GCS_DHDN = 4314,
GCS_Conakry_1905 = 4315,
GCS_WGS_72 = 4322,
GCS_WGS_72BE = 4324,
GCS_WGS_84 = 4326,
GCS_Bern_1898_Bern = 4801,
GCS_Bogota_Bogota = 4802,
GCS_Lisbon_Lisbon = 4803,
GCS_Makassar_Jakarta = 4804,
GCS_MGI_Ferro = 4805,
GCS_Monte_Mario_Rome = 4806,
GCS_NTF_Paris = 4807,
GCS_Padang_Jakarta = 4808,
GCS_Belge_1950_Brussels = 4809,
GCS_Tananarive_Paris = 4810,
GCS_Voirol_1875_Paris = 4811,
GCS_Voirol_Unifie_Paris = 4812,
GCS_Batavia_Jakarta = 4813,
GCS_ATF_Paris = 4901,
GCS_NDG_Paris = 4902,
GCSE_Airy1830 = 4001,
GCSE_AiryModified1849 = 4002,
GCSE_AustralianNationalSpheroid = 4003,
GCSE_Bessel1841 = 4004,
GCSE_BesselModified = 4005,
GCSE_BesselNamibia = 4006,
GCSE_Clarke1858 = 4007,
GCSE_Clarke1866 = 4008,
GCSE_Clarke1866Michigan = 4009,
GCSE_Clarke1880_Benoit = 4010,
GCSE_Clarke1880_IGN = 4011,
GCSE_Clarke1880_RGS = 4012,
GCSE_Clarke1880_Arc = 4013,
GCSE_Clarke1880_SGA1922 = 4014,
GCSE_Everest1830_1937Adjustment = 4015,
GCSE_Everest1830_1967Definition = 4016,
GCSE_Everest1830_1975Definition = 4017,
GCSE_Everest1830Modified = 4018,
GCSE_GRS1980 = 4019,
GCSE_Helmert1906 = 4020,
GCSE_IndonesianNationalSpheroid = 4021,
GCSE_International1924 = 4022,
GCSE_International1967 = 4023,
GCSE_Krassowsky1940 = 4024,
GCSE_NWL9D = 4025,
GCSE_NWL10D = 4026,
GCSE_Plessis1817 = 4027,
GCSE_Struve1860 = 4028,
GCSE_WarOffice = 4029,
GCSE_WGS84 = 4030,
GCSE_GEM10C = 4031,
GCSE_OSU86F = 4032,
GCSE_OSU91A = 4033,
GCSE_Clarke1880 = 4034,
GCSE_Sphere = 4035
} GCSCode_t;
/* 6.3.2.2 Geodetic Datum Codes */
typedef enum <short> {
Datum_Adindan = 6201,
Datum_Australian_Geodetic_Datum_1966 = 6202,
Datum_Australian_Geodetic_Datum_1984 = 6203,
Datum_Ain_el_Abd_1970 = 6204,
Datum_Afgooye = 6205,
Datum_Agadez = 6206,
Datum_Lisbon = 6207,
Datum_Aratu = 6208,
Datum_Arc_1950 = 6209,
Datum_Arc_1960 = 6210,
Datum_Batavia = 6211,
Datum_Barbados = 6212,
Datum_Beduaram = 6213,
Datum_Beijing_1954 = 6214,
Datum_Reseau_National_Belge_1950 = 6215,
Datum_Bermuda_1957 = 6216,
Datum_Bern_1898 = 6217,
Datum_Bogota = 6218,
Datum_Bukit_Rimpah = 6219,
Datum_Camacupa = 6220,
Datum_Campo_Inchauspe = 6221,
Datum_Cape = 6222,
Datum_Carthage = 6223,
Datum_Chua = 6224,
Datum_Corrego_Alegre = 6225,
Datum_Cote_d_Ivoire = 6226,
Datum_Deir_ez_Zor = 6227,
Datum_Douala = 6228,
Datum_Egypt_1907 = 6229,
Datum_European_Datum_1950 = 6230,
Datum_European_Datum_1987 = 6231,
Datum_Fahud = 6232,
Datum_Gandajika_1970 = 6233,
Datum_Garoua = 6234,
Datum_Guyane_Francaise = 6235,
Datum_Hu_Tzu_Shan = 6236,
Datum_Hungarian_Datum_1972 = 6237,
Datum_Indonesian_Datum_1974 = 6238,
Datum_Indian_1954 = 6239,
Datum_Indian_1975 = 6240,
Datum_Jamaica_1875 = 6241,
Datum_Jamaica_1969 = 6242,
Datum_Kalianpur = 6243,
Datum_Kandawala = 6244,
Datum_Kertau = 6245,
Datum_Kuwait_Oil_Company = 6246,
Datum_La_Canoa = 6247,
Datum_Provisional_S_American_Datum_1956 = 6248,
Datum_Lake = 6249,
Datum_Leigon = 6250,
Datum_Liberia_1964 = 6251,
Datum_Lome = 6252,
Datum_Luzon_1911 = 6253,
Datum_Hito_XVIII_1963 = 6254,
Datum_Herat_North = 6255,
Datum_Mahe_1971 = 6256,
Datum_Makassar = 6257,
Datum_European_Reference_System_1989 = 6258,
Datum_Malongo_1987 = 6259,
Datum_Manoca = 6260,
Datum_Merchich = 6261,
Datum_Massawa = 6262,
Datum_Minna = 6263,
Datum_Mhast = 6264,
Datum_Monte_Mario = 6265,
Datum_M_poraloko = 6266,
Datum_North_American_Datum_1927 = 6267,
Datum_NAD_Michigan = 6268,
Datum_North_American_Datum_1983 = 6269,
Datum_Nahrwan_1967 = 6270,
Datum_Naparima_1972 = 6271,
Datum_New_Zealand_Geodetic_Datum_1949 = 6272,
Datum_NGO_1948 = 6273,
Datum_Datum_73 = 6274,
Datum_Nouvelle_Triangulation_Francaise = 6275,
Datum_NSWC_9Z_2 = 6276,
Datum_OSGB_1936 = 6277,
Datum_OSGB_1970_SN = 6278,
Datum_OS_SN_1980 = 6279,
Datum_Padang_1884 = 6280,
Datum_Palestine_1923 = 6281,
Datum_Pointe_Noire = 6282,
Datum_Geocentric_Datum_of_Australia_1994 = 6283,
Datum_Pulkovo_1942 = 6284,
Datum_Qatar = 6285,
Datum_Qatar_1948 = 6286,
Datum_Qornoq = 6287,
Datum_Loma_Quintana = 6288,
Datum_Amersfoort = 6289,
Datum_RT38 = 6290,
Datum_South_American_Datum_1969 = 6291,
Datum_Sapper_Hill_1943 = 6292,
Datum_Schwarzeck = 6293,
Datum_Segora = 6294,
Datum_Serindung = 6295,
Datum_Sudan = 6296,
Datum_Tananarive_1925 = 6297,
Datum_Timbalai_1948 = 6298,
Datum_TM65 = 6299,
Datum_TM75 = 6300,
Datum_Tokyo = 6301,
Datum_Trinidad_1903 = 6302,
Datum_Trucial_Coast_1948 = 6303,
Datum_Voirol_1875 = 6304,
Datum_Voirol_Unifie_1960 = 6305,
Datum_Bern_1938 = 6306,
Datum_Nord_Sahara_1959 = 6307,
Datum_Stockholm_1938 = 6308,
Datum_Yacare = 6309,
Datum_Yoff = 6310,
Datum_Zanderij = 6311,
Datum_Militar_Geographische_Institut = 6312,
Datum_Reseau_National_Belge_1972 = 6313,
Datum_Deutsche_Hauptdreiecksnetz = 6314,
Datum_Conakry_1905 = 6315,
Datum_WGS72 = 6322,
Datum_WGS72_Transit_Broadcast_Ephemeris = 6324,
Datum_WGS84 = 6326,
Datum_Ancienne_Triangulation_Francaise = 6901,
Datum_Nord_de_Guerre = 6902,
/* Ellipsoid-Only Datum:
Note: the numeric code is equal to the corresponding ellipsoid
code, minus 1000. */
DatumE_Airy1830 = 6001,
DatumE_AiryModified1849 = 6002,
DatumE_AustralianNationalSpheroid = 6003,
DatumE_Bessel1841 = 6004,
DatumE_BesselModified = 6005,
DatumE_BesselNamibia = 6006,
DatumE_Clarke1858 = 6007,
DatumE_Clarke1866 = 6008,
DatumE_Clarke1866Michigan = 6009,
DatumE_Clarke1880_Benoit = 6010,
DatumE_Clarke1880_IGN = 6011,
DatumE_Clarke1880_RGS = 6012,
DatumE_Clarke1880_Arc = 6013,
DatumE_Clarke1880_SGA1922 = 6014,
DatumE_Everest1830_1937Adjustment = 6015,
DatumE_Everest1830_1967Definition = 6016,
DatumE_Everest1830_1975Definition = 6017,
DatumE_Everest1830Modified = 6018,
DatumE_GRS1980 = 6019,
DatumE_Helmert1906 = 6020,
DatumE_IndonesianNationalSpheroid = 6021,
DatumE_International1924 = 6022,
DatumE_International1967 = 6023,
DatumE_Krassowsky1960 = 6024,
DatumE_NWL9D = 6025,
DatumE_NWL10D = 6026,
DatumE_Plessis1817 = 6027,
DatumE_Struve1860 = 6028,
DatumE_WarOffice = 6029,
DatumE_WGS84 = 6030,
DatumE_GEM10C = 6031,
DatumE_OSU86F = 6032,
DatumE_OSU91A = 6033,
DatumE_Clarke1880 = 6034,
DatumE_Sphere = 6035
} DatumCode_t;
/* 6.3.2.3 Ellipsoid Codes */
typedef enum <short> {
Ellipse_Airy_1830 = 7001,
Ellipse_Airy_Modified_1849 = 7002,
Ellipse_Australian_National_Spheroid = 7003,
Ellipse_Bessel_1841 = 7004,
Ellipse_Bessel_Modified = 7005,
Ellipse_Bessel_Namibia = 7006,
Ellipse_Clarke_1858 = 7007,
Ellipse_Clarke_1866 = 7008,
Ellipse_Clarke_1866_Michigan = 7009,
Ellipse_Clarke_1880_Benoit = 7010,
Ellipse_Clarke_1880_IGN = 7011,
Ellipse_Clarke_1880_RGS = 7012,
Ellipse_Clarke_1880_Arc = 7013,
Ellipse_Clarke_1880_SGA_1922 = 7014,
Ellipse_Everest_1830_1937_Adjustment = 7015,
Ellipse_Everest_1830_1967_Definition = 7016,
Ellipse_Everest_1830_1975_Definition = 7017,
Ellipse_Everest_1830_Modified = 7018,
Ellipse_GRS_1980 = 7019,
Ellipse_Helmert_1906 = 7020,
Ellipse_Indonesian_National_Spheroid = 7021,
Ellipse_International_1924 = 7022,
Ellipse_International_1967 = 7023,
Ellipse_Krassowsky_1940 = 7024,
Ellipse_NWL_9D = 7025,
Ellipse_NWL_10D = 7026,
Ellipse_Plessis_1817 = 7027,
Ellipse_Struve_1860 = 7028,
Ellipse_War_Office = 7029,
Ellipse_WGS_84 = 7030,
Ellipse_GEM_10C = 7031,
Ellipse_OSU86F = 7032,
Ellipse_OSU91A = 7033,
Ellipse_Clarke_1880 = 7034,
Ellipse_Sphere = 7035
} EllipsoidCode_t;
/* 6.3.2.4 Prime Meridian Codes */
typedef enum <short> {
PM_Greenwich = 8901,
PM_Lisbon = 8902,
PM_Paris = 8903,
PM_Bogota = 8904,
PM_Madrid = 8905,
PM_Rome = 8906,
PM_Bern = 8907,
PM_Jakarta = 8908,
PM_Ferro = 8909,
PM_Brussels = 8910,
PM_Stockholm = 8911
} PrimeMeridianCode_t;
/*6.3.3.1 Projected CS Type Codes */
/* 6.3.3.2 Projection Codes */
/* 6.3.3.3 Coordinate Transformation Codes */
typedef enum <short> {
CT_TransverseMercator = 1,
CT_TransvMercator_Modified_Alaska = 2,
CT_ObliqueMercator = 3,
CT_ObliqueMercator_Laborde = 4,
CT_ObliqueMercator_Rosenmund = 5,
CT_ObliqueMercator_Spherical = 6,
CT_Mercator = 7,
CT_LambertConfConic_2SP = 8,
CT_LambertConfConic_Helmert = 9,
CT_LambertAzimEqualArea = 10,
CT_AlbersEqualArea = 11,
CT_AzimuthalEquidistant = 12,
CT_EquidistantConic = 13,
CT_Stereographic = 14,
CT_PolarStereographic = 15,
CT_ObliqueStereographic = 16,
CT_Equirectangular = 17,
CT_CassiniSoldner = 18,
CT_Gnomonic = 19,
CT_MillerCylindrical = 20,
CT_Orthographic = 21,
CT_Polyconic = 22,
CT_Robinson = 23,
CT_Sinusoidal = 24,
CT_VanDerGrinten = 25,
CT_NewZealandMapGrid = 26,
CT_TransvMercator_SouthOriented= 27
} CTCode_t;
/* 6.3.4.1 Vertical CS Type Codes */
/* 6.3.4.2 Vertical CS Datum Codes */
// GeoTIFF Data Types
typedef struct {
SetBackColor( cLtAqua );
GeoKEYlabel label;
if (ReadUShort(FTell()) != 0)
{
TAG TiffTagLocation;
uint16 Length;
uint16 Offset;
}
else
{
uint16 direct;
uint16 size;
/* size indicate if value is SHORT or DOUBLE: !!!! to be confirmed !!!!! */
switch (size) {
case 1: /* Size SHORT */
switch (label) {
case GTModelTypeGeoKey: /* Section 6.3.1.1 codes */
modeltype_t value;
break;
case GTRasterTypeGeoKey: /* Section 6.3.1.2 codes */
rastertype_t value;
break;
case GeographicTypeGeoKey: /* Section 6.3.2.1 codes */
GCSCode_t value;
break;
case GeogGeodeticDatumGeoKey: /* Section 6.3.2.2 codes */
DatumCode_t value;
break;
case GeogPrimeMeridianGeoKey: /* Section 6.3.2.4 codes */
PrimeMeridianCode_t value;
break;
case GeogLinearUnitsGeoKey: /* Section 6.3.1.3 codes */
LinearUnitCode_t value;
break;
case GeogAngularUnitsGeoKey: /* Section 6.3.1.4 codes */
AngularUnitCode_t value;
break;
case GeogEllipsoidGeoKey: /* Section 6.3.2.3 Codes */
EllipsoidCode_t value;
break;
case GeogAzimuthUnitsGeoKey: /* Section 6.3.1.4 codes */
AngularUnitCode_t value;
break;
case ProjectedCSTypeGeoKey: /* Section 6.3.3.1 codes */
short value;
break;
case ProjectionGeoKey: /* Section 6.3.3.2 codes */
short value;
break;
case ProjCoordTransGeoKey: /* Section 6.3.3.3 codes */
short value;
break;
case ProjLinearUnitsGeoKey: /* Section 6.3.1.3 codes */
short value;
break;
case VerticalCSTypeGeoKey: /* Section 6.3.4.1 Codes */
short value;
break;
case VerticalDatumGeoKey: /* Section 6.3.4.2 Codes */
short value;
break;
case VerticalUnitsGeoKey: /* Section 6.3.1.3 Codes */
LinearUnitCode_t value;
break;
default:
short value;
};
break;
default: /* size <> SHORT !!!! to be confirmed !!!!! */
double value;
};
}
} GEOKEY <read=readGEOKEY>;
/**
* Reader for GEOKEY Types
* Shows the Number of entries and the type of the first directory tag
* @param ifd Pointer to the structure
*/
string readGEOKEY(local GEOKEY &gk) {
local string s;
// NOTE: This only works with 010 v2.1 or greater...
SPrintf(s,"%s (%d)",EnumToString(gk.label), gk.label);
return s;
}
typedef struct eGEOKEYDIR {
SetBackColor( cLtAqua );
uint16 GeoTiffVersion;
uint16 GeoTiffRevMajor;
uint16 GeoTiffRevMinor;
uint16 GeoKeyCount;
local uint16 i;
for (i==0; i<GeoKeyCount; i++)
{
GEOKEY GeoKeyValue;
}; //[GeoKeyCount];
} GEOKEYDIR;
// Rational (e.g. fraction: NUMERATOR/DENOMINATOR)
typedef struct {
uint32 num; // Numerator
uint32 dom; // Denominator
} RATIONAL <read=readRATIONAL,write=writeRATIONAL>;
string readRATIONAL(local RATIONAL &r) {
local string s;
SPrintf(s,"%d/%d",r.num,r.dom);
return s;
}
void writeRATIONAL(local RATIONAL &r, local string s) {
SScanf(s,"%d/%d",r.num,r.dom);
}
// Signed Rational (e.g. fraction: NUMERATOR/DENOMINATOR)
typedef struct {
int32 num; // Numerator
int32 dom; // Denominator
} SRATIONAL <read=readSRATIONAL,write=writeSRATIONAL>;
string readSRATIONAL(local SRATIONAL &r) {
local string s;
SPrintf(s,"%d/%d",r.num,r.dom);
return s;
}
void writeSRATIONAL(local SRATIONAL &r, local string s) {
SScanf(s,"%d/%d",r.num,r.dom);
}
// ENT: Directory Entry
// An Entry holds one tag and tag data (or a pointer to the data)
// Entries are contained in IFDs (Image File Directories)
typedef struct {
SetBackColor( cLtGreen );
TAG tag;
TAGTYPE typ;
uint32 count;
if (typ==eBYTE) {
if (count<4) {
ubyte data[count];
ubyte padding[4-count];
} else if (count==4) { // NO padding in this case
ubyte data[count];
} else {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
ubyte value[count];
FSeek(curpos);
}
} else if (typ==eASCII) {
if (count<4) {
char data[count];
char padding[4-count];
} else if (count==4) {
char data[count];
} else {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
char data[count];
FSeek(curpos);
}
} else if (typ==eSHORT) {
if (count==1) {
if (tag==Compression) {
COMP value;
} else if (tag==PhotometricInterpretation) {
PHOTO value;
} else if (tag==ResolutionUnit) {
RES value;
} else {
uint16 value;
}
uint16 padding;
} else if (count==2) {
uint16 value[2];
} else {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
if (tag==GeoKeyDirectoryTag) {
GEOKEYDIR value; // GeoTIFF Entry
} else {
uint16 value[count];
}
FSeek(curpos);
}
} else if (typ==eLONG) {
if (count==1) {
uint32 value;
} else {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
uint32 value[count];
FSeek(curpos);
}
} else if (typ==eRATIONAL) {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
if (count==1) {
RATIONAL value;
} else {
RATIONAL value[count];
}
FSeek(curpos);
} else if (typ==eSBYTE) {
if (count<4) {
byte data[count];
ubyte padding[4-count];
} else if (count==4) { // NO padding in this case
byte data[count];
} else {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
byte value[count];
FSeek(curpos);
}
} else if (typ==eUNDEF) {
if (count<4) {
ubyte data[count];
ubyte padding[4-count];
} else if (count==4) { // NO padding in this case
ubyte data[count];
} else {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
ubyte value[count];
FSeek(curpos);
}
} else if (typ==eSSHORT) {
if (count==1) {
int16 value;
int16 padding;
} else if (count==2) {
int16 value[2];
} else {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
int16 value[count];
FSeek(curpos);
}
} else if (typ==eSLONG) {
if (count==1) {
int32 value;
} else {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
int32 value[count];
FSeek(curpos);
}
} else if (typ==eSRATIONAL) {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
if (count==1) {
SRATIONAL value;
} else {
SRATIONAL value[count];
}
FSeek(curpos);
} else if (typ==eFLOAT) {
if (count==1) {
float value;
} else {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
float value[count];
FSeek(curpos);
}
} else if (typ==eDOUBLE) {
SetBackColor( cLtBlue );
uint32 offset <format=hex>;
local quad curpos = FTell();
FSeek(offset);
if (count==1) {
double value;
} else {
double value[count];
}
FSeek(curpos);
} else {
//UNKNOWN data type, so we can't tell if this is a value or
//an offset. Nor do we know the size of the data, so we can't
//know how big it is. (Might be a newer TIFF spec)
SetBackColor( cLtRed );
uint32 valOffset <format=hex>;
}
SetBackColor (cNone); // Revert to no color
} ENT <read=readENT>;
/**
* Reader for ENT Types
* Shows the tag string, number, and type (as a string)
* @param ent Pointer to the structure
*/
string readENT(local ENT &ent) {
local string s;
// NOTE: This only works with 010 v2.1 or greater...
SPrintf(s,"%s (%d): %s",EnumToString(ent.tag), ent.tag, EnumToString(ent.typ));
return s;
}
// IFD: Image File Directory
typedef struct {
uint16 numentries;
ENT dir[numentries] <optimize=false>;
uint32 offset <format=hex>;
nextIFD = (quad)offset; // This is how we find the next one
} IFD <read=readIFD>;
/**
* Reader for IFD Types
* Shows the Number of entries and the type of the first directory tag
* @param ifd Pointer to the structure
*/
string readIFD(local IFD &ifd) {
local string s;
// NOTE: This only works with 010 v2.1 or greater...
SPrintf(s,"%d: %s", ifd.numentries, (ifd.numentries>0) ? EnumToString(ifd.dir[0].tag) : "");
return s;
}
// IFH: Image File Header
typedef struct {
char bom[2];
uint16 magic; // Should always be 42
if (magic!=42) {
Warning("Invalid TIFF File: Bad Magic number");
return -1;
}
uint32 offset <format=hex>; // Offset to first IFD
// Sanity check: There must be an initial IFD
if (offset == 0) {
Warning("Invalid TIFF File: No initial IFD");
return -1;
}
nextIFD = (quad)offset; // This is how we find it later
} IFH;
// ---------------------------------------------------------------------------
// MAIN -- Here's where we really allocate the data
// ---------------------------------------------------------------------------
SetBackColor ( cLtAqua );
IFH ifh; // Allocate the Header (and set nextIFD)
while(nextIFD) { // while there is another IFD, ...
FSeek(nextIFD); // Go to it
SetBackColor( cLtGreen );
IFD ifd; // Allocate it (and set nextIFD)
// Handle SubIFDs
local int i;
for (i = 0; i < ifd.numentries; i++) {
if (ifd.dir[i].tag == SubIFDs) {
if (ifd.dir[i].count == 1) { // Handle 1 SubIFD
SetBackColor( cDkGreen );
FSeek(ifd.dir[i].value);
IFD subifd;
SetBackColor( cNone );
} else { // Handle > 1 SubIFDs
local int offs = ReadInt(ifh.offset + 2 + i * 0xC + 8);
local int i2;
for (i2 = 0; i2 < ifd.dir[i].count; i2++) {
SetBackColor( cDkGreen );
FSeek(ReadInt(offs + i2 * 4));
IFD subifd;
SetBackColor( cNone );
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment