You are on page 1of 10

Chương 6.

Đồ họa và âm thanh

CHƯƠNG 6 

ĐỒ HOẠ VÀ ÂM THANH

Đồ hoạ
Âm thanh

I. ĐỒ HOẠ

1. Khái niệm đồ hoạ

1. Điểm ảnh và độ phân giải


Màn hình ở chế độ đồ hoạ là tập hợp các điểm (pixel-picture elements) ảnh. Số
điểm ảnh và cách bố trí theo chiều ngang, dọc của màn hình được gọi là độ phân giải
(resolution). Vì vậy độ phân giải thường được đặc trưng bởi một cặp số chỉ định số
điểm ảnh theo chiều ngang và chiều dọc của màn hình. Ví dụ màn hình VGA ở mode
2 có độ phân giải là 640x480, tức trên mỗi dòng ngang của màn hình có thể vẽ được
640 điểm ảnh và trên mỗi cột dọc vẽ được 480 điểm ảnh. Các cột và dòng được
đánh số từ 0, theo chiều từ trái sang phải (đối với cột) và từ trên xuống dưới (đối với
dòng). Một điểm ảnh hay còn gọi là pixel là giao điểm của một cột và một dòng nào
đó trên màn hình và vị trí của nó được thể hiện bởi cặp toạ độ (x,y) với x biểu diễn
cho cột và y biểu diễn cho dòng. Ví dụ với màn hình trên điểm ảnh “đầu tiên” nằm ở
góc trên bên trái của màn hình có toạ độ (0,0) và điểm “cuối cùng” ở góc dưới bên
phải có toạ độ (639,479). Điểm có toạ độ (150,200) là giao điểm của cột thứ 150 và
dòng 200.

2. Trình điều khiển đồ hoạ


Màn hình đồ hoạ có nhiều loại khác nhau. Mỗi loại màn hình cần có trình điều
khiển tương ứng. C cung cấp các trình điều khiển màn hình trong thư mục BGI đặt
dưới thư mục gốc của C (TC hoặc BC) gồm có:

Tên trình điều khiển Kiểu màn hình đồ hoạ


ATT.BGI ATT & T6300 (400 dòng)
CGA.BGI IBMCGA, MCGA và các máy tương thích

183
Chương 6. Đồ họa và âm thanh

EGAVGA.BGI IBM EGA, VGA và các máy tương thích


HERC.BGI Hercules mono và các máy tương thích
IBM8514.BGI IBM 8514 và các máy tương thích
PC3270.BGI IBM 3270 PC
Ngoài các trình điều khiển trong thư mục BGI còn chứa các file font chữ có đuôi
CHR gồm:
GOTH.CHR
LITT.CHR
SANS.CHR
TRIP.CHR

3. Mốt (mode) đồ hoạ


Mỗi màn hình đồ hoạ có thể hoạt động dưới nhiều mốt khác nhau. Độ phân
giải của màn hình phụ thuộc vào từng mốt. Ví dụ màn hình VGA có thể hoạt động
dưới các mốt 0 (VGALO: độ phân giải thấp 640x200), 1 (VGAMED: độ phân giải
trung bình 640x350), 2 (VGAHI: độ phân giải cao 640x480).

2. Vào/ra chế độ đồ hoạ


Trong C++ các hàm liên quan đến đồ hoạ được khai báo trong tệp <graphics.h>

a. Khởi động chế độ đồ hoạ


void initgraph(int *graphdriver, int *graphmode, char *drivepath)
− drivepath: đường dẫn của thư mục chứa các trình điều khiển đồ hoạ. Nếu
rỗng sẽ tìm trong thư mục hiện tại.
− graphdriver, graphmode: Chỉ định trình quản lý và mốt màn hình cần sử dụng.
Trong đó graphdriver có thể nhận 1 trong các giá trị sau:

DETECT 0
CGA 1
EGA 3
EGA64 4
EGAMONO 5

184
Chương 6. Đồ họa và âm thanh

VGA 9
..................... ..

Hiển nhiên việc chọn giá trị của graphdriver phải tương ứng với màn hình thực
tế. Trong trường hợp ta không biết chủng loại thực tế của màn hình có thể sử dụng
giá trị DETECT (hoặc 0) là giá trị chỉ định cho chương trình tự tìm hiểu về màn hình
và gọi trình điều khiển tương ứng. Trong trường hợp này graphmode sẽ được gán giá
trị tự động với mode có độ phân giải cao nhất có thể. Về graphmode có thể nhận các
giá trị sau:

