There are multiple ways to use dephi for image processing. The most commonly used method is tbitmap, which provides convenient image access capabilities. Combined with canvas, you can draw lines, draw circles, and copy images. However, when performing a large number of image processing operations, we hope to directly read and write the image buffer to achieve higher speed. Looking at the help manual of dephi, we did not find the function of directly obtaining the entire image buffer, but the scanline attribute provided can get the pointer of the specified row of image data, which is close to our requirements, first look at the scanline description:
Provides indexed access to each line of pixels. PropertyScanline [row: integer]: pointer; Description Scanline is used only with dibs (device independent bitmaps) for image editing tools that do low-level pixel work.
|
Let's look at the relationship between scanline [0] And scanline [1:
ProcedureTform1.button1click (Sender: tobject ); VaR Bitmap: tbitmap; S: string; Begin Bitmap: = tbitmap. Create; Try Bitmap. pixelformat: = pf24bit;// 24-bit color, 3 bytes per pixel Bitmap. Width := 1000; Bitmap. Height: = 2; Fmtstr (S, 'scanline [0]: % 8x' #13 'scanline [1]: % 8x' #13 'scanline [1]-scanline [0]: % d' , [INTEGER (bitmap. scanline [0]), INTEGER (bitmap. scanline [1]) , INTEGER (bitmap. scanline [1])-INTEGER (bitmap. scanline [0]); MessageBox (handle, pchar (s), 'scanline', mb_ OK ); Finally IfAssigned (Bitmap)ThenFreeandnil (Bitmap ); End; End;
|
The running result is as follows:
Scanline [0]: e90bb8 Scanline [1]: e90000 Scanline [1]-scanline [0]:-3000. |
The first two results vary depending on the machine, and the third result is very special. The difference between scanline [0] And scanline [1] is 3000 = 1000 pixels wide × 3 bytes, which is easy to understand, but why is it a negative number? Because BMP image data is stored by row, each line is aligned by double words, and rows are stored in reverse order. That is to say, the first line displayed on the screen is stored at the end, the last line displayed on the screen is stored in the front. Therefore, when you use ACDSee or other image-watching software to view larger bitmaps, you must first display them from the lower part.
From the above results, we can see that the image data of tbitmap is continuously stored in the memory in inverted order. The first address is the image buffer address through tbitmap. scanline [tbitmap. Height-1. Next, let's take a look at how to fade out the image to black by Directly Reading and Writing the image buffer:
{===================================================== ==================================== Design by: Peng Guohui Site: http://kacarton.yeah.net/ Blog: http://blog.csdn.net/nhconch Email: kacarton@sohu.com The article is original to the author. Please contact me before reprinting. for reprinting, please indicate the source of the article and retain the author information. Thank you for your support! ========================================================== =================================} ProcedureTform1.button1click (Sender: tobject ); Const Fadeout_step = 24; // fade out attenuation value Fix_width = 320; Fix_height = 200; VaR Bitmap: tbitmap; Hwindc: HDC; Flagagein: Boolean; Lpbuffer: pbyte; // image buffer pointer Begin Bitmap: = tbitmap. Create; If notAssigned (Bitmap)ThenExit; Try // Sets the bitmap format, width, and height. Bitmap. pixelformat: = pf24bit; Bitmap. Width: = fix_width; Bitmap. Height: = fix_height; // Set the width and height of the form to facilitate display of results Button1.visible: = false; Clientwidth: = fix_width; Clientheight: = fix_height; // Copy the image to bitmap Hwindc: = getdc (0 ); If(Hwindc <> null)ThenBitblt (bitmap. Canvas. Handle, 0, 0, fix_width, fix_height, hwindc, 0, 0, srccopy) ElseBitblt (bitmap. Canvas. Handle, 0, 0, fix_width, fix_height, canvas. Handle, 0, 0, srccopy ); Repeat Flagagein: = false; Lpbuffer: = bitmap. scanline [FIX_HEIGHT-1]; // get the first address of the Image Buffer // INTEGER (bitmap. scanline [0]) + fix_width * 3 indicates the end address of the image buffer. WhileINTEGER (lpbuffer) <INTEGER (bitmap. scanline [0]) + fix_width * 3Do begin IfLpbuffer ^> fadeout_stepThen Begin Dec (lpbuffer ^, fadeout_step ); Flagagein: = true; End ElseLpbuffer ^: = 0; INC (lpbuffer ); Application. processmessages; End; Canvas. Draw (0, 0, bitmap ); Until(NotFlagagein ); MessageBox (handle, 'done', 'fadeout', mb_ OK ); Finally IfAssigned (Bitmap)ThenFreeandnil (Bitmap ); Button1.visible: = true; End; End;
|
The following is a further explanation:
1. bitmap image buffer is dual-node alignment. If the image width in Example 1 is changed to 999, a pixel Row still occupies 3000 bytes.
2. Currently, bitmap. pixelformat includes pfdevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit, pf32bit, and pfcustom. Each pixel occupies a different number of bytes in different formats, the image buffer in pf4bit and pf8bit formats stores the color index numbers. The true color values in the color palette are the bits occupied by RGB in pf15bit and pf16bit formats) not necessarily the same. If you are interested, refer to the relevant materials.