Mega Code Archive

 
Categories / Delphi / Graphic
 

How to store several bitmaps into a single file

Title: How to store several bitmaps into a single file? Question: 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.