Through my experience Reading and Writing BMP Images Using C ++ over the past few days, I have finally learned a little about the structure and operation of BMP files, the following describes how to read, rotate, and save BMP images in C ++.
To use C ++ to read BMP image files, you must first understand the structure of BMP image files. Can refer to this article: http://blog.csdn.net/xiajun07061225/article/details/5813726
Note the following points:
When reading BMP images, you must pay attention to the memory alignment, such as the file header. Otherwise, you cannot read the correct results.
For the pixel data of an image, the number of pixels in each row must be an integer multiple of 4. If not, you must complete the configuration. In general, the data in the BMP image file is from bottom to top, from left to right. That is, the first pixel on the left of the bottom row of the image is read from the file, and then the second pixel on the coordinate... next is the first pixel on the last and second rows.
The compiling environment is vs2008.
Image rotation is not difficult. You only need to figure out the pixel coordinate transformation formula. I use the center point of the image as the coordinate origin. First, change the position of the pixel in the target image to the position in the coordinate system, perform Rotation Transformation to find the coordinates in the coordinate system before the transformation, and then change to the position in the image.
Formula: (x1, Y1) is the coordinate in the coordinate system before transformation, (X2, Y2) is the coordinate in the coordinate system after transformation. Angle is the number of degrees that rotate counter-clockwise.
X 1 = cos (angle) * x2-sin (angle) * Y2;
Y1 = sin (angle) * x2-cos (angle) * Y2;
My code is divided into two versions: grayscale and color.
Grayscale image:
A grayscale image contains only brightness information and color information. BMP files do not have the concept of grayscale images, but we can easily use BMP files to represent grayscale images. The method is to use a 256 color palette, but this palette is a bit special. The RGB values of each item are the same, from (, 0), (, 1 ),..., until (255,255,255 ). In this way, the grayscale image can be represented by a 256 color chart. The image data is the color palette index value, that is, the actual RGB brightness value. In addition, because it is a 256-color palette, one byte in the image data represents one pixel. For a color 256 color image, the image processing may produce a color that does not belong to the 256 color. Therefore, the image processing generally uses a grayscale image. This can also focus more on algorithms.
The following is the grayscale image rotation code, which can process BMP grayscale images of any size and rotate any angle (counterclockwise ).
The Code includes two files: BMP rot. h and BMP rot. cpp.
BMP rot. h:
Typedef unsigned char byte; typedef unsigned short word; typedef unsigned int DWORD; typedef long; // bitmap file header definition; // It does not contain the file type information (determined by the memory structure of the struct, // if it is added, the file information cannot be correctly read) typedef struct tagbitmapfileheader {// word bftype; // file type, which must be 0x0000d, that is, the character "BM" DWORD bfsize; // file size word bfreserved1; // reserved WORD bfreserved2; // reserved word DWORD bfoffbits; // The number of offset bytes from the file header to the actual bitmap data} bitmapfileheader; typedef struct tagbitmapinfoheader {DWORD bisize; // The Information header size long biwidth; // The Image Width long biheight; // Image Height word lanlanes; // Number of Bit Planes, which must be 1 word bibitcount; // The number of bits per pixel DWORD bicompression; // compression type DWORD bisizeimage; // The number of bytes of the compressed image long bixpelspermeter; // The horizontal resolution long biypelspermeter; // The vertical resolution DWORD biclrused; // The number of colors actually used by the bitmap DWORD biclrimportant; // number of important colors in the base chart} bitmapinfoheader; // The bitmap information header defines typedef struct tagrgbquad {byte rgbblue; // The Blue byte rgbgreen of the color; // The Green byte rgbred; // The Red byte rgbreserved; // reserved value} rgbquad; // palette definition // Pixel Information typedef struct tagimagedata {byte blue; // byte green; // byte red;} imagedata;
BMP rot. cpp:
# Include <stdio. h> # include "BMP rot. H "# include" stdlib. H "# include" math. H "# include <iostream> # define PI 3.14159 // macro definition of circumference rate # define length_name_bmp 30 // the maximum length of the BMP image file name using namespace STD; // variable defines bitmapfileheader strhead; rgbquad strpla [256]; // bitmapinfoheader strinfo color palette; // display the bitmap file header information void showbmphead (bitmapfileheader pbmphead) {cout <"bitmap file header:" <Endl; cout <"file size:" <pbmphead. bfsize <Endl; cout <"reserved word _ 1:" <pbmphead. Bfreserved1 <Endl; cout <"reserved word _ 2:" <pbmphead. bfreserved2 <Endl; cout <"actual bitmap data offset Byte Count:" <pbmphead. bfoffbits <Endl;} void showbmp inforhead (tagbitmapinfoheader pbmpinforhead) {cout <"bitmap information header:" <Endl; cout <"length of the struct: "<pbmpinforhead. bisize <Endl; cout <"bitmap width:" <pbmpinforhead. biwidth <Endl; cout <"bitmap Height:" <pbmpinforhead. biheight <Endl; cout <"biplanes flat count:" <pbmpinforhead. biplanes <Endl; cout <" itcount uses color digits :" <Pbmpinforhead. bibitcount <Endl; cout <"compression mode:" <pbmpinforhead. bicompression <Endl; cout <"number of bytes occupied by the actual bitmap data of bisizeimage:" <pbmpinforhead. bisizeimage <Endl; cout <"X direction resolution:" <pbmpinforhead. bixpelspermeter <Endl; cout <"y direction resolution:" <pbmpinforhead. biypelspermeter <Endl; cout <"number of colors used:" <pbmpinforhead. biclrused <Endl; cout <"number of important colors:" <pbmpinforhead. biclrimportant <Endl;} int main () {char strfile [length_name_bmp]; // BMP Imagedata * imagedata = NULL; // a two-dimensional array of imagedata * imagedatarot = NULL is dynamically allocated to store the pixel information of the original image; // dynamically allocate two-dimensional array int width and height for storing the pixel information of the rotated image; // the width and height of the image cout <"Enter the file name to read: "<Endl; CIN> strfile; file * FPI, * FPW; FPI = fopen (strfile," rb "); If (FPI! = NULL) {// read the file type word bftype; fread (& bftype, 1, sizeof (Word), FPI); If (0x4d42! = Bftype) {cout <"the file is not a BMP file! "<Endl; return NULL;} // read the file header and information header fread (& strhead, 1, sizeof (tagbitmapfileheader), FPI) of the BMP file ); // showbmphead (strhead); // display the file header fread (& strinfo, 1, sizeof (tagbitmapinfoheader), FPI); // showbmp inforhead (strinfo ); // display the file information header // read the color palette for (unsigned int ncounti = 0; ncounti <strinfo. biclrused; ncounti ++) {fread (char *) & (strpla [ncounti]. rgbblue), 1, sizeof (byte), FPI); fread (char *) & (strpla [ncounti]. rgbgreen), 1, sizeof (byte), FPI); Fr EAD (char *) & (strpla [ncounti]. rgbred), 1, sizeof (byte), FPI); fread (char *) & (strpla [ncounti]. rgbreserved), 1, sizeof (byte), FPI);} width = strinfo. biwidth; Height = strinfo. biheight; // The number of bytes in each row of the image must be an integer multiple of 4. width = (width * sizeof (imagedata) + 3)/4*4; // imagedata = (imagedata *) malloc (width * height * sizeof (imagedata); imagedata = (imagedata *) malloc (width * Height); imagedatarot = (imagedata *) malloc (2 * width * 2 * height * sizeof (imagedata); // initialize the pixel array of the original image for (INT I = 0; I
Data test:
Comparison before and after rotation (45 degrees ):
Color chart:
The processing of a color chart is slightly different from that of a grayscale image. The main difference is that pixel data is different. Since the number of bytes in each row of data must be an integer multiple of 4, it is much more difficult to process this area than the grayscale image. The limitation of this program is that it can only process pictures of an integer multiple of 4, and can rotate any angle (counterclockwise ).
Reference code: There are two files: BMP rot. h and BMP rot. cpp.
BMP rot. h:
Typedef unsigned char byte; typedef unsigned short word; typedef unsigned int DWORD; typedef long; // bitmap file header definition; // It does not contain the file type information (determined by the memory structure of the struct, // if it is added, the file information cannot be correctly read) typedef struct tagbitmapfileheader {// word bftype; // file type, which must be 0x0000d, that is, the character "BM" DWORD bfsize; // file size word bfreserved1; // reserved WORD bfreserved2; // reserved word DWORD bfoffbits; // The number of offset bytes from the file header to the actual bitmap data} bitmapfileheader; typedef struct tagbitmapinfoheader {DWORD bisize; // The Information header size long biwidth; // The Image Width long biheight; // Image Height word lanlanes; // Number of Bit Planes, which must be 1 word bibitcount; // The number of bits per pixel DWORD bicompression; // compression type DWORD bisizeimage; // The number of bytes of the compressed image long bixpelspermeter; // The horizontal resolution long biypelspermeter; // The vertical resolution DWORD biclrused; // The number of colors actually used by the bitmap DWORD biclrimportant; // number of important colors in the base chart} bitmapinfoheader; // The bitmap information header defines typedef struct tagrgbquad {byte rgbblue; // The Blue byte rgbgreen of the color; // The Green byte rgbred; // The Red byte rgbreserved; // reserved value} rgbquad; // palette definition // Pixel Information typedef struct tagimagedata {byte red; byte green; byte blue;} imagedata;
BMP rot. cpp:
# Include <stdio. h> # include "BMP rot. H "# include" stdlib. H "# include" math. H "# include <iostream> # define PI 3.14159 // macro definition of circumference rate # define length_name_bmp 30 // the maximum length of the BMP image file name using namespace STD; // variable defines bitmapfileheader strhead; rgbquad strpla [256]; // bitmapinfoheader strinfo color palette; // display the bitmap file header information void showbmphead (bitmapfileheader pbmphead) {cout <"bitmap file header:" <Endl; cout <"file size:" <pbmphead. bfsize <Endl; cout <"reserved word _ 1:" <pbmphead. Bfreserved1 <Endl; cout <"reserved word _ 2:" <pbmphead. bfreserved2 <Endl; cout <"actual bitmap data offset Byte Count:" <pbmphead. bfoffbits <Endl;} void showbmp inforhead (tagbitmapinfoheader pbmpinforhead) {cout <"bitmap information header:" <Endl; cout <"length of the struct: "<pbmpinforhead. bisize <Endl; cout <"bitmap width:" <pbmpinforhead. biwidth <Endl; cout <"bitmap Height:" <pbmpinforhead. biheight <Endl; cout <"biplanes flat count:" <pbmpinforhead. biplanes <Endl; cout <" itcount uses color digits :" <Pbmpinforhead. bibitcount <Endl; cout <"compression mode:" <pbmpinforhead. bicompression <Endl; cout <"number of bytes occupied by the actual bitmap data of bisizeimage:" <pbmpinforhead. bisizeimage <Endl; cout <"X direction resolution:" <pbmpinforhead. bixpelspermeter <Endl; cout <"y direction resolution:" <pbmpinforhead. biypelspermeter <Endl; cout <"number of colors used:" <pbmpinforhead. biclrused <Endl; cout <"number of important colors:" <pbmpinforhead. biclrimportant <Endl;} int main () {char strfile [length_name_bmp]; // BMP Imagedata * imagedata = NULL; // a two-dimensional array of imagedata * imagedatarot = NULL is dynamically allocated to store the pixel information of the original image; // dynamically allocate two-dimensional array int width and height for storing the pixel information of the rotated image; // the width and height of the image cout <"Enter the file name to read: "<Endl; CIN> strfile; file * FPI, * FPW; FPI = fopen (strfile," rb "); If (FPI! = NULL) {// read the file type word bftype; fread (& bftype, 1, sizeof (Word), FPI); If (0x4d42! = Bftype) {cout <"the file is not a BMP file! "<Endl; return NULL;} // read the file header and information header fread (& strhead, 1, sizeof (tagbitmapfileheader), FPI) of the BMP file ); // showbmphead (strhead); // display the file header fread (& strinfo, 1, sizeof (tagbitmapinfoheader), FPI); // showbmp inforhead (strinfo ); // display the file information header // read the color palette for (unsigned int ncounti = 0; ncounti <strinfo. biclrused; ncounti ++) {// during storage, the reserved words rgbreservedfread (char *) & strpla [ncounti] are generally removed. rgbblue, 1, sizeof (byte), FPI); fread (char *) & strpla [ncounti]. rgbgreen, 1, sizeof (byte), FPI); fread (char *) & strpla [ncounti]. rgbred, 1, sizeof (byte), FPI); cout <"strpla [ncounti]. rgbblue "<strpla [ncounti]. rgbblue <Endl; cout <"strpla [ncounti]. rgbgreen "<strpla [ncounti]. rgbgreen <Endl; cout <"strpla [ncounti]. rgbred "<strpla [ncounti]. rgbred <Endl;} width = strinfo. biwidth; Height = strinfo. biheight; imagedata = (imagedata *) malloc (width * height * sizeof (imagedata); imagedatarot = (Imagedata *) malloc (2 * width * 2 * height * sizeof (imagedata); // initialize the pixel array of the original image for (INT I = 0; I
Data Test: (rotate 10 °)
Note: The color problem has been solved. See the comments section in the code.