怎样在Access数据库里插入图像 ? ( 积分: 50 )

  • 主题发起人 主题发起人 chaofan201
  • 开始时间 开始时间
C

chaofan201

Unregistered / Unconfirmed
GUEST, unregistred user!
各位大侠:
在此先谢了!!
我是菜菜鸟。作了一个delphi程序,实现查询后,从Access数据库取出信息DBMemo1显示,但DBImage1无法显示图片。我该怎么办?查了很多资料都没能成功。
我的图片为 .jpg 图像,怎样做数据库?怎样显示?请高手帮我......
不胜感激!!!
 
各位大侠:
在此先谢了!!
我是菜菜鸟。作了一个delphi程序,实现查询后,从Access数据库取出信息DBMemo1显示,但DBImage1无法显示图片。我该怎么办?查了很多资料都没能成功。
我的图片为 .jpg 图像,怎样做数据库?怎样显示?请高手帮我......
不胜感激!!!
 
如果是在oracle里面可以设置blob字段,access里,俺没接触过
 
到这里去看一看,也许你可以找到答案:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2557534
 
楼主,你加我的QQ,我给你这方面的实例,很简单的。我的QQ 11925922
 
谢谢你cainiaowang!
我希望今晚能和你聊聊!
等你.
QQ 287829321
 
想利用网络赚钱吗?其实很简单,我们需要的就是耐心+时间=金钱.
其实如果只靠下面的一种方式,想一个月赚多少不太可能,除非你能拉许多朋友入伙.最好可以同时注册以下三个推荐,因为3个基本上够了,而且
推荐一:为傻瓜式的,不需要你费多少功夫.每天限制使用4小时.
推荐二:要隔段时间就要点击保存窗口.每天限制使用4小时.
推荐三:同二,要隔段时间就要点击保存窗口,不过没有时间限制啊.

推荐一:
"免费使用 有偿回报" 国内第一款有奖金的实时信息软件
免费加入使用"八趣通宝"赢取奖金或Q币。
免费注册地址为:
http://www.8qu.net/register.asp?net=xie3210563

提示:安装好以后,把任务最小化,然后把鼠标放在通宝标志上,点击鼠标右键,把"打开存点窗口提示"及其他两个任务前面的勾号去掉,就可以不受干扰了.此款软件每天现在限制登陆4小时.

推荐二:中国广告网
NewsBar——最佳上网伴侣!她可以:
→ 1、一边上网,一边赚钱!
→ 2、及时了解最新信息;
→ 3、自由参加各种网络拍卖,赢得巨大乐趣;
→ 4、免费参与多个广告商随时开展的各种抽奖活动...
心动?立刻行动!点击这里,免费注册: http://www.ads4cn.com/newsbar/refferer.asp?xie3210563

推荐三:
SOHO广告网
http://www.sohoads.com/sabar/reg.asp?sj=xie3210563
 
DBImage—思路一(The DBImage - take one)

当试图使用Delphi做新的尝试时,我所做的第一件事是向Delphi的自带帮助寻求方法。这是帮助文档将回答:TDBImage(在组件面板的Data Controls页)表示数据库当前记录的一个BLOB字段的图形图像。使用TDBImage表示图形字段值。TDBImage允许表单显示数据库的图形数据。TDBImage仅仅比TImage组件多了一些数据可视属性。其中两个最重要的属性是:DataSource(数据源)和Field(字段)。DataSource(数据源)属性连接图形组件到数据库。在我们的表单上有一个名为DataSource1的DataSource(数据源)组件—代表着一个数据集。Field(字段)属性指出拥有图像的字段(在表中)。
一切都清楚了,现在在表单上放置一个DBImage组件并默认名为DBImage1。为了真正的把DBImage与表的BLOB字段相连,我们仅需要做以下的配置(使用Object Inspector):

DBImage1.DataSource = DataSource1
DBImage1.Field = Picture

为了显示存在Applications表的Picture字段的JPEG图像,这是必需的窍门。

为了验证这样的配置是否可以工作,我们所需做的唯一一件事是设置ADOTable1组件的Active(激活)属性为True即可。在设计时我们就可在Object Inspector(对象检视器)中完成。一旦你这样做了,就会出现以下的对话框:



