fpexif: Delphi support for XMP metadata.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9012 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2023-11-06 16:42:17 +00:00
parent 3040781187
commit 035442ee36
9 changed files with 297 additions and 63 deletions

View File

@@ -10,11 +10,9 @@ object MainForm: TMainForm
Font.Height = -11 Font.Height = -11
Font.Name = 'Tahoma' Font.Name = 'Tahoma'
Font.Style = [] Font.Style = []
OldCreateOrder = True
ShowHint = True ShowHint = True
OnCreate = FormCreate OnCreate = FormCreate
OnDestroy = FormDestroy OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13 TextHeight = 13
object Splitter2: TSplitter object Splitter2: TSplitter
Left = 274 Left = 274
@@ -181,7 +179,7 @@ object MainForm: TMainForm
Top = 21 Top = 21
Width = 647 Width = 647
Height = 550 Height = 550
ActivePage = PgMetadata ActivePage = PgXMP
Align = alClient Align = alClient
TabOrder = 1 TabOrder = 1
OnChange = PageControl1Change OnChange = PageControl1Change
@@ -241,6 +239,87 @@ object MainForm: TMainForm
end end
end end
end end
object PgXMP: TTabSheet
Caption = 'XMP'
ImageIndex = 2
object Splitter4: TSplitter
Left = 0
Top = 150
Width = 639
Height = 3
Cursor = crVSplit
Align = alTop
end
object XMPListView: TListView
Left = 0
Top = 0
Width = 639
Height = 150
Align = alTop
Columns = <
item
Caption = 'Description'
Width = 200
end
item
Caption = 'Value'
Width = 200
end>
TabOrder = 0
ViewStyle = vsReport
end
object XMPSynEdit: TMemo
Left = 0
Top = 153
Width = 639
Height = 335
Align = alClient
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Courier New'
Font.Style = []
ParentFont = False
TabOrder = 1
end
object Panel6: TPanel
Left = 0
Top = 488
Width = 639
Height = 34
Align = alBottom
BevelOuter = bvNone
TabOrder = 2
object cbProcessXMP: TCheckBox
Left = 8
Top = 8
Width = 129
Height = 17
Caption = 'Load && display XMP'
Checked = True
State = cbChecked
TabOrder = 0
end
object btnApplyChangesXMP: TButton
Left = 143
Top = 7
Width = 98
Height = 25
Caption = 'Apply changes'
TabOrder = 1
OnClick = btnApplyChangesXMPClick
end
object btnSaveXMP: TButton
Left = 247
Top = 7
Width = 75
Height = 25
Caption = 'Save'
TabOrder = 2
OnClick = btnSaveXMPClick
end
end
end
object PgImage: TTabSheet object PgImage: TTabSheet
Caption = 'Image' Caption = 'Image'
object Image: TImage object Image: TImage

View File

