2015-01-03 22:03:11 maozefa 阅读数 5234
  • DelphiXE10零基础实战快速入门

    通过课堂上一个一个的实战例子,演示DelphiXE10的用法,最后通过一个完整的通讯录程序,让学员初步掌握软件开发的全部流程 让零基础学员快速入门Delphi编程,快速掌握Delphi的使用方法,并能够制作出自己的软件来。为同学们下一步的提高打下坚实的基础。

    1066 人正在学习 去看看 陈城

    有不少读者看了我的图像处理文章后,希望得到源代码,我很早就写了一份Delphi图像处理单元,但一直没有时间测试整理,这次元旦抽时间进行了简单的整理,发布在CSDN,有需要的读者可去下载。

    BLOG中的Delphi图像处理文章的代码属简化代码,可作参考。

    由于水平有限,代码中不可避免的存在错误,望进行指证。

   Delphi图像处理代码下载地址:http://download.csdn.net/detail/maozefa/8323289


  2015年1月27日修正:

  ImageUtils.pas的LineBrightContrast函数实现代码:

function LineBrightContrast(var Dest: TImageData; const Source: TImageData;
  Bright, Contrast: Integer; Threshold: Byte;
  Callback: TImageAbort; CallbackData: Pointer): Boolean;
var
  bTab, Table: TGrayTable;
begin
  _CheckCopyArgbData(Dest, Source);
  if Contrast = 0 then
    Result := _Execute(Dest, Source, @_DoBrightness, [Bright], Callback, CallbackData)
  else
  begin
    _GetLineBrightTable(Bright, bTab);
    _GetContrastsTable(Contrast, Threshold, bTab, Table);
    Result := _Execute(Dest, Source, @_DoTableReplace, [@Table], Callback, CallbackData);
  end;
end;

改为:

function LineBrightContrast(var Dest: TImageData; const Source: TImageData;
  Bright, Contrast: Integer; Threshold: Byte;
  Callback: TImageAbort; CallbackData: Pointer): Boolean;
var
  bTab, Table: TGrayTable;
begin
  _CheckCopyArgbData(Dest, Source);
  if (Bright <> 0) or (Contrast <> 0) then
  begin
    _GetLineBrightTable(Bright, bTab);
    _GetContrastsTable(Contrast, Threshold, bTab, Table);
    Result := _Execute(Dest, Source, @_DoTableReplace, [@Table], Callback, CallbackData);
  end
  else if Dest.Scan0 <> Source.Scan0 then
    Result := _Execute(Dest, Source, @_DoCopyArgbData, [], Callback, CallbackData)
  else Result := True;
end;





2011-03-10 00:51:00 xiaofkg 阅读数 826
  • DelphiXE10零基础实战快速入门

    通过课堂上一个一个的实战例子,演示DelphiXE10的用法,最后通过一个完整的通讯录程序,让学员初步掌握软件开发的全部流程 让零基础学员快速入门Delphi编程,快速掌握Delphi的使用方法,并能够制作出自己的软件来。为同学们下一步的提高打下坚实的基础。

    1066 人正在学习 去看看 陈城

 

 

一般我们在Delphi中进行图像处理时采用Pixels像素点赋值的方法,Delphi代码如下:

 

var

x,y:Integer;

cColor:TColor;

begin

  for y:=0 to Image1.Height-1 do

    for x:=0 to Image1.Width-1 do

      cColor:=Image1.Canvas.Pixels[i,j];

end;

 

 

但是这种方法有个缺点,处理速度很慢,小图像还可以,对于大点的图像来说就太慢了。

Delphi提供了一种扫描线ScanLine方法是对图像的一行进行扫描,获取本行中各像素的内存地址。众所周知,内存操作肯定会比常规的像素点赋值速度快很多,所以将大大提高图像的处理速度。

 

Delphi代码如下:

 

var

P:array[0..100] of PByteArray;//像素数组        

y:Integer;

begin

  for y:=0 to Bmp.Height-1 do

  begin

    P[y]:=Bmp.ScanLine[y];//将图片所有像素值存入P

  end;

end;

 

 

这样就将一个图像的所有像素都存入了P这个数组

在SysUtils单元中可以看出PByteArray实际上是一个Byte类型的数组

