返回
{***************************************************************}
{*** FVision Unit Version1.0 ***}
{*** 蓝蚂蚁工作室 ***}
{***************************************************************}
{*** 通用图象文件单元 ***}
{***************************************************************}
{$F+,O+,X+,I-}
Unit FPicture;
Interface
Uses
Dos,FDac,FView,FTool,FXmsDrv,FPhoto,FEvent,
FControl,FMenu,FDialog;
Const
cmSetTime = 1450;
cmInsertBmp = 1451;
cmInsertPcx = 1452;
cmInsertSerial = 1453;
Type
PPicture=^TPicture;
TPicture=object(TPhoto)
Fp:File;
Constructor Init(X,Y:Integer;St:Word;Ds:Byte);
Procedure SetFileType(T:Byte);
Procedure LoadFromFile(Name:PathStr);virtual;
Function SaveToFile(Name:PathStr):Boolean;virtual;
Procedure LoadPcxFile(Name:PathStr);
Procedure ReadPcxLine(Len:Integer);
Function SavePcxFile(Name:PathStr):Boolean;
Procedure WritePcxLine(Len:Integer);
Procedure LoadBmpFile(Name:PathStr);
Procedure ReadBmpLine;
Function SaveBmpFile(Name:PathStr):Boolean;
Procedure WriteBmpLine;
Procedure LoadIcoFile(Name:PathStr);
Procedure LoadGifFile(Name:PathStr);
Function SaveGifFile(Name:PathStr):Boolean;
Procedure LoadFlcFile(Name:PathStr);
Procedure ReadFlcDacChunk(ChType:Word;Len:Word);
end;
MovieType=record
XmsHandle:Word;
Width,Height:Integer;
end;
TMovieType=array[1..1] of MovieType;
PMovie=^TMovie;
TMovie=object(TPicture)
MovieArr:^TMovieType;
Number,MaxNumber,Frame:Integer;
Constructor Init(R:TRect;MN:Integer);
Destructor Done;virtual;
Procedure Insert(Name:PathStr);
Procedure SetFrame(Frm:Integer);
end;
PMovieWin=^TMovieWin;
TMovieWin=object(TWindow)
Movie:PMovie;
Status:PStatusLine;
Timer:PTimer;
DltTime:Longint;
Constructor Init;
Procedure InitMenu;virtual;
Procedure InsertFile(Ext:string);
Procedure InsertSerial(Ext:string);
Procedure SetTimer;
Procedure HandleEvent(var Event:TEvent);virtual;
Procedure RunPopupMenu(var Event:TEvent;T:TPoint);
end;
Implementation
Const
WinDac:array[0..47] of Char=
#0#0#0#32#0#0#0#32#0#32#32#0#0#0#32#32#0#32#0#32#32#31#31#31+
#47#47#47#63#0#0#0#63#0#63#63#0#0#0#63#63#0#63#0#63#63#63#63#63;
Const
GifGlobalPaletteMask = $80;
GifGlobalColorResMask = $70;
GifGlobalColorSortMask = $08;
GifGlobalColorMask = $07;
GifLocalPaletteMask = $80;
GifLocalInterlaceMask = $40;
GifLocalColorSortMask = $20;
GifLocalColorMask = $07;
Type
PcxHeader=record
PcxID:Byte;
Version:Byte;
RleEncoding:Byte;
BitsPerPixel:Byte;
x1,y1:Integer;
x2,y2:Integer;
HRes:Integer;
VRes:Integer;
Palette:array[0..47] of Byte;
Reserved:Byte;
ColorPlanes:Byte;
BytesPerLine:Integer;
PaletteType:Integer;
UnUsed:array[0..57] of Byte;
end;
BmpHeader=record
BmpID:Word;
FileSize:Longint;
Reserved:Longint;
ImageOffset:Longint;
HeaderSize:Longint;
Width:Longint;
Height:Longint;
Planes:Word;
BitsPerPixel:Word;
EncodeType:Longint;
ImageSize:Longint;
XPixelPerMeter:Longint;
YPixelPerMeter:Longint;
ColorUsed:Longint;
ColorImportant:Longint;
end;
BmpRgb=record
Blue:Byte;
Green:Byte;
Red:Byte;
Reserved:Byte;
end;
IcoHeader=record
Reserved1:Word;
ResourceType:Word;
ResourceCount:Word;
Width:Byte;
Height:Byte;
ColorCount:Word;
Reserved2:Word;
Reserved3:Word;
DIBSize:Longint;
DIBOffset:Longint;
end;
GifHeader=record
GifID:array[0..5] of Char;
Width:Integer;
Height:Integer;
GlobalFlag:Byte;
BackGroundColor:Byte;
PixelAspectRatio:Byte;
end;
GifImgDesc=record
XStart,YStart:Integer;
Width:Integer;
Height:Integer;
LocalFlag:Byte;
end;
FlcHeader=record
Reserved1:array[0..7] of Byte;
Width:Integer;
Height:Integer;
Reserved2:array[0..115] of Byte;
end;
FlcFrameHeader=record
FrameSize:Longint;
FrameIdentifier:Word;
ChunkNumber:Word;
Reserved:array[0..7] of Byte;
end;
FlcChunkHeader=record
ChunkSize:Longint;
ChunkType:Word;
end;
Constructor TPicture.Init;
begin
Inherited Init;
MoveTo(X,Y);
Style:=St;
DacStyle:=Ds;
end;
Procedure TPicture.SetFileType;
begin
PictureType:=T;
end;
Procedure TPicture.LoadFromFile;
var
Dir: DirStr;
N: NameStr;
E: ExtStr;
begin
FillChar(PixelNum,1024,0);
Progress^.Loc:=0;
if (Style and phProgress)<>0 then Progress^.Paint;
FreePictureMem;
Dac.GetDac(PhotoDac);
FileName:=Name;
FSplit(Name, Dir, N, E);
UpcaseStr(E);
if E='.PCX' then
LoadPcxFile(Name)
else if E='.BMP' then
LoadBmpFile(Name)
else if E='.GIF' then
LoadGifFile(Name)
else if E='.ICO' then
LoadIcoFile(Name)
else
case PictureType of
ptPcx:LoadPcxFile(Name);
ptBmp:LoadBmpFile(Name);
ptGif:LoadGifFile(Name);
end;
if (XmsHandle<>0) and ((Style and phAdaptSize)<>0) then
begin
AssignRect(ViewRec,0,0,Width-1,Height-1);
SaveRec:=ViewRec;
end else
AssignRect(ViewRec,0,0,ViewRec.b.x-ViewRec.a.x,ViewRec.b.y-ViewRec.a.y);
if (Style and phProgress)<>0 then Progress^.Hide;
end;
Function TPicture.SaveToFile;
begin
SaveToFile:=False;
if Name='' then Exit;
case PictureType of
ptPcx:SaveToFile:=SavePcxFile(Name);
ptBmp:SaveToFile:=SaveBmpFile(Name);
ptGif:SaveToFile:=SaveGifFile(Name);
end;
FileName:=Name;
ModifyFlag:=False;
end;
Procedure TPicture.LoadPcxFile;
var
Result,TempAttr:Word;
PcxHead:PcxHeader;
TempDac:DacType;
DacMark:Byte;
i,j,k:Integer;
TempData:array[0..MaxPicLine-1] of Byte;
begin
if not IsValid then Exit;
PictureType:=ptPcx;
Assign(Fp,Name);
GetFAttr(Fp,TempAttr);
SetFAttr(Fp,Archive);
Reset(Fp,1);
if IOResult<>0 then Exit;
BlockRead(Fp,PcxHead,SizeOf(PcxHeader),Result);
if (PcxHead.PcxID<>10) or (PcxHead.RleEncoding<>1) then Exit;
if not ((PcxHead.Version in [0,2..5]) and
(PcxHead.BitsPerPixel in [1,2,4,8]) and
(PcxHead.ColorPlanes in [1,4])) then Exit;
Width:=PcxHead.x2-PcxHead.x1+1;
Height:=PcxHead.y2-PcxHead.y1+1;
BitsPerPixel:=PcxHead.BitsPerPixel*PcxHead.ColorPlanes;
case BitsPerPixel of
1,2,4:
for i:=0 to (1 shl BitsPerPixel-1) do
begin
PhotoDac[32*3+i*3+1]:=PcxHead.Palette[i*3] shr 2;
PhotoDac[32*3+i*3+2]:=PcxHead.Palette[i*3+1] shr 2;
PhotoDac[32*3+i*3+3]:=PcxHead.Palette[i*3+2] shr 2;
end;
8:begin
Seek(Fp,FileSize(Fp)-769);
BlockRead(Fp,DacMark,1,Result);
if DacMark=$0C then
begin
BlockRead(Fp,TempDac,Sizeof(DacType),Result);
for i:=1 to 256*3 do
TempDac[i]:=TempDac[i] shr 2;
end;
end;
end;
ConvertDac(TempDac);
if ((Style and phNoMalloc)=0)or(XmsHandle=0) then
MallocPictureMem(Width,Height);
Seek(Fp,SizeOf(PcxHeader));
if XmsHandle<>0 then
for i:=0 to Height-1 do
begin
ReadPcxLine(PcxHead.BytesPerLine*PcxHead.ColorPlanes);
FillChar(TempData,MaxPicLine,0);
for j:=0 to PcxHead.ColorPlanes-1 do
for k:=0 to Width-1 do
case BitsPerPixel of
1:TempData[k]:=DacIndex[(Line[k div 8] shr (7-(k mod 8))) and $01];
4:TempData[k]:=DacIndex[TempData[k] or (((Line[j*PcxHead.BytesPerLine+(k div 8)]
shr (7-(k mod 8))) and $01) shl j)];
8:TempData[k]:=DacIndex[Line[k]];
end;
MoveXms(Pointer(Longint(i)*Longint(Width)),XmsHandle,@TempData,0,Width+(Width mod 2));
ViewProgress(i/Height);
end;
Close(Fp);
SetFAttr(Fp,TempAttr);
end;
Procedure TPicture.ReadPcxLine;
var
TempData:array[0..MaxPicLine-1] of Byte;
ByteCount,RunCount,Dtl:Integer;
TempPos:LongInt;
Result:Word;
begin
Dtl:=0;
ByteCount:=0;
TempPos:=FilePos(Fp);
BlockRead(Fp,TempData,MaxPicLine,Result);
while ByteCount<Len do
begin
if TempData[Dtl]>=$C0 then
begin
RunCount:=TempData[Dtl] and $3F;
Inc(Dtl);
FillChar(Line[ByteCount],RunCount,TempData[Dtl]);
Inc(ByteCount,RunCount);
end else
begin
Line[ByteCount]:=TempData[Dtl];
Inc(ByteCount);
end;
Inc(Dtl);
end;
Seek(Fp,TempPos+Dtl);
end;
Function TPicture.SavePcxFile;
var
Result:Word;
PcxHead:PcxHeader;
DacMark:Byte;
i,j,k,TempLen:Integer;
TempData:array[0..MaxPicLine-1] of Byte;
begin
SavePcxFile:=False;
if XmsHandle=0 then Exit;
Assign(Fp,Name);
ReWrite(Fp,1);
if IOResult<>0 then Exit;
PcxHead.PcxID:=$0A;
PcxHead.Version:=5;
PcxHead.RleEncoding:=1;
PcxHead.x1:=SaveRec.a.x;
PcxHead.y1:=SaveRec.a.y;
PcxHead.x2:=SaveRec.b.x;
PcxHead.y2:=SaveRec.b.y;
PcxHead.HRes:=640;
PcxHead.VRes:=480;
PcxHead.Reserved:=0;
PcxHead.PaletteType:=2;
FillChar(PcxHead.UnUsed,58,0);
case BitsPerPixel of
1,2,4:PcxHead.ColorPlanes:=BitsPerPixel;
8:PcxHead.ColorPlanes:=1;
end;
PcxHead.BitsPerPixel:=BitsPerPixel div PcxHead.ColorPlanes;
PcxHead.BytesPerLine:=(PcxHead.BitsPerPixel*(SaveRec.b.x-SaveRec.a.x+1)-1) div 8+1;
if BitsPerPixel<8 then
for i:=0 to 15 do
begin
PcxHead.Palette[i*3]:=PhotoDac[32*3+i*3+1] shl 2;
PcxHead.Palette[i*3+1]:=PhotoDac[32*3+i*3+2] shl 2;
PcxHead.Palette[i*3+2]:=PhotoDac[32*3+i*3+3] shl 2;
end;
BlockWrite(Fp,PcxHead,SizeOf(PcxHeader),Result);
TempLen:=SaveRec.b.x-SaveRec.a.x+1;
if Odd(TempLen) then Inc(TempLen);
for i:=SaveRec.a.y to SaveRec.b.y do
begin
MoveXms(@TempData,0,Pointer(Longint(i)*Longint(Width)+SaveRec.a.x),XmsHandle,TempLen);
FillChar(Line,MaxPicLine,0);
if BitsPerPixel<8 then
for k:=0 to Width-1 do Dec(TempData[k],32);
for j:=0 to PcxHead.ColorPlanes-1 do
for k:=0 to Width-1 do
case BitsPerPixel of
1:Line[k div 8]:=Line[k div 8] or (TempData[k] shl (7-(k mod 8)));
4:Line[j*PcxHead.BytesPerLine+k div 8]:=Line[j*PcxHead.BytesPerLine+k div 8]
or (((TempData[k] shr j) and $01) shl (7-(k mod 8)));
8:Line[k]:=TempData[k];
end;
WritePcxLine(PcxHead.BytesPerLine*PcxHead.ColorPlanes);
end;
if BitsPerPixel=8 then
begin
DacMark:=$0C;
BlockWrite(Fp,DacMark,1,Result);
for i:=0 to 767 do
Line[i]:=PhotoDac[i+1] shl 2;
BlockWrite(Fp,Line,Sizeof(DacType),Result);
end;
Close(Fp);
SavePcxFile:=True;
end;
Procedure TPicture.WritePcxLine;
var
TempData:array[0..MaxPicLine-1] of Byte;
Data:Byte;
ByteCount,RunCount,Dtl:Integer;
Result:Word;
begin
ByteCount:=0;
Dtl:=0;
while ByteCount<Len do
begin
Data:=Line[ByteCount];
RunCount:=1;
Inc(ByteCount);
while (ByteCount<Len) and
(Line[ByteCount]=Data) and (RunCount<$3F) do
begin
Inc(RunCount);
Inc(ByteCount);
end;
if (RunCount>1)or(Data>=$C0) then
begin
TempData[Dtl]:=$C0 or RunCount;
TempData[Dtl+1]:=Data;
Inc(Dtl);
end else
TempData[Dtl]:=Data;
Inc(Dtl);
end;
BlockWrite(Fp,TempData,Dtl,Result);
end;
Procedure TPicture.LoadBmpFile;
var
Result,TempAttr:Word;
BmpHead:BmpHeader;
TempDac:DacType;
BmpDac:array[0..255] of BmpRgb;
i,TrueWid,ColorNum:Integer;
DataPos:Longint;
begin
if not IsValid then Exit;
PictureType:=ptBmp;
Assign(Fp,Name);
GetFAttr(Fp,TempAttr);
SetFAttr(Fp,Archive);
Reset(Fp,1);
if IOResult<>0 then Exit;
BlockRead(Fp,BmpHead,SizeOf(BmpHeader),Result);
if (BmpHead.BmpID<>$4D42) or (BmpHead.EncodeType<>0) or
(not (BmpHead.BitsPerPixel in [1,4,8])) then Exit;
Width:=BmpHead.Width;
Height:=BmpHead.Height;
BitsPerPixel:=BmpHead.BitsPerPixel;
TrueWid:=(Width*BitsPerPixel) div 8;
if (Width*BitsPerPixel) mod 32<>0 then
TrueWid:=TrueWid+4-TrueWid mod 4;
if BmpHead.ColorUsed=0 then
begin
if BitsPerPixel>8 then
ColorNum:=0
else
ColorNum:=1 shl BitsPerPixel;
end else
ColorNum:=BmpHead.ColorUsed;
if ColorNum>256 then ColorNum:=0;
BlockRead(Fp,BmpDac,ColorNum*SizeOf(BmpRgb),Result);
if ColorNum<256 then
for i:=0 to ColorNum-1 do
begin
PhotoDac[32*3+i*3+1]:=BmpDac[i].Red shr 2;
PhotoDac[32*3+i*3+2]:=BmpDac[i].Green shr 2;
PhotoDac[32*3+i*3+3]:=BmpDac[i].Blue shr 2;
end else
for i:=0 to 255 do
begin
TempDac[i*3+1]:=BmpDac[i].Red shr 2;
TempDac[i*3+2]:=BmpDac[i].Green shr 2;
TempDac[i*3+3]:=BmpDac[i].Blue shr 2;
end;
ConvertDac(TempDac);
if ((Style and phNoMalloc)=0)or(XmsHandle=0) then
MallocPictureMem(Width,Height);
DataPos:=Sizeof(BmpHeader)+ColorNum*SizeOf(BmpRgb);
for i:=0 to Height-1 do
begin
Seek(Fp,DataPos+Longint(Height-i-1)*Longint(TrueWid));
BlockRead(Fp,Line,TrueWid,Result);
ReadBmpLine;
MoveXms(Pointer(Longint(i)*Longint(Width)),XmsHandle,@Line,0,Width+Width mod 2);
ViewProgress(i/Height);
end;
Close(Fp);
SetFAttr(Fp,TempAttr);
end;
Procedure TPicture.ReadBmpLine;
var
TempData:array[0..MaxPicLine-1] of Byte;
i:Integer;
begin
System.Move(Line,TempData,MaxPicLine);
for i:=0 to Width-1 do
begin
case BitsPerPixel of
1:Line[i]:=DacIndex[(TempData[i div 8] shr (7-(i mod 8))) and $01];
4:Line[i]:=DacIndex[(TempData[i div 2] shr (4*((i+1) mod 2))) and $0F];
8:Line[i]:=DacIndex[TempData[i]];
end;
end;
end;
Function TPicture.SaveBmpFile;
var
Result:Word;
BmpHead:BmpHeader;
BmpDac:array[0..255] of BmpRgb;
i,TrueWid,ColorNum,TempWid,TempHig:Integer;
begin
SaveBmpFile:=False;
if XmsHandle=0 then Exit;
Assign(Fp,Name);
ReWrite(Fp,1);
if IOResult<>0 then Exit;
ColorNum:=1 shl BitsPerPixel;
TempWid:=SaveRec.b.x-SaveRec.a.x+1;
TempHig:=SaveRec.b.y-SaveRec.a.y+1;
TrueWid:=TempWid*BitsPerPixel div 8;
if (TempWid*BitsPerPixel) mod 32<>0 then
TrueWid:=TrueWid+4-TrueWid mod 4;
BmpHead.BmpID:=$4D42;
BmpHead.FileSize:=54+ColorNum*4+Longint(TrueWid)*Longint(TempHig);
BmpHead.Reserved:=0;
BmpHead.ImageOffset:=54+ColorNum*4;
BmpHead.HeaderSize:=40;
BmpHead.Width:=TempWid;
BmpHead.Height:=TempHig;
BmpHead.Planes:=1;
BmpHead.BitsPerPixel:=BitsPerPixel;
BmpHead.EncodeType:=0;
BmpHead.ImageSize:=Longint(TrueWid)*Longint(TempHig);
BmpHead.XPixelPerMeter:=640;
BmpHead.YPixelPerMeter:=480;
BmpHead.ColorUsed:=0;
BmpHead.ColorImportant:=0;
BlockWrite(Fp,BmpHead,SizeOf(BmpHeader),Result);
if ColorNum<256 then
for i:=0 to ColorNum-1 do
begin
BmpDac[i].Red:=PhotoDac[32*3+i*3+1] shl 2;
BmpDac[i].Green:=PhotoDac[32*3+i*3+2] shl 2;
BmpDac[i].Blue:=PhotoDac[32*3+i*3+3] shl 2;
BmpDac[i].Reserved:=0;
end else
for i:=0 to 255 do
begin
BmpDac[i].Red:=PhotoDac[i*3+1] shl 2;
BmpDac[i].Green:=PhotoDac[i*3+2] shl 2;
BmpDac[i].Blue:=PhotoDac[i*3+3] shl 2;
BmpDac[i].Reserved:=0;
end;
BlockWrite(Fp,BmpDac,ColorNum*SizeOf(BmpRgb),Result);
for i:=SaveRec.b.y downto SaveRec.a.y do
begin
MoveXms(@Line,0,Pointer(Longint(i)*Longint(Width)+SaveRec.a.x),
XmsHandle,TempWid+(TempWid mod 2));
WriteBmpLine;
BlockWrite(Fp,Line,TrueWid,Result);
end;
Close(Fp);
SaveBmpFile:=True;
end;
Procedure TPicture.WriteBmpLine;
var
TempData:array[0..MaxPicLine-1] of Byte;
i:Integer;
begin
System.Move(Line,TempData,MaxPicLine);
FillChar(Line,MaxPicLine,0);
for i:=0 to SaveRec.b.x-SaveRec.a.x do
begin
case BitsPerPixel of
1:Line[i div 8]:=Line[i div 8] or ((TempData[i]-32) shl (7-(i mod 8)));
4:Line[i div 2]:=Line[i div 2] or ((TempData[i]-32) shl (4*((i+1) mod 2)));
8:Line[i]:=TempData[i];
end;
end;
end;
Procedure TPicture.LoadIcoFile;
var
Result,TempAttr:Word;
IcoHead:IcoHeader;
i,j,TrueWid,IcoSize:Integer;
begin
if not IsValid then Exit;
PictureType:=ptIco;
Assign(Fp,Name);
GetFAttr(Fp,TempAttr);
SetFAttr(Fp,Archive);
Reset(Fp,1);
if IOResult<>0 then Exit;
BlockRead(Fp,IcoHead,SizeOf(IcoHeader),Result);
Width:=IcoHead.Width*3;
Height:=IcoHead.Height;
BitsPerPixel:=4;
if IcoHead.ColorCount<16 then Exit;
TrueWid:=(IcoHead.Width*BitsPerPixel) div 8;
IcoSize:=(IcoHead.Width*BitsPerPixel*Height) div 8;
System.Move(WinDac,PhotoDac[32*3+1],48);
ConvertDac(PhotoDac);
if ((Style and phNoMalloc)=0)or(XmsHandle=0) then
MallocPictureMem(Width,Height);
for i:=0 to Height-1 do
begin
Seek(Fp,126+Longint(Height-i-1)*Longint(TrueWid));
BlockRead(Fp,Line[300],TrueWid,Result);
Seek(Fp,126+IcoSize+Longint(Height-i-1)*Longint(TrueWid) div 4);
BlockRead(Fp,Line[400],TrueWid div 4,Result);
for j:=0 to IcoHead.Width-1 do
begin
if not Odd(j) then
Line[j+IcoHead.Width]:=DacIndex[Line[300+j div 2] shr 4]
else
Line[j+IcoHead.Width]:=DacIndex[Line[300+j div 2] and $0F];
Line[j+2*IcoHead.Width]:=0;
if ((Line[400+j div 8] shr (7-(j mod 8))) and $01)<>0 then
Line[j+2*IcoHead.Width]:=$FF;
Line[j]:=Line[j+2*IcoHead.Width] and 7;
Line[j]:=Line[j] xor Line[j+IcoHead.Width];
end;
MoveXms(Pointer(Longint(i)*Longint(Width)),XmsHandle,@Line,0,Width+Width mod 2);
ViewProgress(i/Height);
end;
Close(Fp);
SetFAttr(Fp,TempAttr);
end;
Procedure TPicture.LoadGifFile;
var
Result,TempAttr:Word;
GifHead:GifHeader;
GifImg:GifImgDesc;
GifDac:DacType;
BlockSign:Char;
CurrentX,CurrentY:Integer;
ReadFlag,EndFlag:Boolean;
BlockSize:Byte;
ImageBlock:array[0..260] of Byte;
i:Integer;
Function GifReadCode:Byte;
begin
if ReadFlag and not EndFlag then
begin
BlockRead(Fp,BlockSize,1,Result);
if BlockSize=0 then
begin
ReadFlag:=False;
EndFlag:=True;
end else
begin
BlockRead(Fp,ImageBlock[3],BlockSize,Result);
ReadFlag:=False;
end;
end;
{ ByteOffset:=BitOffset shr 3;}
end;
Procedure GifWritePixel(Color:Byte);
var
TempWid:Longint;
begin
if CurrentY>=GifImg.Height then Exit;
Line[CurrentX]:=Color;
Inc(CurrentX);
if CurrentX>=GifImg.Width then
begin
CurrentX:=0;
TempWid:=GifImg.Width;
if Odd(TempWid) then
begin
Inc(TempWid);
MoveXms(@Line,0,Pointer(Longint(CurrentY)*Longint(Width)+GifImg.XStart),XmsHandle,TempWid);
end;
MoveXms(Pointer(Longint(CurrentY)*Longint(Width)+GifImg.XStart),XmsHandle,@Line,0,TempWid);
Inc(CurrentY);
end;
end;
Procedure GifReadImage;
var
Colors:Integer;
InitCodeSize,CodeSize,Code,MaxCode,ClearCode,EOFCode,
CurCode,OldCode,InCode,FirstFree,FreeCode,
FinChar,BitMask,ReadMask,OutCount:Byte;
begin
BlockRead(Fp,GifImg,Sizeof(GifImgDesc),Result);
if (GifImg.LocalFlag and GifLocalPaletteMask)<>0 then
begin
Colors:=1 shl (GifImg.LocalFlag and GifLocalColorMask)+1;
BlockRead(Fp,PhotoDac,3*Colors,Result)
end else if (GifHead.GlobalFlag and GifGlobalPaletteMask)<>0 then
begin
Colors:=1 shl (GifHead.GlobalFlag and GifGlobalColorMask)+1;
System.Move(GifDac,PhotoDac,3*Colors);
end;
CurrentX:=0;
CurrentY:=0;
ReadFlag:=True;
EndFlag:=False;
BitMask:=Colors-1;
BlockRead(Fp,CodeSize,1,Result);
ClearCode:=1 shl CodeSize;
EOFCode:=ClearCode+1;
FreeCode:=ClearCode+2;
FirstFree:=FreeCode;
Inc(CodeSize);
InitCodeSize:=CodeSize;
MaxCode:=1 shl CodeSize;
ReadMask:=MaxCode-1;
BlockRead(Fp,Line,MaxPicLine,Result);
end;
Procedure GifReadExtension;
var
ExtLabel,ExtSize:Byte;
begin
BlockRead(Fp,ExtLabel,1,Result);
case ExtLabel of
$FE:while ExtLabel<>0 do
BlockRead(Fp,ExtLabel,1,Result);
$F9,$01,$FF:
begin
BlockRead(Fp,ExtSize,1,Result);
BlockRead(Fp,Line,ExtSize,Result);
while ExtLabel<>0 do
BlockRead(Fp,ExtLabel,1,Result);
end;
end;
end;
begin
if not IsValid then Exit;
PictureType:=ptGif;
Assign(Fp,Name);
GetFAttr(Fp,TempAttr);
SetFAttr(Fp,Archive);
Reset(Fp,1);
if IOResult<>0 then Exit;
BlockRead(Fp,GifHead,SizeOf(GifHeader),Result);
if Pos('GIF',GifHead.GifID)=0 then Exit;
Width:=GifHead.Width;
Height:=GifHead.Height;
BitsPerPixel:=(GifHead.GlobalFlag and GifGlobalColorResMask) shr 4+1;
if ((Style and phNoMalloc)=0)or(XmsHandle=0) then
MallocPictureMem(Width,Height);
if (GifHead.GlobalFlag and GifGlobalPaletteMask)<>0 then
BlockRead(Fp,GifDac,3*(1 shl (GifHead.GlobalFlag and GifGlobalColorMask)+1),Result);
BlockRead(Fp,BlockSign,1,Result);
while BlockSign<>';' do
begin
case BlockSign of
',':GifReadImage;
'!':GifReadExtension;
else Exit;
end;
BlockRead(Fp,BlockSign,1,Result);
end;
Close(Fp);
SetFAttr(Fp,TempAttr);
end;
Function TPicture.SaveGifFile;
var
Result:Word;
GifHead:GifHeader;
i:Integer;
begin
SaveGifFile:=False;
if XmsHandle=0 then Exit;
Assign(Fp,Name);
ReWrite(Fp,1);
if IOResult<>0 then Exit;
Close(Fp);
SaveGifFile:=True;
end;
Procedure TPicture.LoadFlcFile;
var
Result,TempAttr:Word;
FlcHead:FlcHeader;
FrameHead:FlcFrameHeader;
i:Integer;
begin
if not IsValid then Exit;
PictureType:=ptFlc;
Assign(Fp,Name);
GetFAttr(Fp,TempAttr);
SetFAttr(Fp,Archive);
Reset(Fp,1);
if IOResult<>0 then Exit;
BlockRead(Fp,FlcHead,SizeOf(FlcHeader),Result);
Width:=FlcHead.Width;
Height:=FlcHead.Height;
BitsPerPixel:=8;
if ((Style and phNoMalloc)=0)or(XmsHandle=0) then
MallocPictureMem(Width,Height);
while not Eof(Fp) do
begin
BlockRead(Fp,FrameHead,SizeOf(FlcFrameHeader),Result);
if FrameHead.FrameIdentifier=$F100 then
begin
Seek(Fp,FilePos(Fp)+FrameHead.FrameSize-SizeOf(FlcFrameHeader));
BlockRead(Fp,FrameHead,SizeOf(FlcFrameHeader),Result);
end;
end;
Close(Fp);
SetFAttr(Fp,TempAttr);
end;
Procedure TPicture.ReadFlcDacChunk;
var
TempDac:DacType;
i,j,Color,P,Nb,Nc:Integer;
Jump,Dlt:Byte;
Result:Word;
begin
if ChType=4 then Dlt:=2 else Dlt:=0;
System.Move(PhotoDac,TempDac,768);
BlockRead(Fp,Line,Len,Result);
Color:=0;
Nb:=Integer(Line[0]);
P:=2;
for i:=0 to Nb-1 do
begin
Jump:=Line[P];
Inc(P);
Inc(Color,Jump);
Nc:=Line[P];
Inc(P);
if Nc=0 then Nc:=256;
for j:=0 to 3*Nc-1 do Line[P+j]:=Line[P+j] shr Dlt;
System.Move(Line[P],TempDac[Color*3],Nc*3);
Inc(P,Nc*3);
Inc(Color,Nc);
end;
ConvertDac(TempDac);
end;
Constructor TMovie.Init;
begin
Inherited Init(0,0,phProgress,phAdaptDac);
SetViewRec(R);
MaxNumber:=MN;
GetMem(MovieArr,SizeOf(MovieType)*MaxNumber);
Number:=0;
Frame:=0;
end;
Destructor TMovie.Done;
var
i:Integer;
begin
for i:=1 to Number do
if MovieArr^[i].XmsHandle<>0 then
FreeXms(MovieArr^[i].XmsHandle);
FreeMem(MovieArr,SizeOf(MovieType)*MaxNumber);
XmsHandle:=0;
Inherited Done;
end;
Procedure TMovie.Insert;
begin
if Number>=MaxNumber then Exit;
if Number>0 then
begin
DacStyle:=phOtherDac;
XmsHandle:=0;
end;
LoadFromFile(Name);
Inc(Number);
MovieArr^[Number].XmsHandle:=XmsHandle;
MovieArr^[Number].Width:=Width;
MovieArr^[Number].Height:=Height;
end;
Procedure TMovie.SetFrame;
begin
if Frm>Number-1 then Exit;
Frame:=Frm;
XmsHandle:=MovieArr^[Frame+1].XmsHandle;
Width:=MovieArr^[Frame+1].Width;
Height:=MovieArr^[Frame+1].Height;
end;
Constructor TMovieWin.Init;
var
R:TRect;
begin
AssignRect(R,0,0,400,280);
Inherited Init(R,'动画编辑器',True);
Option:=Option or opResize;
AssignRect(R,10,50,14+300,54+200);
Insert(New(PShape,Init(gcBroad+gcHideMouse,R,0,0,$07,0,'')));
AssignRect(R,0,0,300,200);
Movie:=New(PMovie,Init(R,100));
Movie^.MoveTo(12,52);
Insert(Movie);
AssignRect(R,5,256,380,278);
Status:=New(PStatusLine,Init(R,0,#0));
Insert(Status);
Timer:=New(PTimer,Init(10));
Timer^.StopTimer;
Insert(Timer);
DltTime:=10;
Center;
end;
Procedure TMovieWin.InitMenu;
var
T:TRect;
begin
Inherited InitMenu;
AssignRect(T,5,27,Broad.b.x-5,44);
Insert(New(PMainMenu,Init(T,False,
NewSubMenu('文件~F~',kbAltF,New(PMenu,Init(
NewMenuItem('播放',kbNoKey,cmPlay,nil,
NewMenuItem('停止',kbNoKey,cmStop,nil,
NewMenuItem('插入 ~Ins~',kbIns,cmInsert,nil,
NewMenuItem('',0,0,nil,
NewMenuItem('关闭 ~Alt+F3~',kbAltF3,cmCloseWin,nil,nil))))))),
NewSubMenu('帮助~H~',kbAltH,New(PMenu,Init(
NewMenuItem('设置延迟时间',kbNoKey,cmSetTime,nil,
NewMenuItem('关于',kbNoKey,cmAbout,nil,nil)))),nil)))));
end;
Procedure TMovieWin.InsertFile;
var
Name:PathStr;
begin
if not OpenFile(Name,'打开文件',Ext) then Exit;
ChangePath(Name);
Movie^.Insert(Name);
Movie^.SetFrame(Movie^.Number-1);
Movie^.Paint;
Status^.Modify('Frame:'+IntStr(Movie^.Number)+#0+FName(Name)+#0);
end;
Procedure TMovieWin.InsertSerial;
var
Name,TempStr:PathStr;
i,Dot,Temp:Integer;
begin
if not OpenFile(Name,'打开文件',Ext) then Exit;
ChangePath(Name);
Movie^.Insert(Name);
Movie^.SetFrame(Movie^.Number-1);
Movie^.Paint;
Status^.Modify('Frame:'+IntStr(Movie^.Number)+#0+FName(Name)+#0);
Dot:=Pos('.',Name);
for i:=0 to 30 do
begin
Temp:=StrsInt(Copy(Name,Dot-3,3))+1;
TempStr:=Copy(Name,1,Dot-4)+Int_Str(Temp,3)+Copy(Name,Dot,4);
Name:=TempStr;
if Exist_Fi(Name) then
begin
Movie^.Insert(Name);
Movie^.SetFrame(Movie^.Number-1);
Movie^.Paint;
Status^.Modify('Frame:'+IntStr(Movie^.Number)+#0+FName(Name)+#0);
end;
end;
end;
Procedure TMovieWin.SetTimer;
var
R:TRect;
P:PWindow;
begin
AssignRect(R, 0, 0, 260, 100);
P:=New(PWindow,Init(R,'设置延迟时间',True));
P^.Insert(New(PStaticText,Init(stNormal,20,45,'Time:',4)));
P^.Insert(New(PDigInput,Init(65,45,@DltTime,12,ipBroad+ipDigital,dtLongint)));
P^.Insert(New(PButton,Init(180, 40,240, 60,'确定',kbAltO,cmOk)));
P^.Insert(New(PButton,Init(180, 70,240, 90,'放弃',kbAltC,cmCancel)));
P^.Next;
P^.Next;
P^.Center;
RunView(P,Event);
if Event.Command=cmOk then Timer^.SetTime(DltTime);
end;
Procedure TMovieWin.HandleEvent;
Label Start;
begin
Start:
Inherited HandleEvent(Event);
case Event.What of
evMouseDown:if IsIn(Event.Where,Broad) and
(Event.Buttons=mbRightButton) then
begin
RunPopupMenu(Event,Event.Where);
goto Start;
end;
evCommand:case Event.Command of
cmSetTime:SetTimer;
cmInsert:InsertFile('*.*');
cmInsertBmp:InsertFile('*.BMP');
cmInsertPcx:InsertFile('*.PCX');
cmInsertSerial:InsertSerial('*.*');
cmPlay:Timer^.Reset;
cmStop:Timer^.StopTimer;
cmTimer:if (Event.InfoPtr=Timer)and(Movie^.Number>0) then
begin
Movie^.SetFrame((Movie^.Frame+1) mod Movie^.Number);
Movie^.Paint;
Status^.Modify('Frame:'+IntStr(Movie^.Frame+1)+#0);
Timer^.Reset;
end else Exit;
else Exit;
end;
else Exit;
end;
ClearEvent(Event);
end;
Procedure TMovieWin.RunPopupMenu;
var
PopMenu:PMenu;
begin
PopMenu:=New(PMenu,Init(
NewMenuItem('插入BMP',0,cmInsertBmp,nil,
NewMenuItem('插入PCX',0,cmInsertPcx,nil,
NewMenuItem('插入序列',0,cmInsertSerial,nil,
NewMenuItem('删除 ~Del~',kbDel,cmDelete,nil,nil))))));
PopMenu^.Owner:=@Self;
PopMenu^.MoveTo(T.X,T.Y);
PopMenu^.Run(Event);
Dispose(PopMenu);
end;
end.