High Performance Graphical Visitor Counter
Counter C++ is a compiled version of the popular graphical Counter script. Written in C++, it displays visitor counts using customizable digit images and executes significantly faster with solid file locking. Perfect for high-traffic websites that need reliable, eye-catching visitor tracking.
The C++ version of Counter offers dramatic performance improvements over the Perl version. As a compiled binary with optimized file locking and image generation, it handles concurrent requests efficiently while producing professional-looking graphical counters.
| Metric | Perl Version | C++ Version |
|---|---|---|
| Execution Time | ~100-200ms | ~5-15ms |
| Memory Usage | 3-6 MB | ~300 KB |
| Requests/Second | ~30 | ~500 |
| File Locking | Basic | Solid |
| Image Quality | Good | Excellent |
| Modification Ease | Easy (edit script) | Moderate (recompile) |
| File | Description |
|---|---|
counter.cpp |
C++ source code with GD library integration |
Makefile |
Compilation instructions with GD linking |
digits/ |
Sample digit images (0-9.gif) |
README |
Compilation and installation guide |
Executes 15-30x faster than Perl version. Handles 500+ requests per second.
Beautiful digit images created on-the-fly. Customizable styles and colors.
Advanced locking prevents count corruption under heavy concurrent access.
Use your own digit images or choose from included styles.
Uses only 300KB of memory compared to 3-6MB for Perl.
C++ type safety reduces runtime errors and crashes.
apt-get install libgd-dev or yum install gd-devel
counter.cpp, Makefile, and digits/ directory to your server.
counter.cpp and set DATA_FILE and DIGIT_PATH constants.
g++ -o counter counter.cpp -lgd or simply make
touch /var/www/data/counter.datchmod 666 /var/www/data/counter.dat
chmod 755 counter
http://yoursite.com/cgi-bin/counter
The GD Graphics Library is required for image generation. Most Linux distributions include it in their repositories. For older systems, you may need to compile GD from source.
#include <iostream>
#include <fstream>
#include <sys/file.h>
#include <unistd.h>
#include <gd.h>
#include <string>
using namespace std;
// Configuration - Edit these paths
const char* DATA_FILE = "/var/www/data/counter.dat";
const char* DIGIT_PATH = "/var/www/html/images/digits/";
int main() {
// Output HTTP header
cout << "Content-type: image/gif\n\n";
int count = 0;
// Open file for reading and writing
int fd = open(DATA_FILE, O_RDWR | O_CREAT, 0666);
if (fd == -1) {
return 1;
}
// Acquire exclusive lock
if (flock(fd, LOCK_EX) == -1) {
close(fd);
return 1;
}
// Read current count
ifstream infile(DATA_FILE);
if (infile.is_open()) {
infile >> count;
infile.close();
}
// Increment count
count++;
// Write new count
ofstream outfile(DATA_FILE, ios::trunc);
if (outfile.is_open()) {
outfile << count;
outfile.close();
}
// Release lock
flock(fd, LOCK_UN);
close(fd);
// Convert count to string
string countStr = to_string(count);
int digits = countStr.length();
// Load digit images and create composite
gdImagePtr images[10];
int digitWidth = 0, digitHeight = 0;
// Load first digit to get dimensions
string firstDigitPath = string(DIGIT_PATH) + "0.gif";
FILE* firstFile = fopen(firstDigitPath.c_str(), "rb");
if (firstFile) {
gdImagePtr tempImg = gdImageCreateFromGif(firstFile);
digitWidth = gdImageSX(tempImg);
digitHeight = gdImageSY(tempImg);
gdImageDestroy(tempImg);
fclose(firstFile);
}
// Create output image
gdImagePtr output = gdImageCreate(digitWidth * digits, digitHeight);
// Composite the digits
for (int i = 0; i < digits; i++) {
char digit = countStr[i];
string digitPath = string(DIGIT_PATH) + digit + ".gif";
FILE* digitFile = fopen(digitPath.c_str(), "rb");
if (digitFile) {
gdImagePtr digitImg = gdImageCreateFromGif(digitFile);
gdImageCopy(output, digitImg, i * digitWidth, 0, 0, 0,
digitWidth, digitHeight);
gdImageDestroy(digitImg);
fclose(digitFile);
}
}
// Output the image
gdImageGif(output, stdout);
gdImageDestroy(output);
return 0;
}
CC = g++
CFLAGS = -O2 -Wall
LIBS = -lgd
TARGET = counter
all: $(TARGET)
$(TARGET): counter.cpp
$(CC) $(CFLAGS) -o $(TARGET) counter.cpp $(LIBS)
clean:
rm -f $(TARGET)
install: $(TARGET)
cp $(TARGET) /usr/local/apache/cgi-bin/
chmod 755 /usr/local/apache/cgi-bin/$(TARGET)
.PHONY: all clean install
<img src="/cgi-bin/counter" alt="Visitor Counter">
<img src="<!--#exec cgi="/cgi-bin/counter"-->" alt="Hit Counter">
<div class="counter-display">
<p>You are visitor number:</p>
<img src="/cgi-bin/counter" alt="Visitor #" class="counter-img">
</div>
<style>
.counter-display {
text-align: center;
background: linear-gradient(to bottom, #1e3c72 0%, #2a5298 100%);
padding: 20px;
border-radius: 10px;
color: white;
}
.counter-img {
box-shadow: 0 4px 6px rgba(0,0,0,0.3);
border: 2px solid #fff;
border-radius: 5px;
}
</style>
<table border="3" bgcolor="#000000" cellpadding="10">
<tr>
<td align="center">
<font color="#00ff00" size="+1"><b>VISITORS</b></font><br>
<img src="/cgi-bin/counter" alt="Counter">
</td>
</tr>
</table>
Each digit (0-9) should be a separate GIF image with consistent dimensions:
C++ source code with GD library
Compilation automation
Sample digit images (0-9.gif)
Installation guide
/cgi-bin/counter?page=home could use home.dat, while /cgi-bin/counter?page=about uses about.dat. You'll need to parse the QUERY_STRING environment variable.