You've already forked lazarus-ccr
fpExif: Fix writing of multi-string IPTC tags. Nicer display text for IPTC CodeCharacterSet tag.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8992 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -60,6 +60,12 @@ type
|
|||||||
property MaxLength: Integer read FMaxLen;
|
property MaxLength: Integer read FMaxLen;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TIptcCodedCharacterSetTag = class(TIptcStringTag)
|
||||||
|
protected
|
||||||
|
function GetAsString: String; override;
|
||||||
|
procedure SetAsString(const AValue: String); override;
|
||||||
|
end;
|
||||||
|
|
||||||
TIptcMultiStringTag = class(TIptcStringTag)
|
TIptcMultiStringTag = class(TIptcStringTag)
|
||||||
protected
|
protected
|
||||||
function GetAsString: String; override;
|
function GetAsString: String; override;
|
||||||
@ -136,7 +142,7 @@ begin
|
|||||||
with IptcTagDefs do begin
|
with IptcTagDefs do begin
|
||||||
Clear;
|
Clear;
|
||||||
// NOTE: The Count field is "abused" as MaxLength of string value
|
// NOTE: The Count field is "abused" as MaxLength of string value
|
||||||
AddStringTag(I+$015A {1:90}, 'CodedCharacterSet', 32, rsCodedCharSet, '', TIptcStringTag);
|
AddStringTag(I+$015A {1:90}, 'CodedCharacterSet', 32, rsCodedCharSet, '', TIptcCodedCharacterSetTag);
|
||||||
AddUShortTag(I+$0200 {2: 0}, 'RecordVersion', 1, rsRecordVersion);
|
AddUShortTag(I+$0200 {2: 0}, 'RecordVersion', 1, rsRecordVersion);
|
||||||
AddStringTag(I+$0203 {2: 3}, 'ObjectType', 64, rsObjectType, '', TIptcStringTag);
|
AddStringTag(I+$0203 {2: 3}, 'ObjectType', 64, rsObjectType, '', TIptcStringTag);
|
||||||
AddStringTag(I+$0204 {2: 4}, 'ObjectAttr', 68, rsObjectAttr, '', TIptcObjectAttrTag);
|
AddStringTag(I+$0204 {2: 4}, 'ObjectAttr', 68, rsObjectAttr, '', TIptcObjectAttrTag);
|
||||||
@ -474,6 +480,36 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// TIptcCodedCharacterSetTag
|
||||||
|
//==============================================================================
|
||||||
|
function TIptcCodedCharacterSetTag.GetAsString: String;
|
||||||
|
var
|
||||||
|
s: String;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
s := inherited GetAsString;
|
||||||
|
if s = #27#37#71 then
|
||||||
|
Result := 'UTF8'
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if s[1] = #27 then
|
||||||
|
Result := 'ESC'
|
||||||
|
else
|
||||||
|
Result := s[1];
|
||||||
|
for i := 2 to Length(s) do
|
||||||
|
Result := Result + ' ' + s[i];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIptcCodedCharacterSetTag.SetAsString(const AValue: String);
|
||||||
|
begin
|
||||||
|
if Uppercase(AValue) = 'UTF8' then
|
||||||
|
inherited SetAsString(#27#37#71)
|
||||||
|
else
|
||||||
|
inherited SetAsString(AValue);
|
||||||
|
end;
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// TIptcMultiStringTag
|
// TIptcMultiStringTag
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
@ -72,6 +72,7 @@ type
|
|||||||
TIPTCWriter = class(TBasicMetadataWriter)
|
TIPTCWriter = class(TBasicMetadataWriter)
|
||||||
private
|
private
|
||||||
FIPTCSegmentStartPos: Int64;
|
FIPTCSegmentStartPos: Int64;
|
||||||
|
function SplitMultiStringTag(ATag: TTag): TStringArray;
|
||||||
protected
|
protected
|
||||||
procedure WriteEndOfDataResourceBlock(AStream: TStream);
|
procedure WriteEndOfDataResourceBlock(AStream: TStream);
|
||||||
procedure WriteImageResourceBlockHeader(AStream: TStream; AResourceID: Integer;
|
procedure WriteImageResourceBlockHeader(AStream: TStream; AResourceID: Integer;
|
||||||
@ -320,6 +321,19 @@ begin
|
|||||||
WriteImageResourceBlockHeader(AStream, $0B04, ''); //, nil, 0);
|
WriteImageResourceBlockHeader(AStream, $0B04, ''); //, nil, 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// During reading repeatable string tags were merged into a single string and
|
||||||
|
// separated by a IPTC_MULTI_TAG_SEPARATOR. Here the combined string is split
|
||||||
|
// into its parts so that they can be written as separate tags again.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
function TIptcWriter.SplitMultiStringTag(ATag: TTag): TStringArray;
|
||||||
|
var
|
||||||
|
s: String;
|
||||||
|
begin
|
||||||
|
s := PChar(ATag.RawData);
|
||||||
|
Result := s.Split(IPTC_MULTI_TAG_SEPARATOR);
|
||||||
|
end;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Writes the IPTC header needed by JPEG files (Segment APP13 header)
|
// Writes the IPTC header needed by JPEG files (Segment APP13 header)
|
||||||
// Call WriteToStream immediately afterwards
|
// Call WriteToStream immediately afterwards
|
||||||
@ -405,9 +419,43 @@ end;
|
|||||||
procedure TIptcWriter.WriteTag(AStream: TStream; ATag: TTag);
|
procedure TIptcWriter.WriteTag(AStream: TStream; ATag: TTag);
|
||||||
const
|
const
|
||||||
TAG_MARKER = $1C;
|
TAG_MARKER = $1C;
|
||||||
|
|
||||||
|
procedure WriteString(AIptcTag: TIptcTag; AText: PChar; ALength: Integer);
|
||||||
|
begin
|
||||||
|
if odd(ALength) then begin
|
||||||
|
inc(ALength);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// "Standard" dataset
|
||||||
|
if ALength < 32768 then begin
|
||||||
|
AIptcTag.Size := NtoBE(word(ALength));
|
||||||
|
AStream.WriteBuffer(AIptcTag, SizeOf(AIptcTag));
|
||||||
|
AStream.WriteBuffer(AText^, ALength);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
// "Extended" dataset
|
||||||
|
if ALength < 65536 then begin
|
||||||
|
// Size is 2, but we must set highest bit to mark tag as being extended.
|
||||||
|
AIptcTag.Size := NtoBE($8002);
|
||||||
|
AStream.WriteBuffer(AIptcTag, SizeOf(AIptcTag));
|
||||||
|
WriteWord(AStream, NtoBE(word(ALength)));
|
||||||
|
AStream.WriteBuffer(AText^, ALength);
|
||||||
|
end else begin
|
||||||
|
// Size is 4, but we must set highest bit to mark tag as being extended.
|
||||||
|
AIptcTag.Size := $8004;
|
||||||
|
AStream.WriteBuffer(AIptcTag, SizeOf(AIptcTag));
|
||||||
|
WriteDWord(AStream, NtoBE(ALength));
|
||||||
|
AStream.WriteBuffer(AText^, ALength);
|
||||||
|
end;
|
||||||
|
if odd(ALength) then // zero-termination of string
|
||||||
|
WriteByte(AStream, 0);
|
||||||
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
iptcTag: TIptcTag;
|
iptcTag: TIptcTag;
|
||||||
len: DWord;
|
len: DWord;
|
||||||
|
i: Integer;
|
||||||
|
sa: TStringArray;
|
||||||
begin
|
begin
|
||||||
iptcTag.TagMarker := byte(TAG_MARKER);
|
iptcTag.TagMarker := byte(TAG_MARKER);
|
||||||
iptcTag.RecordNumber := byte((ATag.TagID and $FF00) shr 8);
|
iptcTag.RecordNumber := byte((ATag.TagID and $FF00) shr 8);
|
||||||
@ -421,6 +469,14 @@ begin
|
|||||||
end;
|
end;
|
||||||
ttString:
|
ttString:
|
||||||
begin
|
begin
|
||||||
|
if ATag is TIptcMultiStringTag
|
||||||
|
then begin
|
||||||
|
sa := SplitMultiStringTag(ATag);
|
||||||
|
for i := 0 to High(sa) do
|
||||||
|
WriteString(iptcTag, PChar(sa[i]), Length(sa[i]));
|
||||||
|
end else
|
||||||
|
WriteString(iptcTag, PChar(ATag.RawData), Length(ATag.RawData));
|
||||||
|
(*
|
||||||
len := Length(ATag.RawData);
|
len := Length(ATag.RawData);
|
||||||
if odd(len) then begin
|
if odd(len) then begin
|
||||||
inc(len);
|
inc(len);
|
||||||
@ -447,6 +503,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
if odd(Length(ATag.RawData)) then // zero-termination of string
|
if odd(Length(ATag.RawData)) then // zero-termination of string
|
||||||
WriteByte(AStream, 0);
|
WriteByte(AStream, 0);
|
||||||
|
*)
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
// I've never seen other tag types than USHORT and STRING...
|
// I've never seen other tag types than USHORT and STRING...
|
||||||
|
@ -190,7 +190,7 @@ type
|
|||||||
property Count: Integer read FCount write FCount;
|
property Count: Integer read FCount write FCount;
|
||||||
{ Raw data of the tag value as read from the file or to be written to the file }
|
{ Raw data of the tag value as read from the file or to be written to the file }
|
||||||
property RawData: TBytes read FRawData write SetRawData;
|
property RawData: TBytes read FRawData write SetRawData;
|
||||||
{ Indicates wheter the raw data are in little endian or big endian byte order }
|
{ Indicates whether the raw data are in little endian or big endian byte order }
|
||||||
property BigEndian: Boolean read GetBigEndian;
|
property BigEndian: Boolean read GetBigEndian;
|
||||||
{ Determines whether the meaning of numberical values will be decoded. }
|
{ Determines whether the meaning of numberical values will be decoded. }
|
||||||
property DecodeValue: Boolean read GetDecodeValue write SetDecodeValue;
|
property DecodeValue: Boolean read GetDecodeValue write SetDecodeValue;
|
||||||
|
Reference in New Issue
Block a user