取得TBitMap图像缓冲区

转载 2004年10月22日 16:33:00
使用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)不一定是等长的。有兴趣的可查阅相关资料。

获取TBitMap图像缓冲区,提高图像处理速度

  使用Dephi进行图像处理可以有多种方法,最常用的应该算是TBitmap,它提供方便的图像存取能力,结合Canvas可进行画线、画圆、图像拷贝等操作。不过在进行大量的图像处理操作时,为了获得更高的...
  • nhconch
  • nhconch
  • 2004年08月08日 14:28
  • 2969

Delphi图像处理 -- 图像像素结构与图像数据转换

    《Delphi图像处理 -- 数据类型及内部过程》一文中定义了基本的图像数据类型及一些内部过程,本文进一步将Delphi常用的图像类型转换为图像处理所需的数据结构,为具体的Delphi图像处理...
  • maozefa
  • maozefa
  • 2009年10月27日 21:41
  • 7936

BCB图像处理总结

近期遇到了一下图像处理的问题,特总结一下先说截图方式一、画布(Canvas)Graphics::TBitmap* bmp=new Graphics::TBitmap;TCanvas* canvas=n...
  • qq752923276
  • qq752923276
  • 2010年11月24日 17:25
  • 2082

Tbitmap

 Tbitmap Tbitmap是Windows位图(HBITMAP)的封装,包含调色板(HPALETTE)。 Unit Graphics 说明: 位图是一个可以用来创建,处理(scal...
  • hutao1101175783
  • hutao1101175783
  • 2014年02月09日 17:42
  • 1331

Delphi TBitMap 位图组件

位图组件(TBitMap)TBitMap组件不存在组件板,它封装了Windows的HBITMAP句柄和HPALETTE句柄,用于操纵位图和调色板。  TBitMap对象支持从文件、剪贴板、流中存取位...
  • a137268431
  • a137268431
  • 2015年08月19日 10:53
  • 1053

cout缓冲区管理

下面的程序是在vector中找元素,找到返回1,否则返回0;同时求出其相对位移vector::difference_type dif.#include #include #include #inclu...
  • xingzheziran
  • xingzheziran
  • 2015年12月22日 10:12
  • 610

用C++ Builder实现图像的特技显示

 在网页、软件和游戏中,我们经常可以看到图像的各种特技显示,如中心扩散、百叶窗帘、右下推出等,这种动感图像显示,往往给人一种赏心悦目的感觉,给我们的应用程序增加了一些美感。在C++ Builder中,...
  • iiprogram
  • iiprogram
  • 2007年10月14日 21:27
  • 688

Delphi的TBitmap对象改进的图像线性亮度调整方法

 线性图像亮度一般是将图像像素的RGB转换为HSL(HSV)等颜色空间,对L(V)部分进行增减调整后,再转换为RGB颜色空间,优点是调整过图像层次感很强;缺点是代码较复杂,调整速度慢,而且当图像亮度增...
  • aroc_lo
  • aroc_lo
  • 2009年11月26日 13:36
  • 672

TImage里的图形转为TJPEGImage,TBitmap

void __fastcall TForm1::Button1Click(TObject *Sender){    Graphics::TBitmap   *bmp=new   Graphics::T...
  • sding
  • sding
  • 2009年03月27日 09:10
  • 2347

Vulkan编程指南翻译 第四章 队列和命令 第3节 清空和填充图像

4.3 清空和填充图像 和缓冲区一样,也可以把数据直接复制到图像,或使用一个值填充。图像是更大、复杂、不透明的数据结构,所以原生的偏移量和数据通常对应用程序来说是不可见的。[2] 2. Of cour...
  • cloudqiu
  • cloudqiu
  • 2017年03月01日 12:04
  • 402
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:取得TBitMap图像缓冲区
举报原因:
原因补充:

(最多只允许输入30个字)