def ExifKeyType(key: str) -> str:
    # From https://sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
    keys = {'InteropIndex': 'string!',
    'InteropVersion': 'undef!:',
    'ProcessingSoftware': 'string',
    'SubfileType': 'int32u!',
    'OldSubfileType': 'int16u!',
    'ImageWidth': 'int32u!',
    'ImageHeight': 'int32u!',
    'BitsPerSample': 'int16u[n]!',
    'Compression': 'int16u!:',
    'PhotometricInterpretation': 'int16u!',
    'Thresholding': 'int16u!',
    'CellWidth': 'int16u!',
    'CellLength': 'int16u!',
    'FillOrder': 'int16u!',
    'DocumentName': 'string',
    'ImageDescription': 'string',
    'Make': 'string',
    'Model': 'string',
    'Orientation': 'int16u',
    'SamplesPerPixel': 'int16u!',
    'RowsPerStrip': 'int32u!',
    'MinSampleValue': 'int16u',
    'MaxSampleValue': 'int16u',
    'XResolution': 'rational64u:',
    'YResolution': 'rational64u:',
    'PlanarConfiguration': 'int16u!',
    'PageName': 'string',
    'XPosition': 'rational64u',
    'YPosition': 'rational64u',
    'FreeOffsets': 'no',
    'FreeByteCounts': 'no',
    'GrayResponseUnit': 'int16u',
    'GrayResponseCurve': 'no',
    'T4Options': 'no',
    'T6Options': 'no',
    'ResolutionUnit': 'int16u:',
    'PageNumber': 'int16u[2]',
    'ColorResponseUnit': 'no',
    'TransferFunction': 'int16u[768]!',
    'Software': 'string',
    'ModifyDate': 'string',
    'Artist': 'string',
    'HostComputer': 'string',
    'Predictor': 'int16u!',
    'WhitePoint': 'rational64u[2]',
    'PrimaryChromaticities': 'rational64u[6]',
    'ColorMap': 'no',
    'HalftoneHints': 'int16u[2]',
    'TileWidth': 'int32u!',
    'TileLength': 'int32u!',
    'TileOffsets': 'no',
    'TileByteCounts': 'no',
    'BadFaxLines': 'no',
    'CleanFaxData': 'no',
    'ConsecutiveBadFaxLines': 'no',
    'SubIFD  A100DataOffset': '- no',
    'InkSet': 'int16u',
    'InkNames': 'no',
    'NumberofInks': 'no',
    'DotRange': 'no',
    'TargetPrinter': 'string',
    'ExtraSamples': 'no',
    'SampleFormat': 'no',
    'SMinSampleValue': 'no',
    'SMaxSampleValue': 'no',
    'TransferRange': 'no',
    'ClipPath': 'no',
    'XClipPathUnits': 'no',
    'YClipPathUnits': 'no',
    'Indexed': 'no',
    'JPEGTables': 'no',
    'OPIProxy': 'no',
    'GlobalParametersIFD': '-',
    'ProfileType': 'no',
    'FaxProfile': 'no',
    'CodingMethods': 'no',
    'VersionYear': 'no',
    'ModeNumber': 'no',
    'Decode': 'no',
    'DefaultImageColor': 'no',
    'T82Options': 'no',
    'JPEGProc': 'no',
    'ThumbnailOffset': 'int32u*',
    'ThumbnailLength  ': 'int32u*',
    'JPEGRestartInterval': 'no',
    'JPEGLosslessPredictors': 'no',
    'JPEGPointTransforms': 'no',
    'JPEGQTables': 'no',
    'JPEGDCTables': 'no',
    'JPEGACTables': 'no',
    'YCbCrCoefficients': 'rational64u[3]!',
    'YCbCrSubSampling': 'int16u[2]!',
    'YCbCrPositioning': 'int16u!:',
    'ReferenceBlackWhite': 'rational64u[6]',
    'StripRowCounts': 'no',
    'ApplicationNotes': 'int8u!',
    'USPTOMiscellaneous': 'no',
    'RelatedImageFileFormat': 'string!',
    'RelatedImageWidth': 'int16u!',
    'RelatedImageHeight': 'int16u!',
    'Rating': 'int16u/',
    'XP_DIP_XML': 'no',
    'StitchInfo': '-',
    'RatingPercent': 'int16u/',
    'SonyRawFileType': 'no',
    'SonyToneCurve': 'no',
    'VignettingCorrection': 'int16s!',
    'VignettingCorrParams': 'int16s[17]!',
    'ChromaticAberrationCorrection': 'int16s!',
    'ChromaticAberrationCorrParams': 'int16s[33]!',
    'DistortionCorrection': 'int16s!',
    'DistortionCorrParams': 'int16s[17]!',
    'SonyCropTopLeft': 'int32u[2]!',
    'SonyCropSize': 'int32u[2]!',
    'ImageID': 'no',
    'WangTag1': 'no',
    'WangAnnotation': 'no',
    'WangTag3': 'no',
    'WangTag4': 'no',
    'ImageReferencePoints': 'no',
    'RegionXformTackPoint': 'no',
    'WarpQuadrilateral': 'no',
    'AffineTransformMat': 'no',
    'Matteing': 'no',
    'DataType': 'no',
    'ImageDepth': 'no',
    'TileDepth': 'no',
    'ImageFullWidth': 'no',
    'ImageFullHeight': 'no',
    'TextureFormat': 'no',
    'WrapModes': 'no',
    'FovCot': 'no',
    'MatrixWorldToScreen': 'no',
    'MatrixWorldToCamera': 'no',
    'Model2': 'no',
    'CFARepeatPatternDim': 'int16u[2]!',
    'CFAPattern2': 'int8u[n]!',
    'BatteryLevel': 'no',
    'KodakIFD': '-',
    'Copyright': 'string',
    'ExposureTime': 'rational64u',
    'FNumber': 'rational64u',
    'MDFileTag': 'no',
    'MDScalePixel': 'no',
    'MDColorTable': 'no',
    'MDLabName': 'no',
    'MDSampleInfo': 'no',
    'MDPrepDate': 'no',
    'MDPrepTime': 'no',
    'MDFileUnits': 'no',
    'PixelScale': 'double[3]',
    'AdventScale': 'no',
    'AdventRevision': 'no',
    'UIC1Tag': 'no',
    'UIC2Tag': 'no',
    'UIC3Tag': 'no',
    'UIC4Tag': 'no',
    'IPTC-NAA': 'int32u!',
    'IntergraphPacketData': 'no',
    'IntergraphFlagRegisters': 'no',
    'IntergraphMatrix': 'double[n]',
    'INGRReserved': 'no',
    'ModelTiePoint': 'double[n]',
    'Site': 'no',
    'ColorSequence': 'no',
    'IT8Header': 'no',
    'RasterPadding': 'no',
    'BitsPerRunLength': 'no',
    'BitsPerExtendedRunLength': 'no',
    'ColorTable': 'no',
    'ImageColorIndicator': 'no',
    'BackgroundColorIndicator': 'no',
    'ImageColorValue': 'no',
    'BackgroundColorValue': 'no',
    'PixelIntensityRange': 'no',
    'TransparencyIndicator': 'no',
    'ColorCharacterization': 'no',
    'HCUsage': 'no',
    'TrapIndicator': 'no',
    'CMYKEquivalent': 'no',
    'SEMInfo': 'string',
    'AFCP_IPTC': '-',
    'PixelMagicJBIGOptions': 'no',
    'JPLCartoIFD': 'no',
    'ModelTransform': 'double[16]',
    'WB_GRGBLevels': 'no',
    'LeafData': '-',
    'PhotoshopSettings': '-',
    'ExifOffset': '-',
    'ICC_Profile': '-',
    'TIFF_FXExtensions': 'no',
    'MultiProfiles': 'no',
    'SharedData': 'no',
    'T88Options': 'no',
    'ImageLayer': 'no',
    'GeoTiffDirectory': 'undef',
    'GeoTiffDoubleParams': 'undef',
    'GeoTiffAsciiParams': 'string',
    'JBIGOptions': 'no',
    'ExposureProgram': 'int16u',
    'SpectralSensitivity': 'string',
    'GPSInfo': '-',
    'ISO': 'int16u[n]',
    'Opto-ElectricConvFactor': 'no',
    'Interlace': 'no',
    'TimeZoneOffset': 'int16s[n]',
    'SelfTimerMode': 'int16u',
    'SensitivityType': 'int16u',
    'StandardOutputSensitivity': 'int32u',
    'RecommendedExposureIndex': 'int32u',
    'ISOSpeed': 'int32u',
    'ISOSpeedLatitudeyyy': 'int32u',
    'ISOSpeedLatitudezzz': 'int32u',
    'FaxRecvParams': 'no',
    'FaxSubAddress': 'no',
    'FaxRecvTime': 'no',
    'FedexEDR': 'no',
    'LeafSubIFD': '-',
    'ExifVersion': 'undef:',
    'DateTimeOriginal': 'string',
    'CreateDate': 'string',
    'GooglePlusUploadCode': 'undef[n]',
    'OffsetTime': 'string',
    'OffsetTimeOriginal': 'string',
    'OffsetTimeDigitized': 'string',
    'ComponentsConfiguration': 'undef[4]!:',
    'CompressedBitsPerPixel': 'rational64u!',
    'ShutterSpeedValue': 'rational64s',
    'ApertureValue': 'rational64u',
    'BrightnessValue': 'rational64s',
    'ExposureCompensation': 'rational64s',
    'MaxApertureValue': 'rational64u',
    'SubjectDistance': 'rational64u',
    'MeteringMode': 'int16u',
    'LightSource': 'int16u',
    'Flash': 'int16u',
    'FocalLength': 'rational64u',
    'FlashEnergy': 'no',
    'SpatialFrequencyResponse': 'no',
    'Noise': 'no',
    'FocalPlaneXResolution': 'no',
    'FocalPlaneYResolution': 'no',
    'FocalPlaneResolutionUnit': 'no',
    'ImageNumber': 'int32u',
    'SecurityClassification': 'string',
    'ImageHistory': 'string',
    'SubjectArea': 'int16u[n]',
    'ExposureIndex': 'no',
    'TIFF-EPStandardID': 'no',
    'SensingMethod': 'no',
    'CIP3DataFile': 'no',
    'CIP3Sheet': 'no',
    'CIP3Side': 'no',
    'StoNits': 'no',
    'MakerNote': 'undef',
    'UserComment': 'undef',
    'SubSecTime': 'string',
    'SubSecTimeOriginal': 'string',
    'SubSecTimeDigitized': 'string',
    'MSDocumentText': 'no',
    'MSPropertySetStorage': 'no',
    'MSDocumentTextPosition': 'no',
    'ImageSourceData': 'undef!',
    'AmbientTemperature': 'rational64s',
    'Humidity': 'rational64u',
    'Pressure': 'rational64u',
    'WaterDepth': 'rational64s',
    'Acceleration': 'rational64u',
    'CameraElevationAngle': 'rational64s',
    'XPTitle': 'int8u',
    'XPComment': 'int8u',
    'XPAuthor': 'int8u',
    'XPKeywords': 'int8u',
    'XPSubject': 'int8u',
    'FlashpixVersion': 'undef:',
    'ColorSpace': 'int16u:',
    'ExifImageWidth': 'int16u:',
    'ExifImageHeight': 'int16u:',
    'RelatedSoundFile': 'string',
    'InteropOffset': '-',
    'SamsungRawPointersOffset': 'no',
    'SamsungRawPointersLength': 'no',
    'SamsungRawByteOrder': 'no',
    'SamsungRawUnknown?': 'no',
    'SubjectLocation': 'int16u[2]',
    'FileSource': 'undef',
    'SceneType': 'undef',
    'CFAPattern': 'undef',
    'CustomRendered': 'int16u',
    'ExposureMode': 'int16u',
    'WhiteBalance': 'int16u',
    'DigitalZoomRatio': 'rational64u',
    'FocalLengthIn35mmFormat': 'int16u',
    'SceneCaptureType': 'int16u',
    'GainControl': 'int16u',
    'Contrast': 'int16u',
    'Saturation': 'int16u',
    'Sharpness': 'int16u',
    'DeviceSettingDescription': 'no',
    'SubjectDistanceRange': 'int16u',
    'ImageUniqueID': 'string',
    'OwnerName': 'string',
    'SerialNumber': 'string',
    'LensInfo': 'rational64u[4]',
    'LensMake': 'string',
    'LensModel': 'string',
    'LensSerialNumber': 'string',
    'GDALMetadata': 'string',
    'GDALNoData': 'string',
    'Gamma': 'rational64u',
    'ExpandSoftware': 'no',
    'ExpandLens': 'no',
    'ExpandFilm': 'no',
    'ExpandFilterLens': 'no',
    'ExpandScanner': 'no',
    'ExpandFlashLamp': 'no',
    'PixelFormat': 'no',
    'Transformation': 'no',
    'Uncompressed': 'no',
    'ImageType': 'no',
    'WidthResolution': 'no',
    'HeightResolution': 'no',
    'ImageOffset': 'no',
    'ImageByteCount': 'no',
    'AlphaOffset': 'no',
    'AlphaByteCount': 'no',
    'ImageDataDiscard': 'no',
    'AlphaDataDiscard': 'no',
    'OceScanjobDesc': 'no',
    'OceApplicationSelector': 'no',
    'OceIDNumber': 'no',
    'OceImageLogic': 'no',
    'Annotations': 'no',
    'PrintIM': 'undef',
    'OriginalFileName': 'no',
    'USPTOOriginalContentType': 'no',
    'CR2CFAPattern': 'no',
    'DNGVersion': 'int8u[4]!',
    'DNGBackwardVersion': 'int8u[4]!',
    'UniqueCameraModel': 'string',
    'LocalizedCameraModel': 'string',
    'CFAPlaneColor': 'no',
    'CFALayout': 'no',
    'LinearizationTable': 'int16u[n]!',
    'BlackLevelRepeatDim': 'int16u[2]!',
    'BlackLevel': 'rational64u[n]!',
    'BlackLevelDeltaH': 'rational64s[n]!',
    'BlackLevelDeltaV': 'rational64s[n]!',
    'WhiteLevel': 'int32u[n]!',
    'DefaultScale': 'rational64u[2]!',
    'DefaultCropOrigin': 'int32u[2]!',
    'DefaultCropSize': 'int32u[2]!',
    'ColorMatrix1': 'rational64s[n]!',
    'ColorMatrix2': 'rational64s[n]!',
    'CameraCalibration1': 'rational64s[n]!',
    'CameraCalibration2': 'rational64s[n]!',
    'ReductionMatrix1': 'rational64s[n]!',
    'ReductionMatrix2': 'rational64s[n]!',
    'AnalogBalance': 'rational64u[n]!',
    'AsShotNeutral': 'rational64u[n]!',
    'AsShotWhiteXY': 'rational64u[2]!',
    'BaselineExposure': 'rational64s!',
    'BaselineNoise': 'rational64u!',
    'BaselineSharpness': 'rational64u!',
    'BayerGreenSplit': 'int32u!',
    'LinearResponseLimit': 'rational64u!',
    'CameraSerialNumber': 'string',
    'DNGLensInfo': 'rational64u[4]',
    'ChromaBlurRadius': 'rational64u!',
    'AntiAliasStrength': 'rational64u!',
    'ShadowScale': 'rational64u!',
    'SR2Private': '- undef!',
    'MakerNoteSafety': 'int16u',
    'RawImageSegmentation': 'no',
    'CalibrationIlluminant1': 'int16u!',
    'CalibrationIlluminant2': 'int16u!',
    'BestQualityScale': 'rational64u!',
    'RawDataUniqueID': 'int8u[16]!',
    'AliasLayerMetadata': 'no',
    'OriginalRawFileName': 'string!',
    'OriginalRawFileData': 'undef!',
    'ActiveArea': 'int32u[4]!',
    'MaskedAreas': 'int32u[n]!',
    'AsShotICCProfile': 'undef!',
    'AsShotPreProfileMatrix': 'rational64s[n]!',
    'CurrentICCProfile': 'undef!',
    'CurrentPreProfileMatrix': 'rational64s[n]!',
    'ColorimetricReference': 'int16u!',
    'SRawType': 'no',
    'PanasonicTitle': 'undef',
    'PanasonicTitle2': 'undef',
    'CameraCalibrationSig': 'string!',
    'ProfileCalibrationSig': 'string!',
    'ProfileIFD': '-',
    'AsShotProfileName': 'string!',
    'NoiseReductionApplied': 'rational64u!',
    'ProfileName': 'string!',
    'ProfileHueSatMapDims': 'int32u[3]!',
    'ProfileHueSatMapData1': 'float[n]!',
    'ProfileHueSatMapData2': 'float[n]!',
    'ProfileToneCurve': 'float[n]!',
    'ProfileEmbedPolicy': 'int32u!',
    'ProfileCopyright': 'string!',
    'ForwardMatrix1': 'rational64s[n]!',
    'ForwardMatrix2': 'rational64s[n]!',
    'PreviewApplicationName': 'string!',
    'PreviewApplicationVersion': 'string!',
    'PreviewSettingsName': 'string!',
    'PreviewSettingsDigest': 'int8u!',
    'PreviewColorSpace': 'int32u!',
    'PreviewDateTime': 'string!',
    'RawImageDigest': 'int8u[16]!',
    'OriginalRawFileDigest': 'int8u[16]!',
    'SubTileBlockSize': 'no',
    'RowInterleaveFactor': 'no',
    'ProfileLookTableDims': 'int32u[3]!',
    'ProfileLookTableData': 'float[n]!',
    'OpcodeList1': 'undef!',
    'OpcodeList2': 'undef!',
    'OpcodeList3': 'undef!',
    'NoiseProfile': 'double[n]!',
    'TimeCodes': 'int8u[n]',
    'FrameRate': 'rational64s',
    'TStop': 'rational64u[n]',
    'ReelName': 'string',
    'OriginalDefaultFinalSize': 'int32u[2]!',
    'OriginalBestQualitySize': 'int32u[2]!',
    'OriginalDefaultCropSize': 'rational64u[2]!',
    'CameraLabel': 'string',
    'ProfileHueSatMapEncoding': 'int32u!',
    'ProfileLookTableEncoding': 'int32u!',
    'BaselineExposureOffset': 'rational64s!',
    'DefaultBlackRender': 'int32u!',
    'NewRawImageDigest': 'int8u[16]!',
    'RawToPreviewGain': 'double!',
    'CacheVersion': 'int32u!',
    'DefaultUserCrop': 'rational64u[4]!',
    'NikonNEFInfo': '-',
    'Padding': 'undef!',
    'OffsetSchema': 'int32s!',
    'Lens': 'string/',
    'KDC_IFD': '-',
    'RawFile': 'string/',
    'Converter': 'string/',
    'Exposure': 'string/',
    'Shadows': 'string/',
    'Brightness': 'string/',
    'Smoothness': 'string/',
    'MoireFilter': 'string/'}

    return keys.get(key)


def utf8(key: str) -> str:
    key = {'Exif.Image.XPTitle': 'int8u',
        'Exif.Image.XPComment': 'int8u',
        'Exif.Image.XPAuthor': 'int8u',
        'Exif.Image.XPKeywords': 'int8u',
        'Exif.Image.XPSubject': 'int8u'}
    return key.get(key)         # returns None if no match

img_text_tags = {
    'DateTimeOriginal': 'string',
    'CreateDate': 'string',
    'Exif.Image.DocumentName': 'string',
    'Exif.Image.ImageDescription': 'string',
    'Exif.Image.XPTitle': 'utf-8',
    'Exif.Image.XPComment': 'utf-8',
    'Exif.Image.XPAuthor': 'utf-8',
    'Exif.Image.XPKeywords': 'utf-8',
    'Exif.Image.XPSubject': 'utf-8',
    'Iptc.Application2.Caption': 'string',
    'Iptc.Description': 'string'}

# for IPTC field reference see:
# https://www.iptc.org/std/photometadata/documentation/userguide/index.htm#!Documents/fieldreferencetable.htm