• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1073
  • Last Modified:

zLib and Stream?

I have most of the code, I just need a little help if possible.  This code does not seem to work.  If I create a TFileStream, then I can save a bitmap picture and LoadFromStream and it brings it back.  However, I am trying to compress the File, and when you use the file, then it decompresses it into memory and uses it, instead of extracting a file somewhere.  Anybody have any ideas why this does not work.  I am using the zLib component that comes with Delphi.

var
  frmMain: TfrmMain;

implementation

{$R *.DFM}

procedure TfrmMain.btnCompressClick(Sender: TObject);
var
    NewFile: TMemoryStream;
begin
  NewFile := TMemoryStream.Create;
  try
    image1.Picture.Bitmap.SaveToStream(NewFile);
    OutFile := TFileStream.Create('e:\001.stm', fmCreate);
    try
      ZStream := TCompressionStream.Create(clFastest, OutFile);
      try
        ZStream.CopyFrom(NewFile, 0);
      finally
        ZStream.Free;
      end;

    finally
      OutFile.Free;
    end;
  finally
    NewFile.Free;
  end;
end;

procedure TfrmMain.btnDecompressClick(Sender: TObject);
var
  Count: Integer;
  NewFile: TMemoryStream;
begin
  InFile := TFileStream.Create('e:\001.stm', fmOpenRead);
  try
    NewFile := TMemoryStream.Create;
    try

      ZStream := TDecompressionStream.Create(InFile);
      try
        while True do
          begin
            Count := ZStream.Read(Buffer, BufferSize);
            if Count <> 0 then NewFile.WriteBuffer(Buffer, Count) else Break;
          end;
        image1.Picture.Bitmap.LoadFromStream(NewFile);
      finally
        ZStream.Free;
      end;
    finally
      NewFile.Free;
    end;
  finally
    InFile.Free;
  end;

end;

end.
0
perkley
Asked:
perkley
  • 6
  • 6
1 Solution
 
intheCommented:
Hi,
an example of saving C:\the.bmp as C:\new.dat then loading C:\new.dat into a TImage
  (note it dont use tcompressionstream for this just thought you may be interested):


implementation
   
uses
  ZLib;
   
.....
   
procedure TForm1.Button1Click(Sender:
TObject);
var
  Strm: TMemoryStream;
  PStrm: Pointer;
  i: Integer;
begin
  Strm := TMemoryStream.Create;
  Strm.LoadFromFile('c:\the.bmp');
  Screen.Cursor := crHourGlass;
  CompressBuf(Strm.Memory, Strm.Size,
PStrm, i);
  Screen.Cursor := crDefault;
  Strm.Clear;
  Strm.Write(PStrm^, i);
  Strm.SaveToFile('c:\new.dat');
  Strm.Clear;
  Strm.Destroy;
end;
   
procedure TForm1.Button2Click(Sender:
TObject);
var
  Strm: TMemoryStream;
  PStrm: Pointer;
  tmp, i: Integer;
begin
  Strm := TMemoryStream.Create;
  Strm.LoadFromFile('c:\new.dat');
  Screen.Cursor := crHourGlass;
  DecompressBuf(Strm.Memory, Strm.Size,
tmp, PStrm, i);
  Screen.Cursor := crDefault;
  Strm.Clear;
  Strm.Write(PStrm^, i);
  Strm.Position := 0;
   
Image1.Picture.BitMap.LoadFromStream(Strm);
end;


0
 
perkleyAuthor Commented:
I am getting an error on this line of your code:

CompressBuf(Strm.Memory, Strm.Size, PStrm, i);

ERROR: Incompatible Types "Integer" and "Pointer".
The error is on the PStrm, which you defined as Pointer.

I am using Delphi 5 Professional
0
 
intheCommented:
mm..i only use d4.03 so cant test what to do .
i have other code for this but the only difference in it is setting

begin
PStrm := nil

you could try CompressBuf(Strm.Memory, Strm.Size,nil,i) ..
i cant really say for sure ,i though it would be same in d4 & d5 for this stuff.

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
perkleyAuthor Commented:
Your code is okay, except, that they added a new variable to send, and that was what the problem was.  I need to send an integer for CmpMode.  Do you have any idea what I should send.  Here is the code that it runs on my computer.

procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; CmpMode : Integer;
                      var OutBuf: Pointer; var OutBytes: Integer);
var
  strm: TZStreamRec;
  P: Pointer;
begin
  FillChar(strm, sizeof(strm), 0);
  strm.zalloc := zlibAllocMem;
  strm.zfree := zlibFreeMem;
  OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
  GetMem(OutBuf, OutBytes);
  try
    strm.next_in := InBuf;
    strm.avail_in := InBytes;
    strm.next_out := OutBuf;
    strm.avail_out := OutBytes;
    CCheck(deflateInit_(strm, cmpMode, zlib_version, sizeof(strm)));
    try
      while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do
      begin
        P := OutBuf;
        Inc(OutBytes, 256);
        ReallocMem(OutBuf, OutBytes);
        strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
        strm.avail_out := 256;
      end;
    finally
      CCheck(deflateEnd(strm));
    end;
    ReallocMem(OutBuf, strm.total_out);
    OutBytes := strm.total_out;
  except
    FreeMem(OutBuf);
    raise
  end;
end;
0
 
perkleyAuthor Commented:
k, cmpmode is the compression level, so it seems to put it to the stream fine.  The problem is that when it comes to the decompression section, it gives an error.  Have you tested it with a bitmap going into an image.picture.bitmap.loadfromstream?
0
 
intheCommented:
i only used it once on d3 only changing a few lines in the d3 exmaple that was provided ,im going to fire up delphi and take a look see what happens.
is the declaration for decompressbuf still the same?

(as a note if you have d4 or d3 you can try using that version of zlib see if get same errors)
0
 
perkleyAuthor Commented:
Yes, the decompressbuf seems to be the same, but it is the decompressbuf that it has the error with when trying to decompress the picture.
0
 
intheCommented:
hi,
i tried my example and worked fine using d4 ,so i am assuming it is a problem with this new CmpMode parameter.so i replace my compressbuf procedure in zlib.pas to your new one and used thus in my unit:

CompressBuf(Strm.Memory, Strm.Size,0,PStrm, i);

it worked fine again,no error on decompress.



0
 
intheCommented:
if you like i could send you my zlib unit and my test unit.
0
 
perkleyAuthor Commented:
Hmm, k, I took the Zlib off of the Delphi 5 CD again, because I noticed that it was coming from a backup program I was using. They had modified the Zlib component a little.

I took the path off for their modified one, and put the original back.  It still gave the same error though, but it did not ask for the Compression Level.

Anyway, let me see your example program, because maybe I typed something wrong somewhere.

Send to Douglas@rexburg.com
0
 
perkleyAuthor Commented:
Thanks, I did have one small problem - called the filename I was reading from.  I changed the example you gave me to fit my program, and I typed the file to read from wrong, and so it was giving me an error.  Sorry to put you through the research, when it was on my end.  Your code does work well.
0
 
intheCommented:
:o) no probs
0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

  • 6
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now