所以我们声明的P:array[0..100] of PByteArray;实际上可以看成是一个二维数组

P数组就是一个图像像素的缓冲区,它的一维是图像Y坐标,二维是图像的X坐标。

这样,如果我们要对图像的某个像素赋值,例如将第一行、第二列的像素赋值为白色,可用下面的Delphi代码

 

var

P:array[0..100] of PByteArray;//像素数组

x,y:Integer;

begin

  for y:=0 to Bmp.Height-1 do

  begin

    P[y]:=Bmp.ScanLine[y];//将图片所有像素值存入P

  end;

  y:=0;//第一行

  x:=1;//第二列

  P[y][x*3]:=255;//像素的第一字节

  P[y][x*3+1]:=255;//像素的第二字节

  P[y][x*3+2]:=255;//像素的第三字节

end;

 

 

上面的代码中,我们使用的图像是24位色的(TPixelFormat:=pf24bit),也就是一张真彩色的图片,pf24bit的图像中,每个像素在内存中占用三个字节,分别表示RGB值的分量,所以我们可以对三个字节直接赋值

 

在其它类型的图像中就不一定能这样赋值了

 

TPixelFormat:=pf1bit的图像(单色图)中每像素用1位来表示,所以要使用位操作来给像素赋值

 

TPixelFormat:=pf4bit的图像中每像素用4位来表示,也要使用位操作来给像素赋值

 

TPixelFormat:=pf8bit的图像中每像素用8位来表示,可以使用Byte类型的值给像素赋值,不过这类图像比较特殊,它的像素值并不是真正的颜色值,而只是调色板上颜色的索引值,这点要注意

 

TPixelFormat:=pf15bit的图像也是一种比较特殊的图像,它每像素用16位来表示,第1位为0,后15位每5位分别表示RGB值,所以也要使用位操作来给像素赋值

 

TPixelFormat:=pf16bit的图像中每像素用16位来表示,绿色占6位,其它红、蓝两种颜色占5位(为什么要这样?我也不知道,要问制定Bitmap格式的人了,据说是因为人眼对绿色比较敏感)

 

TPixelFormat:=pf24bit的图像每个像素用3个字节表示,这就不说了,参看上面的代码

 

TPixelFormat:=pf32bit的图像每个像素用4个字节表示,前面3个字节分别表示RGB值的分量,最后一个字节表示Alpha值

 

2011-04-15 10:44:00 god00 阅读数 687
  • DelphiXE10零基础实战快速入门

    通过课堂上一个一个的实战例子,演示DelphiXE10的用法,最后通过一个完整的通讯录程序,让学员初步掌握软件开发的全部流程 让零基础学员快速入门Delphi编程,快速掌握Delphi的使用方法,并能够制作出自己的软件来。为同学们下一步的提高打下坚实的基础。

    1066 人正在学习 去看看 陈城

一般我们在Delphi中进行图像处理时采用Pixels像素点赋值的方法,Delphi代码如下:

var
x,y:Integer;
cColor:TColor;
begin
  for y:=0 to Image1.Height-1 do
    for x:=0 to Image1.Width-1 do
      cColor:=Image1.Canvas.Pixels[i,j];
end;


但是这种方法有个缺点,处理速度很慢,小图像还可以,对于大点的图像来说就太慢了。
Delphi提供了一种扫描线ScanLine方法是对图像的一行进行扫描,获取本行中各像素的内存地址。众所周知,内存操作肯定会比常规的像素点赋值速度快很多,所以将大大提高图像的处理速度。

Delphi代码如下:

var
P:array[0..100] of PByteArray;//像素数组       
y:Integer;
begin
  for y:=0 to Bmp.Height-1 do
  begin
    P[y]:=Bmp.ScanLine[y];//将图片所有像素值存入P
  end;
end;


这样就将一个图像的所有像素都存入了P这个数组
在SysUtils单元中可以看出PByteArray实际上是一个Byte类型的数组
所以我们声明的P:array[0..100] of PByteArray;实际上可以看成是一个二维数组
P数组就是一个图像像素的缓冲区,它的一维是图像Y坐标,二维是图像的X坐标。
这样,如果我们要对图像的某个像素赋值,例如将第一行、第二列的像素赋值为白色,可用下面的Delphi代码

