⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htmlgif1.pas

📁 查看html文件的控件
💻 PAS
📖 第 1 页 / 共 5 页
字号:

// some things, though, will always be needed

new(fSignature);
if (fSignature = nil) then OutOfMemoryError;
fSignature^.rSignature := '------';

new(fScreenDescriptor);
if (fScreenDescriptor = nil) then OutOfMemoryError;
fillchar(fScreenDescriptor^, sizeof(TGifScreenDescriptor), 0);

fImageDescriptorList := TList.Create;
fColorTableList      := TList.Create;
fPaletteList         := TList.Create;

end;


destructor TGif.Destroy;
begin

// clean up most of the data

FreeImage;

// and then the left-overs

dispose(fSignature);
dispose(fScreenDescriptor);

fImageDescriptorList.Free;
fColorTableList.Free;
fPaletteList.Free;

// and the ancestor

inherited;
end;

{ ---------------------------------------------------------------------------- }
{ release all memory used to store image data }

procedure TGif.FreeImage;
var
    i:    integer;
    id:     PGifImageDescriptor;
    ct:     PGifColorTable;
begin

// temp input/output stream

if (fIOStream <> nil) then fIOStream.Free;
fIOStream := nil;

// temp encoded data

if (fDataStream <> nil) then fDataStream.Free;
fDataStream:= nil;

// temp list of image extensions

if (fExtension <> nil) then FreeExtensionList(fExtension);
fExtension := nil;

// signature record stays, but is cleared

if (fSignature = nil) then new(fSignature);
fSignature^.rSignature := '------';

// ditto the screen descriptor

if (fScreenDescriptor = nil) then new(fScreenDescriptor);
fillchar(fScreenDescriptor^, sizeof(TGifScreenDescriptor), 0);

// delete all items from image list, but leave the list

if (fImageDescriptorList = nil) then fImageDescriptorList := TList.Create;
for i := 0 to (fImageDescriptorList.Count - 1) do
    begin
    id := fImageDescriptorList.Items[i];
    if (id <> nil) then
        begin
        if (id^.rExtensionList <> nil) then FreeExtensionList(id^.rExtensionList);
        if (id^.rPixelList     <> nil) then freemem(id^.rPixelList);
        if (id^.rBitmap        <> nil) then id^.rBitmap.Free;

        dispose(id);
        end;
    end;
fImageDescriptorList.Clear;

// release color tables, but keep the list

if (fColorTableList = nil) then fColorTableList := TList.Create;
for i := 0 to (fColorTableList.Count - 1) do
    begin
    ct := fColorTableList.Items[i];
    if (ct <> nil) then dispose(ct);
    end;
fColorTableList.Clear;

// once again, keep the palette list object, but not the data

if (fPaletteList = nil) then fPaletteList := TList.Create;
fPaletteList.Clear;

// don't need the zip/unzip data block

if (fZipData <> nil) then dispose(fZipData);
fZipData := nil;
end;


{ ---------------------------------------------------------------------------- }
{ READ and WRITE A GIF ------------------------------------------------------- }

{ ---------------------------------------------------------------------------- }
{ read a GIF definition from a stream }

procedure TGif.LoadFromStream(Source: TStream);
var
    done:   boolean;
    b:      byte;
begin

// release old image that may be here ...

FreeImage;

// no error yet

GIF_ErrorCode := 0;
GIF_ErrorString := '';

// make a local copy of the source data
// memory streams are faster and easier to manipulate than file streams

fIOStream := TMemoryStream.Create;
Source.Position := 0;
fIOStream.LoadFromStream(Source);

// local temp vars

fDataStream := TMemoryStream.Create;        // data to be un-zipped
fExtension  := nil;                         // extensions to an image


// read the signature GIF87A or GIF89A

ReadSignature;

// read the logical screen descriptor

ReadScreenDescriptor;

// read extensions and image data until end of file

done := false;
while (not done) do
  try  {LDB}
    if (fIOStream.Position >= fIOStream.Size) then
      //GIF_Error(9);    {LDB} 
      b := 0             {LDB}

    else fIOStream.Read(b, 1);    {LDB}         // image separator

    if (b = 0) then                             // just skip this?
        begin
        b := 0;
        Done := True;   {LDB}
        end
    else if (b = kGifTerminator) then           // got it all
        begin
        done := true;
        end
    else if (b = kGifImageSeparator) then       // next bitmap
        begin
        ReadImageDescriptor;
        end
    else if (b = kGifExtensionSeparator) then   // special operations
        begin
        ReadExtension(Done);
        end
    else                                        // unknown
        begin
        GIF_Error(4);
        end;
  except  {LDB}  
    if GetImageCount > 0 then
      Done := True     {use what images we have}
    else
      Raise;
    end;

// must have an image

if (fImageDescriptorList.Count = 0) then GIF_Error(18);  

// no longer need the source data in memory

fIOStream.Free;
fDataStream.Free;
FreeExtensionList(fExtension);

fIOStream   := nil;
fDataStream := nil;
fExtension  := nil;
end;


function TGif.GetHeight: integer;
begin
GetHeight := fScreenDescriptor^.rHeight;
end;

function TGif.GetWidth: integer;
begin
GetWidth := fScreenDescriptor^.rWidth;
end;

{ ---------------------------------------------------------------------------- }
{ TRANSPARENT is assument to be the same for all images; i.e., if the first }
{ image is transparent, they they are all transparent }
{ if SetTransparent(TRUE) then set default color index for transparent color }
{ this can be changed with TransparentColor after this call }

