在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
使用Dephi进行图像处理可以有多种方法,最常用的应该算是TBitmap,它提供方便的图像存取能力,结合Canvas可进行画线、画圆、图像拷贝等操作。 property ScanLine[Row: Integer]: Pointer; Provides indexed access to each line of pixels. tagBITMAPINFOHEADER = record biSize: DWORD; biWidth: Longint; biHeight: Longint; biPlanes: Word; biBitCount: Word; biCompression: DWORD; biSizeImage: DWORD; biXPelsPerMeter: Longint; biYPelsPerMeter: Longint; biClrUsed: DWORD; biClrImportant: DWORD; end; DWORD biSize;//指定结构需要的比特数。这个值不包含在结构的结尾被添上的颜色表或者颜色盒的大小。 biWidth The width of the bitmap, in pixels. biHeight The height of the bitmap, in pixels. If biCompression is BI_JPEG or BI_PNG, the biHeight member specifies the height of the decompressed JPEG or PNG image file, respectively. BI_RGB BI_BITFIELDS
function BytesPerScanline(PixelsPerScanline, BitsPerPixel, Alignment: Longint): Longint; begin Dec(Alignment); Result := ((PixelsPerScanline * BitsPerPixel) + Alignment) and not Alignment; Result := Result div 8; end;
procedure TForm1.Button1Click( Sender : TObject ); var BitMap : TBitmap; S : String; begin BitMap := TBitmap.Create; try BitMap.PixelFormat := pf24bit; // 24位色,每像素点3个字节 -- 首先设置 PixelFormat 否则出错 ! BitMap.Width := 1000; BitMap.Height := 2; // BitMap.Height := -2; -- Top-Down DIB [ ScanLine[0] -- First Row ] 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 if Assigned( BitMap ) then FreeAndNil( BitMap ); end; end ScanLine[0]: E90BB8 ScanLine[1]: E90000 ScanLine[1]-ScanLine[0]:-3000 让我们再看看ScanLine[0]、ScanLine[1]的关系, ScanLine[0]与ScanLine[1]之间相差3000=1000像素宽×3字节这很容易理解,但为什么是负数呢? Memory : Bottom-Up DIB : origin is the lower-left corner ScanLine[H-1] \ / ***************** ScanLine[H-2] \ / ***************** \/ ScanLine[1] /\ ***************** ScanLine[0] / \ ***************** Memory : Top-Down DIB : origin is the upper-left corner. ScanLine[0] ----- ***************** ScanLine[1] ----- ***************** ScanLine[H-2] ----- ***************** ScanLine[H-1] ----- ***************** http://msdn.microsoft.com/en-us/library/windows/desktop/dd407212(v=vs.85).aspx If you are new to graphics programming, you might expect that a bitmap would be arranged in memory In a bottom-up DIB, the image buffer starts with the bottom row of pixels, followed by the next row up, and so forth.
In a top-down DIB, the order of the rows is reversed.
For RGB DIBs, the image orientation is indicated by the biHeight member of the BITMAPINFOHEADER structure. DIBs in YUV formats are always top-down, and the sign of the biHeight member is ignored. Also, any DIB type that uses a FOURCC in the biCompression member, should express its biHeight as a positive number no matter
function CreateDIB_TopDown( nWidth, nHeight : Integer ) : HBITMAP; var hbm : HBITMAP; hdcMem : HDC; bmi : BITMAPINFO; Bitmap data area
最后补充说明一下:
通过直接对图像缓冲区的读写将图像淡出到黑色 procedure TForm1.Button1Click( Sender : TObject ); const FADEOUT_STEP = 24; // 淡出衰减值 FIX_WIDTH = 320; FIX_HEIGHT = 200; var BitMap : TBitmap; hWinDC : HDC; flagAgein : Boolean; lpBuffer : PByte; // 图像缓冲区指针 begin BitMap := TBitmap.Create; if not Assigned( BitMap ) then Exit; try // 设置位图格式、宽度、高度 BitMap.PixelFormat := pf24bit; BitMap.Width := FIX_WIDTH; BitMap.Height := FIX_HEIGHT; // 设置Form的宽充、高度,便于显示结果 Button1.Visible := false; ClientWidth := FIX_WIDTH; ClientHeight := FIX_HEIGHT; // 拷贝图像到Bitmap中 hWinDC := GetDC( 0 ); if ( hWinDC <> NULL ) then BitBlt( BitMap.Canvas.Handle, 0, 0, FIX_WIDTH, FIX_HEIGHT, hWinDC, 0, 0, SRCCOPY ) else BitBlt( BitMap.Canvas.Handle, 0, 0, FIX_WIDTH, FIX_HEIGHT, Canvas.Handle, 0, 0, SRCCOPY ); repeat flagAgein := false; lpBuffer := BitMap.ScanLine[ FIX_HEIGHT - 1 ];
Bitmap.Scanline for PixelFormat=pf1bit, pf8bit, pf24bitSince someone from Italy asked me for an example of using pf1bit Bitmaps, I thought I would post part of my response and add other details for pf8bit and pf24bit here in case others were wondering. BackgroundThe new Delphi 3 scanline property allows quick access to individual pixels, but you must know what Bitmap.PixelFormat you're working with before you can access the pixels. Possible PixelFormats include: pfDevice pf1bit pf4bit pf8bit pf15bit pf16bit pf24bit pf32bit For pf24bit bitmaps, I define (I wish Borland would) CONST PixelCountMax = 32768; TYPE pRGBArray = ^TRGBArray; TRGBArray = ARRAY [ 0 .. PixelCountMax - 1 ] OF TRGBTriple; Note: TRGBTriple is defined in the Windows.PAS unit. To step through a 24-bit bitmap and while creating a new one and access the 3-bytes-per-pixel data, use a construct like the following VAR i : INTEGER; j : INTEGER; RowOriginal : pRGBArray; RowProcessed : pRGBArray; BEGIN IF OriginalBitmap.PixelFormat <> pf24bit THEN RAISE EImageProcessingError.Create( 'GetImageSpace: ' + 'Bitmap must be 24-bit color.' ); { Step through each row of image. } FOR j := OriginalBitmap.Height - 1 DOWNTO 0 DO BEGIN RowOriginal := pRGBArray( OriginalBitmap.Scanline[ j ] ); RowProcessed := pRGBArray( ProcessedBitmap.Scanline[ j ] ); FOR i := OriginalBitmap.Width - 1 DOWNTO 0 DO BEGIN // Access individual color RGB color planes with references like: // RowProcessed[i].rgbtRed := RowOriginal[i].rgbtRed; // RowProcessed[i].rgbtGreen := RowOriginal[i].rgbtGreen; // RowProcessed[i].rgbtBlue := RowOriginal[i].rgbtBlue; END END END; pf8bit Bitmaps Access to these byte-per-pixel bitmaps is easy using the TByteArray (defined in SysUtils.PAS) PByteArray = ^TByteArray; TByteArray = array[0..32767] of Byte; I suppose, but I've never tried it, you could access pf16bit Bitmaps using the following defined in SysUtils.PAS: PWordArray = ^TWordArray; TWordArray = array[0..16383] of Word; ) To process an 8-bit (pf8bit) bitmap, use a construct like the following that constructs a histogram of such a bitmap: VAR Histogram : THistogram; i : INTEGER; j : INTEGER; Row : pByteArray; FOR i := Low( THistogram ) TO High( THistogram ) DO IF Bitmap.PixelFormat = pf8bit THEN BEGIN FOR j := Bitmap.Height - 1 DOWNTO 0 DO BEGIN Row := pByteArray( Bitmap.Scanline[ j ] ); FOR i := Bitmap.Width - 1 DOWNTO 0 DO BEGIN INC( Histogram[ Row[ i ] ] ) END END END pf1bit Bitmaps Accessing pf8bit bitmaps is easy since they are one byte per pixel. The following code shows how to create the following kinds of 1-bit bitmaps: Create a form with an Image1: TImage on it -- I used 1 256x256 Image1 with Stretch := TRUE to see the individual pixels more easily. // Example of how to use Bitmap.Scanline for PixelFormat=pf1Bit. // Requested by Mino Ballone from Italy. // // Copyright (C) 1997, Earl F. Glynn, Overland Park, KS. All rights reserved. // May be freely used for non-commerical purposes. unit ScreenSingleBit; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class( TForm ) Image1 : TImage; ButtonBlack : TButton; ButtonWhite : TButton; ButtonStripes : TButton; ButtonG : TButton; ButtonArrow : TButton; ButtonRandom : TButton; ButtonInvert : TButton; procedure ButtonStripesClick( Sender : TObject ); procedure ButtonGClick( Sender : TObject ); procedure FormCreate( Sender : TObject ); procedure FormDestroy( Sender : TObject ); procedure ButtonRandomClick( Sender : TObject ); procedure ButtonInvertClick( Sender : TObject ); procedure ButtonArrowClick( Sender : TObject ); private Bitmap : TBitmap; { Private declarations } public { Public declarations } end; var Form1 : TForm1; implementation {$R *.DFM} CONST BitsPerPixel = 8; procedure TForm1.ButtonStripesClick( Sender : TObject ); VAR i : INTEGER; j : INTEGER; Row : pByteArray; Value : BYTE; begin Value := ( Sender AS TButton ).Tag; // Value = $00 = 00000000 binary for black // Value = $FF = 11111111 binary for white // Value = $55 = 01010101 binary for black & white stripes FOR j := 0 TO Bitmap.Height - 1 DO BEGIN Row := pByteArray( Bitmap.Scanline[ j ] ); FOR i := 0 TO ( Bitmap.Width DIV BitsPerPixel ) - 1 DO BEGIN Row[ i ] := Value END END; Image1.Picture.Graphic := Bitmap end; procedure TForm1.ButtonGClick( Sender : TObject ); CONST { The "g" bitmap was adapted from the LaserJet IIP Printer Tech Ref Manual } G : ARRAY [ 0 .. 31, 0 .. 3 ] OF BYTE = { 0 } ( ( $00, $FC, $0F, $C0 ), { 00000000 11111100 00001111 11000000 } { 1 } ( $07, $FF, $1F, $E0 ), { 00000111 11111111 00011111 11100000 } { 2 } ( $0F, $FF, $9F, $C0 ), { 00001111 11111111 10011111 11000000 } { 3 } ( $3F, $D7, $DE, $00 ), { 00111111 11010111 11011110 00000000 } { 4 } ( $3E, $01, $FE, $00 ), { 00111110 00000001 11111110 00000000 } { 5 } ( $7C, $00, $7E, $00 ), { 01111100 00000000 01111110 00000000 } { 6 } ( $78, $00, $7E, $00 ), { 01111000 00000000 01111110 00000000 } { 7 } ( $F0, $00, $3E, $00 ), { 11110000 00000000 00111110 00000000 } { 8 } ( $F0, $00, $3E, $00 ), { 11110000 00000000 00111110 00000000 } { 9 } ( $F0, $00, $1E, $00 ), { 11110000 00000000 00011110 00000000 } { 10 } ( $F0, $00, $1E, $00 ), { 11110000 00000000 00011110 00000000 } { 11 } ( $F0, $00, $1E, $00 ), { 11110000 00000000 00011110 00000000 } { 12 } ( $F0, $00, $1E, $00 ), { 11110000 00000000 00011110 00000000 } { 13 } ( $F0, $00, $3E, $00 ), { 11110000 00000000 00111110 00000000 } { 14 } ( $78, $00, $3E, $00 ), { 01111000 00000000 00111110 00000000 } { 15 } ( $78, $00, $3E, $00 ), { 01111000 00000000 00111110 00000000 } { 16 } ( $78, $00, $7E, $00 ), { 01111000 00000000 01111110 00000000 } { 17 } ( $3C, $00, $FE, $00 ), { 00111100 00000000 11111110 00000000 } { 18 } ( $1F, $D7, $DE, $00 ), { 00011111 11010111 11011110 00000000 } { 19 } ( $0F, $FF, $5E, $00 ), { 00001111 11111111 10011110 00000000 } { 20 } ( $07, $FF, $1E, $00 ), { 00000111 11111111 00011110 00000000 } { 21 } ( $00, $A8, $1E, $00 ), { 00000000 10101000 00011110 00000000 } { 22 } ( $00, $00, $1E, $00 ), { 00000000 00000000 00011110 00000000 } { 23 } ( $00, $00, $1E, $00 ), { 00000000 00000000 00011110 00000000 } { 24 } ( $00, $00, $1E, $00 ), { 00000000 00000000 00011110 00000000 } { 25 } ( $00, $00, $3E, $00 ), { 00000000 00000000 00111110 00000000 } { 26 } ( $00, $00, $3C, $00 ), { 00000000 00000000 00111100 00000000 } { 27 } ( $00, $00, $7C, $00 ), { 00000000 00000000 01111100 00000000 } { 28 } ( $00, $01, $F8, $00 ), { 00000000 00000001 11111000 00000000 } { 29 } ( $01, $FF, $F0, $00 ), { 00000001 11111111 11110000 00000000 } { 30 } ( $03, $FF, $E0, $00 ), { 00000011 11111111 11100000 00000000 } { 31 } ( $01, $FF, $80, $00 ) { 00000001 11111111 10000000 00000000 } ); VAR i : INTEGER; j : INTEGER; Row : pByteArray; begin FOR j := 0 TO Bitmap.Height - 1 DO BEGIN Row := pByteArray( Bitmap.Scanline[ j ] ); FOR i := 0 TO ( Bitmap.Width DIV BitsPerPixel ) - 1 DO BEGIN Row[ i ] := G[ j, i ] END END; Image1.Picture.Graphic := Bitmap end; procedure TForm1.ButtonArrowClick( Sender : TObject ); CONST { The "arrow" bitmap was adapted from the LaserJet IIP Printer Tech Ref Manual } Arrow : ARRAY [ 0 .. 31, 0 .. 3 ] OF BYTE = { 0 } ( ( $00, $00, $80, $00 ), { 00000000 00000000 10000000 00000000 } { 1 } ( $00, $00, $C0, $00 ), { 00000000 00000000 11000000 00000000 } { 2 } ( $00, $00, $E0, $00 ), { 00000000 00000000 11100000 00000000 } { 3 } ( $00, $00, $F0, $00 ), { 00000000 00000000 11110000 00000000 } { 4 } ( $00, $00, $F8, $00 ), { 00000000 00000000 11111000 00000000 } { 5 } ( $00, $00, $FC, $00 ), { 00000000 00000000 11111100 00000000 } { 6 } ( $00, $00, $FE, $00 ), { 00000000 00000000 11111110 00000000 } { 7 } ( $00, $00, $FF, $00 ), { 00000000 00000000 11111111 00000000 } { 8 } ( $00, $00, $FF, $80 ), { 00000000 00000000 11111111 10000000 } { 9 } ( $FF, $FF, $FF, $C0 ), { 11111111 11111111 11111111 11000000 } { 10} ( $FF, $FF, $FF, $E0 ), { 11111111 11111111 11111111 11100000 } { 11} ( $FF, $FF, $FF, $F0 ), { 11111111 11111111 11111111 11110000 } { 12} ( $FF, $FF, $FF, $F8 ), { 11111111 11111111 11111111 11111000 } { 13} ( $FF, $FF, $FF, $FC ), { 11111111 11111111 11111111 11111100 } { 14} ( $FF, $FF, $FF, $FE ), { 11111111 11111111 11111111 11111110 } { 15} ( $FF, $FF, $FF, $FF ), { 11111111 11111111 11111111 11111111 } { 16} ( $FF, $FF, $FF, $FF ), { 11111111 11111111 11111111 11111111 } { 17} ( $FF, $FF, $FF, $FE ), { 11111111 11111111 11111111 11111110 } { 全部评论
专题导读
热门推荐
热门话题
阅读排行榜
|
请发表评论