var
P:array[0..100] of PByteArray;//像素数组
x,y:Integer;
begin
  for y:=0 to Bmp.Height-1 do
  begin
    P[y]:=Bmp.ScanLine[y];//将图片所有像素值存入P
  end;
  y:=0;//第一行
  x:=1;//第二列
  P[y][x*3]:=255;//像素的第一字节
  P[y][x*3+1]:=255;//像素的第二字节
  P[y][x*3+2]:=255;//像素的第三字节
end;


上面的代码中,我们使用的图像是24位色的(TPixelFormat:=pf24bit),也就是一张真彩色的图片,pf24bit的图像中,每个像素在内存中占用三个字节,分别表示RGB值的分量,所以我们可以对三个字节直接赋值

在其它类型的图像中就不一定能这样赋值了

TPixelFormat:=pf1bit的图像(单色图)中每像素用1位来表示,所以要使用位操作来给像素赋值

TPixelFormat:=pf4bit的图像中每像素用4位来表示,也要使用位操作来给像素赋值

TPixelFormat:=pf8bit的图像中每像素用8位来表示,可以使用Byte类型的值给像素赋值,不过这类图像比较特殊,它的像素值并不是真正的颜色值,而只是调色板上颜色的索引值,这点要注意

TPixelFormat:=pf15bit的图像也是一种比较特殊的图像,它每像素用16位来表示,第1位为0,后15位每5位分别表示RGB值,所以也要使用位操作来给像素赋值

TPixelFormat:=pf16bit的图像中每像素用16位来表示,绿色占6位,其它红、蓝两种颜色占5位(为什么要这样?我也不知道,要问制定Bitmap格式的人了,据说是因为人眼对绿色比较敏感)

TPixelFormat:=pf24bit的图像每个像素用3个字节表示,这就不说了,参看上面的代码

TPixelFormat:=pf32bit的图像每个像素用4个字节表示,前面3个字节分别表示RGB值的分量,最后一个字节表示Alpha值

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ruanxundianzi/archive/2009/09/21/4576223.aspx

2010-12-13 12:39:00 shuaihj 阅读数 2769
  • DelphiXE10零基础实战快速入门

    通过课堂上一个一个的实战例子,演示DelphiXE10的用法,最后通过一个完整的通讯录程序,让学员初步掌握软件开发的全部流程 让零基础学员快速入门Delphi编程,快速掌握Delphi的使用方法,并能够制作出自己的软件来。为同学们下一步的提高打下坚实的基础。

    1066 人正在学习 去看看 陈城

《Delphi数字图像处理及高级应用》

Delphi 教程 系列书籍 (077) Delphi数字图像处理及高级应用》 网友(邦)整理 EMail: shuaihj@163.com

下载地址:

Pdf

Delphi数字图像处理及高级应用

  • 作者: 刘骏
  • 出版社:科学出版社
  • ISBN:7030121635
  • 上架时间:2003-11-5
  • 出版日期:2003 年9月
  • 开本:16开
  • 页码:350
  • 版次:1-1

内容简介

本书详细介绍了利用Delphi进行图像处理的技术,常用的图像格式,以及Delphi图像处理的常用方法Scanline。本书共8章,内容包括图像的基本概念、图像的点运算、图像的几何变换、图像的颜色系统、图像的增强、图像代数与分隔、图像的特效、图像处理综合实例,前面7章比较详细地介绍了图像处理的内容,同时提供了非常详细的程序代码,第8章是编者自己创作或者平时收集的一些经典的例子。本书提供了丰富的源代码,并提供了详细的注释,为读者的学习提供方便。本书可以作为高等院校有关老师的教学参考书或高年级学生及研究生的自学用书,也可作为软件开发人员的参考书。

前言

