Visual c ++ 6.0 development of grayscale Bitmap Processing

Source: Internet
Author: User
Tags bmp image
Image processing technology has penetrated into various fields of human life and is increasingly used. image processing involves many image formats, such as TIF, jemp, and BMP, in engineering applications, 256-level grayscale BMP images are often processed, such as those obtained through the black and white acquisition card. As one of the main image formats in windows, BMP grayscale images are highly popular because of their simple format and high adaptability. During image processing, the pixel values in the operated images must obtain an image array. After processing, the pixel values of the processed images are stored. When displaying the images, you must correctly implement the color palette and combine these problems, this article provides some function implementation code and comments when operating the grayscale BMP image.

1. BMP bitmap operation

BMP bitmap consists of bitmapfileheader, bitmapinfoheader, bitmapinfoheader, rgbquad, and bitmap pixel data. When processing bitmap, You need to obtain the bitmap file size, the width and height of the bitmap, the implementation palette, And the bitmap pixel value based on the structure of the file. For a 256-level grayscale image, each pixel uses 8 bits to represent the color index value. Note that in a BMP bitmap, each line of the bitmap's pixel value must be filled with a four-byte boundary, that is, the storage length of each row of the bitmap is a multiple of four bytes. When there is not enough, the excess bit is filled with 0.

Declare the following macros and public variables in the document class (cdibdoc. h) for image processing applications:

# Define widthbytes (BITs) + 31)/32*4) // calculate the number of bytes occupied by pixels in each row of the image

Handle m_hdib; // handle for storing bitmap data

Cpalette * m_paldib; // pointer to the cpalette class of the color palette

Csize m_sizedoc; file: // initialize the View Size

1. Read the grayscale BMP bitmap

According to the structure of the BMP bitmap file, read data from the BMP bitmap file. The onopendocument function of the document block class is reloaded as follows:

Bool cdibdoc: onopendocument (lpctstr lpszpathname)
{
Cfile file;
Cfileexception Fe;
If (! File. Open (lpszpathname, cfile: moderead | cfile: sharedenywrite, & Fe ))
{
Afxmessagebox ("file cannot be opened ");
Return false;
} // Open the file
Deletecontents (); // delete a text block
Beginwaitcursor ();
Bitmapfileheader bmfheader; // defines the structure of the bitmap file header.
DWORD dwbitssize;
Handle hdib;
Lpstr pdib;
Bitmapinfoheader * bmhdr; // pointer to the bitmap information header Structure
Dwbitssize = file. getlength (); // obtain the object length.
If (file. Read (lpstr) & bmfheader, sizeof (bmfheader ))! =
Sizeof (bmfheader ))
Return false;
If (bmfheader. bftype! = 0x4d42) file: // check whether the file is a BMP file
Return false;
Hdib = (handle): globalalloc (gmem_moveable |
Gmem_zeroinit, dwbitssize );
File: // apply for a buffer
If (hdib = 0)
{
Return false;
}
Pdib = (lpstr): globallock (hglobal) hdib );
File: // get the pointer to the requested Buffer
If (file. readhuge (pdib, dwbitssize-sizeof (bitmapfileheader ))! =
Dwbitssize-sizeof (bitmapfileheader ))
{
: Globalunlock (hglobal) hdib );
Hdib = NULL;
Return false;
} // Read data, including bitmap information, bitmap color table, and gray value of image pixels
Bmhdr = (bitmapinfoheader *) pdib; // It is a pointer to the bitmap information header structure.
: Globalunlock (hglobal) hdib );
If (* bmhdr). bibitcount! = 8) file: // verify whether it is an 8-Bit Bitmap
Return false;
M_hdib = hdib;
Initdibdata ();
File: // user-defined function. The bitmap width, height, and color table are obtained based on the read data.
File: // to obtain the size of the initialization view and the color palette.
Endwaitcursor ();
Setpathname (lpszpathname); // you can specify a storage path.
Setmodifiedflag (false); // set the file flag to false.
Return true;
}
 
2. Storage of grayscale bitmap data

To save the pixel values obtained after image processing, the onsavedocument function of the document class is reloaded. Its implementation is as follows:

