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:

FreeGLUT: Rectangle

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.