@@ -1,8 +1,8 @@
unit mdvMain; unit mdvMain;
{$IFDEF FPC} {$IFDEF FPC}
!!! THIS PROGRAM IS INTENDED FOR DELPHI ONLY !!! THIS PROGRAM IS INTENDED FOR DELPHI ONLY !!!
{$ENDIF} {$ENDIF}
interface interface
@@ -44,6 +44,14 @@ type
Splitter2: TSplitter; Splitter2: TSplitter;
DriveComboBox1: TDriveComboBox; DriveComboBox1: TDriveComboBox;
Panel5: TPanel; Panel5: TPanel;
PgXMP: TTabSheet;
XMPListView: TListView;
Splitter4: TSplitter;
XMPSynEdit: TMemo;
Panel6: TPanel;
cbProcessXMP: TCheckBox;
btnApplyChangesXMP: TButton;
btnSaveXMP: TButton;
procedure BtnChangeDateClick(Sender: TObject); procedure BtnChangeDateClick(Sender: TObject);
procedure CbShowTagIDsChange(Sender: TObject); procedure CbShowTagIDsChange(Sender: TObject);
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
@@ -63,6 +71,8 @@ type
procedure ShellListViewChange(Sender: TObject); procedure ShellListViewChange(Sender: TObject);
procedure DriveComboBox1Change(Sender: TObject); procedure DriveComboBox1Change(Sender: TObject);
procedure Panel5Resize(Sender: TObject); procedure Panel5Resize(Sender: TObject);
procedure btnApplyChangesXMPClick(Sender: TObject);
procedure btnSaveXMPClick(Sender: TObject);
private private
FFileName: String; FFileName: String;
FImgInfo: TImgInfo; FImgInfo: TImgInfo;
@@ -70,6 +80,7 @@ type
FImageOrientation: TExifOrientation; FImageOrientation: TExifOrientation;
procedure LoadFile(const AFileName: String); procedure LoadFile(const AFileName: String);
procedure LoadFromIni; procedure LoadFromIni;
procedure LoadXMPTags;
procedure SaveToIni; procedure SaveToIni;
procedure UpdateCaption; procedure UpdateCaption;
@@ -194,6 +205,24 @@ begin
//ShellListView.Parent.DoubleBuffered := true; //ShellListView.Parent.DoubleBuffered := true;
end; end;
procedure TMainForm.btnApplyChangesXMPClick(Sender: TObject);
var
ms: TMemoryStream;
begin
if Assigned(FImgInfo) and FImgInfo.HasXMP then
begin
ms := TMemoryStream.Create;
try
XMPSynEdit.Lines.SaveToStream(ms);
ms.Position := 0;
FImgInfo.XMPData.LoadFromStream(ms);
LoadXMPTags;
finally
ms.Free;
end;
end;
end;
procedure TMainForm.BtnChangeDateClick(Sender: TObject); procedure TMainForm.BtnChangeDateClick(Sender: TObject);
var var
lTag: TTag; lTag: TTag;
@@ -225,6 +254,19 @@ begin
FImgInfo.SaveToFile(fn); FImgInfo.SaveToFile(fn);
end; end;
procedure TMainForm.btnSaveXMPClick(Sender: TObject);
var
fn: String;
begin
if Assigned(FImgInfo) then
begin
fn := FImgInfo.FileName;
fn := ChangeFileExt(fn, '') + '_modified' + ExtractFileExt(fn);
FImgInfo.SaveToFile(fn);
ShowMessage('Modified image saved as ' + fn);
end;
end;
procedure TMainForm.CbShowTagIDsChange(Sender: TObject); procedure TMainForm.CbShowTagIDsChange(Sender: TObject);
var var
c: TListColumn; c: TListColumn;
@@ -290,6 +332,10 @@ begin
FImgInfo.MetadataKinds := FImgInfo.MetadataKinds + [mdkExif] - [mdkExifNoMakerNotes] FImgInfo.MetadataKinds := FImgInfo.MetadataKinds + [mdkExif] - [mdkExifNoMakerNotes]
else else
FImgInfo.MetadataKinds := FImgInfo.MetadataKinds - [mdkExif] + [mdkExifNoMakerNotes]; FImgInfo.MetadataKinds := FImgInfo.MetadataKinds - [mdkExif] + [mdkExifNoMakerNotes];
if CbProcessXMP.Checked then
FImgInfo.MetadataKinds := FImgInfo.MetaDataKinds + [mdkXMP]
else
FImgInfo.MetadataKinds := FImgInfo.MetaDataKinds - [mdkXMP];
FImgInfo.LoadFromFile(AFileName); FImgInfo.LoadFromFile(AFileName);
Messages.Hide; Messages.Hide;
except except
@@ -332,6 +378,22 @@ begin
end else end else
DateTimePanel.Hide; DateTimePanel.Hide;
if FImgInfo.HasXMP then begin
ms := TMemoryStream.Create;
try
FImgInfo.XMPData.SaveToStream(ms);
ms.Position := 0;
XMPSynEdit.Lines.LoadFromStream(ms);
LoadXMPTags;
finally
ms.Free;
end;
end else
begin
XMPListView.Clear;
XMPSynEdit.Clear;
end;
if FImgInfo.HasIptc then begin if FImgInfo.HasIptc then begin
for i := 0 to FImgInfo.IptcData.TagCount-1 do begin for i := 0 to FImgInfo.IptcData.TagCount-1 do begin
lTag := FImgInfo.IptcData.TagByIndex[i]; lTag := FImgInfo.IptcData.TagByIndex[i];
@@ -449,6 +511,24 @@ begin
end; end;
end; end;
procedure TMainForm.LoadXMPTags;
var
i: Integer;
item: TListItem;
begin
XMPListView.Items.BeginUpdate;
try
XMPListView.Items.Clear;
for i := 0 to FImgInfo.XMPData.TagCount-1 do begin
item := XMPListView.Items.Add;
item.Caption := FImgInfo.XMPData.TagName[i];
item.SubItems.Add(FImgInfo.XMPData.TagByIndex[i]);
end;
finally
XMPListView.Items.EndUpdate;
end;
end;
procedure TMainForm.PageControl1Change(Sender: TObject); procedure TMainForm.PageControl1Change(Sender: TObject);
var var
crs: TCursor; crs: TCursor;

