1. Overview
BGI (Borland Graphics Interface) provides an easy way for us to get our hands wet in the world of graphics programming. In this article, we’ll build and install an alternative implementation of BGI for Linux known as libgraph.
In addition, we’ll also discuss OpenGL as an alternative to libgraph.
2. Borland Graphics Interface (BGI)
BGI was a C/C++ graphics library for the Borland compilers. It was written for the DOS operating system in the 1980s. However, it was maintained until the Borland C++ 5.02 compiler.
The BGI library is accessible through graphics.h. In addition, it’s very straightforward to use because it has no support for 3D graphics and event handling.
2.1. libgraph
BGI was solely implemented for DOS. However, there is an open-source library called libgraph that implements BGI for Linux. It’s built on top of SDL (Simple DirectMedia Layer), which is a low-level multimedia library that provides an abstraction layer for hardware components.
libgraph isn’t as powerful as SDL itself. However, it’s very easy to use for learning purposes.
3. Setup
In this section, we’ll install libgraph alongside its dependencies. Unfortunately, on modern Linux systems, most libgraph dependencies are not widely available on the official package repositories.
Therefore, it’s going to be a bit of work to collect the required artifacts.
3.1. Dependencies
On Ubuntu 17.10 and previous versions, we can simply install the dependencies from the package repositories:
$ sudo apt install -y libsdl-image1.2 libsdl-image1.2-dev guile-1.8 \
guile-1.8-dev libsdl1.2debian libart-2.0-dev libaudiofile-dev \
libesd0-dev libdirectfb-dev libdirectfb-extra libfreetype6-dev \
libxext-dev x11proto-xext-dev libfreetype6 libaa1 libaa1-dev \
libslang2-dev libasound2 libasound2-dev build-essential
For Ubuntu 18.04+, we’ll add the Xenial Xerus (Ubuntu 16.04) repositories to the sources.list file:
# Binaries
$ echo "deb http://us.archive.ubuntu.com/ubuntu/ xenial main universe" | sudo tee -a /etc/apt/sources.list
# Sources
$ echo "deb-src http://us.archive.ubuntu.com/ubuntu/ xenial main universe" | sudo tee -a /etc/apt/sources.list
Now, let’s import the missing public keys to verify the integrity of the packages:
$ gpg --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 3B4FE6ACC0B21F32
Then, let’s update the package cache:
$ sudo apt update
Finally, let’s install the dependencies:
$ sudo apt install -y libsdl-image1.2 libsdl-image1.2-dev guile-2.0 \
guile-2.0-dev libsdl1.2debian libart-2.0-dev libaudiofile-dev \
libesd0-dev libdirectfb-dev libdirectfb-extra libfreetype6-dev \
libxext-dev x11proto-xext-dev libfreetype6 libaa1 libaa1-dev \
libslang2-dev libasound2 libasound2-dev
Once the dependencies are installed, we can now build libgraph.
3.2. Building libgraph
First, we’ll need to download libgraph:
$ curl -LO "http://download.savannah.gnu.org/releases/libgraph/libgraph-1.0.2.tar.gz"
Next, we extract the contents of the archive:
$ tar -xvf libgraph-1.0.2.tar.gz
Afterward, we cd into it and run configure:
$ cd libgraph-1.0.2/ && ./configure
Once all the checks are passed, the script creates a Makefile. Then, we simply build the sources:
$ make
Now, let’s install the libraries:
$ sudo make install
Finally, we copy the required libraries to /usr/lib as well:
$ sudo cp /usr/local/lib/libgraph.* /usr/lib
We copied the libraries to /usr/lib because it’s the system-wide shared libraries directory. Therefore, they are available to all the programs on the system.
In contrast, if we left the libraries in /usr/local/lib, we’ll need to provide additional configuration to the linker during the building process of our graphics program.
4. Using graphics.h
Now, we’re ready to include the <graphics.h> header file in our C/C++ source code. As an example, we’ll write a simple program to test this out:
#include <graphics.h>
int main(int argc, char** argv) {
int gd = DETECT, gm;
initgraph(&gd, &gm, NULL);
circle(180, 280, 80);
line(100, 150, 160*3, 150);
delay(10000);
closegraph();
return 0;
}
Let’s dig into this:
- gd is the graphics driver, which is automatically detected with the DETECT macro
- gm is the graphics mode, which will be set by libgraph automatically
- initgraph initializes the graphics system with the graphics driver
- circle renders a circle with the given geometry
- line renders a line with the given geometry
- delay prevents the running of further instructions for 10000 milliseconds or 10 seconds
- closegraph releases the resources and frees up memory
Usually, the program exits when the closegraph function is called.
5. Alternative: OpenGL
At this point, libgraph is very old. No matter how easy it is, over time, it will become more difficult to build it on Linux. Therefore, we can opt for other alternatives like OpenGL.
OpenGL is a graphics API that enables us to develop complex 2D and 3D applications. In contrast to libgraph, it has a steep learning curve. However, there are many learning resources available over the web.
5.1. FreeGLUT
A simpler way to get started with OpenGL is to use FreeGLUT. FreeGLUT is a cross-platform window management library with OpenGL context.
We install it from the official package repositories:
$ sudo apt install -y freeglut3 freeglut3-dev
Once installed, let’s write a simple program that draws a rectangle:
#include <GL/freeglut.h>
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_QUADS);
glVertex2f(-0.5f, -0.5f);
glVertex2f(0.5f, -0.5f);
glVertex2f(0.5f, 0.5f);
glVertex2f(-0.5f, 0.5f);
glEnd();
glFlush();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutCreateWindow("Baeldung on Linux Graphics");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Now, let’s build it:
$ gcc main.c -o demo -lglut -lGL
Finally, let’s test it out:
$ ./demo
The program creates a window with the given title and draws a rectangle with the given vertices:
In addition, the code also calls glutMainLoop, which waits for events and updates. Therefore, when we press the close button, it closes the window.
6. Conclusion
In this tutorial, we discussed how to build and install libgraph, which is an alternative BGI library for Linux. As an alternative to libgraph, we also looked at the OpenGL API through FreeGLUT.