Full Screen quick image color searching in Delphi I. Data Extraction

Source: Internet
Author: User

Preface

Recently, several of my friends are asking me how to find the color of the image. What's strange? Therefore, I wrote a unit file bitmapdata. Pas, which is used to find the color of a graph ". In this unit file, I can import bitmap, screen, mouse pointer, search for subgraph on the image, and search for color on the image. During the search process, you can set the color change range, search from left to right from top to bottom, or search around from the specified point. For more information about downloading and using this file, see section 4. The following describes the implementation of these functions in detail.

I. Data Extraction

Bitmap can be regarded as a matrix composed of pixels. Looking for colors in a graph can be regarded as comparing pixel values. Many new users are designingProgramI like to use the tbitmap. Canvas. pixels attribute. This attribute is actually an encapsulation of the API function getpixel. This function is very slow to execute and is mainly used for occasional accesses to image elements. During the comparison process, frequent access to object elements is required, resulting in slow program running. Another method is to use the tbitmap. scanline attribute to directly access the bitmap data. However, this data is related to the current bitmap format, mainly in terms of color depth. Different color depths have different formats of data. In addition, this attribute needs to be frequently called during the comparison process. Because the comparison process is completely a comparison of data, no painting is required. Therefore, bitmap data can be extracted and placed into a buffer zone for comparison at a time, so that the program performance will be higher and easier to findAlgorithm. In this case, you can call the API function getdibits to obtain the RGB data of the device-independent bitmap. In fact, the scanline attribute also calls this function. The format declaration of the getdibits function is as follows:

Function getdibits (
DC: HDC; // The device context handle;
Bitmap: hbitmap; // bitmap handle. Note that it is not a tbitmap object;
Startscan, // The first scanned line to start retrieval;
Numscans: uint; // Number of scanned lines retrieved in total;
Bits: pointer; // data buffer pointer;
VaR bitinfo: tbitmapinfo; // bitmap information structure, which determines the data format of device-independent bitmaps;
Usage: uint // specify the format of the bmicolors Member of the tbitmapinfo structure.
): Integer; stdcall;

The format of the tbitmapinfo structure is as follows:

Tagbitmapinfo = packed record
Bmiheader: tbitmapinfoheader; // bitmap information header. This structure is used to describe the bitmap format;
Bmicolors: array [0 .. 0] of trgbquad; // color table, which provides the color palette data.
End;

The above structure mainly uses the bmiheader member. The format of the tbitmapinfoheader structure is as follows:

Tagbitmapinfoheader = packed record
Bisize: DWORD; // size of the current structure;
Biwidth: longint; // The width of the bitmap described in this structure is displayed in pixels;
Biheight: longint; // The height of the bitmap described in this structure is displayed in pixels;
Biplanes: word; // Number of flat planes of the target device, which must be 1;
Bibitcount: word; // The number of digits required by each pixel. When the image is true color, the value of this Member is 24;
Bicompression: DWORD; // The compression type of Bitmap. If the Member's value is bi_rgb, the image data is not compressed;
Bisizeimage: DWORD; // the size of the image data in bytes. If the image is a bi_rgb bitmap, the value of this Member must be set to 0;
Bixpelspermeter: longint; // the horizontal direction of the bitmap resolution is displayed in the unit of bytes per meter;
Biypelspermeter: longint; // the vertical direction of the bitmap resolution is displayed in the unit of bytes per meter;
Biclrused: DWORD; // Number of color changes in the color table used by the bitmap;
Biclrimportant: DWORD; // Number of addresses of important colors during bitmap display.
End;

In the above two structures, the bmicolours Member points to a color table, and the number of table items it contains is defined by the bmiheader. bibitcount member. When the value of this Member is 24, the table item in the color table is empty. When the biitcount value is 24 and the bicompression value is bi_rgb, the current bitmap is a 24-bit real color non-compressed bitmap. In this case, we can regard the bitmap data buffer as a one-dimensional byte array. Each 3 bytes represents one pixel. These three bytes define the pixel color in the order of blue (B), Green (G), and red (R. Pay attention to the byte sequence. Generally, the tcolor format we use is an RGB color in the red (R), Green (G), and blue (B) Order, the buffer zone uses BGR colors in the opposite order. In addition, the bitmap data extracted using getdibits is saved from left to right in the buffer from the bottom up, that is, the last row of the bitmap is saved from left to right, and then the last row of data is saved, and so on. In addition to reverse data storage, each row of data is 4 bytes (32 bits) aligned, when the length of a row of data cannot be fully divided by 4, it is filled with byte with a value of 0 at the end of each row so that the data can be fully divided by 4. For example, for bitmap with a width of 5 pixels, each row occupies 16 bytes. The first 15 bytes save 1 pixel color every 3 bytes, and then fill in 1 byte. For bitmap with a width of 10 pixels, each row occupies 32 bytes. The first 30 bytes save 1 pixel color every 3 bytes, and then fill 2 bytes.

You can access the data in the buffer zone by knowing the format of the data in the buffer zone. Now we will provide a demonstration of the relevant access.Code: First, the bitmap data buffer is a one-dimensional byte array, so this array bits can be defined according to the following code:

Type
Tbyteary = array [0 .. 0] of byte;
Pbyteary = ^ tbyteary;
VaR
Bits: pbyteary;

Next we assume there is a bitmap, which is a high-height pixel and a wide-width pixel. After alignment, you can use the following code to calculate the linewidth bytes of each line of data:

Linewidth: = (width * 24) + 31) and ($7fffffff-31) SHR 3;