Bool cdibdoc: onsavedocument (lpctstr lpszpathname)
{
Cfile file;
Cfileexception Fe;
Bitmapfileheader bmfhdr; // bitmap file header Structure
Lpbitmapinfoheader lpbi; file: // pointer to the bitmap Information Structure
DWORD dwdibsize;
If (! File. Open (lpszpathname, cfile: modecreate |
Cfile: modereadwrite | cfile: Export exclusive, & Fe ))
{
Afxmessagebox ("file cannot be opened ");
} // Open the file
Bool bsuccess = false;
Beginwaitcursor ();
Lpbi = (lpbitmapinfoheader): globallock (hglobal) m_hdib );
If (lpbi = NULL)
Return false;
Dwdibsize = * (lpdword) lpbi + 256 * sizeof (rgbquad );
// Partial Calculation
DWORD dwbmbitssize; // number of bytes occupied by the BMP File Information Structure
Dwbmbitssize = widthbytes (lpbi-> biwidth) * (DWORD) lpbi-> bibitcount) * lpbi-> biheight; // The total number of bytes occupied by all bitmap pixels during storage
Dwdibsize + = dwbmbitssize;
Lpbi-> bisizeimage = dwbmbitssize; // The total number of bytes occupied by all bitmap pixels
File: // The following five sentences are the file header structure filling values.
Bmfhdr. bftype = 0x4d42; // The file is of the "BMP" type.
Bmfhdr. bfsize = dwdibsize + sizeof (bitmapfileheader); // total file length
Bmfhdr. bfreserved1 = 0;
Bmfhdr. bfreserved2 = 0;
Bmfhdr. bfoffbits = (DWORD) sizeof (bitmapfileheader) + lpbi-> bisize
+ 256 * sizeof (rgbquad );
File: // bitmap data offset from the question Header
File. Write (lpstr) & bmfhdr, sizeof (bitmapfileheader); // write the file header
File. writehuge (lpbi, dwdibsize );
File: // write bitmap information (Information header structure, color table, and pixel data) into the file.
: Globalunlock (hglobal) m_hdib );
Endwaitcursor ();
Setmodifiedflag (false); // back to unmodified
Return true;
}
 
Ii. operations on the color palette

To display gray images correctly, the logical and system color palette must be implemented, wm_querynewpalette, wm_palettechanged, and view messages defined by windows are processed in the main framework class. wm_dorealize (the message is defined in the main framework window as follows: # define wm_realizepal (wm_user + 100 )) to implement operations on the palette.

Void cmainframe: onpalettechanged (cwnd * pfocuswnd)
{File: // The total palette for implementing the activity View
Cmdiframewnd: onpalettechanged (pfocuswnd );
Required ichildwnd * pmdichildwnd = mdigetactive ();
If (pmdichildwnd = NULL)
Return
Cview * pview = pmdichildwnd-> getactiveview ();
Assert (pview! = NULL );
Sendmessagetodescendants (wm_dorealize, (wparam) pview-> m_hwnd );
File: // notify all sub-windows that the system palette has changed
}
Bool cmainframe: onquerynewpalette () // provides an opportunity to implement the system palette
{
// Implement the activity visual palette
Required ichildwnd * pmdichildwnd = mdigetactive ();
If (pmdichildwnd = NULL)
Return false; // no active MDI child frame (no new palette)
Cview * pview = pmdichildwnd-> getactiveview ();
Assert (pview! = NULL );
File: // The system palette of the notification activity view.
Pview-> sendmessage (wm_dorealize, (wparam) pview-> m_hwnd );
Return true;
}
Lresult cdibview: ondorealize (wparam, lparam) // implement the system palette
{
Assert (wparam! = NULL );
Cdibdoc * pdoc = getdocument ();
If (pdoc-> m_hdib = NULL)
Return 0l; // must be a new document
Cpalette * ppal = pdoc-> m_paldib;
File: // The color table data of the palette is implemented in the initdibdata () function.
If (ppal! = NULL)
{
Cmainframe * pappframe = (cmainframe *) afxgetapp ()-> m_pmainwnd;
Assert_kindof (cmainframe, pappframe );
Cclientdc appdc (pappframe );
Cpalette * oldpalette = appdc. selectpalette (ppal, (hwnd) wparam )! = M_hwnd );
File: // you can set the value to "false" only for the activity ",
// Set the color palette to "foreground" based on the activity view.
If (oldpalette! = NULL)
{
Uint ncolorschanged = appdc. realizepalette (); // implements the system palette.
If (ncolorschanged> 0)
Pdoc-> updateallviews (null); // update the view
Appdc. selectpalette (oldpalette, true );
File: // set the original system palette to the logical palette
}
Else
{
Trace0 ("/tselectpalette failed in
Cdibview: onpalettechanged/N ");
}
}
 

Note: when calling the API function to display a bitmap, do not forget to set the logical palette, that is, the "background" palette. Otherwise, the bitmap cannot be correctly displayed.

Iii. Digital Image Processing

After reading the file, you can obtain the image data. Because the obtained data includes redundant information, you must delete the redundant information during digital image processing, only bitmap pixels are operated. The template-based Qualcomm filter is used as an example to describe the implementation of digital image processing:

Void cdibview: onmenuhighpass ()
{Handle data1handle;
Lpbitmapinfoheader lpbi;
Cdibdoc * pdoc = getdocument ();
Hdib; unsigned char * hdata; unsigned char * data;
Hdib = pdoc-> gethdib ();
Beginwaitcursor ();
Lpbi = (lpbitmapinfoheader) globallock (hglobal) hdib );
Hdata = (unsigned char *) finddibbits (lpstr) lpbi );
Pdoc-> setmodifiedflag (true );
Data1handle = globalalloc (gmem_share, widthbytes (lpbi-> biwidth * 8) * lpbi-> biheight );
Data = (unsigned char *) globallock (hglobal) data1handle );
Afxgetapp ()-> beginwaitcursor ();
Int I, j, S, T, MS = 1;
Int sum = 0, sumw = 0;
Int mask [3] [3] = {-1,-1,-1}, {-1,-1}, {-1,-1, -1 }};
For (I = 0; ibiheight; I ++)
For (j = 0; jbiwidth; j ++)
{
Sumw = 0; sum = 0;
For (S = (-MS); S <= MS; s ++)
For (t = (-MS); t <= MS; t ++)
If (I + S)> = 0) & (J + T)> = 0) & (I + S) biheight) & (J + T) biwidth ))
{
Sumw + = mask [1 + S] [1 + T];
Sum + = * (hdata + (I + s) * widthbytes (lpbi-> biwidth * 8) + (J + T )) * mask [1 + S] [1 + T];
}
If (sumw = 0) sumw = 1; sum/= sumw;
If (sum> 255) sum = 255;
If (sum <0) sum = 0;
* (Data + I * widthbytes (lpbi-> biwidth * 8) + J) = sum;
}
For (j = 0; jbiheight; j ++)
For (I = 0; ibiwidth; I ++)
* (Hdata + I * widthbytes (lpbi-> biwidth * 8) + J) = * (Data + I * widthbytes (lpbi-> biwidth * 8) + J );
Afxgetapp ()-> endwaitcursor ();
Globalunlock (hglobal) hdib );
Globalunlock (data1handle );
Endwaitcursor ();
Invalidate (true );
}
 