CGAC0 0 320 x 200


CGAC1 1 320 x 200
CGAC2 2 320 x 200
CGAC3 3 320 x 200
CGAHI 4 640 x 200 2 color
EGALO 0 640 x 200 16 color
EGAHI 1 640 x 350 16 color
EGA64LO 0 640 x 200 16 color
EGA64HI 1 640 x 350 4 color
VGALO 0 640 x 200 16 color
VGAMED 0 640 x 350 16 color
VGAHI 0 640 x 480 16 color

Trong quá trình sử dụng để xoá màn hình đồ hoạ ta dùng hàm cleardevice();

2. Kết thúc chế độ đồ hoạ


Để kết thúc chế độ đồ hoạ về lại chế độ văn bản ta sử dụng hàm closegraph();

3. Lỗi đồ hoạ
- Sau mỗi thao tác đồ hoạ, hàm graphresult() sẽ cho giá trị 0 nếu không có lỗi,
hoặc các giá trị âm (-1 .. -18) tương ứng với lỗi. Hàm grapherrormsg(n) trả lại nội
dung lỗi và mã lỗi.
Mã lỗi Hằng lỗi (graphresult()) Nội dung lỗi (grapherrormsg())

185
Chương 6. Đồ họa và âm thanh

0 grOk No error
-1 grNoInitGraph (BGI) Không có BGI
-2 grNotDetected Graphics hardware not detected
-3 grFileNotFound Device driver file not found
........................................................................................................

Ví dụ 1 :
Ví dụ sau đây khởi tạo chế độ đồ hoạ với graphdriver = 0 (DETECT) và thông
báo lỗi nếu không thành công hoặc thông báo chế độ đồ hoạ cũng như mode màn
hình. Để biết độ phân giải của màn hình có thể dùng các hàm getmaxx() (số cột) và
getmaxy() (số dòng)
void main()
{
int gd = DETECT, gm, maloi;
initgraph(&gd, &gm, "C:\\BC\\BGI");
maloi = graphresult();
if (maloi != grOk)
{
cout << "Lỗi: " << grapherrormsg(maloi)) << endl;
cout << "An phím bất kỳ để dừng "; getch();
exit(1);
} else {
cout << "Chế độ màn hình = " << gd << endl;
cout << "Mode màn hình = " << gm << endl;
cout << "Độ phân giải: " << getmaxx() << "," << getmaxy() << endl;
getch();
}
closegraph();
}

Các phần tiếp theo sau đây sẽ cung cấp các câu lệnh để vẽ trong chế độ đồ họa.

3. Vẽ điểm, đường, khối, màu sắc

186
Chương 6. Đồ họa và âm thanh

a. Màu sắc
• getmaxcolor(): Trả lại số hiệu (hằng) tương ứng với màu tối đa của màn
hình hiện tại. Do các hằng màu được tính từ 0 nên số màu sẽ bằng hằng trả
lại cộng thêm 1.
• setbkcolor(màu): Đặt màu nền. Có tác dụng với văn bản và các nét vẽ.
• setcolor(màu): Đặt màu vẽ. Có tác dụng với văn bản và các nét vẽ.
• getbkcolor(): Trả lại màu nền hiện tại.
• getcolor(): Trả lại màu vẽ hiện tại (từ 0 đến getmaxcolor()).
Ví dụ: In toạ độ tại vị trí hiện tại của con trỏ màn hình. Trong ví dụ này chúng
ta sử dụng câu lệnh sprintf(xâu s, "dòng đk", các biểu thức cần in), câu lệnh này sẽ
thay việc in các biểu thức ra màn hình thành in ra xâu s (tức tạo xâu s từ các biểu
thức). Ngoài ra hàm outtextxy(x, y, s) sẽ in xâu s tại vị trí (x,y).
void intoado(dx, dy, color)
{
int oldcolor;
oldcolor = getcolor();
setcolor(color);
char td[10];
sprintf(td, "(%d, %d)", getx(), gety());
outtextxy(getx()+dx, gety()+dy, td);
setcolor(oldcolor);
}

