Delphi存取图像完整解决方案

http://blog.sina.com.cn/s/blog_693cf1cf0100plkq.html

对于涉及图像数据的数据库应用程序,图像数据的存取技术是一个关键。由于缺少技术文档及DEMO例程演示,为此笔者在网上搜索了相关资料,有的根本不能用,有的过于繁杂,有的应用范围太窄(如只能适用于BMP图像),有的写得过于简单理解起来十分困难。。。而且在网上这也是大家比较关心的一个问题。笔者对这个问题进行了反复实作和探索,下边笔者将通过一个完整的简单例子来说明如何保存和显示SQL数据库中的图像数据(同时包括BMP和JPEG两种格式)。

  一、 创建演示数据库

  在SQL SERVER中新建一演示数据库:Demo,并创建一数据表Picture1,结构如下:

  

字段名Dtata TypeIdentity
IdIntYes
IsbmpTinyint
MyimageImage

  字段Isbmp是用来记录在Myimage中存入的图像的类型(0表JPEG,1表BMP,其它值表无图像),Isbmp数据类型选用整型Tinyint而末选用逻辑bit型主要是考虑到如下方法仍适用于ACCESS数据库。在SQL中打开表Picture1,添入几条记录,Myimage图像字段值暂不管,字段Isbmp值随便输入0和1之外的其它数。

  二、 窗口设计

  在DELPHI中新建一个工程,在FORM1上放置如表所示控件(考虑到TDBImage型控件不能正确显示JPEG型图像,所以选用Timage型控件显示所有类型图像)。

  

组件类别组件属性名属性值用途说明
TimagecaptionImage1显示图像
nameImage1
StretchTrue
Tbuttoncaption选择图像选择图像
nameselectimage
Tbuttoncaption保存图像保存图像到数据库
namesavetodb
TADOConnectioncaptionAdoconnection1创建与数据库demo的连接
nameAdoconnection1
Connectionstring见备注
ConnectedTrue
LoginpromptFalse
TadotableCaptionAdotable1建立与表Picture1的连接
nameAdotable1
ConnectionAdoconnection1
TablenamePicture1
ActiveTrue
TdatasourceNameDatasource1建立数据源
DatasetAdotable1
TopenpicturedialogCaptionOpenpicturedialog1选择图像文件
NameOpenpicturedialog1
TdbgridCaptionDbgrid1显示记录
NameDbgrid1
DatasourceDatasource1

  备注:

  adoconnection1.connectstring :=

  'Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=demo;

  Data Source=Mysqlserver'

  Mysqlserver为SQL服务器的名称请据实际情况更改。

  三、 程序代码(首先在单元文件接口部分的uses语句中添入JPEG单元引用)

  1. 图像数据的选择及保存

  procedure TForm1.selectimageClick(Sender: TObject); //选择图像

begin

if openpicturedialog1.Execute then

image1.Picture.LoadFromFile(openpicturedialog1.FileName );

end;

procedure TForm1.savetodbClick(Sender: TObject); //保存图像

var

strm:tmemorystream;

ext:string;

begin

if image1.picture.Graphic <> nil then //避免image1中无图像保存出错

begin

ext:=extractfileext(openpicturedialog1.FileName ); //取出文件的扩展名

strm := tmemorystream.Create ;

try

image1.Picture.Graphic.SaveToStream(strm);

adotable1.Edit ;

strm.Position :=0; 

tblobfield(adotable1.FieldByName('myimage')).LoadFromStream(strm);

//如需直接由文件保存可采用如下注释行

//TBlobField(adotable1.FieldByName('myimage')).LoadFromFile(OpenPictureDialog1.FileName);

//以下记录保存到数据库的图像格式

if uppercase(ext) = '.BMP' then

adotable1.FieldByName('isbmp').Value := 1 //BMP型图像数据

else if (uppercase(ext) = '.JPG') OR ( uppercase(ext) = '.JPEG') Then

adotable1.FieldByName('isbmp').Value := 0; //JPEG型图像数据

adotable1.Post ;

finally

strm.Free ; //笔者发现如strm采用tblobstream类,程序运行到该语句会出现问题

end;

end;

end;

  2. 图像数据的读取及显示

  从数据库图像字段中读取数据然后在Image1中把图像显示出来的程序代码,笔者先尝试在Datasource1的OnDataChange事件中来完成,但会出错,后改写在adotable1的afterscroll事件中顺利完成。

  procedure TForm1.adoTable1AfterScroll(DataSet: TDataSet); //显示图像

var

strm:tadoblobstream;

jpegimage:tjpegimage;

