When saving,
AStream.Seek(8, LStart);
should be
AStream.Seek(8, soFromCurrent);
Edit: Error 53 is "File Not Found", check msdn for error codes
When saving,
AStream.Seek(8, LStart);
should be
AStream.Seek(8, soFromCurrent);
Edit: Error 53 is "File Not Found", check msdn for error codes
What I have done is the following:
[pascal]procedure TForm1.Button1Click(Sender: TObject);
Var
F : TFileStream;
M,M2 : TMemoryStream;
J,J1 : TJPEGImage;
X,Y,Z : Integer;
begin
J := TJPEGImage.Create;
J.LoadFromFile('C:\cairnsgames\letter.jpg'); // Load an Image
X := 100;
M := TMemoryStream.Create;
M2 := TMemoryStream.Create;
M.Write(X,SizeOf(Integer)); // Write Tag Information
J.SaveToStream(M2);
X := M2.Size; // Calculate the size of the JPEG
M2.Free;
M.Write(X,SizeOf(Integer)); // Write Size
J.SaveToStream(M); // Write Image
J1 := TJPEGImage.Create; // Create a New Image
M.Seek(0,soBeginning); // Move to start of stream
M.Read(Y,SizeOf(Integer)); // Load Tag Information
M.Read(Z,SizeOf(Integer)); // Load Size Information
J1.LoadFromStream(M); // Load JPEG
J1.SaveToFile('C:\cairnsgames\letter1.jpg'); // Write Out (to compare vs Original)
ShowMessage(IntToStr(Z)); // Display Size info
J1.Free;
J.Free;
end;[/pascal]
And it works fine
I think I understand what it is doing. As JPEGs allow additional information such as who took the photo, commetns and even a thumbnail of the image the load from stream seems to read from the current position in the stream until the end, but only uses the JPEG information it needs to recreate the image in memory. Therefore when you add information at the end of the stream the LoadFromStream reads right past the JPEG size and over tha additional information.
Hope this helps.
William Cairns
My Games: http://www.cairnsgames.co.za (Currently very inactive)
MyOnline Games: http://TheGameDeveloper.co.za (Currently very inactive)
Thanks, but wouldn't soFromCurrent be the same as LStart as LStart is the current position - since the line before it is LStart := AStream.Position; ?Originally Posted by Paulius
Peter
No, you misunderstood the origin parameter, itis only supposed to be constants soFromBeginning, soFromCurrentg or soFromEnd. It probably defaults to one of these if the value is incorrect.Thanks, but wouldn't soFromCurrent be the same as LStart as LStart is the current position - since the line before it is LStart := AStream.Position; ?
oh, I see - thanks. The word origin makes it sound like the position you're offsetting from. It works fine now!
Thanks for everyone's help
Peter
15 years later and I realise that my code above has an issue with loading extra data into the jpeg if the stream contains other data after the jpeg. This can cause an out of memory error if the stream is large. Fixed version is below and avoids this by copying to a new stream containing just the jpeg data.
procedure JPegLoadFromStream(AJPG : TJPegImage ; AStream : TStream);
Var
LEnd : Int64;
LMStream : TMemoryStream;
begin
// load the jpeg end position
AStream.Read(LEnd, 8 );
// Load into temporary stream as TJPeg.LoadFromStream will load to the end
LMStream := TMemoryStream.Create;
LMStream.CopyFrom(AStream, LEnd - AStream.Position);
LMStream.Seek(0, soFromBeginning);
// load the jpeg
AJPG.LoadFromStream(LMStream);
LMStream.Free;
end;
Last edited by peterbone; 29-01-2020 at 03:46 PM.
Bookmarks