Page 1 of 2 12 LastLast
Results 1 to 10 of 16

Thread: TJPEGImage.SaveToStream problem

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1

    TJPEGImage.SaveToStream problem

    I have a problem saving and loading a TJPEGImage to a TMemoryStream. When I load the JPEG from the stream the stream position seems to be in the wrong place as if it's loading less or more memory than it saved. In the help file it says this in TJPEGImage.SaveToStream :
    "SaveToStream expects jpeg image data and may incur overhead of a compression cycle if the source is a bitmap."
    I think that may have something to do with it but I don't know what it means.
    Has anyone else had this problem? If not could someone just explain what that sentence means in the help files.


  2. #2

    TJPEGImage.SaveToStream problem

    All it means, AFAICT, is that if you pass bitmap data it'll have to compress it to JPEG data, which is overhead, before going any further (otherwise it'd be saving a bitmap, not a JPEG). Nothing to worry about there, probably, and it could explain the position difference.

    I'm not sure though. Does the application appear to work correctly despite your unexpected position in the stream?
    "All paid jobs absorb and degrade the mind."
    <br />-- Aristotle

  3. #3

    TJPEGImage.SaveToStream problem

    yes, the application works fine apart from that

    BackIsJPG &#58; boolean; 
    LNumFrames &#58; integer; 
    LStream.Seek&#40;0, 0&#41;; 
    LStream.Write&#40;BackIsJPG, SizeOf&#40;boolean&#41;&#41;; 
    if BackIsJPG then BackgroundJPG.SaveToStream&#40;LStream&#41; 
    else BackgroundBmp.SaveToStream&#40;LStream&#41;; 
    LStream.Write&#40;LNumFrames, SizeOf&#40;integer&#41;&#41;; 
    LStream.Seek&#40;0, 0&#41;; 
    LStream.Read&#40;BackIsJPG, SizeOf&#40;boolean&#41;&#41;; 
    if BackIsJPG then begin 
    end else BackgroundBmp.LoadFromStream&#40;LStream&#41;; 
    LStream.Read&#40;LNumFrames, SizeOf&#40;integer&#41;&#41;;
    When BackIsJPG is False it works (so writing and reading a TBitmap works) but when BackIsJPG is True the LNumFrames value is wrong as if reading the Jpeg positions the stream wrongly.


  4. #4

    TJPEGImage.SaveToStream problem

    I have still not solved this problem - and it is really starting to frustrate me as you might expect!
    I have made a simple demo to demonstrate the problem.
    load a jpeg (from the file menu), set the spinedit to anything between 0 and 255 and then click save stream. It will create a stream containing the jpeg and then a byte containing the spin edit number - it will save it to your c route directory. Then close the application, run it again and click load stream. The jpeg will load fine, but the spin edit value will not be what you set it to because of the error in reading the byte after reading the jpeg. If you can get the demo to work so that it correctly reads the byte I can then correct the error in the main program I'm writing.

    Thanks - any help will be greatly appreciated.


  5. #5

    TJPEGImage.SaveToStream problem

    It looks like TJPegImage.LoadFromStream corrupts streams offset, you could store the size of each image in the stream and seek with recalculated offsets after every call to TJPegImage.LoadFromStream

  6. #6

    TJPEGImage.SaveToStream problem

    good idea, thanks. I just use SizeOf to get the size of the jpeg right?
    Do you think this is a bug in the delphi TJpegImage class or is there a good reason for it - like that overhead of a compression cycle thing?


  7. #7

    TJPEGImage.SaveToStream problem

    No, SizeOf would return the size of a pointer (that is 4 bytes), I'd suggest when writing JPGs do: keep current Position of the stream, skip 8 bytes, write the JPG, keep the new Position, seek back to the old position and write the new position there, and finally seek to the end of the stream. Looks like a bug.

  8. #8

    TJPEGImage.SaveToStream problem

    thanks, i did that and it works.
    I wrote 2 procedures to save and load a jpeg to a stream properly.

    [pascal]// save a jpeg to a memory stream with correct positioning
    procedure JPegSaveToStream(AJPG : TJPegImage ; AStream : TMemoryStream);
    LStart, LEnd : Int64;
    // store current stream position
    LStart := AStream.Position;
    // skip size of stream position
    AStream.Seek(8, LStart);
    // write the jpeg
    // store the new position
    LEnd := AStream.Position;
    // seek back to start position
    AStream.Position := LStart;
    // write jpeg end position to correct position when loading
    AStream.Write(LEnd, ;
    // seek back to end of stream
    AStream.Position := LEnd;

    // load a jpeg from a memory stream with correct positioning
    procedure JPegLoadFromStream(AJPG : TJPegImage ; AStream : TMemoryStream);
    LEnd : Int64;
    // load the jpeg end position
    AStream.Read(LEnd, ;
    // load the jpeg
    // go to the correct end position
    AStream.Position := LEnd;

    seems messy though - I wish I knew why it gets the position wrong.


  9. #9
    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);
    LEnd : Int64;
    LMStream : TMemoryStream;
    // 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

    Last edited by peterbone; 29-01-2020 at 02:46 PM.

  10. #10
    Legendary Member cairnswm's Avatar
    Join Date
    Nov 2002
    Randburg, South Africa

    TJPEGImage.SaveToStream problem

    I'm doing something similar with JPEGs but I always set DIBNeeded := True first and I dont seen to have any problems.
    William Cairns
    My Games: (Currently very inactive)
    MyOnline Games: (Currently very inactive)

Page 1 of 2 12 LastLast


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts