2006. március 24., péntek
How to store several bitmaps into a single file
Problem/Question/Abstract:
Is there a simple way to write a TBitmap object to a file and read it back? I want to store bitmaps and other data all in one file (much like word processors are capable of doing).
Answer:
If you wish to store multiple things into a file, you'll need to implement some sort of file structure so you can know what and where things are in the file. For example, if you wished to store several bitmaps to a file, you could structure your file like this:
file header
bitmap count
bitmap header
bitmap size
bitmap stream
bitmap trailer
...
file trailer
Where "file header" contains information such as the version of the file and a unique file structure identifier, "bitmap count" is the number of bitmaps saved to the file, "bitmap header" is a unique identifier which indicates the start of a bitmap entry in the file, "bitmap size" is the size of the bitmap stream, "bitmap stream" is the bitmap's stream (from SaveToStream), "bitmap trailer" is a trailer identifier which indicates the end of the bitmap entry, and "file trailer" is a unique identifier which indicates the end of the file, and optionally contains the size of the file and a CRC of the file (for error detection). Of course, you'd iterate the "bitmap header"..."bitmap trailer" structure once per bitmap saved to the file.
You can use a TFileStream to read / write this structure. You'll need to write a number of methods which read and interpret each section. You'll also want to create a TBitmap instance each time you encounter a "bitmap header" structure. Here's a quick example of how to implement the "bitmap header"..."bitmap trailer" section:
const
BITMAP_HEADER = 100;
BITMAP_TRAILER = 200;
procedure SaveBitmap(Bitmap: TBitmap; Stream: TStream);
var
Buffer: TMemoryStream;
Identifier: LongInt;
Size: LongInt;
begin
Buffer := TMemoryStream.Create;
try
Bitmap.SaveToStream(Buffer);
Identifier := BITMAP_HEADER;
Stream.Write(Identifier, SizeOf(Identifier));
Size := Buffer.Size;
Stream.Write(Size, SizeOf(Size));
Buffer.Position := 0;
Stream.CopyFrom(Buffer, Size);
Identifier := BITMAP_TRAILER;
Stream.Write(Identifier, SizeOf(Identifier));
finally
Buffer.Free;
end;
end;
procedure ReadBitmap(Bitmap: TBitmap; Stream: TStream);
var
Buffer: TMemoryStream;
Identifier: LongInt;
Size: LongInt;
begin
Buffer := TMemoryStream.Create;
try
Stream.Read(Identifier, SizeOf(Identifier));
if Identifier <> BITMAP_HEADER then
raise Exception.Create('Bitmap header expected');
Stream.Read(Size, SizeOf(Size));
Buffer.CopyFrom(Stream, Size);
Bitmap.LoadFromStream(Buffer);
Stream.Read(Identifier, SizeOf(Identifier));
if Identifier <> BITMAP_TRAILER then
raise Exception.Create('Bitmap trailer expected');
finally
Buffer.Free;
end;
end;
Of course, you'll need to write other methods to read the other file sections, and you'll need to call ReadBitmap the correct number of times (specified in "bitmap count") with a TBitmap instance.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése