One of the powerful
features from the component is the support to additional
TChunk descendents. To do so, you have to create
a new class descendent from TChunk. To read the data, there are two ways:
if the chunk contains large amounts of data, override
LoadFromStream and read data, crc
and check if the crc is valid. If the data is not too large you might use
the content from Data and
DataSize property.
To save
it, either override SaveToStream and
write data manually, override SaveToStream, modify data property and call
inherited SaveToStream. Also there other ways as modifying the data
property directly when the user reads/writes a property.
Other important method to override is the
Assign method to copy the chunk custom properties.
The
essencial part is to register the chunk using
RegisterChunk(ChunkClass: TChunkClass)
from pngimage.pas.
The
chunk bellow reads a text and shows a message box using the text.
type
TChunkcUSt = class(TChunk)
private
fText: String;
public
function SaveToStream(Stream: TStream): Boolean;
override;
function LoadFromStream(Stream: TStream; const
ChunkName: TChunkName; Size: Integer): Boolean; override;
procedure Assign(Source: TChunk); override;
property Text: String read fText write
fText;
end;
implementation
{Saving chunk to a stream}
function TChunkcUSt.SaveToStream(Stream: TStream): Boolean;
var
ChunkLength, ChunkCRC: Cardinal;
begin
{ChunkLength must be in network order}
ChunkLength := ByteSwap(Length(fText));
Stream.Write(ChunkLength, 4);
{Writes chunk name}
Stream.Write(fName[0], 4);
ChunkCRC := update_crc($ffffffff, @fName[0], 4);
{Writes data and finishes calculating crc}
Stream.Write(fText[1], Length(fText));
ChunkCRC := Byteswap(update_crc(ChunkCRC, @fText[1],
Length(fText))
xor $ffffffff);
{Writes crc}
Stream.Write(ChunkCRC, 4);
Result := TRUE;
end;
{Loading chunk from a stream}
function TChunkcUSt.LoadFromStream(Stream: TStream;
const
ChunkName: TChunkName; Size: Integer): Boolean;
var
ReadCRC, ChunkCRC: Cardinal;
begin
{Prepares text to hold}
SetLength(fText, Size);
{Reads data}
Stream.Read(fText[1], Size);
{Calculates crc for data readed}
ChunkCRC := update_crc($ffffffff, @ChunkName[0], 4);
ChunkCRC := Byteswap(update_crc(ChunkCRC, @fText[1],
Size) xor
$ffffffff);
{Reads crc and verify}
Stream.Read(ReadCRC, 4);
{Check if crc is valid}
Result := (ReadCRC = ChunkCRC);
if not Result then
Owner.LoadError(EPngInvalidCRC,
EPngInvalidCRCText)
{If it's valid, show text using a message box}
else ShowMessage(fText);
end;
{Assigns contents from another chunk}
procedure TChunkcUSt.Assign(Source: TChunk);
begin
fText := TChunkcUSt(Source.fText);
end;
initialization
RegisterChunk(TChunkcUSt);
finalization