This article is about what the bmp graphic format looks like. Although this is one of the simpler formats, due to the fact that there are many variations of this format, not all points are obvious. So, stop pouring water, let's get started.
Format structures
The bmp format (from the words BitMaP - bit map, or, in Russian, bit array) is an uncompressed (mostly) image that is quite easy to read and display in Windows OS, which has special API functions that help.
First, let's give a graphical representation of the data in bmp (picture taken from MSDN).
At the beginning there is a file header (BITMAPFILEHEADER). It is described as follows:
bfType determines the file type. Here he should be BM. If you open any BMP file in a text editor (or better yet, a hexadecimal editor), you will see that the first two characters are BM (from the word BitMap, as you probably already guessed).
bfSize is the size of the file itself in bytes. Strictly speaking, you should calculate it (which is recommended), but I set the file size incorrectly (though not on purpose :)) and there were no problems (ACDSee read without problems, my program worked), but I do not recommend you write it deliberately incorrectly , suddenly a conscientious program will appear that will compare this size with the real one and decide that it is not bmp, but something else. Ideally, all programs, in order to make sure that it is a real bmp and not a fake, should, firstly, check that bfType contains "BM" (without quotes), and, secondly, that bfSize is equal to the file size .
bfReserved1 and bfReserved2 are reserved and must be zero.
bfOffBits. This is one of the most important fields in this structure. It shows where the bitmap itself begins relative to the beginning of the file (or, as MSDN says, "from the beginning of the BITMAPFILEHEADER structure"), which describes the picture. That is, to be guaranteed to get to the beginning of the array you must write:
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
) BITMAPINFOHEADER, * PBITMAPINFOHEADER;
biSize is the size of the structure itself. It needs to be initialized as follows: bih.biSize = sizeof(BITMAPINFOHEADER);
Here again we will assume that bih is declared as follows: BITMAPINFOHEADER bih;
biWidth and biHeight set the width and height of the image in pixels, respectively.
biPlanes specifies the number of planes. For now it is always set to 1.
biBitCount- Number of bits per pixel. We'll talk more about this below.
biCompression indicates the type of compression. Don’t be surprised or scared that bmp suddenly experiences compression. I personally have not seen any compressed bmp (but I'm not saying that they don't exist). If there is no compression, then this flag must be set to BI_RGB. In this article we are talking about the uncompressed format, so I won’t even list other flags. It seems that the same structure is used in JPEG and PNG files, because starting from Windows 98 there appeared options BI_JPEG, which shows that this picture is JPEG and BI_PNG, that it is PNG (I don’t know anything about the Jpeg format, I I just made these conclusions based on what is written in MSDN).
biSizeImage indicates the size of the image in bytes. If the image is uncompressed (that is, the previous field is set to BI_RGB), then a zero should be written here. biXPelsPerMeter And biYPelsPerMeter denote, respectively, the horizontal and vertical resolution (in pixels per meter) of the final device onto which the bitmap (raster) will be output. An application can use this value to select from a group of resources the most appropriate bitmap for the desired device. The fact is that the bmp format is essentially a hardware-independent raster, that is, when the appearance of what is obtained does not depend on what this raster is projected onto (so to speak). For example, a picture will look the same regardless of whether it is drawn on a monitor screen or printed on a printer. But the resolution of devices is different, and it is precisely in order to select the most suitable picture from the available ones that these parameters are used.
biClrUsed determines the number of colors used from the table. If this value is zero, then the raster uses the maximum number of colors allowed by the biBitCount value. This is only relevant for compressed images. If biClrUsed is non-zero and biBitCount is less than 16, then biClrUsed determines the current number of graphics engine or device driver colors available. If biBitCount is greater than or equal to 16, then biClrUsed determines the size of the color table used to optimize the current system palette.
biClrImportant- this is the number of important colors. Determines the number of colors that are needed to depict the drawing. If this value is 0 (as it usually is), then all colors are considered important.
Types of BMP format
All types of bmp format conditionally can be divided into two types: palette and non-palette. That is, whether the palette is used in a given format or not. Please note that the palette can even be in palette-free formats, but it is not used there. In paletteless bmps, the color is calculated directly from the bits that go in the file, starting from a certain place. And in palettes, each byte describes one or more pixels, and the byte (or bits) values are the color index in the palette. To begin with, I will provide a table that compares the possible options. The type of picture (palette or palette-free) depends on how many bits are given per pixel, that is, on the biBitCount value of the BITMAPINFOHEADER structure.
biBitCount | Palette or non-palette format | Maximum possible number of colors | Notes | 1 | Palette | 2 | A two-color, mind you, not necessarily black and white, palette picture. If the raster bit (which is just below) is reset (equal to 0), then this means that the first color from the palette should be in this place, and if set (equal to 1), then the second. | 4 | Palette | 16 | Each byte describes 2 pixels. Here is an example from MSDN. If the first byte in the image is 0x1F, then it corresponds to two pixels, the color of the first is the second color from the palette (because the countdown starts from zero), and the second pixel is the 16th color of the palette. | 8 | Palette | 256 | One of the most common options. But at the same time, the simplest ones. The palette takes up one kilobyte (but it’s better not to count on it). One byte is one color. Moreover, its value is the color number in the palette. | 16 | No palette | 2^16 or 2^15 | This is the most confusing option. Let's start with the fact that it is palette-free, that is, every two bytes (one WORD word) in the raster uniquely define one pixel. But here’s what happens: there are 16 bits, and there are 3 color components (Red, Green, Blue). But 16 doesn’t want to be divided by 3. Therefore there are two options here. The first is to use not 16, but 15 bits, then there are 5 bits for each color component. This way we can use a maximum of 2^15 = 32768 colors and get a triple R-G-B = 5-5-5. But then a whole bit out of 16 is wasted in vain. But it just so happens that our eyes, among all colors, perceive green better, so we decided to give this one bit to the green component, that is, then we get the triple R-G-B = 5-6-5, and now we can use 2^16 = 65536 colors. But the most unpleasant thing is that both options are used. MSDN suggests that in order to distinguish how many colors are used, fill the biClrUsed field from the BITMAPINFOHEADER structure with this value. To select each component you need to use the following masks. For 5-5-5 format: 0x001F for blue component, 0x03E0 for green and 0x7C00 for red. For the 5-6-5 format: 0x001F - blue, 0x07E0 - green and 0xF800 red components, respectively. | 24 | No palette | 2^24 | And this is the simplest format. Here 3 bytes define 3 color components. That is, one component per byte. We simply read the RGBTRIPLE structure and use its rgbtBlue, rgbtGreen, rgbtRed fields. They go in that order. | 32 | No palette | 2^32 | Here 4 bytes define 3 components. But, however, one byte is not used. It can be used, for example, for the alpha channel (transparency). In this case, it is convenient to read the raster using RGBQUAD structures, which are described as follows: |
Data storage in bmp format
Well, now we come to the most interesting part. After the BITMAPFILEHEADER and BITMAPINFOHEADER structures comes the palette. Moreover, if the format is palette-free, then it may not be there, however, you should not count on it. The fact is that when I was just starting to understand the bmp format, I read in one book that, supposedly, if the format is palette-free, then it has no palette at all. There were even two pictures - format diagrams: one with a palette, the other without. And at that time I was writing a program that diligently operates with bmp files. And I had to convert incoming images from 256 colors to 24-bit (if any) into temporary files. And I simply did not create a palette in 24-bit (bfOffBits from the BITMAPFILEHEADER structure was equal to the sum of sizeof(BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER), and left the incoming 24-bit ones unchanged. With 256-color rasters everything worked as it should, until I didn’t come across a 24-bit image that had garbage displayed at the bottom instead of the required part. I didn’t immediately understand what was wrong until I compared the size of the original file with the theoretical one that should have been there if there had been no palette. The difference turned out to be exactly 1 KB. 1024 bytes). There was a palette. Therefore, never count on whether there is a palette and do not rely on its size (although all the pictures that I came across had a palette size of 256 colors, or 1Kb), always move through the file to the beginning of the raster, using bfOffBits. The palette is an array of RGBQUAD structures one after another. Even if not all colors are used in the palette (but only, for example, 16), then often 256 fields are allocated for the palette A 256 * 4 = 1024. 4 is the size of the RGBQUAD structure, that is, that same one kilobyte is obtained.
Immediately after the palette comes the raster itself. This is where things get more confusing. Firstly, the pixels are described here as written in the table above, depending on the format. And they can themselves contain the value of the color components (for palette-free ones), or they can be indexes of a palette array. The picture itself is recorded line by line. Secondly, the picture appears to be upside down. That is, the bottom line is written first, then the penultimate line, and so on until the very top. And, thirdly, as written in, if the size of the raster line is not a multiple of 4, then it is padded with 1 to 3 empty (zero) bytes so that the length of the line is a multiple of the paragraph. This is the most unpleasant thing. The fact is that for each format you have to adjust this number of empty bytes (though I like to write part of the palette there, I just don’t want to create extra “zero” variables if these bytes are skipped anyway and no one needs them). I provide a table with formulas that show for which format how many bytes should be added to the end of the line. There, the Width variable, as you might guess, means the width of the image. All these formulas were established experimentally. I will give an example only for the most used formats. For the rest, you can write it yourself.
Example programs
You can download all the sources. I won’t write much here. I'll just give the functions with comments.
Hello 1. Creating a picture in bmp format.
Here a monochromatic picture is created. There are three examples of such functions: creating bmp 8, 16 and 24 bits. I will give only for 16-bit.
// Let's create a picture in bmp format 16 bits like 5-5-5, which will be simply monochromatic
void CreateBmp555(char * fname, WORD color)
{
HANDLE hFile;
DWORD RW;
int i, j;
// Declare the necessary structures
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
BYTE Palette[1024]; // Palette
// Let's have an image of 35 x 50 pixels
int Width = 35 ;
int Height = 50 ;
memset(Palette, 0, 1024); // In the palette we have zeros, fill them
memset (&bfh, 0 , sizeof (bfh) ) ;
Bfh.bfType = 0x4D42 ; // Let's denote that this is bmp "BM"
bfh.bfOffBits = sizeof (bfh) + sizeof (bih) + 1024 ; // The palette takes up 1Kb, but we won't use it
bfh.bfSize = bfh.bfOffBits +
sizeof(color) * Width * Height +
Height * ((sizeof (color) * Width) % 4 ) ; // Calculate the size of the final file
memset (&bih, 0 , sizeof (bih) ) ;
bih.biSize = sizeof(bih); // That's how it's supposed to be
bih.biBitCount = 16 ; // 16 bits per pixel
bih.biClrUsed = 32768 ; // We use 5-5-5
bih.biCompression = BI_RGB; // Without compression
bih.biHeight = Height;
bih.biWidth = Width;
bih.biPlanes = 1 ; // Should be 1
// And the remaining fields remain 0
HFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return ;
// Write the headers
WriteFile (hFile, & bfh, sizeof (bfh) , & RW, NULL ) ;
WriteFile (hFile, & bih, sizeof (bih) , & RW, NULL ) ;
// Write the palette
WriteFile(hFile, Palette, 1024, &RW, NULL);
for (i = 0 ; i<
Height;
i++
)
{
for (j = 0 ; j<
Width;
j++
)
{
WriteFile (hFile, & color, sizeof (color) , & RW, NULL ) ;
}
// Align with the border
WriteFile (hFile, Palette, (sizeof (color) * Width) % 4 , & RW, NULL ) ;
}
CloseHandle(hFile) ;
}
color - picture color. The value of this variable must be filled in according to the first table. You can view the resulting picture in ACDSee, for example. I just tried to open it in Photoshop, but it turned out that it can’t read them in this format. But you can :).
Example 2. Converting a picture from 8-bit (256 colors) to 24-bit.
BOOL Convert256To24 (char * fin, char * fout)
{
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
int Width, Height;
RGBQUAD Palette[ 256 ] ;
BYTE * inBuf;
RGBTRIPLE * outBuf;
HANDLE hIn, hOut;
DWORD RW;
DWORD OffBits;
int i, j;
HIn = CreateFile (fin, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hIn == INVALID_HANDLE_VALUE)
return FALSE;
HOut = CreateFile(fout, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hOut == INVALID_HANDLE_VALUE)
{
CloseHandle(hIn);
return FALSE;
}
// Read the data
ReadFile (hIn, & bfh, sizeof (bfh) , & RW, NULL ) ;
ReadFile (hIn, & bih, sizeof (bih) , & RW, NULL ) ;
ReadFile (hIn, Palette, 256 * sizeof (RGBQUAD) , & RW, NULL ) ;
// Set the pointer to the beginning of the raster
SetFilePointer (hIn, bfh.bfOffBits, NULL, FILE_BEGIN) ;
Width = bih.biWidth ;
Height = bih.biHeight ;
OffBits = bfh.bfOffBits ;
// Allocate memory
inBuf = new BYTE [ Width ] ;
outBuf = new RGBTRIPLE [ Width ] ;
// Fill in the headers
bfh.bfOffBits = sizeof (bfh) + sizeof (bih) ; // Let's not write a palette
bih.biBitCount = 24 ;
bfh.bfSize = bfh.bfOffBits + 4 * Width * Height + Height * (Width % 4 ) ; // File size
// And the rest remains unchanged
// Write the headers
WriteFile (hOut, & bfh, sizeof (bfh) , & RW, NULL ) ;
WriteFile (hOut, & bih, sizeof (bih) , & RW, NULL ) ;
// Let's start converting
for (i = 0 ; i<
Height;
i++
)
{
ReadFile(hIn, inBuf, Width, & RW, NULL);
for (j = 0 ; j<
Width;
j++
)
{
outBuf[ j].rgbtRed = Palette[ inBuf[ j] ] .rgbRed ;
outBuf[ j].rgbtGreen = Palette[ inBuf[ j] ] .rgbGreen ;
outBuf[ j].rgbtBlue = Palette[ inBuf[ j] ] .rgbBlue ;
}
WriteFile (hOut, outBuf, sizeof (RGBTRIPLE) * Width, & RW, NULL ) ;
// Write garbage for alignment
WriteFile (hOut, Palette, Width % 4 , & RW, NULL ) ;
SetFilePointer(hIn, (3 * Width) % 4, NULL, FILE_CURRENT) ;
}
delete inBuf;
delete outBuf;
CloseHandle(hIn);
CloseHandle(hOut);
return TRUE;
}
The names of the source and destination files must be passed to the function, respectively.
The most common cause of problems with opening the BMP file is simply the lack of appropriate applications installed on your computer. In this case, it is enough to find, download and install an application that serves files in the BMP format - such programs are available below.
Search system
Enter file extension
Help
Clue
Please note that some encoded data from files that our computer does not read can sometimes be viewed in Notepad. In this way we will read fragments of text or numbers - It is worth checking whether this method also works in the case of BMP files.
What to do if the application from the list has already been installed?
Often an installed application should automatically link to a BMP file. If this does not happen, then the BMP file can be successfully associated manually with the newly installed application. Simply right-click on the BMP file, and then from the available list select the "Choose default program" option. Then you need to select the “View” option and find your favorite application. The entered changes must be approved using the "OK" option.
Programs that open the BMP file
Windows
Mac OS
Why can't I open a BMP file?
Problems with BMP files can also have other causes. Sometimes even installing software on your computer that supports BMP files will not solve the problem. The reason for the inability to open and work with the BMP file may also be:
Inappropriate BMP file associations in registry entries
- corruption of the BMP file we open
- BMP file infection (viruses)
- too little computer resource
- outdated drivers
- removing the BMP extension from the Windows registry
- incomplete installation of a program that supports the BMP extension
Fixing these issues should result in freely opening and working with BMP files. In case your computer still has problems with files, you need to take the help of an expert who will determine the exact cause.
My computer does not show file extensions, what should I do?
In standard Windows system settings, the computer user does not see the BMP file extension. This can be successfully changed in the settings. Just go to the "Control Panel" and select "View and Personalization". Then you need to go to "Folder Options" and open "View". In the "View" tab there is an option "Hide extensions of known file types" - you must select this option and confirm the operation by clicking the "OK" button. At this point, the extensions of all files, including BMP, should appear sorted by file name.
Announcement
BMP Raster image file format
BMP (bitmap file, device-independent bitmap file format) are bitmap files used to store digital bitmap images separately from the display device. This file type was previously used in Microsoft Windows and OS/2. The term "raster" comes from the programmers' idea of a bitmap. BMP images are usually uncompressed or losslessly compressed (for example, using ZIP or RAR - due to the presence of redundant data in the file). Today, JPG is the preferred image format - mainly due to the large file size of BMP, which can cause problems or delays when downloading, sending or uploading files.
Technical information about BMP files
BMP files are stored as 2D images of various sizes, colors, and color depths without data compression, color profiles, or alpha channels. BMP images are saved in device-independent bitmap (DIB) formats, meaning the image has colors rather than system specifications. This explains why some BMP images look different on different computers. BMP images can be viewed on any device, including computer and television screens. The lack of patents has made this image type a popular format for a wide range of devices.
Additional information about the BMP format
File extension | .bmp |
File category | |
Example file | (2.7 MiB) (487.85 KiB) |
Related programs | Adobe Photoshop MS Paint Microsoft Photo Editor Paintbrush |