4921 lines
188 KiB
Plaintext
4921 lines
188 KiB
Plaintext
(* ImageEn Build 7.0.0.06.2637 @ 7-4-17 14:58:42.679 *)
|
||
(*
|
||
Copyright (c) 1998-2017 by Carlotta Calandra. All rights reserved.
|
||
Copyright (c) 2011-2017 by Xequte Software.
|
||
|
||
This software comes without express or implied warranty.
|
||
In no case shall the author be liable for any damage or unwanted behavior of any
|
||
computer hardware and/or software.
|
||
|
||
Author grants you the right to include the component
|
||
in your application, whether COMMERCIAL, SHAREWARE, or FREEWARE.
|
||
|
||
ImageEn, IEvolution and ImageEn ActiveX may not be included in any
|
||
commercial, shareware or freeware libraries or components.
|
||
|
||
www.ImageEn.com
|
||
*)
|
||
|
||
|
||
(*
|
||
File: iexMetaHelpers.pas
|
||
Description: Helper functions for working with EXIF, IPTC, Dicom meta data
|
||
File version: 1034
|
||
Notes:
|
||
- Requires: Delphi 2005 or newer
|
||
- TListView enhancements by William Miller, Adirondack Software & Graphics
|
||
*)
|
||
|
||
|
||
// STRING GRID SUPPORT
|
||
// Define to include methods for loading and saving content to/from TStringGrids
|
||
{$DEFINE USE_STRINGGRIDS}
|
||
|
||
// LIST VIEW SUPPORT
|
||
// Define to include methods for loading and saving content to/from TListViews
|
||
{$DEFINE USE_LISTVIEW}
|
||
|
||
|
||
unit iexMetaHelpers;
|
||
|
||
{$I ie.inc}
|
||
|
||
interface
|
||
|
||
|
||
uses
|
||
{$IFDEF USE_STRINGGRIDS}
|
||
grids,
|
||
{$ENDIF}
|
||
{$IFDEF USE_LISTVIEW}
|
||
ComCtrls,
|
||
{$ENDIF}
|
||
ImageEnIO, dialogs, Sysutils, math, Graphics, Classes, iexBitmaps;
|
||
|
||
type
|
||
|
||
{!!
|
||
<FS>TIEDicomInclude
|
||
|
||
<FM>Declaration<FC>
|
||
TIEDicomInclude = set of (diDeprecated, diProprietary, diChildTags, diUnknown);
|
||
|
||
<FM>Description<FN>
|
||
<TABLE>
|
||
<R> <H>Value</H> <H>Description</H> </R>
|
||
<R> <C><FC>diDeprecated<FN></C> <C>Include tags that have been retired in the NEMA standard</C> </R>
|
||
<R> <C><FC>diProprietary<FN></C> <C>Include tags that are not in the NEMA standard (vendor specific tags)</C> </R>
|
||
<R> <C><FC>diChildTags<FN></C> <C>Include subordinate tags (children of parent tags)</C> </R>
|
||
<R> <C><FC>diUnknown<FN></C> <C>Include tags even if they do not have a description</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
TIEDicomInclude = set of (diDeprecated, diProprietary, diChildTags, diUnknown);
|
||
|
||
{$IFDEF Delphi2005orNewer}
|
||
{!!
|
||
<FS>TIOParamsHelper
|
||
|
||
<FM>Declaration<FC>
|
||
TIOParamsHelper = class helper for TIOParams
|
||
|
||
<FM>Description<FN>
|
||
<A iexMetaHelpers>
|
||
!!}
|
||
// TIOParamsHelper Helper Functions
|
||
TIOParamsHelper = class helper for TIOParams
|
||
private
|
||
function GetEXIF_ApertureValue_Str : string;
|
||
function GetEXIF_Camera_Str : AnsiString;
|
||
function GetEXIF_ExposureTime_Str : string;
|
||
function GetEXIF_FNumber_Str : string;
|
||
function GetEXIF_MaxApertureValue_Str : string;
|
||
function GetEXIF_ShutterSpeedValue_Str : string;
|
||
function GetEXIF_XResolution_Str : AnsiString;
|
||
function GetEXIF_YResolution_Str : AnsiString;
|
||
function GetEXIF_AsStr(Index: Integer): string;
|
||
function GetEXIF_FieldDescription(Index: Integer): string;
|
||
function GetEXIF_CanWriteEXIFData : Boolean;
|
||
function GetEXIF_SubjectArea_Str : string;
|
||
function GetEXIF_SubjectLocation_Str : string;
|
||
|
||
function GetXMP_AsStr(const Field: String): string;
|
||
function GetXMP_AsInt(const Field: String): Integer;
|
||
function GetXMP_AsDateTime(const Field: String): TDateTime;
|
||
|
||
procedure SetEXIF_ApertureValue_Str(const value : string);
|
||
procedure SetEXIF_Camera_Str(const value : AnsiString);
|
||
procedure SetEXIF_ExposureTime_Str(value : string);
|
||
procedure SetEXIF_FNumber_Str(value : string);
|
||
procedure SetEXIF_MaxApertureValue_Str(const value : string);
|
||
procedure SetEXIF_ShutterSpeedValue_Str(const value : string);
|
||
procedure SetEXIF_XResolution_Str(value : AnsiString);
|
||
procedure SetEXIF_YResolution_Str(value : AnsiString);
|
||
procedure SetEXIF_SubjectLocation_Str(value : string);
|
||
procedure SetEXIF_AsStr(Index: Integer; value : string);
|
||
|
||
public
|
||
property EXIF_AsStr [index : Integer]: string read GetEXIF_AsStr write SetEXIF_AsStr;
|
||
property EXIF_FieldDescription [index : Integer]: string read GetEXIF_FieldDescription;
|
||
property EXIF_CanWriteEXIFData : Boolean read GetEXIF_CanWriteEXIFData;
|
||
|
||
property EXIF_ApertureValue_Str : string read GetEXIF_ApertureValue_Str write SetEXIF_ApertureValue_Str;
|
||
property EXIF_Camera_Str : AnsiString read GetEXIF_Camera_Str write SetEXIF_Camera_Str;
|
||
property EXIF_ExposureTime_Str : string read GetEXIF_ExposureTime_Str write SetEXIF_ExposureTime_Str;
|
||
property EXIF_FNumber_Str : string read GetEXIF_FNumber_Str write SetEXIF_FNumber_Str;
|
||
property EXIF_MaxApertureValue_Str : string read GetEXIF_MaxApertureValue_Str write SetEXIF_MaxApertureValue_Str;
|
||
property EXIF_ShutterSpeedValue_Str : string read GetEXIF_ShutterSpeedValue_Str write SetEXIF_ShutterSpeedValue_Str;
|
||
property EXIF_XResolution_Str : AnsiString read GetEXIF_XResolution_Str write SetEXIF_XResolution_Str;
|
||
property EXIF_YResolution_Str : AnsiString read GetEXIF_YResolution_Str write SetEXIF_YResolution_Str;
|
||
property EXIF_SubjectArea_Str : string read GetEXIF_SubjectArea_Str;
|
||
property EXIF_SubjectLocation_Str : string read GetEXIF_SubjectLocation_Str write SetEXIF_SubjectLocation_Str;
|
||
|
||
property XMP_AsStr[const Field : string] : string read GetXMP_AsStr;
|
||
property XMP_AsInt[const Field : string] : Integer read GetXMP_AsInt;
|
||
property XMP_AsDateTime[const Field : string] : TDateTime read GetXMP_AsDateTime;
|
||
|
||
{$ifdef IEINCLUDEDICOM}
|
||
function DICOM_FindTag(Group: Word; Element: Word): PIEDicomTag;
|
||
{$endif}
|
||
|
||
function IPTC_HasIPTCData : Boolean;
|
||
function DICOM_HasDicomTags : Boolean;
|
||
function XMP_HasXMPData : Boolean;
|
||
|
||
function EXIF_WriteToStrings(Dest : TStrings) : Boolean;
|
||
function IPTC_WriteToStrings(Dest : TStrings) : Boolean;
|
||
{$ifdef IEINCLUDEDICOM}
|
||
function DICOM_WriteToStrings(Dest : TStrings; TagInclude: TIEDicomInclude) : Boolean;
|
||
{$endif}
|
||
function XMP_WriteToStrings(Dest : TStrings) : Boolean;
|
||
end;
|
||
{$ENDIF}
|
||
|
||
|
||
{$IFDEF USE_STRINGGRIDS}
|
||
{$IFDEF Delphi2005orNewer}
|
||
{!!
|
||
<FS>TStringGridHelper
|
||
|
||
<FM>Declaration<FC>
|
||
TStringGridHelper = class helper for TStringGrid
|
||
|
||
<FM>Description<FN>
|
||
<A iexMetaHelpers>
|
||
!!}
|
||
// TStringGridHelper Helper Functions
|
||
TStringGridHelper = class helper for TStringGrid
|
||
private
|
||
public
|
||
// EXIF
|
||
procedure NewGridForExif(bReadOnly : Boolean = False);
|
||
function ReadGridFromExif(IOParams : TIOParams; bReadOnly : Boolean = False) : Boolean; overload;
|
||
function ReadGridFromExif(const sFilename : string; bReadOnly : Boolean = False) : Boolean; overload;
|
||
function WriteGridToExif(IOParams : TIOParams) : Boolean; overload;
|
||
function WriteGridToExif(const sFilename : string) : Boolean; overload;
|
||
|
||
// IPTC
|
||
procedure NewGridForIPTC(bReadOnly : Boolean = False);
|
||
function ReadGridFromIPTC(IOParams : TIOParams; bReadOnly : Boolean = False) : Boolean; overload;
|
||
function ReadGridFromIPTC(const sFilename : string; bReadOnly : Boolean = False) : Boolean; overload;
|
||
function WriteGridToIPTC(IOParams : TIOParams) : Boolean; overload;
|
||
function WriteGridToIPTC(const sFilename : string) : Boolean; overload;
|
||
|
||
// DICOM
|
||
{$ifdef IEINCLUDEDICOM}
|
||
function ReadGridFromDicom(IOParams : TIOParams; TagInclude: TIEDicomInclude) : Boolean; overload;
|
||
function ReadGridFromDicom(const sFilename : string; TagInclude: TIEDicomInclude) : Boolean; overload;
|
||
{$endif}
|
||
|
||
// XMP
|
||
function ReadGridFromXMP(IOParams : TIOParams) : Boolean; overload;
|
||
function ReadGridFromXMP(const sFilename : string) : Boolean; overload;
|
||
|
||
// GENERAL
|
||
procedure InitializeGrid(bFixLayout : Boolean = True);
|
||
procedure ClearGridFields;
|
||
end;
|
||
{$ENDIF}
|
||
{$ENDIF}
|
||
|
||
|
||
{$IFDEF USE_LISTVIEW}
|
||
{$IFDEF Delphi2005orNewer}
|
||
{!!
|
||
<FS>TListViewHelper
|
||
|
||
<FM>Declaration<FC>
|
||
TListViewHelper = class helper for TListView
|
||
|
||
<FM>Description<FN>
|
||
<A iexMetaHelpers>
|
||
!!}
|
||
// TListViewHelper Helper Functions
|
||
TListViewHelper = class helper for TListView
|
||
private
|
||
|
||
public
|
||
// EXIF
|
||
procedure NewListForExif();
|
||
function ReadListFromExif(IOParams : TIOParams) : Boolean; overload;
|
||
function ReadListFromExif(const sFilename : string) : Boolean; overload;
|
||
function WriteListToExif(IOParams : TIOParams) : Boolean; overload;
|
||
function WriteListToExif(const sFilename : string) : Boolean; overload;
|
||
|
||
// IPTC
|
||
procedure NewListForIPTC();
|
||
function ReadListFromIPTC(IOParams : TIOParams) : Boolean; overload;
|
||
function ReadListFromIPTC(const sFilename : string) : Boolean; overload;
|
||
function WriteListToIPTC(IOParams : TIOParams) : Boolean; overload;
|
||
function WriteListToIPTC(const sFilename : string) : Boolean; overload;
|
||
|
||
// DICOM
|
||
{$ifdef IEINCLUDEDICOM}
|
||
function ReadListFromDicom(IOParams : TIOParams; TagInclude: TIEDicomInclude) : Boolean; overload;
|
||
function ReadListFromDicom(const sFilename : string; TagInclude: TIEDicomInclude) : Boolean; overload;
|
||
{$endif}
|
||
|
||
// XMP
|
||
function ReadListFromXMP(IOParams : TIOParams) : Boolean; overload;
|
||
function ReadListFromXMP(const sFilename : string) : Boolean; overload;
|
||
|
||
// GENERAL
|
||
procedure InitializeList(bFixLayout : Boolean = True);
|
||
procedure ClearListFields;
|
||
end;
|
||
{$ENDIF}
|
||
{$ENDIF}
|
||
|
||
// GENERAL EXIF METHODS
|
||
function ExifCompatibleFile(const sFilename: string): boolean;
|
||
{$IFDEF Delphi2005orNewer}
|
||
function ReadExifCameraFieldsFromFile(const sFilename : string;
|
||
out sCameraModel : string;
|
||
out sExposureTime : string;
|
||
out sFlashMode : string
|
||
) : boolean;
|
||
{$ENDIF}
|
||
function ReadExifGPSFieldsFromFile(const sFilename : string;
|
||
out GPSLatitude: Double;
|
||
out GPSLongitude: Double
|
||
) : boolean; overload;
|
||
function ReadExifGPSFieldsFromFile(const sFilename : string;
|
||
out sGPSLatitude: string;
|
||
out sGPSLongitude: string
|
||
) : boolean; overload;
|
||
|
||
// EXIF TAG METHODS
|
||
procedure GetExifTagList(ssDest: TStrings);
|
||
function ContainsExifTag(const Text: string): Boolean;
|
||
{$IFDEF Delphi2005orNewer}
|
||
function ReplaceExifTags(const Text: string; EXIFSource : TIOParams): string; overload;
|
||
function ReplaceExifTags(const Text: string; const sEXIFSourceFilename : string): string; overload;
|
||
{$ENDIF}
|
||
|
||
// GENERAL IPTC METHODS
|
||
function IPTCCompatibleFile(const sFilename: string): boolean;
|
||
function ReadIPTCDescriptionAndKeywordsFromFile(const sFilename: string;
|
||
out sDescription: string;
|
||
ssKeywords: TStrings = nil) : Boolean;
|
||
procedure WriteIPTCDescriptionAndKeywordsToFile(const sFilename: string;
|
||
sDescription: string;
|
||
ssKeywords: TStrings = nil);
|
||
|
||
// OTHER METHODS
|
||
function DicomCompatibleFile(const sFilename: string): boolean;
|
||
function XMPCompatibleFile(const sFilename: string): boolean;
|
||
|
||
// EXIF handling functions
|
||
function DoubleToFraction(dValue: double): string;
|
||
function FractionToDouble(dValue: string): double;
|
||
function ApexToStr(dBase: double;
|
||
dValue: double;
|
||
const sPrepend: string): string;
|
||
function StrToApex(dBase: double;
|
||
Value: string;
|
||
sPrepended: string
|
||
): double;
|
||
|
||
{!!
|
||
<FS>EXIF Consts for EXIF_AsStr<FN>
|
||
|
||
<FM>Declaration<FC>
|
||
}
|
||
const
|
||
_EXIF_UserComment = 0;
|
||
_EXIF_ImageDescription = 1;
|
||
_EXIF_CameraMake = 2;
|
||
_EXIF_CameraModel = 3;
|
||
_EXIF_XResolution = 4;
|
||
_EXIF_YResolution = 5;
|
||
_EXIF_DateTime = 6;
|
||
_EXIF_DateTimeOriginal = 7;
|
||
_EXIF_DateTimeDigitized = 8;
|
||
_EXIF_Copyright = 9;
|
||
_EXIF_Orientation = 10;
|
||
_EXIF_ExposureTime = 11;
|
||
_EXIF_FNumber = 12;
|
||
_EXIF_ExposureProgram = 13;
|
||
_EXIF_ISOSpeedRatings = 14;
|
||
_EXIF_ShutterSpeedValue = 15;
|
||
_EXIF_ApertureValue = 16;
|
||
_EXIF_BrightnessValue = 17;
|
||
_EXIF_ExposureBiasValue = 18;
|
||
_EXIF_MaxApertureValue = 19;
|
||
_EXIF_SubjectDistance = 20;
|
||
_EXIF_MeteringMode = 21;
|
||
_EXIF_LightSource = 22;
|
||
_EXIF_Flash = 23;
|
||
_EXIF_FocalLength = 24;
|
||
_EXIF_FlashPixVersion = 25;
|
||
_EXIF_ColorSpace = 26;
|
||
_EXIF_ExifImageWidth = 27;
|
||
_EXIF_ExifImageHeight = 28;
|
||
_EXIF_RelatedSoundFile = 29;
|
||
_EXIF_FocalPlaneXResolution = 30;
|
||
_EXIF_FocalPlaneYResolution = 31;
|
||
_EXIF_ExposureIndex = 32;
|
||
_EXIF_SensingMethod = 33;
|
||
_EXIF_FileSource = 34;
|
||
_EXIF_SceneType = 35;
|
||
_EXIF_YCbCrPositioning = 36;
|
||
_EXIF_ExposureMode = 37;
|
||
_EXIF_WhiteBalance = 38;
|
||
_EXIF_DigitalZoomRatio = 39;
|
||
_EXIF_FocalLengthIn35mmFilm = 40;
|
||
_EXIF_SceneCaptureType = 41;
|
||
_EXIF_GainControl = 42;
|
||
_EXIF_Contrast = 43;
|
||
_EXIF_Saturation = 44;
|
||
_EXIF_Sharpness = 45;
|
||
_EXIF_SubjectDistanceRange = 46;
|
||
_EXIF_GPSLatitude = 47;
|
||
_EXIF_GPSLongitude = 48;
|
||
_EXIF_GPSAltitude = 49;
|
||
_EXIF_GPSImageDirection = 50;
|
||
_EXIF_GPSTrack = 51;
|
||
_EXIF_GPSSpeed = 52;
|
||
_EXIF_GPSDateAndTime = 53;
|
||
_EXIF_GPSSatellites = 54;
|
||
_EXIF_GPSVersionID = 55;
|
||
_EXIF_Artist = 56;
|
||
_EXIF_XPTitle = 57;
|
||
_EXIF_XPComment = 58;
|
||
_EXIF_XPAuthor = 59;
|
||
_EXIF_XPKeywords = 60;
|
||
_EXIF_XPSubject = 61;
|
||
_EXIF_XPRating = 62;
|
||
_EXIF_InteropVersion = 63;
|
||
_EXIF_CameraOwnerName = 64;
|
||
_EXIF_BodySerialNumber = 65;
|
||
_EXIF_LensMake = 66;
|
||
_EXIF_LensModel = 67;
|
||
_EXIF_LensSerialNumber = 68;
|
||
_EXIF_Gamma = 69;
|
||
_EXIF_SubjectArea = 70;
|
||
_EXIF_SubjectLocation = 71;
|
||
|
||
_EXIF_Tag_Count = 72;
|
||
|
||
{!!}
|
||
|
||
{ SKIPPED :
|
||
|
||
Skipped the following fields :
|
||
|
||
EXIF_Bitmap
|
||
EXIF_ResolutionUnit
|
||
EXIF_SubsecTime
|
||
EXIF_SubsecTimeOriginal
|
||
EXIF_SubsecTimeDigitized
|
||
EXIF_WhitePoint
|
||
EXIF_PrimaryChromaticities
|
||
EXIF_YCbCrCoefficients
|
||
EXIF_ReferenceBlackWhite
|
||
EXIF_CompressedBitsPerPixel
|
||
EXIF_FocalPlaneResolutionUnit
|
||
EXIF_ExifVersion
|
||
EXIF_Software
|
||
EXIF_MakerNote
|
||
EXIF_ImageUniqueID
|
||
EXIF_GPSStatus
|
||
EXIF_GPSMapDatum
|
||
EXIF_GPSMeasureMode
|
||
EXIF_GPSDOP
|
||
EXIF_GPSDestLatitudeRef
|
||
EXIF_GPSDestLatitudeDegrees
|
||
EXIF_GPSDestLatitudeMinutes
|
||
EXIF_GPSDestLatitudeSeconds
|
||
EXIF_GPSDestLongitudeRef
|
||
EXIF_GPSDestLongitudeDegrees
|
||
EXIF_GPSDestLongitudeMinutes
|
||
EXIF_GPSDestLongitudeSeconds
|
||
EXIF_GPSDestBearingRef
|
||
EXIF_GPSDestBearing
|
||
EXIF_GPSDestDistanceRef
|
||
EXIF_GPSDestDistance
|
||
EXIF_InteropIndex
|
||
}
|
||
Example_File_Only = 'Example File';
|
||
SKIP_DESCRIPTION = 'SKIP_DESCRIPTION';
|
||
|
||
Maintain_File_Dates_On_Meta_Write : Boolean = False; // Set to true if updating the EXIF data should not modify the file date
|
||
|
||
// Deprecated: Instead of Digital_Raw_Camera_Formats, use Camera_Raw_File_Extensions
|
||
EXIF_COMPATIBLE_EXTENSIONS = '*.TIF;*.TIFF;*.JPE;*.JPG;*.JPEG;' + Camera_Raw_File_Extensions;
|
||
XMP_COMPATIBLE_EXTENSIONS = '*.TIF;*.TIFF;*.JPE;*.JPG;*.JPEG;*.PSD;';
|
||
|
||
|
||
{!!
|
||
<FS>Consts for Common XMP Fields<FN>
|
||
|
||
<FM>Declaration<FC>
|
||
|
||
<TABLE>
|
||
<R> <H>Const</H> <H>XMP Property</H> <H>Description</H> </R>
|
||
<R> <C><FC>XMP_Aux_ApproximateFocusDistance<FN></C> <C>aux:ApproximateFocusDistance</C> <C>Focus Distance</C> </R>
|
||
<R> <C><FC>XMP_Aux_Firmware<FN></C> <C>aux:Firmware</C> <C>Firmware</C> </R>
|
||
<R> <C><FC>XMP_Aux_FlashCompensation<FN></C> <C>aux:FlashCompensation</C> <C>Flash Compensation</C> </R>
|
||
<R> <C><FC>XMP_Aux_ImageNumber<FN></C> <C>aux:ImageNumber</C> <C>Image Number</C> </R>
|
||
<R> <C><FC>XMP_Aux_Lens<FN></C> <C>aux:Lens</C> <C>Lens</C> </R>
|
||
<R> <C><FC>XMP_Aux_LensID<FN></C> <C>aux:LensID</C> <C>Lens ID</C> </R>
|
||
<R> <C><FC>XMP_Aux_LensInfo<FN></C> <C>aux:LensInfo</C> <C>Lens Info</C> </R>
|
||
<R> <C><FC>XMP_Aux_LensSerialNumber<FN></C> <C>aux:LensSerialNumber</C> <C>Lens Serial Number</C> </R>
|
||
<R> <C><FC>XMP_Aux_OwnerName<FN></C> <C>aux:OwnerName</C> <C>Owner Name</C> </R>
|
||
<R> <C><FC>XMP_Aux_SerialNumber<FN></C> <C>aux:SerialNumber</C> <C>Serial Number</C> </R>
|
||
<R> <C><FC>XMP_CC_AttributionName<FN></C> <C>cc:AttributionName</C> <C>Attribution Name</C> </R>
|
||
<R> <C><FC>XMP_CC_AttributionURL<FN></C> <C>cc:AttributionURL</C> <C>Attribution URL</C> </R>
|
||
<R> <C><FC>XMP_CC_DeprecatedOn<FN></C> <C>cc:DeprecatedOn</C> <C>Deprecated On</C> </R>
|
||
<R> <C><FC>XMP_CC_Jurisdiction<FN></C> <C>cc:Jurisdiction</C> <C>Jurisdiction</C> </R>
|
||
<R> <C><FC>XMP_CC_LegalCode<FN></C> <C>cc:LegalCode</C> <C>Legal Code</C> </R>
|
||
<R> <C><FC>XMP_CC_License<FN></C> <C>cc:License</C> <C>License</C> </R>
|
||
<R> <C><FC>XMP_CC_MorePermissions<FN></C> <C>cc:MorePermissions</C> <C>More Permissions</C> </R>
|
||
<R> <C><FC>XMP_CC_Permits<FN></C> <C>cc:Permits</C> <C>Permits</C> </R>
|
||
<R> <C><FC>XMP_CC_Prohibits<FN></C> <C>cc:Prohibits</C> <C>Prohibits</C> </R>
|
||
<R> <C><FC>XMP_CC_Requires<FN></C> <C>cc:Requires</C> <C>Requires</C> </R>
|
||
<R> <C><FC>XMP_CC_UseGuidelines<FN></C> <C>cc:UseGuidelines</C> <C>Use Guidelines</C> </R>
|
||
<R> <C><FC>XMP_DC_Contributor<FN></C> <C>dc:Contributor</C> <C>Contributor</C> </R>
|
||
<R> <C><FC>XMP_DC_Coverage<FN></C> <C>dc:Coverage</C> <C>Coverage</C> </R>
|
||
<R> <C><FC>XMP_DC_Creator<FN></C> <C>dc:Creator</C> <C>Creator</C> </R>
|
||
<R> <C><FC>XMP_DC_Date<FN></C> <C>dc:Date</C> <C>Date</C> </R>
|
||
<R> <C><FC>XMP_DC_Description<FN></C> <C>dc:Description</C> <C>Description</C> </R>
|
||
<R> <C><FC>XMP_DC_Format<FN></C> <C>dc:Format</C> <C>Format</C> </R>
|
||
<R> <C><FC>XMP_DC_Identifier<FN></C> <C>dc:Identifier</C> <C>Identifier</C> </R>
|
||
<R> <C><FC>XMP_DC_Language<FN></C> <C>dc:Language</C> <C>Language</C> </R>
|
||
<R> <C><FC>XMP_DC_Publisher<FN></C> <C>dc:Publisher</C> <C>Publisher</C> </R>
|
||
<R> <C><FC>XMP_DC_Relation<FN></C> <C>dc:Relation</C> <C>Relation</C> </R>
|
||
<R> <C><FC>XMP_DC_Rights<FN></C> <C>dc:Rights</C> <C>Rights</C> </R>
|
||
<R> <C><FC>XMP_DC_Source<FN></C> <C>dc:Source</C> <C>Source</C> </R>
|
||
<R> <C><FC>XMP_DC_Subject<FN></C> <C>dc:Subject</C> <C>Subject</C> </R>
|
||
<R> <C><FC>XMP_DC_Title<FN></C> <C>dc:Title</C> <C>Title</C> </R>
|
||
<R> <C><FC>XMP_DC_Type<FN></C> <C>dc:Type</C> <C>Type</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_AuthorsPosition<FN></C> <C>photoshop:AuthorsPosition</C> <C>Authors Position</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_CaptionWriter<FN></C> <C>photoshop:CaptionWriter</C> <C>Caption Writer</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_Category<FN></C> <C>photoshop:Category</C> <C>Category</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_City<FN></C> <C>photoshop:City</C> <C>City</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_ColorMode<FN></C> <C>photoshop:ColorMode</C> <C>Color Mode</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_Country<FN></C> <C>photoshop:Country</C> <C>Country</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_Credit<FN></C> <C>photoshop:Credit</C> <C>Credit</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_DateCreated<FN></C> <C>photoshop:DateCreated</C> <C>Date Created</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_DocumentAncestorID<FN></C> <C>photoshop:DocumentAncestorID</C> <C>Document Ancestor ID</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_Headline<FN></C> <C>photoshop:Headline</C> <C>Headline</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_History<FN></C> <C>photoshop:History</C> <C>History</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_ICCProfileName<FN></C> <C>photoshop:ICCProfileName</C> <C>ICC Profile Name</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_Instructions<FN></C> <C>photoshop:Instructions</C> <C>Instructions</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_Source<FN></C> <C>photoshop:Source</C> <C>Source</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_State<FN></C> <C>photoshop:State</C> <C>State</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_SupplementalCategories<FN></C> <C>photoshop:SupplementalCategories</C> <C>Supplemental Categories</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_TextLayerName<FN></C> <C>photoshop:TextLayerName</C> <C>Text Layer Name</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_TextLayerText<FN></C> <C>photoshop:TextLayerText</C> <C>Text Layer Text</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_TransmissionReference<FN></C> <C>photoshop:TransmissionReference</C> <C>Transmission Reference</C> </R>
|
||
<R> <C><FC>XMP_Photoshop_Urgency<FN></C> <C>photoshop:Urgency</C> <C>Urgency</C> </R>
|
||
<R> <C><FC>XMP_Advisory<FN></C> <C>xmp:Advisory</C> <C>Advisory</C> </R>
|
||
<R> <C><FC>XMP_Author<FN></C> <C>xmp:Author</C> <C>Author</C> </R>
|
||
<R> <C><FC>XMP_BaseURL<FN></C> <C>xmp:BaseURL</C> <C>Base URL</C> </R>
|
||
<R> <C><FC>XMP_CreateDate<FN></C> <C>xmp:CreateDate</C> <C>Create Date</C> </R>
|
||
<R> <C><FC>XMP_CreatorTool<FN></C> <C>xmp:CreatorTool</C> <C>Creator Tool</C> </R>
|
||
<R> <C><FC>XMP_Description<FN></C> <C>xmp:Description</C> <C>Description</C> </R>
|
||
<R> <C><FC>XMP_Format<FN></C> <C>xmp:Format</C> <C>Format</C> </R>
|
||
<R> <C><FC>XMP_Identifier<FN></C> <C>xmp:Identifier</C> <C>Identifier</C> </R>
|
||
<R> <C><FC>XMP_Keywords<FN></C> <C>xmp:Keywords</C> <C>Keywords</C> </R>
|
||
<R> <C><FC>XMP_Label<FN></C> <C>xmp:Label</C> <C>Label</C> </R>
|
||
<R> <C><FC>XMP_MetadataDate<FN></C> <C>xmp:MetadataDate</C> <C>Metadata Date</C> </R>
|
||
<R> <C><FC>XMP_ModifyDate<FN></C> <C>xmp:ModifyDate</C> <C>Modify Date</C> </R>
|
||
<R> <C><FC>XMP_Nickname<FN></C> <C>xmp:Nickname</C> <C>Nickname</C> </R>
|
||
<R> <C><FC>XMP_Rating<FN></C> <C>xmp:Rating</C> <C>Rating</C> </R>
|
||
<R> <C><FC>XMP_Title<FN></C> <C>xmp:Title</C> <C>Title</C> </R>
|
||
</TABLE>
|
||
!!}
|
||
XMP_Aux_ApproximateFocusDistance = 'aux:ApproximateFocusDistance';
|
||
XMP_Aux_Firmware = 'aux:Firmware';
|
||
XMP_Aux_FlashCompensation = 'aux:FlashCompensation';
|
||
XMP_Aux_ImageNumber = 'aux:ImageNumber';
|
||
XMP_Aux_Lens = 'aux:Lens';
|
||
XMP_Aux_LensID = 'aux:LensID';
|
||
XMP_Aux_LensInfo = 'aux:LensInfo';
|
||
XMP_Aux_LensSerialNumber = 'aux:LensSerialNumber';
|
||
XMP_Aux_OwnerName = 'aux:OwnerName';
|
||
XMP_Aux_SerialNumber = 'aux:SerialNumber';
|
||
XMP_CC_AttributionName = 'cc:AttributionName';
|
||
XMP_CC_AttributionURL = 'cc:AttributionURL';
|
||
XMP_CC_DeprecatedOn = 'cc:DeprecatedOn';
|
||
XMP_CC_Jurisdiction = 'cc:Jurisdiction';
|
||
XMP_CC_LegalCode = 'cc:LegalCode';
|
||
XMP_CC_License = 'cc:License';
|
||
XMP_CC_MorePermissions = 'cc:MorePermissions';
|
||
XMP_CC_Permits = 'cc:Permits';
|
||
XMP_CC_Prohibits = 'cc:Prohibits';
|
||
XMP_CC_Requires = 'cc:Requires';
|
||
XMP_CC_UseGuidelines = 'cc:UseGuidelines';
|
||
XMP_DC_Contributor = 'dc:Contributor';
|
||
XMP_DC_Coverage = 'dc:Coverage';
|
||
XMP_DC_Creator = 'dc:Creator';
|
||
XMP_DC_Date = 'dc:Date';
|
||
XMP_DC_Description = 'dc:Description';
|
||
XMP_DC_Format = 'dc:Format';
|
||
XMP_DC_Identifier = 'dc:Identifier';
|
||
XMP_DC_Language = 'dc:Language';
|
||
XMP_DC_Publisher = 'dc:Publisher';
|
||
XMP_DC_Relation = 'dc:Relation';
|
||
XMP_DC_Rights = 'dc:Rights';
|
||
XMP_DC_Source = 'dc:Source';
|
||
XMP_DC_Subject = 'dc:Subject';
|
||
XMP_DC_Title = 'dc:Title';
|
||
XMP_DC_Type = 'dc:Type';
|
||
XMP_Photoshop_AuthorsPosition = 'photoshop:AuthorsPosition';
|
||
XMP_Photoshop_CaptionWriter = 'photoshop:CaptionWriter';
|
||
XMP_Photoshop_Category = 'photoshop:Category';
|
||
XMP_Photoshop_City = 'photoshop:City';
|
||
XMP_Photoshop_ColorMode = 'photoshop:ColorMode';
|
||
XMP_Photoshop_Country = 'photoshop:Country';
|
||
XMP_Photoshop_Credit = 'photoshop:Credit';
|
||
XMP_Photoshop_DateCreated = 'photoshop:DateCreated';
|
||
XMP_Photoshop_DocumentAncestorID = 'photoshop:DocumentAncestorID';
|
||
XMP_Photoshop_Headline = 'photoshop:Headline';
|
||
XMP_Photoshop_History = 'photoshop:History';
|
||
XMP_Photoshop_ICCProfileName = 'photoshop:ICCProfileName';
|
||
XMP_Photoshop_Instructions = 'photoshop:Instructions';
|
||
XMP_Photoshop_Source = 'photoshop:Source';
|
||
XMP_Photoshop_State = 'photoshop:State';
|
||
XMP_Photoshop_SupplementalCategories = 'photoshop:SupplementalCategories';
|
||
XMP_Photoshop_TextLayerName = 'photoshop:TextLayerName';
|
||
XMP_Photoshop_TextLayerText = 'photoshop:TextLayerText';
|
||
XMP_Photoshop_TransmissionReference = 'photoshop:TransmissionReference';
|
||
XMP_Photoshop_Urgency = 'photoshop:Urgency';
|
||
XMP_Advisory = 'xmp:Advisory';
|
||
XMP_Author = 'xmp:Author';
|
||
XMP_BaseURL = 'xmp:BaseURL';
|
||
XMP_CreateDate = 'xmp:CreateDate';
|
||
XMP_CreatorTool = 'xmp:CreatorTool';
|
||
XMP_Description = 'xmp:Description';
|
||
XMP_Format = 'xmp:Format';
|
||
XMP_Identifier = 'xmp:Identifier';
|
||
XMP_Keywords = 'xmp:Keywords';
|
||
XMP_Label = 'xmp:Label';
|
||
XMP_MetadataDate = 'xmp:MetadataDate';
|
||
XMP_ModifyDate = 'xmp:ModifyDate';
|
||
XMP_Nickname = 'xmp:Nickname';
|
||
XMP_Rating = 'xmp:Rating';
|
||
XMP_Title = 'xmp:Title';
|
||
|
||
|
||
implementation
|
||
|
||
uses
|
||
Windows, hyiedefs, iedicom, hyieutils, Contnrs;
|
||
|
||
type
|
||
TIEMetaType = (iemEXIF, iemIPTC, iemDicom, iemXMP);
|
||
|
||
TExifTag = record
|
||
Desc : string; // Description
|
||
VarType : Integer; // Type of field
|
||
Edit : boolean; // Write support available for field
|
||
end;
|
||
|
||
resourcestring
|
||
|
||
// EXIF Data
|
||
s_UserComment = 'User Comment';
|
||
s_Description = 'Description';
|
||
s_CameraMake = 'Camera Make';
|
||
s_CameraModel = 'Camera Model';
|
||
s_Orientation = 'Camera Orientation';
|
||
s_Inch = 'inch';
|
||
s_CM = 'cm';
|
||
s_PerInch = ' / inch';
|
||
s_PerCM = ' / cm';
|
||
s_XResolution = 'Horizontal Resolution';
|
||
s_Yresolution = 'Vertical Resolution';
|
||
s_DateTime = 'Date and Time';
|
||
s_DateTimeOriginal = 'Original Date and Time';
|
||
s_DateTimeDigitized = 'Digitized Date and Time';
|
||
s_Copyright = 'Copyright';
|
||
s_ExposureTime = 'Exposure Time';
|
||
s_FNumber = 'F-Stop';
|
||
s_ExposureProgram = 'Exposure Program';
|
||
s_ManualControl = 'Manual';
|
||
s_ProgramNormal = 'Normal';
|
||
s_AperturePriority = 'Aperture Priority';
|
||
s_ShutterPriority = 'Shutter Priority';
|
||
s_CreativeProgram = 'Creative Program';
|
||
s_ActionProgram = 'Action Program';
|
||
s_Portraitmode = 'Portrait Mode';
|
||
s_LandscapeMode = 'Landscape Mode';
|
||
s_CompressedBitsPerPixel = 'Compression Ratio';
|
||
s_ShutterSpeedValue = 'Shutter Speed';
|
||
s_ApertureValue = 'Aperture Value';
|
||
s_ISOSpeedRatings = 'ISO Speed Rating';
|
||
s_BrightnessValue = 'Brightness';
|
||
s_ExposureBiasValue = 'Exposure Compensation';
|
||
s_MaxApertureValue = 'Max Aperture Value';
|
||
s_SubjectDistance = 'Subject Distance';
|
||
s_MeteringMode = 'Metering Mode';
|
||
s_average = 'Average';
|
||
s_CenterWeightedAverage = 'Center-weighted Average';
|
||
s_Spot = 'Spot';
|
||
s_MultiSpot = 'Multi-Spot';
|
||
s_MultiSegment = 'Multi-Segment';
|
||
s_partial = 'Partial';
|
||
s_Lighting = 'Lighting';
|
||
s_daylight = 'Daylight';
|
||
s_fluorescent = 'Flourescent';
|
||
s_tungsten = 'Tungsten';
|
||
s_flash = 'Flash';
|
||
s_standardLightA = 'Standard Light A';
|
||
s_standardLightB = 'Standard Light B';
|
||
s_standardLightC = 'Standard Light C';
|
||
s_D55 = 'D55';
|
||
s_D65 = 'D65';
|
||
s_D75 = 'D75';
|
||
s_FlashDidNotFire = 'Not Used';
|
||
s_flashFired = 'Fired';
|
||
s_flashFiredNoStrobeLight = 'Fired, No Strobe Return';
|
||
s_flashFiredStrobeLight = 'Fired, with Strobe Return';
|
||
s_FocalLength = 'Focal Length';
|
||
s_FlashPixVersion = 'FlashPix Version';
|
||
s_ColorSpace = 'Color Space';
|
||
s_RGB = 'RGB';
|
||
s_Uncalibrated = 'Uncalibrated';
|
||
s_WhiteBalance = 'White Balance';
|
||
s_ExifImageWidth = 'Image Width';
|
||
s_ExifImageHeight = 'Image Height';
|
||
s_RelatedSoundFile = 'Sound File';
|
||
s_FocalPlaneXResolution = 'Focal Plane Horz. Resolution';
|
||
s_FocalPlaneYResolution = 'Focal Plane Vert. Resolution';
|
||
s_ExposureIndex = 'Exposure Index';
|
||
s_SensingMethod = 'Sensing Method';
|
||
s_OneChipColorAreaSensor = 'Single Chip Color Area';
|
||
s_UnknownMethod = 'Unknown Method';
|
||
s_FileSource = 'File Source';
|
||
s_DigitalStillCamera = 'Digital Still Camera';
|
||
s_UnknownDevice = 'Unknown Device';
|
||
s_SceneType = 'Scene Type';
|
||
s_DirectlyPhotographed = 'Directly Photographed';
|
||
s_YcbCrPositioning = 'Chroma Sample Point';
|
||
s_Centered = 'Centered';
|
||
s_DataPoint = 'Data Point';
|
||
s_Seconds = 'Seconds';
|
||
s_Second = 'Second';
|
||
s_EXIFOrientation1 = 'Orientated Correctly';
|
||
s_EXIFOrientation2 = 'Horizontally Flipped';
|
||
s_EXIFOrientation3 = 'Offset by 180<38>';
|
||
s_EXIFOrientation4 = 'Vertically Flipped';
|
||
s_EXIFOrientation5 = 'Flipped Horiz. and Offset 90<39> CCW';
|
||
s_EXIFOrientation6 = 'Offset by 90<39> CCW';
|
||
s_EXIFOrientation7 = 'Flipped Horiz. and Offset 90<39> CW';
|
||
s_EXIFOrientation8 = 'Offset by 90<39> Clockwise';
|
||
|
||
s_ExposureMode = 'Exposure Mode';
|
||
s_DigitalZoomRatio = 'Digital Zoom Ratio';
|
||
s_FocalLengthIn35mmFilm = 'Focal Length in 35mm Film';
|
||
s_SceneCaptureType = 'Scene Capture Type';
|
||
s_GainControl = 'Gain Control';
|
||
s_Contrast = 'Contrast';
|
||
s_Saturation = 'Saturation';
|
||
s_Sharpness = 'Sharpness';
|
||
s_SubjectDistanceRange = 'Subject Distance';
|
||
s_GPSLatitude = 'GPS Latitude';
|
||
s_GPSLongitude = 'GPS Longitude';
|
||
s_GPSAltitude = 'GPS Altitude';
|
||
s_GPSImageDirection = 'GPS Image Direction';
|
||
s_GPSTrack = 'GPS Movement Direction';
|
||
s_GPSSpeed = 'GPS Movement Speed';
|
||
s_GPSDateAndTime = 'GPS Date and Time';
|
||
s_GPSSatellites = 'GPS Satellites';
|
||
s_GPSVersionID = 'GPS Version';
|
||
|
||
s_AutoExposure = 'Auto exposure';
|
||
s_ManualExposure = 'Manual exposure';
|
||
s_AutoBracket = 'Auto bracket';
|
||
|
||
s_Autowhitebalance = 'Auto white balance';
|
||
s_Manualwhitebalance = 'Manual white balance';
|
||
|
||
s_Standard = 'Standard';
|
||
s_Landscape = 'Landscape';
|
||
s_Portrait = 'Portrait';
|
||
s_NightScene = 'Night scene';
|
||
|
||
s_None = 'None';
|
||
s_LowGainup = 'Low gain up';
|
||
s_HighGainup = 'High gain up';
|
||
s_LowGaindown = 'Low gain down';
|
||
s_HighGaindown = 'High gain down';
|
||
|
||
s_Normal = 'Normal';
|
||
s_Soft = 'Soft';
|
||
s_Hard = 'Hard';
|
||
|
||
s_LowSaturation = 'Low saturation';
|
||
s_HighSaturation = 'High saturation';
|
||
|
||
s_Macro = 'Macro';
|
||
s_CloseView = 'Close view';
|
||
s_DistantView = 'Distant view';
|
||
|
||
s_Artist = 'Artist';
|
||
s_XPTitle = 'Title (Windows)';
|
||
s_XPComment = 'Comment (Windows)';
|
||
s_XPAuthor = 'Author (Windows)';
|
||
s_XPKeywords = 'Keywords (Windows)';
|
||
s_XPSubject = 'Subject (Windows)';
|
||
s_XPRating = 'Rating (Windows)';
|
||
|
||
s_InteropVersion = 'Interoperability Version';
|
||
s_CameraOwnerName = 'Camera Owner Name';
|
||
s_BodySerialNumber = 'Body Serial Number';
|
||
s_LensMake = 'Lens Make';
|
||
s_LensModel = 'Lens Model';
|
||
s_LensSerialNumber = 'Lens Serial Number';
|
||
s_Gamma = 'Gamma';
|
||
s_SubjectArea = 'Subject Area';
|
||
s_SubjectLocation = 'Subject Location';
|
||
|
||
s_PointAtXByX = 'Point at %d,%d';
|
||
s_CircleOfXCenteredAtAtXByX = 'Circle of %d centered at %d,%d';
|
||
s_RectangleOfXByXCenteredAtXByX = 'Rectangle of %d,%d centered at %d,%d';
|
||
|
||
const
|
||
_vString = 1;
|
||
_vInteger = 2;
|
||
_vDouble = 3;
|
||
|
||
ExifTags : array [0.._EXIF_Tag_Count - 1] of TExifTag = (
|
||
(Desc : s_UserComment ; VarType : _vString; Edit : TRUE ), // _EXIF_UserComment
|
||
(Desc : s_Description ; VarType : _vString; Edit : TRUE ), // _EXIF_ImageDescription
|
||
(Desc : s_CameraMake ; VarType : _vString; Edit : TRUE ), // _EXIF_Make
|
||
(Desc : s_CameraModel ; VarType : _vString; Edit : TRUE ), // _EXIF_Model
|
||
(Desc : s_XResolution ; VarType : _vDouble; Edit : TRUE ), // _EXIF_XResolution
|
||
(Desc : s_YResolution ; VarType : _vDouble; Edit : TRUE ), // _EXIF_YResolution
|
||
(Desc : s_DateTime ; VarType : _vString; Edit : TRUE ), // _EXIF_DateTime
|
||
(Desc : s_DateTimeOriginal ; VarType : _vString; Edit : TRUE ), // _EXIF_DateTimeOriginal
|
||
(Desc : s_DateTimeDigitized ; VarType : _vString; Edit : TRUE ), // _EXIF_DateTimeDigitized
|
||
(Desc : s_Copyright ; VarType : _vString; Edit : TRUE ), // _EXIF_Copyright
|
||
(Desc : s_Orientation ; VarType : _vInteger; Edit : TRUE ), // _EXIF_Orientation
|
||
(Desc : s_ExposureTime ; VarType : _vDouble; Edit : TRUE ), // _EXIF_ExposureTime
|
||
(Desc : s_FNumber ; VarType : _vDouble; Edit : TRUE ), // _EXIF_FNumber
|
||
(Desc : s_ExposureProgram ; VarType : _vInteger; Edit : TRUE ), // _EXIF_ExposureProgram
|
||
(Desc : s_ISOSpeedRatings ; VarType : _vInteger; Edit : TRUE ), // _EXIF_ISOSpeedRatings
|
||
(Desc : s_ShutterSpeedValue ; VarType : _vDouble; Edit : TRUE ), // _EXIF_ShutterSpeedValue
|
||
(Desc : s_ApertureValue ; VarType : _vDouble; Edit : TRUE ), // _EXIF_ApertureValue
|
||
(Desc : s_BrightnessValue ; VarType : _vDouble; Edit : TRUE ), // _EXIF_BrightnessValue
|
||
(Desc : s_ExposureBiasValue ; VarType : _vDouble; Edit : TRUE ), // _EXIF_ExposureBiasValue
|
||
(Desc : s_MaxApertureValue ; VarType : _vDouble; Edit : TRUE ), // _EXIF_MaxApertureValue
|
||
(Desc : s_SubjectDistance ; VarType : _vDouble; Edit : TRUE ), // _EXIF_SubjectDistance
|
||
(Desc : s_MeteringMode ; VarType : _vInteger; Edit : TRUE ), // _EXIF_MeteringMode
|
||
(Desc : s_Lighting ; VarType : _vInteger; Edit : TRUE ), // _EXIF_LightSource
|
||
(Desc : s_Flash ; VarType : _vInteger; Edit : TRUE ), // _EXIF_Flash
|
||
(Desc : s_FocalLength ; VarType : _vDouble; Edit : TRUE ), // _EXIF_FocalLength
|
||
(Desc : s_FlashPixVersion ; VarType : _vString; Edit : TRUE ), // _EXIF_FlashPixVersion
|
||
(Desc : s_ColorSpace ; VarType : _vInteger; Edit : TRUE ), // _EXIF_ColorSpace
|
||
(Desc : s_ExifImageWidth ; VarType : _vInteger; Edit : TRUE ), // _EXIF_ExifImageWidth
|
||
(Desc : s_ExifImageHeight ; VarType : _vInteger; Edit : TRUE ), // _EXIF_ExifImageHeight
|
||
(Desc : s_RelatedSoundFile ; VarType : _vString; Edit : TRUE ), // _EXIF_RelatedSoundFile
|
||
(Desc : s_FocalPlaneXResolution ; VarType : _vDouble; Edit : TRUE ), // _EXIF_FocalPlaneXResolution
|
||
(Desc : s_FocalPlaneYResolution ; VarType : _vDouble; Edit : TRUE ), // _EXIF_FocalPlaneYResolution
|
||
(Desc : s_ExposureIndex ; VarType : _vDouble; Edit : TRUE ), // _EXIF_ExposureIndex
|
||
(Desc : s_SensingMethod ; VarType : _vInteger; Edit : FALSE ), // _EXIF_SensingMethod
|
||
(Desc : s_FileSource ; VarType : _vInteger; Edit : FALSE ), // _EXIF_FileSource
|
||
(Desc : s_SceneType ; VarType : _vInteger; Edit : FALSE ), // _EXIF_SceneType
|
||
(Desc : s_YCbCrPositioning ; VarType : _vInteger; Edit : TRUE ), // _EXIF_YCbCrPositioning
|
||
(Desc : s_ExposureMode ; VarType : _vInteger; Edit : FALSE ), // _EXIF_ExposureMode
|
||
(Desc : s_WhiteBalance ; VarType : _vInteger; Edit : FALSE ), // _EXIF_WhiteBalance
|
||
(Desc : s_DigitalZoomRatio ; VarType : _vDouble; Edit : FALSE ), // _EXIF_DigitalZoomRatio
|
||
(Desc : s_FocalLengthIn35mmFilm ; VarType : _vInteger; Edit : FALSE ), // _EXIF_FocalLengthIn35mmFilm
|
||
(Desc : s_SceneCaptureType ; VarType : _vInteger; Edit : FALSE ), // _EXIF_SceneCaptureType
|
||
(Desc : s_GainControl ; VarType : _vInteger; Edit : FALSE ), // _EXIF_GainControl
|
||
(Desc : s_Contrast ; VarType : _vInteger; Edit : FALSE ), // _EXIF_Contrast
|
||
(Desc : s_Saturation ; VarType : _vInteger; Edit : FALSE ), // _EXIF_Saturation
|
||
(Desc : s_Sharpness ; VarType : _vInteger; Edit : FALSE ), // _EXIF_Sharpness
|
||
(Desc : s_SubjectDistanceRange ; VarType : _vInteger; Edit : FALSE ), // _EXIF_SubjectDistanceRange
|
||
(Desc : s_GPSLatitude ; VarType : _vDouble; Edit : FALSE ), // _EXIF_GPSLatitude
|
||
(Desc : s_GPSLongitude ; VarType : _vDouble; Edit : FALSE ), // _EXIF_GPSLongitude
|
||
(Desc : s_GPSAltitude ; VarType : _vDouble; Edit : FALSE ), // _EXIF_GPSAltitude
|
||
(Desc : s_GPSImageDirection ; VarType : _vDouble; Edit : FALSE ), // _EXIF_GPSImageDirection
|
||
(Desc : s_GPSTrack ; VarType : _vDouble; Edit : FALSE ), // _EXIF_GPSTrack
|
||
(Desc : s_GPSSpeed ; VarType : _vDouble; Edit : FALSE ), // _EXIF_GPSSpeed
|
||
(Desc : s_GPSDateAndTime ; VarType : _vDouble; Edit : FALSE ), // _EXIF_GPSDateAndTime
|
||
(Desc : s_GPSSatellites ; VarType : _vString; Edit : TRUE ), // _EXIF_GPSSatellites
|
||
(Desc : s_GPSVersionID ; VarType : _vString; Edit : TRUE ), // _EXIF_GPSVersionID
|
||
(Desc : s_Artist ; VarType : _vString; Edit : TRUE ), // _EXIF_Artist
|
||
(Desc : s_XPTitle ; VarType : _vString; Edit : TRUE ), // _EXIF_XPTitle
|
||
(Desc : s_XPComment ; VarType : _vString; Edit : TRUE ), // _EXIF_XPComment
|
||
(Desc : s_XPAuthor ; VarType : _vString; Edit : TRUE ), // _EXIF_XPAuthor
|
||
(Desc : s_XPKeywords ; VarType : _vString; Edit : TRUE ), // _EXIF_XPKeywords
|
||
(Desc : s_XPSubject ; VarType : _vString; Edit : TRUE ), // _EXIF_XPSubject
|
||
(Desc : s_XPRating ; VarType : _vInteger; Edit : TRUE ), // _EXIF_XPRating
|
||
(Desc : s_InteropVersion ; VarType : _vString; Edit : TRUE ), // _EXIF_InteropVersion
|
||
(Desc : s_CameraOwnerName ; VarType : _vString; Edit : TRUE ), // _EXIF_CameraOwnerName
|
||
(Desc : s_BodySerialNumber ; VarType : _vString; Edit : TRUE ), // _EXIF_BodySerialNumber
|
||
(Desc : s_LensMake ; VarType : _vString; Edit : TRUE ), // _EXIF_LensMake
|
||
(Desc : s_LensModel ; VarType : _vString; Edit : TRUE ), // _EXIF_LensModel
|
||
(Desc : s_LensSerialNumber ; VarType : _vString; Edit : TRUE ), // _EXIF_LensSerialNumber
|
||
(Desc : s_Gamma ; VarType : _vDouble; Edit : TRUE ), // _EXIF_Gamma
|
||
(Desc : s_SubjectArea ; VarType : _vString; Edit : FALSE ), // _EXIF_SubjectArea
|
||
(Desc : s_SubjectLocation ; VarType : _vString; Edit : TRUE ) // _EXIF_SubjectLocation
|
||
);
|
||
|
||
// Exif Tags are a representation of the exif field that a user can put in a text string to be replaced
|
||
// dymanically by the actual value read from the file, e.g. %EXIF-User-Comment%
|
||
Exif_Tag_Prefix = '%EXIF-';
|
||
Exif_Tag_Suffix = '%';
|
||
|
||
|
||
|
||
resourcestring
|
||
s_Title = 'Title'; // Object name
|
||
s_Caption = 'Caption'; // Caption/Abstract
|
||
s_Keywords = 'Keywords';
|
||
s_SpecialInstructions = 'Special Instructions';
|
||
s_DateCreated_YYYYMMDD = 'Date Created (YYYYMMDD)';
|
||
s_TimeCreated_HHMMSS_HHMM = 'Time Created (HHMMSS<53>HHMM)';
|
||
s_Byline1 = 'By-line 1';
|
||
s_Byline2 = 'By-line 2';
|
||
s_City = 'City';
|
||
s_s_StateProvince = 'State/Province';
|
||
s_CountryPrimaryLocationCode = 'Country/Primary Location Code';
|
||
s_CountryPrimaryLocationName = 'Country/Primary Location Name';
|
||
s_OriginalTransmissionReference = 'Original Transmission Reference';
|
||
s_Credit = 'Credit';
|
||
s_Source = 'Source';
|
||
s_WriterEditor = 'Writer/Editor';
|
||
s_Editstatus = 'Edit status';
|
||
s_Urgency = 'Urgency';
|
||
s_Category = 'Category';
|
||
s_SupplementalCategory = 'Supplemental Category';
|
||
s_FixtureIdentifier = 'Fixture Identifier';
|
||
s_ReleaseDate_YYYYMMDD = 'Release Date (YYYYMMDD)';
|
||
s_ReleaseTime_HHMMSS_HHMM = 'Release Time (HHMMSS<53>HHMM)';
|
||
s_ReferenceService = 'Reference Service';
|
||
s_ReferenceDate_YYYYMMDD = 'Reference Date (YYYYMMDD)';
|
||
s_ReferenceNumber = 'Reference Number';
|
||
s_OriginatingProgram = 'Originating Program';
|
||
s_ProgramVersion = 'Program Version';
|
||
s_ObjectCycle_ABC = 'Object Cycle (a=AM, b=PM, c=both)';
|
||
s_CopyrightNotice = 'Copyright Notice';
|
||
s_ImageType = 'Image Type';
|
||
|
||
type
|
||
TIPTCTag = record
|
||
Rec : integer; // Record Number
|
||
DSet : integer; // Data Set
|
||
Desc : string; // Field Description
|
||
end;
|
||
|
||
const
|
||
IPTC_COMPATIBLE_EXTENSIONS = '*.TIF;*.TIFF;*.JPE;*.JPG;*.JPEG;';
|
||
|
||
IPTCTags : array [0..30] of TIPTCTag = (
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Title; Desc : s_Title ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Caption; Desc : s_Caption ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Keywords; Desc : s_Keywords ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Instructions; Desc : s_SpecialInstructions ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Date_Created; Desc : s_DateCreated_YYYYMMDD ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Time_Created; Desc : s_TimeCreated_HHMMSS_HHMM ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Byline_1; Desc : s_Byline1 ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Byline_2; Desc : s_Byline2 ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_City; Desc : s_City ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_State_Province; Desc : s_s_StateProvince ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Country_Code; Desc : s_CountryPrimaryLocationCode ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Country; Desc : s_CountryPrimaryLocationName ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Transmission_Reference; Desc : s_OriginalTransmissionReference ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Credit; Desc : s_Credit ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Source; Desc : s_Source ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Writer; Desc : s_WriterEditor ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Edit_Status; Desc : s_Editstatus ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Urgency; Desc : s_Urgency ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Category; Desc : s_Category ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Category_2; Desc : s_SupplementalCategory ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Fixture_Identifier; Desc : s_FixtureIdentifier ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Release_Date; Desc : s_ReleaseDate_YYYYMMDD ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Release_Time; Desc : s_ReleaseTime_HHMMSS_HHMM ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Reference_Service; Desc : s_ReferenceService ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Reference_Date; Desc : s_ReferenceDate_YYYYMMDD ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Reference_Number; Desc : s_ReferenceNumber ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Originating_Program; Desc : s_OriginatingProgram ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Program_Version; Desc : s_ProgramVersion ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Object_Cycle; Desc : s_ObjectCycle_ABC ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Copyright_Notice; Desc : s_CopyrightNotice ),
|
||
(Rec : PhotoShop_IPTC_Records; DSet : IPTC_PS_Image_Type; Desc : s_ImageType )
|
||
);
|
||
|
||
resourcestring
|
||
s_Unknown = 'Unknown';
|
||
|
||
resourcestring
|
||
s_FocusDistance = 'Focus Distance';
|
||
s_Firmware = 'Firmware';
|
||
s_FlashCompensation = 'Flash Compensation';
|
||
s_ImageNumber = 'Image Number';
|
||
s_Lens = 'Lens';
|
||
s_LensID = 'Lens ID';
|
||
s_LensInfo = 'Lens Info';
|
||
// s_LensSerialNumber = 'Lens Serial Number';
|
||
s_OwnerName = 'Owner Name';
|
||
s_SerialNumber = 'Serial Number';
|
||
s_AttributionName = 'Attribution Name';
|
||
s_AttributionURL = 'Attribution URL';
|
||
s_DeprecatedOn = 'Deprecated On';
|
||
s_Jurisdiction = 'Jurisdiction';
|
||
s_LegalCode = 'Legal Code';
|
||
s_License = 'License';
|
||
s_MorePermissions = 'More Permissions';
|
||
s_Permits = 'Permits';
|
||
s_Prohibits = 'Prohibits';
|
||
s_Requires = 'Requires';
|
||
s_UseGuidelines = 'Use Guidelines';
|
||
s_Contributor = 'Contributor';
|
||
s_Coverage = 'Coverage';
|
||
s_Creator = 'Creator';
|
||
s_Date = 'Date';
|
||
// s_Description = 'Description';
|
||
s_Format = 'Format';
|
||
s_Identifier = 'Identifier';
|
||
s_Language = 'Language';
|
||
s_Publisher = 'Publisher';
|
||
s_Relation = 'Relation';
|
||
s_Rights = 'Rights';
|
||
// s_Source = 'Source';
|
||
s_Subject = 'Subject';
|
||
// s_Title = 'Title';
|
||
s_Type = 'Type';
|
||
s_AuthorsPosition = 'Authors Position';
|
||
s_CaptionWriter = 'Caption Writer';
|
||
// s_Category = 'Category';
|
||
// s_City = 'City';
|
||
s_ColorMode = 'Color Mode';
|
||
s_Country = 'Country';
|
||
// s_Credit = 'Credit';
|
||
s_DateCreated = 'Date Created';
|
||
s_DocumentAncestorID = 'Document Ancestor ID';
|
||
s_Headline = 'Headline';
|
||
s_History = 'History';
|
||
s_ICCProfileName = 'ICC Profile Name';
|
||
s_Instructions = 'Instructions';
|
||
// s_Source = 'Source';
|
||
s_State = 'State';
|
||
s_SupplementalCategories = 'Supplemental Categories';
|
||
s_TextLayerName = 'Text Layer Name';
|
||
s_TextLayerText = 'Text Layer Text';
|
||
s_TransmissionReference = 'Transmission Reference';
|
||
// s_Urgency = 'Urgency';
|
||
s_Advisory = 'Advisory';
|
||
s_Author = 'Author';
|
||
s_BaseURL = 'Base URL';
|
||
s_CreateDate = 'Create Date';
|
||
s_CreatorTool = 'Creator Tool';
|
||
// s_Description = 'Description';
|
||
// s_Format = 'Format';
|
||
// s_Identifier = 'Identifier';
|
||
// s_Keywords = 'Keywords';
|
||
s_Label = 'Label';
|
||
s_MetadataDate = 'Metadata Date';
|
||
s_ModifyDate = 'Modify Date';
|
||
s_Nickname = 'Nickname';
|
||
s_Rating = 'Rating';
|
||
// s_Title = 'Title';
|
||
|
||
|
||
type
|
||
TXmpTag = record
|
||
Field : string; // Field Name
|
||
Desc : string; // Field Description
|
||
end;
|
||
|
||
const
|
||
|
||
XmpTags : array [0..70] of TXmpTag = (
|
||
( Field: XMP_Aux_ApproximateFocusDistance; Desc: s_FocusDistance ),
|
||
( Field: XMP_Aux_Firmware; Desc: s_Firmware ),
|
||
( Field: XMP_Aux_FlashCompensation; Desc: s_FlashCompensation ),
|
||
( Field: XMP_Aux_ImageNumber; Desc: s_ImageNumber ),
|
||
( Field: XMP_Aux_Lens; Desc: s_Lens ),
|
||
( Field: XMP_Aux_LensID; Desc: s_LensID ),
|
||
( Field: XMP_Aux_LensInfo; Desc: s_LensInfo ),
|
||
( Field: XMP_Aux_LensSerialNumber; Desc: s_LensSerialNumber ),
|
||
( Field: XMP_Aux_OwnerName; Desc: s_OwnerName ),
|
||
( Field: XMP_Aux_SerialNumber; Desc: s_SerialNumber ),
|
||
( Field: XMP_CC_AttributionName; Desc: s_AttributionName ),
|
||
( Field: XMP_CC_AttributionURL; Desc: s_AttributionURL ),
|
||
( Field: XMP_CC_DeprecatedOn; Desc: s_DeprecatedOn ),
|
||
( Field: XMP_CC_Jurisdiction; Desc: s_Jurisdiction ),
|
||
( Field: XMP_CC_LegalCode; Desc: s_LegalCode ),
|
||
( Field: XMP_CC_License; Desc: s_License ),
|
||
( Field: XMP_CC_MorePermissions; Desc: s_MorePermissions ),
|
||
( Field: XMP_CC_Permits; Desc: s_Permits ),
|
||
( Field: XMP_CC_Prohibits; Desc: s_Prohibits ),
|
||
( Field: XMP_CC_Requires; Desc: s_Requires ),
|
||
( Field: XMP_CC_UseGuidelines; Desc: s_UseGuidelines ),
|
||
( Field: XMP_DC_Contributor; Desc: s_Contributor ),
|
||
( Field: XMP_DC_Coverage; Desc: s_Coverage ),
|
||
( Field: XMP_DC_Creator; Desc: s_Creator ),
|
||
( Field: XMP_DC_Date; Desc: s_Date ),
|
||
( Field: XMP_DC_Description; Desc: s_Description ),
|
||
( Field: XMP_DC_Format; Desc: s_Format ),
|
||
( Field: XMP_DC_Identifier; Desc: s_Identifier ),
|
||
( Field: XMP_DC_Language; Desc: s_Language ),
|
||
( Field: XMP_DC_Publisher; Desc: s_Publisher ),
|
||
( Field: XMP_DC_Relation; Desc: s_Relation ),
|
||
( Field: XMP_DC_Rights; Desc: s_Rights ),
|
||
( Field: XMP_DC_Source; Desc: s_Source ),
|
||
( Field: XMP_DC_Subject; Desc: s_Subject ),
|
||
( Field: XMP_DC_Title; Desc: s_Title ),
|
||
( Field: XMP_DC_Type; Desc: s_Type ),
|
||
( Field: XMP_Photoshop_AuthorsPosition; Desc: s_AuthorsPosition ),
|
||
( Field: XMP_Photoshop_CaptionWriter; Desc: s_CaptionWriter ),
|
||
( Field: XMP_Photoshop_Category; Desc: s_Category ),
|
||
( Field: XMP_Photoshop_City; Desc: s_City ),
|
||
( Field: XMP_Photoshop_ColorMode; Desc: s_ColorMode ),
|
||
( Field: XMP_Photoshop_Country; Desc: s_Country ),
|
||
( Field: XMP_Photoshop_Credit; Desc: s_Credit ),
|
||
( Field: XMP_Photoshop_DateCreated; Desc: s_DateCreated ),
|
||
( Field: XMP_Photoshop_DocumentAncestorID; Desc: s_DocumentAncestorID ),
|
||
( Field: XMP_Photoshop_Headline; Desc: s_Headline ),
|
||
( Field: XMP_Photoshop_History; Desc: s_History ),
|
||
( Field: XMP_Photoshop_ICCProfileName; Desc: s_ICCProfileName ),
|
||
( Field: XMP_Photoshop_Instructions; Desc: s_Instructions ),
|
||
( Field: XMP_Photoshop_Source; Desc: s_Source ),
|
||
( Field: XMP_Photoshop_State; Desc: s_State ),
|
||
( Field: XMP_Photoshop_SupplementalCategories; Desc: s_SupplementalCategories ),
|
||
( Field: XMP_Photoshop_TextLayerName; Desc: s_TextLayerName ),
|
||
( Field: XMP_Photoshop_TextLayerText; Desc: s_TextLayerText ),
|
||
( Field: XMP_Photoshop_TransmissionReference; Desc: s_TransmissionReference ),
|
||
( Field: XMP_Photoshop_Urgency; Desc: s_Urgency ),
|
||
( Field: XMP_Advisory; Desc: s_Advisory ),
|
||
( Field: XMP_Author; Desc: s_Author ),
|
||
( Field: XMP_BaseURL; Desc: s_BaseURL ),
|
||
( Field: XMP_CreateDate; Desc: s_CreateDate ),
|
||
( Field: XMP_CreatorTool; Desc: s_CreatorTool ),
|
||
( Field: XMP_Description; Desc: s_Description ),
|
||
( Field: XMP_Format; Desc: s_Format ),
|
||
( Field: XMP_Identifier; Desc: s_Identifier ),
|
||
( Field: XMP_Keywords; Desc: s_Keywords ),
|
||
( Field: XMP_Label; Desc: s_Label ),
|
||
( Field: XMP_MetadataDate; Desc: s_MetadataDate ),
|
||
( Field: XMP_ModifyDate; Desc: s_ModifyDate ),
|
||
( Field: XMP_Nickname; Desc: s_Nickname ),
|
||
( Field: XMP_Rating; Desc: s_Rating ),
|
||
( Field: XMP_Title; Desc: s_Title )
|
||
);
|
||
|
||
// Return a double value as a fraction string
|
||
function DoubleToFraction(dValue: double): string;
|
||
begin
|
||
if (dValue = 0) or (dValue = -1) then
|
||
result := ''
|
||
else
|
||
result := '1/' + FloatToStr(dValue);
|
||
end;
|
||
|
||
// Convert a fraction string to a double
|
||
function FractionToDouble(dValue: string): double;
|
||
begin
|
||
if pos('1/', dValue) <> 1 then
|
||
raise EConvertError.create('Not a fraction');
|
||
|
||
delete(dValue, 1, 2);
|
||
result := StrToFloat(dValue);
|
||
end;
|
||
|
||
// Return a float as string, if the value is not 0 or -1
|
||
function FloatToStrOrNull(dValue: double; sAppend: string = ''): string;
|
||
begin
|
||
if (dValue = 0) or (dValue = -1) then
|
||
result := ''
|
||
else
|
||
result := FloatToStr(dValue) + sAppend;
|
||
end;
|
||
|
||
// Remove sStrip from the start of the string value
|
||
function StripPrefix(const Value: string; const sStrip: string): string;
|
||
begin
|
||
result := value;
|
||
if pos(uppercase(sStrip), uppercase(result)) = 1 then
|
||
Delete(result, 1, length(sStrip));
|
||
end;
|
||
|
||
// Remove sStrip from the end of the string value
|
||
function StripSuffix(const Value: string; const sStrip: string): string;
|
||
var
|
||
iPos: Integer;
|
||
begin
|
||
result := value;
|
||
iPos := Pos( Uppercase( sStrip), Uppercase( result ));
|
||
if ( iPos > 0 ) and ( iPos = ( Length( result ) - Length( sStrip )) + 1 ) then
|
||
SetLength(result, Length( result ) - Length( sStrip ));
|
||
end;
|
||
|
||
// Convert an apex value to a string
|
||
function ApexToStr(dBase: double;
|
||
dValue: double;
|
||
const sPrepend: string): string;
|
||
begin
|
||
result := '';
|
||
if (dBase <> 0) and (dValue <> -1) then
|
||
try
|
||
dValue := Power(dBase, dValue);
|
||
|
||
if (sPrepend = '1/') and
|
||
(dValue > 0) and
|
||
(dvalue <= 1) then
|
||
// cope with values such as 0.17
|
||
result := IEFloatToFormatString(dValue, 1, True)
|
||
else
|
||
result := sPrepend + IEFloatToFormatString(dValue, 1, True);
|
||
except
|
||
// UNEXPECTED ERROR
|
||
end;
|
||
end;
|
||
|
||
// Convert a string to an apex value
|
||
function StrToApex(dBase: double;
|
||
Value: string;
|
||
sPrepended: string
|
||
): double;
|
||
var
|
||
dValue: double;
|
||
begin
|
||
if (sPrepended = '1/') and
|
||
(pos('1/', Value) = 0) then
|
||
begin
|
||
dValue := 1 / StrToFloat(Value);
|
||
end
|
||
else
|
||
begin
|
||
Value := StripPrefix(Value, sPrepended);
|
||
dValue := StrToFloat(Value);
|
||
end;
|
||
|
||
Result := LogN(dBase, dValue);
|
||
end;
|
||
|
||
// Remove the null terminator from a string
|
||
function RemoveNull(Value: String): string;
|
||
begin
|
||
result := trim( String( Value ));
|
||
if (result <> '') and
|
||
(result[length(result)] = #0) then
|
||
SetLength(result, length(result) - 1);
|
||
result := trim(result);
|
||
end;
|
||
|
||
function RemoveNullA(Value: AnsiString): string;
|
||
begin
|
||
result := RemoveNull( String( Value ));
|
||
end;
|
||
|
||
// Convert EXIF_Flash to a descriptive string
|
||
function FlashModeToString(iFlash: Integer): string;
|
||
begin
|
||
Case iFlash of
|
||
0: result := s_FlashDidNotFire;
|
||
1: result := s_flashFired;
|
||
5: result := s_flashFiredNoStrobeLight;
|
||
7: result := s_flashFiredStrobeLight;
|
||
else
|
||
result := '';
|
||
end;
|
||
end;
|
||
|
||
// Return any text found before SeekStr
|
||
function GetTextBeforeChar(const Value, SeekStr: string; bNullIfNotFound: boolean = false): string;
|
||
var
|
||
iPos: integer;
|
||
begin
|
||
result := Value;
|
||
iPos := pos(uppercase(SeekStr), uppercase(Value));
|
||
if iPos > 0 then
|
||
delete(Result, iPos, (length(Result) - iPos) + 1)
|
||
else
|
||
if bNullIfNotFound then
|
||
result := '';
|
||
end;
|
||
|
||
// Return any text found after SeekStr
|
||
function GetTextAfterChar(const Value, SeekStr: string; bNullIfNotFound: boolean = false): string;
|
||
var
|
||
ipos: integer;
|
||
begin
|
||
result := Value;
|
||
iPos := pos(uppercase(SeekStr), uppercase(Value));
|
||
if ipos > 0 then
|
||
Delete(Result, 1, iPos + (length(SeekStr) - 1))
|
||
else
|
||
if bNullIfNotFound then
|
||
result := '';
|
||
end;
|
||
|
||
|
||
{$IFDEF Delphi2005orNewer}
|
||
|
||
function _ReadFromEXIF_Params(ADest: TObject; IOParams : TIOParams) : Boolean;
|
||
var
|
||
i: integer;
|
||
begin
|
||
if ADest is TStrings then
|
||
TStrings(ADest).Clear;
|
||
result := IOParams.EXIF_HasEXIFData;
|
||
if result = False then
|
||
exit;
|
||
|
||
for i := low(ExifTags) to high(ExifTags) do
|
||
begin
|
||
{$IFDEF USE_STRINGGRIDS}
|
||
if ADest is TStringGrid then
|
||
TStringGrid(ADest).Cells[1, i + TStringGrid(ADest).FixedRows] := IOParams.EXIF_AsStr[ i ]
|
||
else
|
||
{$endif}
|
||
{$IFDEF USE_LISTVIEW}
|
||
if ADest is TListView then
|
||
TListView(ADest).Items.Item[i].SubItems[0] := IOParams.EXIF_AsStr[ i ]
|
||
else
|
||
{$endif}
|
||
if ADest is TStrings then
|
||
TStrings(ADest).Add( ExifTags[ i ].Desc + ': ' + IOParams.EXIF_AsStr[ i ] )
|
||
else
|
||
raise EIEException.create('Invalid');
|
||
end;
|
||
end;
|
||
|
||
function _ReadFromIPTC_Params(ADest: TObject; IOParams : TIOParams) : Boolean;
|
||
var
|
||
i: integer;
|
||
sValue: string;
|
||
begin
|
||
result := false;
|
||
if ADest is TStrings then
|
||
TStrings(ADest).Clear;
|
||
|
||
if IOParams.IPTC_HasIPTCData = False then
|
||
exit;
|
||
|
||
// set properties to grid
|
||
for i := low(IPTCTags) to high(IPTCTags) do
|
||
begin
|
||
sValue := IOParams.ReadIPTCField(IPTCTags[i].Rec, IPTCTags[i].DSet);
|
||
|
||
{$IFDEF USE_STRINGGRIDS}
|
||
if ADest is TStringGrid then
|
||
TStringGrid(ADest).Cells[1, i + TStringGrid(ADest).FixedRows] := sValue
|
||
else
|
||
{$endif}
|
||
{$IFDEF USE_LISTVIEW}
|
||
if ADest is TListView then
|
||
TListView(ADest).Items[i].SubItems[0] := sValue
|
||
else
|
||
{$endif}
|
||
if ADest is TStrings then
|
||
TStrings(ADest).Add( IPTCTags[i].Desc + ': ' + sValue )
|
||
else
|
||
raise EIEException.create('Invalid');
|
||
|
||
if sValue <> '' then
|
||
result := true;
|
||
end;
|
||
end;
|
||
|
||
|
||
{$ifdef IEINCLUDEDICOM}
|
||
function _ReadFromDicom_Params(ADest: TObject; IOParams : TIOParams; TagInclude: TIEDicomInclude) : Boolean;
|
||
var
|
||
iRows: Integer;
|
||
|
||
procedure _ParseTags(tags: TIEDicomTags);
|
||
var
|
||
i, j: integer;
|
||
tag: PIEDicomTag;
|
||
sDescription: string;
|
||
sValue: String;
|
||
aListItem: TListItem;
|
||
aTagSource: TIEDicomTagSource;
|
||
bAllowTag: Boolean;
|
||
begin
|
||
for i := 0 to tags.Count - 1 do
|
||
begin
|
||
// GET DATA
|
||
tag := tags.GetTag(i);
|
||
sDescription := tags.GetTagDescription(i, aTagSource);
|
||
|
||
bAllowTag := True;
|
||
if (aTagSource = dsDeprecated) and ((diDeprecated in TagInclude) = False) then
|
||
bAllowTag := False
|
||
else
|
||
if (aTagSource = dsProprietary) and ((diProprietary in TagInclude) = False) then
|
||
bAllowTag := False;
|
||
|
||
if (sDescription = '') then
|
||
begin
|
||
if (diUnknown in TagInclude) = False then
|
||
bAllowTag := False
|
||
else
|
||
sDescription := s_Unknown;
|
||
end;
|
||
|
||
sValue := Trim( String( tags.GetTagString(i) ));
|
||
|
||
// ADD TO OUR CONTROL
|
||
if bAllowTag and (sValue <> '') then
|
||
begin
|
||
result := true;
|
||
|
||
{$IFDEF USE_STRINGGRIDS}
|
||
if ADest is TStringGrid then
|
||
begin
|
||
inc(iRows);
|
||
if TStringGrid(ADest).RowCount < TStringGrid(ADest).FixedRows + iRows then
|
||
TStringGrid(ADest).RowCount := TStringGrid(ADest).FixedRows + iRows;
|
||
|
||
TStringGrid(ADest).Cells[0, iRows + TStringGrid(ADest).FixedRows - 1] := sDescription;
|
||
TStringGrid(ADest).Cells[1, iRows + TStringGrid(ADest).FixedRows - 1] := sValue;
|
||
end
|
||
else
|
||
{$endif}
|
||
{$IFDEF USE_LISTVIEW}
|
||
if ADest is TListView then
|
||
begin
|
||
aListItem := TListView(ADest).Items.Add;
|
||
aListItem.Caption := sDescription;
|
||
aListItem.SubItems.Add(sValue);
|
||
end
|
||
else
|
||
{$endif}
|
||
if ADest is TStrings then
|
||
begin
|
||
TStrings(ADest).Add( sDescription + ': ' + sValue )
|
||
end
|
||
else
|
||
raise EIEException.create('Invalid');
|
||
end;
|
||
|
||
// PROCESS ANY CHILDREN
|
||
if (diChildTags in TagInclude) and assigned(tag.Children) then
|
||
begin
|
||
// tag.Children is a TObjectList object, where each item is a TIEDicomTags object to pass recursively into ShowRawTags
|
||
for j := 0 to tag.Children.Count - 1 do
|
||
_ParseTags(tag.Children[j] as TIEDicomTags);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
begin
|
||
result := False;
|
||
if ADest is TStrings then
|
||
TStrings(ADest).Clear;
|
||
|
||
if IOParams.DICOM_HasDicomTags = False then
|
||
exit;
|
||
|
||
if ADest is TStrings then
|
||
TStrings(ADest).BeginUpdate;
|
||
try
|
||
iRows := 0;
|
||
_ParseTags(IOParams.DICOM_Tags);
|
||
finally
|
||
if ADest is TStrings then
|
||
TStrings(ADest).EndUpdate;
|
||
end;
|
||
end;
|
||
{$endif}
|
||
|
||
function _ReadFromXMP_Params(ADest: TObject; IOParams : TIOParams) : Boolean;
|
||
var
|
||
i: integer;
|
||
sValue: string;
|
||
sDescription: string;
|
||
iRows: Integer;
|
||
aListItem: TListItem;
|
||
begin
|
||
result := false;
|
||
iRows := 0;
|
||
if ADest is TStrings then
|
||
TStrings(ADest).Clear;
|
||
|
||
if IOParams.XMP_HasXMPData = False then
|
||
exit;
|
||
|
||
// set properties to grid
|
||
for i := low(XMPTags) to high(XMPTags) do
|
||
begin
|
||
sValue := IOParams.XMP_AsStr[ XMPTags[ i ].Field ];
|
||
sDescription := XMPTags[ i ].Desc;
|
||
|
||
if sValue = '' then
|
||
begin { SKIP } end
|
||
else
|
||
{$IFDEF USE_STRINGGRIDS}
|
||
if ADest is TStringGrid then
|
||
begin
|
||
inc(iRows);
|
||
if TStringGrid(ADest).RowCount < TStringGrid(ADest).FixedRows + iRows then
|
||
TStringGrid(ADest).RowCount := TStringGrid(ADest).FixedRows + iRows;
|
||
TStringGrid(ADest).Cells[0, iRows + TStringGrid(ADest).FixedRows - 1] := sDescription;
|
||
TStringGrid(ADest).Cells[1, iRows + TStringGrid(ADest).FixedRows - 1] := sValue;
|
||
end
|
||
else
|
||
{$endif}
|
||
{$IFDEF USE_LISTVIEW}
|
||
if ADest is TListView then
|
||
begin
|
||
aListItem := TListView(ADest).Items.Add;
|
||
aListItem.Caption := sDescription;
|
||
aListItem.SubItems.Add(sValue);
|
||
end
|
||
else
|
||
{$endif}
|
||
if ADest is TStrings then
|
||
begin
|
||
TStrings(ADest).Add( sDescription + ': ' + sValue )
|
||
end
|
||
else
|
||
raise EIEException.create('Invalid');
|
||
|
||
if sValue <> '' then
|
||
result := true;
|
||
end;
|
||
end;
|
||
|
||
function _ReadFromMeta_File(ADest: TObject; AMetaType : TIEMetaType; const sFilename : string; DicomTagInclude: TIEDicomInclude = []) : Boolean;
|
||
var
|
||
aImageEnIO: TImageEnIO;
|
||
begin
|
||
{$IFDEF IEForceVarInitialization}
|
||
Result := False;
|
||
{$ENDIF}
|
||
aImageEnIO := TImageEnIO.create(nil);
|
||
try
|
||
aImageEnIO.ParamsFromFile(sFilename);
|
||
|
||
case AMetaType of
|
||
iemEXIF : Result := _ReadFromEXIF_Params(ADest, aImageEnIO.Params);
|
||
iemIPTC : Result := _ReadFromIPTC_Params(ADest, aImageEnIO.Params);
|
||
{$ifdef IEINCLUDEDICOM}
|
||
iemDicom : Result := _ReadFromDicom_Params(ADest, aImageEnIO.Params, DicomTagInclude);
|
||
{$endif}
|
||
iemXMP : Result := _ReadFromXMP_Params(ADest, aImageEnIO.Params);
|
||
else raise EIEException.create('Invalid');
|
||
end;
|
||
|
||
finally
|
||
aImageEnIO.Free;
|
||
end;
|
||
end;
|
||
|
||
function _WriteToExif_Params(ADest: TObject; IOParams : TIOParams) : Boolean;
|
||
var
|
||
sNewValue : string;
|
||
i : integer;
|
||
bExifHasData : boolean;
|
||
bExifHasChanged: Boolean;
|
||
begin
|
||
bExifHasData := false;
|
||
bExifHasChanged := False;
|
||
|
||
for i := low(ExifTags) to high(ExifTags) do
|
||
begin
|
||
{$IFDEF USE_STRINGGRIDS}
|
||
if ADest is TStringGrid then
|
||
sNewValue := TStringGrid(ADest).Cells[1, i + TStringGrid(ADest).FixedRows]
|
||
else
|
||
{$endif}
|
||
{$IFDEF USE_LISTVIEW}
|
||
if ADest is TListView then
|
||
sNewValue := TListView(ADest).Items.Item[i].SubItems[0]
|
||
else
|
||
{$endif}
|
||
raise EIEException.create('Invalid');
|
||
|
||
if sNewValue <> '' then
|
||
bExifHasData := True;
|
||
|
||
// Has the data for that field changed?
|
||
if sNewValue <> IOParams.EXIF_AsStr[ i ] then
|
||
begin
|
||
bExifHasChanged := True;
|
||
IOParams.EXIF_AsStr[ i ] := sNewValue;
|
||
end;
|
||
end;
|
||
IOParams.EXIF_HasEXIFData := bExifHasData;
|
||
|
||
Result := bExifHasChanged;
|
||
end;
|
||
|
||
function _WriteToIPTC_Params(ADest: TObject; IOParams : TIOParams) : Boolean;
|
||
var
|
||
i: integer;
|
||
sOldValue, sNewValue: string;
|
||
begin
|
||
Result := False;
|
||
for i := low(IPTCTags) to high(IPTCTags) do
|
||
begin
|
||
{$IFDEF USE_STRINGGRIDS}
|
||
if ADest is TStringGrid then
|
||
sNewValue := TStringGrid(ADest).Cells[1, i + TStringGrid(ADest).FixedRows]
|
||
else
|
||
{$endif}
|
||
{$IFDEF USE_LISTVIEW}
|
||
if ADest is TListView then
|
||
sNewValue := TListView(ADest).Items.Item[i].SubItems[0]
|
||
else
|
||
{$endif}
|
||
raise EIEException.create('Invalid');
|
||
|
||
sOldValue := IOParams.ReadIPTCField(IPTCTags[i].Rec, IPTCTags[i].DSet);
|
||
|
||
if sNewValue <> sOldValue then
|
||
begin
|
||
Result := True;
|
||
IOParams.WriteIPTCField(IPTCTags[i].Rec, IPTCTags[i].DSet, sNewValue);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
|
||
function _WriteToMeta_File(ADest: TObject; AMetaType : TIEMetaType; const sFilename : string) : Boolean;
|
||
var
|
||
aImageEnIO: TImageEnIO;
|
||
dFileDate : TDateTime;
|
||
bHasChanged: Boolean;
|
||
begin
|
||
Result := False;
|
||
|
||
aImageEnIO := TImageEnIO.create(nil);
|
||
try
|
||
if FileExists(sFilename) = False then
|
||
raise EIEException.create('Cannot find file to update: ' + sFilename);
|
||
|
||
// Get existing meta data
|
||
// NOTE: There is no InjectTiffIPTC
|
||
if (AMetaType = iemIPTC) and
|
||
(IEFilenameInExtensions(sFilename, '*.jpeg;*.jpg;*.jpe;') = False) then
|
||
aImageEnIO.LoadFromFile(sFilename)
|
||
else
|
||
aImageEnIO.ParamsFromFile(sFilename);
|
||
|
||
case AMetaType of
|
||
iemEXIF : bHasChanged := _WriteToExif_Params(ADest, aImageEnIO.Params);
|
||
iemIPTC : bHasChanged := _WriteToIPTC_Params(ADest, aImageEnIO.Params);
|
||
else raise EIEException.create('Invalid');
|
||
end;
|
||
|
||
if bHasChanged then
|
||
begin
|
||
Result := True;
|
||
|
||
{$WARNINGS OFF} // FileAge is deprecated
|
||
dFileDate := 0;
|
||
if Maintain_File_Dates_On_Meta_Write then
|
||
dFileDate := FileDateToDateTime(FileAge(sFileName));
|
||
{$WARNINGS ON}
|
||
|
||
if aImageEnIO.Params.FileType = ioJPEG then
|
||
case AMetaType of
|
||
iemEXIF : aImageEnIO.InjectJpegEXIF(sFileName);
|
||
iemIPTC : aImageEnIO.InjectJpegIPTC(sFileName);
|
||
end
|
||
else
|
||
if aImageEnIO.Params.FileType = ioTIFF then
|
||
case AMetaType of
|
||
iemEXIF : aImageEnIO.InjectTiffEXIF(sFileName);
|
||
iemIPTC : aImageEnIO.SaveToFile(sFileName);
|
||
end
|
||
else
|
||
raise EIEException.create('File format does not support this meta data type');
|
||
|
||
if Maintain_File_Dates_On_Meta_Write and (dFileDate <> 0) then
|
||
IEFileSetDate(sFileName, dFileDate);
|
||
end;
|
||
|
||
finally
|
||
aImageEnIO.Free;
|
||
end;
|
||
end;
|
||
|
||
{$endif}
|
||
|
||
{ TStringGridHelper }
|
||
|
||
{$IFDEF Delphi2005orNewer}
|
||
{$IFDEF USE_STRINGGRIDS}
|
||
|
||
{!!
|
||
<FS>TStringGridHelper.InitializeGrid
|
||
|
||
<FM>Declaration<FC>
|
||
procedure InitializeGrid(bFixLayout : Boolean = True);
|
||
|
||
<FM>Description<FN>
|
||
Set up a TStringGrid for display or editing of EXIF, IPTC and Dicom meta data. If <FC>bFixLayout<FN> is true then it will automatically add columns and a header row to your grid.
|
||
|
||
<FM>Example<FC>
|
||
// Display a grid allowing user to add EXIF data
|
||
procedure TExifForm.FormCreate(Sender: TObject);
|
||
begin
|
||
// Fix grid layout
|
||
MyExifStringGrid.InitializeGrid;
|
||
|
||
// Add fields to grid
|
||
MyExifStringGrid.NewGridForExif;
|
||
end;
|
||
!!}
|
||
procedure TStringGridHelper.InitializeGrid(bFixLayout : Boolean = True);
|
||
var
|
||
c, r: integer;
|
||
begin
|
||
if bFixLayout then
|
||
begin
|
||
FixedRows := 1;
|
||
RowCount := FixedRows + 1;
|
||
FixedCols := 1;
|
||
ColCount := FixedCols + 1;
|
||
ColWidths[ 0 ] := Width div 3; // 1/3 the width
|
||
ColWidths[ 1 ] := MulDiv(Width, 3, 2); // 2/3 the width
|
||
end;
|
||
|
||
// Clear content
|
||
for r := 0 to RowCount - 1 do
|
||
for c := 0 to ColCount - 1 do
|
||
Cells[c, r] := '';
|
||
|
||
// header row
|
||
if FixedRows > 0 then
|
||
begin
|
||
Cells[0, 0] := iemsg(IEMSG_NAME);
|
||
Cells[1, 0] := iemsg(IEMSG_VALUE);
|
||
end;
|
||
end;
|
||
|
||
procedure _NewGrid(AStringGrid: TStringGrid; AMetaType : TIEMetaType; bReadOnly : Boolean);
|
||
var
|
||
i: integer;
|
||
sDescription: string;
|
||
iRowMax: Integer;
|
||
begin
|
||
with AStringGrid do
|
||
begin
|
||
case AMetaType of
|
||
iemEXIF : iRowMax := High(ExifTags);
|
||
iemIPTC : iRowMax := High(IPTCTags);
|
||
iemDicom,
|
||
iemXMP : iRowMax := -1; // Filled later
|
||
else raise EIEException.create('Invalid');
|
||
end;
|
||
|
||
// add a row for each EXIF plus the header (if there is a fixed row)
|
||
if iRowMax > 0 then
|
||
RowCount := iRowMax + 1 + FixedRows
|
||
else
|
||
RowCount := FixedRows + 1;
|
||
|
||
InitializeGrid(False);
|
||
|
||
// fill the fields with the EXIF property names
|
||
for i := 0 to RowCount - 2 do
|
||
begin
|
||
case AMetaType of
|
||
iemEXIF : sDescription := ExifTags[i].Desc;
|
||
iemIPTC : sDescription := IPTCTags[i].Desc;
|
||
iemDicom,
|
||
iemXMP : sDescription := ''; // Filled later
|
||
else raise EIEException.create('Invalid');
|
||
end;
|
||
Cells[0, i + FixedRows] := sDescription;
|
||
Cells[1, i + FixedRows] := '';
|
||
end;
|
||
|
||
if bReadOnly then
|
||
Options := Options - [goEditing]
|
||
else
|
||
Options := Options + [goEditing];
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TStringGridHelper.NewGridForExif
|
||
|
||
<FM>Declaration<FC>
|
||
procedure NewGridForExif(bReadOnly : Boolean = False);
|
||
|
||
<FM>Description<FN>
|
||
Set up a TStringGrid for specifying values for EXIF fields (e.g. to a file without EXIF fields presently).
|
||
Two columns will be added with the left one containing property descriptions (using <A TIOParamsHelper.EXIF_FieldDescription>) and the right blank for field entry. If the grid has a fixed row it will be given a heading of "Name" and "Value".
|
||
If <FC>bReadOnly<FN> is true the right-column will not be editable.
|
||
|
||
Note: You may wish to call <A TStringGridHelper.InitializeGrid> before <FC>NewGridForExif<FN> to automatically assign the optimal layout to the grid.
|
||
|
||
<FM>Example<FC>
|
||
// Display a grid allowing user to add EXIF data
|
||
procedure TExifForm.FormCreate(Sender: TObject);
|
||
begin
|
||
// Fix grid layout
|
||
MyExifStringGrid.InitializeGrid;
|
||
|
||
// Add fields to grid
|
||
MyExifStringGrid.NewGridForExif;
|
||
end;
|
||
!!}
|
||
procedure TStringGridHelper.NewGridForExif(bReadOnly : Boolean = False);
|
||
begin
|
||
_NewGrid(Self, iemEXIF, bReadOnly);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TStringGridHelper.NewGridForIPTC
|
||
|
||
<FM>Declaration<FC>
|
||
procedure NewGridForIPTC(bReadOnly : Boolean = False);
|
||
|
||
<FM>Description<FN>
|
||
Set up a TStringGrid for specifying values for IPTC fields (e.g. to a file without IPTC fields presently).
|
||
Two columns will be added with the left one containing property descriptions and the right blank for field entry. If the grid has a fixed row it will be given a heading of "Name" and "Value".
|
||
If <FC>bReadOnly<FN> is true the right-column will not be editable.
|
||
|
||
Note: You may wish to call <A TStringGridHelper.InitializeGrid> before <FC>NewGridForIPTC<FN> to automatically assign the optimal layout to the grid.
|
||
|
||
<FM>Example<FC>
|
||
// Display a grid allowing user to add IPTC data
|
||
procedure TIPTCForm.FormCreate(Sender: TObject);
|
||
begin
|
||
// Fix grid layout
|
||
MyIPTCStringGrid.InitializeGrid;
|
||
|
||
// Add fields to grid
|
||
MyIPTCtringGrid.NewGridForIPTC;
|
||
end;
|
||
!!}
|
||
// Formerly InitializeIPTCStringGrid
|
||
procedure TStringGridHelper.NewGridForIPTC(bReadOnly : Boolean = False);
|
||
begin
|
||
_NewGrid(Self, iemIPTC, bReadOnly);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TStringGridHelper.ReadGridFromExif
|
||
|
||
<FM>Declaration<FC>
|
||
function ReadGridFromExif(IOParams : <A TIOParams>; bReadOnly : Boolean = False) : Boolean; overload;
|
||
function ReadGridFromExif(const sFilename : string; bReadOnly : Boolean = False) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Fill a TStringGrid with the EXIF properties of the current image, or one loaded from file.
|
||
Two columns will be added with the left one containing property descriptions (using <A TIOParamsHelper.EXIF_FieldDescription>) and the right one containing properties values (using <A TIOParamsHelper.EXIF_AsStr>). If the grid has a fixed row it will be given a heading of "Name" and "Value".
|
||
If <FC>bReadOnly<FN> is true the right-column will not be editable.
|
||
Result is true if the file has any EXIF fields.
|
||
|
||
Note: You may wish to call <A TStringGridHelper.InitializeGrid> before <FC>ReadGridFromExif<FN> to automatically assign the optimal layout to the grid.
|
||
|
||
<FM>Examples<FC>
|
||
// Display the EXIF properties of the current image
|
||
MyExifStringGrid.ReadGridFromExif( ImageEnView1.IO.Params );
|
||
|
||
// Read-only display of EXIF properties of a file
|
||
MyExifStringGrid.ReadGridFromExif( 'C:\MyImage.jpeg', True );
|
||
!!}
|
||
function TStringGridHelper.ReadGridFromExif(IOParams : TIOParams; bReadOnly : Boolean = False) : Boolean;
|
||
begin
|
||
NewGridForExif(bReadOnly);
|
||
Result := _ReadFromEXIF_Params(Self, IOParams);
|
||
end;
|
||
|
||
function TStringGridHelper.ReadGridFromExif(const sFilename : string; bReadOnly : Boolean = False) : Boolean;
|
||
begin
|
||
NewGridForExif(bReadOnly);
|
||
Result := _ReadFromMeta_File(Self, iemEXIF, sFilename);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TStringGridHelper.ReadGridFromIPTC
|
||
|
||
<FM>Declaration<FC>
|
||
function ReadGridFromIPTC(IOParams : <A TIOParams>; bReadOnly : Boolean = False) : Boolean; overload;
|
||
function ReadGridFromIPTC(const sFilename : string; bReadOnly : Boolean = False) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Fill a TStringGrid with the IPTC properties of the current image, or one loaded from file.
|
||
Two columns will be added with the left one containing property descriptions and the right one containing properties values. If the grid has a fixed row it will be given a heading of "Name" and "Value".
|
||
If <FC>bReadOnly<FN> is true the right-column will not be editable.
|
||
Result is true if the file has any IPTC fields.
|
||
|
||
Note: You may wish to call <A TStringGridHelper.InitializeGrid> before <FC>ReadGridFromIPTC<FN> to automatically assign the optimal layout to the grid.
|
||
|
||
<FM>Examples<FC>
|
||
// Display the IPTC properties of the current image
|
||
MyIPTCStringGrid.ReadGridFromIPTC( ImageEnView1.IO.Params );
|
||
|
||
// Read-only display of IPTC properties of a file
|
||
MyIPTCStringGrid.ReadGridFromIPTC( 'C:\MyImage.jpeg', True );
|
||
!!}
|
||
// Formerly LoadIPTCFields
|
||
function TStringGridHelper.ReadGridFromIPTC(IOParams : TIOParams; bReadOnly : Boolean = False) : Boolean;
|
||
begin
|
||
NewGridForIPTC(bReadOnly);
|
||
Result := _ReadFromIPTC_Params(Self, IOParams);
|
||
end;
|
||
|
||
function TStringGridHelper.ReadGridFromIPTC(const sFilename : string; bReadOnly : Boolean = False) : Boolean;
|
||
begin
|
||
NewGridForIPTC(bReadOnly);
|
||
Result := _ReadFromMeta_File(Self, iemIPTC, sFilename);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TStringGridHelper.ReadGridFromDicom
|
||
|
||
<FM>Declaration<FC>
|
||
function ReadGridFromDicom(IOParams : <A TIOParams>; TagInclude: <A TIEDicomInclude>) : Boolean; overload;
|
||
function ReadGridFromDicom(const sFilename : string; TagInclude: <A TIEDicomInclude>) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Fill a TStringGrid with the Dicom properties of the current image, or one loaded from file.
|
||
Two columns will be added with the left one containing property descriptions (using <A TIEDicomTags.GetTagDescription>) and the right one containing Dicom values (using <A TIEDicomTags.GetTagString>). If the grid has a fixed row it will be given a heading of "Name" and "Value".
|
||
<FC>TagInclude<FN> allows you to filter the types of tags returned.
|
||
Result is true if the file has any Dicom fields.
|
||
|
||
Note: You may wish to call <A TStringGridHelper.InitializeGrid> before <FC>ReadGridFromDicom<FN> to automatically assign the optimal layout to the grid.
|
||
|
||
<FM>Examples<FC>
|
||
// Display the Dicom properties of the current image (all types)
|
||
MyDicomGridView.ReadGridFromDicom( ImageEnView1.IO.Params, [ diProprietary, diDeprecated, diChildTags, diUnknown ] );
|
||
|
||
// Display of Dicom properties of a file (excluding deprecated and unknown tags)
|
||
MyDicomGridView.ReadGridFromDicom( 'C:\MyImage.jpeg', [ diProprietary, diChildTags ] );
|
||
!!}
|
||
{$ifdef IEINCLUDEDICOM}
|
||
function TStringGridHelper.ReadGridFromDicom(IOParams : TIOParams; TagInclude: TIEDicomInclude) : Boolean;
|
||
begin
|
||
_NewGrid(Self, iemDicom, True);
|
||
Result := _ReadFromDicom_Params(Self, IOParams, TagInclude);
|
||
end;
|
||
{$endif}
|
||
|
||
{$ifdef IEINCLUDEDICOM}
|
||
function TStringGridHelper.ReadGridFromDicom(const sFilename : string; TagInclude: TIEDicomInclude) : Boolean;
|
||
begin
|
||
_NewGrid(Self, iemDicom, True);
|
||
Result := _ReadFromMeta_File(Self, iemDicom, sFilename, TagInclude);
|
||
end;
|
||
{$endif}
|
||
|
||
|
||
{!!
|
||
<FS>TStringGridHelper.ReadGridFromXMP
|
||
|
||
<FM>Declaration<FC>
|
||
function ReadGridFromXMP(IOParams : <A TIOParams>) : Boolean; overload;
|
||
function ReadGridFromXMP(const sFilename : string) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Fill a TStringGrid with XMP properties of the current image, or one loaded from file.
|
||
Two columns will be added with the left one containing property descriptions and the right one containing XMP values (using <A TIEDictionary.GetString>). If the grid has a fixed row it will be given a heading of "Name" and "Value".
|
||
|
||
Result is true if the file has XMP fields.
|
||
|
||
Note: Only <L Consts for Common XMP Fields>common XMP fields</L> are added
|
||
|
||
<FM>Demo<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_DEMO> <C>Demos\InputOutput\XMP\XMP.dpr </C> </R>
|
||
</TABLE>
|
||
|
||
<FM>Examples<FC>
|
||
// Display the XMP properties of the current image
|
||
MyXMPGridView.ReadGridFromXMP( ImageEnView1.IO.Params );
|
||
|
||
// Display of XMP properties of a file
|
||
MyXMPGridView.ReadGridFromXMP( 'C:\MyImage.jpeg' );
|
||
!!}
|
||
function TStringGridHelper.ReadGridFromXMP(IOParams : TIOParams) : Boolean;
|
||
begin
|
||
_NewGrid(Self, iemXMP, True);
|
||
Result := _ReadFromXMP_Params( Self, IOParams );
|
||
end;
|
||
|
||
function TStringGridHelper.ReadGridFromXMP(const sFilename : string) : Boolean;
|
||
begin
|
||
_NewGrid(Self, iemXMP, True);
|
||
Result := _ReadFromMeta_File( Self, iemXMP, sFilename );
|
||
end;
|
||
|
||
{!!
|
||
<FS>TStringGridHelper.WriteGridToExif
|
||
|
||
<FM>Declaration<FC>
|
||
function WriteGridToExif(IOParams : <A TIOParams>) : Boolean; overload;
|
||
function WriteGridToExif(const sFilename : string) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Write the changes made by a user to EXIF values in a TStringGrid (which was filled using <A TStringGridHelper.NewGridForExif> or <A TStringGridHelper.ReadGridFromExif>) to the current image or an image file.
|
||
Result is true if any changes were made to the EXIF properties (i.e. a result of false means the TStringGrid EXIF content matches the file).
|
||
|
||
Notes:
|
||
- For first overload, only the <A TIOParams> is updated, the changes are not saved to file.
|
||
- For the second overload, the file must already exist! If no changes were made to the EXIF data then the file is not modified
|
||
|
||
<FM>Examples<FC>
|
||
// Write changes to EXIF properties of the current image, and ask if the user wants to save changes if any fields were modified
|
||
if MyExifStringGrid.WriteGridToExif( ImageEnView1.IO.Params ) then
|
||
PromptToSaveFile;
|
||
|
||
// write EXIF changes to a file
|
||
MyExifStringGrid.WriteGridToExif( 'D:\MyImage.jpeg' );
|
||
!!}
|
||
function TStringGridHelper.WriteGridToExif(IOParams : TIOParams) : Boolean;
|
||
begin
|
||
Result := _WriteToExif_Params(Self, IOParams);
|
||
end;
|
||
|
||
function TStringGridHelper.WriteGridToExif(const sFilename : string) : Boolean;
|
||
begin
|
||
Result := _WriteToMeta_File(Self, iemEXIF, sFilename);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TStringGridHelper.WriteGridToIPTC
|
||
|
||
<FM>Declaration<FC>
|
||
function WriteGridToIPTC(IOParams : <A TIOParams>) : Boolean; overload;
|
||
function WriteGridToIPTC(const sFilename : string) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Write the changes made by a user to IPTC values in a TStringGrid (which was filled using <A TStringGridHelper.NewGridForIPTC> or <A TStringGridHelper.ReadGridFromIPTC>) to the current image or an image file.
|
||
Result is true if any changes were made to the IPTC properties (i.e. a result of false means the TStringGrid IPTC content matches the file).
|
||
|
||
Notes:
|
||
- For first overload, only the <A TIOParams> is updated, the changes are not saved to file.
|
||
- For the second overload, the file must already exist! If no changes were made to the IPTC data then the file is not modified
|
||
|
||
<FM>Examples<FC>
|
||
// Write changes to IPTC properties of the current image, and ask if the user wants to save changes if any fields were modified
|
||
if MyIPTCStringGrid.WriteGridToIPTC( ImageEnView1.IO.Params ) then
|
||
PromptToSaveFile;
|
||
|
||
// write IPTC changes to a file
|
||
MyIPTCStringGrid.WriteGridToIPTC( 'D:\MyImage.jpeg' );
|
||
!!}
|
||
// Formerly SaveIPTCFields
|
||
function TStringGridHelper.WriteGridToIPTC(IOParams : TIOParams) : Boolean;
|
||
begin
|
||
Result := _WriteToIPTC_Params(Self, IOParams);
|
||
end;
|
||
|
||
function TStringGridHelper.WriteGridToIPTC(const sFilename : string) : Boolean;
|
||
begin
|
||
Result := _WriteToMeta_File(Self, iemIPTC, sFilename);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TStringGridHelper.ClearGridFields
|
||
|
||
<FM>Declaration<FC>
|
||
procedure ClearGridFields;
|
||
|
||
<FM>Description<FN>
|
||
Clears all values in a TStringGrid containing EXIF or IPTC properties, which was filled using one of the following:
|
||
- <A TStringGridHelper.NewGridForExif>
|
||
- <A TStringGridHelper.NewGridForIPTC>
|
||
- <A TStringGridHelper.ReadGridFromExif>
|
||
- <A TStringGridHelper.ReadGridFromIPTC>
|
||
|
||
Note: Only clears the grid, not EXIF or IPTC properties of a file
|
||
|
||
<FM>Examples<FC>
|
||
procedure TMainForm.btnResetGridClick(Sender: TObject);
|
||
begin
|
||
// Clear all the specified values for our grid
|
||
MyExifStringGrid.ClearGridFields;
|
||
end;
|
||
!!}
|
||
procedure TStringGridHelper.ClearGridFields;
|
||
var
|
||
i: integer;
|
||
begin
|
||
for i := FixedRows to RowCount - 1 do
|
||
Cells[1, i] := '';
|
||
end;
|
||
|
||
{$endif}
|
||
{$endif}
|
||
|
||
|
||
{ TListViewHelper }
|
||
|
||
{$IFDEF Delphi2005orNewer}
|
||
{$IFDEF USE_LISTVIEW}
|
||
|
||
|
||
{!!
|
||
<FS>TListViewHelper.InitializeList
|
||
|
||
<FM>Declaration<FC>
|
||
procedure InitializeList(bFixLayout : Boolean = True);
|
||
|
||
<FM>Description<FN>
|
||
Set up a TListView for display or editing of EXIF, IPTC and Dicom meta data. If <FC>bFixLayout<FN> is true then it will automatically adjust the properties for best display.
|
||
|
||
<FM>Example<FC>
|
||
// Display a TListView allowing user to add EXIF data
|
||
procedure TEXIFForm.FormCreate(Sender: TObject);
|
||
begin
|
||
// Fix List layout
|
||
MyExifListView.InitializeList;
|
||
|
||
// Add fields to List
|
||
MyExifListView.NewListForExif;
|
||
end;
|
||
!!}
|
||
procedure TListViewHelper.InitializeList(bFixLayout : Boolean = True);
|
||
const
|
||
Buffer_px = 4;
|
||
var
|
||
aListColumn: TListColumn;
|
||
begin
|
||
Clear;
|
||
|
||
if bFixLayout then
|
||
begin
|
||
ViewStyle := vsReport;
|
||
Columns.Clear;
|
||
end;
|
||
|
||
// Clear content
|
||
Clear;
|
||
|
||
// Setup the columns
|
||
if Columns.count < 2 then
|
||
begin
|
||
aListColumn := Columns.Add;
|
||
aListColumn.Caption := iemsg(IEMSG_NAME);
|
||
aListColumn.Width := Width div 3; // 1/3 width
|
||
aListColumn := Columns.Add;
|
||
aListColumn.Caption := iemsg(IEMSG_VALUE);
|
||
aListColumn.Width := MulDiv(Width, 3, 2) - GetSystemMetrics(SM_CYVSCROLL) - Buffer_px; // 2/3 width less Scrollbar width
|
||
end;
|
||
end;
|
||
|
||
|
||
procedure _NewList(aListView: TListView; AMetaType : TIEMetaType; bReadOnly : Boolean);
|
||
var
|
||
i: integer;
|
||
aListItem: TListItem;
|
||
iRowMax: Integer;
|
||
sDescription: string;
|
||
begin
|
||
with aListView do
|
||
begin
|
||
InitializeList( False );
|
||
|
||
case AMetaType of
|
||
iemEXIF : iRowMax := High(ExifTags);
|
||
iemIPTC : iRowMax := High(IPTCTags);
|
||
iemDicom,
|
||
iemXMP : iRowMax := -1; // Handle at time of fill
|
||
else raise EIEException.create('Invalid');
|
||
end;
|
||
|
||
// fill the fields with the property names
|
||
for i := 0 to iRowMax do
|
||
begin
|
||
case AMetaType of
|
||
iemEXIF : sDescription := ExifTags[i].Desc;
|
||
iemIPTC : sDescription := IPTCTags[i].Desc;
|
||
else raise EIEException.create('Invalid');
|
||
end;
|
||
aListItem := Items.Add;
|
||
aListItem.Caption := sDescription;
|
||
aListItem.SubItems.Add('')
|
||
end;
|
||
|
||
ReadOnly := bReadOnly;
|
||
end;
|
||
end;
|
||
|
||
{!!
|
||
<FS>TListViewHelper.NewListForExif
|
||
|
||
<FM>Declaration<FC>
|
||
procedure NewListForExif;
|
||
|
||
<FM>Description<FN>
|
||
Set up a TListView for specifying values for EXIF fields (e.g. to a file without EXIF fields presently).
|
||
Two columns will be added with the left one containing property descriptions (using <A TIOParamsHelper.EXIF_FieldDescription>) and the right blank for field entry. The headings will read "Name" and "Value".
|
||
|
||
Notes:
|
||
- A standard TListView does not permit editing of subitems, so either download a TListView descendent that allows editing, or search for code snippets for "Edit Subitems TListView"
|
||
- You may wish to call <A TListViewHelper.InitializeList> before <FC>NewListForExif<FN> to automatically assign the optimal layout to the TListView
|
||
|
||
<FM>Example<FC>
|
||
// Display a TListView allowing user to add EXIF data
|
||
procedure TExifForm.FormCreate(Sender: TObject);
|
||
begin
|
||
// Fix List layout
|
||
MyExifListView.InitializeList;
|
||
|
||
// Add fields to List
|
||
MyExifListView.NewListForExif;
|
||
end;
|
||
!!}
|
||
procedure TListViewHelper.NewListForExif();
|
||
begin
|
||
_NewList(Self, iemEXIF, True);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TListViewHelper.NewListForIPTC
|
||
|
||
<FM>Declaration<FC>
|
||
procedure NewListForIPTC;
|
||
|
||
<FM>Description<FN>
|
||
Set up a TListView for specifying values for IPTC fields (e.g. to a file without IPTC fields presently).
|
||
Two columns will be added with the left one containing property descriptions and the right blank for field entry. The headings will read "Name" and "Value".
|
||
|
||
Notes:
|
||
- A standard TListView does not permit editing of subitems, so either download a TListView descendent that allows editing, or search for code snippets for "Edit Subitems TListView"
|
||
- Call <A TListViewHelper.InitializeList> before <FC>NewListForIPTC<FN> to automatically assign the optimal layout to the TListView
|
||
|
||
<FM>Example<FC>
|
||
// Display a TListView allowing user to add IPTC data
|
||
procedure TIPTCForm.FormCreate(Sender: TObject);
|
||
begin
|
||
// Fix List layout
|
||
MyIPTCListView.InitializeList;
|
||
|
||
// Add fields to List
|
||
MyIPTCListView.NewListForIPTC;
|
||
end;
|
||
!!}
|
||
// Formerly InitializeIPTCListView
|
||
procedure TListViewHelper.NewListForIPTC();
|
||
begin
|
||
_NewList(Self, iemIPTC, True);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TListViewHelper.ReadListFromExif
|
||
|
||
<FM>Declaration<FC>
|
||
function ReadListFromExif(IOParams : <A TIOParams>) : Boolean; overload;
|
||
function ReadListFromExif(const sFilename : string) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Fill a TListView with the EXIF properties of the current image, or one loaded from file.
|
||
Result is true if the file has any EXIF fields.
|
||
|
||
Note: You may wish to call <A TListViewHelper.InitializeList> before <FC>ReadListFromExif<FN> to automatically assign the optimal layout to the TListView
|
||
|
||
<FM>Examples<FC>
|
||
// Display the EXIF properties of the current image
|
||
MyExifListView.ReadListFromExif( ImageEnView1.IO.Params );
|
||
|
||
// Read-only display of EXIF properties of a file
|
||
MyExifListView.ReadListFromExif( 'C:\MyImage.jpeg', True );
|
||
!!}
|
||
function TListViewHelper.ReadListFromExif(IOParams : TIOParams) : Boolean;
|
||
begin
|
||
NewListForExif();
|
||
Result := _ReadFromEXIF_Params(Self, IOParams);
|
||
end;
|
||
|
||
function TListViewHelper.ReadListFromExif(const sFilename : string) : Boolean;
|
||
begin
|
||
NewListForExif();
|
||
Result := _ReadFromMeta_File(Self, iemEXIF, sFilename);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TListViewHelper.ReadListFromIPTC
|
||
|
||
<FM>Declaration<FC>
|
||
function ReadListFromIPTC(IOParams : <A TIOParams>) : Boolean; overload;
|
||
function ReadListFromIPTC(const sFilename : string) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Fill a TListView with the IPTC properties of the current image, or one loaded from file.
|
||
Result is true if the file has any IPTC fields specified.
|
||
|
||
Note: You may wish to call <A TListViewHelper.InitializeList> before <FC>ReadListFromIPTC<FN> to automatically assign the optimal layout to the TListView
|
||
|
||
<FM>Examples<FC>
|
||
// Display the IPTC properties of the current image
|
||
MyIPTCListView.ReadListFromIPTC( ImageEnView1.IO.Params );
|
||
|
||
// Read-only display of IPTC properties of a file
|
||
MyIPTCListView.ReadListFromIPTC( 'C:\MyImage.jpeg', True );
|
||
!!}
|
||
// Formerly LoadIPTCFields
|
||
function TListViewHelper.ReadListFromIPTC(IOParams : TIOParams) : Boolean;
|
||
begin
|
||
NewListForIPTC();
|
||
Result := _ReadFromIPTC_Params(Self, IOParams);
|
||
end;
|
||
|
||
function TListViewHelper.ReadListFromIPTC(const sFilename : string) : Boolean;
|
||
begin
|
||
NewListForIPTC();
|
||
Result := _ReadFromMeta_File(Self, iemIPTC, sFilename);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TListViewHelper.ReadListFromDicom
|
||
|
||
<FM>Declaration<FC>
|
||
function ReadListFromDicom(IOParams : <A TIOParams>; TagInclude: <A TIEDicomInclude>) : Boolean; overload;
|
||
function ReadListFromDicom(const sFilename : string; TagInclude: <A TIEDicomInclude>) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Fill a TListView with the Dicom properties of the current image, or one loaded from file. <FC>TagInclude<FN> allows you to filter the types of tags returned.
|
||
Result is true if the file has any Dicom fields specified.
|
||
|
||
Note: You may wish to call <A TListViewHelper.InitializeList> before <FC>ReadListFromDicom<FN> to automatically assign the optimal layout to the TListView
|
||
|
||
<FM>Examples<FC>
|
||
// Display the Dicom properties of the current image (all types)
|
||
MyDicomListView.ReadListFromDicom( ImageEnView1.IO.Params, [ diProprietary, diDeprecated, diChildTags, diUnknown ] );
|
||
|
||
// Display of Dicom properties of a file (excluding deprecated and unknown tags)
|
||
MyDicomListView.ReadListFromDicom( 'C:\MyImage.jpeg', [ diProprietary, diChildTags ] );
|
||
!!}
|
||
{$ifdef IEINCLUDEDICOM}
|
||
function TListViewHelper.ReadListFromDicom(IOParams : TIOParams; TagInclude: TIEDicomInclude) : Boolean;
|
||
begin
|
||
_NewList(Self, iemDicom, True);
|
||
Result := _ReadFromDicom_Params(Self, IOParams, TagInclude);
|
||
end;
|
||
{$endif}
|
||
|
||
{$ifdef IEINCLUDEDICOM}
|
||
function TListViewHelper.ReadListFromDicom(const sFilename : string; TagInclude: TIEDicomInclude) : Boolean;
|
||
begin
|
||
_NewList(Self, iemDicom, True);
|
||
Result := _ReadFromMeta_File(Self, iemDicom, sFilename, TagInclude);
|
||
end;
|
||
{$endif}
|
||
|
||
|
||
{!!
|
||
<FS>TListViewHelper.ReadListFromXMP
|
||
|
||
<FM>Declaration<FC>
|
||
function ReadListFromXMP(IOParams : <A TIOParams>) : Boolean; overload;
|
||
function ReadListFromXMP(const sFilename : string) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Fill a TListView with XMP properties of the current image, or one loaded from file.
|
||
Result is true if the file has XMP fields specified.
|
||
|
||
Note: Only <L Consts for Common XMP Fields>common XMP fields</L> are added
|
||
|
||
<FM>Examples<FC>
|
||
// Display the XMP properties of the current image
|
||
MyXMPListView.ReadListFromXMP( ImageEnView1.IO.Params );
|
||
|
||
// Display of XMP properties of a file (excluding deprecated and unknown tags)
|
||
MyXMPListView.ReadListFromXMP( 'C:\MyImage.jpeg' );
|
||
!!}
|
||
function TListViewHelper.ReadListFromXMP(IOParams : TIOParams) : Boolean;
|
||
begin
|
||
_NewList(Self, iemXMP, True);
|
||
Result := _ReadFromXMP_Params( Self, IOParams );
|
||
end;
|
||
|
||
function TListViewHelper.ReadListFromXMP(const sFilename : string) : Boolean;
|
||
begin
|
||
_NewList(Self, iemXMP, True);
|
||
Result := _ReadFromMeta_File( Self, iemXMP, sFilename );
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TListViewHelper.WriteListToExif
|
||
|
||
<FM>Declaration<FC>
|
||
function WriteListToExif(IOParams : <A TIOParams>) : Boolean; overload;
|
||
function WriteListToExif(const sFilename : string) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Write the changes made by a user to EXIF values in a TListView (which was initialized using <A TListViewHelper.NewListForExif> or <A TListViewHelper.ReadListFromExif>) to the current image or an image file.
|
||
Result is true if any changes were made to the EXIF properties (i.e. a result of false means the TListView EXIF content matches the file).
|
||
|
||
NOTE: A standard TListView does not permit editing of subitems, so either download a TListView descendent that allows editing, or search for code snippets for "Edit Subitems TListView"
|
||
|
||
Other Notes:
|
||
- For first overload, only the <A TIOParams> is updated, the changes are not saved to file.
|
||
- For the second overload, the file must already exist! If no changes were made to the EXIF data then the file is not modified
|
||
|
||
<FM>Examples<FC>
|
||
// Write changes to EXIF properties of the current image, and ask if the user wants to save changes if any fields were modified
|
||
if MyExifListView.WriteListToExif( ImageEnView1.IO.Params ) then
|
||
PromptToSaveFile;
|
||
|
||
// write EXIF changes to a file
|
||
MyExifListView.WriteListToExif( 'D:\MyImage.jpeg' );
|
||
!!}
|
||
function TListViewHelper.WriteListToExif(IOParams : TIOParams) : Boolean;
|
||
begin
|
||
Result := _WriteToEXIF_Params(Self, IOParams);
|
||
end;
|
||
|
||
function TListViewHelper.WriteListToExif(const sFilename : string) : Boolean;
|
||
begin
|
||
Result := _WriteToMeta_File(Self, iemEXIF, sFilename);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TListViewHelper.WriteListToIPTC
|
||
|
||
<FM>Declaration<FC>
|
||
function WriteListToIPTC(IOParams : <A TIOParams>) : Boolean; overload;
|
||
function WriteListToIPTC(const sFilename : string) : Boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Write the changes made by a user to IPTC values in a TListView (which was initialized using <A TListViewHelper.NewListForIPTC> or <A TListViewHelper.ReadListFromIPTC>) to the current image or an image file.
|
||
Result is true if any changes were made to the IPTC properties (i.e. a result of false means the TListView IPTC content matches the file).
|
||
|
||
NOTE: A standard TListView does not permit editing of subitems, so either download a TListView descendent that allows editing, or search for code snippets for "Edit Subitems TListView"
|
||
|
||
Other Notes:
|
||
- For first overload, only the <A TIOParams> is updated, the changes are not saved to file.
|
||
- For the second overload, the file must already exist! If no changes were made to the IPTC data then the file is not modified
|
||
|
||
<FM>Examples<FC>
|
||
// Write changes to IPTC properties of the current image, and ask if the user wants to save changes if any fields were modified
|
||
if MyIPTCListView.WriteListToIPTC( ImageEnView1.IO.Params ) then
|
||
PromptToSaveFile;
|
||
|
||
// write IPTC changes to a file
|
||
MyIPTCListView.WriteListToIPTC( 'D:\MyImage.jpeg' );
|
||
!!}
|
||
// Formerly SaveIPTCFields
|
||
function TListViewHelper.WriteListToIPTC(IOParams : TIOParams) : Boolean;
|
||
begin
|
||
Result := _WriteToIPTC_Params(Self, IOParams);
|
||
end;
|
||
|
||
function TListViewHelper.WriteListToIPTC(const sFilename : string) : Boolean;
|
||
begin
|
||
Result := _WriteToMeta_File(Self, iemIPTC, sFilename);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TListViewHelper.ClearListFields
|
||
|
||
<FM>Declaration<FC>
|
||
procedure ClearListFields;
|
||
|
||
<FM>Description<FN>
|
||
Clears all values in a TListView containing EXIF or IPTC properties, which was initialized using:
|
||
- <A TListViewHelper.NewListForExif>
|
||
- <A TListViewHelper.NewListForIPTC>
|
||
- <A TListViewHelper.ReadListFromExif>
|
||
- <A TListViewHelper.ReadListFromIPTC>
|
||
|
||
Note: Only clears the ListView, not EXIF/IPTC properties of a file
|
||
|
||
<FM>Examples<FC>
|
||
procedure TMainForm.btnResetListClick(Sender: TObject);
|
||
begin
|
||
// Clear all the specified values for our ListView
|
||
MyExifListView.ClearEXIFFields;
|
||
end;
|
||
!!}
|
||
procedure TListViewHelper.ClearListFields;
|
||
var
|
||
i: integer;
|
||
begin
|
||
for i := 0 to Items.Count - 1 do
|
||
Items.Item[i].SubItems[0] := '';
|
||
end;
|
||
|
||
{$endif}
|
||
{$endif}
|
||
|
||
|
||
|
||
{ TIOParamsHelper }
|
||
|
||
{$IFDEF Delphi2005orNewer}
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_Camera_Str
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_Camera_Str : string; (read/write)
|
||
|
||
<FM>Description<FN>
|
||
Returns a concatenation of <A TIOParams.EXIF_Make> and <A TIOParams.EXIF_Model>.
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_Camera_Str : AnsiString;
|
||
var
|
||
sMake, sModel: string;
|
||
begin
|
||
// EXIF_Make and EXIF_Model combined
|
||
sMake := RemoveNullA(EXIF_Make);
|
||
sModel := RemoveNullA(EXIF_Model);
|
||
|
||
// sometimes EXIF_Model already includes the make
|
||
if (sMake <> '') and (pos(sMake, sModel) > 0) then
|
||
sMake := '';
|
||
|
||
if ( sMake <> '' ) and ( sModel <> '' ) then
|
||
Result := AnsiString( sMake + ' ' + sModel )
|
||
else
|
||
Result := AnsiString( sMake + sModel );
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_XResolution_Str
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_XResolution_Str : string; (read/write)
|
||
|
||
<FM>Description<FN>
|
||
A string formatted version of <A TIOParams.EXIF_XResolution>. E.g. if EXIF_XResolution is 72 then EXIF_XResolution_Str returns '1/72'
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_XResolution_Str : AnsiString;
|
||
begin
|
||
// Display/Print resolution of image. Default value is 1/72inch, but it has no mean because personal computer doesn't use this value to display/print out
|
||
result := AnsiString( DoubleToFraction( EXIF_Xresolution ));
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_YResolution_Str
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_YResolution_Str : string; (read/write)
|
||
|
||
<FM>Description<FN>
|
||
A string formatted version of <A TIOParams.EXIF_YResolution>. E.g. if EXIF_YResolution is 72 then EXIF_YResolution_Str returns '1/72'
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_YResolution_Str : AnsiString;
|
||
begin
|
||
// Display/Print resolution of image. Default value is 1/72inch, but it has no mean because personal computer doesn't use this value to display/print out
|
||
result := AnsiString( DoubleToFraction( EXIF_Yresolution ));
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_SubjectArea_Str
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_SubjectArea_Str : string; (read-only)
|
||
|
||
<FM>Description<FN>
|
||
A string formatted version of <A TIOParams.EXIF_SubjectArea>.
|
||
|
||
Example results:
|
||
"Point at 100,200"
|
||
"Circle of 50 centered at 100,200"
|
||
"Rectangle of 50,50 centered at 100,200"
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_SubjectArea_Str : string;
|
||
begin
|
||
Result := '';
|
||
|
||
{
|
||
Subject Area
|
||
Specifies the location and area of the main subject in the overall scene. EXIF_SubjectArea has either 2, 3, or 4 values, so Index can be 0 to 3.
|
||
|
||
The subject location and area are defined by Count values as follows:
|
||
Count = 2: Indicates the location of the main subject as coordinates. The first value is the X coordinate and the second is the Y coordinate.
|
||
Count = 3: The area of the main subject is given as a circle. The circular area is expressed as center coordinates and diameter. The first value is the center X coordinate, the second is the center Y coordinate, and the third is the diameter.
|
||
Count = 4: The area of the main subject is given as a rectangle. The rectangular area is expressed as center coordinates and area dimensions. The first value is the center X coordinate, the second is the center Y coordinate, the third is the width of the area, and the fourth is the height of the area.
|
||
}
|
||
|
||
// Can have 2, 3 or 4 values
|
||
if EXIF_SubjectArea[ 3 ] <> -1 then
|
||
// The area of the main subject is given as a rectangle. The rectangular area is expressed as center coordinates and area dimensions. The first value is the center X coordinate, the second is the center Y coordinate, the third is the width of the area, and the fourth is the height of the area.
|
||
// 'Rectangle of %d,%d centered at %d,%d'
|
||
Result := Format( s_RectangleOfXByXCenteredAtXByX,
|
||
[ EXIF_SubjectArea[ 2 ],
|
||
EXIF_SubjectArea[ 3 ],
|
||
EXIF_SubjectArea[ 0 ],
|
||
EXIF_SubjectArea[ 1 ] ])
|
||
else
|
||
if EXIF_SubjectArea[ 2 ] <> -1 then
|
||
// The area of the main subject is given as a circle. The circular area is expressed as center coordinates and diameter. The first value is the center X coordinate, the second is the center Y coordinate, and the third is the diameter.
|
||
// 'Circle of %d centered at %d,%d'
|
||
Result := Format( s_CircleOfXCenteredAtAtXByX,
|
||
[ EXIF_SubjectArea[ 2 ],
|
||
EXIF_SubjectArea[ 0 ],
|
||
EXIF_SubjectArea[ 1 ] ])
|
||
else
|
||
if EXIF_SubjectArea[ 1 ] <> -1 then
|
||
// Location of the main subject as coordinates. The first value is the X coordinate and the second is the Y coordinate.
|
||
// 'Point at %d,%d'
|
||
Result := Format( s_PointAtXByX,
|
||
[ EXIF_SubjectArea[ 0 ],
|
||
EXIF_SubjectArea[ 1 ] ]);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_SubjectLocation_Str
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_SubjectLocation_Str : string; (read/write)
|
||
|
||
<FM>Description<FN>
|
||
A string formatted version of <A TIOParams.EXIF_SubjectLocationX> and <A TIOParams.EXIF_SubjectLocationY>, e.g. "150,250"
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_SubjectLocation_Str : string;
|
||
begin
|
||
Result := '';
|
||
if ( EXIF_SubjectLocationX <> -1 ) and ( EXIF_SubjectLocationY <> -1 ) then
|
||
Result := IntToStr( EXIF_SubjectLocationX ) + ',' + IntToStr( EXIF_SubjectLocationY );
|
||
end;
|
||
|
||
procedure TIOParamsHelper.SetEXIF_SubjectLocation_Str(Value : string);
|
||
var
|
||
sLocationX, sLocationY : string;
|
||
begin
|
||
sLocationX := GetTextBeforeChar( Value, ',', True );
|
||
if sLocationX = '' then
|
||
EXIF_SubjectLocationX := -1
|
||
else
|
||
EXIF_SubjectLocationX := StrToInt( sLocationX );
|
||
|
||
sLocationY := GetTextAfterChar ( Value, ',', True );
|
||
if sLocationY = '' then
|
||
EXIF_SubjectLocationY := -1
|
||
else
|
||
EXIF_SubjectLocationY := StrToInt( sLocationY );
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_ExposureTime_Str
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_ExposureTime_Str : string; (read/write)
|
||
|
||
<FM>Description<FN>
|
||
A string formatted version of <A TIOParams.EXIF_ExposureTime>. E.g. if EXIF_ExposureTime is 4 then EXIF_ExposureTime_Str returns '4' (seconds). If EXIF_ExposureTime is 0.25 then it returns '1/4' (of a second).
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_ExposureTime_Str : string;
|
||
var
|
||
iExposureTime: double;
|
||
begin
|
||
// Exposure time (reciprocal of shutter speed). Unit is seconds
|
||
iExposureTime := EXIF_ExposureTime;
|
||
|
||
if iExposureTime > 1 then
|
||
// then it will be something like 4 i.e. 4 seconds
|
||
result := inttostr(round(iExposureTime))
|
||
else
|
||
if (iExposureTime > 0) then
|
||
// then it is an integer second value, e.g. 0.25, which translates to 1/4 second
|
||
result := DoubleToFraction(round(1 / iExposureTime));
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_FNumber_Str
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_FNumber_Str : string; (read/write)
|
||
|
||
<FM>Description<FN>
|
||
A string formatted version of <A TIOParams.EXIF_FNumber>. <FC>EXIF_FNumber_Str<FN> simply prefixes an 'F' for valid values, e.g. if <FC>EXIF_FNumber<FN> is 5.6, this property would return 'F5.6'
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_FNumber_Str : string;
|
||
begin
|
||
// The actual F-number(F-stop) of lens when the image was taken
|
||
result := '';
|
||
if (EXIF_Fnumber <> 0) and (EXIF_Fnumber <> -1) then
|
||
result := 'F' + FloatToStrOrNull( EXIF_FNumber );
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_ShutterSpeedValue_Str
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_ShutterSpeedValue_Str : string; (read/write)
|
||
|
||
<FM>Description<FN>
|
||
A string formatted version of <A TIOParams.EXIF_ShutterSpeedValue>. Returns the value as a formatted fraction or number, e.g. '1/4' of a second or '2' (seconds).
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_ShutterSpeedValue_Str : string;
|
||
begin
|
||
// Shutter speed by APEX value. To convert this value to ordinary 'Shutter Speed'; calculate this value's power of 2, then reciprocal. For example, if the ShutterSpeedValue is '4', shutter speed is 1/(24)=1/16 second
|
||
result := ApexToStr(2, EXIF_ShutterSpeedValue, '1/');
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_ApertureValue_Str
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_ApertureValue_Str : string; (read/write)
|
||
|
||
<FM>Description<FN>
|
||
A string formatted version of <A TIOParams.EXIF_ApertureValue>. <FC>EXIF_ApertureValue<FN> is an Apex value which can be difficult to calculate. This property returns a human readible format, e.g. if <FC>EXIF_ApertureValue<FN> is 5, then 'F5.6' will be returned.
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_ApertureValue_Str : string;
|
||
begin
|
||
// The actual aperture value of lens when the image was taken. Unit is APEX. To convert this value to
|
||
// ordinary F-number (F-stop), calculate this value's power of root 2 (=1.4142). For example, if the
|
||
// ApertureValue is '5', F-number is 1.41425 = F5.6.
|
||
result := ApexToStr(Sqrt(2), EXIF_ApertureValue, 'F');
|
||
if Result = 'F0' then
|
||
result := '';
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_MaxApertureValue_Str
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_MaxApertureValue_Str : string; (read/write)
|
||
|
||
<FM>Description<FN>
|
||
A string formatted version of <A TIOParams.EXIF_MaxApertureValue>. <FC>EXIF_MaxApertureValue<FN> is an Apex value which can be difficult to calculate. This property returns a human readible format, e.g. if <FC>EXIF_MaxApertureValue<FN> is 5, then 'F5.6' will be returned.
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_MaxApertureValue_Str : string;
|
||
begin
|
||
// Maximum aperture value of lens. You can convert to F-number by calculating power of root 2 (same process of ApertureValue)
|
||
result := ApexToStr(Sqrt(2), EXIF_MaxApertureValue, 'F');
|
||
if Result = 'F0' then
|
||
result := '';
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_AsStr
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_AsStr [index : Integer]: string; (read/write)
|
||
|
||
<FM>Description<FN>
|
||
Provides an alternative way to access EXIF properties in batch situations. Each property is available as a human-readible string value, and in most cases write access is also supported.
|
||
|
||
Index is a value between 0 and <FC>_EXIF_Tag_Count<FN> - 1 and can be referred to by <L EXIF Consts for EXIF_AsStr>constants</L>.
|
||
|
||
<TABLE>
|
||
<R> <H>Const</H> <H>Description</H> <H>Writeable?</H> <H>Output</H> </R>
|
||
<R> <C><FC>_EXIF_UserComment<FN></C> <C>User Comment</C> <C>YES</C> <C><A TIOParams.EXIF_UserComment></C> </R>
|
||
<R> <C><FC>_EXIF_ImageDescription<FN></C> <C>Description</C> <C>YES</C> <C><A TIOParams.EXIF_ImageDescription></C> </R>
|
||
<R> <C><FC>_EXIF_Make<FN></C> <C>Camera Make</C> <C>YES</C> <C><A TIOParams.EXIF_Make></C> </R>
|
||
<R> <C><FC>_EXIF_Model<FN></C> <C>Camera Model</C> <C>YES</C> <C><A TIOParams.EXIF_Model></C> </R>
|
||
<R> <C><FC>_EXIF_XResolution<FN></C> <C>Horizontal Resolution</C> <C>YES</C> <C><A TIOParamsHelper.EXIF_YResolution_Str> with <L TIOParams.EXIF_ResolutionUnit>unit</L></C> </R>
|
||
<R> <C><FC>_EXIF_YResolution<FN></C> <C>Vertical Resolution</C> <C>YES</C> <C><A TIOParamsHelper.EXIF_XResolution_Str> with <L TIOParams.EXIF_ResolutionUnit>unit</L></C> </R>
|
||
<R> <C><FC>_EXIF_DateTime<FN></C> <C>Date and Time</C> <C>YES</C> <C>DateTimeToStr(<A TIOParams.EXIF_DateTime2>)</C> </R>
|
||
<R> <C><FC>_EXIF_DateTimeOriginal<FN></C> <C>Original Date and Time</C> <C>YES</C> <C>DateTimeToStr(<A TIOParams.EXIF_DateTimeOriginal2>)</C> </R>
|
||
<R> <C><FC>_EXIF_DateTimeDigitized<FN></C> <C>Digitized Date and Time</C> <C>YES</C> <C>DateTimeToStr(<A TIOParams.EXIF_DateTimeDigitized2>)</C> </R>
|
||
<R> <C><FC>_EXIF_Copyright<FN></C> <C>Copyright</C> <C>YES</C> <C><A TIOParams.EXIF_Copyright></C> </R>
|
||
<R> <C><FC>_EXIF_Orientation<FN></C> <C>Orientation</C> <C>YES</C> <C>Text description of <A TIOParams.EXIF_Orientation></C> </R>
|
||
<R> <C><FC>_EXIF_ExposureTime<FN></C> <C>Exposure Time</C> <C>YES</C> <C><A TIOParamsHelper.EXIF_ExposureTime_Str> seconds</C> </R>
|
||
<R> <C><FC>_EXIF_FNumber<FN></C> <C>F-Stop</C> <C>YES</C> <C><A TIOParamsHelper.EXIF_Fnumber_Str></C> </R>
|
||
<R> <C><FC>_EXIF_ExposureProgram<FN></C> <C>Exposure Program</C> <C>YES</C> <C>Text description of <A TIOParams.EXIF_ExposureProgram></C> </R>
|
||
<R> <C><FC>_EXIF_ISOSpeedRatings<FN></C> <C>ISO Speed Rating</C> <C>YES</C> <C><A TIOParams.EXIF_ISOSpeedRatings></C> </R>
|
||
<R> <C><FC>_EXIF_ShutterSpeedValue<FN></C> <C>Shutter Speed</C> <C>YES</C> <C><A TIOParamsHelper.EXIF_ShutterSpeedValue_Str></C> </R>
|
||
<R> <C><FC>_EXIF_ApertureValue<FN></C> <C>Aperture Value</C> <C>YES</C> <C><A TIOParamsHelper.EXIF_ApertureValue_Str></C> </R>
|
||
<R> <C><FC>_EXIF_BrightnessValue<FN></C> <C>Brightness</C> <C>YES</C> <C>FloatToStr(<A TIOParams.EXIF_BrightnessValue>)</C> </R>
|
||
<R> <C><FC>_EXIF_ExposureBiasValue<FN></C> <C>Exposure Compensation</C> <C>YES</C> <C>FloatToStr(<A TIOParams.EXIF_ExposureBiasValue>)</C> </R>
|
||
<R> <C><FC>_EXIF_MaxApertureValue<FN></C> <C>Max Aperture Value</C> <C>YES</C> <C><A TIOParamsHelper.EXIF_MaxApertureValue_Str></C> </R>
|
||
<R> <C><FC>_EXIF_SubjectDistance<FN></C> <C>Subject Distance</C> <C>YES</C> <C>FloatToStr(<A TIOParams.EXIF_SubjectDistance>) m</C> </R>
|
||
<R> <C><FC>_EXIF_MeteringMode<FN></C> <C>Metering Mode</C> <C>YES</C> <C>Text description of <A TIOParams.EXIF_MeteringMode></C> </R>
|
||
<R> <C><FC>_EXIF_LightSource<FN></C> <C>Lighting</C> <C>YES</C> <C>Text description of <A TIOParams.EXIF_LightSource></C> </R>
|
||
<R> <C><FC>_EXIF_Flash<FN></C> <C>Flash</C> <C>YES</C> <C>Text description of <A TIOParams.EXIF_Flash></C> </R>
|
||
<R> <C><FC>_EXIF_FocalLength<FN></C> <C>Focal Length</C> <C>YES</C> <C>FloatToStr(<A TIOParams.EXIF_FocalLength>) mm</C> </R>
|
||
<R> <C><FC>_EXIF_FlashPixVersion<FN></C> <C>FlashPix Version</C> <C>YES</C> <C><A TIOParams.EXIF_FlashPixVersion></C> </R>
|
||
<R> <C><FC>_EXIF_ColorSpace<FN></C> <C>Color Space</C> <C>YES</C> <C>Text description of <A TIOParams.EXIF_ColorSpace></C> </R>
|
||
<R> <C><FC>_EXIF_ExifImageWidth<FN></C> <C>Image Width</C> <C>YES</C> <C><A TIOParams.EXIF_EXIFImageWidth></C> </R>
|
||
<R> <C><FC>_EXIF_ExifImageHeight<FN></C> <C>Image Height</C> <C>YES</C> <C><A TIOParams.EXIF_EXIFImageHeight></C> </R>
|
||
<R> <C><FC>_EXIF_RelatedSoundFile<FN></C> <C>Sound File</C> <C>YES</C> <C><A TIOParams.EXIF_RelatedSoundFile></C> </R>
|
||
<R> <C><FC>_EXIF_FocalPlaneXResolution<FN></C> <C>Focal Plane Horz. Resolution</C> <C>YES</C> <C>FloatToStr(<A TIOParams.EXIF_FocalPlaneXResolution>) with <L TIOParams.EXIF_FocalPlaneResolutionUnit>unit</L></C> </R>
|
||
<R> <C><FC>_EXIF_FocalPlaneYResolution<FN></C> <C>Focal Plane Vert. Resolution</C> <C>YES</C> <C>FloatToStr(<A TIOParams.EXIF_FocalPlaneYResolution>) with <L TIOParams.EXIF_FocalPlaneResolutionUnit>unit</L></C> </R>
|
||
<R> <C><FC>_EXIF_ExposureIndex<FN></C> <C>Exposure Index</C> <C>YES</C> <C>FloatToStr(<A TIOParams.EXIF_ExposureIndex>)</C> </R>
|
||
<R> <C><FC>_EXIF_SensingMethod<FN></C> <C>Sensing Method</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_SensingMethod></C> </R>
|
||
<R> <C><FC>_EXIF_FileSource<FN></C> <C>File Source</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_FileSource></C> </R>
|
||
<R> <C><FC>_EXIF_SceneType<FN></C> <C>Scene Type</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_SceneType></C> </R>
|
||
<R> <C><FC>_EXIF_YCbCrPositioning<FN></C> <C>Data Point</C> <C>YES</C> <C>Text description of <A TIOParams.EXIF_YCbCrPositioning></C> </R>
|
||
<R> <C><FC>_EXIF_ExposureMode<FN></C> <C>Exposure Mode</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_ExposureMode></C> </R>
|
||
<R> <C><FC>_EXIF_WhiteBalance<FN></C> <C>White Balance</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_WhiteBalance></C> </R>
|
||
<R> <C><FC>_EXIF_DigitalZoomRatio<FN></C> <C>Digital Zoom Ratio</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_DigitalZoomRatio></C> </R>
|
||
<R> <C><FC>_EXIF_FocalLengthIn35mmFilm<FN></C> <C>Focal Length in 35mm Film</C> <C>no</C> <C>IntToStr(<A TIOParams.EXIF_FocalLengthIn35mmFilm>) mm</C> </R>
|
||
<R> <C><FC>_EXIF_SceneCaptureType <FN></C> <C>Scene Capture Type</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_SceneCaptureType></C> </R>
|
||
<R> <C><FC>_EXIF_GainControl<FN></C> <C>Gain Control</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_GainControl></C> </R>
|
||
<R> <C><FC>_EXIF_Contrast<FN></C> <C>Contrast</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_Contrast></C> </R>
|
||
<R> <C><FC>_EXIF_Saturation<FN></C> <C>Saturation</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_Saturation></C> </R>
|
||
<R> <C><FC>_EXIF_Sharpness<FN></C> <C>Sharpness</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_Sharpness></C> </R>
|
||
<R> <C><FC>_EXIF_SubjectDistanceRange<FN></C> <C>Subject Distance</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_SubjectDistanceRange></C> </R>
|
||
<R> <C><FC>_EXIF_GPSLatitude<FN></C> <C>GPS Latitude</C> <C>no</C> <C><A TIOParams.EXIF_GPSLatitude_Str></C> </R>
|
||
<R> <C><FC>_EXIF_GPSLongitude<FN></C> <C>GPS Longitude</C> <C>no</C> <C><A TIOParams.EXIF_GPSLongitude_Str></C> </R>
|
||
<R> <C><FC>_EXIF_GPSAltitude<FN></C> <C>GPS Altitude</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_GPSAltitude> and <A TIOParams.EXIF_GPSAltitudeRef></C> </R>
|
||
<R> <C><FC>_EXIF_GPSImageDirection<FN></C> <C>GPS Image Direction</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_GPSImgDirection> and <A TIOParams.EXIF_GPSImgDirectionRef></C> </R>
|
||
<R> <C><FC>_EXIF_GPSTrack<FN></C> <C>GPS Movement Direction</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_GPSTrack> and <A TIOParams.EXIF_GPSTrackRef></C> </R>
|
||
<R> <C><FC>_EXIF_GPSSpeed<FN></C> <C>GPS Movement Speed</C> <C>no</C> <C>Text description of <A TIOParams.EXIF_GPSSpeed> and <A TIOParams.EXIF_GPSSpeedRef></C> </R>
|
||
<R> <C><FC>_EXIF_GPSDateAndTime<FN></C> <C>GPS Date and Time</C> <C>no</C> <C><A TIOParams.EXIF_GPSDateStamp></C> </R>
|
||
<R> <C><FC>_EXIF_GPSSatellites<FN></C> <C>GPS Satellites</C> <C>YES</C> <C><A TIOParams.EXIF_GPSSatellites></C> </R>
|
||
<R> <C><FC>_EXIF_GPSVersionID<FN></C> <C>GPS Version</C> <C>YES</C> <C><A TIOParams.EXIF_GPSVersionID></C> </R>
|
||
<R> <C><FC>_EXIF_Artist<FN></C> <C>Artist</C> <C>YES</C> <C><A TIOParams.EXIF_Artist></C> </R>
|
||
<R> <C><FC>_EXIF_XPTitle<FN></C> <C>Title (Windows)</C> <C>YES</C> <C><A TIOParams.EXIF_XPTitle></C> </R>
|
||
<R> <C><FC>_EXIF_XPComment<FN></C> <C>Comment (Windows)</C> <C>YES</C> <C><A TIOParams.EXIF_XPComment></C> </R>
|
||
<R> <C><FC>_EXIF_XPAuthor<FN></C> <C>Author (Windows)</C> <C>YES</C> <C><A TIOParams.EXIF_XPAuthor></C> </R>
|
||
<R> <C><FC>_EXIF_XPKeywords<FN></C> <C>Keywords (Windows)</C> <C>YES</C> <C><A TIOParams.EXIF_XPKeywords></C> </R>
|
||
<R> <C><FC>_EXIF_XPSubject<FN></C> <C>Subject (Windows)</C> <C>YES</C> <C><A TIOParams.EXIF_XPSubject></C> </R>
|
||
<R> <C><FC>_EXIF_XPRating<FN></C> <C>Rating (Windows)</C> <C>YES</C> <C>IntToStr(<A TIOParams.EXIF_XPRating>)</C> </R>
|
||
<R> <C><FC>_EXIF_InteropVersion<FN></C> <C>Interoperability Version</C> <C>YES</C> <C><A TIOParams.EXIF_InteropVersion></C> </R>
|
||
<R> <C><FC>_EXIF_CameraOwnerName<FN></C> <C>Camera Owner Name</C> <C>YES</C> <C><A TIOParams.EXIF_CameraOwnerName></C> </R>
|
||
<R> <C><FC>_EXIF_BodySerialNumber<FN></C> <C>Body Serial Number</C> <C>YES</C> <C><A TIOParams.EXIF_BodySerialNumber></C> </R>
|
||
<R> <C><FC>_EXIF_LensMake<FN></C> <C>Lens Make</C> <C>YES</C> <C><A TIOParams.EXIF_LensMake></C> </R>
|
||
<R> <C><FC>_EXIF_LensModel<FN></C> <C>Lens Model</C> <C>YES</C> <C><A TIOParams.EXIF_LensModel></C> </R>
|
||
<R> <C><FC>_EXIF_LensSerialNumber<FN></C> <C>Lens Serial Number</C> <C>YES</C> <C><A TIOParams.EXIF_LensSerialNumber></C> </R>
|
||
<R> <C><FC>_EXIF_Gamma<FN></C> <C>Gamma</C> <C>YES</C> <C>FloatToStr(<A TIOParams.EXIF_Gamma>)</C> </R>
|
||
<R> <C><FC>_EXIF_SubjectArea<FN></C> <C>Subject Area</C> <C>no</C> <C><A TIOParamsHelper.EXIF_SubjectArea_Str></C> </R>
|
||
<R> <C><FC>_EXIF_SubjectLocation<FN></C> <C>Subject Location</C> <C>YES</C> <C><A TIOParamsHelper.EXIF_SubjectLocation_Str></C> </R>
|
||
</TABLE>
|
||
|
||
<FM>See Also<FN>
|
||
- <A TIOParamsHelper.EXIF_FieldDescription>
|
||
|
||
<FM>Examples<FC>
|
||
// Output all fields of current image to a memo (same as <A TIOParamsHelper.EXIF_WriteToStrings>)
|
||
for i := 0 to _EXIF_Tag_Count - 1 do
|
||
memo1.Lines.Add( ImageEnView1.IO.Params.EXIF_FieldDescription[ i ] + ': ' + ImageEnView1.IO.Params.EXIF_AsStr[ i ] );
|
||
|
||
// Set EXIF_ShutterSpeedValue to 1/4 a second
|
||
ImageEnView1.IO.Params.EXIF_AsStr[ _EXIF_ShutterSpeedValue ] := '1/4';
|
||
!!}
|
||
// get a string representation of the exif data specified by the field index
|
||
function TIOParamsHelper.GetEXIF_AsStr(Index: Integer): string;
|
||
|
||
function _DateTimeToStrOrNull(aDate : TDateTime): string;
|
||
begin
|
||
Result := '';
|
||
if aDate <> 0 then
|
||
result := DateTimeToStr(aDate)
|
||
end;
|
||
|
||
var
|
||
sFPUnit: string; // used in retrieval of EXIF data (resolution unit)
|
||
sResUnit: string; // used in retrieval of EXIF data (resolution unit)
|
||
begin
|
||
result := '';
|
||
try
|
||
case Index of
|
||
|
||
_EXIF_UserComment: result := RemoveNull(EXIF_UserComment);
|
||
_EXIF_ImageDescription: result := RemoveNullA(EXIF_ImageDescription);
|
||
_EXIF_CameraMake : Result := String( EXIF_Make );
|
||
_EXIF_CameraModel: Result := String( EXIF_Model );
|
||
|
||
{
|
||
Unit of XResolution/YResolution:
|
||
1 means no-unit
|
||
2 means inch
|
||
3 means centimeter
|
||
Default value is 2 (inch)
|
||
}
|
||
_EXIF_XResolution: { EXIF_XResolution and EXIF_ResolutionUnit }
|
||
begin
|
||
case EXIF_ResolutionUnit of
|
||
2: sResUnit := s_Inch;
|
||
3: sResUnit := s_CM;
|
||
else
|
||
sResUnit := '';
|
||
end;
|
||
result := String( EXIF_XResolution_Str ) + ' ' + sResUnit;
|
||
end;
|
||
|
||
{
|
||
Unit of XResolution/YResolution:
|
||
1 means no-unit
|
||
2 means inch
|
||
3 means centimeter
|
||
Default value is 2 (inch)
|
||
}
|
||
_EXIF_YResolution: { EXIF_YResolution and EXIF_ResolutionUnit }
|
||
begin
|
||
case EXIF_ResolutionUnit of
|
||
2: sResUnit := s_Inch;
|
||
3: sResUnit := s_CM;
|
||
else
|
||
sResUnit := '';
|
||
end;
|
||
|
||
result := String( EXIF_YResolution_Str ) + ' ' + sResUnit;
|
||
end;
|
||
|
||
_EXIF_DateTime: result := _DateTimeToStrOrNull(EXIF_DateTime2);
|
||
_EXIF_DateTimeOriginal: result := _DateTimeToStrOrNull(EXIF_DateTimeOriginal2);
|
||
_EXIF_DateTimeDigitized: result := _DateTimeToStrOrNull(EXIF_DateTimeDigitized2);
|
||
|
||
_EXIF_Copyright: result := RemoveNullA(EXIF_Copyright);
|
||
|
||
_EXIF_Orientation:
|
||
case EXIF_Orientation of
|
||
1: result := s_EXIFOrientation1;
|
||
2: result := s_EXIFOrientation2;
|
||
3: result := s_EXIFOrientation3;
|
||
4: result := s_EXIFOrientation4;
|
||
5: result := s_EXIFOrientation5;
|
||
6: result := s_EXIFOrientation6;
|
||
7: result := s_EXIFOrientation7;
|
||
8: result := s_EXIFOrientation8;
|
||
end;
|
||
|
||
_EXIF_ExposureTime:
|
||
begin
|
||
result := EXIF_ExposureTime_Str;
|
||
if result <> '' then
|
||
begin
|
||
if Pos('1/', result) > 0 then
|
||
result := result + ' ' + s_Second
|
||
else
|
||
result := result + ' ' + s_Seconds
|
||
end;
|
||
end;
|
||
|
||
_EXIF_FNumber: Result := EXIF_FNumber_Str;
|
||
|
||
{
|
||
EXIF_ExposureProgram:
|
||
1 means manual control
|
||
2 program normal
|
||
3 aperture priority
|
||
4 shutter priority
|
||
5 program creative (slow program)
|
||
6 program action(high-speed program)
|
||
7 portrait mode
|
||
8 landscape mode.
|
||
}
|
||
_EXIF_ExposureProgram:
|
||
case EXIF_ExposureProgram of
|
||
1: result := s_ManualControl;
|
||
2: result := s_ProgramNormal;
|
||
3: result := s_AperturePriority;
|
||
4: result := s_ShutterPriority;
|
||
5: result := s_CreativeProgram;
|
||
6: result := s_ActionProgram;
|
||
7: result := s_Portraitmode;
|
||
8: result := s_LandscapeMode;
|
||
end;
|
||
|
||
// CCD sensitivity equivalent to Ag-Hr film speedrate.
|
||
_EXIF_ISOSpeedRatings:
|
||
if (EXIF_ISOSpeedRatings[0] <> 0) and (EXIF_ISOSpeedRatings[0] <> -1) then
|
||
result := inttostr(EXIF_ISOSpeedRatings[0]);
|
||
|
||
_EXIF_ShutterSpeedValue: result := EXIF_ShutterSpeedValue_Str;
|
||
_EXIF_ApertureValue: result := EXIF_ApertureValue_Str;
|
||
|
||
{
|
||
Brightness of taken subject, unit is APEX. To calculate Exposure(Ev) from BrigtnessValue(Bv), you must add SensitivityValue(Sv).
|
||
Ev=Bv+Sv Sv=log2(ISOSpeedRating/3.125)
|
||
ISO100 : Sv=5, ISO200 : Sv=6, ISO400 : Sv=7, ISO125 : Sv=5.32.
|
||
}
|
||
_EXIF_BrightnessValue: Result := FloatToStrOrNull( EXIF_BrightnessValue );
|
||
|
||
_EXIF_ExposureBiasValue: result := FloatToStrOrNull( EXIF_ExposureBiasValue );
|
||
_EXIF_MaxApertureValue: result := EXIF_MaxApertureValue_Str;
|
||
|
||
// Distance to focus point, unit is meter.
|
||
_EXIF_SubjectDistance:
|
||
if EXIF_SubjectDistance > 0 then
|
||
result := FloatToStrOrNull( EXIF_SubjectDistance, ' m' );
|
||
|
||
{
|
||
Exposure metering method:
|
||
0 means unknown
|
||
1 average
|
||
2 center weighted average
|
||
3 spot
|
||
4 multi-spot
|
||
5 multi-segment
|
||
6 partial
|
||
255 other.
|
||
}
|
||
_EXIF_MeteringMode:
|
||
case EXIF_MeteringMode of
|
||
1: result := s_average;
|
||
2: result := s_CenterWeightedAverage;
|
||
3: result := s_Spot;
|
||
4: result := s_MultiSpot;
|
||
5: result := s_MultiSegment;
|
||
6: result := s_partial;
|
||
end;
|
||
|
||
{
|
||
Light source, actually this means white balance setting:
|
||
0 means unknown
|
||
1 daylight
|
||
2 fluorescent
|
||
3 tungsten
|
||
10 flash
|
||
17 standard light A
|
||
18 standard light B
|
||
19 standard light C
|
||
20 D55
|
||
21 D65
|
||
22 D75
|
||
255 other.
|
||
}
|
||
_EXIF_LightSource:
|
||
case EXIF_LightSource of
|
||
1: result := s_daylight;
|
||
2: result := s_fluorescent;
|
||
3: result := s_tungsten;
|
||
10: result := s_flash;
|
||
17: result := s_standardLightA;
|
||
18: result := s_standardLightB;
|
||
19: result := s_standardLightC;
|
||
20: result := s_D55;
|
||
21: result := s_D65;
|
||
22: result := s_D75;
|
||
end;
|
||
|
||
{
|
||
EXIF_Flash:
|
||
0 means flash did not fire
|
||
1 flash fired
|
||
5 flash fired but strobe return light not detected
|
||
7 flash fired and strobe return light detected
|
||
}
|
||
_EXIF_Flash: result := FlashModeToString(EXIF_Flash);
|
||
|
||
// Focal length of lens used to take image. Unit is millimeter.
|
||
_EXIF_FocalLength:
|
||
if EXIF_FocalLength > 0 then
|
||
result := FloatToStrOrNull( EXIF_FocalLength, ' mm' );
|
||
|
||
// Stores FlashPix version. If the image data is based on FlashPix formar Ver.1.0, value is "0100".
|
||
_EXIF_FlashPixVersion: result := RemoveNullA(EXIF_FlashPixVersion);
|
||
|
||
// Defines Color Space. DCF image must use sRGB color space so value is always '1'. If the picture uses the other color space, value is '65535' : Uncalibrated.
|
||
_EXIF_ColorSpace:
|
||
case EXIF_ColorSpace of
|
||
1: result := s_RGB;
|
||
65535: result := s_Uncalibrated;
|
||
end;
|
||
|
||
_EXIF_ExifImageWidth : if EXIF_ExifImageWidth > 0 then
|
||
result := IntToStr(EXIF_ExifImageWidth);
|
||
_EXIF_ExifImageHeight : if EXIF_ExifImageHeight > 0 then
|
||
result := IntToStr(EXIF_ExifImageHeight);
|
||
|
||
// If this digicam can record audio data with image, shows name of audio data.
|
||
_EXIF_RelatedSoundFile: result := RemoveNullA(EXIF_RelatedSoundFile);
|
||
|
||
{
|
||
Unit of FocalPlaneXResoluton/FocalPlaneYResolution:
|
||
1 means no-unit
|
||
2 inch
|
||
3 centimeter.
|
||
Note : Some of Fujifilm's digicam(e.g.FX2700, FX2900, Finepix4700Z/40i etc) uses value '3' so it must be 'centimeter', but it seems that they use a '8.3mm?'(1/3in.?) to their ResolutionUnit. Fuji's BUG? Finepix4900Z has been changed to use value '2' but it doesn't match to actual value also.
|
||
}
|
||
_EXIF_FocalPlaneXResolution:
|
||
begin
|
||
case EXIF_FocalPlaneResolutionUnit of
|
||
2: sFPUnit := s_PerInch;
|
||
3: sFPUnit := s_PerCM;
|
||
else
|
||
sFPUnit := '';
|
||
end;
|
||
|
||
// Pixel density at CCD's position. If you have MegaPixel digicam and take a picture by lower resolution(e.g.VGA mode), this value is re-sampled by picture resolution. In such case, FocalPlaneResolution is not same as CCD's actual resolution.
|
||
if EXIF_FocalPlaneXResolution > 50 then
|
||
result := IntToStr(Trunc(EXIF_FocalPlaneXResolution)) + sFPUnit
|
||
else
|
||
if EXIF_FocalPlaneXResolution > 0 then
|
||
result := IEFloatToFormatString(EXIF_FocalPlaneXResolution, 2, true) + sFPUnit;
|
||
end;
|
||
|
||
_EXIF_FocalPlaneYResolution:
|
||
begin
|
||
case EXIF_FocalPlaneResolutionUnit of
|
||
2: sFPUnit := s_PerInch;
|
||
3: sFPUnit := s_PerCM;
|
||
else
|
||
sFPUnit := '';
|
||
end;
|
||
|
||
// Pixel density at CCD's position. If you have MegaPixel digicam and take a picture by lower resolution(e.g.VGA mode), this value is re-sampled by picture resolution. In such case, FocalPlaneResolution is not same as CCD's actual resolution.
|
||
if EXIF_FocalPlaneYResolution > 50 then
|
||
result := IntToStr(Trunc(EXIF_FocalPlaneYResolution)) + sFPUnit
|
||
else
|
||
if EXIF_FocalPlaneYResolution > 0 then
|
||
result := IEFloatToFormatString(EXIF_FocalPlaneYResolution, 2, true) + sFPUnit;
|
||
end;
|
||
|
||
// EXIF_ExposureIndex: Same as ISOSpeedRatings(0x8827) but data type is unsigned rational. Only Kodak's digicam uses this tag instead of ISOSpeedRating.
|
||
_EXIF_ExposureIndex: result := FloatToStrOrNull( EXIF_ExposureIndex );
|
||
|
||
// Image sensor unit: '2' means 1 chip color area sensor, most of all digicam use this type.
|
||
_EXIF_SensingMethod:
|
||
if EXIF_SensingMethod = 2 then
|
||
result := s_OneChipColorAreaSensor;
|
||
|
||
// Image source: Value '0x03' means the image source is digital still camera.
|
||
_EXIF_FileSource:
|
||
if EXIF_FileSource = $03 then
|
||
result := s_DigitalStillCamera;
|
||
|
||
// Type of scene: Value '0x01' means that the image was directly photographed.
|
||
_EXIF_SceneType:
|
||
if EXIF_SceneType = $01 then
|
||
result := s_DirectlyPhotographed;
|
||
|
||
{
|
||
When image format is YCbCr and uses 'Subsampling' (cropping of chroma data, all the digicam do that), defines the chroma sample point of subsampling pixel array.
|
||
1 means the center of pixel array
|
||
2 means the datum point.
|
||
}
|
||
_EXIF_YCbCrPositioning:
|
||
case EXIF_YcbCrPositioning of
|
||
1: result := s_Centered;
|
||
2: result := s_DataPoint;
|
||
end;
|
||
|
||
{
|
||
The exposure mode set when the image was shot. In auto-bracketing mode, the camera shoots a series of frames of the same scene at different exposure settings.
|
||
0 = Auto exposure
|
||
1 = Manual exposure
|
||
2 = Auto bracket
|
||
}
|
||
_EXIF_ExposureMode:
|
||
case EXIF_ExposureMode of
|
||
0: s_Autoexposure;
|
||
1: s_Manualexposure;
|
||
2: s_Autobracket;
|
||
end;
|
||
|
||
{
|
||
The white balance mode set when the image was shot.
|
||
0 = Auto white balance
|
||
1 = Manual white balance
|
||
}
|
||
_EXIF_WhiteBalance:
|
||
case EXIF_WhiteBalance of
|
||
0: s_Autowhitebalance;
|
||
1: s_Manualwhitebalance;
|
||
end;
|
||
|
||
// The digital zoom ratio when the image was shot. If the numerator of the recorded value is 0, this indicates that digital zoom was not used.
|
||
_EXIF_DigitalZoomRatio:
|
||
if (EXIF_DigitalZoomRatio = 0) or (EXIF_DigitalZoomRatio = -1) then
|
||
result := s_None
|
||
else
|
||
result := FloatToStrOrNull( EXIF_DigitalZoomRatio );
|
||
|
||
// The equivalent focal length assuming a 35mm film camera, in mm. A value of 0 means the focal length is unknown. Note that this tag differs from the FocalLength tag.
|
||
_EXIF_FocalLengthIn35mmFilm:
|
||
if EXIF_FocalLengthIn35mmFilm > 0 then
|
||
result := IntToStr(EXIF_FocalLengthIn35mmFilm) + ' mm';
|
||
|
||
{
|
||
The type of scene that was shot. It can also be used to record the mode in which the image was shot. Note that this differs from the scene type (SceneType) tag.
|
||
0 = Standard
|
||
1 = Landscape
|
||
2 = Portrait
|
||
3 = Night scene
|
||
}
|
||
_EXIF_SceneCaptureType:
|
||
case EXIF_SceneCaptureType of
|
||
0: s_Standard;
|
||
1: s_Landscape;
|
||
2: s_Portrait;
|
||
3: s_Nightscene;
|
||
end;
|
||
|
||
{
|
||
The degree of overall image gain adjustment.
|
||
0 = None
|
||
1 = Low gain up
|
||
2 = High gain up
|
||
3 = Low gain down
|
||
4 = High gain down
|
||
}
|
||
_EXIF_GainControl:
|
||
case EXIF_GainControl of
|
||
0: s_None;
|
||
1: s_LowGainup;
|
||
2: s_HighGainup;
|
||
3: s_LowGaindown;
|
||
4: s_HighGaindown;
|
||
end;
|
||
|
||
{
|
||
The direction of contrast processing applied by the camera when the image was shot.
|
||
0 = Normal
|
||
1 = Soft
|
||
2 = Hard
|
||
}
|
||
_EXIF_Contrast:
|
||
case EXIF_Contrast of
|
||
0: s_Normal;
|
||
1: s_Soft;
|
||
2: s_Hard;
|
||
end;
|
||
|
||
{
|
||
The direction of saturation processing applied by the camera when the image was shot.
|
||
0 = Normal
|
||
1 = Low saturation
|
||
2 = High saturation
|
||
}
|
||
_EXIF_Saturation:
|
||
case EXIF_Saturation of
|
||
0: s_Normal;
|
||
1: s_Lowsaturation;
|
||
2: s_Highsaturation;
|
||
end;
|
||
|
||
{
|
||
The direction of sharpness processing applied by the camera when the image was shot.
|
||
0 = Normal
|
||
1 = Soft
|
||
2 = Hard
|
||
}
|
||
_EXIF_Sharpness:
|
||
case EXIF_Sharpness of
|
||
0: s_Normal;
|
||
1: s_Soft;
|
||
2: s_Hard;
|
||
end;
|
||
|
||
{
|
||
The distance to the subject:
|
||
0 = unknown
|
||
1 = Macro
|
||
2 = Close view
|
||
3 = Distant view
|
||
}
|
||
_EXIF_SubjectDistanceRange:
|
||
case EXIF_SubjectDistanceRange of
|
||
1: s_Macro;
|
||
2: s_Closeview;
|
||
3: s_Distantview;
|
||
end;
|
||
|
||
_EXIF_GPSLatitude : Result := EXIF_GPSLatitude_Str;
|
||
_EXIF_GPSLongitude : Result := EXIF_GPSLongitude_Str;
|
||
|
||
// The altitude based on the reference in Ref. The reference unit is meters.
|
||
_EXIF_GPSAltitude:
|
||
if (EXIF_GPSAltitude <> 0) or (EXIF_GPSAltitudeRef <> '') then
|
||
begin
|
||
result := FloatToStrOrNull( EXIF_GPSAltitude );
|
||
|
||
if RemoveNullA(EXIF_GPSAltitudeRef) = '1' then
|
||
Result := Result + ' (Below sea-level)';
|
||
end;
|
||
|
||
_EXIF_GPSDateAndTime:
|
||
if (EXIF_GPSDateStamp <> '') then
|
||
begin
|
||
result := Format('%s %s : %s.%s', [RemoveNullA(EXIF_GPSDateStamp),
|
||
FloatToStr(EXIF_GPSTimeStampHour),
|
||
FloatToStr(EXIF_GPSTimeStampMinute),
|
||
FloatToStr(EXIF_GPSTimeStampSecond)]);
|
||
end;
|
||
|
||
_EXIF_GPSImageDirection:
|
||
{
|
||
EXIF_GPSImgDirection : The direction of the image when it was captured. The range of values is from 0.00 to 359.99.
|
||
EXIF_GPSImgDirectionRef : The reference for giving the direction of the image when it is captured. 'T' denotes true direction and 'M' is magnetic direction.
|
||
}
|
||
if (EXIF_GPSImgDirection <> 0) or (RemoveNullA(EXIF_GPSImgDirectionRef) <> '') then
|
||
begin
|
||
result := FloatToStrOrNull( EXIF_GPSImgDirection, ' degrees' );
|
||
if uppercase(RemoveNullA(EXIF_GPSImgDirectionRef)) = 'T' then
|
||
Result := Result + ' (True)'
|
||
else
|
||
if uppercase(RemoveNullA(EXIF_GPSImgDirectionRef)) = 'M' then
|
||
Result := Result + ' (Magnetic)';
|
||
end;
|
||
|
||
_EXIF_GPSSpeed:
|
||
{
|
||
EXIF_GPSSpeed : speed of GPS receiver movement
|
||
EXIF_GPSSpeedRef : unit used to express the GPS receiver speed of movement. 'K' 'M' and 'N' represents kilometers per hour, miles per hour, and knots.
|
||
}
|
||
if (EXIF_GPSSpeed <> 0) or (RemoveNullA(EXIF_GPSSpeedRef) <> '') then
|
||
begin
|
||
if uppercase(RemoveNullA(EXIF_GPSSpeedRef)) = 'K' then
|
||
Result := FloatToStr(EXIF_GPSSpeed) + ' km/h'
|
||
else
|
||
if uppercase(RemoveNullA(EXIF_GPSSpeedRef)) = 'M' then
|
||
Result := FloatToStr(EXIF_GPSSpeed) + ' mph'
|
||
else
|
||
if uppercase(RemoveNullA(EXIF_GPSSpeedRef)) = 'N' then
|
||
Result := FloatToStr(EXIF_GPSSpeed) + ' knots'
|
||
else
|
||
Result := FloatToStr(EXIF_GPSSpeed) + ' ' + RemoveNullA(EXIF_GPSSpeedRef);
|
||
end;
|
||
|
||
_EXIF_GPSTrack:
|
||
{
|
||
EXIF_GPSTrack : direction of GPS receiver movement. The range of values is from 0.00 to 359.99.
|
||
EXIF_GPSTrackRef : The reference for giving the direction of the direction of GPS receiver movement. 'T' denotes true direction and 'M' is magnetic direction.
|
||
}
|
||
if (EXIF_GPSTrack <> 0) or (RemoveNullA(EXIF_GPSTrackRef) <> '') then
|
||
begin
|
||
result := FloatToStrOrNull( EXIF_GPSTrack, ' degrees' );
|
||
if uppercase(RemoveNullA(EXIF_GPSTrackRef)) = 'T' then
|
||
Result := Result + ' (True)'
|
||
else
|
||
if uppercase(RemoveNullA(EXIF_GPSTrackRef)) = 'M' then
|
||
Result := Result + ' (Magnetic)';
|
||
end;
|
||
|
||
_EXIF_GPSSatellites: result := RemoveNullA(EXIF_GPSSatellites);
|
||
_EXIF_GPSVersionID: result := RemoveNullA(EXIF_GPSVersionID);
|
||
|
||
_EXIF_Artist: result := RemoveNullA(EXIF_Artist);
|
||
|
||
_EXIF_XPTitle: result := WideCharToString(PWideChar(EXIF_XPTitle));
|
||
_EXIF_XPComment: result := WideCharToString(PWideChar(EXIF_XPComment));
|
||
_EXIF_XPAuthor: result := WideCharToString(PWideChar(EXIF_XPAuthor));
|
||
_EXIF_XPKeywords: result := WideCharToString(PWideChar(EXIF_XPKeywords));
|
||
_EXIF_XPSubject: result := WideCharToString(PWideChar(EXIF_XPSubject));
|
||
_EXIF_XPRating:
|
||
begin
|
||
{
|
||
Windows XP Rating
|
||
Allowed values from 0 up to 5. -1 means not available.
|
||
}
|
||
if EXIF_XPRating < 0 then
|
||
Result := ''
|
||
else
|
||
Result := IntToStr(EXIF_XPRating);
|
||
end;
|
||
|
||
_EXIF_InteropVersion : result := RemoveNullA( EXIF_InteropVersion );
|
||
_EXIF_CameraOwnerName : result := RemoveNullA( EXIF_CameraOwnerName );
|
||
_EXIF_BodySerialNumber : result := RemoveNullA( EXIF_BodySerialNumber );
|
||
_EXIF_LensMake : result := RemoveNullA( EXIF_LensMake );
|
||
_EXIF_LensModel : result := RemoveNullA( EXIF_LensModel );
|
||
_EXIF_LensSerialNumber : result := RemoveNullA( EXIF_LensSerialNumber );
|
||
_EXIF_Gamma : result := FloatToStrOrNull( EXIF_Gamma );
|
||
_EXIF_SubjectArea : result := EXIF_SubjectArea_Str;
|
||
_EXIF_SubjectLocation : result := EXIF_SubjectLocation_Str;
|
||
end;
|
||
|
||
except
|
||
// ERROR
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_FieldDescription
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_FieldDescription [index : Integer]: string; (read-only)
|
||
|
||
<FM>Description<FN>
|
||
Returns a description of an EXIF field specified by the <L EXIF Consts for EXIF_AsStr>constants</L> used by <A TIOParamsHelper.EXIF_AsStr>.
|
||
|
||
Index is a value between 0 and <FC>_EXIF_Tag_Count<FN> - 1.
|
||
|
||
<TABLE>
|
||
<R> <H>Const</H> <H>Description</H> </R>
|
||
<R> <C><FC>_EXIF_UserComment<FN></C> <C>User Comment</C> </R>
|
||
<R> <C><FC>_EXIF_ImageDescription<FN></C> <C>Description</C> </R>
|
||
<R> <C><FC>_EXIF_Make<FN></C> <C>Camera Make</C> </R>
|
||
<R> <C><FC>_EXIF_Model<FN></C> <C>Camera Model</C> </R>
|
||
<R> <C><FC>_EXIF_XResolution<FN></C> <C>Horizontal Resolution</C> </R>
|
||
<R> <C><FC>_EXIF_YResolution<FN></C> <C>Vertical Resolution</C> </R>
|
||
<R> <C><FC>_EXIF_DateTime<FN></C> <C>Date and Time</C> </R>
|
||
<R> <C><FC>_EXIF_DateTimeOriginal<FN></C> <C>Original Date and Time</C> </R>
|
||
<R> <C><FC>_EXIF_DateTimeDigitized<FN></C> <C>Digitized Date and Time</C> </R>
|
||
<R> <C><FC>_EXIF_Copyright<FN></C> <C>Copyright</C> </R>
|
||
<R> <C><FC>_EXIF_Orientation<FN></C> <C>Orientation</C> </R>
|
||
<R> <C><FC>_EXIF_ExposureTime<FN></C> <C>Exposure Time</C> </R>
|
||
<R> <C><FC>_EXIF_FNumber<FN></C> <C>F-Stop</C> </R>
|
||
<R> <C><FC>_EXIF_ExposureProgram<FN></C> <C>Exposure Program</C> </R>
|
||
<R> <C><FC>_EXIF_ISOSpeedRatings<FN></C> <C>ISO Speed Rating</C> </R>
|
||
<R> <C><FC>_EXIF_ShutterSpeedValue<FN></C> <C>Shutter Speed</C> </R>
|
||
<R> <C><FC>_EXIF_ApertureValue<FN></C> <C>Aperture Value</C> </R>
|
||
<R> <C><FC>_EXIF_BrightnessValue<FN></C> <C>Brightness</C> </R>
|
||
<R> <C><FC>_EXIF_ExposureBiasValue<FN></C> <C>Exposure Compensation</C> </R>
|
||
<R> <C><FC>_EXIF_MaxApertureValue<FN></C> <C>Max Aperture Value</C> </R>
|
||
<R> <C><FC>_EXIF_SubjectDistance<FN></C> <C>Subject Distance</C> </R>
|
||
<R> <C><FC>_EXIF_MeteringMode<FN></C> <C>Metering Mode</C> </R>
|
||
<R> <C><FC>_EXIF_LightSource<FN></C> <C>Lighting</C> </R>
|
||
<R> <C><FC>_EXIF_Flash<FN></C> <C>Flash</C> </R>
|
||
<R> <C><FC>_EXIF_FocalLength<FN></C> <C>Focal Length</C> </R>
|
||
<R> <C><FC>_EXIF_FlashPixVersion<FN></C> <C>FlashPix Version</C> </R>
|
||
<R> <C><FC>_EXIF_ColorSpace<FN></C> <C>Color Space</C> </R>
|
||
<R> <C><FC>_EXIF_ExifImageWidth<FN></C> <C>Image Width</C> </R>
|
||
<R> <C><FC>_EXIF_ExifImageHeight<FN></C> <C>Image Height</C> </R>
|
||
<R> <C><FC>_EXIF_RelatedSoundFile<FN></C> <C>Sound File</C> </R>
|
||
<R> <C><FC>_EXIF_FocalPlaneXResolution<FN></C> <C>Focal Plane Horz. Resolution</C> </R>
|
||
<R> <C><FC>_EXIF_FocalPlaneYResolution<FN></C> <C>Focal Plane Vert. Resolution</C> </R>
|
||
<R> <C><FC>_EXIF_ExposureIndex<FN></C> <C>Exposure Index</C> </R>
|
||
<R> <C><FC>_EXIF_SensingMethod<FN></C> <C>Sensing Method</C> </R>
|
||
<R> <C><FC>_EXIF_FileSource<FN></C> <C>File Source</C> </R>
|
||
<R> <C><FC>_EXIF_SceneType<FN></C> <C>Scene Type</C> </R>
|
||
<R> <C><FC>_EXIF_YCbCrPositioning<FN></C> <C>Data Point</C> </R>
|
||
<R> <C><FC>_EXIF_ExposureMode<FN></C> <C>Exposure Mode</C> </R>
|
||
<R> <C><FC>_EXIF_WhiteBalance<FN></C> <C>White Balance</C> </R>
|
||
<R> <C><FC>_EXIF_DigitalZoomRatio <FN></C> <C>Digital Zoom Ratio</C> </R>
|
||
<R> <C><FC>_EXIF_FocalLengthIn35mmFilm<FN></C> <C>Focal Length in 35mm Film</C> </R>
|
||
<R> <C><FC>_EXIF_SceneCaptureType <FN></C> <C>Scene Capture Type</C> </R>
|
||
<R> <C><FC>_EXIF_GainControl<FN></C> <C>Gain Control</C> </R>
|
||
<R> <C><FC>_EXIF_Contrast <FN></C> <C>Contrast</C> </R>
|
||
<R> <C><FC>_EXIF_Saturation<FN></C> <C>Saturation</C> </R>
|
||
<R> <C><FC>_EXIF_Sharpness<FN></C> <C>Sharpness</C> </R>
|
||
<R> <C><FC>_EXIF_SubjectDistanceRange<FN></C> <C>Subject Distance</C> </R>
|
||
<R> <C><FC>_EXIF_GPSLatitude<FN></C> <C>GPS Latitude</C> </R>
|
||
<R> <C><FC>_EXIF_GPSLongitude<FN></C> <C>GPS Longitude</C> </R>
|
||
<R> <C><FC>_EXIF_GPSAltitude<FN></C> <C>GPS Altitude</C> </R>
|
||
<R> <C><FC>_EXIF_GPSImageDirection<FN></C> <C>GPS Image Direction</C> </R>
|
||
<R> <C><FC>_EXIF_GPSTrack<FN></C> <C>GPS Movement Direction</C> </R>
|
||
<R> <C><FC>_EXIF_GPSSpeed<FN></C> <C>GPS Movement Speed</C> </R>
|
||
<R> <C><FC>_EXIF_GPSDateAndTime<FN></C> <C>GPS Date and Time</C> </R>
|
||
<R> <C><FC>_EXIF_GPSSatellites<FN></C> <C>GPS Satellites</C> </R>
|
||
<R> <C><FC>_EXIF_GPSVersionID<FN></C> <C>GPS Version</C> </R>
|
||
<R> <C><FC>_EXIF_Artist<FN></C> <C>Artist</C> </R>
|
||
<R> <C><FC>_EXIF_XPTitle<FN></C> <C>Title (Windows)</C> </R>
|
||
<R> <C><FC>_EXIF_XPComment<FN></C> <C>Comment (Windows)</C> </R>
|
||
<R> <C><FC>_EXIF_XPAuthor<FN></C> <C>Author (Windows)</C> </R>
|
||
<R> <C><FC>_EXIF_XPKeywords<FN></C> <C>Keywords (Windows)</C> </R>
|
||
<R> <C><FC>_EXIF_XPSubject<FN></C> <C>Subject (Windows)</C> </R>
|
||
<R> <C><FC>_EXIF_XPRating<FN></C> <C>Rating (Windows)</C> </R>
|
||
<R> <C><FC>_EXIF_InteropVersion<FN></C> <C>Interoperability Version</C> </R>
|
||
<R> <C><FC>_EXIF_CameraOwnerName<FN></C> <C>Camera Owner Name</C> </R>
|
||
<R> <C><FC>_EXIF_BodySerialNumber<FN></C> <C>Body Serial Number</C> </R>
|
||
<R> <C><FC>_EXIF_LensMake<FN></C> <C>Lens Make</C> </R>
|
||
<R> <C><FC>_EXIF_LensModel<FN></C> <C>Lens Model</C> </R>
|
||
<R> <C><FC>_EXIF_LensSerialNumber<FN></C> <C>Lens Serial Number</C> </R>
|
||
<R> <C><FC>_EXIF_Gamma<FN></C> <C>Gamma</C> </R>
|
||
<R> <C><FC>_EXIF_SubjectArea<FN></C> <C>Subject Area</C> </R>
|
||
<R> <C><FC>_EXIF_SubjectLocation<FN></C> <C>Subject Location</C> </R>
|
||
</TABLE>
|
||
|
||
<FM>See Also<FN>
|
||
- <A TIOParamsHelper.EXIF_AsStr>
|
||
|
||
<FM>Example<FC>
|
||
// Output all fields of current image to a memo (same as <A TIOParamsHelper.EXIF_WriteToStrings>)
|
||
for i := 0 to _EXIF_Tag_Count - 1 do
|
||
memo1.Lines.Add( ImageEnView1.IO.Params.EXIF_FieldDescription[ i ] + ': ' + ImageEnView1.IO.Params.EXIF_AsStr[ i ] );
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_FieldDescription(Index: Integer): string;
|
||
begin
|
||
Result := ExifTags[ Index ].Desc;
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_CanWriteEXIFData
|
||
|
||
<FM>Declaration<FC>
|
||
property EXIF_CanWriteEXIFData : Boolean; (read-only)
|
||
|
||
<FM>Description<FN>
|
||
Returns true if the current image is of a type that supports EXIF writing, i.e. TIFF or JPEG
|
||
|
||
Note: This is only based on the current format. Naturally you could add EXIF data to an image that was loaded as a Bitmap and then save it to JPEG.
|
||
!!}
|
||
function TIOParamsHelper.GetEXIF_CanWriteEXIFData : Boolean;
|
||
begin
|
||
Result := FileType in [ioJPEG, ioTIFF];
|
||
end;
|
||
|
||
|
||
procedure TIOParamsHelper.SetEXIF_Camera_Str(const value: AnsiString);
|
||
begin
|
||
// EXIF_Make and EXIF_Model combined
|
||
if GetEXIF_Camera_Str <> Value then
|
||
begin
|
||
EXIF_Make := AnsiString( GetTextBeforeChar( String( Value ), ' ', False ));
|
||
EXIF_Model := AnsiString( GetTextAfterChar( String( Value ), ' ', True ));
|
||
end;
|
||
end;
|
||
|
||
procedure TIOParamsHelper.SetEXIF_XResolution_Str(value: AnsiString);
|
||
begin
|
||
// Display/Print resolution of image. Default value is 1/72inch, but it has no mean because personal computer doesn't use this value to display/print out.
|
||
Value := AnsiString( StripSuffix( String( value ), ' ' + s_Inch ));
|
||
Value := AnsiString( StripSuffix( String( value ), ' ' + s_CM ));
|
||
|
||
EXIF_XResolution := FractionToDouble( String( value ));
|
||
end;
|
||
|
||
procedure TIOParamsHelper.SetEXIF_YResolution_Str(value: AnsiString);
|
||
begin
|
||
// Display/Print resolution of image. Default value is 1/72inch, but it has no mean because personal computer doesn't use this value to display/print out.
|
||
Value := AnsiString( StripSuffix( String( value ), ' ' + s_Inch ));
|
||
Value := AnsiString( StripSuffix( String( value ), ' ' + s_CM ));
|
||
|
||
EXIF_YResolution := FractionToDouble( String( value ));
|
||
end;
|
||
|
||
procedure TIOParamsHelper.SetEXIF_ExposureTime_Str(value: string);
|
||
begin
|
||
// Exposure time (reciprocal of shutter speed). Unit is seconds
|
||
Value := StripSuffix(value, ' ' + s_Seconds);
|
||
Value := StripSuffix(value, ' ' + s_Second);
|
||
if pos('1/', value) > 0 then
|
||
EXIF_ExposureTime := 1 / FractionToDouble(value)
|
||
else
|
||
EXIF_ExposureTime := StrToInt(value);
|
||
end;
|
||
|
||
procedure TIOParamsHelper.SetEXIF_FNumber_Str(value: string);
|
||
begin
|
||
// The actual F-number(F-stop) of lens when the image was taken
|
||
if uppercase(value)[1] = 'F' then
|
||
delete(value, 1, 1);
|
||
|
||
EXIF_FNumber := StrToFloat(value);
|
||
end;
|
||
|
||
procedure TIOParamsHelper.SetEXIF_ShutterSpeedValue_Str(const value: string);
|
||
begin
|
||
// Shutter speed by APEX value. To convert this value to ordinary 'Shutter Speed'; calculate this value's power of 2, then reciprocal. For example, if the ShutterSpeedValue is '4', shutter speed is 1/(24)=1/16 second
|
||
EXIF_ShutterSpeedValue := StrToApex(2, value, '1/');
|
||
end;
|
||
|
||
procedure TIOParamsHelper.SetEXIF_ApertureValue_Str(const value: string);
|
||
begin
|
||
// The actual aperture value of lens when the image was taken. Unit is APEX. To convert this value to
|
||
// ordinary F-number (F-stop), calculate this value's power of root 2 (=1.4142). For example, if the
|
||
// ApertureValue is '5', F-number is 1.41425 = F5.6.
|
||
EXIF_ApertureValue := StrToApex(Sqrt(2), value, 'F');
|
||
end;
|
||
|
||
procedure TIOParamsHelper.SetEXIF_MaxApertureValue_Str(const value: string);
|
||
begin
|
||
// Maximum aperture value of lens. You can convert to F-number by calculating power of root 2 (same process of ApertureValue)
|
||
EXIF_MaxApertureValue := StrToApex(Sqrt(2), value, 'F');
|
||
end;
|
||
|
||
// exif data specified by the field index with the value in the specified string
|
||
procedure TIOParamsHelper.SetEXIF_AsStr(Index: Integer; value : string);
|
||
begin
|
||
value := Trim(value);
|
||
try
|
||
case Index of
|
||
|
||
_EXIF_UserComment: EXIF_UserComment := value;
|
||
_EXIF_ImageDescription: EXIF_ImageDescription := AnsiString( value );
|
||
_EXIF_CameraMake : EXIF_Make := AnsiString( Value );
|
||
_EXIF_CameraModel : EXIF_Model := AnsiString( Value );
|
||
|
||
{
|
||
Unit of XResolution/YResolution:
|
||
1 means no-unit
|
||
2 means inch
|
||
3 means centimeter
|
||
Default value is 2 (inch)
|
||
}
|
||
_EXIF_XResolution:
|
||
begin
|
||
if pos(uppercase(s_Inch), uppercase(value)) > 0 then
|
||
EXIF_ResolutionUnit := 2
|
||
else
|
||
if pos(uppercase(s_CM), uppercase(value)) > 0 then
|
||
EXIF_ResolutionUnit := 3;
|
||
|
||
EXIF_XResolution_Str := AnsiString( value );
|
||
end;
|
||
|
||
{
|
||
Unit of XResolution/YResolution:
|
||
1 means no-unit
|
||
2 means inch
|
||
3 means centimeter
|
||
Default value is 2 (inch)
|
||
}
|
||
_EXIF_YResolution:
|
||
begin
|
||
if pos(uppercase(s_Inch), uppercase(value)) > 0 then
|
||
EXIF_ResolutionUnit := 2
|
||
else
|
||
if pos(uppercase(s_CM), uppercase(value)) > 0 then
|
||
EXIF_ResolutionUnit := 3;
|
||
|
||
Value := StripSuffix(value, s_Inch);
|
||
Value := StripSuffix(value, s_CM);
|
||
|
||
EXIF_YResolution_Str := AnsiString( value );
|
||
end;
|
||
|
||
_EXIF_DateTime: EXIF_DateTime2 := StrToDateTime(value);
|
||
_EXIF_DateTimeOriginal: EXIF_DateTimeOriginal2 := StrToDateTime(value);
|
||
_EXIF_DateTimeDigitized: EXIF_DateTimeDigitized2 := StrToDateTime(value);
|
||
|
||
_EXIF_Copyright: EXIF_Copyright := AnsiString( value );
|
||
|
||
// The orientation of the camera relative to the scene, when the image was captured
|
||
_EXIF_Orientation:
|
||
begin
|
||
if SameText(value, s_EXIFOrientation1) then
|
||
EXIF_Orientation := 1
|
||
else
|
||
if SameText(value, s_EXIFOrientation2) then
|
||
EXIF_Orientation := 2
|
||
else
|
||
if SameText(value, s_EXIFOrientation3) then
|
||
EXIF_Orientation := 3
|
||
else
|
||
if SameText(value, s_EXIFOrientation4) then
|
||
EXIF_Orientation := 4
|
||
else
|
||
if SameText(value, s_EXIFOrientation5) then
|
||
EXIF_Orientation := 5
|
||
else
|
||
if SameText(value, s_EXIFOrientation6) then
|
||
EXIF_Orientation := 6
|
||
else
|
||
if SameText(value, s_EXIFOrientation7) then
|
||
EXIF_Orientation := 7
|
||
else
|
||
if SameText(value, s_EXIFOrientation8) then
|
||
EXIF_Orientation := 8;
|
||
end;
|
||
|
||
_EXIF_ExposureTime: EXIF_ExposureTime_Str := Value;
|
||
_EXIF_FNumber: EXIF_FNumber_Str := value;
|
||
|
||
{
|
||
Exposure program that the camera used when image was taken:
|
||
1 means manual control
|
||
2 program normal
|
||
3 aperture priority
|
||
4 shutter priority
|
||
5 program creative (slow program)
|
||
6 program action(high-speed program)
|
||
7 portrait mode
|
||
8 landscape mode.
|
||
}
|
||
_EXIF_ExposureProgram:
|
||
begin
|
||
if SameText(value, s_ManualControl) then
|
||
EXIF_ExposureProgram := 1
|
||
else
|
||
if SameText(value, s_ProgramNormal) then
|
||
EXIF_ExposureProgram := 2
|
||
else
|
||
if SameText(value, s_AperturePriority) then
|
||
EXIF_ExposureProgram := 3
|
||
else
|
||
if SameText(value, s_ShutterPriority) then
|
||
EXIF_ExposureProgram := 4
|
||
else
|
||
if SameText(value, s_CreativeProgram) then
|
||
EXIF_ExposureProgram := 5
|
||
else
|
||
if SameText(value, s_ActionProgram) then
|
||
EXIF_ExposureProgram := 6
|
||
else
|
||
if SameText(value, s_Portraitmode) then
|
||
EXIF_ExposureProgram := 7
|
||
else
|
||
if SameText(value, s_LandscapeMode) then
|
||
EXIF_ExposureProgram := 8;
|
||
end;
|
||
|
||
// EXIF_ISOSpeedRatings: CCD sensitivity equivalent to Ag-Hr film speedrate.
|
||
_EXIF_ISOSpeedRatings: EXIF_ISOSpeedRatings[0] := StrToInt(value);
|
||
_EXIF_ShutterSpeedValue: EXIF_ShutterSpeedValue_Str := value;
|
||
_EXIF_ApertureValue: EXIF_ApertureValue_Str := value;
|
||
|
||
{
|
||
Brightness of taken subject, unit is APEX. To calculate Exposure(Ev) from BrigtnessValue(Bv), you must add SensitivityValue(Sv):
|
||
Ev=Bv+Sv Sv=log2(ISOSpeedRating/3.125)
|
||
ISO100 : Sv=5, ISO200 : Sv=6, ISO400 : Sv=7, ISO125 : Sv=5.32.
|
||
}
|
||
_EXIF_BrightnessValue: if Value <> '' then
|
||
EXIF_BrightnessValue := StrToFloat(value);
|
||
_EXIF_ExposureBiasValue: EXIF_ExposureBiasValue := StrToFloat(value);
|
||
_EXIF_MaxApertureValue: EXIF_MaxApertureValue_Str := value;
|
||
|
||
// Distance to focus point, unit is meter.
|
||
_EXIF_SubjectDistance:
|
||
begin
|
||
value := StripSuffix(value, ' m');
|
||
EXIF_SubjectDistance := StrToFloat(value);
|
||
end;
|
||
|
||
{
|
||
Exposure metering method:
|
||
0 means unknown
|
||
1 average
|
||
2 center weighted average
|
||
3 spot
|
||
4 multi-spot
|
||
5 multi-segment
|
||
6 partial
|
||
255 other.
|
||
}
|
||
_EXIF_MeteringMode:
|
||
begin
|
||
if SameText(value, s_average) then
|
||
EXIF_MeteringMode := 1
|
||
else
|
||
if SameText(value, s_CenterWeightedAverage) then
|
||
EXIF_MeteringMode := 2
|
||
else
|
||
if SameText(value, s_Spot) then
|
||
EXIF_MeteringMode := 3
|
||
else
|
||
if SameText(value, s_MultiSpot) then
|
||
EXIF_MeteringMode := 4
|
||
else
|
||
if SameText(value, s_MultiSegment) then
|
||
EXIF_MeteringMode := 5
|
||
else
|
||
if SameText(value, s_partial) then
|
||
EXIF_MeteringMode := 6;
|
||
end;
|
||
|
||
{
|
||
Light source, actually this means white balance setting:
|
||
0 means unknown
|
||
1 daylight
|
||
2 fluorescent
|
||
3 tungsten
|
||
10 flash
|
||
17 standard light A
|
||
18 standard light B
|
||
19 standard light C
|
||
20 D55
|
||
21 D65
|
||
22 D75
|
||
255 other.
|
||
}
|
||
_EXIF_LightSource:
|
||
begin
|
||
if SameText(value, s_daylight) then
|
||
EXIF_LightSource := 1
|
||
else
|
||
if SameText(value, s_fluorescent) then
|
||
EXIF_LightSource := 2
|
||
else
|
||
if SameText(value, s_tungsten) then
|
||
EXIF_LightSource := 3
|
||
else
|
||
if SameText(value, s_flash) then
|
||
EXIF_LightSource := 10
|
||
else
|
||
if SameText(value, s_standardLightA) then
|
||
EXIF_LightSource := 17
|
||
else
|
||
if SameText(value, s_standardLightB) then
|
||
EXIF_LightSource := 18
|
||
else
|
||
if SameText(value, s_standardLightC) then
|
||
EXIF_LightSource := 19
|
||
else
|
||
if SameText(value, s_D55) then
|
||
EXIF_LightSource := 20
|
||
else
|
||
if SameText(value, s_D65) then
|
||
EXIF_LightSource := 21
|
||
else
|
||
if SameText(value, s_D75) then
|
||
EXIF_LightSource := 22;
|
||
end;
|
||
|
||
{
|
||
EXIF_Flash:
|
||
0 means flash did not fire
|
||
1 flash fired
|
||
5 flash fired but strobe return light not detected
|
||
7 flash fired and strobe return light detected
|
||
}
|
||
_EXIF_Flash:
|
||
begin
|
||
if SameText(value, s_FlashDidNotFire) then
|
||
EXIF_Flash := 0
|
||
else
|
||
if SameText(value, s_flashFired) then
|
||
EXIF_Flash := 1
|
||
else
|
||
if SameText(value, s_flashFiredNoStrobeLight) then
|
||
EXIF_Flash := 5
|
||
else
|
||
if SameText(value, s_flashFiredStrobeLight) then
|
||
EXIF_Flash := 7;
|
||
end;
|
||
|
||
// Focal length of lens used to take image. Unit is millimeter.
|
||
_EXIF_FocalLength:
|
||
begin
|
||
value := StripSuffix(value, ' mm');
|
||
EXIF_FocalLength := StrToFloat(value);
|
||
end;
|
||
|
||
_EXIF_FlashPixVersion: EXIF_FlashPixVersion := AnsiString( Value );
|
||
|
||
// Defines Color Space: DCF image must use sRGB color space so value is always '1'. If the picture uses the other color space, value is '65535' : Uncalibrated.
|
||
_EXIF_ColorSpace:
|
||
begin
|
||
if SameText(value, s_RGB) then
|
||
EXIF_ColorSpace := 1
|
||
else
|
||
if SameText(value, s_Uncalibrated) then
|
||
EXIF_ColorSpace := 65535;
|
||
end;
|
||
|
||
_EXIF_ExifImageWidth : EXIF_ExifImageWidth := StrToInt(value);
|
||
_EXIF_ExifImageHeight: EXIF_ExifImageHeight := StrToInt(value);
|
||
|
||
// If this digicam can record audio data with image, shows name of audio data.
|
||
_EXIF_RelatedSoundFile: EXIF_RelatedSoundFile := AnsiString( value );
|
||
|
||
{
|
||
Unit of FocalPlaneXResoluton/FocalPlaneYResolution:
|
||
1 means no-unit
|
||
2 inch
|
||
3 centimeter.
|
||
Note : Some of Fujifilm's digicam(e.g.FX2700, FX2900, Finepix4700Z/40i etc) uses value '3' so it must be 'centimeter', but it seems that they use a '8.3mm?'(1/3in.?) to their ResolutionUnit. Fuji's BUG? Finepix4900Z has been changed to use value '2' but it doesn't match to actual value also.
|
||
}
|
||
_EXIF_FocalPlaneXResolution:
|
||
begin
|
||
if pos(uppercase(s_Inch), uppercase(value)) > 0 then
|
||
EXIF_FocalPlaneResolutionUnit := 2
|
||
else
|
||
if pos(uppercase(s_CM), uppercase(value)) > 0 then
|
||
EXIF_FocalPlaneResolutionUnit := 3;
|
||
|
||
Value := StripSuffix(value, s_PerInch);
|
||
Value := StripSuffix(value, s_PerCM);
|
||
|
||
EXIF_FocalPlaneXResolution := StrToFloat(value);
|
||
end;
|
||
|
||
_EXIF_FocalPlaneYResolution:
|
||
begin
|
||
if pos(uppercase(s_Inch), uppercase(value)) > 0 then
|
||
EXIF_FocalPlaneResolutionUnit := 2
|
||
else
|
||
if pos(uppercase(s_CM), uppercase(value)) > 0 then
|
||
EXIF_FocalPlaneResolutionUnit := 3;
|
||
|
||
Value := StripSuffix(value, s_PerInch);
|
||
Value := StripSuffix(value, s_PerCM);
|
||
|
||
EXIF_FocalPlaneYResolution := StrToFloat(value);
|
||
end;
|
||
|
||
// EXIF_ExposureIndex: Same as ISOSpeedRatings(0x8827) but data type is unsigned rational. Only Kodak's digicam uses this tag instead of ISOSpeedRating.
|
||
_EXIF_ExposureIndex: EXIF_ExposureIndex := StrToFloat(value);
|
||
|
||
{
|
||
When image format is YCbCr and uses 'Subsampling' (cropping of chroma data, all the digicam do that), defines the chroma sample point of subsampling pixel array.
|
||
1 means the center of pixel array
|
||
2 means the datum point.
|
||
}
|
||
_EXIF_YCbCrPositioning:
|
||
begin
|
||
if SameText(value, s_Centered) then
|
||
EXIF_YcbCrPositioning := 1
|
||
else
|
||
if SameText(value, s_DataPoint) then
|
||
EXIF_YcbCrPositioning := 2;
|
||
end;
|
||
|
||
_EXIF_GPSSatellites: EXIF_GPSSatellites := AnsiString( Value );
|
||
_EXIF_GPSVersionID: EXIF_GPSVersionID := AnsiString( Value );
|
||
|
||
_EXIF_Artist: EXIF_Artist := AnsiString( Value );
|
||
|
||
_EXIF_XPTitle: EXIF_XPTitle := Value;
|
||
_EXIF_XPComment: EXIF_XPComment := Value;
|
||
_EXIF_XPAuthor: EXIF_XPAuthor := Value;
|
||
_EXIF_XPKeywords: EXIF_XPKeywords := Value;
|
||
_EXIF_XPSubject: EXIF_XPSubject := Value;
|
||
_EXIF_XPRating: EXIF_XPRating := StrToIntDef(Value, -1);
|
||
|
||
_EXIF_InteropVersion : EXIF_InteropVersion := AnsiString(Value);
|
||
|
||
_EXIF_CameraOwnerName : EXIF_CameraOwnerName := AnsiString( Value );
|
||
_EXIF_BodySerialNumber : EXIF_BodySerialNumber := AnsiString( Value );
|
||
_EXIF_LensMake : EXIF_LensMake := AnsiString( Value );
|
||
_EXIF_LensModel : EXIF_LensModel := AnsiString( Value );
|
||
_EXIF_LensSerialNumber : EXIF_LensSerialNumber := AnsiString( Value );
|
||
_EXIF_Gamma : EXIF_Gamma := StrToFloat( Value );
|
||
_EXIF_SubjectLocation : EXIF_SubjectLocation_Str := Value;
|
||
|
||
{
|
||
TO-DO: ADD WRITE SUPPORT :
|
||
|
||
_EXIF_SensingMethod
|
||
_EXIF_FileSource
|
||
_EXIF_SceneType
|
||
_EXIF_ExposureMode
|
||
_EXIF_WhiteBalance
|
||
_EXIF_DigitalZoomRatio
|
||
_EXIF_FocalLengthIn35mmFilm
|
||
_EXIF_SceneCaptureType
|
||
_EXIF_GainControl
|
||
_EXIF_Contrast
|
||
_EXIF_Saturation
|
||
_EXIF_Sharpness
|
||
_EXIF_SubjectDistanceRange
|
||
_EXIF_GPSLatitude
|
||
_EXIF_GPSLongitude
|
||
_EXIF_GPSAltitude
|
||
_EXIF_GPSImageDirection
|
||
_EXIF_GPSTrack
|
||
_EXIF_GPSSpeed
|
||
_EXIF_GPSDateAndTime
|
||
_EXIF_SubjectArea
|
||
}
|
||
end;
|
||
|
||
except
|
||
// ERROR
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.EXIF_WriteToStrings
|
||
|
||
<FM>Declaration<FC>
|
||
function TIOParamsHelper.EXIF_WriteToStrings(Dest : TStrings) : Boolean;
|
||
|
||
<FM>Description<FN>
|
||
Fills a TStrings object with the EXIF properties of the current image in the format:
|
||
Description: Value
|
||
|
||
Result is true if the image has any EXIF fields.
|
||
|
||
<FM>Example<FC>
|
||
// Output the EXIF properties of the current image to a TMemo
|
||
ImageEnView1.IO.Params.EXIF_WriteToStrings( memo1.Lines );
|
||
!!}
|
||
function TIOParamsHelper.EXIF_WriteToStrings(Dest : TStrings) : Boolean;
|
||
begin
|
||
Result := _ReadFromEXIF_Params(Dest, Self);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.IPTC_WriteToStrings
|
||
|
||
<FM>Declaration<FC>
|
||
function TIOParamsHelper.IPTC_WriteToStrings(Dest : TStrings) : Boolean;
|
||
|
||
<FM>Description<FN>
|
||
Fills a TStrings object with the IPTC properties of the current image in the format:
|
||
Description: Value
|
||
|
||
Result is true if the image has any IPTC fields.
|
||
|
||
<FM>Example<FC>
|
||
// Output the IPTC properties of the current image to a TMemo
|
||
ImageEnView1.IO.Params.IPTC_WriteToStrings( memo1.Lines );
|
||
!!}
|
||
function TIOParamsHelper.IPTC_WriteToStrings(Dest : TStrings) : Boolean;
|
||
begin
|
||
Result := _ReadFromIPTC_Params(Dest, Self);
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.DICOM_WriteToStrings
|
||
|
||
<FM>Declaration<FC>
|
||
function TIOParamsHelper.DICOM_WriteToStrings(Dest : TStrings; TagInclude: <A TIEDicomInclude>) : Boolean;
|
||
|
||
<FM>Description<FN>
|
||
Fills a TStrings object with the Dicom properties of the current image in the format:
|
||
Description: Value
|
||
|
||
<FC>TagInclude<FN> allows you to filter the types of tags returned.
|
||
Result is true if the image has any Dicom fields.
|
||
|
||
<FM>Examples<FC>
|
||
// Output the Dicom properties of the current image to a TMemo (all types)
|
||
ImageEnView1.IO.DICOM_WriteToStrings( memo1.Lines, [ diProprietary, diDeprecated, diChildTags, diUnknown ] );
|
||
|
||
// Export the dicom list of the current image to a file (exclude deprecated and unknown tags)
|
||
aStringList := TStringList.create;
|
||
ImageEnView1.IO.Params.DICOM_WriteToStrings( aStringList, [ diProprietary, diChildTags ] );
|
||
aStringList.SaveToFile('D:\DicomList.txt');
|
||
aStringList.Free;
|
||
!!}
|
||
{$ifdef IEINCLUDEDICOM}
|
||
function TIOParamsHelper.DICOM_WriteToStrings(Dest : TStrings; TagInclude: TIEDicomInclude) : Boolean;
|
||
begin
|
||
Result := _ReadFromDicom_Params(Dest, Self, TagInclude);
|
||
end;
|
||
{$endif}
|
||
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.XMP_WriteToStrings
|
||
|
||
<FM>Declaration<FC>
|
||
function TIOParamsHelper.XMP_WriteToStrings(Dest : TStrings) : Boolean;
|
||
|
||
<FM>Description<FN>
|
||
Fills a TStrings object with the XMP properties of the current image in the format:
|
||
Description: Value
|
||
|
||
Result is true if the image has any XMP fields.
|
||
|
||
Note: Only <L Consts for Common XMP Fields>common XMP fields</L> are added. Unknown XMP tags are skipped.
|
||
|
||
<FM>Examples<FC>
|
||
// Output the XMP properties of the current image to a TMemo
|
||
ImageEnView1.IO.Params.XMP_WriteToStrings( memo1.Lines );
|
||
|
||
// Export the XMP list of the current image to a file (exclude deprecated and unknown tags)
|
||
aStringList := TStringList.create;
|
||
ImageEnView1.IO.Params.XMP_WriteToStrings( aStringList );
|
||
aStringList.SaveToFile('D:\XMPList.txt');
|
||
aStringList.Free;
|
||
!!}
|
||
function TIOParamsHelper.XMP_WriteToStrings(Dest : TStrings) : Boolean;
|
||
begin
|
||
Result := _ReadFromXMP_Params(Dest, Self);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.XMP_AsStr
|
||
|
||
<FM>Declaration<FC>
|
||
property XMP_AsStr [Field : Integer]: String; (read-only)
|
||
|
||
<FM>Description<FN>
|
||
A shortcut function that calls:
|
||
<FC>Result := Dict.GetDictionary( 'XMP' ).GetString( Field, True )<FN>
|
||
|
||
Any XMP field, such as dc:subject, can be specified. Result is '' if the field is not found. Consts are available <L Consts for Common XMP Fields>common XMP fields</L>
|
||
|
||
<FM>Examples<FC>
|
||
// Return the photo description
|
||
sDescription := ImageEnView1.IO.Params.XMP_AsStr[ XMP_DC_Description ];
|
||
|
||
// Which is the same as calling (except that exceptions are raised on failure)
|
||
sDescription := ImageEnView1.IO.Params.Dict.GetDictionary( 'XMP' ).GetString( 'dc:Description', True );
|
||
|
||
// Return the creator or author of the asset
|
||
sCreator := ImageEnView1.IO.Params.XMP_AsStr[ XMP_DC_Creator ];
|
||
|
||
// Return location information about the content being shown in the image
|
||
sLocation := ImageEnView1.IO.Params.XMP_AsStr[ XMP_Photoshop_City ] + ', ' +
|
||
ImageEnView1.IO.Params.XMP_AsStr[ XMP_Photoshop_State ] + ', ' +
|
||
ImageEnView1.IO.Params.XMP_AsStr[ XMP_Photoshop_Country ];
|
||
|
||
// Return the document title
|
||
sTitle := ImageEnView1.IO.Params.XMP_AsStr[ XMP_DC_Title ];
|
||
|
||
// Return the document keywords
|
||
sKeywords := ImageEnView1.IO.Params.XMP_AsStr[ XMP_DC_Subject ];
|
||
|
||
// Return the document copyright information
|
||
sCopyright := ImageEnView1.IO.Params.XMP_AsStr[ XMP_DC_Rights ];
|
||
|
||
// Return the Photoshop Headline
|
||
sHeadline := ImageEnView1.IO.Params.XMP_AsStr[ XMP_Photoshop_Headline ];
|
||
|
||
// Return the Windows Rating (0 to 5)
|
||
sRating := ImageEnView1.IO.Params.XMP_AsStr[ XMP_Rating ];
|
||
|
||
// Return the creation date (XMP date strings are formatted the same EXIF date strings)
|
||
dtCreateDate := EXIFDateToDateTime( ImageEnView1.IO.Params.XMP_AsStr[ XMP_CreateDate ] );
|
||
|
||
<FM>See Also<FN>
|
||
- <A TIOParamsHelper.XMP_AsInt>
|
||
- <A TIOParamsHelper.XMP_AsDateTime>
|
||
- <A TIOParams.XMP_Info>
|
||
- <A TIOParams.Dict>
|
||
!!}
|
||
function TIOParamsHelper.GetXMP_AsStr(const Field: String): string;
|
||
begin
|
||
try
|
||
Result := Dict.GetDictionary( 'XMP' ).GetString( Field, True );
|
||
except
|
||
Result := '';
|
||
end;
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.XMP_AsInt
|
||
|
||
<FM>Declaration<FC>
|
||
property XMP_AsInt [Field : Integer]: Integer; (read-only)
|
||
|
||
<FM>Description<FN>
|
||
A shortcut function that calls:
|
||
<FC>Result := Dict.GetDictionary( 'XMP' ).GetInteger( Field, True )<FN>
|
||
|
||
Any XMP field, such as photoshop:ColorMode, can be specified. Result is 0 if the field is not found or not an integer field. Consts are available <L Consts for Common XMP Fields>common XMP fields</L>
|
||
|
||
<FM>Examples<FC>
|
||
// Return the Photoshop Color Mode from the XMP metadata
|
||
iColorMode := ImageEnView1.IO.Params.XMP_AsInt[ 'photoshop:ColorMode' ];
|
||
|
||
<FM>See Also<FN>
|
||
- <A TIOParamsHelper.XMP_AsStr>
|
||
- <A TIOParamsHelper.XMP_AsDateTime>
|
||
- <A TIOParams.XMP_Info>
|
||
- <A TIOParams.Dict>
|
||
!!}
|
||
function TIOParamsHelper.GetXMP_AsInt(const Field: String): Integer;
|
||
begin
|
||
try
|
||
Result := Dict.GetDictionary( 'XMP' ).GetInteger( Field, True );
|
||
except
|
||
Result := 0;
|
||
end;
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.XMP_AsDateTime
|
||
|
||
<FM>Declaration<FC>
|
||
property XMP_AsDateTime [Field : Integer]: TDateTime; (read-only)
|
||
|
||
<FM>Description<FN>
|
||
A shortcut function that calls:
|
||
<FC>Result := Dict.GetDictionary( 'XMP' ).GetString( Field, True )<FN>
|
||
|
||
And then uses <A EXIFDateToDateTime> to convert the value to a TDateTime (as XMP date strings are the same as EXIF).
|
||
|
||
Any XMP field, such as xmp:CreateDate, can be specified. Result is 0 if the field is not found or not a valid date field. Consts are available <L Consts for Common XMP Fields>common XMP fields</L>
|
||
|
||
<FM>Examples<FC>
|
||
// Return the creation date
|
||
dtCreateDate := ImageEnView1.IO.Params.XMP_AsDateTime[ XMP_CreateDate ];
|
||
|
||
<FM>See Also<FN>
|
||
- <A TIOParamsHelper.XMP_AsStr>
|
||
- <A TIOParamsHelper.XMP_AsInt>
|
||
- <A TIOParams.XMP_Info>
|
||
- <A TIOParams.Dict>
|
||
!!}
|
||
function TIOParamsHelper.GetXMP_AsDateTime(const Field: String): TDateTime;
|
||
begin
|
||
try
|
||
Result := EXIFDateToDateTime( Dict.GetDictionary( 'XMP' ).GetString( Field, True ));
|
||
except
|
||
Result := 0;
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.DICOM_FindTag
|
||
|
||
<FM>Declaration<FC>
|
||
function TIOParamsHelper.DICOM_FindTag(Group: Word; Element: Word): <A PIEDicomTag>;
|
||
|
||
<FM>Description<FN>
|
||
Parses all the tags of <A TIOParams.DICOM_Tags> to find the first tag matching the specified group and element (even if it is a child tag).
|
||
|
||
<FM>Examples<FC>
|
||
// Find the "Pixel Data" tag
|
||
aTag := ImageEnMView1.MIO.Params[0].DICOM_FindTag( $7FE0, $0010 );
|
||
if assigned( aTag ) then
|
||
begin
|
||
aMemStream := TMemoryStream.Create();
|
||
aMemStream.Write( atag^.Data, atag^.DataLen );
|
||
aMemStream.Position := 0;
|
||
// Do something with aMemStream
|
||
aMemStream.Free;
|
||
end;
|
||
|
||
<FM>See Also<FN>
|
||
- <A TIOParamsHelper.DICOM_HasDicomTags>
|
||
- <A TIEDicomTags.GetTag>
|
||
- <A TIEDicomTags>
|
||
!!}
|
||
{$ifdef IEINCLUDEDICOM}
|
||
function TIOParamsHelper.DICOM_FindTag(Group: Word; Element: Word): PIEDicomTag;
|
||
{}
|
||
procedure _ParseTags(tags: TIEDicomTags);
|
||
var
|
||
i, j: integer;
|
||
tag: PIEDicomTag;
|
||
begin
|
||
for i := 0 to tags.Count - 1 do
|
||
begin
|
||
// GET DATA
|
||
tag := tags.GetTag(i);
|
||
if ( tag^.Group = Group ) and ( tag^.Element = Element ) then
|
||
begin
|
||
Result := tag;
|
||
Exit;
|
||
end;
|
||
|
||
// PARSE ANY CHILDREN
|
||
if assigned( tag.Children ) then
|
||
begin
|
||
// tag.Children is a TObjectList object, where each item is a TIEDicomTags object to pass recursively into ShowRawTags
|
||
for j := 0 to tag.Children.Count - 1 do
|
||
begin
|
||
_ParseTags( tag.Children[j] as TIEDicomTags );
|
||
|
||
// Found tag?
|
||
if Result <> nil then
|
||
Exit;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
{}
|
||
begin
|
||
result := nil;
|
||
_ParseTags( DICOM_Tags );
|
||
end;
|
||
{$endif}
|
||
|
||
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.IPTC_HasIPTCData
|
||
|
||
<FM>Declaration<FC>
|
||
function IPTC_HasIPTCData : Boolean; (read-only)
|
||
|
||
<FM>Description<FN>
|
||
Returns true if there are any IPTC tags in the current image.
|
||
|
||
This is a shortcut function that calls:
|
||
<FC>Result := IPTC_Info.Count > 0;
|
||
|
||
<FM>Examples<FC>
|
||
btnShowIPTC.Enabled := ImageEnView1.IO.Params.IPTC_HasIPTCData;
|
||
!!}
|
||
function TIOParamsHelper.IPTC_HasIPTCData : Boolean;
|
||
begin
|
||
Result := IPTC_Info.Count > 0;
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.DICOM_HasDicomTags
|
||
|
||
<FM>Declaration<FC>
|
||
function DICOM_HasDicomTags : Boolean; (read-only)
|
||
|
||
<FM>Description<FN>
|
||
Returns true if there are any Dicom tags in the current image.
|
||
|
||
This is a shortcut function that calls:
|
||
<FC>Result := DICOM_Info.Count > 0;
|
||
|
||
<FM>Examples<FC>
|
||
btnShowDicom.Enabled := ImageEnView1.IO.Params.DICOM_HasDicomTags;
|
||
!!}
|
||
function TIOParamsHelper.DICOM_HasDicomTags : Boolean;
|
||
begin
|
||
{$ifdef IEINCLUDEDICOM}
|
||
Result := DICOM_Tags.Count > 0;
|
||
{$ELSE}
|
||
Result := False;
|
||
{$endif}
|
||
end;
|
||
|
||
{!!
|
||
<FS>TIOParamsHelper.XMP_HasXMPData
|
||
|
||
<FM>Declaration<FC>
|
||
function XMP_HasXMPData : Boolean; (read-only)
|
||
|
||
<FM>Description<FN>
|
||
Returns true if there are any XMP tags in the current image.
|
||
|
||
This is a shortcut function that calls:
|
||
<FC>Result := XMP_Info <> '';
|
||
|
||
<FM>Examples<FC>
|
||
btnShowXMP.Enabled := ImageEnView1.IO.Params.XMP_HasXMPData;
|
||
!!}
|
||
function TIOParamsHelper.XMP_HasXMPData : Boolean;
|
||
begin
|
||
Result := XMP_Info <> '';
|
||
end;
|
||
|
||
{$endif}
|
||
|
||
|
||
// GENERAL EXIF METHODS
|
||
|
||
{!!
|
||
<FS>ExifCompatibleFile
|
||
|
||
<FM>Declaration<FC>
|
||
function ExifCompatibleFile(const sFilename: string): boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns true if the specified filename has an extension of a file type that supports EXIF reading (JPEG, TIFF or Camera Raw).
|
||
|
||
<FM>Examples<FC>
|
||
// Enable button if the selected file may contain exif fields
|
||
btnShowExif.Enabled := ExifCompatibleFile( MyFileListBox.Filename );
|
||
!!}
|
||
// return true if the specified filename can support writing of EXIF Fields
|
||
function ExifCompatibleFile(const sFilename: string): boolean;
|
||
begin
|
||
Result := IEFilenameInExtensions(sFilename, EXIF_COMPATIBLE_EXTENSIONS);
|
||
end;
|
||
|
||
{!!
|
||
<FS>ReadExifCameraFieldsFromFile
|
||
|
||
<FM>Declaration<FC>
|
||
function ReadExifCameraFieldsFromFile(const sFilename : string;
|
||
out sCameraModel : string;
|
||
out sExposureTime : string;
|
||
out sFlashMode : string
|
||
) : boolean;
|
||
|
||
<FM>Description<FN>
|
||
Retrieves camera related EXIF data from a file. The following properties are returned:
|
||
- <A TIOParamsHelper.EXIF_Camera_Str>
|
||
- <A TIOParamsHelper.EXIF_ExposureTime_Str>
|
||
- <A TIOParams.EXIF_Flash>
|
||
|
||
Returns false if <FC>sFilename<FN> is not a file type that supports EXIF.
|
||
|
||
<FM>Examples<FC>
|
||
// Show Camera data for selected file
|
||
if ReadExifCameraFieldsFromFile( MyFileListBox.Filename, sCameraModel, sExposureTime, sFlashMode ) then
|
||
begin
|
||
lblCameraModel .Caption := sCameraModel;
|
||
lblExposureTime.Caption := sExposureTime;
|
||
lblFlashMode .Caption := sFlashMode;
|
||
end
|
||
else
|
||
begin
|
||
lblCameraModel .Caption := '';
|
||
lblExposureTime.Caption := '';
|
||
lblFlashMode .Caption := '';
|
||
end;
|
||
!!}
|
||
// Formerly GetUsefulExifFields
|
||
{$IFDEF Delphi2005orNewer}
|
||
function ReadExifCameraFieldsFromFile(const sFilename : string;
|
||
out sCameraModel : string;
|
||
out sExposureTime : string;
|
||
out sFlashMode : string
|
||
) : boolean;
|
||
var
|
||
aImageEnIO: TImageEnIO;
|
||
begin
|
||
result := false;
|
||
if ExifCompatibleFile(sFilename) then
|
||
try
|
||
aImageEnIO := TImageEnIO.create(nil);
|
||
try
|
||
aImageEnIO.ParamsFromFile(sFilename);
|
||
if aImageEnIO.Params.EXIF_HasEXIFData then
|
||
begin
|
||
sCameraModel := String( aImageEnIO.Params.EXIF_Camera_Str );
|
||
sExposureTime := String( aImageEnIO.Params.EXIF_ExposureTime_Str );
|
||
sFlashMode := FlashModeToString(aImageEnIO.Params.EXIF_Flash);
|
||
|
||
result := (sCameraModel <> '') or (sExposureTime <> '');
|
||
end;
|
||
|
||
finally
|
||
aImageEnIO.Free;
|
||
end;
|
||
|
||
except
|
||
// ERROR
|
||
end;
|
||
end;
|
||
{$ENDIF}
|
||
|
||
|
||
function _ReadExifGPSFieldsFromFile(const sFilename : string;
|
||
out GPSLatitude: Double;
|
||
out GPSLongitude: Double;
|
||
out sGPSLatitude: string;
|
||
out sGPSLongitude: string
|
||
) : boolean;
|
||
var
|
||
aImageEnIO: TImageEnIO;
|
||
begin
|
||
result := false;
|
||
GPSLatitude := 0;
|
||
GPSLongitude := 0;
|
||
sGPSLatitude := '';
|
||
sGPSLongitude := '';
|
||
|
||
if ExifCompatibleFile(sFilename) then
|
||
try
|
||
aImageEnIO := TImageEnIO.create(nil);
|
||
try
|
||
aImageEnIO.ParamsFromFile(sFilename);
|
||
if aImageEnIO.Params.EXIF_HasEXIFData then
|
||
begin
|
||
GPSLatitude := aImageEnIO.Params.EXIF_GPSLatitude;
|
||
GPSLongitude := aImageEnIO.Params.EXIF_GPSLongitude;
|
||
Result := (GPSLatitude <> 0) or (GPSLongitude <> 0);
|
||
if Result then
|
||
begin
|
||
sGPSLatitude := aImageEnIO.Params.EXIF_GPSLatitude_Str;
|
||
sGPSLongitude := aImageEnIO.Params.EXIF_GPSLongitude_Str;
|
||
end;
|
||
end;
|
||
finally
|
||
aImageEnIO.Free;
|
||
end;
|
||
|
||
except
|
||
// ERROR
|
||
end;
|
||
end;
|
||
|
||
{!!
|
||
<FS>ReadExifGPSFieldsFromFile
|
||
|
||
<FM>Declaration<FC>
|
||
function ReadExifGPSFieldsFromFile(const sFilename : string;
|
||
out GPSLatitude: Double;
|
||
out GPSLongitude: Double
|
||
) : boolean; overload;
|
||
|
||
function ReadExifGPSFieldsFromFile(const sFilename : string;
|
||
out sGPSLatitude: string;
|
||
out sGPSLongitude: string
|
||
) : boolean; overload;
|
||
|
||
<FM>Description<FN>
|
||
Retrieves GPS location data from a file. The following properties are returned:
|
||
- <A TIOParams.EXIF_GPSLatitude>
|
||
- <A TIOParams.EXIF_GPSLongitude>
|
||
|
||
Returns false if <FC>sFilename<FN> does not contain any GPS data.
|
||
|
||
<FM>Examples<FC>
|
||
// Show location on map for selected file
|
||
if ReadExifGPSFieldsFromFile( MyFileListBox.Filename, GPSLatitude, GPSLongitude ) then
|
||
Map.NavigateTo( GPSLatitude, GPSLongitude );
|
||
|
||
// Show GPS location for selected file
|
||
if ReadExifGPSFieldsFromFile( MyFileListBox.Filename, sGPSLatitude, sGPSLongitude ) then
|
||
begin
|
||
lblGPSLatitude .Caption := sGPSLatitude;
|
||
lblGPSLongitude.Caption := sGPSLongitude;
|
||
end
|
||
else
|
||
begin
|
||
lblGPSLatitude .Caption := '';
|
||
lblGPSLongitude.Caption := '';
|
||
end;
|
||
!!}
|
||
// Formerly ExifGPSData
|
||
function ReadExifGPSFieldsFromFile(const sFilename : string;
|
||
out GPSLatitude: Double;
|
||
out GPSLongitude: Double
|
||
) : boolean;
|
||
var
|
||
sGPSLatitude: string;
|
||
sGPSLongitude: string;
|
||
begin
|
||
Result := _ReadExifGPSFieldsFromFile( sFilename, GPSLatitude, GPSLongitude, sGPSLatitude, sGPSLongitude);
|
||
end;
|
||
|
||
function ReadExifGPSFieldsFromFile(const sFilename : string;
|
||
out sGPSLatitude: string;
|
||
out sGPSLongitude: string
|
||
) : boolean;
|
||
var
|
||
GPSLatitude: Double;
|
||
GPSLongitude: Double;
|
||
begin
|
||
Result := _ReadExifGPSFieldsFromFile( sFilename, GPSLatitude, GPSLongitude, sGPSLatitude, sGPSLongitude);
|
||
end;
|
||
|
||
|
||
// EXIF TAG ROUTINES
|
||
|
||
function ExifFieldToTag(const sExifField : string) : string;
|
||
begin
|
||
Result := Exif_Tag_Prefix + StringReplace(sExifField, ' ', '-', [rfReplaceAll]) + Exif_Tag_Suffix;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>ContainsExifTag
|
||
|
||
<FM>Declaration<FC>
|
||
function ContainsExifTag(const Text: string): Boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns true if <FC>Text<FN> contains an exif tag, such as %EXIF-User-Comment%
|
||
|
||
<FM>Exif Tags<FN>
|
||
Exif tags allow creation of generic text blocks where the data within the text is replaced with EXIF data (in a similar way to a mail merge). For example, a user may insert the exif tag, %EXIF-User-Comment%, you can then call <A ReplaceExifTags> to replace the tag with the actually value of the <A TIOParams.EXIF_UserComment> field.
|
||
|
||
BEFORE:
|
||
Description: %EXIF-User-Comment%
|
||
Camera: %EXIF-Camera-Make%
|
||
Shutter Speed: %EXIF-Shutter-Speed%
|
||
|
||
AFTER (Example):
|
||
Description: Eiffel Tower
|
||
Camera: Nikon
|
||
Shutter Speed: 1/200 second
|
||
|
||
<FM>Examples<FC>
|
||
// Replace the exif tags in memo with the actual values of the current image
|
||
if ContainsExifTag( Memo1.Text ) then
|
||
Memo1.Text := ReplaceExifTags( Memo1.Text, ImageEnView1.IO.Params );
|
||
!!}
|
||
function ContainsExifTag(const Text: string): Boolean;
|
||
begin
|
||
Result := Pos(uppercase(Exif_Tag_Prefix), uppercase(Text)) > 0;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>GetExifTagList
|
||
|
||
<FM>Declaration<FC>
|
||
procedure GetExifTagList(ssDest: TStrings);
|
||
|
||
<FM>Description<FN>
|
||
Fill <FC>ssDest<FN> with all available exif tags, such as %EXIF-User-Comment%
|
||
|
||
<FM>Exif Tags<FN>
|
||
Exif tags allow creation of generic text blocks where the data within the text is replaced with EXIF data (in a similar way to a mail merge). For example, a user may insert the exif tag, %EXIF-User-Comment%, you can then call <A ReplaceExifTags> to replace the tag with the actually value of the <A TIOParams.EXIF_UserComment> field.
|
||
|
||
BEFORE:
|
||
Description: %EXIF-User-Comment%
|
||
Camera: %EXIF-Camera-Make%
|
||
Shutter Speed: %EXIF-Shutter-Speed%
|
||
|
||
AFTER (Example):
|
||
Description: Eiffel Tower
|
||
Camera: Nikon
|
||
Shutter Speed: 1/200 second
|
||
|
||
<FM>Examples<FC>
|
||
// Fill our tag selector with all available Exif tags
|
||
GetExifTagList( lbxExifTagList.Items );
|
||
!!}
|
||
procedure GetExifTagList(ssDest: TStrings);
|
||
var
|
||
i: integer;
|
||
begin
|
||
// fill the strings with the EXIF tag names
|
||
for i := Low(ExifTags) to High(ExifTags) do
|
||
ssDest.Add( ExifFieldToTag(ExifTags[ i ].Desc) );
|
||
end;
|
||
|
||
{$IFDEF Delphi2005orNewer}
|
||
function _ReplaceExifTags(const Text: string; EXIFSource : TIOParams; bValid, bSample : Boolean): string;
|
||
var
|
||
i: Integer;
|
||
sValue: string;
|
||
begin
|
||
// NOTE: May be slow with large text blocks!
|
||
for i := Low(ExifTags) to high(ExifTags) do
|
||
begin
|
||
if bSample then
|
||
sValue := 'Sample ' + ExifTags[ i ].Desc
|
||
else
|
||
if bValid then
|
||
sValue := EXIFSource.EXIF_AsStr[ i ]
|
||
else
|
||
sValue := '';
|
||
|
||
Result := StringReplace(result, ExifFieldToTag(ExifTags[ i ].Desc), sValue, [rfReplaceAll, rfIgnoreCase]);
|
||
end;
|
||
end;
|
||
{$ENDIF}
|
||
|
||
{!!
|
||
<FS>ReplaceExifTags
|
||
|
||
<FM>Declaration<FC>
|
||
function ReplaceExifTags(const Text: string; EXIFSource : TIOParams): string; overload;
|
||
function ReplaceExifTags(const Text: string; const sEXIFSourceFilename : string): string; overload;
|
||
|
||
<FM>Description<FN>
|
||
Replace all Exif tags found in <FC>Text<FN> with the actual EXIF properties of the current image, or an image loaded from file.
|
||
|
||
Note: Specify sEXIFSourceFilename as <FC>Example_File_Only<FN> to show example properties to the user (e.g. instead of reading the <A TIOParams.EXIF_UserComment> field from file, it will insert 'Sample User Comment')
|
||
|
||
<FM>Exif Tags<FN>
|
||
Exif tags allow creation of generic text blocks where the data within the text is replaced with EXIF data (in a similar way to a mail merge). For example, a user may insert the exif tag, %EXIF-User-Comment%, you can then call <A ReplaceExifTags> to replace the tag with the actually value of the <A TIOParams.EXIF_UserComment> field.
|
||
|
||
BEFORE:
|
||
Description: %EXIF-User-Comment%
|
||
Camera: %EXIF-Camera-Make%
|
||
Shutter Speed: %EXIF-Shutter-Speed%
|
||
|
||
AFTER (Example):
|
||
Description: Eiffel Tower
|
||
Camera: Nikon
|
||
Shutter Speed: 1/200 second
|
||
|
||
<FM>Examples<FC>
|
||
// Replace the exif tags in memo with the actual values of the current image
|
||
if ContainsExifTag( Memo1.Text ) then
|
||
Memo1.Text := ReplaceExifTags( Memo1.Text, ImageEnView1.IO.Params );
|
||
|
||
// Show sample output
|
||
memSample.Text := ReplaceExifTags( 'Camera: %EXIF-Camera-Make%'#13#10'Shutter Speed: %EXIF-Shutter-Speed%', Example_File_Only );
|
||
(*
|
||
Which outputs:
|
||
Camera: Sample Camera Make
|
||
Shutter Speed: Sample Shutter Speed
|
||
*)
|
||
!!}
|
||
{$IFDEF Delphi2005orNewer}
|
||
function ReplaceExifTags(const Text: string; EXIFSource : TIOParams): string;
|
||
var
|
||
bValid: Boolean;
|
||
begin
|
||
Result := Text;
|
||
|
||
// Anything to do?
|
||
if ContainsExifTag(Text) then
|
||
begin
|
||
bValid := EXIFSource.EXIF_HasEXIFData;
|
||
Result := _ReplaceExifTags(Text, EXIFSource, bValid, False);
|
||
end;
|
||
end;
|
||
{$ENDIF}
|
||
|
||
{$IFDEF Delphi2005orNewer}
|
||
function ReplaceExifTags(const Text: string; const sEXIFSourceFilename : string): string;
|
||
var
|
||
bValid: Boolean;
|
||
aImageEnIO: TImageEnIO;
|
||
bSampleOnly: Boolean;
|
||
begin
|
||
Result := Text;
|
||
|
||
// Anything to do?
|
||
if ContainsExifTag(Text) = False then
|
||
Exit;
|
||
|
||
bSampleOnly := SameText(sEXIFSourceFilename, Example_File_Only);
|
||
aImageEnIO := TImageEnIO.create(nil);
|
||
try
|
||
aImageEnIO.ParamsFromFile(sEXIFSourceFilename);
|
||
|
||
bValid := False;
|
||
if EXIFCompatibleFile(sEXIFSourceFilename) then
|
||
try
|
||
AImageEnIO.ParamsFromFile(sEXIFSourceFilename);
|
||
bValid := AImageEnIO.Params.EXIF_HasEXIFData;
|
||
except
|
||
// ERROR
|
||
end;
|
||
|
||
Result := _ReplaceExifTags(Text, AImageEnIO.Params, bValid, bSampleOnly);
|
||
finally
|
||
aImageEnIO.Free;
|
||
end;
|
||
end;
|
||
{$ENDIF}
|
||
|
||
|
||
// GENERAL IPTC METHODS
|
||
|
||
{!!
|
||
<FS>IPTCCompatibleFile
|
||
|
||
<FM>Declaration<FC>
|
||
function IPTCCompatibleFile(const sFilename: string): boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns true if the specified filename has an extension of a file type that supports IPTC (i.e. JPEG or TIFF).
|
||
|
||
<FM>Examples<FC>
|
||
// Enable button if the selected file may contain IPTC
|
||
btnShowIPTC.Enabled := IPTCCompatibleFile( MyFileListBox.Filename );
|
||
!!}
|
||
function IPTCCompatibleFile(const sFilename : string) : boolean;
|
||
begin
|
||
result := IEFilenameInExtensions(sFilename, IPTC_COMPATIBLE_EXTENSIONS);
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>ReadIPTCDescriptionAndKeywordsFromFile
|
||
|
||
<FM>Declaration<FC>
|
||
function ReadIPTCDescriptionAndKeywordsFromFile(const sFilename: string;
|
||
out sDescription: string;
|
||
ssKeywords: TStrings = nil) : Boolean;
|
||
|
||
<FM>Description<FN>
|
||
Retrieves the description and keywords from the IPTC data of a file. The following records are returned:
|
||
- PhotoShop_IPTC_Records/IPTC_PS_Caption
|
||
- PhotoShop_IPTC_Records/IPTC_PS_Keywords
|
||
|
||
Returns false if the file does not contain an IPTC description or keywords.
|
||
|
||
Note: ssKeywords can be nil
|
||
|
||
<FM>Example<FC>
|
||
// Show keyword and description of selected file
|
||
if ReadIPTCCameraFieldsFromFile( MyFileListBox.Filename, sDescription, ssKeywords ) then
|
||
begin
|
||
lblDescription .Caption := sDescription;
|
||
lblKeywords .Caption := ssKeywords.CommaText;
|
||
end
|
||
else
|
||
begin
|
||
lblDescription .Caption := '';
|
||
lblKeywords .Caption := '';
|
||
end;
|
||
!!}
|
||
function ReadIPTCDescriptionAndKeywordsFromFile(const sFilename: string;
|
||
out sDescription: string;
|
||
ssKeywords: TStrings = nil) : Boolean;
|
||
var
|
||
aImageEnIO: TImageEnIO;
|
||
begin
|
||
result := false;
|
||
sDescription := '';
|
||
|
||
if IPTCCompatibleFile(sFilename) then
|
||
try
|
||
aImageEnIO := TImageEnIO.create(nil);
|
||
try
|
||
aImageEnIO.ParamsFromFile(sFilename);
|
||
|
||
// DESCRIPTION FIELD
|
||
sDescription := aImageEnIO.Params.ReadIPTCField(PhotoShop_IPTC_Records, IPTC_PS_Caption);
|
||
if sDescription <> '' then
|
||
Result := True;
|
||
|
||
// KEYWORD FIELD (ssKeywords can be nil)
|
||
if assigned(ssKeywords) then
|
||
begin
|
||
// get the keywords
|
||
aImageEnIO.Params.ReadIPTCField(PhotoShop_IPTC_Records, IPTC_PS_Caption, ssKeywords);
|
||
if ssKeywords.Text <> '' then
|
||
Result := True;
|
||
end;
|
||
|
||
finally
|
||
aImageEnIO.Free;
|
||
end;
|
||
|
||
except
|
||
// ERROR
|
||
end;
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>WriteIPTCDescriptionAndKeywordsToFile
|
||
|
||
<FM>Declaration<FC>
|
||
procedure WriteIPTCDescriptionAndKeywordsToFile(const sFilename: string;
|
||
sDescription: string;
|
||
ssKeywords: TStrings = nil);
|
||
|
||
<FM>Description<FN>
|
||
Saves a description and keywords to the IPTC data of a file. The following records are used:
|
||
- PhotoShop_IPTC_Records/IPTC_PS_Caption
|
||
- PhotoShop_IPTC_Records/IPTC_PS_Keywords
|
||
|
||
Notes:
|
||
- Specify the <FC>SKIP_DESCRIPTION<FN> const to avoid updating the description
|
||
- Pass ssKeywords as nil to avoid updating the keywords
|
||
|
||
<FM>Examples<FC>
|
||
// Save description and keywords to a file
|
||
WriteIPTCDescriptionAndKeywordsToFile( 'D:\MyImage.jpeg', edtDescription.Text, lbxKeywords.Items );
|
||
|
||
// Save description to a file
|
||
WriteIPTCDescriptionAndKeywordsToFile( 'D:\MyImage.jpeg', edtDescription.Text, nil );
|
||
|
||
// Save keywords to a file
|
||
WriteIPTCDescriptionAndKeywordsToFile( 'D:\MyImage.jpeg', SKIP_DESCRIPTION, lbxKeywords.Items );
|
||
!!}
|
||
// Formerly WriteIPTCDescriptionAndKeywords
|
||
procedure WriteIPTCDescriptionAndKeywordsToFile(const sFilename: string;
|
||
sDescription: string;
|
||
ssKeywords: TStrings = nil);
|
||
var
|
||
aImageEnIO: TImageEnIO;
|
||
dFileDate : TDateTime;
|
||
bCanUpdateJPEG: Boolean;
|
||
begin
|
||
aImageEnIO := TImageEnIO.create(nil);
|
||
try
|
||
if FileExists(sFilename) = False then
|
||
raise EIEException.create('Cannot find file to update: ' + sFilename);
|
||
|
||
bCanUpdateJPEG := IEFilenameInExtensions(sFilename, '*.jpeg;*.jpg;*.jpe;');
|
||
if bCanUpdateJPEG then
|
||
aImageEnIO.ParamsFromFile(sFilename)
|
||
else
|
||
aImageEnIO.LoadFromFile(sFilename);
|
||
|
||
// DESCRIPTION
|
||
if sDescription <> SKIP_DESCRIPTION then
|
||
aImageEnIO.Params.WriteIPTCField(PhotoShop_IPTC_Records, IPTC_PS_Caption, sDescription);
|
||
|
||
// KEYWORDS
|
||
if Assigned(ssKeywords) then
|
||
aImageEnIO.Params.WriteIPTCField(PhotoShop_IPTC_Records, IPTC_PS_Keywords, ssKeywords);
|
||
|
||
{$WARNINGS OFF} // FileAge is deprecated
|
||
dFileDate := 0;
|
||
if Maintain_File_Dates_On_Meta_Write then
|
||
dFileDate := FileDateToDateTime(FileAge(sFileName));
|
||
{$WARNINGS ON}
|
||
|
||
// Can write IPTC data?
|
||
if (aImageEnIO.Params.FileType in [ioJPEG, ioTIFF]) = False then
|
||
raise EIEException.create('File format does not support IPTC');
|
||
|
||
if bCanUpdateJPEG then
|
||
aImageEnIO.InjectJpegIPTC(sFileName)
|
||
else
|
||
aImageEnIO.SaveToFile(sFilename);
|
||
|
||
if Maintain_File_Dates_On_Meta_Write and (dFileDate <> 0) then
|
||
IEFileSetDate(sFileName, dFileDate);
|
||
|
||
finally
|
||
aImageEnIO.Free;
|
||
end;
|
||
end;
|
||
|
||
|
||
// OTHER METHODS
|
||
|
||
{!!
|
||
<FS>DicomCompatibleFile
|
||
|
||
<FM>Declaration<FC>
|
||
function DicomCompatibleFile(const sFilename: string): boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns true if the specified filename has a DICOM extension (i.e. *.DICOM, *.DCM, *.DIC or *.V2).
|
||
|
||
<FM>Examples<FC>
|
||
// Enable button if the selected file is Dicom format
|
||
btnShowDicom.Enabled := DicomCompatibleFile( MyFileListBox.Filename );
|
||
!!}
|
||
function DicomCompatibleFile(const sFilename: string): boolean;
|
||
begin
|
||
{$ifdef IEINCLUDEDICOM}
|
||
result := IEFilenameToInternalFileType( sFileName ) = ioDicom;
|
||
{$ELSE}
|
||
result := False;
|
||
{$endif}
|
||
end;
|
||
|
||
{!!
|
||
<FS>XMPCompatibleFile
|
||
|
||
<FM>Declaration<FC>
|
||
function XMPCompatibleFile(const sFilename: string): boolean;
|
||
|
||
<FM>Description<FN>
|
||
Returns true if the specified filename has an extension of a file type that supports XMP meta-data (i.e. JPEG, TIFF or PSD).
|
||
|
||
<FM>Examples<FC>
|
||
// Enable button if the selected file may contain XMP meta-data
|
||
btnShowXMP.Enabled := XMPCompatibleFile( MyFileListBox.Filename );
|
||
!!}
|
||
function XMPCompatibleFile(const sFilename: string): boolean;
|
||
begin
|
||
result := IEFilenameInExtensions( sFilename, XMP_COMPATIBLE_EXTENSIONS );
|
||
end;
|
||
|
||
|
||
{!!
|
||
<FS>iexMetaHelpers
|
||
|
||
<FN>iexMetaHelpers.pas provides helper functions for working with the EXIF and IPTC meta data in compatible files (e.g. JPEG and TIFF files). It includes an array of all common EXIF fields and provides methods for reading and writing fields by ID, as well as displaying and saving data in a TStringGrid or TListView. Also supports DICOM meta data.
|
||
|
||
Simply add iexMetaHelpers to your uses clause to access the new methods
|
||
|
||
<FM>IOPARAMS EXIF HELPER FUNCTIONS<FN>
|
||
Provide string formatted access (human-readable) to some <L TIOParams>EXIF properties</L> (that are complex to interpret):
|
||
<TABLE2>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_AsStr></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_CanWriteEXIFData></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_FieldDescription></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_ApertureValue_Str></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_Camera_Str></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_ExposureTime_Str></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_FNumber_Str></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_MaxApertureValue_Str></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_ShutterSpeedValue_Str></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_SubjectArea_Str></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_SubjectLocation_Str></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_XResolution_Str></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_YResolution_Str></C> </R>
|
||
</TABLE>
|
||
|
||
<FM>IOPARAMS XMP HELPER FUNCTIONS<FN>
|
||
Helper functions for XMP meta-data:
|
||
<TABLE2>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.XMP_AsStr></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.XMP_AsInt></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.XMP_AsDateTime></C> </R>
|
||
</TABLE>
|
||
|
||
<FM>IOPARAMS METADATA OUTPUT FUNCTIONS<FN>
|
||
Helper functions to output EXIF, IPTC, Dicom and XMP fields to a TStrings Object:
|
||
<TABLE2>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.EXIF_WriteToStrings></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.IPTC_WriteToStrings></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.Dicom_WriteToStrings></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.XMP_WriteToStrings></C> </R>
|
||
</TABLE>
|
||
|
||
<FM>OTHER IOPARAMS HELPER FUNCTIONS<FN>
|
||
General Helper functions for working with meta-data:
|
||
<TABLE2>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.DICOM_FindTag></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.IPTC_HasIPTCData></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.DICOM_HasDicomTags></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TIOParamsHelper.XMP_HasXMPData></C> </R>
|
||
</TABLE>
|
||
|
||
|
||
<FM>STRINGGRID HELPER FUNCTIONS<FN>
|
||
Helper functions to output EXIF, IPTC and Dicom fields to a TStringGrid:
|
||
<TABLE2>
|
||
<R> <C_IMG_METHOD> <C><A TStringGridHelper.NewGridForExif></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TStringGridHelper.ReadGridFromExif></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TStringGridHelper.WriteGridToExif></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TStringGridHelper.NewGridForIPTC></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TStringGridHelper.ReadGridFromIPTC></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TStringGridHelper.WriteGridToIPTC></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TStringGridHelper.ReadGridFromDicom></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TStringGridHelper.ReadGridFromXMP></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TStringGridHelper.InitializeGrid></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TStringGridHelper.ClearGridFields></C> </R>
|
||
</TABLE>
|
||
|
||
<FM>LISTVIEW HELPER FUNCTIONS<FN>
|
||
Helper functions to output EXIF and IPTC fields to a TListView:
|
||
<TABLE2>
|
||
<R> <C_IMG_METHOD> <C><A TListViewHelper.NewListForExif></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TListViewHelper.ReadListFromExif></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TListViewHelper.WriteListToExif></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TListViewHelper.NewListForIPTC></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TListViewHelper.ReadListFromIPTC></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TListViewHelper.WriteListToIPTC></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TListViewHelper.ReadListFromDicom></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TListViewHelper.ReadListFromXMP></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TListViewHelper.InitializeList></C> </R>
|
||
<R> <C_IMG_METHOD> <C><A TListViewHelper.ClearListFields></C> </R>
|
||
</TABLE>
|
||
|
||
<FM>GENERAL EXIF METHODS<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_GLOBMETHOD> <C><A EXIFCompatibleFile></C> </R>
|
||
<R> <C_IMG_GLOBMETHOD> <C><A ReadEXIFCameraFieldsFromFile></C> </R>
|
||
<R> <C_IMG_GLOBMETHOD> <C><A ReadEXIFGPSFieldsFromFile></C> </R>
|
||
</TABLE>
|
||
|
||
<FM>GENERAL IPTC METHODS<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_GLOBMETHOD> <C><A IPTCCompatibleFile></C> </R>
|
||
<R> <C_IMG_GLOBMETHOD> <C><A ReadIPTCDescriptionAndKeywordsFromFile></C> </R>
|
||
<R> <C_IMG_GLOBMETHOD> <C><A WriteIPTCDescriptionAndKeywordsToFile></C> </R>
|
||
</TABLE>
|
||
|
||
<FM>EXIF TAG METHODS<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_GLOBMETHOD> <C><A ContainsExifTag></C> </R>
|
||
<R> <C_IMG_GLOBMETHOD> <C><A GetExifTagList></C> </R>
|
||
<R> <C_IMG_GLOBMETHOD> <C><A ReplaceExifTags></C> </R>
|
||
</TABLE>
|
||
|
||
<FM>OTHER METHODS<FN>
|
||
<TABLE2>
|
||
<R> <C_IMG_GLOBMETHOD> <C><A DicomCompatibleFile></C> </R>
|
||
<R> <C_IMG_GLOBMETHOD> <C><A XMPCompatibleFile></C> </R>
|
||
</TABLE>
|
||
|
||
* Note: Delphi/C++ 2005 or newer is required to use helper classes
|
||
!!}
|
||
|
||
end.
|
||
|
||
|