图像处理是一门理论与实践紧密结合的学科,一直以来受到人们的重视。Visual C++(以下简称VC)作为图像处理的常用工具,虽然功能强大,但由于其落后的MFC架构,使得很多初级程序员望而却步;Delphi作为Windows环境下面向对象快速开发工具 (RAD),以其高速的开发效率深得程序员的喜爱,它的编译器的编译速度是VC的几倍,并且具有良好的封装性。 Delphi除了在数据库方面有很强的优势以外,在图像处理上也有着非常强大的功能,Delphi进行图像处理的速度并不亚于VC,同时大大提高了开发效率,只需要少量代码就能实现很多复杂的功能。但是目前专门介绍Delphi数字图像处理的书还很少,以前的Delphi书籍在讲到图像这一节基本上都是一笔带过,没有做系统介绍,本书的写作正是基于这一点,编者把平时工作中遇到的和平时收集的一系列图像处理方面的问题做了一个系统的整理,而成此书。随着图像、多媒体技术的发展以及人们对开发效率的追求,使用Delphi来进行图像处理无疑是最好的选择。 同其他数字图像处理图书相比,本书具有如下显著特点: 1)详细介绍了各种常用、经典图像处理理论。 2)详细介绍小波压缩算法以及实现原理,同时介绍了JPEG2000图像处理技术。 3)完善的代码支持,本书光盘提供了各实例的源代码:为了节省篇幅,书中只给出了核心的代码和详细的注释。 4)本书介绍了近30个各种图像应用实例,包括实际工程应用的具体实例及其源代码,读者可以直接引用。 5)语言简洁易懂,读者很容易明白。 本书包括8章,分别为: 第1章为图像的基本概念,详细介绍了最新的JPEG2000图像格式以及各种其他常用的文件格式,同时介绍各种基础理论。第2章为图像的点运算,对图像的灰度、对比度、灰度直方图、着色、反色等效果做了详细的介绍,并对图像的反走样做了全面的说明,对图像的Gamma校正和特大位图的创建方法也有深入说明。 第3章是图像的几何变换,除了介绍常见的几何变换以外还增加了图像的扭曲,波浪和远视图效果。第4章为图像的颜色系统,不仅介绍了颜色空间的基本概念,还给出了比较重要的颜色空间的转换原理和代码,如RGB空间到CMYK空间的相互转换,RGB空间和HSL空间之间的相互转换等。 第5章是图像的增强,介绍了灰度直方图的拉伸、图像的伪彩色增强等常见处理的原理。第6章是图像的代数与分割,主要介绍了数学形态学在图像处理中的应用,以及经典的边缘检测方法。 第7章为图像特效,图像的特效包括了一些经典的动态效果和静态效果。 第8章是应用篇,给出一些非常好的实用的例子。本书从理论到实践(程序实现)介绍的都非常详细,相信Delphi的初中级程序员很快就会掌握。本书提供了丰富的源代码,并提供了详细的解释,为读者的学习提供方便。 本书可以作为高等院校有关老师的教学参考书或高年级学生或者研究生的自学用书,也可作为软件开发人员的参考书。本书由刘骏主编,参与写作的人员有王华、汪洁、刘海英、白露、王占全、庞演、顾强、李平、孙阳、宁海洋、吴阳、张曙等。同时还要感谢一些网友,如活跃在大富翁论坛上的huazai网友、卷起千堆雪tyn网友,以及其他的一些不知名的热心的网友的帮助。由于时间仓促和作者的水平有限,书中错误和不妥之处在所难免,敬请读者批评指正。如果有任何问题,可以登录www.2wintech.net询问,作者会在一周之内做出答复。 作 者 2003年6月

目录

第1章 图像的基础知识

1.1 图像的基本概念

1.1.1 图像的应用

1.1.2 位映像图像和向量图像

1.1.3 图像处理中的分辨率

1.2 三基色原理和图像的输入

1.2.1 可见光谱与光度学参量

1.2.2 三基色原理

1.2.3 视觉生理和心理规律

1.3 图像的几种常见的格式

1.3.1 BMP格式

1.3.2 GIF格式

1.3.3 JPEG格式

1.3.4 PCX格式

1.3.5 TIF格式

1.3.6 JPEG2000格式

1.4 图像格式转换器实例

1.4.1 程序功能

1.4.2 程序实现

1.5 图像浏览器实例

1.5.1 程序功能

1.5.2 程序实现

1.6 Delphi图像处理中Scanline的用法

1.6.1 pf8bit的位图

1.6.2 pf24bit的位图

1.6.3 pf32bit的位图

1.6.4 pf8bit向pf24bit转换

小结

第2章 图像的点运算

2.1 图像灰度处理

2.1.1 实现原理

2.1.2 程序实现

2.2 图像的灰度直方图

2.2.1 实现原理

2.2.2 程序实现

2.3 图像的二值化

2.3.1 实现原理

2.3.2 程序实现

2.4 图像亮度处理

2.4.1 实现原理

2.4.2 程序实现

2.5 图像对比度处理

2.5.1 实现原理

2.5.2 程序实现

2.6 饱和度调节

2.6.1 实现原理

2.6.2 程序实现

2.7 图像着色

2.7.1 实现原理

2.7.2 程序实现

2.8 图像反色

2.8.1 实现原理

2.8.2 程序实现

2.9 图像曝光

2.9.1 实现原理

2.9.2 程序实现

2.10 Gamma校正

2.10.1 实现原理

2.10.2 程序实现

2.11 迷人的万花筒

2.11.1 实现原理

2.11.2 程序实现

2.12 位图的反走样

2.12.1 实现原理

2.12.2 程序实现

2.13 位图的与、或操作

2.13.1 实现原理

2.13.2 程序实现

2.14 创建大型位图以及统计位图颜色

2.14.1 实现原理

2.14.2 程序实现

2.15 位图的噪声调节

2.15.1 实现原理

2.15.2 程序实现

小结

第3章 图像的几何变换

3.1 图像的平移

3.1.1 实现原理

3.1.2 程序实现

3.2 图像的缩放

3.2.1 实现原理

3.2.2 程序实现

3.3 图像的旋转

3.3.1 90度旋转

3.3.2 任意角旋转

3.4 图像的镜像

3.4.1 实现原理

3.4.2 程序实现

3.5 图像扭曲

3.5.1 实现原理

3.5.2 程序实现

3.6 图像的波浪效果

3.6.1 实现原理

3.6.2 程序实现

3.7 远视图

3.7.1 实现原理

3.7.2 程序实现

3.8 裁剪和合并

3.8.1 实现原理

3.8.2 程序实现

小结

第4章 图像的颜色系统

4.1 颜色的基本概念

4.2 颜色空间简介

4.2.1 RGB颜色空间

4.2.2 YIQ颜色空间

4.2.3 YUV颜色模型

4.2.4 HSV颜色模型

4.2.5 CMYK模型

4.2.6 CIE-XYZ颜色空间

4.2.7 Lab颜色空间

4.3 颜色空间的转换

4.3.1 RGB颜色空间和HSL颜色空间相互转换

4.3.2 RGB颜色空间和CMYK颜色空间的相互转换

4.3.3 RGB和HSV颜色空间互换

4.4 亮度/饱和度调整

4.4.1 实现原理

4.4.2 程序实现

4.5 通道与模式

4.5.1 实现原理

4.5.2 程序实现

4.6 RGB颜色调整

4.6.1 实现原理

4.6.2 程序实现

4.7 特殊色彩的实现

4.7.1 实现原理

4.7.2 程序实现

4.8 颜色量化与减色

4.8.1 实现原理

4.8.2 程序实现

4.9 颜色混合

4.9.1 实现原理

4.9.2 程序实现

小结

第5章 图像的增强

5.1 图像增强概述

5.2 灰度线性变换

5.2.1 实现原理

5.2.2 程序实现

5.3 灰度非线性变换

5.3.1 实现原理

5.3.2 程序实现

5.4 灰度直方图拉伸

5.4.1 实现原理

5.4.2 程序实现

5.5 图像锐化与图像平滑

5.5.1 图像的锐化

5.5.2 图像平滑

5.6 伪彩色增强

5.6.1 实现原理

5.6.2 程序实现

5.7 中值滤波

5.7.1 实现原理

5.7.2 程序实现

小结

第6章 图像代数与图像分割

6.1 图像的腐蚀

6.1.1 实现原理

6.1.2 程序实现

6.2 图像的膨胀

6.2.1 实现原理

6.2.2 程序实现

6.3 图像的结构开和结构闭

6.3.1 实现原理

6.3.2 程序实现

6.4 图像的细化

6.4.1 实现原理

6.4.2 程序实现

6.5 图像的边缘检测

6.5.1 实现原理

6.5.2 程序实现

6.6 图像的Hough变换

6.6.1 实现原理

6.6.2 程序实现

6.7 图像的轮廓提取

6.7.1 实现原理

