High color & True color
Trang 1High color & True color
Lưu Văn Minh
Email:vanminhluu@yahoo.com
gày nay,đồ họa độ phân giải cao và độ sâu màu lớn đang phát triển mạnh mẽ và trở nênquen thuộc Tuy nhiên trên nền DOS để hiển thị một bức ảnh với số lượng màu lớn(16 triệu màu) không phải là một việc dễ dàng Nếu bạn không có các drive hỗtrợ 16 - 24 - 32 bit màu thì bạn chỉ có thể hiển thị tối đa 256 màu, một con sốquá
ít so với số màu sắc trung thực của một bức ảnh mà hiện nay hầu như toànđược lưu trữ
với chuẩn 24 bit màu Vậy chúng ta làm thế nào để thiết lập đượcchế độ High Color & True Color
Cáccard HiColor và TrueColor dùng RAMDAC chip (chip chuyển đổi
digital/analog)chuyển trị số trong VRAM thành tín hiệu tương tự ra màn hình HiColor vàTrueColor thể hiện màu trực tiếp - nghĩa là bạn trực tiếp chỉ định trị Red -Green - Blue (RGB) cho mỗi pixel, không phải lấy các trị màu này từ một mảngpalette màu giới hạn Nói cách khác trị màu cho chúng ta biết trực tiếp cácthành phần RGB
- Mode15-bit cho phép thể hiện 32k màu, mỗi màu thể hiện như một trị 2-byte:
X R R R R RG G G G GB B B B B trong đó bitX không được dùng
- Mode16-bit cho phép thể hiện 64k màu, mỗi màu thể hiện như một trị 2-byte:
R R R R RG G G G G GB B B B B
trong modenày G chiếm 6 bit vì người ta cho rằng mắt người nhạy cảm với màu xanh lá câycó nhiều trong thiên nhiên
- Mode24-bit cho phép thể hiện 16 triệu màu, mỗi màu thể hiện như một trị 3-byte:
R R R R R R R RG G G G G G G GB B B B B B B B
Mode16-bit được gọi là chế độ High Color và mode 24-bit được gọi làchế độ True Color Một vài SuperVGA card có thêm chế độ 32-bitmàu và 64-bit màu, byte thêm gọi
là kênh anpha, lưu trị transparency, trị màutrong suốt khi phủ ảnh lên một ảnh khác
Bằngphục vụ 10h của ngắt 10h bạn chỉ có thể khởi tạo được các mode màn hình có sốmàu thấp (VGA BIOS) Nhưng thông qua các hàm phục vụ của VESA BIOS tôi muốngiới thiệu với các bạn một cách khởi tạo chế độ mà Card Video của bạn cho phép Cáchàm mở của VESA được gọi qua phục vụ mở 4Fh (AH = 4Fh) và chỉ số phục vụ controng AL
N
Trang 2Phục vụ con
Chức năng của phục vụ
00h Lấy các khả năng của vỉ SuperVGA 01h Lấy thông tin chế độ SVGA
02h Đặt chế độ video SuperVGA 03h
Lấy chế độ video hiện hành 04h Lưu trạng thái video SuperVGA 05h Đặt, lấy cửa sổ truy nhập RAM video
Kiểm tra các khảnăng của vỉ Super VGA
Trướckhi chạy trong chế độ nào đó bạn phải gọi hàm con 00h để có các khả năng của vỉSuperVGA đã cài đặt Với lời gọi hàm này số hiệu hàm và hàm con đặt trong AH vàAL, con trỏ Far trỏ đến vùng đệm 256K đặt trong cặp thanh ghi ES:DI
Cấu trúc đệm hàmcon 00h
04h Bản VESA, số hiệu bản chính 1 Byte
05h Bản VESA, số hiệu bản phụ 1 Byte
06h Con trỏ Far trỏ tới tên nhà sản xuất Pointer (4byte)
0Ah Cờ chỉ khả năng hiện thời không dùng Dword
0Eh Con trỏ Far trỏ tới danh sách các mode
hỗ trợ
Pointer
Đọc chế độ videoxác định
Lờigọi hàm này số hiệu hàm và hàm con đặt trong AH và AL, chế độ thích hợp đặttrong
CX, con trỏ Far trỏ đến vùng đệm đặt trong cặp thanh ghi ES:DI sẽ chứathông tin
02h Cờ chế độ cửa sổ truy nhập đầu tiên 1 Byte 03h Cờ chế độ cửa sổ truy nhập thứ hai 1 Byte 04h Khoảng tăng của hai của sổ (KB) 1 Word 06h Kích thước hai cửa sổ truy nhập (KB) 1 Word 08h Địa chỉ đoạn của cửa sổ thứ nhất 1 Word 0Ah Địa chỉ đoạn của cửa sổ thứ hai 1 Word 0Ch Con trỏ Far đến thủ tục đặt vùng nhìn
thấy trong hai cửa sổ truy nhập
Pointer
10h Số byte cần cho mỗi dòng điểm của RAM video
1 Word
Trang 312h Độ phân giải chiều ngang 1 Word
17h Chiều cao ma trận ký tự 1 Byte
19h Số bit cho mỗi điểm màn hình 1 Byte
1Ch Kích thước các khối bộ nhớ (Kb) 1 Byte
Đặt chế độ
AX = 4F02h
BX = mode
Trả lại
AL = 4Fh: Lỗi khởi tạo không thành công
AL = 00h: Thành công
Đặt cửa sổ truynhập
AX = 4F05h
BH = 0
BL = cửa sổ
DX = trang đặt của sổ
Trả lại
AL = 4Fh: Lỗi
AL = 00h: Thành công
Tìm chế độ cầnkhởi tạo
Chúngta đã có các hàm cần thiết để xây dựng chương trình Vấn đề đặt ra bây giờ làvới chế độ nào ta khởi tạo được chế độ với số bit màu mà ta cần
Ta cóhàm con 01h trả về độ phân giải của màn hình và số bit cho mỗi pixel Vậy ta cóthể
sử dụng hàm này để tìm mode cần tìm
Đầutiên ta lấy thông tin về các mode được hỗ trợ bởi Card đồ họa và lưu lại Khita cần mode có độ phân giải XxY và n bit cho mỗi pixel ta duyệt lần lượt cácmode đã lưu lại, nếu giá trị trả về độ phân giải và số bit cho mỗi pixel saulời gọi hàm con 01h trùng với các giá trị ta cần thì đấy chính là mode cần tìm
Vẽ một điểm
Ta vẽmột điểm có toạ độ (X, Y) thông qua địa chỉ phân đoạn A000h qua 65535 byte:
Trang 4địachỉ thực = (X + Y * Độ phân giải chiều ngang) * Số byte mỗi pixel;
Vìgiới hạn trong 65535 byte truy nhập nên ta phải xác định xem điểm đó thuộctrang nào trang= địa chỉ thực div FFFFh
ĐặtBL = trang rồi gọi hàm con 05h
sau đó taghi trực tiếp vào bộ nhớ
Sauđây là unit Graph32.pas dùng để khởi tạo đồ họa High Color được viết trên
nềnPascal Trong unit này chỉ có một thủ tục đồ họa cơ bản đó là vẽ một điểm ramàn hình, nhưng tin chắc rằng kết hợp với một số kiến thức cơ bản về đồ họa(chẳng hạn như
bài viết "Tự làm lấy đồ họa máy tính" của tácgiả Nguyễn Xuân Huy đã được đăng trên
các số trước) bạn có thể xây dựng đượcmột thư viện đồ họa mạnh, có thể giải quyết được nhiều vấn đề mà unit Graph củaPascal không làm được
unit Graph32;
interface
type
NullString = array [0 255] of Char;
ModeList = array [1 3277] of Word;
SVGAInformation = record
Signature: array [1 4] of Char;
Version: Word;
OEMStringPtr: ^NullString;
Capabilities: LongInt;
VideoModePtr: ^ModeList;
TotalMemory: Integer;
OEMSoftwareRev: Integer;
OEMVendorNamePtr: Pointer;
OEMProductNamePtr: Pointer;
OEMProductRevPtr: Pointer;
Reserved: array [1 222] of Byte;
OEMData: array [1 256] of Byte;
end;
SVGAMode = record
ModeAttributes: Word;
WinAAttributes: Byte;
WinBAttributes: Byte;
WinGranularity: Integer;
WinSize: Word;
WinASegment: Word;
WinBSegment: Word;
WinFunctionPtr: procedure;
BytesPerScanLine: Integer;
Trang 5XResolution: Integer;
YResolution: Integer;
XCharSize: Byte;
YCharSize: Byte;
NumberOfPlanes: Byte;
MemoryModel: Byte;
BankSize: Byte;
NumberOfImagePages: Byte;
Reserved1: Byte;
RedMaskSize: Byte;
RedFieldPosition: Byte;
GreenMaskSize: Byte;
GreenFieldPosition: Byte;
BlueMaskSize: Byte;
BlueFieldPosition: Byte;
RsvdMaskSize: Byte;
RsvdFieldPosition: Byte;
DirectColorModeInfor: Byte;
PhysicalBasePtr: Pointer;
OffScreenMemOffse: Pointer;
OffScreenMemSize: Integer;
Reserved: array [1 206] of Byte;
end;
var
VesaInfor: SVGAInformation;
VesaModeInfor: SVGAMode;
MaxX, MaxY: Word;
BitPerPixel: Byte;
Seg_, Ofs_: Word;
BytePerPixel: Word;
BytePerLine: Integer;
x_: Word;
P, PO: Word;
DP: Byte;
function GetVesaInfor: Boolean;
function GetModeInfor(Mode: Word): Boolean; function FindMode(x, y: Word; b: Byte): Word; function InitGraph(x, y: Word; b: Byte): Boolean; procedure PutPixel(x, y: Word; r, g, b: Byte); function CloseGraph: Boolean;
implementation
function GetVesaInfor;
var
ReturnCode: Word;
begin
asm
Trang 6mov ax, Seg VesaInfor;
mov es, ax;
mov di, Offset VesaInfor;
mov ax, 4F00h;
int 10h;
mov ReturnCode, ax;
end;
if ReturnCode = $4f then GetVesaInfor := True
else GetVesaInfor := False;
end;
function GetModeInfor;
var
ReturnCode: Word;
begin
asm
mov ax, Seg VesaModeInfor;
mov es, ax;
mov di, Offset VesaModeInfor;
mov ax, 4F01h;
mov cx, Mode;
int 10h;
mov ReturnCode, ax;
end;
High color & True color
Lưu Văn Minh
(Tiếp theo sốtrước)
Email: vanminhluu@yahoo.com
function GetModeInfor;
var
ReturnCode: Word;
begin
asm
mov ax, Seg VesaModeInfor;
Trang 7mov es, ax;
mov di, Offset VesaModeInfor;
mov ax, 4F01h;
mov cx, Mode;
int 10h;
mov ReturnCode, ax;
end;
if ReturnCode = $4f then GetModeInfor:= True else GetModeInfor := False;
end;
function FindMode;
var
i: Word;
begin
i := 0;
repeat
Inc(i);
GetModeInfor(VesaInfor.VideoModePtr^[i]); until ((VesaModeInfor.XResolution = x)and (VesaModeInfor.YResolution = y)and
(VesaModeInfor.MemoryModel = b))or
(VesaInfor.VideoModePtr^[i] =65535);
FindMode := VesaInfor.VideoModePtr^[i];
Trang 8function InitGraph;
var
Mode: Word;
begin
Mode := FindMode(x, y, b);
if Mode = 65535 then
begin
InitGraph := False;
Writeln('Khong khoi tao duoc');
Writeln('Hay chon mode khac');
Readln;
Halt;
end
else
begin
InitGraph := True;
MaxX := VesaModeInfor.XResolution;
MaxY := VesaModeInfor.YResolution;
BitPerPixel := b;
BytePerPixel := BitPerPixel div 8;
if BitPerPixel = 15 then BytePerPixel:= 2;
BytePerLine :=VesaModeInfor.BytesPerScanLine;
Trang 9DP := 32 divVesaModeInfor.WinGranularity; P:=0; PO:=P;
asm
mov ax, 4F02h
mov bx, Mode
int 10h
end;
end;
end;
procedure page;assembler;
Asm
Mov ax, P
Mov cl, DP
Shr ax, cl
Mov ax, 4f05H
Mov bx, 0
Mov dx, P
Int 10h
end;
procedure Mem_;
begin
Mem[$A000: x_] := Mem[Seg_: Ofs_];
end;
Trang 10procedure RGB(r, g, b: LongInt; varColor: LongInt); begin
Case BitPerPixel of
32, 24: Color := (r shl 16) or (g shl8) or b;
16: Color := (r shr 3 shl 11) or (gshr 2 shl 5) or b shr 3; 15: Color := (r shr 3 shl 10) or (gshr 3 shl 5) or b shr 3; end;
end;
procedure Putpixel;
label
Lap, Page1, Page2;
var
Color: LongInt;
begin
RGB(r, g, b, Color);
Seg_ := Seg(Color);
Ofs_ := Ofs(Color);
Asm
Mov ax, x
Mul BytePerPixel
Mov x, ax
Mov ax, y
Mul BytePerPixel
Trang 11Mul MaxX
Ađ ax, x
Mov x_, ax
Adc dx, 0
Cmp dx, PO
Je Page1
Mov P, dx
Mov bx, P
Mov PO, bx
Call Page
Page1:
Mov cx, BytePerPixel Lap:
Call Mem_
Inc Ofs_
Ađ x_, 1
Jae Page2
Adc P, 0
Mov bx, P
Mov PO, bx
Push cx
Call Page
Pop cx
Trang 12Loop Lap
End;
End;
function CloseGraph;
begin
asm
Mov ax, 0003h;
int 10h;
end;
end;
BEGIN
GetVesaInfor;
END.
style='font-size:10.0pt;'> Ví dụ để khởi tạo đồ họa640x480x16-bit màu và vẽ ra màn hình nền giống màn hình nền của Window2000 taviết chương trình sau:
uses
Graph32;
var
x, y: Integer;
BEGIN
{Khởi tạo chế độ đồ họa 640x480x16 bit}
InitGraph(640, 480, 16);
for x := 0 to 640 do
Trang 13for y := 0 to 480 do
PutPixel(x, y, 56, 112, 168);
{r = 56; g = 112; b = 168}
Readln;
{Đóng chế độ đồ họa}
CloseGraph;
END.
Để minh họa chi tiết hơn cho việcsử dụng unit này, xin giới thiệu với các bạn unit Bmp.pas dùng để đọc ảnhBitmap (*.bmp) 24-bit màu, không nén
Unit BMP;
interface
uses Graph32;
type
TBitmapHeader = record
bfType: array [1 2] of Char;
bfSize: LongInt;
bfReserve: array [1 4] of Char;
bfOffBits: LongInt;
end;
TBitmapInfoHeader = record
Size: LongInt;
Width: LongInt;
Height: LongInt;
Planes: Word;
Trang 14BitCount: Word;
Compression: LongInt;
SizeImage: LongInt;
XPelsPerMeter: LongInt;
YPelsPerMeter: LongInt;
ClrUsed: LongInt;
ClrImportant: LongInt;
end;
TColor = record
b, g, r: Byte;
end;
procedure LoadBMP(PosX, PosY: Integer;FileName: string); implementation
procedure LoadBMP;
var
Header: TBitmapHeader;
Info: TBitmapInfoHeader;
Size, Size_: Word;
f: file;
Dl: array [0 5000] of TColor;
x, y: Integer;
Color: TColor;
begin
Trang 15Assign(f, FileName);
{$I-}
Reset(f, 1);
if IOResult <> 0 then Exit;
{$I+}
BlockRead(f, Header, SizeOf(Header));
BlockRead(f, Info, SizeOf(Info));
if (Header.bfType <> 'BM') or(Info.BitCount <> 24) then begin
Close(f);
Exit;
end;
Size := Info.Width * 3;
if Info.Width mod 2 <> 0 thenSize := Size + 1;
Seek(f, Header.bfOffBits);
for y := Info.Height - 1 downto 0 do
begin
BlockRead(f, Dl, Size);
for x := 0 to Info.Width - 1 do
PutPixel(PosX + x, PosY + y,Dl[x].r, Dl[x].g, Dl[x].b); end;
Close(f);
end;
Trang 16END.
Ví dụ để đọc file "Flower.bmp"bạn viết chương trình sau:
uses
Graph32, BMP;a
BEGIN
InitGraph(640, 480, 16);
{Load ảnh Flower.bmp, toạ độ đỉnh tráitrên của ảnh (0, 0)}
LoadBMP(0, 0, 'Flower.bmp');
Readln;
CloseGraph;
END.
Dokhuôn khổ bài báo nên unit Bmp.pas này chỉ đọc được các ảnh Bitmap 24-bit màuvà ở chế độ không nén, mong các bạn thông cảm Nếu bạn nào muốn có được unitBmp đầy đủ
có thể đọc được nhiều dạng ảnh bitmap hơn hãy liên hệ với toà soạnhoặc với tác giả qua email