Keywords: BMP format | C/C++ programming | image processing | boolean matrix | monochrome image
Abstract: This article explains how to write BMP image files in pure C/C++ without external libraries, focusing on converting a boolean matrix to a monochrome image. It covers the BMP file format, implementation details, and provides a complete code example for practical understanding.
In algorithm development, there is often a need to output boolean matrices as image files for visualization purposes. The BMP (Bitmap) format is a simple and widely supported image format that can be implemented in pure C/C++ without external libraries. Based on the core knowledge of the BMP file format and practical code examples, this article details how to generate a monochrome BMP image from a boolean matrix.
Overview of the BMP File Format
The BMP file format consists of several key parts: the BITMAPFILEHEADER (file header), BITMAPINFOHEADER (info header), an optional color table, and the pixel data array. For monochrome images, a 24-bit per pixel RGB format or a 1-bit per pixel indexed format can be used. The 24-bit format is simpler, requiring no color table, with each pixel represented by three bytes for red, green, and blue components; white is RGB(255,255,255) and black is RGB(0,0,0). The file and info headers define basic properties such as size, pixel depth, and compression.
Implementing Conversion from Boolean Matrix to Monochrome BMP
Given a boolean matrix where true represents white pixels and false represents black pixels, we need to map the matrix to BMP pixel data. Implementation steps include: setting up the file and info headers, calculating image dimensions and padding bytes to ensure each row's byte count is a multiple of four, and writing pixel data in bottom-up order. For 24-bit BMP, each pixel is stored with three bytes in blue, green, red order.
C++ Code Example
#include <iostream>
#include <fstream>
#include <vector>
void writeBMP(const std::vector<std::vector<bool>>& matrix, const std::string& filename) {
int height = matrix.size();
int width = matrix[0].size();
int rowSize = (width * 3 + 3) & ~3; // Pad to multiple of 4 bytes
int fileSize = 54 + rowSize * height; // 54 bytes for headers
unsigned char header[54] = {0};
// Set BITMAPFILEHEADER
header[0] = 'B'; header[1] = 'M';
header[2] = fileSize & 0xFF; header[3] = (fileSize >> 8) & 0xFF; header[4] = (fileSize >> 16) & 0xFF; header[5] = (fileSize >> 24) & 0xFF;
header[10] = 54; // Offset to pixel data
// Set BITMAPINFOHEADER
header[14] = 40; // Info header size
header[18] = width & 0xFF; header[19] = (width >> 8) & 0xFF; header[20] = (width >> 16) & 0xFF; header[21] = (width >> 24) & 0xFF;
header[22] = height & 0xFF; header[23] = (height >> 8) & 0xFF; header[24] = (height >> 16) & 0xFF; header[25] = (height >> 24) & 0xFF;
header[26] = 1; // Planes
header[28] = 24; // Bits per pixel
header[30] = 0; // No compression
std::ofstream file(filename, std::ios::binary);
file.write(reinterpret_cast<char*>(header), 54);
unsigned char* imgData = new unsigned char[rowSize * height];
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
int index = i * rowSize + j * 3;
if (matrix[i][j]) { // true for white
imgData[index] = 255; // Blue
imgData[index + 1] = 255; // Green
imgData[index + 2] = 255; // Red
} else {
imgData[index] = 0;
imgData[index + 1] = 0;
imgData[index + 2] = 0;
}
}
// Padding bytes
for (int p = width * 3; p < rowSize; ++p) {
imgData[i * rowSize + p] = 0;
}
}
// Write pixel data bottom-up
for (int i = height - 1; i >= 0; --i) {
file.write(reinterpret_cast<char*>(imgData + i * rowSize), rowSize);
}
delete[] imgData;
file.close();
}
int main() {
std::vector<std::vector<bool>> matrix = {{true, false}, {false, true}};
writeBMP(matrix, "output.bmp");
std::cout << "Image generated successfully!" << std::endl;
return 0;
}
This code demonstrates a basic implementation, highlighting key aspects such as correct header setup, pixel order handling, and padding management. This approach allows flexible conversion of boolean data into visual images.
Conclusion
By deeply understanding the BMP file format and implementing it directly in C/C++, we can efficiently convert boolean matrices to monochrome images without external dependencies. This not only aids in algorithm debugging but also applies to simple graphical output scenarios. Mastering these fundamental techniques lays the groundwork for more advanced image processing tasks.