C/C ++ BMP (24-bit true color) Image Processing (4) ------ image rotate ,------
After more than a month, CSDN seems to have finally fixed the BUG of returning the reading amount of the article list to zero, so it is almost impossible to put an article written at the end of the big job to test the effect, don't try again like the last one!
This article is about image rotation, which is not a fresh question. But now many tools, such as MATLAB and OPENCV, write algorithms for user calls, so most users only know why, so it is good to review them.
After all, the rotation of an image means that each pixel rotates around a center of a certain angle. If you are writing code, the rotation angle and circle center should be known conditions. Our first idea is to obtain the coordinates of the new Pixel after the image is rotated based on known conditions. This idea is clearly correct. However, there is a problem that some pixels of the rotated image have been transferred out of the image size, and some pixels cannot match the original image. This makes programming as complicated as follows. Therefore, we thought in turn that we should plan the rotated image first, and then use a method to calculate whether each pixel of the new image corresponds to the pixel of the original image, if it corresponds to the position where the pixel is located in the original image, and if it does not correspond to the value of the pixel. In this way, we can traverse all the pixels of the new image to get the rotated image.
OK. We have already clarified the idea of image rotation. What we do not know yet is the relationship between pixels before and after image rotation. This relationship is a little more complex. I have referred to the calculation method of this blog, and I will deduce or reproduce it below.
See, after the above derivation, we want to get x and y from x', y. This means that the final form we will get is:
X = f (x', y ');
Y = g (x', y ')
This way. OK. The formula is derived as follows (the style is slightly different in word ...) :
Okay, after the theoretical work is done, the next step is programming. It should be noted that the points of the Post-rotation image correspond to the points of the pre-rotation image, which are basically not likely to be positive, therefore, bilinear interpolation is required (the specific analysis of this theory is described in the previous article ).
The main code is as follows:
/******************* Image rotation ****************** /int centerofrotation_x = MYDRAW_WIDTH/2; // rotation center x coordinate int centerofrotation_y = MYDRAW_HEIGHT/2; // rotation center y coordinate double degree = 60; // counter-clockwise rotation angle double radian = degree/180 * pi; // converts degrees to radians for (int hnum = 0; hnum <MYDRAW_HEIGHT; hnum ++) for (int wnum = 0; wnum <MYDRAW_WIDTH; wnum ++) {int pixel_point = hnum * write_width + wnum * 3; // ing the position offset of the Image array; double d_original_img_wnum = (wnum-centerofrotation_x) * cos (radian) * sin (radian) + centerofrotation_x; double d_original_img_hnum = (wnum-centerofrotation_x) * sin (radian) + (hnum-centerofrotation_y) * cos (radian) + centerofrotation_y; if (d_original_img_wnum <0 | d_original_img_wnum> width | d_original_img_hnum <0 | d_original_img_hnum> height) // The relationship with the original image cannot be found {pColorDataMid [pixel_point] = pColorDataMid [pixel_point + 1] = pColorDataMid [pixel_point + 2] = 0; continue;} int vertex = d_original_img_hnum; int distance = d_original_img_wnum; double distance_to_a_x = d_original_img_wnum-distance; // horizontal distance between the original image and the point double distance_to_a_y = d_original_img_hnum-distance; // The vertical distance between the original image and the point int original_point_a = I _original_img_hnum * l_width + I _original_img_wnum * 3; // The array position offset, which corresponds to the start point of each pixel in the image, equivalent to A int original_point_ B = I _original_img_hnum * l_width + (I _original_img_wnum + 1) * 3; // array position offset, which corresponds to the RGB start point of each pixel of the image, equivalent to Bint original_point_c = (I _original_img_hnum + 1) * l_width + I _original_img_wnum * 3; // array position offset, which corresponds to the RGB start point of each pixel in the image, equivalent to point C int original_point_d = (I _original_img_hnum + 1) * l_width + (I _original_img_wnum + 1) * 3; // array position offset, which corresponds to the start point of each pixel in the image, RGB, equivalent to D if (vertex = MYDRAW_HEIGHT-1) {original_point_c = original_point_a; original_point_d = vertex;} if (vertex = MYDRAW_WIDTH-1) {original_point_a = vertex; vertex = original_point_d;} pColorDataMid [pixel_point] = pColorData [original_point_a] * (1-second) * (1-second) + pColorData [original_point_ B] * vertex * (1-second) + pColorData [original_point_c] * distance_to_a_y * (1-distance_to_a_x) + pColorData [original_point_c] * distance_to_a_y * distance_to_a_x; pColorDataMid [pixel_point + 1] = pColorData [original_point_a + 1] * (1-distance_to_a_x) + pColorData [original_point_c + 1] * distance_to_a_y * (1-distance_to_a_x) + pColorData [original_point_c + 1] * distance_to_a_y * hour; pColorDataMid [pixel_point + 2] = pColorData [original_point_a + 2] * (1-distance_to_a_x) + pColorData [original_point_c + 2] * distance_to_a_y * (1-example) + pColorData [original_point_c + 2] * distance_to_a_y * distance_to_a_x ;} /******************* image rotation ******************/
The entire project code is as follows:
# Include <string. h> # include <math. h> # include <stdio. h> # include <stdlib. h> # include <malloc. h> # include <time. h> // time-related header files, where the function compute image processing speed # define WIDTHBYTES (bits) + 31)/32*4) // used to multiply the Image Width by 4 bytes # define MYDRAW_HEIGHT 1054 // Target Image Height # define MYDRAW_WIDTH 1500 // target image width # define pi 3.1415926535 typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; typedef long LONG; // Bitmap File Header Information Structure Definition // It does not contain file type information (because of the memory structure of the structure, if it is added, the file information cannot be correctly read) typedef struct tagBITMAPFILEHEADER {DWORD bfSize; // file size: WORD bfReserved1; // reserved words, excluding WORD bfReserved2; // reserved words, same as DWORD bfOffBits; // The actual bitmap data offset byte count, that is, the sum of the first three parts} BITMAPFILEHEADER; // The Information header BITMAPINFOHEADER is also a structure, which is defined as follows: typedef struct tagBITMAPINFOHEADER {// public: DWORD biSize; // specify the length of this struct, which is 40 LONG biWidth; // bitmap width LONG biHeight; // bitmap height WORD lanlanes; // number of planes, which is 1 WORD biBi TCount; // The number of digits in the color, which can be 1, 2, 4, 8, 16, 24, and the new one can be 32 DWORD biCompression; // compression mode, which can be 0, 1, 2, 0 indicates that DWORD biSizeImage is not compressed; // The number of bytes occupied by the actual bitmap data LONG biXPelsPerMeter; // LONG biYPelsPerMeter in the X direction; // DWORD biClrUsed in the Y direction; // The number of colors used. If it is 0, it indicates the default value (2 ^ number of colors) DWORD biClrImportant; // The number of important colors. If it is 0, indicates that all colors are important} BITMAPINFOHEADER; void main () {long now = 0; now = clock (); // stores the image processing start time BITMAPFILEHEADER bitHead, writebitHead; BITMAPINFOHEADER bitIn FoHead, writebitInfoHead; FILE * pfile; // input FILE * wfile; // output FILE char strFile [50] = "15.bmp"; // open the image path, BMP images must be in 24-bit real-color format char strFilesave [50] = "16.bmp"; // after processing, the image storage path fopen_s (& pfile, strFile, "rb "); // file open image fopen_s (& wfile, strFilesave, "wb"); // open the file to prepare for storing the Modified Image // read the bitmap file header information WORD fileType; fread (& fileType, 1, sizeof (WORD), pfile); fwrite (& fileType, 1, sizeof (WORD), wfile); if (fileType! = 0x4d42) {printf ("file is not. bmp file! "); Return;} // read the bitmap file header information fread (& bitHead, 1, sizeof (tagBITMAPFILEHEADER), pfile); writebitHead = bitHead; // because the captured image header is similar to the source file header, you must first grant the source file header data to the captured file header. // read the bitmap information header information fread (& bitInfoHead, 1, sizeof (BITMAPINFOHEADER ), pfile); writebitInfoHead = bitInfoHead; // similar to writebitInfoHead. biHeight = MYDRAW_HEIGHT; // rewrite the bitmap height writebitInfoHead for the captured file. biWidth = MYDRAW_WIDTH; // rewrite the bitmap width int mywritewidth = WIDTHBYTES (writebitInfoHead. biWidth * writebitInfoHead. biBitCount); // The actual bitmap data area width of the BMP image is a multiple of 4 bytes, and the actual data area width is writebitInfoHead. biSizeImage = mywritewidth * writebitInfoHead. biHeight; // calculate the actual size of the bitmap data area writebitHead. bfSize = 54 + writebitInfoHead. biSizeImage; // the size of the bitmap file header is the size of the bitmap data area plus 54 bytefwrite (& writebitHead, 1, sizeof (tagBITMAPFILEHEADER), wfile ); // write back the Bitmap header information to the output file fwrite (& writebitInfoHead, 1, sizeof (BITMAPINFOHEADER), wfile); // write back the Bitmap header information to the output file int width = bitInfoHead. biWidth; int height = bitInfoHead. biHeight; // allocate memory space to store the source image into the memory int l_width = WIDTHBYTES (width * bitInfoHead. biBitCount); // calculate the actual width of the bitmap and make sure it is a multiple of 4 bytes int write_width = WIDTHBYTES (writebitInfoHead. biWidth * writebitInfoHead. biBitCount); // calculate the actual width of the write bitmap and make sure it is a multiple of 4 bytes. BYTE * pColorData = (BYTE *) malloc (height * l_width ); // open up memory space to store image data memset (pColorData, 0, height * l_width); BYTE * pColorDataMid = (BYTE *) malloc (mywritewidth * MYDRAW_HEIGHT ); // open up the memory space to store the data memset (pColorDataMid, 0, mywritewidth * MYDRAW_HEIGHT) after image processing; long nData = height * l_width; long write_nData = mywritewidth * MYDRAW_HEIGHT; // definition of the captured bitmap data area length // read bitmap data information to fread (pColorData, 1, nData, pfile) in the array ); // image processing can be achieved through the operation of this part of data/********************* image processing part ***** ************ // ************************* image rotation **** * ************/int centerofrotation_x = MYDRAW_WIDTH/2; // rotation center x coordinate int centerofrotation_y = MYDRAW_HEIGHT/2; // rotation center y coordinate double degree = 60; // counter-clockwise rotation angle double radian = degree/180 * pi; // converts degrees to radians for (int hnum = 0; hnum <MYDRAW_HEIGHT; hnum ++) for (int wnum = 0; wnum <MYDRAW_WIDTH; wnum ++) {int pixel_point = hnum * write_width + wnum * 3; // ing the position offset of the Image array; double d_original_img_wnum = (wnum-centerofrotation_x) * cos (radian) * sin (radian) + centerofrotation_x; double d_original_img_hnum = (wnum-centerofrotation_x) * sin (radian) + (hnum-centerofrotation_y) * cos (radian) + centerofrotation_y; if (d_original_img_wnum <0 | d_original_img_wnum> width | d_original_img_hnum <0 | d_original_img_hnum> height) // The relationship with the original image cannot be found {pColorDataMid [pixel_point] = pColorDataMid [pixel_point + 1] = pColorDataMid [pixel_point + 2] = 0; continue;} int vertex = d_original_img_hnum; int distance = d_original_img_wnum; double distance_to_a_x = d_original_img_wnum-distance; // horizontal distance between the original image and the point double distance_to_a_y = d_original_img_hnum-distance; // The vertical distance between the original image and the point int original_point_a = I _original_img_hnum * l_width + I _original_img_wnum * 3; // The array position offset, which corresponds to the start point of each pixel in the image, equivalent to A int original_point_ B = I _original_img_hnum * l_width + (I _original_img_wnum + 1) * 3; // array position offset, which corresponds to the RGB start point of each pixel of the image, equivalent to Bint original_point_c = (I _original_img_hnum + 1) * l_width + I _original_img_wnum * 3; // array position offset, which corresponds to the RGB start point of each pixel in the image, equivalent to point C int original_point_d = (I _original_img_hnum + 1) * l_width + (I _original_img_wnum + 1) * 3; // array position offset, which corresponds to the start point of each pixel in the image, RGB, equivalent to D if (vertex = MYDRAW_HEIGHT-1) {original_point_c = original_point_a; original_point_d = vertex;} if (vertex = MYDRAW_WIDTH-1) {original_point_a = vertex; vertex = original_point_d;} pColorDataMid [pixel_point] = pColorData [original_point_a] * (1-second) * (1-second) + pColorData [original_point_ B] * vertex * (1-second) + pColorData [original_point_c] * distance_to_a_y * (1-distance_to_a_x) + pColorData [original_point_c] * distance_to_a_y * distance_to_a_x; pColorDataMid [pixel_point + 1] = pColorData [original_point_a + 1] * (1-distance_to_a_x) + pColorData [original_point_c + 1] * distance_to_a_y * (1-distance_to_a_x) + pColorData [original_point_c + 1] * distance_to_a_y * hour; pColorDataMid [pixel_point + 2] = pColorData [original_point_a + 2] * (1-distance_to_a_x) + pColorData [original_point_c + 2] * distance_to_a_y * (1-example) + pColorData [original_point_c + 2] * distance_to_a_y * distance_to_a_x ;} /******************* image rotation ****************** **************** **/fwrite (pColorDataMid, 1, write_nData, wfile); // write the processed image data area back to the file fclose (pfile); fclose (wfile); printf ("image processed \ n "); printf ("Run Time: % dms \ n", int (double) (clock ()-now)/CLOCKS_PER_SEC * 1000 )); // time spent in output image processing}
The original image and the obtained rotating image are as follows:
Original Image
Rotated image
24-bit real-color BMP image. Is a pixel 24-bit?
For example, a 480000 x image has pixels. Then a pixel is 24 bits (true color ). 800X600X24 Bytes 8 = 1440000 bytes. In fact, there are only three colors (red, green, and blue) for a single point pixel on the display)
A 120x80 24-bit real-color image occupies ____ bytes of storage space
120*80 = 9600 pixels, each pixel is 24-bit data, 24-bit is 3 bytes, theoretically up to 28800 bytes, this is only the size of the BMP bitmap file. In fact, because many adjacent pixels have the same color, the space-saving algorithm is used in data recording. JPG images are generally smaller than this size.