📄 pngimage.pas
字号:
{Size in bytes of each line and offset}
Row_Bytes, Offset : Cardinal;
{Contains data for the lines}
Encode_Buffer: Array[0..5] of pByteArray;
Row_Buffer: Array[Boolean] of pByteArray;
{Variable to invert the Row_Buffer used}
RowUsed: Boolean;
{Ending position for the current IDAT chunk}
EndPos: Integer;
{Filter the current line}
procedure FilterRow;
{Filter to encode and returns the best filter}
function FilterToEncode: Byte;
{Reads ZLIB compressed data}
function IDATZlibRead(var ZLIBStream: TZStreamRec2; Buffer: Pointer;
Count: Integer; var EndPos: Integer; var crcfile: Cardinal): Integer;
{Compress and writes IDAT data}
procedure IDATZlibWrite(var ZLIBStream: TZStreamRec2; Buffer: Pointer;
const Length: Cardinal);
procedure FinishIDATZlib(var ZLIBStream: TZStreamRec2);
{Prepares the palette}
procedure PreparePalette;
protected
{Decode interlaced image}
procedure DecodeInterlacedAdam7(Stream: TStream;
var ZLIBStream: TZStreamRec2; const Size: Integer; var crcfile: Cardinal);
{Decode non interlaced imaged}
procedure DecodeNonInterlaced(Stream: TStream;
var ZLIBStream: TZStreamRec2; const Size: Integer;
var crcfile: Cardinal);
protected
{Encode non interlaced images}
procedure EncodeNonInterlaced(Stream: TStream;
var ZLIBStream: TZStreamRec2);
{Encode interlaced images}
procedure EncodeInterlacedAdam7(Stream: TStream;
var ZLIBStream: TZStreamRec2);
protected
{Memory copy methods to decode}
procedure CopyNonInterlacedRGB8(
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyNonInterlacedRGB16(
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyNonInterlacedPalette148(
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyNonInterlacedPalette2(
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyNonInterlacedGray2(
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyNonInterlacedGrayscale16(
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyNonInterlacedRGBAlpha8(
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyNonInterlacedRGBAlpha16(
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyNonInterlacedGrayscaleAlpha8(
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyNonInterlacedGrayscaleAlpha16(
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyInterlacedRGB8(const Pass: Byte;
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyInterlacedRGB16(const Pass: Byte;
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyInterlacedPalette148(const Pass: Byte;
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyInterlacedPalette2(const Pass: Byte;
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyInterlacedGray2(const Pass: Byte;
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyInterlacedGrayscale16(const Pass: Byte;
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyInterlacedRGBAlpha8(const Pass: Byte;
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyInterlacedRGBAlpha16(const Pass: Byte;
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyInterlacedGrayscaleAlpha8(const Pass: Byte;
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
procedure CopyInterlacedGrayscaleAlpha16(const Pass: Byte;
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar);
protected
{Memory copy methods to encode}
procedure EncodeNonInterlacedRGB8(Src, Dest, Trans: pChar);
procedure EncodeNonInterlacedRGB16(Src, Dest, Trans: pChar);
procedure EncodeNonInterlacedGrayscale16(Src, Dest, Trans: pChar);
procedure EncodeNonInterlacedPalette148(Src, Dest, Trans: pChar);
procedure EncodeNonInterlacedRGBAlpha8(Src, Dest, Trans: pChar);
procedure EncodeNonInterlacedRGBAlpha16(Src, Dest, Trans: pChar);
procedure EncodeNonInterlacedGrayscaleAlpha8(Src, Dest, Trans: pChar);
procedure EncodeNonInterlacedGrayscaleAlpha16(Src, Dest, Trans: pChar);
procedure EncodeInterlacedRGB8(const Pass: Byte; Src, Dest, Trans: pChar);
procedure EncodeInterlacedRGB16(const Pass: Byte; Src, Dest, Trans: pChar);
procedure EncodeInterlacedPalette148(const Pass: Byte;
Src, Dest, Trans: pChar);
procedure EncodeInterlacedGrayscale16(const Pass: Byte;
Src, Dest, Trans: pChar);
procedure EncodeInterlacedRGBAlpha8(const Pass: Byte;
Src, Dest, Trans: pChar);
procedure EncodeInterlacedRGBAlpha16(const Pass: Byte;
Src, Dest, Trans: pChar);
procedure EncodeInterlacedGrayscaleAlpha8(const Pass: Byte;
Src, Dest, Trans: pChar);
procedure EncodeInterlacedGrayscaleAlpha16(const Pass: Byte;
Src, Dest, Trans: pChar);
public
{Loads the chunk from a stream}
function LoadFromStream(Stream: TStream; const ChunkName: TChunkName;
Size: Integer): Boolean; override;
{Saves the chunk to a stream}
function SaveToStream(Stream: TStream): Boolean; override;
end;
{Image last modification chunk}
TChunktIME = class(TChunk)
private
{Holds the variables}
fYear: Word;
fMonth, fDay, fHour, fMinute, fSecond: Byte;
public
{Returns/sets variables}
property Year: Word read fYear write fYear;
property Month: Byte read fMonth write fMonth;
property Day: Byte read fDay write fDay;
property Hour: Byte read fHour write fHour;
property Minute: Byte read fMinute write fMinute;
property Second: Byte read fSecond write fSecond;
{Loads the chunk from a stream}
function LoadFromStream(Stream: TStream; const ChunkName: TChunkName;
Size: Integer): Boolean; override;
{Saves the chunk to a stream}
function SaveToStream(Stream: TStream): Boolean; override;
{Assigns from another TChunk}
procedure Assign(Source: TChunk); override;
end;
{Textual data}
TChunktEXt = class(TChunk)
private
fKeyword, fText: String;
public
{Keyword and text}
property Keyword: String read fKeyword write fKeyword;
property Text: String read fText write fText;
{Loads the chunk from a stream}
function LoadFromStream(Stream: TStream; const ChunkName: TChunkName;
Size: Integer): Boolean; override;
{Saves the chunk to a stream}
function SaveToStream(Stream: TStream): Boolean; override;
{Assigns from another TChunk}
procedure Assign(Source: TChunk); override;
end;
{zTXT chunk}
TChunkzTXt = class(TChunktEXt)
{Loads the chunk from a stream}
function LoadFromStream(Stream: TStream; const ChunkName: TChunkName;
Size: Integer): Boolean; override;
{Saves the chunk to a stream}
function SaveToStream(Stream: TStream): Boolean; override;
end;
{Here we test if it's c++ builder or delphi version 3 or less}
{$IFDEF VER110}{$DEFINE DelphiBuilder3Less}{$ENDIF}
{$IFDEF VER100}{$DEFINE DelphiBuilder3Less}{$ENDIF}
{$IFDEF VER93}{$DEFINE DelphiBuilder3Less}{$ENDIF}
{$IFDEF VER90}{$DEFINE DelphiBuilder3Less}{$ENDIF}
{$IFDEF VER80}{$DEFINE DelphiBuilder3Less}{$ENDIF}
{Registers a new chunk class}
procedure RegisterChunk(ChunkClass: TChunkClass);
{Calculates crc}
function update_crc(crc: {$IFNDEF DelphiBuilder3Less}Cardinal{$ELSE}Integer
{$ENDIF}; buf: pByteArray; len: Integer): Cardinal;
{Invert bytes using assembly}
function ByteSwap(const a: integer): integer;
implementation
var
ChunkClasses: TPngPointerList;
{Table of CRCs of all 8-bit messages}
crc_table: Array[0..255] of Cardinal;
{Flag: has the table been computed? Initially false}
crc_table_computed: Boolean;
{Draw transparent image using transparent color}
procedure DrawTransparentBitmap(dc: HDC; srcBits: Pointer;
var srcHeader: TBitmapInfoHeader;
srcBitmapInfo: pBitmapInfo; Rect: TRect; cTransparentColor: COLORREF);
var
cColor: COLORREF;
bmAndBack, bmAndObject, bmAndMem: HBITMAP;
bmBackOld, bmObjectOld, bmMemOld: HBITMAP;
hdcMem, hdcBack, hdcObject, hdcTemp: HDC;
ptSize, orgSize: TPOINT;
OldBitmap, DrawBitmap: HBITMAP;
begin
hdcTemp := CreateCompatibleDC(dc);
// Select the bitmap
DrawBitmap := CreateDIBitmap(dc, srcHeader, CBM_INIT, srcBits, srcBitmapInfo^,
DIB_RGB_COLORS);
OldBitmap := SelectObject(hdcTemp, DrawBitmap);
// Sizes
OrgSize.x := abs(srcHeader.biWidth);
OrgSize.y := abs(srcHeader.biHeight);
ptSize.x := Rect.Right - Rect.Left; // Get width of bitmap
ptSize.y := Rect.Bottom - Rect.Top; // Get height of bitmap
// Create some DCs to hold temporary data.
hdcBack := CreateCompatibleDC(dc);
hdcObject := CreateCompatibleDC(dc);
hdcMem := CreateCompatibleDC(dc);
// Create a bitmap for each DC. DCs are required for a number of
// GDI functions.
// Monochrome DCs
bmAndBack := CreateBitmap(ptSize.x, ptSize.y, 1, 1, nil);
bmAndObject := CreateBitmap(ptSize.x, ptSize.y, 1, 1, nil);
bmAndMem := CreateCompatibleBitmap(dc, ptSize.x, ptSize.y);
// Each DC must select a bitmap object to store pixel data.
bmBackOld := SelectObject(hdcBack, bmAndBack);
bmObjectOld := SelectObject(hdcObject, bmAndObject);
bmMemOld := SelectObject(hdcMem, bmAndMem);
// Set the background color of the source DC to the color.
// contained in the parts of the bitmap that should be transparent
cColor := SetBkColor(hdcTemp, cTransparentColor);
// Create the object mask for the bitmap by performing a BitBlt
// from the source bitmap to a monochrome bitmap.
StretchBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,
orgSize.x, orgSize.y, SRCCOPY);
// Set the background color of the source DC back to the original
// color.
SetBkColor(hdcTemp, cColor);
// Create the inverse of the object mask.
BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0,
NOTSRCCOPY);
// Copy the background of the main DC to the destination.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, dc, Rect.Left, Rect.Top,
SRCCOPY);
// Mask out the places where the bitmap will be placed.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
// Mask out the transparent colored pixels on the bitmap.
// BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
StretchBlt(hdcTemp, 0, 0, OrgSize.x, OrgSize.y, hdcBack, 0, 0,
PtSize.x, PtSize.y, SRCAND);
// XOR the bitmap with the background on the destination DC.
StretchBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,
OrgSize.x, OrgSize.y, SRCPAINT);
// Copy the destination to the screen.
BitBlt(dc, Rect.Left, Rect.Top, ptSize.x, ptSize.y, hdcMem, 0, 0,
SRCCOPY);
// Delete the memory bitmaps.
DeleteObject(SelectObject(hdcBack, bmBackOld));
DeleteObject(SelectObject(hdcObject, bmObjectOld));
DeleteObject(SelectObject(hdcMem, bmMemOld));
DeleteObject(SelectObject(hdcTemp, OldBitmap));
// Delete the memory DCs.
DeleteDC(hdcMem);
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcTemp);
end;
{Make the table for a fast CRC.}
procedure make_crc_table;
var
c: Cardinal;
n, k: Integer;
begin
{fill the crc table}
for n := 0 to 255 do
begin
c := Cardinal(n);
for k := 0 to 7 do
begin
if Boolean(c and 1) then
c := $edb88320 xor (c shr 1)
else
c := c shr 1;
end;
crc_table[n] := c;
end;
{The table has already being computated}
crc_table_computed := true;
end;
{Update a running CRC with the bytes buf[0..len-1]--the CRC
should be initialized to all 1's, and the transmitted value
is the 1's complement of the final running CRC (see the
crc() routine below)).}
function update_crc(crc: {$IFNDEF DelphiBuilder3Less}Cardinal{$ELSE}Integer
{$ENDIF}; buf: pByteArray; len: Integer): Cardinal;
var
c: Cardinal;
n: Integer;
begin
c := crc;
{Create the crc table in case it has not being computed yet}
if not crc_table_computed then make_crc_table;
{Update}
for n := 0 to len - 1 do
c := crc_table[(c XOR buf^[n]) and $FF] XOR (c shr 8);
{Returns}
Result := c;
end;
{$IFNDEF UseDelphi}
function FileExists(Filename: String): Boolean;
var
FindFile: THandle;
FindData: TWin32FindData;
begin
FindFile := FindFirstFile(PChar(Filename), FindData);
Result := FindFile <> INVALID_HANDLE_VALUE;
if Result then Windows.FindClose(FindFile);
end;
{$ENDIF}
{$IFNDEF UseDelphi}
{Exception implementation}
constructor Exception.Create(Msg: String);
begin
end;
{$ENDIF}
{Calculates the paeth predictor}
function PaethPredictor(a, b, c: Byte): Byte;
var
pa, pb, pc: Integer;
begin
{ a = left, b = above, c = upper left }
pa := abs(b - c); { distances to a, b, c }
pb := abs(a - c);
pc := abs(a + b - c * 2);
{ return nearest of a, b, c, breaking ties in order a, b, c }
if (pa <= pb) and (pa <= pc) then
Result := a
else
if pb <= pc then
Result := b
else
Result := c;
end;
{Invert bytes using assembly}
function ByteSwap(const a: integer): integer;
asm
bswap eax
end;
function ByteSwap16(inp:word): word;
asm
bswap eax
shr eax, 16
end;
{Calculates number of bytes for the number of pixels using the}
{color mode in the paramenter}
function BytesForPixels(const Pixels: Integer; const ColorType,
BitDepth: Byte): Integer;
begin
case ColorType of
{Palette and grayscale contains a single value, for palette}
{an value of size 2^bitdepth pointing to the palette index}
{and grayscale the value from 0 to 2^bitdepth with color intesity}
COLOR_GRAYSCALE, COLOR_PALETTE:
Result := (Pixels * BitDepth + 7) div 8;
{RGB contains 3 values R, G, B with size 2^bitdepth each}
COLOR_RGB:
Result := (Pixels * BitDepth * 3) div 8;
{Contains one value followed by alpha value booth size 2^bitdepth}
COLOR_GRAYSCALEALPHA:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -