请问如何将*.jpg或非bmp格式的图片保存到数据库并能读出(50分)

  • 主题发起人 主题发起人 dx2527
  • 开始时间 开始时间
D

dx2527

Unregistered / Unconfirmed
GUEST, unregistred user!
如题:
ADO+SQL Server
SQL Field : Image
 
USES
JPEG;

Var
Jpeg:TJpegImage;
begin
Jpeg:=TJpegImage.Create;
Jpeg.LoadFromFile('文件 ');
DBImage1.Picture.Assign(Jpeg.Picture);
DBImage1.clip**
DBImage1.*****
end;
后面两个函数忘了不过会自动出来查一下就行。
end;
 
转一个:
var
bmp:tbitmap;
jpg:tjpegimage;
str,str1:tmemorystream;

if (adoquery1.FieldByName('ZP').Value)='' then
begin
image1.Picture.Graphic:=nil
end
else begin
try
str:=tmemorystream.Create;
str.Position:=0;
tblobfield(adoquery1.FieldByName('ZP')).SaveToStream(str);
str.Position:=0;
image1.Picture.Graphic:=nil;
image1.Picture.Graphic:=tjpegimage.Create;
image1.Picture.Graphic.LoadFromStream(str);
except
image1.Picture.Graphic.LoadFromStream(str);
end;
str.Free;
end; //显示照片

str:=tmemorystream.Create;
progressbar1.StepBy(15);
image1.Picture.Graphic.savetostream(str);
progressbar1.StepBy(35);
str.position:=0;
tblobfield(dmunit.Ztb_DM.zjADOQuery.fieldbyname('ZP')).loadfromstream(str);
progressbar1.StepBy(30);
dmunit.Ztb_DM.zjADOQuery.Post;
progressbar1.StepBy(20);
str.Free; //保存图片
 
如何实现在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。

 
abc_xp说得对,用MemoryStream方便灵活
 
用文件流的方式
 
一个简单的DEMO,适用于大多数文件保存到数据库或从数据库中取出:
procedure TForm1.Button1Click(Sender: TObject);
begin //-----这是从文件到数据库
with DataModule1.ADOQuery1 do
begin
Close;
SQL.Clear;
SQL.Add('insert into Tab(name,files) values(:aa,:bb)');
Parameters.ParamByName('aa').Value:=Edit1.Text;
Parameters.ParamByName('bb').LoadFromFile('C:/a.jpg',ftVarBytes);//指定文件来源路径
ExecSQL;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var aStream:TADOBlobStream;
begin //----------这是从数据库到文件
with DataModule1.ADOQuery1 do
begin
Close;
SQL.Clear;
SQL.Add('select * from tab where name=:aa');
Parameters.ParamByName('aa').Value:=Edit1.Text;
Open;
end;

ShowMessage('查找到:'+inttostr( DataModule1.ADOQuery1.RecordCount)+'条记录!');

if not DataModule1.ADOQuery1.IsEmpty then
begin
aStream:= TADOBlobStream.Create(DataModule1.ADOQuery1.FieldByName('files') as TBlobField, bmRead);
aStream.Position:=0;
aStream.SaveToFile('C:/b.jpg'); //指定文件保存路径
aStream.Free;
end;
end;
 
//保存图片(*.jpg)
var
JPEGImage: TJPEGImage;
Stream: TMemoryStream;
begin
if OpenpictureDialog1.Execute then
begin
JPEGImage:= TJPEGImage.Create;
Stream:= TMemoryStream.Create;

ADOQuery1.Insert;
//JPEGImage.Assign(Image1);
JPEGImage.LoadFromFile(OpenPictureDialog1.FileName);
JPEGImage.SaveToStream(Stream);
TBlobField(ADOQuery1.FieldByName('Image')).LoadFromStream(Stream);
ADOQuery1.Post;
JPEGImage.Free;
Stream.Free;
end;
end;

//用image1显示库中图片
procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
var
MS: TStream;
JPEG: TJPEGImage;
begin
with ADOQuery1 do
MS:=CreateBlobStream
(FieldbyName('image_Picture'),bmRead);
JPEG:= TJPEGImage.Create;
JPEG.LoadFromStream(MS);
JPEG.SaveToFile('C:/111.JPG');<--此处报错
Image1.Picture.LoadFromFile('C:/111.JPG');
JPEG.Free;
MS.Free;
end;
 
如果MDB数据库里的ZP字段保存如: ./pic/111.jpg 这样的内容,我用DBImage控件(该控件嵌在DBCtrl控件中)从库中读出,如何实现?
实际的JPG文件放在当时目录的PIC目录中
 
很简单,用流啊,即Delphi中的Blob字段,关送你一个控件吧,DB的,可以直接将Jpeg存入数据库。

E-Mail?
 
xionglin@dgnantai.com.hk

Thank you!
 
Uses JPEG;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);//save picture
var
JPEGImage: TJPEGImage;
Stream: TMemoryStream;
begin
if OpenpictureDialog1.Execute then
begin
JPEGImage:= TJPEGImage.Create;
Stream:= TMemoryStream.Create;

ADOQuery1.Insert;
//JPEGImage.Assign(Image1);
JPEGImage.LoadFromFile(OpenPictureDialog1.FileName);
JPEGImage.SaveToStream(Stream);
TBlobField(ADOQuery1.FieldByName('Image_Picture')).LoadFromStream(Stream);
ADOQuery1.Post;
JPEGImage.Free;
Stream.Free;
end;
ADOQuery1.Close;
ADOQuery1.Open;
end;

procedure TForm1.Button3Click(Sender: TObject);//show the picture
var
jpeg:tjpegimage;
stream :TMemoryStream;
begin
if TBlobField(adoquery1.FieldByName('Image_Picture')).BlobSize>0 then
begin
jpeg:=tjpegimage.Create;
stream :=TMemoryStream.Create;
tblobfield(adoquery1.FieldByName('Image_Picture')).savetostream(stream);
Stream.Seek(0,soFromBeginning);//好象要加?句的,?是stream?出?的有流的?
//?信息,所以你的JPEG LOAD ?????不是
//有效的JPEG文件。
jpeg.loadfromstream(stream);
image1.Picture.Bitmap.Assign(jpeg);
jpeg.Free;
stream.Free;
end
else
image1.Picture:=nil;
end;

上面语句可以实现保存/读出*.jpg图片且只能是jpg格式的图片,其它格式则会报错,那幺该如何判断是否为jpg格式呢?加一字段标明吗?如果是tif或gif格式的图片又如何来保存和读出呢?
有高手能帮忙解答吗?

 
TO dx2527:
控件已发,请查收!
 
To lichaogang:
谢谢,已收到!!
可否再帮忙想一想如何处理gif格式图片?有没有通用的方法?
Tif格式的好象是要装一个外部的程序,在www.delphipages.com上有下
 
有大虾能否再帮忙看看有没有通用的方法?
 

function JpegStartsInBlob(PicField:TBlobField):integer;
var
ghy: TADOBlobstream;
buffer:Word;
hx: string;
begin
Result := -1;
ghy := TADOBlobstream.Create(PicField, bmRead);
try
while (Result = -1) and (ghy.Position + 1 < ghy.Size) do
begin
ghy.ReadBuffer(buffer, 1);
hx:=IntToHex(buffer, 2);
if hx ='FF' then begin
ghy.ReadBuffer(buffer, 1);
hx:=IntToHex(buffer, 2);
if hx = 'D8' then Result := ghy.Position - 2
else if hx = 'FF' then
ghy.Position := ghy.Position-1;
end; //if
end; //while
finally
ghy.Free
end; //try
end;
{上面的函数用来测试图片数据在BLOB字段中的起始位置}
procedure TForm3.ADOQuery1AfterScroll(DataSet: TDataSet);
var
ghy:TADOBlobstream;
pic:tjpegimage;
begin
with adoquery1 do
if not(State = dsEdit) or not(State = dsInsert) then
begin
if not FieldByName('zp').IsNULL then
begin
ghy := TADOBlobstream.Create(FieldByName('zp') as TBlobField, bmRead);
try
ghy.Seek(JpegStartsInBlob(FieldByName('zp') as TBlobField),soFromBeginning);
Pic:=TJpegImage.Create;
try
Pic.LoadFromStream(ghy);
Image1.Picture.Graphic:=Pic;
finally
Pic.Free;
end;{try}
finally
ghy.Free
end;{try}
image1.Show;
end {if}
else
image1.Hide;
end;{if}
end;
{当指针移动时显示图片到Image1中}procedure TForm3.Button4Click(Sender: TObject);
var
ghy:TadoBLOBStream;
begin
with adoquery1 do begin
edit;
ghy := TADOBlobStream.Create(FieldByName('zp') as TBlobField, bmRead);
if OpenPictureDialog1.execute then begin
ghy.LoadFromFile(OpenPictureDialog1.filename);
ghy.Position:=0;
edit;
Tblobfield(FieldByName('zp')).LoadFromStream(ghy);
post;
end;
end;
ghy.Position:=0;
image1.Picture.Graphic.LoadFromStream(ghy);
ghy.free;
end;
{更改图片并显示}

 
多人接受答案了。
 
后退
顶部