C + + reads and writes bmp diagram and displays images

Preparatory knowledge

bitmap-file header

typedef struct tagBITMAPFILEHEADER {
        WORD bfType;          //File type, must be BM(1-2 bytes)
        DWORD bfSize;         //File size, in bytes (3-6 bytes, low order first)
        WORD bfReserved1;     //Reserved word, must be 0 (7-8 bytes)
        WORD bfReserved2;     //Reserved word, must be 0 (9-10 bytes)
        DWORD bfOffBits;      //The starting position of bitmap data relative to the bitmap (11-14 bytes, low order first)
} BITMAPFILEHEADER;

Bitmap header

typedef struct tagBITMAPINFOHEADER{
	    DWORD biSize;        //Number of bytes occupied by this structure (15-18 bytes)
	    LONG biWidth;        //Width of bitmap (19-22 bytes)
	    LONG biHeight;       //Height of bitmap (23-26 bytes)
	    WORD biPlanes;       //The level of the target device must be 1 (27-28 bytes)
	    WORD biBitCount;     //The number of bits required for each pixel must be one of 1 (two color), 4 (16 color), 8 (256 color), 16 (high color) or 24 (true color) (29-30 bytes)
	    DWORD biCompression; //Bitmap compression type, which must be one of 0 (uncompressed), 1(BI_RLE8 compression type) or 2(BI_RLE4 compression type) (31-34 bytes)
	    DWORD biSizeImage;   //Size of bitmap (4-byte alignment), in bytes (35-38 bytes)
	    LONG biXPelsPerMeter;//Bitmap horizontal resolution, pixels per meter (39-42 bytes)
	    LONG biYPelsPerMeter;//Bitmap vertical resolution, pixels per meter (43-46 bytes)
	    DWORD biClrUsed;     //The number of colors in the color table actually used by the bitmap (47-50 bytes)
	    DWORD biClrImportant;//Number of important colors in bitmap display (51-54 bytes)

fopen

FILE * fopen(const char * path,const char * mode);

Path is the bmp image path of string type; mode reading mode. Next time, use "rb" to read and write. Open a binary file to allow reading and writing data. The file must exist.

fseek

int fseek(FILE *stream, long offset, int fromwhere);

Function to set the position of the file pointer stream, which points to the position offset by offset bytes based on from where.

fread

size_t fread ( void *buffer, size_t size, size_t count, FILE *stream);

Read count units from stream, size bytes, and store them in buffer.

SetPixel

Function function: this function sets the pixel at the specified coordinate to the specified color
Function prototype: colorref setPixel (HDC, HDC, int x, int y, colorref crcolor);
Parameters:
hdc: device environment handle.
10: Specifies the X-axis coordinates of the point to set, in logical units
Y: Specifies the y-axis coordinates of the point to be set, in logical units.
crColor: Specifies the color to use to draw the point.
Return value: if the function is executed successfully, the return value is the RGB color value of the pixel set by the function. This value may be different from the color specified by crColor. Sometimes this happens because no real match is found for the specified color; if the function fails, the return value is C1.

code

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<Windows.h>
using namespace std;

int main()
{
	//Read image file
	FILE* fp = fopen("1.bmp", "rb");//Read in file
	if (!fp) {
		cout << "File not opened!\n";
		exit(0);
	}
	long width, height;
	BITMAPFILEHEADER fileHead;//bitmap-file header 
	fread(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);//Read the BITMAPFILEHEADER information from fp to fileHead, and move the pointer of fp at the same time
	BITMAPINFOHEADER infoHead;//Bitmap header
	fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);//Read the BITMAPINFOHEADER information from fp to infoHead, and move the pointer of fp at the same time
	width = infoHead.biWidth;
	height = infoHead.biHeight;

	cout << "width = " << width << endl << "height = " << height << endl;

	char* bmpBuf = new char[width * height * 3];
	fseek(fp, long(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)), 0);//Go to start position
	fread(bmpBuf, sizeof(char), width * height * 3, fp);
	fclose(fp);

	//Write file information
	FILE* outFile = fopen("show.bmp", "wb");//output file
	fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, outFile);
	fwrite(&infoHead, sizeof(BITMAPINFOHEADER), 1, outFile);
	char* tmp = bmpBuf;
	for (int j = 0;j < height;j++)
		for (int i = 0;i < width * 3;i++)
			fwrite(tmp++, 1, 1, outFile);
	fclose(outFile);

	//Display image
	HWND hwnd = GetForegroundWindow();//Window handle
	HDC hdc = GetDC(hwnd);//Drawing handle
	BYTE b, g, r, rgb;
	tmp = bmpBuf;
	for (int j = 0;j < height;j++) {
		for (int i = 0;i < width;i++) {
			b = *tmp++;
			g = *tmp++;
			r = *tmp++;
			SetPixel(hdc, i, 150 + height - j, RGB(r, g, b));
		}
	}
}

Running screenshot

Thinking & explanation

  1. The data of the bitmap file header and the bitmap information header of the image are read respectively. The bitmap information header structure contains the width and height information of the image. Therefore, biwidth and biheight are used to obtain the width and height of the image;
  2. Allocate space for BMP buf with the size of width * height * 3, because each pixel is composed of three RGB components;
  3. Since the bitmap file header and bitmap information header are read with fread, fp is also offset, and the offset length is sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER). Therefore, you need to use the fseek function to adjust fp to the initial position, and then you can read the corresponding data from fp into bmpBuf;
  4. When writing a file, use a temporary variable tmp to point to the header of BMP buf, and then write it successively. Note that the data in each line is width * 3, also because each pixel is composed of three RGB components;
  5. When displaying an image, use the HWND and HDC data types and GetForegroundWindow(), GetDC(HWND hwnd) functions in Windows.h to obtain the window and drawing handle, and then call the setPixel (HDC, HDC, int x, int y, colorref color) function to draw. When obtaining rgb data, the color information in each pixel in the file is B, G, R in order.

be careful

The image read should be a 24 bit bmp image, otherwise the program may not run.
Some bmp images saved by default may not be 24 bit. Just open the image in the "drawing" software in windows system, click Save as, and select 24 bit bitmap.

Keywords: C++ image processing

Added by chris davies on Wed, 22 Sep 2021 20:12:22 +0300