View File

@@ -141,9 +141,9 @@ object MainForm: TMainForm
Height = 539 Height = 539
Top = 23 Top = 23
Width = 647 Width = 647
ActivePage = PgMetadata ActivePage = PgXMP
Align = alClient Align = alClient
TabIndex = 0 TabIndex = 1
TabOrder = 1 TabOrder = 1
OnChange = PageControlChange OnChange = PageControlChange
object PgMetadata: TTabSheet object PgMetadata: TTabSheet

View File

@@ -126,7 +126,7 @@ type
TAdobeImageResourceBlock = class TAdobeImageResourceBlock = class
public public
Identifier: Word; Identifier: Word;
Name: String; Name: AnsiString;
Data: TBytes; Data: TBytes;
end; end;

View File

@@ -13,11 +13,7 @@ uses
{$IFDEF FPC} {$IFDEF FPC}
LazUTF8, LazUTF8,
{$ENDIF} {$ENDIF}
fpeGlobal, fpeGlobal, fpeXmpData, fpeExifData, fpeIptcData;
{$IFDEF FPC}
fpeXmpData,
{$ENDIF}
fpeExifData, fpeIptcData;
type type
TImgInfo = class; TImgInfo = class;
@@ -67,9 +63,7 @@ type
private private
FExifData: TExifData; FExifData: TExifData;
FIptcData: TIptcData; FIptcData: TIptcData;
{$IFDEF FPC}
FXmpData: TXmpData; FXmpData: TXmpData;
{$ENDIF}
function GetComment: String; function GetComment: String;
function GetWarnings: String; function GetWarnings: String;
procedure SetComment(const AValue: String); procedure SetComment(const AValue: String);
@@ -92,18 +86,14 @@ type
function CreateExifData(ABigEndian: Boolean = false): TExifData; function CreateExifData(ABigEndian: Boolean = false): TExifData;
function CreateIptcData: TIptcData; function CreateIptcData: TIptcData;
{$IFDEF FPC}
function CreateXmpData: TXmpData; function CreateXmpData: TXmpData;
{$ENDIF}
function HasComment: Boolean; function HasComment: Boolean;
function HasExif: Boolean; function HasExif: Boolean;
function HasIptc: Boolean; function HasIptc: Boolean;
function HasThumbnail: Boolean; function HasThumbnail: Boolean;
function HasWarnings: boolean; function HasWarnings: boolean;
{$IFDEF FPC}
function HasXMP: Boolean; function HasXMP: Boolean;
{$ENDIF}
{ Comment stored in the Jpeg COM segment } { Comment stored in the Jpeg COM segment }
property Comment: String read GetComment write SetComment; property Comment: String read GetComment write SetComment;
@@ -128,9 +118,7 @@ type
property ExifData: TExifData read FExifData; property ExifData: TExifData read FExifData;
property IptcData: TIptcData read FIptcData; property IptcData: TIptcData read FIptcData;
{$IFDEF FPC}
property XmpData: TXmpData read FXmpData; property XmpData: TXmpData read FXmpData;
{$ENDIF}
end; end;
@@ -138,8 +126,7 @@ implementation
uses uses
Variants, Variants,
fpeStrConsts, fpeUtils, fpeExifReadWrite, {$IFDEF FPC}fpeXMPReadWrite,{$ENDIF} fpeStrConsts, fpeUtils, fpeExifReadWrite, fpeXMPReadWrite, fpeIptcReadWrite;
fpeIptcReadWrite;
type type
TJpegJFIFSegment = packed record TJpegJFIFSegment = packed record
@@ -276,9 +263,7 @@ begin
FWarnings.Free; FWarnings.Free;
FExifData.Free; FExifData.Free;
FIptcData.Free; FIptcData.Free;
{$IFDEF FPC}
FXmpData.Free; FXmpData.Free;
{$ENDIF}
inherited; inherited;
end; end;
@@ -298,7 +283,6 @@ begin
Result := FIptcData; Result := FIptcData;
end; end;
{$IFDEF FPC}
function TImgInfo.CreateXmpData: TXmpData; function TImgInfo.CreateXmpData: TXmpData;
begin begin
FWarnings.Clear; FWarnings.Clear;
@@ -306,7 +290,6 @@ begin
FXmpData := TXmpData.Create; FXmpData := TXmpData.Create;
Result := FXmpData; Result := FXmpData;
end; end;
{$ENDIF}
procedure TImgInfo.Error(const AMsg: String); procedure TImgInfo.Error(const AMsg: String);
begin begin
@@ -381,12 +364,10 @@ begin
Result := FWarnings.Count > 0; Result := FWarnings.Count > 0;
end; end;
{$IFDEF FPC}
function TImgInfo.HasXMP: Boolean; function TImgInfo.HasXMP: Boolean;
begin begin
Result := FXmpData <> nil; Result := FXmpData <> nil;
end; end;
{$ENDIF}
procedure TImgInfo.LoadFromFile(const AFileName: String); procedure TImgInfo.LoadFromFile(const AFileName: String);
var var
@@ -441,7 +422,7 @@ var
{$IFDEF FPC} {$IFDEF FPC}
s: RawByteString = ''; s: RawByteString = '';
{$ELSE} {$ELSE}
s: String; s: AnsiString;
{$ENDIF} {$ENDIF}
begin begin
// Write the header segment and all metadata segments stored in TImgInfo // Write the header segment and all metadata segments stored in TImgInfo
@@ -588,7 +569,6 @@ begin
finally finally
reader.Free; reader.Free;
end; end;
{$IFDEF FPC}
end else end else
if HasXMPHeader(AStream) and (mdkXMP in FMetadataKinds) then if HasXMPHeader(AStream) and (mdkXMP in FMetadataKinds) then
begin begin
@@ -602,7 +582,6 @@ begin
raise EFpExifReader.Create('Error reading XMP data: ' + E.Message); raise EFpExifReader.Create('Error reading XMP data: ' + E.Message);
end; end;
end; end;
{$ENDIF}
end; end;
end; end;
M_IPTC: M_IPTC:
@@ -842,7 +821,6 @@ begin
end; end;
end; end;
{$IFDEF FPC}
// XMP --> Write another APP1 segment // XMP --> Write another APP1 segment
if (mdkXMP in FMetadataKinds) and HasXMP then if (mdkXMP in FMetadataKinds) and HasXMP then
begin begin
@@ -853,8 +831,7 @@ begin
writer.Free; writer.Free;
end; end;
end; end;
{$ENDIF}
// Write IPTCSegment (APP13) // Write IPTCSegment (APP13)
if (mdkIPTC in FMetadataKinds) and HasIPTC then begin if (mdkIPTC in FMetadataKinds) and HasIPTC then begin
writer := TIptcWriter.Create(Self); writer := TIptcWriter.Create(Self);