Iv. Basic image operation and Processing

1. Image Translation

Image translation only changes the position of the image on the screen, and the image itself does not change. Assume that the coordinates in the upper-left corner of the original image area are (x0, y0), and the lower-right coordinates are (x1, Y1), and the images are translated along X and Y axes Dx and Dy, respectively, then, the coordinates in the upper left corner of the new image are (x0 + dx, y0 + dy), and those in the lower right corner are (X1 + dx, Y1 + dy ). The coordinate translation and transformation formula is:

X1 = x + dx

Y1 = Y + dy

There are four steps to move an image on the screen:

(1) read the original image to the buffer zone;

(2) erase the original image from the view;

(3) Calculate the new coordinates after translation.

(4) use the API function: stretchdibits () to re-display the original image at the Coordinate Position in the new upper left corner.

The method used to erase the original image is the same as that used to erase the original image in the graphic transformation. in the implementation process, the original image is still erased by drawing XOR. For the calculation of the new coordinate value, the boundary condition should also be considered. Do not go beyond the allowed screen range after the image is translated.

2. image upside down

Image inversion refers to displaying the defined image area up and down on the screen. After analyzing the image inversion process, we can find that the image information of each line remains unchanged, but changes the sequence of rows, switching the first line with the last n lines, the second line exchanges with the nth line ......, In this way, the image is reversed. You only need to use the line-based switching method to conveniently modify the buffer content and reverse the image. The basic steps are as follows:

(1) read the original image into the buffer zone and erase the original image;

(2) Calculate the Image Height, that is, the row height; Calculate the image width and width; generate a new Buffer Based on the width and height;

(3) exchange the first line with the last line, and the second line with the n-1 line ......, And so on until all the exchanges are completed. The (x, y) points in the source image correspond to X1 = x, Y1 = height-1-y in the new image. Read the pixel value in the source image into the (x1, Y1) Point of the new buffer.

(4) re-display the swap image buffer on the screen.

3. Image Transformation

Image conversion refers to displaying images in a specified area on the screen right and right. After analyzing the image transformation process, we can find that each line of image information is processed in the same way, and the row sequence does not change, only the pixel information of each row is reversed from left to right, thus realizing image transformation. Therefore, the image is transformed point-by-point by line.

The formula for the Coordinate Transformation of the new coordinate (x1, Y1) after the image transformation of any point (x, y) in the source image is given:

X1 = width-x-1

Y1 = y

Based on the above formula, after the new coordinates are calculated for each pixel, the pixel value in the original image is read into the (x1, Y1) Point of the new buffer.

4. Rotate images from any angle

Image Rotation refers to the rotation of a defined image around a certain point to a certain angle in the clockwise or clockwise direction, usually refers to the rotation of the center around the image in the clockwise direction.

First, the maximum width and height of the rotated image are calculated based on the rotation angle and diagonal length of the image. A new buffer zone is generated based on the maximum width and height of the rotated image, assume that the upper left corner of the image is (left, top), and the lower right corner is (right, bottom) after the angle is rotated counterclockwise, the formula for calculating the new Coordinate Position (x1, Y1) is as follows:

Xcenter = (width + 1)/2 + left;

Ycenter = (height + 1)/2 + top;

X1 = (X-xcenter) COS θ-(Y-ycenter) sin θ + xcenter;

Y1 = (X-xcenter) sin θ + (Y-ycenter) COS θ + ycenter;

Similar to image transformation, the pixel value in the source image is read at (x1, Y1) points in the new buffer zone. Note that the values of pixel points that do not correspond to the source image in the new buffer are replaced by white.

V. Summary

The image processing program developed by the author is compiled and approved in the Windows 98 environment. This article mainly describes the processing of 8bit gray images, readers can develop their own image processing systems for binary and true color formats based on this article.
 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.