什么?为什么显示“位图图像无效”呢?我们有JPEG图片而不是BMP图片—问题就在这里吗?让我们再回头看看帮助。

通过在帮助中的一阵点击之后,得出结论:为了得到数据库里的JPG图片,我们得使用TJpegImage对象。为了显示图片,我们需要Image(图像)组件的简单、不可视版本。同时,我们需要用流(Stream)从BLOB对象中载出图片。帮助文档叙述:我们应使用TADOBlobStream来访问或改变ADO数据集中BLOB或memo(备注)字段的值。





第三节 用流引出JPEG—错误的方法

引出JPEG—思路二(Pulling the Jpeg - take two!)

既然我们不能使用DBImage做任何事—从表单中去掉它并放上一个普通的TImage组件(Additional页)命名为ADOImage。不幸的是,Image组件没有任何数据可视(data-aware)的属性,因此,需要一个单独的程序来显示它所表示的数据库表中的图片。完成这件事的最简单的方法是:在表单上放置一个Button(按钮),把所有的程序代码放在它的OnClick事件中,按钮的名称为:“btnShowImage”。

为了使用ADOBLOBStream,帮助文档建议创建一个TADOBlobStream实例,用“流”的方法从数据集中读取图形字段,然后释放BLOB流。在中间的某个地方,我们将需要用LoadFromStream方法从TADOBlobStream对象中载入JPEG图像。Image(图像)组件的Picture(图片)、Graphic(图形)属性将用于真正的存储和显示图片。

字段对象,它是什么?

这时,我假设只需要一点点关于字段对象的知识对于你掌握本章已绰绰有余了。在Delphi数据库的开发中,主要的对象之一是TField对象。字段组件是表示运行(或设计)时的数据集字段的非可视化对象。TADOTable(和其他TDataSet子类)提供设计时对Fields Editor(字段编辑器)的访问方法。Fields Editor使你能选择数据集中你所想包含的字段。更重要的是,它创建了应用程序数据集中使用的字段组件的稳固的列表。为了调用Fields Editor,可以双击TADOTable组件。默认情况下,字段列表是空的。点击Add按钮打开一个对话框,里面列出了Applications表的字段列表。缺省情况下,所有字段都被选择,然后选择OK。

Delphi会按如下的方式给出字段的默认名称:Table(表)名+Field(字段)名。这意味着我们的图片字段名为:ADOTable1Picture。

TADOBlobStream的Create(创建)方法创建一个实例用于读或写一个指定的BLOB字段对象,在这里是ADOTable1Picture字段。

我们在btnShowImage按钮的OnClick事件中写入程序代码。该代码将从当前所选行的Picture字段中读取图片。源代码如下所示:

uses jpeg;
...
procedure TForm1.btnShowImageClick(Sender: TObject);
var bS: TADOBlobStream;
Pic : TJpegImage;
begin
bS := TADOBlobStream.Create
(AdoTable1Picture, bmRead);
try
Pic:=TJpegImage.Create;
try
Pic.LoadFromStream(bS);
ADOImage.Picture.Graphic:=Pic;
finally
Pic.Free;
end;
finally
bS.Free
end;
end;


OK,让我们运行这个工程。当然,设置ADOTable1.Active属性为True。表单显示后,点击按钮,将出现下面的显示:



呃, 怎么哪?代码百分之百的正确但为什么不显示图像呢!记住“永不放弃,永不投降”!让我们深入到字节水平看看到底发生了什么!

第四节 在BLOB中寻找JPEG的开端

OLE对象类型格式—思路三(OLE object type format - take three!)
现在所有我们需要做的是存储图片到磁盘(存为普通的二进制文件)并了解它里门的内容是什么。

所有的图片文件(格式)都有用来唯一的标识图像的文件头。JPG图片文件以所谓的SOI标记开始,该标记的十六进制值是$FFD8。

下面一行代码存储图片字段值到工作目录的相关文件(BlobImage.dat)。在表单的OnCreate事件中放置这条代码,开始工程以后再移除该代码。