bitmap:tbitmap;

begin

strm := tadoblobstream.Create(tblobfield(adotable1.fieldbyname('MYIMAGE')),bmread);

try //try1

strm.position :=0;

image1.Picture.Graphic := nil; //清除图像

// BMP、JPEG两种图像数据必需分别处理

if adotable1.fieldbyname('isbmp').asstring ='1' then //BMP型图像数据

begin //begin11

bitmap := tbitmap.Create ;

try //try11

bitmap.LoadFromStream(strm);

image1.Picture.Graphic := bitmap;

finally

bitmap.Free;

end; //end try11

end //end begin11

else if adotable1.fieldbyname('isbmp').asstring ='0' then //JPEG型图像数据

begin //begin12

jpegimage := tjpegimage.Create ;

try //try12

jpegimage.LoadFromStream(strm);

image1.Picture.Graphic := jpegimage;

finally

jpegimage.Free ;

end; //end try12

end; //end begin12

finally

strm.Free ;

end; //end try1

end;

  如果你想将数据库中的图像导出到外部文件中可采用如下关键语句:

  image1.Picture.SaveToFile(FileName );

  以上程序代码不但适用于SQL数据库,而且完全适用于ACCESS数据库,但创建ACCESS数据库时应注意图像字段的数据类型应为OLE型,数据库创建完成之后再将Adoconnection1连接到该ACCESS数据库即可运行。欲知详细情况,请索取源程序。以上提供了DELPHI利用Tsteam类存取JPEG、BMP图像到数据库的一种解决方案,笔者争取下文介绍DELPHI利用ASSIGN方法存取JPEG、BMP图像到数据库的另一解决方案。

  以上程序代码在DELPHI6.0+SQL(或ACCESS)数据库下运行通过。

Delphi图像存取另类解决方案

在前文中,提供了一种DELPHI存取JPEG、BMP图像到数据库的解决方案,虽然它适用于ACCESS和SQL数据库,但它并不适用于所有数据库(比如PARADOX数据库中的GRAPHIC图像字段就不能采用该方法存取图像数据),下文将介绍DELPHI利用ASSIGN方法存取JPEG、BMP图像到数据库的另一解决方案来进行补充完善。演示数据库结构和窗口界面设计同前文,不再重述,将单元的相应程序代码作如下更换:

  1. 图像数据的选择及保存

  procedure Tform1.selectimageClick(Sender: TObject); //选择图像

begin

if openpicturedialog1.Execute then

image1.Picture.LoadFromFile(openpicturedialog1.FileName );

end;

procedure Tform1.savetodbClick(Sender: TObject); //保存图像到数据库

var

ext:string;

begin

if image1.picture.Graphic <> nil then //避免image1中无图像保存出错

begin

adotable1.Edit ;

adotable1.FieldByName('myimage').Assign(image1.Picture.Graphic);

//以下记录保存到数据库的图像格式

ext:=extractfileext(openpicturedialog1.FileName ); //取出文件扩展名

if uppercase(ext) = '.BMP' THEN

adotable1.FieldByName('isbmp').VALUE := 1 //BMP型图像数据

ELSE IF (UPPERCASE(EXT) = '.JPEG') OR (UPPERCASE(EXT) = '.JPG') THEN

adotable1.FieldByName('isbmp').VALUE := 0; //JPEG型图像数据

ADOTABLE1.Post ;

end;

end;

  2. 图像数据的读取及显示

  procedure Tform1.ADOTable1AfterScroll(DataSet: TDataSet); //ADOTable1的AfterScroll事件方法程序

 var

  jpegimage:tjpegimage;

 begin

  image1.Picture.Graphic :=nil;

  //下边BMP、JPEG两种图像数据必需分别处理

  if adotable1.fieldbyname('isbmp').Asstring = '1' then //BMP型图像数据

   image1.Picture.bitmap.Assign(adotable1.fieldbyname('myimage'))

   //上边语句中的bitmap不能为graphic,否则会出错

  else if adotable1.fieldbyname('isbmp').asstring = '0' then //JPEG型图像数据

   begin //begin2

    jpegimage := tjpegimage.Create ; //通过jpegimage将图像显示在image1,否则会出错

    try

     jpegimage.Assign(adotable1.fieldbyname('myimage'));

     image1.Picture.Graphic :=jpegimage;

    finally

     jpegimage.Free ;

    end; //end try

  end; //end begin2

end;

  注:别忘了在单元文件接口部分的uses语句中添入JPEG单元引用。

  以上程序代码在DELPHI6.0+SQL(或ACCESS或PARADOX)数据库下运行通过。