2. Vẽ điểm
• putpixel(x, y, c): Vẽ điểm (x, y) với màu c.
• getpixel (x, y): Trả lại màu tại điểm (x, y).
Ví dụ 2 : Vẽ bầu trời sao
void sky()
{
int maxx, maxy, maxc;
int i, xarr[3001], yarr[3001];
maxx = getmaxx();

187
Chương 6. Đồ họa và âm thanh

maxy = getmaxy();
maxc = getmaxcolor();
randomize();
for (i=1;i<3001;i++) {xarr[i]=random(maxx);yarr[i]=random(maxy);}
while (!kbhit()) {
for (i=1;i<3001;i++)
{
putpixel(xarr[i], yarr[i], random(maxc));delay(1);
}
for (i=1;i<3001;i++)
if (getpitxel(xarr[i], yarr[i]) == random(maxc))
putpitxel(xarr[i], yarr[i], 0);
}
}

3. Vẽ đường thẳng và gấp khúc


• line(x1, y1, x2, y2): Vẽ đường thẳng từ (x1, y1) đến (x2, y2). Con trỏ màn
hình vẫn đứng tại vị trí cũ.
• lineto(x, y): Vẽ đường thẳng từ vị trí hiện tại của con trỏ đến vị trí (x, y).
con trỏ chuyển về (x, y).
• linerel(dx, dy): Gọi (x, y) là vị trí hiện tại của con trỏ, lệnh này sẽ vẽ đường
thẳng nối (x, y) với điểm mới có tọa độ (x+dx, y+dy). Tức lệnh này cũng
tương đương với lệnh lineto(getx()+dx, gety()+dy), trong đó getx() và gety()
là hai hàm trả lại vị trí x, y hiện tại của con trỏ. Lệnh linerel sau khi thực
hiện xong sẽ đặt con trỏ tại vị trí cuối của đường thẳng vừa vẽ.
Ví dụ 3 : Vẽ hình bao thư bằng 1 nét.
void baothu()
{
setbkcolor(1);
setcolor(YELLOW);
moveto(100, 100);
lineto(300, 100); lineto(300, 200); lineto(100, 200); lineto(100, 100);

188
Chương 6. Đồ họa và âm thanh

lineto(200, 50); lineto(300, 100);


}
• rectangle(x1, y1, x2, y2): Vẽ hình khung chữ nhật với góc trên bên trái có tọa
độ (x1, y1) và góc dưới bên phải có tọa độ (x2, y2).
• bar(x1, y1, x2, y2): Vẽ hình chữ nhật đặc. Màu khung được đặt bởi setcolor
và màu nền lẫn mẫu tô nền được đặt bởi lệnh setlinestyle. Mẫu nền ngầm
định là đặc và màu là getmaxcolor.
• bar3d(x1, y1, x2, y2, c, top): Vẽ hình trụ chữ nhật với đáy là (x1, y1, x2, y2)
và độ cao c, nếu top = 1 hình sẽ có nắp và nếu top = 0 hình không có nắp.
Ví dụ : Vẽ các hình khối chữ nhật với mầu nền và mẫu tô khác nhau.
void main()
{
int gdriver = DETECT, gmode;
initgraph(&gdriver, &gmode, "c:\\borlandc\\bgi");
int midx = getmaxx() / 2;
int midy = getmaxy() / 2;
for (int i=SOLID_FILL; i<USER_FILL; i++)
{
setfillstyle(i, i);
bar3d(midx-50, midy-50, midx+50, midy+50, 100, 0);
getch();
}
closegraph();
}

Ghi chú: để xoá điểm hoặc đường ta vẽ lại điểm hoặc đường đó bằng màu nền hiện
tại. Để biết màu nền hiện tại ta sử dụng hàm getbkcolor().

4. Các thuộc tính về đường (kiểu đường, độ rộng)


• setlinestyle(style, pattern, width): đặt các thuộc tính về đường vẽ, trong đó
style là kiểu đường, pattern là mẫu tô và width là độ đậm của đường vẽ. Các
thuộc tính này được giải thích bên dưới.
• getlinesettings(struct linesettingstype *info): Lấy các thuộc tính về đường

189
Chương 6. Đồ họa và âm thanh

vẽ hiện tại cho vào biến được trỏ bởi info.


