TBITMAP双缓冲

来源:互联网 发布:手机备份数据在哪里 编辑:程序博客网 时间:2024/05/19 18:16
  首 页 | 新 闻 | 技术中心 | 第二书店 | 《程序员》 | 《开发高手》 | 社 区 | 黄 页 | 人 才
移 动专 题SUNIBM微 软微 创精 华Donews人 邮
我的技术中心 
我的分类我的文档
全部文章发表文章
专栏管理使用说明

 RSS 订阅 
最新文档列表
Windows/.NET
.NET  (rss)    
Visual C++  (rss)    
Delphi  (rss)    
Visual Basic  (rss)    
ASP  (rss)    
JavaScript  (rss)    
Java/Linux
Java  (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;
Description
ScanLine 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]: E90BB8
ScanLine[1]: E90000
ScanLine[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)不一定是等长的。有兴趣的可查阅相关资料。

 


相关文章
对该文的评论


网站简介 - 广告服务 - 网站地图 - 帮助信息 - 联系方式 - English
北京百联美达美数码科技有限公司 版权所有 京ICP证020026号
Copyright © CSDN.NET, Inc. All Rights Reserved
原创粉丝点击