返回
{***************************************************************}
{*** FVision Unit Version1.0 ***}
{*** 蓝蚂蚁工作室 ***}
{***************************************************************}
{*** PCX图形文件支持单元 ***}
{***************************************************************}
{$F+,O+,X+,S-,D-}
Unit FPcx;
Interface
Uses
Dos,FDac,FView,SvgaDrv,FWrite,FTool;
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;
PPcx=^TPcx;
TPcx=object(TView)
Fp:file;
Result:Word;
FileName:PathStr;
PcxHead:PcxHeader;
PcxDac:DacType;
Line,Data:array[0..2047] of Byte;
Height,Width,TrueWid:Integer;
ColorNum:Integer;
VideoMode256,VideoMode16:Word;
TempAttr:Word;
Center,ShowInfo,ReSetVideo,ReSetDac,BackGround:Boolean;
Start:LongInt;
InfoStr:String;
constructor Init(AFileName:string;Intx,Inty:Integer);
destructor Done;virtual;
procedure SetOption(V256,V16:Word;Cen,ShIn,RV,RD,BC:Boolean);
procedure SetPosition(x,y:Integer);
procedure GetInfo(var Wid,Hig,Col:Integer);
procedure ProHeader;
procedure OpenFile;
procedure Draw;virtual;
procedure PutToLine(var Arr;x,y:Integer);
procedure Creat(x,y:Integer);
end;
Implementation
constructor TPcx.Init;
begin
Inherited Init;
FileName:=AFileName;
Origin.x:=Intx;
Origin.y:=Inty;
Start:=0;
SetOption($101,$12,False,False,False,False,False);
TempAttr:=Archive;
end;
destructor TPcx.Done;
begin
SetFAttr(Fp,TempAttr);
{$i-}Close(Fp);{$i+}
end;
procedure TPcx.SetOption;
begin
VideoMode256:=V256;
VideoMode16:=V16;
Center:=Cen;
ShowInfo:=ShIn;
ReSetVideo:=RV;
ReSetDac:=RD;
BackGround:=BC;
end;
procedure TPcx.SetPosition;
begin
Origin.x:=x;
Origin.y:=y;
end;
procedure TPcx.GetInfo;
begin
Wid:=Width+1;
Hig:=Height+1;
Col:=ColorNum;
end;
procedure TPcx.ProHeader;
var
DacMark:Byte;
i:Integer;
begin
case PcxHead.BitsPerPixel of
1:ColorNum:=1 shl PcxHead.ColorPlanes;
2:if PcxHead.ColorPlanes=4 then
ColorNum:=16
else
ColorNum:=4;
4:ColorNum:=16;
8:if PcxHead.ColorPlanes=1 then
ColorNum:=256
else
ColorNum:=0;
end;
if ColorNum=256 then
begin
Seek(Fp,FileSize(Fp)-769);
BlockRead(Fp,DacMark,1,Result);
BlockRead(Fp,PcxDac,Sizeof(DacType),Result);
if DacMark=$0C then
for i:=1 to 256*3 do
PcxDac[i]:=PcxDac[i] shr 2;
end else
if ColorNum=16 then
for i:=0 to 15 do
begin
PcxDac[GetDacIndex(i)*3+1]:=PcxHead.Palette[i*3] shr 2;
PcxDac[GetDacIndex(i)*3+2]:=PcxHead.Palette[i*3+1] shr 2;
PcxDac[GetDacIndex(i)*3+3]:=PcxHead.Palette[i*3+2] shr 2;
end;
end;
procedure TPcx.OpenFile;
begin
IsValid:=False;
Assign(Fp,FileName);
GetFAttr(Fp,TempAttr);
SetFAttr(Fp,Archive);
{$i-}Reset(Fp,1);{$i+}
if IOResult<>0 then
begin
Writecs(10,10,'Open File '+FileName+' Error!',15);
Exit;
end;
BlockRead(Fp,PcxHead,SizeOf(PcxHeader),Result);
if PcxHead.PcxID<>10 then Exit;
if PcxHead.RleEncoding<>1 then Exit;
if not (PcxHead.Version in [0,2..5]) then Exit;
if not (PcxHead.BitsPerPixel in [1,2,4,8]) then Exit;
if not (PcxHead.ColorPlanes in [1,4]) then Exit;
ProHeader;
Width:=PcxHead.x2-PcxHead.x1;
Height:=PcxHead.y2-PcxHead.y1;
TrueWid:=PcxHead.BytesPerLine*PcxHead.ColorPlanes;
IsValid:=True;
end;
procedure TPcx.Draw;
procedure SetCenter;
begin
if Center then
begin
Origin.X:=0;
Origin.Y:=0;
if Maxx>Width then
Origin.X:=(Maxx-Width) div 2;
if Maxy>Height then
Origin.Y:=(Maxy-Height) div 2;
if MaxColor<256 then
Start:=Origin.Y*ScanLeng + Origin.X div 8;
end;
end;
procedure ReadPcxLine;
var
ByteCount,RunCount,Dtl:Integer;
TempPos:LongInt;
begin
ByteCount:=0;
Dtl:=0;
TempPos:=FilePos(Fp);
BlockRead(Fp,Data,2048,Result);
while ByteCount<TrueWid do
begin
if Data[Dtl]>=$C0 then
begin
RunCount:=Data[Dtl] and $3F;
Inc(Dtl);
FillChar(Line[ByteCount],RunCount,Data[Dtl]);
Inc(ByteCount,RunCount);
end else
begin
Line[ByteCount]:=Data[Dtl];
Inc(ByteCount);
end;
Inc(Dtl);
end;
Seek(Fp,TempPos+Dtl);
end;
procedure Draw_Pcx2;
var
i:Integer;
OfsVideo:Longint;
begin
if ReSetVideo then SetVideoMode(VideoMode16);
SetCenter;
SetWPlane(1);
for i:=0 to Height do
begin
OfsVideo:=Start+Longint(ScanLeng)*i;
if (OfsVideo div $10000)<>Current_Page then
SelectPageVESA(OfsVideo div $10000);
ReadPcxLine;
Move(Line,Ptr($A000,OfsVideo)^,pcxhead.BytesPerLine);
end;
end;
procedure Draw_Pcx16;
var
i,j:Integer;
OfsVideo:Longint;
begin
if ReSetVideo then SetVideoMode(VideoMode16);
SetCenter;
if ReSetDac then Dac.SetNewDac(PcxDac);
for i:=0 to Height do
begin
ReadPcxLine;
OfsVideo:=Start+Longint(ScanLeng)*i;
if (OfsVideo div $10000)<>Current_Page then
SelectPageVESA(OfsVideo div $10000);
for j:=0 to 3 do
begin
SetWPlane(1 shl j);
Move(Line[j*PcxHead.BytesPerLine],
Ptr($A000,OfsVideo)^,PcxHead.BytesPerLine);
end;
end;
end;
procedure Draw_Pcx256;
var
i,j:integer;
begin
if ReSetVideo then SetVideoMode(VideoMode256);
SetCenter;
if ReSetDac then Dac.SetNewDac(PcxDac);
for i:=0 to Height do
begin
ReadPcxLine;
PutLine8(Origin.x,Origin.y+i,Seg(Line),Ofs(Line),Width+1);
end;
end;
begin
if not IsValid then Exit;
GetVideoMode;
Seek(Fp,SizeOf(PcxHeader));
if ColorNum=2 then Draw_Pcx2
else if ColorNum=16 then Draw_Pcx16
else if ColorNum=256 then Draw_Pcx256;
if ShowInfo then
begin
SvgaDrv.SetColor(GetLightColor(DacRegsType(PcxDac)));
SvgaDrv.MoveTo(Maxx div 2 - 70,Maxy-20);
InfoStr:=Intstr(Width+1)+'*'+Intstr(Height+1)+' '+Intstr(ColorNum)+'Color';
SvgaDrv.OutText(InfoStr);
end;
end;
procedure TPcx.PutToLine;
procedure ReadPcxLine;
var
ByteCount,RunCount,Dtl:Integer;
TempPos:LongInt;
begin
ByteCount:=0;
Dtl:=0;
TempPos:=FilePos(Fp);
BlockRead(Fp,Data,2048,Result);
while ByteCount<TrueWid do
begin
if Data[Dtl]>=$C0 then
begin
RunCount:=Data[Dtl] and $3F;
Inc(Dtl);
FillChar(Line[ByteCount],RunCount,Data[Dtl]);
Inc(ByteCount,RunCount);
end else
begin
Line[ByteCount]:=Data[Dtl];
Inc(ByteCount);
end;
Inc(Dtl);
end;
Seek(Fp,TempPos+Dtl);
end;
Type
ArrType=array[1..$FFFF] of Byte;
var
i,j:Integer;
begin
if ColorNum<>256 then Exit;
Seek(Fp,SizeOf(PcxHeader));
for i:=0 to Height do
if (i<y) then
begin
ReadPcxLine;
Move(Line[0],ArrType(Arr)[1+i*x],x);
end;
end;
procedure TPcx.Creat;
procedure ConvertDac;
var
i:Integer;
begin
if Maxcolor=0 then Exit;
if Maxcolor=16 then
for i:=0 to Maxcolor-1 do
begin
PcxHead.Palette[i*3]:=PcxDac[getdacindex(i)*3+1] shl 2;
PcxHead.Palette[i*3+1]:=PcxDac[getdacindex(i)*3+2] shl 2;
PcxHead.Palette[i*3+2]:=PcxDac[getdacindex(i)*3+3] shl 2;
end
else
if MaxColor=256 then
for i:=1 to 768 do
PcxDac[i]:=PcxDac[i] shl 2;
end;
procedure WritePcxLine;
var
ByteCount,RunCount,Dtl:Integer;
TempData:byte;
begin
ByteCount:=0;
Dtl:=0;
while ByteCount<TrueWid do
begin
TempData:=Line[ByteCount];
RunCount:=1;
Inc(ByteCount);
while (ByteCount<TrueWid) and
(Line[ByteCount]=TempData) and (RunCount<$3f) do
begin
Inc(RunCount);
Inc(ByteCount);
end;
if (RunCount>1)or(TempData>=$C0) then
begin
Data[Dtl]:=$C0 or RunCount;
Data[Dtl+1]:=TempData;
Inc(Dtl);
end else
Data[Dtl]:=TempData;
Inc(Dtl);
end;
BlockWrite(Fp,Data,Dtl,Result);
end;
procedure WritePcx16;
var
i,j,k:Integer;
begin
for i:=0 to Height-1 do
begin
for j:=0 to 3 do
begin
SetRPlane(j);
Move(Ptr($A000,ScanLeng*(Origin.y+i)+Origin.x div 8)^,
Line[j*PcxHead.BytesPerLine],PcxHead.BytesPerLine);
end;
WritePcxLine;
end;
end;
procedure WritePcx256;
var
i,j:Integer;
Mark:Byte;
begin
for i:=0 to Height-1 do
begin
for j:=0 to TrueWid-1 do
Line[j]:=GetPixel8(Origin.x+j,Origin.y+i);
WritePcxLine;
end;
Mark:=$0C;
BlockWrite(Fp,Mark,1,Result);
BlockWrite(Fp,PcxDac,Sizeof(DacType),Result);
end;
begin
GetVideoMode;
if (MaxColor<>16)and(MaxColor<>256) then Exit;
Assign(Fp,FileName);
{$i-}ReWrite(Fp,1);{$i+}
if IOResult<>0 then Exit;
Width:=x;
Height:=y;
PcxHead.PcxID:=$0A;
PcxHead.Version:=5;
PcxHead.RleEncoding:=1;
PcxHead.x1:=0;
PcxHead.y1:=0;
PcxHead.x2:=Width-1;
PcxHead.y2:=Height-1;
PcxHead.HRes:=Maxx;
PcxHead.VRes:=Maxy;
PcxHead.Reserved:=0;
PcxHead.PaletteType:=2;
fillchar(PcxHead.UnUsed,58,0);
PcxHead.ColorPlanes:=1;
if MaxColor=16 then
begin
PcxHead.BitsPerPixel:=1;
PcxHead.ColorPlanes:=4;
end else
if MaxColor=256 then PcxHead.BitsPerPixel:=8;
PcxHead.BytesPerLine:=PcxHead.BitsPerPixel*width div 8;
truewid:=pcxhead.BytesPerLine*pcxhead.ColorPlanes;
Dac.GetDac(PcxDac);
ConvertDac;
BlockWrite(Fp,PcxHead,SizeOf(PcxHeader),Result);
if MaxColor=16 then WritePcx16
else if MaxColor=256 then WritePcx256;
end;
end.