View File

@@ -20,24 +20,28 @@ uses
Classes, SysUtils, contnrs, Classes, SysUtils, contnrs,
{$IFDEF FPC} {$IFDEF FPC}
laz2_dom, laz2_xmlread, laz2_dom, laz2_xmlread,
{$ELSE}
XMLDoc, XMLIntf,
{$ENDIF} {$ENDIF}
fpeGlobal, fpeTags; fpeGlobal, fpeTags;
type type
TXMPData = class TXMPData = class
private private
FData: String; FData: AnsiString;
{$IFDEF FPC}
FDoc: TXMLDocument; FDoc: TXMLDocument;
{$ELSE}
FDoc: IXMLDocument;
{$ENDIF}
FTags: TStringList; FTags: TStringList;
function GetTagByIndex(AIndex: Integer): String; function GetTagByIndex(AIndex: Integer): String;
function GetTagByName(ATagName: String): String; function GetTagByName(ATagName: String): String;
function GetTagName(AIndex: Integer): String; function GetTagName(AIndex: Integer): String;
function GetTagCount: Integer; function GetTagCount: Integer;
protected protected
{$IFDEF FPC} procedure Create_RDFDescription_Tags(ANode: {$IFDEF FPC}TDOMNode{$ELSE}IXMLNode{$ENDIF});
procedure Create_RDFDescription_Tags(ANode: TDOMNode);
procedure CreateTags; procedure CreateTags;
{$ENDIF}
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
@@ -69,61 +73,120 @@ begin
inherited; inherited;
end; end;
{$IFDEF FPC} procedure TXMPData.Create_RDFDescription_Tags(ANode: {$IFDEF FPC}TDOMNode{$ELSE}IXMLNode{$ENDIF});
procedure TXMPData.Create_RDFDescription_Tags(ANode: TDOMNode);
var var
{$IFDEF FPC}
node: TDOMNode; node: TDOMNode;
nodeName: String;
i: Integer;
attr: TDOMNode; attr: TDOMNode;
{$ELSE}
node: IXMLNode;
attr: IXMLNode;
{$ENDIF}
nodeName: String;
i, n: Integer;
lTagName, lTagValue: String; lTagName, lTagValue: String;
lTag: TTag; lTag: TTag;
begin begin
while ANode <> nil do begin while ANode <> nil do begin
nodeName := ANode.NodeName; nodeName := ANode.NodeName;
{$IFDEF FPC}
for i := 0 to ANode.Attributes.Length-1 do for i := 0 to ANode.Attributes.Length-1 do
begin begin
attr := ANode.Attributes.Item[i]; attr := ANode.Attributes.Item[i];
lTagName := attr.NodeName; lTagName := attr.NodeName;
lTagValue := attr.NodeValue; lTagValue := attr.nodeValue;
FTags.Add(lTagName + '=' + lTagValue); FTags.Add(lTagName + '=' + lTagValue);
end; end;
if ANode.HasChildNodes then if ANode.HasChildNodes then
begin begin
node := ANode.FirstChild; node := ANode.FirstChild;
while node <> nil do while node <> nil do
begin begin
nodeName := node.NodeName; nodeName := node.NodeName;
{$IFDEF FPC}
lTagValue := node.TextContent; lTagValue := node.TextContent;
{$ELSE}
lTagValue := node.NodeValue;
{$ENDIF}
if lTagName <> '' then if lTagName <> '' then
FTags.Add(nodeName + '=' + lTagValue); FTags.Add(nodeName + '=' + lTagValue);
node := node.NextSibling; node := node.NextSibling;
end; end;
end; end;
ANode := ANode.NextSibling; ANode := ANode.NextSibling;
{$ELSE}
for i := 0 to ANode.AttributeNodes.Count-1 do
begin
attr := ANode.AttributeNodes[i];
lTagName := attr.NodeName;
lTagValue := attr.NodeValue;
FTags.Add(lTagName + '=' + lTagValue);
end;
if ANode.HasChildNodes then
begin
node := ANode.ChildNodes.First;
while node <> nil do
begin
nodeName := node.NodeName;
{$IFDEF FPC}
lTagValue := node.TextContent;
{$ELSE}
lTagValue := node.NodeValue;
{$ENDIF}
if lTagName <> '' then
FTags.Add(nodeName + '=' + lTagValue);
node := node.NextSibling;
end;
end;
ANode := ANode.NextSibling;
{$ENDIF}
end; end;
end; end;
procedure TXMPData.CreateTags; procedure TXMPData.CreateTags;
var var
stream: TStringStream; {$IFDEF FPC}
node: TDOMNode; node: TDOMNode;
{$ELSE}
node: IXMLNode;
{$ENDIF}
nodeName: String; nodeName: String;
stream: TStringStream;
begin begin
{$IFDEF FPC}
FDoc.Free; FDoc.Free;
{$ENDIF}
stream := TStringStream.Create(FData); stream := TStringStream.Create(FData);
try try
{$IFDEF FPC}
ReadXMLFile(FDoc, stream); ReadXMLFile(FDoc, stream);
{$ELSE}
FDoc := TXMLDocument.Create(nil);
FDoc.Options := FDoc.Options - [doNodeAutoCreate];
FDoc.LoadFromStream(stream, xetUTF_8);
{$ENDIF}
finally finally
stream.Free; stream.Free;
end; end;
FTags.Clear; FTags.Clear;
try try
{$IFDEF FPC}
node := FDoc.DocumentElement.FindNode('rdf:RDF'); node := FDoc.DocumentElement.FindNode('rdf:RDF');
if node = nil then exit; if node = nil then exit;
node := node.FirstChild; node := node.FirstChild;
while node <> nil do {$ELSE}
node := FDoc.DocumentElement;
if node.ChildNodes.Count = 0 then
exit;
node := node.ChildNodes.First;
nodename :=node.NodeName;
if nodeName <> 'rdf:RDF' then
exit;
node := node.ChildNodes.First;
{$ENDIF}
while node <> nil do
begin begin
nodeName := node.NodeName; nodeName := node.NodeName;
if nodeName = 'rdf:Description' then if nodeName = 'rdf:Description' then
@@ -132,11 +195,12 @@ begin
end; end;
except except
FTags.Clear; FTags.Clear;
{$IFDEF FPC}
FreeAndNil(FDoc); FreeAndNil(FDoc);
{$ENDIF}
raise; raise;
end; end;
end; end;
{$ENDIF}
function TXMPData.GetTagByIndex(AIndex: Integer): String; function TXMPData.GetTagByIndex(AIndex: Integer): String;
begin begin
@@ -161,7 +225,7 @@ end;
procedure TXMPData.LoadFromStream(AStream: TStream; ASize: Integer = -1); procedure TXMPData.LoadFromStream(AStream: TStream; ASize: Integer = -1);
var var
p: Int64; p: Int64;
i: SizeInt; i: Cardinal;
begin begin
if ASize = -1 then if ASize = -1 then
ASize := AStream.Size; ASize := AStream.Size;
@@ -181,9 +245,7 @@ begin
end; end;
AStream.Position := p; AStream.Position := p;
{$IFDEF FPC}
CreateTags; CreateTags;
{$ENDIF}
end; end;
procedure TXMPData.SaveToStream(AStream: TStream); procedure TXMPData.SaveToStream(AStream: TStream);

