Solved

zLib and Stream?

Posted on 2000-03-13
12
928 Views
Last Modified: 2010-05-18
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
Comment
Question by:perkley
  • 6
  • 6
12 Comments
 
LVL 17

Accepted Solution

by:
inthe earned 50 total points
ID: 2613477
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
 

Author Comment

by:perkley
ID: 2613512
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
 
LVL 17

Expert Comment

by:inthe
ID: 2613823
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
 

Author Comment

by:perkley
ID: 2613887
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
 

Author Comment

by:perkley
ID: 2613907
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
 
LVL 17

Expert Comment

by:inthe
ID: 2613929
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:perkley
ID: 2614008
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
 
LVL 17

Expert Comment

by:inthe
ID: 2614042
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
 
LVL 17

Expert Comment

by:inthe
ID: 2614056
if you like i could send you my zlib unit and my test unit.
0
 

Author Comment

by:perkley
ID: 2614071
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
 

Author Comment

by:perkley
ID: 2614124
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
 
LVL 17

Expert Comment

by:inthe
ID: 2614159
:o) no probs
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now