release
notes for the PNG encoder and decoder for Delphi 5 version 1.2
This is version 1.2 of
the encoder and decoder to the Portable Graphics Network format
for Delphi 5. This implementation is capable of reading and saving
images with Gamma correction and direct access to all the PNG
chunks. This implementation was all worked on Delphi 5 and it can show
images progressively, as it is being decoded.
The unit was tested in
all the images Willem van Schaik test
page, and, it worked with 100% of the images.
TPNGImage>TBitmap>TGraphic>TObject>TPersistent |
Component
to implement the PNG format
This is the main
component that implements the decoder and encoder for PNGs. The
component is based on TBitmap meaning it have all TBitmap properties and
methods. It is possible to use the Assign procedure
to copy the contents from most of TGraphic descendents like TJPEGImage,
etc..
procedure
LoadFromStream(Stream: TStream)
Use the
LoadFromStream to load a PNG file from any class derivate from TStream
like TMemoryStream or TFileStream.
The method will read
all the chunks until it find the IEND chunk. If the OnProgress
event is set, using additional code, the image may be displayed progressively
(with a loss of speed).
Example
on how using the method.
{The
method bellow opens the image X.PNG }
{and put it on the background of the }
{current window. Note that this method }
{makes the same work that LoadFromFile do}
var
PNG: TPNGImage;
FStream: TFileStream;
begin
PNG := TPNGImage.Create;
try
FStream := TFileStream.Create('X.PNG',fmOpenRead);
PNG.LoadFromStream(FStream);
Form1.Canvas.Draw(0, 0, PNG);
finally
PNG.Free;
FStream.Free;
end;
end;
See
also:
LoadFromFile
SaveToFile
SaveToStream
procedure
SaveToStream(Stream: TStream)
SaveToStream saves the
current image from the TPNGImage object to a class derivate from TStream
like TFileStream or TMemoryStream.
All the chunks from
the previous loaded image will be mantained, with modifications to the
necessary chunks.
Also, the filter
property is important to set which filters maybe used to save the image.
See
also:
SaveToStream
LoadFromFile
LoadFromStream
procedure
LoadFromFile(const FileName: String)
LoadFromFile loads a
png file from a file specified by the parameter. The image will be
readed until the IEND chunk is found or until the end of the file (some
applications like the current version of ACDSee for a bug does not add
the IEND chunk).
See
also:
SaveToStream
SaveToFile
LoadFromStream
procedure
SaveToFile(const FileName: String)
SaveToFile saves the
current image to a file. The method uses the SaveToStream
procedure to save the image.
See
also:
SaveToStream
LoadFromFile
LoadFromStream
TPNGImage.RegisterChunkClass |
TChunkType = Array[0..3] of
Char;
TChunkClass = class of TChunk;
procedure RegisterChunkClass(ChunkType: TChunkType;
ChunkClass: TChunkClass)
This procedure will
probably not be used. It is used mainly internally for upgrade reasons
to support new chunk types.
When the method TChunkList.Add(Stream:
TStream) is called, the procedure look for registered chunk classes
by this method in an internal chunk list. If the chunk read is
registered, it will create a new chunk class based on the registered to
do special work when the class is being saved or readed.
To create a new class
it is necessary to declare a class based on TChunk and in the ChunkType
field use a name with 4 letters.
The Portable
Graphics Network have some conventions when naming new chunks:
Letter |
What
means if the letter case is: |
Uppercase |
Lowercase |
1 |
The chunk is
critical to the image be decoded |
The chunk is not
critical to the image be decoded. |
2 |
The chunk is public
and is in the PNG specification. |
The chunk is private
and is used only by a specific application. |
3 |
Must be in uppercase. |
Can not be in
lowercase. |
4 |
The chunk is safe to
be copied in case there is any modification in the image. |
The chunk should be
removed in case there are any modifications in the image. |
In the new class created it is possible
to modify the procedures Assign, SaveToStream
and DoAction using override in the declaration to add
specific actions when the chunk is copied, saved or readed.
procedure
Assign(Source: TPersistent)
The Assign procedure
copies the content from another TPNGImage or derivates from TGraphic as
TBitmap, TJPEGImage.
Example
on how using the procedure.
{The method
bellow convert from TJPEGImage}
{to TPNGImage and saves the file. Include }
{jpeg in the application uses}
var
JPEG:TJPEGImage;
PNG :TPNGImage;
begin
JPEG := TJpegImage.Create;
PNG := TPNGImage.Create;
try
JPEG.LoadFromFile('Picture.JPG');
PNG.Assign(JPEG);
PNG.SaveToFile('Picture.PNG');
finally
JPEG.Free;
PNG.Free;
end;
end;
property
Chunks: TChunkList;
Use the Chunks
property to have direct access to all the chunks from the TPNGImage.
Chunks are "pieces" of essential and non essential information
for the image. For instance, the IHDR chunk contains information about the
image size, color type, interlace, type, etc...
The IDAT chunk contains the image itself and will be decoded
automatically.
The IEND chunk indicates the end of the file.
TEncodeFilter
= (efNone, efSub, efUp, efAverage, efPaeth))
TEncodeFilterSet = set of TEncodeFilter
property Filter: TEncodeFilterSet;
The filter property
indicates which filters will be applied before the image is compressed.
It is allowed to set the property as Filter := [efNone, efSub,
efUp, efAverage, efPaeth] to always make sure to use the best filters to
each line (with a performace loose).
Each line in the PNG
may use a different filter, and the encoder will test all the filters in
the property to test which one is better.
TProgressStage
= (psStarting, psRunning, psEnding)
TProgressEvent = procedure (Sender: TObject; Stage: TProgressStage;
PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string)
of object;
property OnProgress: TProgressEvent
The OnProgress event
receives progress information as the image is being decoded. This event
is useful for displaying the image progressively.
For more information
about this event, take a look on the Delphi Help (TGraphic.OnProgress).
Example
on how using the event:
{The method
bellow reads an images and }
{display it as it is being
readed }
procedure TForm1.Progresso(Sender: TObject; Stage:TProgressStage;
PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg:
string
var
PNG: TPNGImage;
begin
PNG := TPNGImage(Sender);
{If it is a TPNG image we can show it progressive}
if (PercentDone mod 5 = 0) and
(TChunkIHDR(PNG.Chunks[0]).Interlaced = 0) then
begin
BitBlt(Canvas.Handle, (Width - PNG.Width) div 2,
((Height - PNG.Height) div 2) + LastPos,
R.Right, R.Bottom - LastPos,
PNG.Canvas.Handle, 0, LastPos, SRCCOPY);
LastPos := R.Bottom;
end
else if (TChunkIHDR(PNG.Chunks[0]).Interlaced = 1) then
Canvas.Draw((Width - PNG.Width) div 2,
((Height) - PNG.Height) div 2, PNG);
end;
Application.Processmessages;
end;
Mananges
all the chunks in the image
The TChunkList
component allows access to all the chunks in the image. Using methods in
this component allows to access, add, remove and manage all the chunks.
Chunks are "pieces"
of essential and not essential information for the image. For instance,
the chunk IHDR contains information about the image dimension, color
type, interlace type, etc...
The chunk IDAT contains the image itself and it will be decoded
automatically.
The IEND chunk indicates the end of the file.
function
Add(Item: TChunk): TChunk;
This Add declaration
add an existent chunk to the end of the list. Although this item must
exist. It will return the same item from the parameter.
function
Add(ChunkClass: TChunkClass): TChunk;
This declaration
creates a new item using the class from the parameter and add it to the
list. It will return the item created.
ex:
PNG.Chunks.Move(PNG.Chunks.Add(TChunkTEXT).Index,
PNG.Chunks.Count - 2);
function
Add(Stream: TStream): TChunk;
This declaration of
the Add method is only used internally. It reads the chunk from the
Stream and add the item to the list. The function returns the chunk
created from the Stream.
procedure
Clear;
This method clears all
the items in the list. It is not recommended to call this method unless
you intend to create the essential chunks before saving the image.
function
IndexOf(Chunk: TChunk): Integer
This declaration of
IndexOf returns the position of the chunk in the parameter. If it is not
in the list, it will return -1.
function
IndexOf(ChunkClass: TChunkClass): Integer
This declaration of
IndexOf returns the position of the first chunk with the specified class
in the parameter. If none item is found, it returns -1.
procedure
Move(Index1, Index2: Integer)
The procedure Move
moves the position of a chunk in the list. Index1 is the position of the
chunk to move and index2 is the new position.
property
Count: Integer;
The property chunk
returns the number of chunks in the list.
property
Item[Index: Integer]: TChunk
The property Item
returns a chunk from the list. As the property is default, it is
possible to access this property with TChunkList object, ex:
PNG.Chunks[0].Index.
Its also possible to
typecast the returned chunk to access it specific property in case there
is a known derived chunk class.
Exemplo
de uso do método.
{The method
bellow, looks for the first }
{TEXT chunk and shows it contains
}
procedure Exibe(Arquivo:
String);
var
PNG: TPNGImage;
POSI: Integer;
TEXT: TChunkTEXT;
begin
PNG := TPNGImage.Create;
PNG.LoadFromFile(Arquivo);
POSI := PNG.Chunks.IndexOf(TChunkTEXT);
If POSI = -1 THEN
begin
showmessage('There are no TEXT chunk in the image.');
exit;
end;
TEXT := TChunkTEXT(PNG.Chunks[Posi]);
showmessagefmt('Keyword: %s%s Valor: %s',
[TEXT.Keyword, #13#10#13#10, TEXT.text]);
PNG.Free;
end;
property
Owner: TPNGImage
The property returns
the TPNGImage owner that contains this TChunkList.
Class
for unknown chunks or base class for known
This class contains
information for a chunk in the image. There are various classes
that derivates from TChunk like TChunkIHDR, TChunkIDAT, TChunkTEXT,
etc... that are implementations for known chunks. You may use typecast
the TChunk to access declared methods and properties from the derivate
classes.
It is not necessary to
access the TChunk and derivates unless you need to access specifics
operations from the Portable Graphics Network format.
All the data from the
stream are declared in the "Stream", a
protected property that allows direct access to the data. Only
descendents classes may access this property and it is intended to be
used in the creation of new TChunk classes.
procedure
Assign(Source: TPersistent); virtual;
This method is used
internally to copy the contents from another chunk with the same class
into the current one.
In case you are
creating a descendent class from TChunk is recommended to override this
class to copy additional properties that the class may store.
procedure
DoAction; virtual;
The DoAction method is
automatically for each chunk as soon as the decoder finishes reading all
the chunk. This procedure is declared as protected and may only
be accessed by TChunk descendent classes.
When creating a new
TChunk class it is essential to override this method if the chunk
modifies the image.
procedure
SaveToStream(Stream: TStream); virtual;
The method
SaveToStream saves the chunk content in a stream. This method is
normally used internally and may be overridden in descendents TChunk
classes to make additional operations (usually cleaning the Stream and writing
the code all over again). The method calculates and add the CRC code
automatically.
TChunkType
= Array[0..3] of Char
property ChunkType: TChunkType
The property returns
the chunk kind for the current chunk.
property
Index: Integer
The property index,
returns the position of the current chunk from the list in the TChunkList
owner.
property
Size: Integer
The property size
returns the size of the stream (Stream.size), which is the chunk data.
property
Stream: TMemoryStream
The stream property is
declared as protected in the TChunk declaration meaning it can't be
accessed directly, but only from descendents of TChunk.
The property gives
direct access to the Chunk contents and may be modified normally as a
TMemoryStream (see Delphi Help).
This property is
important only to create new chunk types as it gives access to the data.
property
Owner: TChunkList
The owner property
returns the TChunkList that contains the current chunk.
TChunkGamma
> TChunk > TObject |
Controls
the image color intensity
The chunk gamma (gAMA),
defines the intensity for the output. As in different operational
systems, or in different environments, the intensity of the same RGB
color may be different, the Portable
Graphics Network specification defines a chunk gAMA to correct the
intensity. The decoder already do all the work when it is decoding the
image, but it is possible to get the value calling the property value.
property
Value: Cardinal
The property Value,
returns the Gamma value from the chunk. To calculate the real value, you
should divide the value from this property by 100000
(using an appropriate variable kind like double, float, real...)
TChunkText
> TChunk > TObject
TChunkZTXT > TChunk > TObject |
Contain
additional text information about the image
The difference between
the chunks TChunkText (tEXT) and TChunkZTXT (zTXT) is that the second
one is compressed meaning that, if the text is large, it will use less
memory.
Booth the chunks have
the same properties and they are used to add extra comments to the image
(like in GIF), such as the image creator, etc..
TChunkText.Keyword
TChunkZTXT.Keyword |
property
Keyword: String
The property Keyword
indicates the meaning of the field value. For
instance, let's suppose you want to put a comment on how the image was
created. You could then put "Image creation" on the Keyword
field.
TChunkText.Value
TChunkZTXT.Value |
property
Value: String
The Value property
indicates the text value for the keyword. There are no limits for the
size, but it is recommended to use the TChunkZTXT in case the text is
big.
TChunkPLTE>TChunk>TObject |
Palette
for indexed mode or recommended palette
The TChunkPLTE
(PLTE) palette is critical in case the color mode is indexed (each pixel
indicates a palette index). It contains the possible colors that the
pixels may use.
In case the color mode is RGB, the palette is a recommended palette to
use.
property
Palette: HPalette
This is a read-only
property. This property creates a palette using WIN32API and returns its
handle (hPalette).
To modify the paletty being used by the current image, it is necessary
to change the property Palette from the TPNGImage. (what requeries
creating a new palette using WIN32API).
This method is used
main internaly and it does not always correspond to the current palette
used by the images. It is recommended to use the property Palette from
TPNGImage.
TChunkIHDR
> TChunk > TObject |
Contains
important information about the image
TChunkIHDR (IHDR) is obligatorily
the first chunk in the image and contains information about the image
dimension, the color mode, interlace type, compression method, and set
of filters.
Although most of the
properties are transfered to the TPNGImage, some information from this
chunk may have some importance.
Modification in this
chunk does not modify the image and they will be overriden when the
image is saved.
property
BitDepth: Byte
This property
indicates how many bits each sample has.
If ColorType
value is Palette, this property can be 1, 2, 4 or 8. This means that
each pixel will have this number of bits.
In case the image is
Grayscale, this property may be 1, 2, 4, 8 or 16. If the value is 0, the
pixel color is black, if the value is 2^BitDepth, the color is white.
In case the ColorType
is RGB, this property can be 8 or 16, and each pixel has 3 values with
the number of the bits corresponding the bitdepth. The values indicates
Red, Green, Blue, or known as RGB. The mix of these 3 values results in
almost any color.
In case the image is
RGBALPHA or GRAYSCALEALPHA, the value can be 8 or 16. RGBALPHA works
like RGB, but with an extra value, alpha, indicating the transparency.
The same thing happens with GRAYSCALEALPHA and GRAYSCALE.
Note: In case
the bitdepth is 16, it will be reduced to 8 due to incompability with
windows and with current video adpters. This although doesn't affect
visually the image.
property
ColorType: Byte
The colortype property
indicates the color mode being used in the current image. The supported
values are:
0 - (Grayscale) Means
that the image uses grayscale tons
1 - (RGB) Each pixel in the image has 3 values RGB
3 - (Palette) Each sample correspond to a palette color
4 - (GrayscaleAlpha) Grayscale with an alpha value
5 - (RGBAlpha) Pixel with 3 RGB values and one alpha
property
Compression: Byte
There is currently
only one possible value for this property, 0. As in Portable
Graphics Network specification it means that the image uses ZLIB
compression method for compressing the images. It was added for future
expansions in PNG.
property
Filter: Byte
This property
indicates the set of filters, that are operations made to the image
bytes before it is compressed, to get a better compression.
Currently, only the
value 0, adaptive filtering with 5 basic filters is supported by PNG
specification. In case the decoder finds any other value, it will report
an error.
property
Height: Cardinal
Returns the image
height (pixels). It is not recommended to use this value because it will
not be updated when the image is changed.
To get the Height, use
the property TPNGImage.Height.
property
Interlaced: Byte
The interlaced
property in the current PNG specification provides two values:
0 - No interlacement
is used
1 - ADAM7 interlacement
Interlacing is a
technique used to show the image contents progressively in a better way
using a different transmission method.
property
Width: Cardinal
Returns the width
(pixels) from the readed image. It is not recommended to use this value
because it value will not be updated when the image is changed.
To get the Width, use
the TPNGImage.Width property.
TChunkIDAT
> TChunk > TObject |
Contain
the file image
The TChunkIDAT (IDAT)
is the main chunk and contains the compressed image. This chunk is
decoded automatically by TPNGImage decoder.
TChunkIEND
> TChunk > TObject |
End
of the file
The IEND chunk
indicates the end of the PNG file.
|