View File

@@ -1,12 +1,14 @@
unit fpeXMPReadWrite; unit fpeXMPReadWrite;
{$mode objfpc}{$H+} {$IFDEF FPC}
{$mode objfpc}{$H+}
{$ENDIF}
interface interface
uses uses
Classes, SysUtils, Classes, SysUtils,
fpeGlobal, fpeMetaData; fpeGlobal, fpeUtils, fpeMetaData;
const const
XMP_BASE_KEY = 'http://ns.adobe.com/xap/1.0/'; XMP_BASE_KEY = 'http://ns.adobe.com/xap/1.0/';
@@ -27,12 +29,12 @@ implementation
function HasXMPHeader(AStream: TStream): Boolean; function HasXMPHeader(AStream: TStream): Boolean;
var var
p: Int64; p: Int64;
hdr: array of ansichar; hdr: array of ansichar;
begin begin
p := AStream.Position; p := AStream.Position;
SetLength(hdr, Length(XMP_KEY)); SetLength(hdr, Length(XMP_KEY));
AStream.Read(hdr[0], Length(XMP_KEY)); AStream.Read(hdr[0], Length(XMP_KEY));
Result := CompareMem(@hdr[0], @XMP_KEY[1], Length(XMP_KEY)); Result := CompareMem(PAnsiChar(hdr), PAnsiChar(AnsiString(XMP_KEY)), Length(XMP_KEY));
if not Result then if not Result then
AStream.Position := p; AStream.Position := p;
end; end;
@@ -66,7 +68,7 @@ begin
// Size of the segment // Size of the segment
ADataSize := NToBE(Word(ADataSize)); ADataSize := NToBE(Word(ADataSize));
AStream.WriteBuffer(ADataSize, 2); AStream.WriteBuffer(ADataSize, 2);
AStream.WriteBuffer(XMP_KEY, Length(XMP_KEY)); AStream.WriteBuffer(AnsiString(XMP_KEY), Length(XMP_KEY));
end; end;
end. end.

