Reading Tips:
《Delphi Image ProcessingThe series focuses on efficiency. The general code is Pascal, and the core code is BaSm.
The C ++ image processing series focuses on code clarity and readability, all using C ++ code.
Make sure that the two items are consistent and can be compared with each other.
The code in this article must include the imagedata. Pas unit in "Delphi Image Processing-data type and public process.
Csdn forums often see screenshots. A screenshot is an operation that gets information from a screen or a window on the screen and converts it to an image. For this reason, I also wrote several "screenshot" functions in Windows:
function GetBitmapInfoHeader(const Data: TImageData): TBitmapInfoHeader;begin Result.biSize := Sizeof(TBitmapInfoHeader); Result.biWidth := Data.Width; Result.biHeight := Data.Height; Result.biPlanes := 1; Result.biBitCount := (Data.PixelFormat shr 8) and $ff; Result.biCompression := BI_RGB;end;procedure GetDCImageData(DC: HDC; x, y: Integer; var Data: TImageData; pbi: TBitmapInfo);var saveBitmap, Bitmap: HBITMAP; memDC: HDC;begin Bitmap := CreateCompatibleBitmap(DC, Data.Width, Data.Height); try memDC := CreateCompatibleDC(DC); saveBitmap := SelectObject(memDC, Bitmap); try BitBlt(memDC, 0, 0, Data.Width, Data.Height, DC, x, y, SRCCOPY); finally SelectObject(memDC, saveBitmap); DeleteDC(memDC); end; GetDIBits(DC, bitmap, 0, Data.Height, Data.Scan0, pbi, DIB_RGB_COLORS); finally DeleteObject(Bitmap); end;end;function GetImageDataFromDC(DC: HDC; Rect: TRect): TImageData; procedure FillAlpha; asm mov eax, Result mov edx, [eax].TImageData.Scan0 mov ecx, [eax].TImageData.Width imul ecx, [eax].TImageData.Height mov eax, 0ff000000h@@Loop: or [edx], eax add edx, 4 loop @@Loop end;var r: TRect; pbi: TBitmapInfo;begin FillChar(Result, Sizeof(TImageData), 0); if GetClipBox(DC, r) <= NULLREGION then Exit; if not IntersectRect(r, r, Rect) then Exit; Result := NewImageData(r.Right - r.Left, r.Bottom - r.Top); Result.AlphaFlag := False; pbi.bmiHeader := GetBitmapInfoHeader(Result); GetDCImageData(DC, r.Left, r.Top, Result, pbi); FillAlpha; _InvertScan0(Result);end;function GetHandleImageData(Handle: HWnd; Rect: TRect): TImageData;var DC: HDC;begin DC := GetDC(Handle); try Result := GetImageDataFromDC(DC, Rect); finally ReleaseDC(Handle, DC); end;end;function GetCanvasImageData(Canvas: TCanvas; Rect: TRect): TImageData;begin Result := GetImageDataFromDC(Canvas.Handle, Rect);end;function GetGpGraphicsImageData(g: TGpGraphics; Rect: TRect): TImageData;var DC: HDC;begin DC := g.GetHDC; try Result := GetImageDataFromDC(DC, Rect); finally g.ReleaseHDC(DC); end;end;
The above Code provides three "screenshot" methods, which are suitable for Delphi painting and layout TCanvas, window handle, and GDI + painting and layout tgpgraphics.
First, let's briefly introduce the implementation principles of this method:
The three "screenshot" methods are completed by calling the getimagedatafromdc function.
First, use the Windows API createcompatiblebitmap to create a bitmap handle compatible with the device context DC, and then call bitblt to copy the image data of the relevant device to the image in place;
Next, we need to copy the image data in the bitmap to the memory buffer of the timagedata type. Because no matter whether it is a display screen, window or other devices, the resolution is different. Taking the display quality as an example, the resolution is set to 32 bits or 16 bits, it is obviously difficult to convert 256 colors or lower quality to images in the corresponding pixel format. They must be converted into images in a uniform pixel format, for further analysis and processing, Windows provides this API, namely, the getdibits function, which can effectively solve this problem. In the internal process, gethbitmapdata calls API getdibits to complete this task.
Since the Delphi image processing series adopts a uniform 32-bit image pixel format, the geidibits function does not have the ability to fill the Alpha component in the 32-bit pixel format, this function is completed by the internal process fillalpha.
The scanned line of the obtained image data is in Windows bitmap format, that is, the first address of the scanned line is the last line of the image. Therefore, you must use _ invertscan0 to flip it over: point the first line of the image data to the first line of the image, and set the scanning line spacing to a negative number.
All screenshot image data must use freeimagedata to release the memory.
Theoretically, as long as the above three types of windows or devices can be provided, they can be converted to image data, but this is not the case:
1. Many devices are only written, such as printer devices, and image data cannot be provided in turn (Note: I have no printer equipment around me, and I did not test it, but I think it is based on experience ). Even if we think that the device context handle that should be able to obtain the image is often unable to meet our aspirations, such as the tgpbitmap of GDI +, we can associate a tgpgraphics type with it. In theory, we use tgpgraphics. the device context obtained by getdc should be able to obtain the image data of tgpbitmap. However, I tried multiple times to get only a black-filled image;
2. for various windows displayed on the display screen, the expected image data may not be obtained, because after all or part of the window is blocked, windows does not draw blocked windows (or some windows). We can only correctly obtain the image of the current Cropping Area of the device. The remaining part is not black, and it is messy, capturing their image data is meaningless. Therefore, in the internal process getimagedatafromdc, only the image data of the Current DC Cropping Area (Calculated using the API getclipbox) is obtained.
A simple example is used to obtain the image data of the current window, move it to the right by 50, and display it in the current window. You can also change canvas to handle:
procedure TForm1.Button4Click(Sender: TObject);var data: TImageData;begin data := GetCanvasImageData(Canvas, ClientRect); ImageDraw(Canvas.Handle, 50, 0, data); FreeImageData(data);end;
For the imagedraw process in the code, see 《Delphi Image Processing-Image Display.
For details about the use of GDI + units and descriptions in the "Delphi image processing" series, see the article 《GDI + for VCL basics-GDI + and VCL.
Due to limited levels, errors are inevitable. Correction and guidance are welcome. Email Address:Maozefa@hotmail.com
Here, you can access "Delphi Image Processing-Article Index".