ADOTable1Picture.SaveToFile("BlobImage.dat");

一旦我们有了这个文件。我们就可以使用Hex editor看它的内容。



你相信吗?MS Access把连接的OLE对象的路径作为对象定义的一部分存储在OLE对象字段中。因为OLE对象的存储定义没有被文档化(!?这直接来自于MS),所以没有办法知道真正的图像数据被写之前能得到什么。

分两个部分考虑这个问题。第一:我们需要找到"FFD8"并从那儿开始读取图像。第二:"FFD8"不可能总在文件的同一个位置。结论:我们需要一个函数,返回Access数据库中存储为OLE对象的JPG文件的SOI标记的位置。

正确的方法—思路四(The correct way - take four!)

提供了Blob类型字段后,我们的函数应返回ADOBlobStream中"FFD8"字符串的位置。ReadBuffer(读缓冲区)从流中一个字节一个字节的读取数据。对ReadBuffer的每个调用都会一个字节一个字节的移动流的位置。当两个字节一起引出SOI标记时,函数返回流的位置。这是这个函数:

function JpegStartsInBlob(PicField:TBlobField):integer; var bS : TADOBlobStream; buffer : Word; hx : string; begin Result := -1; bS := TADOBlobStream.Create(PicField, bmRead); try while (Result = -1) and (bS.Position + 1 < bS.Size) do begin bS.ReadBuffer(buffer, 1); hx:=IntToHex(buffer, 2); if hx = &quot;FF&quot; then begin bS.ReadBuffer(buffer, 1); hx:=IntToHex(buffer, 2); if hx = &quot;D8&quot; then Result := bS.Position - 2 else if hx = &quot;FF&quot; then bS.Position := bS.Position-1; end; //if end; //while finally bS.Free end; //try end; 一旦我们有了SOI标记的位置,我们就能使用它在ADOBlob流中找到图片的位置。 uses jpeg; ... procedure TForm1.btnShowImageClick(Sender: TObject); var bS : TADOBlobStream; Pic : TJpegImage; begin bS := TADOBlobStream.Create(AdoTable1Picture, bmRead); try bS.Seek(JpegStartsInBlob(AdoTable1Picture),soFromBeginning); Pic:=TJpegImage.Create; try Pic.LoadFromStream(bS); ADOImage.Picture.Graphic:=Pic; finally Pic.Free; end; finally bS.Free end; end; 运行工程,OK! 现在谁会说编程没有趣味? 注:在真正的代码程序中,我们会在TDataSet的AfterScroll事件中加入代码用于从当前行中读取和显示图像(它在ADOTable1AfterScroll事件过程中)。当应用程序从一个记录滚到另一个时,AfterScroll事件发生。
 
在MSAccess数据库中图像的存储和显示

在保存图片时用:

TBlobField(FieldByName('ZLPIC')).LoadFromFile(OPD.FileName);
其中OPE为一个打开文件对话框。

在打开图片时用:
MS := CreateBlobStream(FieldbyName('ZLPIC'),bmRead);
Image2.Picture.LoadFromStream(MS);
MS.Free;
MS 为TStream的变量。
从来没有什么问题,显示、打印都没问题,也没管过什么文件头。



