首 页 | 新 闻 | 技术中心 | 第二书店 | 《程序员》 | 《开发高手》 | 社 区 | 黄 页 | 人 才 移 动∣专 题∣SUN∣IBM∣微 软∣微 创∣精 华∣Donews∣人 邮 我的技术中心 我的分类我的文档全部文章发表文章专栏管理使用说明 RSS 订阅 最新文档列表 Windows/.NET.NET (rss) Visual C++ (rss) Delphi (rss) Visual Basic (rss) ASP (rss) JavaScript (rss) Java/LinuxJava (rss) Perl (rss) 综合其他开发语言 (rss) 文件格式 (rss) 企业开发游戏开发 (rss) 网站制作技术 (rss) 数据库数据库开发 (rss) 软件工程其他 (rss) 积极原创作者 A8P8D3JK (1)adamsun (3)ahxu (2)maoerzuozuo (6)playyuer (30)lgchao (2)devercn (8)foxmail (3)netcasper (2)cker (12) CSDN - 文档中心 - Delphi 阅读:566 评论: 0 参与评论 标题 获取TBitMap图像缓冲区,提高图像处理速度 nhconch [原作] 关键字 获取TBitMap图像缓冲区,提高图像处理速度出处 使用Dephi进行图像处理可以有多种方法,最常用的应该算是TBitmap,它提供方便的图像存取能力,结合Canvas可进行画线、画圆、图像拷贝等操作。不过在进行大量的图像处理操作时,为了获得更高的速度,我们希望能够直接对图像缓冲区进行读写。查阅Dephi的帮助手册没有发现直接取得整个图像缓冲区的功能,但提供的ScanLine属性可以取得指定行图像数据的指针,比较接近我们的要求,先看看ScanLine的描述: Provides indexed access to each line of pixels.property ScanLine[Row: Integer]: Pointer;DescriptionScanLine is used only with DIBs (Device Independent Bitmaps) for image editing tools that do low-level pixel work. 让我们再看看ScanLine[0]、ScanLine[1]的关系: procedure TForm1.Button1Click(Sender: TObject);var BitMap: TBitmap; S: String;begin BitMap := TBitmap.Create; try BitMap.PixelFormat := pf24bit; //24位色,每像素点3个字节 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 if Assigned(BitMap) then FreeAndNil(BitMap); end;end; 下面是运行结果: ScanLine[0]: E90BB8ScanLine[1]: E90000ScanLine[1]-ScanLine[0]:-3000 前两个结果因机器不同而不同,第三个结果很特别,ScanLine[0]与ScanLine[1]之间相差3000=1000像素宽×3字节这很容易理解,但为什么是负数呢?因为BMP图像数据是“按行存放,每行按双字对齐,行按倒序方式存放”的,也就是说屏幕显示的第一行存放在最后,屏幕显示的最后一行存放在前面,所以用ACDSee等看图软件查看尺寸较大的位图时先从下部开始显示就是这个道理。 从上面的结果可以看出TBitmap的图像数据在内存中是按行倒序连续存放的,通过TBitmap.ScanLine[TBitmap.Height-1]可以取得首地址即图像缓冲区地址。接着我们来实践一下,通过直接对图像缓冲区的读写将图像淡出到黑色: 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]; //取得图像缓冲区首地址 //Integer(BitMap.ScanLine[0]) + FIX_WIDTH*3 为图像缓冲区结束地址 while Integer(lpBuffer) < Integer(BitMap.ScanLine[0]) + FIX_WIDTH*3 do begin if lpBuffer^>FADEOUT_STEP then begin Dec(lpBuffer^, FADEOUT_STEP); flagAgein := true; end else lpBuffer^ :=0; Inc(lpBuffer); Application.ProcessMessages; end; Canvas.Draw(0, 0, BitMap); until (not flagAgein); MessageBox(Handle, 'Done', 'Fadeout', MB_OK); finally if Assigned(BitMap) then FreeAndNil(BitMap); Button1.Visible := true; end;end; 最后补充说明一下: 1、Bitmap图像缓冲区是双节对齐的,如果把例1中的图像宽度改为999,一个像素行还是占3000个字节。 2、目前Bitmap.PixelFormat有pfDevice、pf1bit、pf4bit、pf8bit、pf15bit、pf16bit、pf24bit、pf32bit、pfCustom共9种,不同格式每个像素所占字节数不同,其中pf4bit和pf8bit格式的图像缓冲区保存的为颜色索引号,真正的颜色值在调色板中,pf15bit、pf16bit格式中RGB所占的位数(Bit)不一定是等长的。有兴趣的可查阅相关资料。 作者Blog: http://blog.csdn.net/nhconch/ 相关文章 SQL数据库ID备忘录 判断密码是不是简单文本的函数 获取TBitMap图像缓冲区,提高图像处理速度 自定义网页右键弹出菜单 ASP的数据库类 对该文的评论 【评论】 【关闭】 网站简介 - 广告服务 - 网站地图 - 帮助信息 - 联系方式 - English 北京百联美达美数码科技有限公司 版权所有 京ICP证020026号Copyright © CSDN.NET, Inc. All Rights Reserved <script> document.write(" "); </script>