2

I'm wanting to extract a zip file loaded with images into memory in some way. I don't really care what type of stream they go into, as long as I can load them afterwards. I do not have that great of an understanding with streams, and explanations on the subject don't seem to go into much detail.

Essentially, what I am doing now is extracting the files to (getcurrentdir + '\temp\'). This works, but isn't quite what I am wanting to do. I would be more happy to have the jpg's end up in memory and then be able to read from memory into a TImage.bitmap.

I am currently using jclcompresion to handle zips and rars, but was considering moving back to system.zip because I really only need to be able to handle zip files. If it would be easier to stay with jclcompression though that would work for me.

RRUZ
  • 134,889
  • 20
  • 356
  • 483
Larmos
  • 23
  • 1
  • 6

1 Answers1

7

The read method of the TZipFile class can be used with a stream

procedure Read(FileName: string; out Stream: TStream; out LocalHeader: TZipHeader); overload;
procedure Read(Index: Integer; out Stream: TStream; out LocalHeader: TZipHeader); overload;

from here you can access the compressed file using the index or the filename.

Check this sample which uses a TMemoryStream to hold the uncompressed data.

uses
  Vcl.AxCtrls,
  System.Zip;

procedure TForm41.Button1Click(Sender: TObject);
var
  LStream    : TStream;
  LZipFile   : TZipFile;
  LOleGraphic: TOleGraphic;
  LocalHeader: TZipHeader;
begin
  LZipFile := TZipFile.Create;
  try
    //open the compressed file
    LZipFile.Open('C:\Users\Dexter\Desktop\registry.zip', zmRead);
    //create the memory stream
    LStream := TMemoryStream.Create;
    try
      //LZipFile.Read(0, LStream, LocalHeader); you can  use the index of the file
      LZipFile.Read('SAM_0408.JPG', LStream, LocalHeader); //or use the filename 
      //do something with the memory stream
      //now using the TOleGraphic to detect the image type from the stream
      LOleGraphic := TOleGraphic.Create;
      try
         LStream.Position:=0;
         //load the image from the memory stream
         LOleGraphic.LoadFromStream(LStream);
         //load the image into the TImage component
         Image1.Picture.Assign(LOleGraphic);
      finally
        LOleGraphic.Free;
      end;
    finally
      LStream.Free;
    end;
  finally
   LZipFile.Free;
  end;
end;
RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • Am I correct in assuming that the indexing is done 0,1,2,ect each increment being the next file? If so, this is far easier than I thought it would be. – Larmos Jun 14 '12 at 06:00
  • Yes the index are zero based, and the max value must be obtained using the `FileCount` property of the TZipFile class. – RRUZ Jun 14 '12 at 06:06
  • Much appreciated. I'll be implementing this tomorrow. – Larmos Jun 14 '12 at 06:33
  • I'm finally having time to go back and get this into my code and I just realized there might be a small problem. I need the stream to be accessable throughout the life of the program. When should I free it in order to keep it active the entire time so that it remains usable? I'm rather new to delphi and I know that in C++ there was a way to execute code on program terminating, is there the same thing with delphi? – Larmos Jun 15 '12 at 18:27
  • Actually, I've ran into more problems than just that. It turns out I didn't fully understand the code entirely. I am wanting to be able to put all of the images into memory at once. And then be able to scroll through them on button clicks. I tried to implement this with the code given but I'm getting memory address errors and I think it has something to do with writing them all through a loop. Do you think you could show me how you would do this with a loop and scrolling through images? – Larmos Jun 15 '12 at 19:07
  • @Larmos, post another question with your exact issue and what do you want accomplish. – RRUZ Jun 15 '12 at 19:20