View File

@@ -7,7 +7,7 @@
<TargetedPlatforms>1</TargetedPlatforms> <TargetedPlatforms>1</TargetedPlatforms>
<AppType>Application</AppType> <AppType>Application</AppType>
<FrameworkType>VCL</FrameworkType> <FrameworkType>VCL</FrameworkType>
<ProjectVersion>18.8</ProjectVersion> <ProjectVersion>19.5</ProjectVersion>
<Platform Condition="'$(Platform)'==''">Win32</Platform> <Platform Condition="'$(Platform)'==''">Win32</Platform>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''"> <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
@@ -18,6 +18,11 @@
<CfgParent>Base</CfgParent> <CfgParent>Base</CfgParent>
<Base>true</Base> <Base>true</Base>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
<Base_Win64>true</Base_Win64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_1)'!=''"> <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_1)'!=''">
<Cfg_1>true</Cfg_1> <Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent> <CfgParent>Base</CfgParent>
@@ -29,6 +34,12 @@
<Cfg_1>true</Cfg_1> <Cfg_1>true</Cfg_1>
<Base>true</Base> <Base>true</Base>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win64)'!=''">
<Cfg_1_Win64>true</Cfg_1_Win64>
<CfgParent>Cfg_1</CfgParent>
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_2)'!=''"> <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_2)'!=''">
<Cfg_2>true</Cfg_2> <Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent> <CfgParent>Base</CfgParent>
@@ -40,6 +51,12 @@
<Cfg_2>true</Cfg_2> <Cfg_2>true</Cfg_2>
<Base>true</Base> <Base>true</Base>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win64)'!=''">
<Cfg_2_Win64>true</Cfg_2_Win64>
<CfgParent>Cfg_2</CfgParent>
<Cfg_2>true</Cfg_2>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''"> <PropertyGroup Condition="'$(Base)'!=''">
<DCC_E>false</DCC_E> <DCC_E>false</DCC_E>
<DCC_F>false</DCC_F> <DCC_F>false</DCC_F>
@@ -58,6 +75,9 @@
<VerInfo_Locale>1033</VerInfo_Locale> <VerInfo_Locale>1033</VerInfo_Locale>
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=0.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=</VerInfo_Keys> <VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=0.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=</VerInfo_Keys>
<DCC_DcuOutput>output\dcu\Delphi</DCC_DcuOutput> <DCC_DcuOutput>output\dcu\Delphi</DCC_DcuOutput>
<Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
<UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
<UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Base_Win32)'!=''"> <PropertyGroup Condition="'$(Base_Win32)'!=''">
<DCC_Namespace>System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace> <DCC_Namespace>System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
@@ -70,6 +90,13 @@
<UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44> <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
<UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150> <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''">
<DCC_Namespace>System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''"> <PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define> <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
<DCC_DebugInformation>0</DCC_DebugInformation> <DCC_DebugInformation>0</DCC_DebugInformation>
@@ -80,6 +107,9 @@
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes> <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
<AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode> <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''"> <PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define> <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
<DCC_Optimize>false</DCC_Optimize> <DCC_Optimize>false</DCC_Optimize>
@@ -94,6 +124,9 @@
<AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode> <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
<BT_BuildType>Debug</BT_BuildType> <BT_BuildType>Debug</BT_BuildType>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win64)'!=''">
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<DelphiCompile Include="$(MainSource)"> <DelphiCompile Include="$(MainSource)">
<MainSource>MainSource</MainSource> <MainSource>MainSource</MainSource>
@@ -107,15 +140,11 @@
<DCCReference Include="..\..\fpemetadata.pas"/> <DCCReference Include="..\..\fpemetadata.pas"/>
<DCCReference Include="..\..\fpestrconsts.pas"/> <DCCReference Include="..\..\fpestrconsts.pas"/>
<DCCReference Include="..\..\fpetags.pas"/> <DCCReference Include="..\..\fpetags.pas"/>
<DCCReference Include="..\..\fpeutils.pas"/> <DCCReference Include="..\..\fpeUtils.pas"/>
<DCCReference Include="common\fetexifbe.pas"/> <DCCReference Include="common\fetexifbe.pas"/>
<DCCReference Include="common\fetexifle.pas"/> <DCCReference Include="common\fetexifle.pas"/>
<DCCReference Include="common\fetiptc.pas"/> <DCCReference Include="common\fetiptc.pas"/>
<DCCReference Include="common\fetutils.pas"/> <DCCReference Include="common\fetutils.pas"/>
<BuildConfiguration Include="Debug">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
<BuildConfiguration Include="Base"> <BuildConfiguration Include="Base">
<Key>Base</Key> <Key>Base</Key>
</BuildConfiguration> </BuildConfiguration>
@@ -123,6 +152,10 @@
<Key>Cfg_1</Key> <Key>Cfg_1</Key>
<CfgParent>Base</CfgParent> <CfgParent>Base</CfgParent>
</BuildConfiguration> </BuildConfiguration>
<BuildConfiguration Include="Debug">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
</ItemGroup> </ItemGroup>
<ProjectExtensions> <ProjectExtensions>
<Borland.Personality>Delphi.Personality.12</Borland.Personality> <Borland.Personality>Delphi.Personality.12</Borland.Personality>
@@ -135,6 +168,7 @@
</Delphi.Personality> </Delphi.Personality>
<Platforms> <Platforms>
<Platform value="Win32">True</Platform> <Platform value="Win32">True</Platform>
<Platform value="Win64">False</Platform>
</Platforms> </Platforms>
</BorlandProject> </BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion> <ProjectFileVersion>12</ProjectFileVersion>