对于涉及图像数据的数据库应用程序
图像数据的存取技术是一个关键
由于缺少技术文档及DEMO例程演示
为此笔者在网上搜索了相关资料
有的根本不能用
有的过于繁杂
有的应用范围太窄(如只能适用于BMP图像)
有的写得过于简单理解起来十分困难
而且在网上这也是大家比较关心的一个问题
笔者对这个问题进行了反复实作和探索
下边笔者将通过一个完整的简单例子来说明如何保存和显示SQL数据库中的图像数据(同时包括BMP和JPEG两种格式)
一 创建演示数据库
在SQL SERVER中新建一演示数据库Demo并创建一数据表Picture结构如下
字段名Data TypeIdentityIdIntYes IsbmpTinyint MyimageImage
字段Isbmp是用来记录在Myimage中存入的图像的类型(表JPEG表BMP其它值表无图像)Isbmp数据类型选用整型Tinyint而末选用逻辑bit型主要是考虑到如下方法仍适用于ACCESS数据库在SQL中打开表Picture添入几条记录Myimage图像字段值暂不管字段Isbmp值随便输入和之外的其它数
二 窗口设计
在DELPHI中新建一个工程在FORM1上放置如表所示控件(考虑到TDBImage型控件不能正确显示JPEG型图像所以选用Timage型控件显示所有类型图像)
组件类别组件属性名属性值用途说明TimagecaptionImage
显示图像nameImage
StretchTrueTbuttoncaption选择图像选择图像nameselectimageTbuttoncaption保存图像保存图像到数据库namesavetodb TADOConnectioncaption Adoconnection
创建与数据库demo的连接nameAdoconnection
Connectionstring见备注ConnectedTrueLoginpromptFalse TadotableCaptionAdotable
建立与表Picture
的连接nameAdotable
Connection Adoconnection
TablenamePicture
Active TrueTdatasourceNameDatasource
建立数据源DatasetAdotable
TopenpicturedialogCaptionOpenpicturedialog
选择图像文件NameOpenpicturedialog
TdbgridCaption Dbgrid
显示记录NameDbgrid
DatasourceDatasource
备注
adoconnectionconnectstring :=
Provider=SQLOLEDB;Persist Security Info=False;User ID=sa;Initial Catalog=demo;
Data Source=Mysqlserver
Mysqlserver为SQL服务器的名称请据实际情况更改
三 程序代码(首先在单元文件接口部分的uses语句中添入JPEG单元引用)
图像数据的选择及保存
procedure TFormselectimageClick(Sender: TObject); //选择图像
begin
if openpicturedialogExecute then
imagePictureLoadFromFile(openpicturedialogFileName );
end;
procedure TFormsavetodbClick(Sender: TObject); //保存图像
var
strm:tmemorystream;
ext:string;
begin
if imagepictureGraphic <> nil then //避免image中无图像保存出错
begin
ext:=extractfileext(openpicturedialogFileName ); //取出文件的扩展名
strm := tmemorystreamCreate ;
try
imagePictureGraphicSaveToStream(strm);
adotableEdit ;
strmPosition :=;
tblobfield(adotableFieldByName(myimage))LoadFromStream(strm);
//如需直接由文件保存可采用如下注释行
//TBlobField(adotableFieldByName(myimage))LoadFromFile(OpenPictureDialogFileName);
//以下记录保存到数据库的图像格式
if uppercase(ext) = BMP then
adotableFieldByName(isbmp)Value := //BMP型图像数据
else if (uppercase(ext) = JPG) OR ( uppercase(ext) = JPEG) Then
adotableFieldByName(isbmp)Value := ; //JPEG型图像数据
adotablePost ;
finally
strmFree ; //笔者发现如strm采用tblobstream类程序运行到该语句会出现问题
end;
end;
end;
图像数据的读取及显示
从数据库图像字段中读取数据然后在Image中把图像显示出来的程序代码笔者先尝试在Datasource的OnDataChange事件中来完成但会出错后改写在adotable的afterscroll事件中顺利完成
procedure TFormadoTableAfterScroll(DataSet: TDataSet); //显示图像
var
strm:tadoblobstream;
jpegimage:tjpegimage;
bitmap:tbitmap;
begin
strm := tadoblobstreamCreate(tblobfield(adotablefieldbyname(MYIMAGE))bmread);
try //try
strmposition :=;
imagePictureGraphic := nil; //清除图像
// BMPJPEG两种图像数据必需分别处理
if adotablefieldbyname(isbmp)asstring = then //BMP型图像数据
begin //begin
bitmap := tbitmapCreate ;
try //try
bitmapLoadFromStream(strm);
imagePictureGraphic := bitmap;
finally
bitmapFree;
end; //end try
end //end begin
else if adotablefieldbyname(isbmp)asstring = then //JPEG型图像数据
begin //begin
jpegimage := tjpegimageCreate ;
try //try
jpegimageLoadFromStream(strm);
imagePictureGraphic := jpegimage;
finally
jpegimageFree ;
end; //end try
end; //end begin
finally
strmFree ;
end; //end try
end;
如果你想将数据库中的图像导出到外部文件中可采用如下关键语句
imagePictureSaveToFile(FileName );
以上程序代码不但适用于SQL数据库而且完全适用于ACCESS数据库但创建ACCESS数据库时应注意图像字段的数据类型应为OLE型数据库创建完成之后再将Adoconnection连接到该ACCESS数据库即可运行欲知详细情况请索取源程序以上提供了DELPHI利用Tsteam类存取JPEGBMP图像到数据库的一种解决方案笔者争取下文介绍DELPHI利用ASSIGN方法存取JPEGBMP图像到数据库的另一解决方案
以上程序代码在DELPHI+SQL(或ACCESS)数据库下运行通过
四另一解决方案
在上文中笔者提供了一种DELPHI存取JPEGBMP图像到数据库的解决方案虽然它适用于ACCESS和SQL数据库但它并不适用于所有数据库(比如PARADOX数据库中的GRAPHIC图像字段就不能采用该方法存取图像数据)下文将介绍DELPHI利用ASSIGN方法存取JPEGBMP图像到数据库的另一解决方案来进行补充完善演示数据库结构和窗口界面设计同前文不再重述将单元的相应程序代码作如下更换
图像数据的选择及保存
procedure TformselectimageClick(Sender: TObject); //选择图像
begin
if openpicturedialogExecute then
imagePictureLoadFromFile(openpicturedialogFileName );
end;
procedure TformsavetodbClick(Sender: TObject);//保存图像到数据库
var
ext:string;
begin
if imagepictureGraphic <> nil then //避免image中无图像保存出错
begin
adotableEdit ;
adotableFieldByName(myimage)Assign(imagePictureGraphic);
//以下记录保存到数据库的图像格式
ext:=extractfileext(openpicturedialogFileName ); //取出文件扩展名
if uppercase(ext) = BMP THEN
adotableFieldByName(isbmp)VALUE := //BMP型图像数据
ELSE IF (UPPERCASE(EXT) = JPEG) OR (UPPERCASE(EXT) = JPG) THEN
adotableFieldByName(isbmp)VALUE := ; //JPEG型图像数据
ADOTABLEPost ;
end;
end;
图像数据的读取及显示
procedure TformADOTableAfterScroll(DataSet: TDataSet); //ADOTable的AfterScroll事件方法程序
var
jpegimage:tjpegimage;
begin
imagePictureGraphic :=nil;
//下边BMPJPEG两种图像数据必需分别处理
if adotablefieldbyname(isbmp)Asstring = then //BMP型图像数据
imagePicturebitmapAssign(adotablefieldbyname(myimage))
//上边语句中的bitmap不能为graphic否则会出错
else if adotablefieldbyname(isbmp)asstring = then //JPEG型图像数据
begin //begin
jpegimage := tjpegimageCreate ; //通过jpegimage将图像显示在image否则会出错
try
jpegimageAssign(adotablefieldbyname(myimage));
imagePictureGraphic :=jpegimage;
finally
jpegimageFree ;
end; //end try
end; //end begin
end;
注别忘了在单元文件接口部分的uses语句中添入JPEG单元引用
以上程序代码在DELPHI+SQL(或ACCESS或PARADOX)数据库下运行通过