{LDB  changed so that if any images are transparent, Transparent returns True}
function TGif.GetTransparent: boolean;
var
    b:      boolean;
    gx:     PGifExtensionGraphic;
    i:      integer;
begin
b := false;
for I := 0 to (fImageDescriptorList.Count - 1) do
  begin
  gx := FindGraphicExtension(I);
  if (gx <> nil) then
    b := gx^.rTransparentValid or b;
  end;

GetTransparent := b;
end;

{ ---------------------------------------------------------------------------- }
{ PROCEDURES TO READ A GIF FILE ---------------------------------------------- }

{ ---------------------------------------------------------------------------- }
{ read the GIF signature from the source stream }
{ this assumes the memory stream position is correct }
{ the signature is always 6 bytes, and must be either GIF87A or GIF89A }

procedure TGif.ReadSignature;
var
    s:      string;
begin
with fSignature^ do
    begin
    fIOStream.Read(rSignature, 6);
    s := rSignature;
    s := UpperCase(s);
    if ((s <> 'GIF87A') and (s <> 'GIF89A')) then GIF_Error(1);
    end;
end;


{ ---------------------------------------------------------------------------- }
{ read the GIF logical screen descriptor from the source stream }
{ this assumes the memory stream position is correct }
{ this always follows the GIF signature }

procedure TGif.ReadScreenDescriptor;
var
    i,n:    integer;
begin
with fScreenDescriptor^ do
    begin
    ReadSourceInteger(2, rWidth);                   // logical screen width
    ReadSourceInteger(2, rHeight);                  // logical screen height

    ReadSourceInteger(1, n);                        // packed bit fields
    rGlobalColorValid := ((n and $80) <> 0);
    rColorResolution  := ((n shr 4) and $07) + 1;
    rSorted           := ((n and $08) <> 0);

    i := (n and $07);
    if      (i = 0) then rGlobalColorSize := 2
    else if (i = 1) then rGlobalColorSize := 4
    else if (i = 2) then rGlobalColorSize := 8
    else if (i = 3) then rGlobalColorSize := 16
    else if (i = 4) then rGlobalColorSize := 32
    else if (i = 5) then rGlobalColorSize := 64
    else if (i = 6) then rGlobalColorSize := 128
    else if (i = 7) then rGlobalColorSize := 256
    else                 rGlobalColorSize := 256;


    ReadSourceInteger(1, rBackgroundIndex);         // background color
    ReadSourceInteger(1, rAspectRatio);             // pixel aspect ratio

// read the global color table from the source stream
// this assumes the memory stream position is correct
// the global color table is only valid if a flag is set in the logical
// screen descriptor.  if the flag is set, the global color table will
// immediately follow the logical screen descriptor

    rGlobalColorTable := -1;
    if (rGlobalColorValid) then                     // a global color table?
        ReadColorTable(rGlobalColorSize, rGlobalColorTable)
    end;
end;

{ ---------------------------------------------------------------------------- }
{ read in any type of color table }
{ number of RGB entries is given by SIZE, and save the index into the }
{ master color table list in TABLE }
{ if SIZE is <= 0, then there is no table, and the TABLE becomes -1 }

procedure TGif.ReadColorTable(Size: integer; var Table: integer);
var
    i,n:        integer;
    r,g,b:      byte;
    ct:         PGifColorTable;
begin
Table := -1;                            // assume no table
if (Size > 0) then                      // OK, a table does exist
    begin
    new(ct);                            // make a anew color table
    if (ct = nil) then OutOfMemoryError;
    n := fColorTableList.Add(ct);       // save it in master list
    Table := n;                         // save index for a valid table

    ct^.rSize := Size;

    for i := 0 to (ct^.rSize-1) do      // read a triplet for each TColor
        begin
        fIOStream.Read(r, 1);             // red
        fIOStream.Read(g, 1);             // green
        fIOStream.Read(b, 1);             // blue

        ct^.rColors[i] := r or (g shl 8) or (b shl 16);  
        end;

// make sure we store palette handle in same index slot as the color table

    while (fPaletteList.Count < fColorTableList.Count) do fPaletteList.Add(nil);
    fPaletteList.Items[Table] := Nil;
    end;
end;

{ ---------------------------------------------------------------------------- }
{ read the next image descriptor }
{ the source stream position should be immediately following the }
{ special code image separator }
{ note: this routine only reads in the raw data; the LZW de-compression }
{ occurs later, after all the data has been read }
{ this probably makes for a bigger data chunk, but it doesn't much effect }
{ the speed, and it is certainly a more modular approach and is much easier }
{ to understand the mechanics later }

procedure TGif.ReadImageDescriptor;
var
    i,n:    integer;
    ix:     integer;
    id:     PGifImageDescriptor;
    db:     TGifDataBlock;
begin

// make a new image desctiptor record and add this record to main list

new(id);
if (id = nil) then OutOfMemoryError;
if (fImageDescriptorList = nil) then fImageDescriptorList := TList.Create;
ix := fImageDescriptorList.Add(id);
id^.rIndex := ix;

// initialize data

fillchar(id^, sizeof(TGifImageDescriptor), 0);

// init the sotrage for compressed data

fDataStream.Clear;

// if extensions were read in earlier, save that list
// for this image descriptor
// if no extensions were read in, then we don't need this list at all

if (fExtension <> nil) then
    begin
    id^.rExtensionList := fExtension;
    fExtension := nil;
    end;

// shortcut to the record fields

with id^ do
    begin

// read the basic descriptor record

    ReadSourceInteger(2, rLeft);            // left position

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -