主题:在作图模式下显示16色PCX图像
请注意:这里说的16色pcx文件的格式是以前最早的pcx格式。现在用acdsee,photoshop等作图工具转换,这个程序不能够显示。为此我花了两三个小时的冤枉时间检查一个本来并没有错误的程序。最后用老掉牙的软件:dos下的alchemy.exe,或者是windows下的photoimpact 3.01转了一下文件,才显示得出来! >_<
如果你要一个pcx文件样本的话我可以寄给你。
因为这个程序也是参考一本老掉牙的书的!原书是用C编的。我偏要用PASCAL来编!因为用pascal来编这种东东的书几乎找不到一本!
这下可惨了,C的指针可以随便乱指,PASCAL语言的指针可没有C那么灵活!仅仅为了定位一个指针,就费了九牛二虎之力。
TURBO PASCAL 7.0,可以提供了下一个640*480*16色的作图模式。缺省定义好了16种颜色。但并不是说就一定要用这16种颜色,你可以自己定义另外的16种颜色来用。但每次调色板里,最多只能有16种颜色。你可以这一次,用这16种颜色,下一次换屏幕显示时,用另外16种颜色。这主要和机器的基本显存有关系。
以前念书时,偷了windows 3.1接龙的扑克牌图案,用显示pcx图像的方法,用C语言做了个扑克牌游戏,让同学们大吃一惊:这些牌的图案你是怎么做出来的?我说:“我一点一点地描出来的!”哈!其实那些牌的图案,全部颜色加起来也不到16种。编起来绰绰有余。
可惜我经常乱删程序,常常把自己编的程序删得一干二净。在这里也要告诉大家:自己编的程序要珍惜噢!不要象我,一个删除把长时间的劳动成果在一秒钟之内删掉。
下面程序,你可以看到改调色板的过程,连汇编语言都出来了。因为我认为调用DOS中断,也其调用函数,还不如直接打汇编语言更简单。
程序在TURBO PASCAL 7.0下通过。
==========================
(* 16 colors PCX file viewer.
Programmed by j.t.Chang.
*)
program pcx16demo;
uses crt,graph;
type
paltype=array[0..47] of byte;
pcxhead=record
manufac:byte;
version:byte;
encoding:byte;
bits_per_pixel:byte;
xmin,ymin:integer;
xmax,ymax:integer;
hres:integer;
vres:integer;
palette:paltype;
reserved:byte;
colour_planes:byte;
bytes_per_line:integer;
palette_type:integer;
filler:array[0..57] of byte;
end;
pbyte=^byte;
var
ch : char;
pcxhdr : pcxhead;
bytes,width,depth,showdepth,size : word;
p : pointer;
f0 : file of pcxhead;
f : file of byte;
filename : string;
(*************************************)
procedure init;
var
gd,gm,ErrCode : integer;
begin
gd:=detect;
initgraph(gd,gm,'');
ErrCode:=graphresult;
if ErrCode<>grOK then
begin
Writeln('Graphics error: ', GraphErrorMsg(ErrCode));
exit;
end;
end;
(*************************************)
procedure Loadpalette;
var
t1,t2 : word;
k : byte;
begin
for k:=0 to 15 do
begin
asm mov ah,10h
mov al,0
mov bh,k
mov bl,k
int 10h
end;
end;
for k:=0 to 47 do
pcxhdr.palette[k]:= pcxhdr.palette[k] shr 2;
t1:=OFS(pcxhdr.palette);
t2:=SEG(pcxhdr.palette);
asm mov ax,1012h
mov bx,0
mov cx,16
mov dx,t1
mov es,t2
int 10h
end;
end;
(*************************************)
procedure RPL(p:Pbyte);
var
t : pbyte;
n, i : integer;
b,c : byte;
begin
n:=0; t:=p;
repeat
read(f,c);
if (c and $c0) = $c0 then
begin
i:=c and $3f;
read(f,c);
while i>0 do
begin
t^:=c;
inc(t,1);
n:=n+1;
i:=i-1;
end;
end
else
begin
t^:=c;
inc(t,1);
n:=n+1;
end;
until n>=bytes ;
end;
(*************************************)
procedure unpackpcx;
var
q : Pbyte;
i,j,n,st : integer;
begin
n:=0; st:=0; q:=p;
q^:=width-1; inc(q,1);
q^:=(width-1) shr 8; inc(q,1);
q^:=120; inc(q,1);
q^:=120 shr 8; inc(q,1);
for i:=0 to showdepth-1 do
begin
j:=pcxhdr.colour_planes;
j:=j-1; q:=p;
inc(q,bytes*(n+j)+4);
RPL(q);
j:=j-1; q:=p;
inc(q,bytes*(n+j)+4);
RPL(q);
j:=j-1; q:=p;
inc(q,bytes*(n+j)+4);
RPL(q);
j:=j-1; q:=p;
inc(q,bytes*(n+j)+4);
RPL(q);
n:=n+pcxhdr.colour_planes;
if n>=(120*pcxhdr.colour_planes) then
begin
PutImage(0, st*120, P^, NormalPut);
st:=st+1;
n:=0;
end;
end;
if (showdepth mod 120<>0) then
begin
q:=p; inc(q,2);
q^:=showdepth mod 120-1; inc(q,1);
q^:= (showdepth mod 120-1) shr 8;
PutImage(0, st*120, P^, NormalPut);
end;
end;
(*************************************)
begin
clrscr;
write('Enter a 16 colors PCX file name: ');
readln(filename);
assign(f0,filename);
reset(f0);
read(f0,pcxhdr);
close(f0);
if pcxhdr.manufac<>$a then
begin
writeln('Not an invalide PCX file.');
exit;
end;
if (pcxhdr.bits_per_pixel<>1) then
if (pcxhdr.bits_per_pixel<>4) then
begin
writeln('Not a 16 colors PCX file.');
exit;
end;
assign(f,filename);
reset(f);
seek(f,sizeof(pcxhead));
width:=pcxhdr.xmax-pcxhdr.xmin+1;
depth:=pcxhdr.ymax-pcxhdr.ymin+1;
bytes:=pcxhdr.bytes_per_line;
if depth>480 then showdepth:=480
else showdepth:=depth;
size:=4;
size:= 4+size*bytes*120;
GetMem(P,Size);
init;
Loadpalette;
Unpackpcx;
close(f);
ch:=readkey;
closegraph;
freemem(p,size);
end.
=======================
如果你要一个pcx文件样本的话我可以寄给你。
因为这个程序也是参考一本老掉牙的书的!原书是用C编的。我偏要用PASCAL来编!因为用pascal来编这种东东的书几乎找不到一本!
这下可惨了,C的指针可以随便乱指,PASCAL语言的指针可没有C那么灵活!仅仅为了定位一个指针,就费了九牛二虎之力。
TURBO PASCAL 7.0,可以提供了下一个640*480*16色的作图模式。缺省定义好了16种颜色。但并不是说就一定要用这16种颜色,你可以自己定义另外的16种颜色来用。但每次调色板里,最多只能有16种颜色。你可以这一次,用这16种颜色,下一次换屏幕显示时,用另外16种颜色。这主要和机器的基本显存有关系。
以前念书时,偷了windows 3.1接龙的扑克牌图案,用显示pcx图像的方法,用C语言做了个扑克牌游戏,让同学们大吃一惊:这些牌的图案你是怎么做出来的?我说:“我一点一点地描出来的!”哈!其实那些牌的图案,全部颜色加起来也不到16种。编起来绰绰有余。
可惜我经常乱删程序,常常把自己编的程序删得一干二净。在这里也要告诉大家:自己编的程序要珍惜噢!不要象我,一个删除把长时间的劳动成果在一秒钟之内删掉。
下面程序,你可以看到改调色板的过程,连汇编语言都出来了。因为我认为调用DOS中断,也其调用函数,还不如直接打汇编语言更简单。
程序在TURBO PASCAL 7.0下通过。
==========================
(* 16 colors PCX file viewer.
Programmed by j.t.Chang.
*)
program pcx16demo;
uses crt,graph;
type
paltype=array[0..47] of byte;
pcxhead=record
manufac:byte;
version:byte;
encoding:byte;
bits_per_pixel:byte;
xmin,ymin:integer;
xmax,ymax:integer;
hres:integer;
vres:integer;
palette:paltype;
reserved:byte;
colour_planes:byte;
bytes_per_line:integer;
palette_type:integer;
filler:array[0..57] of byte;
end;
pbyte=^byte;
var
ch : char;
pcxhdr : pcxhead;
bytes,width,depth,showdepth,size : word;
p : pointer;
f0 : file of pcxhead;
f : file of byte;
filename : string;
(*************************************)
procedure init;
var
gd,gm,ErrCode : integer;
begin
gd:=detect;
initgraph(gd,gm,'');
ErrCode:=graphresult;
if ErrCode<>grOK then
begin
Writeln('Graphics error: ', GraphErrorMsg(ErrCode));
exit;
end;
end;
(*************************************)
procedure Loadpalette;
var
t1,t2 : word;
k : byte;
begin
for k:=0 to 15 do
begin
asm mov ah,10h
mov al,0
mov bh,k
mov bl,k
int 10h
end;
end;
for k:=0 to 47 do
pcxhdr.palette[k]:= pcxhdr.palette[k] shr 2;
t1:=OFS(pcxhdr.palette);
t2:=SEG(pcxhdr.palette);
asm mov ax,1012h
mov bx,0
mov cx,16
mov dx,t1
mov es,t2
int 10h
end;
end;
(*************************************)
procedure RPL(p:Pbyte);
var
t : pbyte;
n, i : integer;
b,c : byte;
begin
n:=0; t:=p;
repeat
read(f,c);
if (c and $c0) = $c0 then
begin
i:=c and $3f;
read(f,c);
while i>0 do
begin
t^:=c;
inc(t,1);
n:=n+1;
i:=i-1;
end;
end
else
begin
t^:=c;
inc(t,1);
n:=n+1;
end;
until n>=bytes ;
end;
(*************************************)
procedure unpackpcx;
var
q : Pbyte;
i,j,n,st : integer;
begin
n:=0; st:=0; q:=p;
q^:=width-1; inc(q,1);
q^:=(width-1) shr 8; inc(q,1);
q^:=120; inc(q,1);
q^:=120 shr 8; inc(q,1);
for i:=0 to showdepth-1 do
begin
j:=pcxhdr.colour_planes;
j:=j-1; q:=p;
inc(q,bytes*(n+j)+4);
RPL(q);
j:=j-1; q:=p;
inc(q,bytes*(n+j)+4);
RPL(q);
j:=j-1; q:=p;
inc(q,bytes*(n+j)+4);
RPL(q);
j:=j-1; q:=p;
inc(q,bytes*(n+j)+4);
RPL(q);
n:=n+pcxhdr.colour_planes;
if n>=(120*pcxhdr.colour_planes) then
begin
PutImage(0, st*120, P^, NormalPut);
st:=st+1;
n:=0;
end;
end;
if (showdepth mod 120<>0) then
begin
q:=p; inc(q,2);
q^:=showdepth mod 120-1; inc(q,1);
q^:= (showdepth mod 120-1) shr 8;
PutImage(0, st*120, P^, NormalPut);
end;
end;
(*************************************)
begin
clrscr;
write('Enter a 16 colors PCX file name: ');
readln(filename);
assign(f0,filename);
reset(f0);
read(f0,pcxhdr);
close(f0);
if pcxhdr.manufac<>$a then
begin
writeln('Not an invalide PCX file.');
exit;
end;
if (pcxhdr.bits_per_pixel<>1) then
if (pcxhdr.bits_per_pixel<>4) then
begin
writeln('Not a 16 colors PCX file.');
exit;
end;
assign(f,filename);
reset(f);
seek(f,sizeof(pcxhead));
width:=pcxhdr.xmax-pcxhdr.xmin+1;
depth:=pcxhdr.ymax-pcxhdr.ymin+1;
bytes:=pcxhdr.bytes_per_line;
if depth>480 then showdepth:=480
else showdepth:=depth;
size:=4;
size:= 4+size*bytes*120;
GetMem(P,Size);
init;
Loadpalette;
Unpackpcx;
close(f);
ch:=readkey;
closegraph;
freemem(p,size);
end.
=======================