The size of the bits array is linewidth * height. For the left (two-dimensional) position on any pixel location map, use the following code to calculate the position of the pixel data in the array bits (one-dimensional ):

Off: = (height-top-1) * linewidth) + (left * 3 );

Assuming a color value in BGR format, the following code reads a pixel color value from the off position of the array bits:

Color: = (pinteger (@ (BITS [off]) ^ and $ ffffff );

After using the getdibits function, you can no longer use the tbitmap object. The following sample code is used to display the current screen in full screen and extract the bitmap data to the buffer to return the result:

Procedure copyscreen (VAR bits: pbyteary; var size: integer );
VaR
Width, height, linewidth: integer;
WND: hwnd;
DC, memdc: HDC;
Bitmap, oldbitmap: hbitmap;
Bitinfo: tbitmapinfo;
Begin
// Data Initialization
Width: = getsystemmetrics (sm_cxscreen );
Height: = getsystemmetrics (sm_cyscreen );
Linewidth: = (width * 24) + 31) and ($7fffffff-31) SHR 3;
Size: = linewidth * height;
Getmem (bits, size );
//
WND: = getdomaintopwindow ();
DC: = getwindowdc (WND );
Memdc: = createcompatibledc (DC );
Bitmap: = createcompatiblebitmap (DC, width, height );
Oldbitmap: = SelectObject (memdc, bitmap );
Bitblt (memdc, 0, 0, width, height, DC, 0, srccopy );
Bitmap: = SelectObject (memdc, oldbitmap );
// Bitmap information Initialization
With bitinfo. bmiheader do
Begin
Bisize: = sizeof (tbitmapinfoheader );
Biwidth: = width;
Biheight: = height;
Biplanes: = 1;
Bibitcount: = 24;
Bicompression: = bi_rgb;
Bisizeimage: = 0;
Bixpelspermeter: = 0;
Biypelspermeter: = 0;
Biclrused: = 0;
Biclrimportant: = 0;
End;
// Extract data
Getdibits (DC, bitmap, 0, height, pointer (BITs), bitinfo, dib_rgb_colors );
Deletedc (memdc );
Deleteobject (Bitmap );
Deleteobject (oldbitmap );
Releasedc (WND, DC );
End;

For standard 24-bit BMP bitmap files, the bitmap data is also saved in the preceding format. Some 24-bit BMP files are not standard, so it is best to use the Windows built-in drawing program to save the files. The following sample code imports bitmap data from a standard 24-bit BMP file to the buffer and returns the result:

Procedure LoadFile (const filename: string; var bits: pbyteary; var size: integer );
VaR
Stream: tfilestream;
Fileheader: tbitmapfileheader;
Infoheader: tbitmapinfoheader;
Linewidth: integer;
Begin
Stream: = tfilestream. Create (filename, fmopenread );
// Read the file header
Stream. Read (fileheader, sizeof (tbitmapfileheader ));
Stream. Read (infoheader, sizeof (tbitmapinfoheader ));
With fileheader, infoheader do
Begin
// Determine the image format
If (bftype <> $4d42) or (bisize <> sizeof (tbitmapinfoheader) or
(Bibitcount <> 24) or (bicompression <> bi_rgb) then
Begin
Bits: = nil;
Size: = 0;
Exit;
End;
// Data Initialization
Linewidth: = (biwidth * 24) + 31) and ($7fffffff-31) SHR 3;
Size: = linewidth * biheight;
Getmem (bits, size );
End;
// Read data
Stream. Read (BITS ^, size );
Stream. Free;
End;

To sum up, when the bitmap data is extracted to a buffer zone, the process of searching for the color of the image is to access the data in the buffer zone. This buffer can be accessed as a matrix. You only need to traverse the Matrix to find the color of the image.

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.