Graphics Programming
Graphics Programming
gramming
All Lines Are Not Same
Stylish Lines
Drawing and Filling Images
Patterns with A Difference
Why Use A bar( )?
Filling Regular and Non-Regular Shapes
Of Palettes and Colors
Outputting Text
Justifying Text
A Bit of Animation
System Metrics
Exercise
627
116 Let Us
# include "graphics.h"
main( )
{
int gd = DETECT, gm, x, y ;
int array[ ] = { 540, 220, 590, 270, 570, 320, 510,
320, 490, 270, 540,
220 } ;
x = getmaxx( ) ;
y = getmaxy( ) ;
setcolor ( WHITE ) ;
rectangle ( x / 30, y / 20, x / 5, y / 4 ) ;
outtextxy ( x / 30 + 15, y / 8 + 5, "Rectangle" ) ;
circle ( x / 2, y / 6, 75 ) ;
putpixel ( x / 2, y / 6, WHITE ) ;
Chapter 20: Graphics Programming 117
outtextxy ( x / 2 - textwidth ( "Circle" ) / 2, y / 6 +
10, "Circle" ) ;
drawpoly ( 6, array ) ;
outtextxy ( 515, 270, "Polygon" ) ;
getch( ) ;
closegraph( ) ;
restorecrtmode( ) ;
}
First thing that we need to do before we can carry out any drawing
activity is, switch over to the graphics mode. This is not simple,
since depending on the adapter and monitor that is installed on your
computer, only some of the several graphics modes may be
available to you. These modes have been given numbers. Out of all
the modes available, we would like to switch over to the one which
offers the best possible resolution.
118 Let Us
C
Did we say resolution? Well, the number of dots or picture elements
(pixels) available to us on the screen in the graphics mode, is known
as the resolution. The greater the number of dots, the higher the
resolution. Simply put, this means that more the dots available,
clearer would be our picture.
To switch over to the graphics mode that offers the best resolution
we need to call the function initgraph( ). It figures out the best
resolution and puts the number corresponding to that mode in the
variable gm. The gm number tells us which monitor we are using,
and its resolution, the number of video pages it supports and the
colors that are available.
The basic tools we’ll need for drawing shapes are functions like
putpixel( ), line( ), circle( ), ellipse( ), arc( ) and drawpoly( ). All
these functions have been used in our program. Their general form
is shown in Figure 20.1. Before drawing the rectangle we have used
two functions getmaxx( ) and getmaxy( ). These fetch the
maximum x and y coordinates for the chosen graphics mode.
120 Let Us
Function Meaning
Figure 20.1
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
main( )
{
int gd = DETECT, gm ;
char msg[80] ;
C
lineto ( 300, 350 ) ; /* draws a line up to the point
*/
getch( ) ;
closegraph( ) ;
restorecrtmode( ) ;
}
This program draws three lines. The first line has been drawn using
the usual line( ) function. The second one has been drawn using the
moveto( ), lineto( ) functions. Note that for drawing this line we
have reached our starting point (300, 50) by calling the moveto( )
function and then drawn a line up to (300, 350) using the lineto( )
function. This shifts the C.P. to (300, 350). The third line is drawn
Chapter 20: Graphics Programming 123
by first shifting the C.P. from its current position by a relative
distance of 200 pixels to the right and 300 pixels up using the
moverel( ) function. Next the line is drawn using the function
linerel( ), once again using the relative distances.
Stylish Lines
So far we have drawn only solid lines. However, situations may
demand to draw lines with other line styles. For example, we may
use dashed lines to indicate hidden edges of an object, or center
lines to indicate center lines of a circle, and so on. Turbo C provides
four different line styles to draw solid, dotted, center and dashed
lines. These styles can be used to draw either normal or thick lines.
It also permits us to use a line style created by us to draw the lines.
The first parameter specifies the type of line (solid, dashed, etc.).
The second parameter is applicable only if the line style is user-
defined. The third parameter specifies the line thickness. The
various line styles have been enumerated in ‘graphics.h’ as under:
0 Solid Line
1 Dotted Line
2 Center Line (alternating dashes and dots)
3 Dashed Line
4 User-defined Line
The thickness parameter can take the value 1 or 3. The former
corresponds to a line thickness of one pixel (normal), the latter to a
thickness of three pixels (thick). Let us now use this information to
draw lines of different styles.
# include "graphics.h"
main( )
124 Let Us
C
{
int gd = DETECT, gm, maxy, x, style ;
char str[40] ;
struct linesettingstype ls ;
maxy = getmaxy( ) ;
setcolor ( WHITE ) ;
outtextxy ( 10, 20, "Normal width" ) ;
x = 20 ;
for ( style = 0 ; style <= 4 ; style++ )
{
setlinestyle ( style, 0, 1 ) ;
if ( style == 0 )
getlinesettings ( &ls ) ; /* save line setting */
if ( style == 4 )
{
setlinestyle ( 4, 15, 1 ) ;
line ( x, 50, x, maxy - 50 ) ;
}
else
line ( x, 50, x, maxy - 50 ) ;
getch( ) ;
closegraph( ) ;
restorecrtmode( ) ;
}
C
After setting the style to solid and thickness to 1 we have saved the
current line settings in a linesettingstype structure by calling the
function getlinesettings( ). This function stores the style, pattern
and thickness in the linesettingstype structure which is defined in
‘graphics.h’ as follows:
struct linesettingstype
{
int linestyle ;
unsigned upattern ;
int thickness ;
};
# include "graphics.h"
main( )
{
int gd = DETECT, gm, maxx, maxy, x = 40, y = 40,
fst ;
char str[40] ;
char *pattern[ ] = {
"EMPTY_FILL", "SOLID_FILL",
"LINE_FILL", "LTSLASH_FILL",
"SLASH_FILL",
"BKSLASH_FILL", "LTBKSLASH_FILL",
Chapter 20: Graphics Programming 127
"HATCH_FILL", "XHATCH_FILL",
"INTERLEAVE_FILL",
"WIDE_DOT_FILL",
"CLOSE_DOT_FILL", "USER_FILL"
};
maxx = getmaxx( ) ;
maxy = getmaxy( ) ;
rectangle ( 0, 10, maxx, maxy ) ;
setcolor ( WHITE ) ;
outtextxy ( 175, 0, "Pre-defined Fill styles" ) ;
x = x + 150 ;
if ( x > 490 )
{
y = y + 150 ;
x = 40 ;
}
}
getch( ) ;
closegraph( ) ;
128 Let Us
C
restorecrtmode( ) ;
}
Figure 20.2
If we want, we can save the current fill pattern and current fill color
through statements given below:
struct fillsettingstype
{
int pattern ;
int color ;
};
If saved earlier, the fill pattern and the fill color can be restored
through a call to setfillstyle( ):
C
The first parameter is a pointer to a sequence of 8 bytes, with each
byte corresponding to 8 pixels in the pattern. Whenever a bit in a
pattern byte is set to 1, the corresponding pixel will be plotted. The
second parameter specifies the color in which the pattern would be
drawn.
# include "graphics.h"
main( )
{
int gd = DETECT, gm, maxx, maxy, x = 40, y = 40,
fst ;
char str[40] ;
char patterns[ ][8] =
{
{ 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
0x55 },
{ 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC,
0xCC },
{ 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F,
0x0F },
{ 0x00, 0x10, 0x28, 0x44, 0x28, 0x10, 0x00,
0x00 },
{ 0x00, 0x70, 0x20, 0x27, 0x24, 0x24, 0x07,
0x00 },
{ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
0x00 },
{ 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00,
0x00 },
{ 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E,
0x00 },
Chapter 20: Graphics Programming 131
{ 0x00, 0x00, 0x22, 0x08, 0x00, 0x22, 0x1C,
0x00 },
{ 0xFF, 0x7E, 0x3C, 0x18, 0x18, 0x3C, 0x7E,
0xFF },
{ 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00,
0x00 },
{ 0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42,
0x00 }
};
maxx = getmaxx( ) ;
maxy = getmaxy( ) ;
rectangle ( 0, 10, maxx, maxy ) ;
setcolor ( WHITE ) ;
outtextxy ( 175, 0, "User-defined Fill styles" ) ;
x = x + 150 ;
if ( x > 490 )
{
y = y + 150 ;
x = 40 ;
}
}
132 Let Us
C
getch( ) ;
closegraph( ) ;
restorecrtmode( ) ;
}
Next we have set the fill pattern and fill color by calling the function
setfillstyle( ). Then using this fill style and color we have filled the
rectangle using the floodfill( ) function. The other two rectangles
and their patterns have been constructed as in the last program.
# include "graphics.h"
main( )
{
int gd = DETECT, gm, maxx, maxy ;
char pattern[ ] = { 0x00, 0x70, 0x20, 0x27, 0x24,
0x24, 0x07, 0x00 } ;
setcolor ( WHITE ) ;
outtextxy ( 175, 0, "color shapes and patterns" ) ;
setcolor ( WHITE ) ;
rectangle ( 80, 150, 180, 250 ) ;
getch( ) ;
closegraph( ) ;
restorecrtmode( ) ;
}
Note that while using the floodfill( ) function one must make sure
that the right color is specified or else the function will seek a
boundary you don’t want.
134 Let Us
The following program draws an ellipse and a triangle and fills them
by calling the fillellipse( ) and fillpoly( ) functions. Next it draws
an overlapping triangle and circle and fills the intersecting and non-
intersecting areas by repeatedly calling the floodfill( ) function. The
parameters passed to fillellipse( ) include coordinates of the center,
x-radius and y-radius. The parameters passed to drawpoly( ) and
fillpoly( ) are same—the number of points used to build the
polygon and the base address of the array containing the coordinates
of these points.
# include "graphics.h"
main( )
{
int gd = DETECT, gm, maxx, maxy, x = 600, y =
450 ;
int array[ ] = { 350, 180, 400, 80, 450, 180, 350,
180 } ;
maxx = getmaxx( ) ;
maxy = getmaxy( ) ;
Chapter 20: Graphics Programming 135
rectangle ( 0, 20, maxx, maxy ) ;
setcolor ( WHITE ) ;
outtextxy ( 150, 10, "Fill Figures using different
functions" ) ;
ellipse ( x / 4, 10 * y / 35, 0, 360, 100, 50 ) ;
drawpoly ( 4, array ) ;
fillpoly ( 4, array ) ;
outtextxy ( 370, 200, "Polygon" ) ;
getch( ) ;
closegraph( ) ;
restorecrtmode( ) ;
136 Let Us
C
}
#include "graphics.h"
#include "stdlib.h"
main( )
{
int gd = DETECT, gm, i, j, x, y, color, startcolor,
height, width ;
struct palettetype palette ;
struct viewporttype vp ;
getpalette ( &palette ) ;
getviewsettings ( &vp ) ;
width = ( vp.right - vp.left ) / 16 ;
height = ( vp.bottom - vp.top - 20 ) / 16 ;
x=0;
y = 20 ;
Chapter 20: Graphics Programming 137
startcolor = 0 ;
while ( !kbhit( ) )
setpalette ( random ( 16 ), random ( 65 ) ) ;
setallpalette ( &palette ) ;
getch( ) ;
closegraph( ) ;
restorecrtmode( ) ;
}
C
variables color and startcolor. Once the screen is filled with 256
rectangles, using the setpalette( ) function we have changed the
color values. Which color number gets changed to what color value
is decided at random since we have generated both the numbers
using the random( ) function. The colors keep getting changed in a
while loop till we do not interrupt the process by pressing a key.
Once we hit a key the control goes outside the while loop,
whereupon we change all the colors to their original values (which
we have earlier saved in the palettetype structure by calling
getpalette( ) function) through the function setallpalette( ).
Note that we have not redrawn any of the rectangles. We have only
changed the color values in the palette. By doing so, all rectangles
on the screen which had the earlier color values are changed to
reflect the new color values in the palette.
Outputting Text
So far we have outputted text using the function outtextxy( ).
However, there is more to outputting text than what we have
covered. The following program would put the whole issue in the
right perspective.
# include "graphics.h"
main( )
{
int gd = DETECT, gm, x = 10, y, i, j ;
char str[ ] = "Fonts" ;
char *demo[ ] = {
"Default Font Demonstration" ,
Triplex Font Demonstration",
"Small Font Demonstration",
"Sansserif Font Demonstration",
"Gothic Font Demonstration",
Chapter 20: Graphics Programming 139
"Script Font Demonstration",
"Simplex Font Demonstration",
"Triplex Script Font Demonstration",
"Complex Font Demonstration",
"European Font Demonstration",
"Bold Font Demonstration"
};
setcolor ( WHITE ) ;
y = 30 ;
for ( j = 1 ; j <= 4 ; j++ )
{
settextstyle ( i, HORIZ_DIR, j ) ;
outtextxy ( 10, y, str ) ;
y += ( textheight ( str ) + 10 ) ;
}
settextstyle ( i, VERT_DIR, 0 ) ;
setusercharsize ( 2, 1, 3, 2 ) ;
outtextxy ( 10, y, str ) ;
getch( ) ;
clearviewport( ) ;
}
closegraph( ) ;
restorecrtmode( ) ;
}
140 Let Us
multx = 2 ; divx = 1 ;
multy = 3 ; divy = 2 ;
Justifying Text
Not only can we control the font, direction and point size of the text
that is drawn on the screen in the graphics mode, we can also
exercise control over its orientation (justification) with respect to
C.P. Justification of text simply means positioning it with reference
to C.P. Remember that each character occupies a block of pixels.
Using the settextjustify( ) function we can align this block
horizontally or vertically such that C.P. is at the top, center or
bottom of this block (for vertical justification) and to the left, center
or right of this block (for horizontal justification). The default
justification settings are LEFT_TEXT (for horizontal) and
TOP_TEXT (for vertical). This means the block of character(s)
would be to the left of C.P. and below it. The other settings and their
values as enumerated in the file ‘graphics.h’ are shown in Figure
20.3.
LEFT_TEXT 0 Horizontal
CENTRE_TEXT 1 Horizontal and Vertical
RIGHT_TEXT 2 Horizontal
BOTTOM_TEXT 0 Vertical
142 Let Us
C
TOP_TEXT 2 Vertical
Figure 20.3
The following program shows all possible combinations of vertical
and horizontal justification for displaying a string of text.
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
void cross ( int x, int y ) ;
main( )
{
int gd = DETECT, gm ;
int midx, midy, i, j ;
char msg[80] = "Hello, Good Morning" ;
char msg1[80], msg2[80] ;
Chapter 20: Graphics Programming 143
initgraph ( &gd, &gm, "c:\\tc\\bgi" ) ;
midx = getmaxx( ) / 2 ;
midy = getmaxy( ) / 2 ;
getch( ) ;
}
}
closegraph( ) ;
restorecrtmode( ) ;
}
C
{
line ( x - 20, y, x + 20, y ) ;
line ( x, y - 20, x, y + 20 ) ;
}
A Bit of Animation
Drawing images is all right, what if we want to move them on the
screen? This can be achieved through two functions getimage( )
and putimage( ). The former reads any specified image from the
screen, and the latter places it at a predetermined subsequent
location, giving the illusion of movement. The following program
shows how these functions can be used in tandem to move a ball on
the screen.
# include "graphics.h"
# include "alloc.h"
main( )
{
int gd = DETECT, gm, area, x = 25, y = 25, ch,
xdirn = 1, ydirn = 1 ;
int maxx, maxy ;
char *buff ;
setcolor ( WHITE ) ;
setfillstyle ( SOLID_FILL, RED ) ;
circle ( 50, 50, 25 ) ;
floodfill ( 50, 50, WHITE ) ;
while ( 1 )
{
if ( kbhit( ) )
{
ch = getch( ) ;
C
nosound( ) ;
xdirn *= -1 ;
}
getch( ) ;
closegraph( ) ;
restorecrtmode( ) ;
}
How come the same putimage( ) can sometimes draw the image
and at other times erase it? The value of the fourth argument
supplied to putimage( ) decides whether it would draw or erase.
The value of this argument and its significance is given in the Figure
20.4.
Memory Screen
XOR_PUT Present Present Erased
XOR_PUT Present Absent Drawn
OR_PUT Present Present Superimposed
OR_PUT Present Absent Superimposed
COPY_PUT Present Present Replaced
COPY_PUT Present Absent Replaced
148 Let Us
Figure 20.4
The variables xdirn and ydirn are used to change the trajectory of
movement of ball. Anytime enter key is hit the direction in which the
ball is traversing is reversed. Anytime the ball hits the boundary, the
sound( ) function is used to activate the speaker followed by
nosound( ) to stop the sound. delay( ) serves the purpose of letting
the speaker beep for sometime before it is shut out by nosound( ).
System Metrics
If we draw a line, by default it is drawn as a solid line in white color.
If we display text then by default it is drawn in DEFAULT_FONT,
horizontally with each character built out of a matrix of 8 x 8 pixels.
The text displayed, by default, is justified to the left horizontally and
to the top vertically. Likewise, if we draw a rectangle using a bar( )
function, it is filled with a default pattern in default color. The point
that I am trying to make is there are a lot of default values that the
graphics library functions assume. Can we not find all these default
settings through a program? We can, and that too in as simple a
manner as shown below:
#include <dos.h>
#include <math.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include “graphics.h”
char *fonts[ ] = {
"DefaultFont", "TriplexFont", "SmallFont",
Chapter 20: Graphics Programming 149
"SansSerifFont", "GothicFont",
"ScriptFont",
"SimplexFont", "TriplexScriptFont",
"ComplexFont", "EuropeanFont",
"BoldFont"
};
char *linestyles[ ] = {
"SolidLn", "DottedLn", "CenterLn",
"DashedLn", "UserBitLn"
};
char *fillstyles[ ] = {
"EmptyFill", "SolidFill", "LineFill",
"LtSlashFill", "SlashFill", "BkSlashFill",
"LtBkSlashFill", "HatchFill", "XHatchFill",
"InterleaveFill", "WideDotFill",
"CloseDotFill"
};
char *textdirect[ ] = {
"HorizDir", "VertDir"s
};
char *horizontal[ ] = {
"LeftText", "CenterText", "RightText"
};
char *vertical[ ] = {
"BottomText", "CenterText", "TopText"
};
struct pts
{
int x, y ;
};
150 Let Us
C
int gprintf ( int *xloc, int *yloc, char *fmt, ... ) ;
main( )
{
struct viewporttype viewinfo ;
struct linesettingstype lineinfo ;
struct fillsettingstype fillinfo ;
struct textsettingstype textinfo ;
struct palettetype palette, far *pal ;
float aspectratio ;
int maxx, maxy, maxcolors, errorcode, xasp, yasp,
low, high ;
getviewsettings ( &viewinfo ) ;
getlinesettings ( &lineinfo ) ;
getfillsettings ( &fillinfo ) ;
gettextsettings ( &textinfo ) ;
getpalette ( &palette ) ;
getaspectratio ( &xasp, &yasp ) ;
aspectratio = xasp / yasp ;
driver = getdrivername( ) ;
mode = getmodename ( gm ) ;
getmoderange ( gd, &low, &high ) ;
gm = getgraphmode( ) ;
maxcolors = getmaxcolor( ) + 1 ;
Chapter 20: Graphics Programming 151
pal = getdefaultpalette( ) ;
x = 20 ;
y = 30 ;
C
gprintf ( &x, &y, "Current fill color: %d", fillinfo.color
);
gprintf ( &x, &y, "Current font: %s", fonts[
textinfo.font ] ) ;
gprintf ( &x, &y, "Text direction: %s", textdirect[
textinfo.direction ] ) ;
gprintf ( &x, &y, "Character size: %d",
textinfo.charsize ) ;
gprintf ( &x, &y, "Horizontal justify: %s", horizontal[
textinfo.horiz ] ) ;
gprintf ( &x, &y, "Vertical justify: %s", vertical[
textinfo.vert ] ) ;
gprintf ( &x, &y, "Palette size: %d", getpalettesize( )
);
getch( ) ;
closegraph( ) ;
restorecrtmode( ) ;
}
Function Description
C
getdefaultpalette( ) Gets information about the palette initi-
alised by the driver during initgraph( ).
In this program the text has been outputted on the screen using the
user defined function gprintf( ). This function works similar to
printf( ) except that it is capable of displaying output in graphics
mode. The advantage of this function is that it can collect a variable
number of arguments. Each time it is called we have passed to it the
position where the text is to be outputted on the screen, the format
string and a list of variables whose values are to be printed. The
macros va_start, va_list, va_end are defined in the file ‘stdarg.h’.
Out of these, the va_start macro is used to set up a pointer to the
format string. Next, the string to be outputted is written to the string
str[ ] by calling the vsprintf( ) function. The contents of the string
are then displayed on the screen using the usual outtextxy( )
function.
Chapter 20: Graphics Programming 155
Exercise
[A] State True or False:
C
(d) Write a program to draw a line interactively. Interactive line
drawing involves the following:
− Creating a plus shaped cursor.
− Managing the movement of the cursor using arrow keys,
Pgup, PgDn, Home and End.
− On positioning the cursor at a suitable place, if enter is hit
the point where the cursor was positioned should be treated
as the starting point of the line.
− Now the cursor should disappear and as arrow keys, PgUp,
PgDn, Home or End are hit the line drawing should begin.
− For every key hit the earlier line should get erased and a
new one should get drawn.
− Line should be made permanent when Enter key is hit.
(e) Write a function to consttruct a button similar to the one that
you often see in Windows. To this function you should pass
size of the button, position of the button, color of the button,
the text to be displayed on it and the font of the text.