04. Point
Dated: 12-04-2025
Pixel
The smallest dot illuminated that can be seen on screen.
This is also called the picture element
.
Picture
Composition of pixels makes picture that forms on whole screen.
Resolution
Resolution is defined as number of rows (scan lines) from top to bottom, times, number of pixels from left to right.
Example
Mode 19 uses 200 scan lines, each with 320 pixels.
Therefore, resolution
is \(320 \times 200\).
Higher resolution
means more clear, pleasing image quality, alongside more memory required for that image and less staircase effect
.
Text and Graphics Modes
Video cards
1 are responsible to send picture data to monitor each time it refresh itself.
They support both, text
and graphics
modes, each having their own refresh rates, resolutions and colors.
Examples from VGA
1
- \(25 \times 80\) with \(16\) colors support (
text mode
). - \(320 \times 200\) with \(8\) colors support (
graphics mode
). - \(640 \times 480\) with \(16\) colors support (
graphics mode
). - \(640 \times 480\) with \(8, 16, 24, 32\) colors support (
graphics mode
). - \(800 \times 600\) with \(8, 16, 24, 32\) colors support (
graphics mode
).
Text and Graphics
The amount of memory
required representing a character
on screen in text mode
and a pixel in graphics mode
varies from mode to mode.
Mode No. | Type | Resolution | Memory Required |
---|---|---|---|
\(3\) | Text | \(80 \times 25\) | \(2\) bytes per char |
\(6\) | Graphics | \(640 \times 200\) | \(1\) bit per pixel |
\(7\) | Text | \(80 \times 25\) | \(2\) bytes per char |
\(18\) | Graphics | \(640 \times 480\) | \(1\) bit per pixel |
\(19\) | Graphics | \(320 \times 200\) | \(1\) byte per pixel |
In mode \(6\), each pixel displayed onto the screen occupies \(1\) bit
memory in VDU
(Video Display Unit
) memory
. Therefore, only 2 colors can be used for this pixel.
How Text Displays
Text mode
requires \(2\) bytes
, first one for the ASCII
value of the character
to be printed and second one is the attribute byte
, controlling the colors of it.
The character generator
, found in VBIOS
or video cards
1 is responsible for translating the ASCII
value into a character
to be drawn on screen.
Example
CGA
1 uses \(8\)scan lines
, each with \(8\) pixels.MA
1 uses \(9\)scan lines
, each with \(14\) pixels.
Therefore, MA
1 has better resolution for characters
.
The character generator
for MA
1 and CGA
1 is located in ROM
meanwhile for EGA
1 and VGA
,1 it is loaded into plane 2
of VRAM
1 which makes it easy to load custom character sets
.
Multiple character sets
(\(4\) for EGA
1 and \(8\) for VGA
1) can be loaded at the same time.
A set of BIOS
services is available for easy loading of character sets
, each containing \(256\) characters
.
Either one or two character sets
may be active and \(1\) bit
inside attribute byte
determines which character set
to use for the current character
.
ROM-BIOS
service allows us to select the active character set
.
EGA
1 uses \(8 \times 14\) and VGA
1 uses \(9 \times 16\) resolution for each character
.
Custom character sets
can also be loaded using BIOS VDU
services.
The advantage of graphics mode
is that we can draw characters
with different shapes, styles, size etc. because this mode draws very differently.
Text Mode Colors
Let's break down the attribute byte
.
- \(7\) - Blinking component
- \(6\) -
Red
component ofbackground color
- \(5\) -
Green
component ofbackground color
- \(4\) -
Blue
component ofbackground color
- \(3\) -
Intensity
component offoreground color
. - \(2\) -
Red
component offoreground color
- \(1\) -
Green
component offoreground color
- \(0\) -
Blue
component offoreground color
Graphics Mode Colors
There are few differences in comparison to text mode
.
- There is no blinking.
- The pixel is a discrete dot of
color
(there is no background or foreground). - The way colors are generated for different
video cards
1 can drastically differ.
Colors in VGA
1
IBM introduces VGA
1 in 1987
.
It has \(4\) color planes
.
- Red
- Green
- Blue
- Intensity
Each is associated with \(1\) bit
.
Following are the ways to write pixel on screen.
- Using
video BIOS services
to write pixel. - Accessing
memory
andregisters
directly to write pixel on screen. - Using library functions to write pixel on screen.
Practical Approach to Write Pixel on Screen
Using Video BIOS Service
- Settings desired
video mode
. - Using
BIOS service
to setcolor
of a screen pixel. - Calling
BIOS
interrupt to executing pixel writing on the screen.
Source Code
asm (
mov ah, 0 ; service number
mov al, 13h ; mode number from 0 to 19
int 10h ; video bios interrupt number, sets the mode
);
Source Code for Writing Pixel
asm (
mov ah, 0ch ; service number
mov al, color_num ; color number, ranging 0 - 255
mov bh, 0 ; page number (0 is default), this mode only supports one page
mov cx, row_num
mov dx, column_num
int 10h ; BIOS interrupt
);
Writing Pixel by Accessing Memory Directly
Steps
- Set
video mode
by usingvideo BIOS routine
. - Set any
pointer
to thevideo graphics memory address
(0x0A0000
). - Write
color value
.
Source Code
asm(
mov ax,0a000h
mov ds,ax ; segment address changed
mov si,10 ; column number
mov [si], color_num
; Formula: row * 320 + column in si to control position
);
Writing Character Directly on Screen
Steps
- Use
BIOS service
to settext mode
(mode number \(3\)). - Set
pointer
to text memory address0x0b8000
.
Source Code
asm (
mov ax, 0b8000h
mov ds, ax
mov si, 10 ; column number
mov [si], 'a' ; character to write
);
Using Library Functions
These graphics library functions use BIOS routines
or use direct memory access drivers
to draw pixel on screen.
#include <graphics.h> // Borland Graphics Interface
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
int gdriver = DETECT
int gmode;
int errorcode;
// Initialize graphics mode
initgraph(&gdriver, &gmode, "");
// Read the result of initialization
errorcode = graphresult();
if (errorcode != grOk) {
// An error occurred
printf("Graphics error: %s\n", getch());
exit(1);
}
// Draw a pixel at (10, 10) with blue color
putpixel(10, 10, BLUE);
// Pause the screen
getch();
// Close the graphics mode
closegraph();
return 0;
}
Discussion on Pixel Drawing Methods
- BIOS routines are built-in VGA functions but are slow.
- Drawing shapes (triangles, rectangles, circles) using pixels via BIOS is slower than direct memory access (DMA).
- Direct Memory Access (DMA) is faster and bypasses BIOS, but it's mainly convenient in mode 13h.
- Library functions (provided by companies) are the easiest and fastest, as they are optimized and come with special drivers.
Drawing Pixel in Microsoft Windows
Windows does not allow access to BIOS
or directory memory
that easily and we have to rely on library functions (APIs) which requires knowledge of Windows GDI
(Graphics Device Interface
).
Source Code Example
// a.cpp : Defines the entry point for the application.
#include "stdafx.h"
#include "resource.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_A, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow)) {
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_A);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
// FUNCTION: MyRegisterClass()
// PURPOSE: Registers the window class.
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_A);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = (LPCSTR)IDC_A;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
// FUNCTION: InitInstance()
// PURPOSE: Saves instance handle and creates main window
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);
if (!hWnd) {
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
// FUNCTION: WndProc()
// PURPOSE: Processes messages for the main window.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message) {
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId) {
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
{
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
RECT rt;
GetClientRect(hWnd, &rt);
int j = 0;
// To draw some pixels of RED colour on the screen
for (int i = 0; i < 100; i++) {
SetPixel(hdc, i + j, 10, RGB(255, 0, 0));
j += 6;
}
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}