6.7.2 程序实现

6.8 图像的识别和模板匹配

6.8.1 投影法

6.8.2 差影法

6.8.3 模板匹配

小结

第7章 图像的特效处理

7.1 图像的滑入和卷帘显示效果

7.1.1 图像的卷帘显示效果

7.1.2 图像的滑入效果

7.2 图像的淡入淡出效果

7.3 扩散效果

7.3.1 实现原理

7.3.2 程序实现

7.4 百叶窗效果和马赛克效果

7.4.1 百叶窗效果

7.4.2 马赛克效果

7.5 交错效果

7.5.1 垂直交错效果

7.5.2 水平交错效果

7.6 浮雕效果

7.6.1 灰色浮雕

7.6.2 彩色浮雕

7.7 图像的中心渐出和渐入效果

7. 7.1 图像的中心渐出效果

7.7.2 图像的中心渐入效果

7.8 图像的雨滴效果和积木效果

7.8.1 图像的雨滴效果

7.8.2 图像的积木效果

小结

第8章 综合实例

8.1 利用Delphi实现桌面更换

8.1.1 实现原理

8.1.2 程序实现

8.2 图片文件的加密解密

8.2.1 位图文件的加密解密

8.2.2 JPG文件加密解密

8.3 自定义光标的实现

8.4 基于Delphi的图像漫游

8.4.1 实现原理

8.4.2 程序实现

8.5 用Delphi实现屏幕图像捕捉

8.6 图片存取到流以及从流中复原

8.6.1 实现原理

8.6.2 程序实现

8.7 Delphi图像处理在纺织检测中的应用

8.7.1 Hough变换进行边缘检测

8.7.2 纱线参数测量

8.7.3 织物表面粗糙度比较

8.7.4 织物疵点检测

8.8 Photoshop中流动蚂蚁线的实现

8.8.1 矩形流动蚂蚁线

8.8.2 椭圆流动蚂蚁线

8.8.3 任意位置流动蚂蚁线

8.9 用Delphi读取JPEG文件的缩览图

8.9.1 实现原理

8.9.2 程序实现

8.10 Delphi数据压缩/解压缩处理

8.10.1 实现原理

8.10.2 程序实现

8.11 特大位图的快速显示

8.11.1 实现原理

8.11.2 程序实现

8.12 Photoshop中的喷枪实现

8.12.1 实现原理

8.12.2 程序实现

8.13 颜色填充

8.13.1 种子填充

8.13.2 路径填充

8.14 位图与组件

8.14.1 Combobox中添加位图

8.14.2 ListBox中显示位图

8.14.3 RichEdit中内容显示为位图

8.15 颜色拾取器

8.15.1 实现原理

8.15.2 程序实现

8.16 位图的打印

8.16.1 实现原理

8.16.2 程序实现

8.17 Delphi图像处理在交通中的应用——车牌识别

8.18 位图文件信息写到文本文件以及恢复

8.19 放大镜

8.19.1 实现原理

8.19.2 程序实现

8.20 调色板创建及应用

8.20.1 创建调色板

8.20.2 调色板应用

8.21 图像的局域网传输

8.21.1 实现原理

8.21.2 程序实现

8.22 图像纵横比率最佳调节

8.22.1 实现原理

8.22.2 程序实现

8.23 JPEG格式图片错误信息显示

8.24 JPG图片存取到数据库

8.24.1 实现原理

8.24.2 程序实现

8.25 基于小波变换的JPEG2000压缩实现

8.25.1 实现原理

8.25.2 程序实现

8.26 傅里叶变换

8.26.1 实现原理

8.26.2 程序实现

参考文献