注:以下程序中注意在uses处加上DB,jpeg,如没有则TBlobField找不到
如何实现在MS Access数据库中图像的存储和显示
一、 原理介绍——流式数据的类型及其应用
在Dephi中提供了TStream来支持对流式数据的操作。TStream是万流之源,但由于它是一个抽象类,故不能被直接使用;而要使用其相应的子类,如:TFileStream
、TStringStream、TMemoryStream、TBlobStream、TWinSocketStream和TOleStream。TStream提供了统一、简洁的方法来进行数据的读写。
1.)SaveToStream(Stream: TStream );
作用:将类中的数据写到Stream的当前位置中
2.)LoadFromStream(Stream: TStream); 作用:从当前位置读入Stream里的数据
实际使用时我们基本上只要使用上面两个函数就可以了。
二、所遇到的问题及相应的解决方法
为了节省图像的存储空间和使用更加方便,决定采用JPEG这种图像格式。
(一)所遇到的问题
第一、在Delphi
5中进行画图所用到的组件是TImage,所生成的图像的格式为BMP格式,而为了节省图像的存储空间,图像在数据库里存储的格式须为JPEG格式,这样就产生了图像格式转化的需求;而TImage本身并不直接提供这两种图像格式之间的转化。
第二、怎样将存储在Microsoft Access数据库中的图像取出并且显示出来:在Delphi
5中,能提供这种功能的组件是TDBImage,但该组件却存在着一个很大的缺陷:它所能显示的图像类型只能是一些图标文件,元文件和BMP文件,而不能支持JPEG格式的图像在该组件中的显示;但根据实际需要,在Microsoft
Access数据库中所存储的图像数据却是以JPEG格式保存的。
(二)相应的解决方法
为了解决上述两个问题,可以采用目前数据库中一种名为大二分对象(BLOB——Binary Large
Object),它是用来处理某些特殊格式的数据的。BLOB在数据库的表中实际上是以二进制数据的形式存放的。
为了处理BLOB字段,可以借鉴一些可视的桌面数据库的方法。在这里,我们选择了通过内存流的方式来完成;使用内存流,可减少磁盘操作,大大提高运行效率。
具体的过程和相关的程序代码如下:



1、如何实现在Microsoft Access数据库中的图像存储:
这里是利用TStream的子类TMemoryStream向Microsoft
Access数据库中存储图像的。下面的这段代码是在按了“保存”按钮之后所触发的事件处理程序:
procedure TForm1.Button1Click(Sender: TObject);
var
MyJPEG : TJPEGImage;
MS: TMemoryStream;
begin
MyJPEG := TJPEGImage.Create;
try
with MyJPEG do
begin
Assign(Image.Picture.Graphic);
MS:=TMemoryStream.create;
SaveToStream(MS);
MS.Position:=0;
Table1.Edit;

TBlobField(Table1.FieldbyName('Image')).LoadFromStream(MS);
Table1.Post;

messagebox(getactivewindow(),'图像保存完毕!','保存',mb_ok);
end;
finally
MyJPEG.Free;
end;
end;
在这段代码里TStream的子类TMemoryStream利用内存流起到了将BMP格式转化为JPEG格式的中间桥梁的作用。



2、如何将图像从Microsoft Access数据库中取出并显示出来:
下面的这段代码是在按了“查看图像”按钮之后所触发的事件处理程序:
procedure TForm1.Button1Click(Sender: TObject);
var tempstream:TStringStream;
tempjpeg:TJPEGImage;
begin
try
tempstream:=TStringStream.Create(' ');

TBlobField(Query1.FieldByName('Image')).SaveToStream(tempstream);

tempstream.Position:=0;
tempjpeg:=TJPEGImage.Create;
tempjpeg.LoadFromStream(tempstream);
DBImage1.Picture.Bitmap.Assign(tempjpeg);
finally
tempstream.Free;
tempjpeg.Free;
end;
end;
这段代码的主要作用是:首先将查询结果中的JPEG图像格式数据保存到TStringStream中去,然后设置数据指针在TStringStream中的位置为0;接着从TStringStream中读入相关数据,并把它们赋给TDBImage.Picture.Bitmap,这样一来就实现了将数据库中所存储的JPEG格式的数据转化为BMP格式,并在TDBImage中将图像显示出来。最后将TStringStream和TJPEGImage这两个对象释放掉。特别要注意的是不能在设计阶段设置TDBImage的DataField属性,而只能通过写代码的形式在运行阶段把利用流式数据所转化过来的新格式的图像数据赋给TDBImage.Picture.Bitmap。

使用ADO连接
1.保存
TBlobField(ADOQuery1.FieldName('blob')).Loadfromfile('文件名')
提取
TBlobField(ADOQuery1.FieldName('blob')).Savetofile('文件名')
2.
保存
(ADOQuery1.FieldByName('blob') as
TBlobField).Loadfromfile('文件名')
提取
(ADOQuery1.FieldByName('blob') as
TBlobField).Savetofile('文件名')
 
分分
myhby 25分
无泪 25分
 
多人接受答案了。
 
后退
顶部