670 lines
19 KiB
Plaintext
670 lines
19 KiB
Plaintext
{
|
|
Vampyre Imaging Library
|
|
by Marek Mauder
|
|
https://github.com/galfar/imaginglib
|
|
https://imaginglib.sourceforge.io
|
|
- - - - -
|
|
This Source Code Form is subject to the terms of the Mozilla Public
|
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
file, You can obtain one at https://mozilla.org/MPL/2.0.
|
|
}
|
|
|
|
{ This unit contains default IO functions for reading from/writing to
|
|
files, streams and memory.}
|
|
unit ImagingIO;
|
|
|
|
{$I ImagingOptions.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, Classes, ImagingTypes, Imaging, ImagingUtility;
|
|
|
|
type
|
|
TMemoryIORec = record
|
|
Data: ImagingUtility.PByteArray;
|
|
Position: LongInt;
|
|
Size: LongInt;
|
|
end;
|
|
PMemoryIORec = ^TMemoryIORec;
|
|
|
|
var
|
|
OriginalFileIO: TIOFunctions;
|
|
FileIO: TIOFunctions;
|
|
StreamIO: TIOFunctions;
|
|
MemoryIO: TIOFunctions;
|
|
|
|
{ Helper function that returns size of input (from current position to the end)
|
|
represented by Handle (and opened and operated on by members of IOFunctions).}
|
|
function GetInputSize(const IOFunctions: TIOFunctions; Handle: TImagingHandle): Int64;
|
|
{ Helper function that initializes TMemoryIORec with given params.}
|
|
function PrepareMemIO(Data: Pointer; Size: LongInt): TMemoryIORec;
|
|
{ Reads one text line from input (CR+LF, CR, or LF as line delimiter).}
|
|
function ReadLine(const IOFunctions: TIOFunctions; Handle: TImagingHandle;
|
|
out Line: AnsiString; FailOnControlChars: Boolean = False): Boolean;
|
|
{ Writes one text line to input with optional line delimiter.}
|
|
procedure WriteLine(const IOFunctions: TIOFunctions; Handle: TImagingHandle;
|
|
const Line: AnsiString; const LineEnding: AnsiString = sLineBreak);
|
|
|
|
type
|
|
TReadMemoryStream = class(TCustomMemoryStream)
|
|
public
|
|
constructor Create(Data: Pointer; Size: Integer);
|
|
class function CreateFromIOHandle(const IOFunctions: TIOFunctions; Handle: TImagingHandle): TReadMemoryStream;
|
|
end;
|
|
|
|
TImagingIOStream = class(TStream)
|
|
private
|
|
FIO: TIOFunctions;
|
|
FHandle: TImagingHandle;
|
|
public
|
|
constructor Create(const IOFunctions: TIOFunctions; Handle: TImagingHandle);
|
|
end;
|
|
|
|
implementation
|
|
|
|
const
|
|
DefaultBufferSize = 16 * 1024;
|
|
|
|
type
|
|
{ Based on TaaBufferedStream
|
|
Copyright (c) Julian M Bucknall 1997, 1999 }
|
|
TBufferedStream = class
|
|
private
|
|
FBuffer: PByteArray;
|
|
FBufSize: Integer;
|
|
FBufStart: Integer;
|
|
FBufPos: Integer;
|
|
FBytesInBuf: Integer;
|
|
FSize: Integer;
|
|
FDirty: Boolean;
|
|
FStream: TStream;
|
|
function GetPosition: Integer;
|
|
function GetSize: Integer;
|
|
procedure ReadBuffer;
|
|
procedure WriteBuffer;
|
|
procedure SetPosition(const Value: Integer);
|
|
public
|
|
constructor Create(AStream: TStream);
|
|
destructor Destroy; override;
|
|
function Read(var Buffer; Count: Integer): Integer;
|
|
function Write(const Buffer; Count: Integer): Integer;
|
|
function Seek(Offset: Integer; Origin: Word): Integer;
|
|
procedure Commit;
|
|
property Stream: TStream read FStream;
|
|
property Position: Integer read GetPosition write SetPosition;
|
|
property Size: Integer read GetSize;
|
|
end;
|
|
|
|
constructor TBufferedStream.Create(AStream: TStream);
|
|
begin
|
|
inherited Create;
|
|
FStream := AStream;
|
|
FBufSize := DefaultBufferSize;
|
|
GetMem(FBuffer, FBufSize);
|
|
FBufPos := 0;
|
|
FBytesInBuf := 0;
|
|
FBufStart := 0;
|
|
FDirty := False;
|
|
FSize := AStream.Size;
|
|
end;
|
|
|
|
destructor TBufferedStream.Destroy;
|
|
begin
|
|
if FBuffer <> nil then
|
|
begin
|
|
Commit;
|
|
FreeMem(FBuffer);
|
|
end;
|
|
FStream.Position := Position; // Make sure source stream has right position
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TBufferedStream.GetPosition: Integer;
|
|
begin
|
|
Result := FBufStart + FBufPos;
|
|
end;
|
|
|
|
procedure TBufferedStream.SetPosition(const Value: Integer);
|
|
begin
|
|
Seek(Value, soFromCurrent);
|
|
end;
|
|
|
|
function TBufferedStream.GetSize: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
procedure TBufferedStream.ReadBuffer;
|
|
var
|
|
SeekResult: Integer;
|
|
begin
|
|
SeekResult := FStream.Seek(FBufStart, soBeginning);
|
|
if SeekResult = -1 then
|
|
raise Exception.Create('TBufferedStream.ReadBuffer: seek failed');
|
|
FBytesInBuf := FStream.Read(FBuffer^, FBufSize);
|
|
if FBytesInBuf <= 0 then
|
|
raise Exception.Create('TBufferedStream.ReadBuffer: read failed');
|
|
end;
|
|
|
|
procedure TBufferedStream.WriteBuffer;
|
|
var
|
|
SeekResult: Integer;
|
|
BytesWritten: Integer;
|
|
begin
|
|
SeekResult := FStream.Seek(FBufStart, soBeginning);
|
|
if SeekResult = -1 then
|
|
raise Exception.Create('TBufferedStream.WriteBuffer: seek failed');
|
|
BytesWritten := FStream.Write(FBuffer^, FBytesInBuf);
|
|
if BytesWritten <> FBytesInBuf then
|
|
raise Exception.Create('TBufferedStream.WriteBuffer: write failed');
|
|
end;
|
|
|
|
procedure TBufferedStream.Commit;
|
|
begin
|
|
if FDirty then
|
|
begin
|
|
WriteBuffer;
|
|
FDirty := False;
|
|
end;
|
|
end;
|
|
|
|
function TBufferedStream.Read(var Buffer; Count: Integer): Integer;
|
|
var
|
|
BufAsBytes: TByteArray absolute Buffer;
|
|
BufIdx, BytesToGo, BytesToRead: Integer;
|
|
begin
|
|
// Calculate the actual number of bytes we can read - this depends on
|
|
// the current position and size of the stream as well as the number
|
|
// of bytes requested.
|
|
BytesToGo := Count;
|
|
if FSize < (FBufStart + FBufPos + Count) then
|
|
BytesToGo := FSize - (FBufStart + FBufPos);
|
|
|
|
if BytesToGo <= 0 then
|
|
begin
|
|
Result := 0;
|
|
Exit;
|
|
end;
|
|
// Remember to return the result of our calculation
|
|
Result := BytesToGo;
|
|
|
|
BufIdx := 0;
|
|
if FBytesInBuf = 0 then
|
|
ReadBuffer;
|
|
// Calculate the number of bytes we can read prior to the loop
|
|
BytesToRead := FBytesInBuf - FBufPos;
|
|
if BytesToRead > BytesToGo then
|
|
BytesToRead := BytesToGo;
|
|
// Copy from the stream buffer to the caller's buffer
|
|
Move(FBuffer^[FBufPos], BufAsBytes[BufIdx], BytesToRead);
|
|
// Calculate the number of bytes still to read}
|
|
Dec(BytesToGo, BytesToRead);
|
|
|
|
// while we have bytes to read, read them
|
|
while BytesToGo > 0 do
|
|
begin
|
|
Inc(BufIdx, BytesToRead);
|
|
// As we've exhausted this buffer-full, advance to the next, check
|
|
// to see whether we need to write the buffer out first
|
|
if FDirty then
|
|
begin
|
|
WriteBuffer;
|
|
FDirty := false;
|
|
end;
|
|
Inc(FBufStart, FBufSize);
|
|
FBufPos := 0;
|
|
ReadBuffer;
|
|
// Calculate the number of bytes we can read in this cycle
|
|
BytesToRead := FBytesInBuf;
|
|
if BytesToRead > BytesToGo then
|
|
BytesToRead := BytesToGo;
|
|
// Copy from the stream buffer to the caller's buffer
|
|
Move(FBuffer^, BufAsBytes[BufIdx], BytesToRead);
|
|
// Calculate the number of bytes still to read
|
|
Dec(BytesToGo, BytesToRead);
|
|
end;
|
|
// Remember our new position
|
|
Inc(FBufPos, BytesToRead);
|
|
if FBufPos = FBufSize then
|
|
begin
|
|
Inc(FBufStart, FBufSize);
|
|
FBufPos := 0;
|
|
FBytesInBuf := 0;
|
|
end;
|
|
end;
|
|
|
|
function TBufferedStream.Seek(Offset: Integer; Origin: Word): Integer;
|
|
var
|
|
NewBufStart, NewPos: Integer;
|
|
begin
|
|
// Calculate the new position
|
|
case Origin of
|
|
soFromBeginning : NewPos := Offset;
|
|
soFromCurrent : NewPos := FBufStart + FBufPos + Offset;
|
|
soFromEnd : NewPos := FSize + Offset;
|
|
else
|
|
raise Exception.Create('TBufferedStream.Seek: invalid origin');
|
|
end;
|
|
|
|
if (NewPos < 0) or (NewPos > FSize) then
|
|
begin
|
|
//NewPos := ClampInt(NewPos, 0, FSize); don't do this - for writing
|
|
end;
|
|
// Calculate which page of the file we need to be at
|
|
NewBufStart := NewPos and not Pred(FBufSize);
|
|
// If the new page is different than the old, mark the buffer as being
|
|
// ready to be replenished, and if need be write out any dirty data
|
|
if NewBufStart <> FBufStart then
|
|
begin
|
|
if FDirty then
|
|
begin
|
|
WriteBuffer;
|
|
FDirty := False;
|
|
end;
|
|
FBufStart := NewBufStart;
|
|
FBytesInBuf := 0;
|
|
end;
|
|
// Save the new position
|
|
FBufPos := NewPos - NewBufStart;
|
|
Result := NewPos;
|
|
end;
|
|
|
|
function TBufferedStream.Write(const Buffer; Count: Integer): Integer;
|
|
var
|
|
BufAsBytes: TByteArray absolute Buffer;
|
|
BufIdx, BytesToGo, BytesToWrite: Integer;
|
|
begin
|
|
// When we write to this stream we always assume that we can write the
|
|
// requested number of bytes: if we can't (eg, the disk is full) we'll
|
|
// get an exception somewhere eventually.
|
|
BytesToGo := Count;
|
|
// Remember to return the result of our calculation
|
|
Result := BytesToGo;
|
|
|
|
BufIdx := 0;
|
|
if (FBytesInBuf = 0) and (FSize > FBufStart) then
|
|
ReadBuffer;
|
|
// Calculate the number of bytes we can write prior to the loop
|
|
BytesToWrite := FBufSize - FBufPos;
|
|
if BytesToWrite > BytesToGo then
|
|
BytesToWrite := BytesToGo;
|
|
// Copy from the caller's buffer to the stream buffer
|
|
Move(BufAsBytes[BufIdx], FBuffer^[FBufPos], BytesToWrite);
|
|
// Mark our stream buffer as requiring a save to the actual stream,
|
|
// note that this will suffice for the rest of the routine as well: no
|
|
// inner routine will turn off the dirty flag.
|
|
FDirty := True;
|
|
// Calculate the number of bytes still to write
|
|
Dec(BytesToGo, BytesToWrite);
|
|
|
|
// While we have bytes to write, write them
|
|
while BytesToGo > 0 do
|
|
begin
|
|
Inc(BufIdx, BytesToWrite);
|
|
// As we've filled this buffer, write it out to the actual stream
|
|
// and advance to the next buffer, reading it if required
|
|
FBytesInBuf := FBufSize;
|
|
WriteBuffer;
|
|
Inc(FBufStart, FBufSize);
|
|
FBufPos := 0;
|
|
FBytesInBuf := 0;
|
|
if FSize > FBufStart then
|
|
ReadBuffer;
|
|
// Calculate the number of bytes we can write in this cycle
|
|
BytesToWrite := FBufSize;
|
|
if BytesToWrite > BytesToGo then
|
|
BytesToWrite := BytesToGo;
|
|
// Copy from the caller's buffer to our buffer
|
|
Move(BufAsBytes[BufIdx], FBuffer^, BytesToWrite);
|
|
// Calculate the number of bytes still to write
|
|
Dec(BytesToGo, BytesToWrite);
|
|
end;
|
|
// Remember our new position
|
|
Inc(FBufPos, BytesToWrite);
|
|
// Make sure the count of valid bytes is correct
|
|
if FBytesInBuf < FBufPos then
|
|
FBytesInBuf := FBufPos;
|
|
// Make sure the stream size is correct
|
|
if FSize < (FBufStart + FBytesInBuf) then
|
|
FSize := FBufStart + FBytesInBuf;
|
|
// If we're at the end of the buffer, write it out and advance to the
|
|
// start of the next page
|
|
if FBufPos = FBufSize then
|
|
begin
|
|
WriteBuffer;
|
|
FDirty := False;
|
|
Inc(FBufStart, FBufSize);
|
|
FBufPos := 0;
|
|
FBytesInBuf := 0;
|
|
end;
|
|
end;
|
|
|
|
{ File IO functions }
|
|
|
|
function FileOpen(FileName: PChar; Mode: TOpenMode): TImagingHandle; cdecl;
|
|
var
|
|
Stream: TStream;
|
|
begin
|
|
Stream := nil;
|
|
|
|
case Mode of
|
|
omReadOnly: Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
|
|
omCreate: Stream := TFileStream.Create(FileName, fmCreate);
|
|
omReadWrite:
|
|
begin
|
|
if FileExists(FileName) then
|
|
Stream := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive)
|
|
else
|
|
Stream := TFileStream.Create(FileName, fmCreate);
|
|
end;
|
|
end;
|
|
|
|
Assert(Stream <> nil);
|
|
Result := TBufferedStream.Create(Stream);
|
|
end;
|
|
|
|
procedure FileClose(Handle: TImagingHandle); cdecl;
|
|
var
|
|
Stream: TStream;
|
|
begin
|
|
Stream := TBufferedStream(Handle).Stream;
|
|
TBufferedStream(Handle).Free;
|
|
Stream.Free;
|
|
end;
|
|
|
|
function FileEof(Handle: TImagingHandle): Boolean; cdecl;
|
|
begin
|
|
Result := TBufferedStream(Handle).Position = TBufferedStream(Handle).Size;
|
|
end;
|
|
|
|
function FileSeek(Handle: TImagingHandle; Offset: Int64; Mode: TSeekMode): Int64; cdecl;
|
|
begin
|
|
Result := TBufferedStream(Handle).Seek(Offset, LongInt(Mode));
|
|
end;
|
|
|
|
function FileTell(Handle: TImagingHandle): Int64; cdecl;
|
|
begin
|
|
Result := TBufferedStream(Handle).Position;
|
|
end;
|
|
|
|
function FileRead(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): LongInt; cdecl;
|
|
begin
|
|
Result := TBufferedStream(Handle).Read(Buffer^, Count);
|
|
end;
|
|
|
|
function FileWrite(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): LongInt; cdecl;
|
|
begin
|
|
Result := TBufferedStream(Handle).Write(Buffer^, Count);
|
|
end;
|
|
|
|
{ Stream IO functions }
|
|
|
|
function StreamOpen(FileName: PChar; Mode: TOpenMode): TImagingHandle; cdecl;
|
|
begin
|
|
Result := FileName;
|
|
end;
|
|
|
|
procedure StreamClose(Handle: TImagingHandle); cdecl;
|
|
begin
|
|
end;
|
|
|
|
function StreamEof(Handle: TImagingHandle): Boolean; cdecl;
|
|
begin
|
|
Result := TStream(Handle).Position = TStream(Handle).Size;
|
|
end;
|
|
|
|
function StreamSeek(Handle: TImagingHandle; Offset: Int64; Mode: TSeekMode): Int64; cdecl;
|
|
begin
|
|
Result := TStream(Handle).Seek(Offset, Word(Mode));
|
|
end;
|
|
|
|
function StreamTell(Handle: TImagingHandle): Int64; cdecl;
|
|
begin
|
|
Result := TStream(Handle).Position;
|
|
end;
|
|
|
|
function StreamRead(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt):
|
|
LongInt; cdecl;
|
|
begin
|
|
Result := TStream(Handle).Read(Buffer^, Count);
|
|
end;
|
|
|
|
function StreamWrite(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): LongInt; cdecl;
|
|
begin
|
|
Result := TStream(Handle).Write(Buffer^, Count);
|
|
end;
|
|
|
|
{ Memory IO functions }
|
|
|
|
function MemoryOpen(FileName: PChar; Mode: TOpenMode): TImagingHandle; cdecl;
|
|
begin
|
|
Result := FileName;
|
|
end;
|
|
|
|
procedure MemoryClose(Handle: TImagingHandle); cdecl;
|
|
begin
|
|
end;
|
|
|
|
function MemoryEof(Handle: TImagingHandle): Boolean; cdecl;
|
|
begin
|
|
Result := PMemoryIORec(Handle).Position = PMemoryIORec(Handle).Size;
|
|
end;
|
|
|
|
function MemorySeek(Handle: TImagingHandle; Offset: Int64; Mode: TSeekMode): Int64; cdecl;
|
|
begin
|
|
Result := PMemoryIORec(Handle).Position;
|
|
case Mode of
|
|
smFromBeginning: Result := Offset;
|
|
smFromCurrent: Result := PMemoryIORec(Handle).Position + Offset;
|
|
smFromEnd: Result := PMemoryIORec(Handle).Size + Offset;
|
|
end;
|
|
//Result := ClampInt(Result, 0, PMemoryIORec(Handle).Size); don't do this - some file formats use it
|
|
PMemoryIORec(Handle).Position := Result;
|
|
end;
|
|
|
|
function MemoryTell(Handle: TImagingHandle): Int64; cdecl;
|
|
begin
|
|
Result := PMemoryIORec(Handle).Position;
|
|
end;
|
|
|
|
function MemoryRead(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt):
|
|
LongInt; cdecl;
|
|
var
|
|
Rec: PMemoryIORec;
|
|
begin
|
|
Rec := PMemoryIORec(Handle);
|
|
Result := Count;
|
|
if Rec.Position + Count > Rec.Size then
|
|
Result := Rec.Size - Rec.Position;
|
|
Move(Rec.Data[Rec.Position], Buffer^, Result);
|
|
Rec.Position := Rec.Position + Result;
|
|
end;
|
|
|
|
function MemoryWrite(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): LongInt; cdecl;
|
|
var
|
|
Rec: PMemoryIORec;
|
|
begin
|
|
Rec := PMemoryIORec(Handle);
|
|
Result := Count;
|
|
if Rec.Position + Count > Rec.Size then
|
|
Result := Rec.Size - Rec.Position;
|
|
Move(Buffer^, Rec.Data[Rec.Position], Result);
|
|
Rec.Position := Rec.Position + Result;
|
|
end;
|
|
|
|
{ Helper IO functions }
|
|
|
|
function GetInputSize(const IOFunctions: TIOFunctions; Handle: TImagingHandle): Int64;
|
|
var
|
|
OldPos: Int64;
|
|
begin
|
|
OldPos := IOFunctions.Tell(Handle);
|
|
IOFunctions.Seek(Handle, 0, smFromEnd);
|
|
Result := IOFunctions.Tell(Handle);
|
|
IOFunctions.Seek(Handle, OldPos, smFromBeginning);
|
|
end;
|
|
|
|
function PrepareMemIO(Data: Pointer; Size: LongInt): TMemoryIORec;
|
|
begin
|
|
Result.Data := Data;
|
|
Result.Position := 0;
|
|
Result.Size := Size;
|
|
end;
|
|
|
|
function ReadLine(const IOFunctions: TIOFunctions; Handle: TImagingHandle;
|
|
out Line: AnsiString; FailOnControlChars: Boolean): Boolean;
|
|
const
|
|
MaxLine = 1024;
|
|
var
|
|
EolPos, Pos: Integer;
|
|
C: AnsiChar;
|
|
EolReached: Boolean;
|
|
Endings: set of AnsiChar;
|
|
begin
|
|
Line := '';
|
|
Pos := 0;
|
|
EolPos := 0;
|
|
EolReached := False;
|
|
Endings := [#10, #13];
|
|
Result := True;
|
|
|
|
while not IOFunctions.Eof(Handle) do
|
|
begin
|
|
IOFunctions.Read(Handle, @C, SizeOf(C));
|
|
|
|
if FailOnControlChars and (Byte(C) < $20) then
|
|
begin
|
|
Break;
|
|
end;
|
|
|
|
if not (C in Endings) then
|
|
begin
|
|
if EolReached then
|
|
begin
|
|
IOFunctions.Seek(Handle, EolPos, smFromBeginning);
|
|
Exit;
|
|
end
|
|
else
|
|
begin
|
|
SetLength(Line, Length(Line) + 1);
|
|
Line[Length(Line)] := C;
|
|
end;
|
|
end
|
|
else if not EolReached then
|
|
begin
|
|
EolReached := True;
|
|
EolPos := IOFunctions.Tell(Handle);
|
|
end;
|
|
|
|
Inc(Pos);
|
|
if Pos >= MaxLine then
|
|
begin
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
Result := False;
|
|
IOFunctions.Seek(Handle, -Pos, smFromCurrent);
|
|
end;
|
|
|
|
procedure WriteLine(const IOFunctions: TIOFunctions; Handle: TImagingHandle;
|
|
const Line: AnsiString; const LineEnding: AnsiString);
|
|
var
|
|
ToWrite: AnsiString;
|
|
begin
|
|
ToWrite := Line + LineEnding;
|
|
IOFunctions.Write(Handle, @ToWrite[1], Length(ToWrite));
|
|
end;
|
|
|
|
{ TReadMemoryStream }
|
|
|
|
constructor TReadMemoryStream.Create(Data: Pointer; Size: Integer);
|
|
begin
|
|
SetPointer(Data, Size);
|
|
end;
|
|
|
|
class function TReadMemoryStream.CreateFromIOHandle(const IOFunctions: TIOFunctions; Handle: TImagingHandle): TReadMemoryStream;
|
|
var
|
|
Data: Pointer;
|
|
Size: Integer;
|
|
begin
|
|
Size := GetInputSize(IOFunctions, Handle);
|
|
GetMem(Data, Size);
|
|
IOFunctions.Read(Handle, Data, Size);
|
|
Result := TReadMemoryStream.Create(Data, Size);
|
|
end;
|
|
|
|
{ TImagingIOStream }
|
|
|
|
constructor TImagingIOStream.Create(const IOFunctions: TIOFunctions;
|
|
Handle: TImagingHandle);
|
|
begin
|
|
|
|
end;
|
|
|
|
initialization
|
|
OriginalFileIO.Open := FileOpen;
|
|
OriginalFileIO.Close := FileClose;
|
|
OriginalFileIO.Eof := FileEof;
|
|
OriginalFileIO.Seek := FileSeek;
|
|
OriginalFileIO.Tell := FileTell;
|
|
OriginalFileIO.Read := FileRead;
|
|
OriginalFileIO.Write := FileWrite;
|
|
|
|
StreamIO.Open := StreamOpen;
|
|
StreamIO.Close := StreamClose;
|
|
StreamIO.Eof := StreamEof;
|
|
StreamIO.Seek := StreamSeek;
|
|
StreamIO.Tell := StreamTell;
|
|
StreamIO.Read := StreamRead;
|
|
StreamIO.Write := StreamWrite;
|
|
|
|
MemoryIO.Open := MemoryOpen;
|
|
MemoryIO.Close := MemoryClose;
|
|
MemoryIO.Eof := MemoryEof;
|
|
MemoryIO.Seek := MemorySeek;
|
|
MemoryIO.Tell := MemoryTell;
|
|
MemoryIO.Read := MemoryRead;
|
|
MemoryIO.Write := MemoryWrite;
|
|
|
|
ResetFileIO;
|
|
|
|
{
|
|
File Notes:
|
|
|
|
-- TODOS ----------------------------------------------------
|
|
- nothing now
|
|
|
|
-- 0.77.3 ---------------------------------------------------
|
|
- IO functions now have 64bit sizes and offsets.
|
|
- Added helper classes TReadMemoryStream and TImagingIOStream.
|
|
|
|
-- 0.77.1 ---------------------------------------------------
|
|
- Updated IO Open functions according to changes in ImagingTypes.
|
|
- Added ReadLine and WriteLine functions.
|
|
|
|
-- 0.23 Changes/Bug Fixes -----------------------------------
|
|
- Added merge between buffered read-only and write-only file
|
|
stream adapters - TIFF saving needed both reading and writing.
|
|
- Fixed bug causing wrong value of TBufferedWriteFile.Size
|
|
(needed to add buffer pos to size).
|
|
|
|
-- 0.21 Changes/Bug Fixes -----------------------------------
|
|
- Removed TMemoryIORec.Written, use Position to get proper memory
|
|
position (Written didn't take Seeks into account).
|
|
- Added TBufferedReadFile and TBufferedWriteFile classes for
|
|
buffered file reading/writing. File IO functions now use these
|
|
classes resulting in performance increase mainly in file formats
|
|
that read/write many small chunks.
|
|
- Added fmShareDenyWrite to FileOpenRead. You can now read
|
|
files opened for reading by Imaging from other apps.
|
|
- Added GetInputSize and PrepareMemIO helper functions.
|
|
|
|
-- 0.19 Changes/Bug Fixes -----------------------------------
|
|
- changed behaviour of MemorySeek to act as TStream
|
|
based Seeks
|
|
}
|
|
end.
|
|
|