• Kiểu của biến chứa các thuộc tính đường vẽ:
struct linesettingstype {
int linetsyle;
int upattern;
int thickness;
}
• Các hằng số qui định các kiểu đường (style):
style: SOLID_LINE = 0
DOTTED_LINE = 1
CENTER_LINE = 2
DASHED_LINE = 3
USERBIT_LINE = 4, // Kiểu đường do NSD định nghĩa
• pattern: Do NSD định nghĩa theo 2 byte cho một đường. Chỉ có tác dụng khi
style = 4.
• Các hằng số qui định độ đậm (độ dày) của đường (width):
NORM_WIDTH = 1
THICK_WIDTH = 3

Ví dụ 4 :
void netve()
{
char *lname[] = {"Duong lien net", "Duong cham cham",
"Duong trung tam", "Duong dut net", "Duong do NSD dinh nghia" };
int style, midx, midy, mauNSD;
midx = getmaxx() / 2; midy = getmaxy() / 2;
// Mẫu đường được định nghĩa bởi NSD "0000000000000001"
mauNSD = 1;
for (style=SOLID_LINE; style<=USERBIT_LINE; style++) {
setlinestyle(style, mauNSD, 1);
line(0, 0, midx-10, midy);

190
Chương 6. Đồ họa và âm thanh

rectangle(0, 0, getmaxx(), getmaxy());


outtextxy(midx, midy, lname[style]);
line(midx, midy+10, midx+8*strlen(lname[style]), midy+10);
getch();
cleardevice();
}
}

5. Các thuộc tính về hình (mẫu tô, màu tô)


• setfillstyle(mẫu tô, màu tô): Đặt mẫu tô, màu tô
• setfillpattern(mẫu tô, màu tô): Định nghĩa mẫu tô.
• getfillsettings(struct fillsettingstype *info): Lấy mẫu tô hiện tại
struct fillsettingstype {
int pattern;
int color;
};
• getfillpattern(mẫu tô): Trả lại mẫu tô hiện do NSD định nghĩa. Là một con
trỏ trỏ đến mảng 8 kí tự. Sau đây là một số mẫu tô và các hằng tương
ứng
EMPTY_FILL 0
SOLID_FILL 1
LINE_FILL 2
LTSLASH_FILL 3
SLASH_FILL 4
BKSLASH_FILL 5
LTBKSLASH_FILL 6
HATCH_FILL 7
XHATCH_FILL 8
INTERLEAVE_FILL 9
WIDE_DOT_FILL 10
CLOSE_DOT_FILL 11

191
Chương 6. Đồ họa và âm thanh

USER_FILL 12
Ví dụ 5 : Đặt mẫu tô.
char caro[8] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
maxx = getmaxx();
maxy = getmaxy();
setfillpattern(caro, getmaxcolor());
// Tô màn hình theo mẫu
bar(0, 0, maxx, maxy);
getch();

6. Vẽ đa giác
• drawpoly(số đỉnh, vị trí đỉnh): Vẽ đường đa giác theo setlinestyle;
• fillpoly(số đỉnh, vị trí đỉnh): Vẽ hình đa giác đặc theo setfillstyle;
Vị trí đỉnh là con trỏ trỏ đến dãy các toạ độ, thông thường dùng mảng.
Để vẽ đa giác đóng phải đưa ra n+1 toạ độ trong đó toạ độ n = toạ độ 0.
Ví dụ 6 :
int poly[10];
poly[0] = 20; poly[1] = maxy / 2; // đỉnh thứ nhất
poly[2] = maxx - 20; poly[3] = 20; // đỉnh thứ hai
poly[4] = maxx - 50; poly[5] = maxy - 20; // đỉnh thứ ba
poly[6] = maxx / 2; poly[7] = maxy / 2; // đỉnh thứ tư
poly[8] = poly[0]; poly[9] = poly[1];
// vẽ đa giác
drawpoly(5, poly);

7. Vẽ đường cong
• arc(x, y, góc đầu, góc cuối, bán kính): Vẽ cung tròn có tâm (x, y) với các
góc và bán kính tương ứng.
• circle(x, y, bán kính): Vẽ đường tròn có tâm tại (x, y).
• pieslice(x, y, góc đầu, góc cuối, bán kính): Vẽ hình quạt tròn đặc với mẫu
hiện tại;
• ellipse(x, y, góc đầu, góc cuối, bkx, bky): Vẽ cung elip với tâm, các góc và

192

You might also like