📄 pngimage.pas
字号:
Buffer : Array[Byte] of Byte;
InflateRet: Integer;
begin
with StreamRec do
begin
{Initializes}
Result := True;
OutputSize := 0;
{Prepares the data to decompress}
FillChar(StreamRec, SizeOf(TZStreamRec), #0);
InflateInit_(StreamRec, zlib_version, SIZEOF(TZStreamRec));
next_in := Input;
avail_in := InputSize;
{Decodes data}
repeat
{In case it needs an output buffer}
if (avail_out = 0) then
begin
next_out := @Buffer;
avail_out := SizeOf(Buffer);
end {if (avail_out = 0)};
{Decompress and put in output}
InflateRet := inflate(StreamRec, 0);
if (InflateRet = Z_STREAM_END) or (InflateRet = 0) then
begin
{Reallocates output buffer}
inc(OutputSize, total_out);
if Output = nil then
GetMem(Output, OutputSize) else ReallocMem(Output, OutputSize);
{Copies the new data}
CopyMemory(Ptr(Longint(Output) + OutputSize - total_out),
@Buffer, total_out);
end {if (InflateRet = Z_STREAM_END) or (InflateRet = 0)}
{Now tests for errors}
else if InflateRet < 0 then
begin
Result := False;
ErrorOutput := StreamRec.msg;
InflateEnd(StreamRec);
Exit;
end {if InflateRet < 0}
until InflateRet = Z_STREAM_END;
{Terminates decompression}
InflateEnd(StreamRec);
end {with StreamRec}
end;
{Compresses ZLIB into a memory address}
function CompressZLIB(Input: Pointer; InputSize, CompressionLevel: Integer;
var Output: Pointer; var OutputSize: Integer;
var ErrorOutput: String): Boolean;
var
StreamRec : TZStreamRec;
Buffer : Array[Byte] of Byte;
DeflateRet: Integer;
begin
with StreamRec do
begin
Result := True; {By default returns TRUE as everything might have gone ok}
OutputSize := 0; {Initialize}
{Prepares the data to compress}
FillChar(StreamRec, SizeOf(TZStreamRec), #0);
DeflateInit_(StreamRec, CompressionLevel,zlib_version, SIZEOF(TZStreamRec));
next_in := Input;
avail_in := InputSize;
while avail_in > 0 do
begin
{When it needs new buffer to stores the compressed data}
if avail_out = 0 then
begin
{Restore buffer}
next_out := @Buffer;
avail_out := SizeOf(Buffer);
end {if avail_out = 0};
{Compresses}
DeflateRet := deflate(StreamRec, Z_FINISH);
if (DeflateRet = Z_STREAM_END) or (DeflateRet = 0) then
begin
{Updates the output memory}
inc(OutputSize, total_out);
if Output = nil then
GetMem(Output, OutputSize) else ReallocMem(Output, OutputSize);
{Copies the new data}
CopyMemory(Ptr(Longint(Output) + OutputSize - total_out),
@Buffer, total_out);
end {if (InflateRet = Z_STREAM_END) or (InflateRet = 0)}
{Now tests for errors}
else if DeflateRet < 0 then
begin
Result := False;
ErrorOutput := StreamRec.msg;
DeflateEnd(StreamRec);
Exit;
end {if InflateRet < 0}
end {while avail_in > 0};
{Finishes compressing}
DeflateEnd(StreamRec);
end {with StreamRec}
end;
{TPngPointerList implementation}
{Object being created}
constructor TPngPointerList.Create(AOwner: TPNGObject);
begin
inherited Create; {Let ancestor work}
{Holds owner}
fOwner := AOwner;
{Memory pointer not being used yet}
fMemory := nil;
{No items yet}
fCount := 0;
end;
{Removes value from the list}
function TPngPointerList.Remove(Value: Pointer): Pointer;
var
I, Position: Integer;
begin
{Gets item position}
Position := -1;
FOR I := 0 TO Count - 1 DO
if Value = Item[I] then Position := I;
{In case a match was found}
if Position >= 0 then
begin
Result := Item[Position]; {Returns pointer}
{Remove item and move memory}
Dec(fCount);
if Position < Integer(FCount) then
System.Move(fMemory^[Position + 1], fMemory^[Position],
(Integer(fCount) - Position) * SizeOf(Pointer));
end {if Position >= 0} else Result := nil
end;
{Add a new value in the list}
procedure TPngPointerList.Add(Value: Pointer);
begin
Count := Count + 1;
Item[Count - 1] := Value;
end;
{Object being destroyed}
destructor TPngPointerList.Destroy;
begin
{Release memory if needed}
if fMemory <> nil then
FreeMem(fMemory, fCount * sizeof(Pointer));
{Free things}
inherited Destroy;
end;
{Returns one item from the list}
function TPngPointerList.GetItem(Index: Cardinal): Pointer;
begin
if (Index <= Count - 1) then
Result := fMemory[Index]
else
{In case it's out of bounds}
Result := nil;
end;
{Inserts a new item in the list}
procedure TPngPointerList.Insert(Value: Pointer; Position: Cardinal);
begin
if (Position < Count) then
begin
{Increase item count}
SetSize(Count + 1);
{Move other pointers}
if Position < Count then
System.Move(fMemory^[Position], fMemory^[Position + 1],
(Count - Position - 1) * SizeOf(Pointer));
{Sets item}
Item[Position] := Value;
end;
end;
{Sets one item from the list}
procedure TPngPointerList.SetItem(Index: Cardinal; const Value: Pointer);
begin
{If index is in bounds, set value}
if (Index <= Count - 1) then
fMemory[Index] := Value
end;
{This method resizes the list}
procedure TPngPointerList.SetSize(const Size: Cardinal);
begin
{Sets the size}
if (fMemory = nil) and (Size > 0) then
GetMem(fMemory, Size * SIZEOF(Pointer))
else
if Size > 0 then {Only realloc if the new size is greater than 0}
ReallocMem(fMemory, Size * SIZEOF(Pointer))
else
{In case user is resize to 0 items}
begin
FreeMem(fMemory);
fMemory := nil;
end;
{Update count}
fCount := Size;
end;
{TPNGList implementation}
{Removes an item}
procedure TPNGList.RemoveChunk(Chunk: TChunk);
begin
Remove(Chunk);
Chunk.Free
end;
{Add a new item}
function TPNGList.Add(ChunkClass: TChunkClass): TChunk;
var
IHDR: TChunkIHDR;
IEND: TChunkIEND;
IDAT: TChunkIDAT;
PLTE: TChunkPLTE;
begin
Result := nil; {Default result}
{Adding these is not allowed}
if (ChunkClass = TChunkIHDR) or (ChunkClass = TChunkIDAT) or
(ChunkClass = TChunkPLTE) or (ChunkClass = TChunkIEND) then
fOwner.RaiseError(EPngError, EPNGCannotAddChunkText)
{Two of these is not allowed}
else if ((ChunkClass = TChunkgAMA) and (ItemFromClass(TChunkgAMA) <> nil)) or
((ChunkClass = TChunktRNS) and (ItemFromClass(TChunktRNS) <> nil)) then
fOwner.RaiseError(EPngError, EPNGCannotAddChunkText)
{There must have an IEND and IHDR chunk}
else if (ItemFromClass(TChunkIEND) = nil) or
(ItemFromClass(TChunkIHDR) = nil) then
fOwner.RaiseError(EPngError, EPNGCannotAddInvalidImageText)
else
begin
{Get common chunks}
IHDR := ItemFromClass(TChunkIHDR) as TChunkIHDR;
IEND := ItemFromClass(TChunkIEND) as TChunkIEND;
{Create new chunk}
Result := ChunkClass.Create(Owner);
{Add to the list}
if (ChunkClass = TChunkgAMA) then
Insert(Result, IHDR.Index + 1)
{Transparency chunk (fix by Ian Boyd)}
else if (ChunkClass = TChunktRNS) then
begin
{Transparecy chunk must be after PLTE; before IDAT}
IDAT := ItemFromClass(TChunkIDAT) as TChunkIDAT;
PLTE := ItemFromClass(TChunkPLTE) as TChunkPLTE;
if Assigned(PLTE) then
Insert(Result, PLTE.Index + 1)
else if Assigned(IDAT) then
Insert(Result, IDAT.Index)
else
Insert(Result, IHDR.Index + 1)
end
else {All other chunks}
Insert(Result, IEND.Index);
end {if}
end;
{Returns item from the list}
function TPNGList.GetItem(Index: Cardinal): TChunk;
begin
Result := inherited GetItem(Index);
end;
{Returns first item from the list using the class from parameter}
function TPNGList.ItemFromClass(ChunkClass: TChunkClass): TChunk;
var
i: Integer;
begin
Result := nil; {Initial result}
FOR i := 0 TO Count - 1 DO
{Test if this item has the same class}
if Item[i] is ChunkClass then
begin
{Returns this item and exit}
Result := Item[i];
break;
end {if}
end;
{$IFNDEF UseDelphi}
{TStream implementation}
{Copies all from another stream}
function TStream.CopyFrom(Source: TStream; Count: Cardinal): Cardinal;
const
MaxBytes = $f000;
var
Buffer: PChar;
BufSize, N: Cardinal;
begin
{If count is zero, copy everything from Source}
if Count = 0 then
begin
Source.Seek(0, soFromBeginning);
Count := Source.Size;
end;
Result := Count; {Returns the number of bytes readed}
{Allocates memory}
if Count > MaxBytes then BufSize := MaxBytes else BufSize := Count;
GetMem(Buffer, BufSize);
{Copy memory}
while Count > 0 do
begin
if Count > BufSize then N := BufSize else N := Count;
Source.Read(Buffer^, N);
Write(Buffer^, N);
dec(Count, N);
end;
{Deallocates memory}
FreeMem(Buffer, BufSize);
end;
{Set current stream position}
procedure TStream.SetPosition(const Value: Longint);
begin
Seek(Value, soFromBeginning);
end;
{Returns position}
function TStream.GetPosition: Longint;
begin
Result := Seek(0, soFromCurrent);
end;
{Returns stream size}
function TStream.GetSize: Longint;
var
Pos: Cardinal;
begin
Pos := Seek(0, soFromCurrent);
Result := Seek(0, soFromEnd);
Seek(Pos, soFromCurrent);
end;
{TFileStream implementation}
{Filestream object being created}
constructor TFileStream.Create(Filename: String; Mode: TFileStreamModeSet);
{Makes file mode}
function OpenMode: DWORD;
begin
Result := 0;
if fsmRead in Mode then Result := GENERIC_READ;
if (fsmWrite in Mode) or (fsmCreate in Mode) then
Result := Result OR GENERIC_WRITE;
end;
const
IsCreate: Array[Boolean] of Integer = (OPEN_ALWAYS, CREATE_ALWAYS);
begin
{Call ancestor}
inherited Create;
{Create handle}
fHandle := CreateFile(PChar(Filename), OpenMode, FILE_SHARE_READ or
FILE_SHARE_WRITE, nil, IsCreate[fsmCreate in Mode], 0, 0);
{Store mode}
FileMode := Mode;
end;
{Filestream object being destroyed}
destructor TFileStream.Destroy;
begin
{Terminates file and close}
if FileMode = [fsmWrite] then
SetEndOfFile(fHandle);
CloseHandle(fHandle);
{Call ancestor}
inherited Destroy;
end;
{Writes data to the file}
function TFileStream.Write(const Buffer; Count: Longint): Cardinal;
begin
if not WriteFile(fHandle, Buffer, Count, Result, nil) then
Result := 0;
end;
{Reads data from the file}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -