Hallo
ASM,
vielen Dank für Deine Unterstützung! Mit dem Problem der Positionierung im Stream hast Du grundsätzlich recht. Ich habe allerdings festgestellt, wenn man unmittelbar vor dem CopyFrom den Seek-Befehl ausführt, funktioniert das Kopieren ab der Seek-Position.
Mein Problem war übrigens ein Leichtsinnsfehler! Habe beim zweiten Read statt 4 nur 3 Zeichen gelesen! Das habe ich aber erst nach viel Debuggen und Hexen herausbekommen!
Immerhin, jetzt scheint es zu funktionieren!
Falls es mal jemand braucht, hier nochmals der finale Code:
Delphi-Quellcode:
procedure TForm1.CopyEXIF(const FileNameEXIFSource, FileNameEXIFTarget: string);
const
M_JFIF = $E0;
M_EXIF = $E1;
var
MSSource, MSTarget: TMemoryStream;
FS: TFileStream;
TargetStartPos, SourceEndPos: Longint;
Buf: Array [0..3] of Byte;
begin
MSTarget := TMemoryStream.Create;
try
// 4. Lies dann Deine veränderte jpeg-Datei in den MemoryStream.
TargetStartPos := 2;
MSTarget.LoadFromFile(FileNameEXIFTarget);
MSTarget.Seek(TargetStartPos, soFromBeginning);
MSTarget.Read(Buf, 4);
if Buf[1] = M_JFIF then begin
TargetStartPos := TargetStartPos+(Buf[2]*256)+Buf[3]+2;
MSTarget.Seek(TargetStartPos, soFromBeginning);
MSTarget.Read(Buf, 4);
end;
if (Buf[1] <> M_EXIF) or
(MessageDLG('Die Datei '''+FileNameEXIFTarget+''' hat selbst ein EXIF! Soll dieser wirklich überschrieben werden?',
mtConfirmation, [mbYes,mbNo], 0) = mrYes) then begin
if Buf[1] = M_EXIF then TargetStartPo s:= TargetStartPos+(Buf[2]*256)+Buf[3]+2;
MSSource := TMemoryStream.Create;
try
// 1. Lies aus Deiner originalen jpeg-Datei die Größe der EXIF-Struktur aus (steht in den Bytes unmittelbar nach dem EXIF-StartTag "FFE1" und reicht bis zur Kennung "786969660000" = "Exif").
SourceEndPos := 2;
MSSource.LoadFromFile(FileNameEXIFSource);
MSSource.Seek(SourceEndPos, soFromBeginning);
MSSource.Read(Buf, 4);
if Buf[1] = M_EXIF then SourceEndPos := SourceEndPos+(Buf[2]*256)+Buf[3]+2;
// 2. Lies die originale jpeg-Datei in einen MemoryStream. Setze die Größe des MemoryStreams zurück auf die Größe der EXIF-Struktur zuzüglich der 4 führenden Kennbytes der jpeg-Datei (FFD8 und FFE1).
MSSource.SetSize(SourceEndPos);
// 3. Übertrage den MemoryStream in den FileStream, der Deine neue jpeg-Datei anlegt, welche sowohl Dein verändertes jpeg-Bild als auch die ursprüngliche EXIF-Information aufnehmen soll.
FS := TFileStream.Create(FileNameEXIFTarget, fmCreate or fmShareExclusive);
try
MSSource.SaveToStream(FS);
// 5. Setze den Pointer des MemoryStreams auf die Position $02 (also ab dem 3.Byte, d.h. ohne die JPEG-Kennung "FFD8" der zweiten Datei) und übertrage den MemoryStream ab dieser Position in den zuvor begonnenen Filestream.
MSTarget.Seek(TargetStartPos, soFromBeginning);
FS.CopyFrom(MSTarget, MSTarget.Size-TargetStartPos);
finally
FS.Free;
end;
finally
MSSource.Free;
end
end;
finally
MSTarget.Free;
end;
end;