Cách chèn ảnh vào pascal

22/01/2014 kakashipro Pascal mở rộng 0

1. Các hàm và thủ tục tạo ảnh chuyển động

Một ảnh được lưu trữ trong bộ nhớ bằng tập hợp các bit (gọi là ảnh bit, bit image), chẳng hạn với ảnh 16 màu thì mỗi pixel tương ứng với 4 bit (ứng với một màu từ 0, 1, 2, . . ., 15). Việc xử lý ảnh bit được tiến hành theo từng bit.

Các hàm và thủ tục sau dùng để tạo ảnh chuyển động:

* Hàm ImageSize(x1, y1, x2, y2: integer): word xác định  số byte cần thiết cho thủ tục GetImage lưu vùng chữ nhật trên màn hình  (x1, y1, x2, y2). Kích thước ảnh bao gồm thêm cả ba word: word đầu lưu độ rộng của vùng chữ nhật, word thứ hai lưu chiều cao vùng, word thứ ba dùng để dự trữ. Máy lưu các điểm ảnh theo hàng, mỗi điểm ảnh chiếm 4 bít, nếu số lượng [(số điểm ảnh một hàng * 4 bit) / 8 bit] byte không chia hết cho 4 thì máy sẽ thêm từ 1 đến 3 byte để số byte cần lưu một hàng chia hết cho 4. Ví dụ nếu vùng ảnh là (1,1,100,100) thì số byte cần thiết để lưu vùng ảnh là [(100 điểm * 4 bit / 8 bit + 2 byte] * 100 hàng + 6 byte = 5206 byte. Nếu bộ nhớ yêu cầu để lưu vùng lớn hơn 64 KB thì hàm trả về giá trị 0 và GraphResult = -11.

* Thủ tục GetImage(x1, y1, x2, y2: integer; var BitMap) chép ảnh bit nằm trong vùng chữ nhật (x1, y1, x2, y2) vào biến BitMap. BitMap là một tham số không định kiểu. Hai word đầu tiên của BitMap lưu trữ chiều rộng và chiều cao của vùng, word thứ ba dùng để dự trữ, phần còn lại của BitMap được dùng để ghi ảnh bit. Dùng hàm ImageSize để xác định yêu cầu về kích thước của BitMap.

* Thủ tục PutImage(x,y: integer; var BitMap ; BitBlt: word): đặt ảnh bit lưu trong BitMap lên màn hình, góc trên bên trái của vùng ảnh có toạ độ là (x, y). BitMap là tham số không định kiểu chứa chiều cao và chiều rộng của vùng ảnh, và ảnh bit sẽ được đặt lên màn hình. Tham số BitBlt xác định phép toán thao tác bit nào sẽ được dùng để đặt ảnh bit lên màn hình. Mỗi một hằng số tương ứng với một phép toán thao tác bit:

Tên hằng                             Giá trị                      Phép toán bit

CopyPut, NormalPut           0                             MOV

XORPut                             1                             XOR

ORPut                                2                             OR

ANDPut                             3                             AND

NOTPut                             4                             NOT

Ý nghĩa các phép toán thao tác bit:

Bit A (ảnh)      Bit B (nền)   A and B       A or B       C=A xor B      A xor C      not A

1                   1                 1                 1               0                   1               0

1                   0                 0                 1               1                   0

0                   1                 0                 1               1                   1               1

0                   0                 0                 0               0                   0

Ví dụ, PutImage(x, y, BitMap, NormalPut) sẽ đặt ảnh lưu trong Bitmap tại (x,y) bằng cách dùng lệnh MOV của ngôn ngữ Assembler với từng byte trong ảnh (ảnh mới sẽ ghi đè lên ảnh cũ trên màn hình). Lệnh PutImage(x, y, BitMap, XorPut) sẽ đặt ảnh lưu trong BitMap tại (x,y) bằng cách dùng lệnh XOR của ngôn ngữ Assembler với từng byte trong ảnh, lệnh này thường dùng để tạo ảnh chuyển động trên màn hình có nền. Lệnh PutImage(x, y, Bitmap, NotPut): đảo các bit  trong BitMap, sau đó đặt ảnh lưu trong Bitmap lên màn hình tại (x,y) bằng cách dùng lệnh MOV với từng byte trong ảnh, như vậy ảnh sẽ bị đảo so với ảnh gốc.

Từ cột 5 và cột 6 của bảng trên ta có nhận xét: khi in hai lần một ảnh vào cùng một vị trí theo cách XorPut thì ảnh sẽ bị xoá và nền cũ hiện lại (cột 6 trùng với cột 2). Ta sẽ ứng dụng nhận xét này để tạo ảnh chuyển động mà vẫn giữ nguyên màn hình nền. Từ cột 5 ta thấy: dùng cách XorPut để in ảnh thì ảnh bị đổi màu (xem chương trình XorPut.pas ở dưới), nếu ảnh vẽ và ảnh nền cùng màu thì màu kết quả theo cách XorPut là màu nền.

Chương trình PutImag.pas: lưu vùng ảnh chữ nhật vào P^, 21 lần in ảnh lưu ra màn hình theo cách CopyPut.

uses Graph;
var Gd, Gm,i: Integer; P: Pointer; Size: Word;
begin Gd := Detect; InitGraph(Gd, Gm, ‘ ‘);
if GraphResult <> grOk then   Halt(1);
Bar(0, 0, GetMaxX, GetMaxY);
Size := ImageSize(10, 20, 30, 40); GetMem(P, Size);
GetImage(10, 20, 30, 40, P^); Readln; ClearDevice;
for i:=0 to 20  do PutImage(10+i*22, 10+i*22, P^, CopyPut);
Readln; CloseGraph;
end.

2. Tạo ảnh chuyển động không có màn hình nền.

Phương pháp này chỉ sử dụng trong trường hợp vật chuyển động qua vùng màn hình trơn (không có ảnh các vật thể khác, chỉ có màu nền). Các bước thực hiện: tạo ảnh bằng màu vẽ, xoá ảnh bằng màu nền, tạo lại ảnh bằng màu vẽ tại vị trí mới

Chương trình Bong.pas: vẽ một quả bóng màu đỏ trên nền Cyan, khi ấn một phím mũi tên quả bóng liên tục chuyển động theo hướng mũi tên cho đến biên màn hình, ấn phím ESC để dừng chương trình.

uses crt,graph;
const r=50; s=3;
var gd,gm,x,y,mx,my,nen: integer; c: char;
procedure Bong(x,y,mau: word);
begin setcolor(mau); setfillstyle(1,mau); fillellipse(x,y,r,r);
end;
begin gd:= detect; initgraph(gd,gm,”);
nen:=cyan; setbkcolor(nen); mx:= getmaxx; my:= getmaxy;
randomize; x:= random(mx-2*r)+r; y:=random(my-2*r)+r;
bong(x,y,red);
repeat  c := readkey;
if (c = #0) then
begin c := readkey;
case c of
#75: while (not keypressed) and (x>r) do
begin bong(x,y,nen);x:=x-s;bong(x,y,red);delay(100) end;
#77: while (not keypressed) and (x
begin bong(x,y,nen);x:=x+s;bong(x,y,red);delay(100) end;
#72: while (not keypressed) and (y>r) do
begin bong(x,y,nen);y:=y-s;bong(x,y,red);delay(100) end;
#80: while (not keypressed) and (y
begin bong(x,y,nen);y:=y+s;bong(x,y,red);delay(100) end;
end;
end;
until c=#27; closegraph;
end.

3. Tạo ảnh chuyển động trên một màn hình nền

Thuật toán tạo ảnh chuyển động mà không xoá nền:

1. Vẽ ảnh trong vùng (x1, y1, x2, y2),

2. Tính số byte cần thiết để lưu ảnh thuộc vùng chữ nhật nhờ hàm ImageSize (giả sử là n), cấp phát vùng nhớ n byte và cho con trỏ P trỏ vào byte đầu tiên của vùng nhớ này bằng lệnh GetMem,

3. Dùng lệnh GetImage để chép ảnh từ vùng chữ nhật (x1, y1, x2, y2) vào vùng nhớ vừa cấp phát (ứng với biến động P^),

4. Xoá màn hình, tạo màn hình nền hoàn toàn mới,

5. Dùng lệnh PutImage in ảnh lưu trong P^ ra màn hình tại toạ độ (x,y) theo cách XorPut, dừng chương trình một lát, thay đổi các thành phần x,y để được điểm (x,y) mới, dùng PutImage in lại ảnh vẫn tại toạ độ (x,y) cũ theo cách XorPut để xoá ảnh và khôi phục nền cũ, dùng PutImage in ảnh ở điểm (x,y) mới . . . Thời gian giữa xoá ảnh cũ và in ảnh mới càng ngắn càng tốt.

Chương trình CDong.pas: vẽ một viên đạn nghiêng sang phải 45 độ, ghi ảnh vào biến con trỏ P, đặt nền màn hình màu Cyan, viết 2 dòng chữ màu Blue ở giữa màn hình, vẽ một mặt trăng màu trắng ở giữa nửa trên màn hình. Cho 4 viên đạn xuất phát ngẫu nhiên từ cạnh trái màn hình và từ cạnh đáy màn hình chuyển động từ phía trái sang phía phải  với góc nghiêng 45 độ.

uses graph,crt;
var gd,gm,x1,y1,x2,y2,x3,y3,x4,y4,u1,u2,u3,u4,v1,v2,v3,v4:integer;
p: pointer;
begin gd:=VGA; gm:=VgaHi; initgraph(gd,gm,”);
setcolor(red); setfillstyle(1,red);
line(0,12,8,20); line(8,20,18,10); line(18,10,20,0);
line(20,0,10,2); line(10,2,0,12);
floodfill(10,10,red); readln;
getmem(p,imagesize(0,0,20,20)); getimage(0,0,20,20,p^);
cleardevice;
setbkcolor(cyan); settextstyle(0,0,2); settextjustify(1,1);
setcolor(blue); outtextxy(320,240,’Bui The Tam, Lop 12 A’);
outtextxy(320,280,’Truong Trung hoc Pho thong Ly Bi’);
setcolor(white); ellipse(320,100,180,360,50,50);
ellipse(320,100,180,360,50,25); setfillstyle(1,white);
floodfill(320,130,white);
x1:=0; y1:=random(460); x2:=random(620); y2:=479;
x3:=0; y3:=random(460); x4:=random(620); y4:=479;
repeat  putimage(x1,y1,p^,1); putimage(x2,y2,p^,1);
putimage(x3,y3,p^,1); putimage(x4,y4,p^,1);
u1:=x1; v1:=y1;u2:=x2; v2:=y2;
u3:=x3; v3:=y3;u4:=x4; v4:=y4;
x1:=x1+5; y1:=y1-5; if y1<0 then begin x1:=0; y1:=random(480) end;
x2:=x2+5; y2:=y2-5;
if (y2<0) or(x2>640-20) then begin x2:=random(620); y2:=479 end;
x3:=x3+5; y3:=y3-5; if y3<0 then begin x3:=0; y3:=random(480) end;
x4:=x4+5; y4:=y4-5;
if (y4<0) or(x4>640-20) then begin x4:=random(620); y4:=479 end;
delay(20); putimage(u1,v1,p^,1); putimage(u2,v2,p^,1);
putimage(u3,v3,p^,1); putimage(u4,v4,p^,1);
until keypressed;
closegraph; dispose(p);
end.

Việc chép ảnh bằng lệnh PutImage theo cách XorPut có nhược điểm là ảnh bị đổi màu khi đi qua ảnh nền. Để khắc phục điều này ta có thể kết hợp việc vẽ ảnh với việc cất ảnh nền ở vị trí định vẽ để sau đó có thể khôi phục ảnh nền cũ bằng CopyPut. Chương trình LuuNen.pas minh hoạ cách làm này: tạo 500 hình tròn có màu ngẫu nhiên làm ảnh nền, cho quả bóng màu đỏ chuyển động ngang màn hình mà không xoá nền.

uses graph,crt;
var i,k,gd,gm,x1,y1,u1,v1,r:integer; n: word; p: pointer;
begin
gd:=VGA; gm:=VgaHi; initgraph(gd,gm,”); randomize; r:=50;
for i:=1 to 500 do
begin k:= random(15)+1; setcolor(k); setfillstyle(1,k);
Fillellipse(random(640-40)+20,random(480-40)+20,20,20);
end;
x1:=r; y1:=240;
n:=imagesize(x1-r,y1-r,x1+r,y1+r); getmem(p,n);
repeat
GetImage(x1-r,y1-r,x1+r,y1+r,p^);
setcolor(LightRed); setfillstyle(1,LightRed); FillEllipse(x1,y1,r,r);
u1:=x1; v1:=y1; x1:=x1+5;
if x1>639-r then
begin delay(500); x1:=r; putimage(u1-r,v1-r,p^,0) end
else  begin delay(500); putimage(u1-r,v1-r,p^,0); end;
until keypressed;
dispose(p); closegraph;
end.

Nguồn sưu tầm