2009-10-27 21:41:00 maozefa 阅读数 8503
  • DelphiXE10零基础实战快速入门

    通过课堂上一个一个的实战例子,演示DelphiXE10的用法,最后通过一个完整的通讯录程序,让学员初步掌握软件开发的全部流程 让零基础学员快速入门Delphi编程,快速掌握Delphi的使用方法,并能够制作出自己的软件来。为同学们下一步的提高打下坚实的基础。

    1066 人正在学习 去看看 陈城

    《Delphi图像处理 -- 数据类型及内部过程》一文中定义了基本的图像数据类型及一些内部过程,本文进一步将Delphi常用的图像类型转换为图像处理所需的数据结构,为具体的Delphi图像处理过程作准备,同时也要将处理好的图像数据转换为Delphi的常用图像类型。《Delphi图像处理》系列除图像数据转换过程外,其它图像处理过程都统一使用32位ARGB像素格式。

    一、数据格式转换。

    本节提供了2个互逆的图像数据拷贝过程。ImageCopyFrom是把1 - 32位像素格式的图像数据源结构拷贝到32位像素格式的图像数据目标结构中,而ImageCopyTo则是把32位像素格式的图像数据源结构拷贝到24 - 32位像素格式的图像数据目标结构,转换为低于24位像素格式的图像数据结构应借助TIndexImage类(见《Delphi图像处理 -- 真彩色图像转换为低色彩图像》)。

    过程中Dest和Source参数的获取方法见《Delphi图像处理 -- 数据类型及内部过程》和本文第六节的内容;如何使用这2个过程可参见本文的第二节和第四节的内容。

    下面以图例的方式简单介绍一下几种像素格式的内存结构,供对图像处理感兴趣,而又对各种像素格式的结构不熟悉的朋友参考:

    1、单色图像。每字节8像素,从高位到低位依次排列,与字节位的顺序相反:

                    高位           低位

    字 节 位: 7 6 5 4 3 2 1 0

    像素排列: 0 1 2 3 4 5 6 7

    2、16色图像。每字节2像素,高四位为第一像素,低四位为第二像素:

                    高位           低位

    字 节 位: 7 6 5 4 3 2 1 0

    像素排列: 第1像素 第2像素

    3、256色图像。每字节1像素,这个简单,不必图示。

    4、15位图像。2字节1像素,R、G、B各分量都占5个位,俗称555格式:

                    高位                                   低位

    字 节 位: F E D C B A 9 8 7 6 5 4 3 2 1 0

    像素排列: 0 r r r r r g g g g g b b b b b

    5、16位图像。2字节1像素,R、B分量各占5个位,G分量占6个位,俗称565格式:

                    高位                                   低位

    字 节 位: F E D C B A 9 8 7 6 5 4 3 2 1 0

    像素排列: r r r r r g g g g g g b b b b b

    6、24位图像。3字节1像素,从高到低,R、G、B各占1字节,图示略。

    7、32位像素。4字节1像素,从高到低,A、R、G、B各占1字节,图示略。

    8、无论何种像素格式,其扫描线长度必须是32位(4字节)的整倍数,如果按图像宽度计算出来的扫描线字节不足32位整倍数,必须以0填充。所以,除32位图像像素格式外,其它像素格式都有可能扫描线宽度不等于图像宽度 * 位数 / 8。

    二、获取TGraphic的图像数据。

    TGraphic是Delphi的图像类基类,特别是其派生类TBitmap,更是Delphi最重要,也是最基础的图像类,它封装了Windows位图的常用操作,其它TGraphic派生类(包括一些第三方派生类)都可以转换为TBitmap,因此,获取了TBitmap的图像数据,也就获取了TGraphic派生类的图像数据。

    有多个方法获取TBitmap的图像数据,一是直接在TBitmap的扫描线上操作,其好处是图像处理后直接反映在TBitmap中,不必再进行转换,缺点是由于本图像处理系列采用了统一的32位ARGB像素格式,所以必须设置TBitmap.PixelFormat属性,如此一来,势必破坏了原图像像素格式,而且除原32位图像外,实际上也进行了一次图像数据拷贝;二是不破坏TBitmap的像素格式,直接在TBitmap.ScanLine中解析拷贝图像数据,这是间接的TBitmap图像数据处理,处理完毕,有可能要转换为新的TBitmap;三是,用TBitmap.Handle属性借助Windows API进行数据转换,这种方式与第二种方式差不多,《Delphi图像处理 -- 真彩色图像转换为低色彩图像》一文中就是采用的这种方式。本文采用前2种方式获取TBitmap图像数据,具体采用何种方式由具体情况而定。下面是实现代码:

    从上面的代码可以看出,采用第一种方式最简单:先设置其PixelFormat := pf32Bit,然后设定数据结构即可(非32位像素格式图像转换为32位像素格式后必须填充其Alpha分量为255,填充由内部过程FillAlpha完成);第二种方式则很复杂,必须针对pf1Bit到pf32Bit的内存像素解析后进行拷贝,拷贝过程使用了本文第一节介绍的ImageCopyFrom过程。

     三、获取GDI+ TGpBitmap的图像数据。

    GDI+也是近些年来在Delphi中使用较多的图像类,同TBitmap一样,也有几种方式获取图像数据,获取TGpBitmap图像数据很简单,使用TGpBitmap.Lockbits函数就可搞定。

    GetImageData(Bitmap: TGpBitmap; FreeBitmap: Boolean)是间接获取TGpBitmap图像数据的函数,这里面并没有调用任何拷贝过程,而是使用了TGpBitmap.LockBits的一点小技巧,其原理可参见《使用GDI+位图数据扫描线处理图像的小技巧》。如果你看了《使用GDI+位图数据扫描线处理图像的小技巧》。有的的朋友可能发现,那篇文章是用C++写的,而C++中的Bitmap.Lockbits函数中,BitmapData类型的Data是作为一个指针参数传递给函数的,所以预先设定Stride和Scan0是没话可说的,而Delphi中,TBitmapData类型的Data是通过返回值获取而不是通过参数传递的,那么预先设置的Stride和Scan0有何意义呢?呵呵,其实,这就是Delphi默认调用方式的特殊之处了。类似结构之类的数据类型获取返回值,在C/C++,是一个个字段拷贝的,预先设定的值铁定会被返回值覆盖;而Delphi对于这种大于4字节结构类型的返回值却是在调用时以指针方式作为隐含的一个参数传递给函数的,因而,在函数内部对返回值的操作也是针对该指针的,所以Delphi与C++的LockBits函数外形上不一样,实质上都是传递了一个返回值的指针参数。

   四、TImageData转换为TGraphic。

    图像数据转换为到32位或者24位像素格式时使用了本文第一节介绍的ImageCopyTo过程,其它像素格式的转换借助了TIndexImage类型,该类型在文章《Delphi图像处理 -- 真彩色图像转换为低色彩图像》中。其实,按照常规写法,ImageDataAssignTo过程没有这样复杂,关键是新建的TBitmap对象,只有按照先设定PixelFormat,再设置调色板,最后设置图像尺寸才是最优顺序,否则,不仅在TBitmap内部要多一次数据拷贝,而且图像数据还会被搞乱。

    五、TImageData转换为TGpBitmap。

    这个24位以下像素格式也要借助TGpIndexImage类型,代码如下:

    六、其它。包括新建TImageData对象,获取子图,获取裁剪图等过程(代码较长,已折叠)。

    对一个图像的局部数据进行处理,可以借助GetClipImageData或者GetSubImageData过程进行,前者是从图像数据上裁剪一个局部,对它的操作不会影响原图,而后者只是原图数据的一部分,对它的数据处理,就是对原图的局部图像处理。

    GetExpandData是内部过程,功能是扩展图像边框,以便正确地处理图像边缘。在很多图像处理过程中,都涉及到图像边缘的处理,如图像缩放、旋转、卷积等操作,这是一个即耗时又麻烦的事,GetExpandData就是对图像预先进行边界扩展,这样在具体处理过程中就不必要作边界判断了。

    七、过程调用过程。

    本次重新修订,针对有些图像处理过程比较耗时和需要经常性进行调整的问题,对这些图像处理增加了回调处理过程,用于在图像调整时,及时终止前面的图像处理过程,图像处理过程中响应用户回调函数是个较麻烦的事,为此写了2个内部处理过程,存放于此作为本文第七部分(代码就不解释了):

    八、内部使用参数表及初始化过程(这些过程是在单元最后部分调用的,因此原样复制于此):

    关于图像数据的转换就介绍到这里。

    文章中使用GDI+版本下载地址和说明见《GDI+ for VCL基础 -- GDI+ 与 VCL》。

    文章中所用数据类型及一些内部过程见《Delphi图像处理 -- 数据类型及内部过程》。

    尽管我十分努力,但水平有限,错误在所难免,欢迎指正和指导。邮箱地址:

    maozefa@hotmail.com

    补充:本文于2010.5.20重新修订

 

没有更多推荐了,返回首页