使用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]可以取得首地址即图像缓冲区地址。接着我们来实践一下,通过直接对图像缓冲区的读写将图像淡出到黑色:

{======================================================================
  DESIGN BY :  彭国辉
  SITE:        http://kacarton.yeah.net/
  BLOG:        http://blog.csdn.net/nhconch
  EMAIL:       kacarton@sohu.com

文章为作者原创,转载前请先与本人联系,转载请注明文章出处、保留作者信息,谢谢支持!
======================================================================}

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)不一定是等长的。有兴趣的可查阅相关资料。

http://blog.csdn.net/nhconch/article/details/68479

获取TBitMap图像缓冲区,提高图像处理速度的更多相关文章

  1. NeuralEnhance: 提高图像分辨率的深度学习模型

    NeuralEnhance是使用深度学习训练的提高图像分辨率的模型,使用Python开发,项目地址:https://github.com/alexjc/neural-enhance. 貌似很多电影都有 ...

  2. Python 图像处理 OpenCV (3):图像属性、图像感兴趣 ROI 区域及通道处理

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 图像属性 图像 ...

  3. Opencv-Python:图像尺寸、图像的读取、显示、保存与复制

    Opencv-Python:图像尺寸.图像的读取.显示.保存与复制 原创 2017年11月23日 21:30:49 4440 在使用opencv的方法时,首先必须导入opencv包.新的opencv导 ...

  4. 五、如何通过CT三维图像得到DRR图像

    一.介绍 获取DRR图像是医疗图像配准里面的一个重要的前置步骤:它的主要目的是,通过CT三维图像,获取模拟X射线影像,这个过程也被称为数字影响重建. 在2D/3D的配准流程里面,需要首先通过CT三维图 ...

  5. 14、OpenCV实现图像的空间滤波——图像锐化及边缘检测

    1.图像锐化理论基础 1.锐化的概念 图像锐化的目的是使模糊的图像变得清晰起来,主要用于增强图像的灰度跳变部分,这一点与图像平滑对灰度跳变的抑制正好相反.而且从算子可以看出来,平滑是基于对图像领域的加 ...

  6. OpenCV计算机视觉学习(1)——图像基本操作(图像视频读取,ROI区域截取,常用cv函数解释)

    1,计算机眼中的图像 我们打开经典的 Lena图片,看看计算机是如何看待图片的: 我们点击图中的一个小格子,发现计算机会将其分为R,G,B三种通道.每个通道分别由一堆0~256之间的数字组成,那Ope ...

  7. OpenCV计算机视觉学习(11)——图像空间几何变换(图像缩放,图像旋转,图像翻转,图像平移,仿射变换,镜像变换)

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 图像 ...

  8. 学习 opencv---(3) ROI 区域图像叠加&初级图像混合

    在这篇文章里,我们一起学习了在OpenCV中如何定义感兴趣区域ROI,如何使用addWeighted函数进行图像混合操作,以及将ROI和addWeighted函数结合起来使用,对指定区域进行图像混合操 ...

  9. 本图片处理类功能非常之强大可以实现几乎所有WEB开发中对图像的处理功能都集成了,包括有缩放图像、切割图像、图像类型转换、彩色转黑白、文字水印、图片水印等功能

    import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphic ...

随机推荐

  1. Java字节码中的方法调用

    invokestatic,用于static修饰的方法.任何时候调用的时候只需要类名+方法名即可,无需new.JVM直接将其映射到方法区,执行速度极快.当该方法需要参数的时候,invokestatic会 ...

  2. QML在XP等显卡明显不好的情况下 可以参考

    http://doc.qt.io/qt-5/windows-requirements.html

  3. scrapy入门

    安装完scrapy后,创建一个新的工程: scrapy startproject tutorial 会创建一个tutorial文件夹有以下的文件: tutorial/ scrapy.cfg tutor ...

  4. uva 816 - Abbott&#39;s Revenge(有点困难bfs迷宫称号)

    是典型的bfs,但是,这个问题的目的在于读取条件的困难,而不是简单地推断,需要找到一种方法来读取条件.还需要想办法去推断每一点不能满足条件,继续往下走. #include<cstdio> ...

  5. 一款简单的客户端安卓手机qq源码

    给大家分享一款比较简单的安卓手机qq应用源码,效果非常不错,大家可以借鉴一下,希望大家会喜欢. 1.png  (7.24 KB, 下载次数: 0) 02.png  (68.52 KB, 下载次数: 0 ...

  6. T-Sql中的pivot和unpivot

    写在前面 今天休息,抽空了解下pivot和unpivot,记得老师讲行转列的时候,貌似提到过,不过他说的最多的就是“这个你们私下可以自己学,很简单的...”,简单你咋不讲呢,不吐槽他了,还是好好整理下 ...

  7. 如何将UISearchBar上"Cancel"按钮改为”取消“?

    别说话,直接上代码 for (id obj in [searchBar subviews]) {        if ([obj isKindOfClass:[UIView class]]) {    ...

  8. Source Insight使用技巧

    1. source insight必设: option-->key assignments-->    Edit: Delete Line ---- Assign New Key: Ctr ...

  9. 分享非常有用的Java程序(关键代码)(七)---抓屏程序

    原文:分享非常有用的Java程序(关键代码)(七)---抓屏程序 import java.awt.Dimension; import java.awt.Rectangle; import java.a ...

  10. jackson 转json. 过滤null值

    @Test public void tttttt() throws JsonGenerationException, JsonMappingException, IOException { Objec ...