图像存取数据库问题(200分)

  • 主题发起人 主题发起人 wohoot
  • 开始时间 开始时间
W

wohoot

Unregistered / Unconfirmed
GUEST, unregistred user!
要是图像直接存数据库,量大的话,数据库会恶性膨胀,我的意思是数据库只存图片的保存路径,应该怎么样实现图片路径的存入和读取?
 
偶有办法,可以用一个自增类型编号,文件名就以编号命名,全部copy到程序下的一个方件夹中,要用的时候直接loadfromfile就O了!
 
老大,不明白你的意思,保存路径直接用字符串就可以阿
数据的插入,读取而已
 
不就是把路径存入数据库,建一个主键ID与记录关联起来不就OK了,
 
图片的路径就是一个简单的字符字段阿!
或者楼主还有别的想法。
 
字符字段存放文件路径
 
存图片用IMAGE字段的话,最大可以存2G,但如果存路径的话那也就是个字符串,从库中将那个字段读出即可
 
uses jpeg;
保存Image1中的图象至数据库 :
var
Ms:TmemoryStream;
jpg:Tjpegimage;
begin
ms:=TmemoryStream.Create;
Jpg.Assign(Image1.Picture.Graphic);
Jpg.SaveToStream(Ms) ;
Ms.Position :=0;
ADOquery1.append;
TBlobField(ADOquery1.FieldByName('img')).LoadFromStream(Ms);
ADOquery1.Post;
Ms.Free ;
jpg.free;
end;
从数据库中读取图象到image2中:
Var
Ms:TStringStream;
jpg:Tjpegimage;
begin
Ms:=TstringStream.Create('');
TBlobField(ADOquery1.FieldByName('img')).SaveToStream(Ms);
Ms.Position :=0;
Jpg.LoadFromStream(Ms);
Image2.Picture.Assign(Jpg);
Ms.Free;
jpg.free;
end;

例子2:

procedure TForm1.Button1Click(Sender: TObject); //插入圖片過程
var
testStream:TMemoryStream;
begin
try
testStream := TMemoryStream.Create; //創建內存流
Image1.Picture.Graphic.SaveToStream(testStream);  //將圖片保存至內存流中
adoquery1.Close;
adoquery1.SQL.Clear;
adoQuery1.SQL.Add('Insert into test (id,photo) values (:id,:photo)'); //進行插入操作
adoquery1.Parameters.ParamByName('id').Value := '003';
adoQuery1.Parameters.ParamByName('photo').LoadFromStream(testStream,ftBlob); //讀取保存的內存圖
adoquery1.ExecSQL;
finally
testStream.Free;   //釋放內存流
end;
end;

procedure TForm1.Button2Click(Sender: TObject); //讀取圖片過程
var
mStream:TMemoryStream;
JpgFile:TjpegImage;
begin
if not ADOQuery1.FieldByName('photo').IsNull then begin ;
mStream:=TMemoryStream.Create ;
JpgFile:=TjpegImage.Create ;
TBlobField(ADOQuery1.FieldByName('photo')).SaveToStream(mStream);  //顯示的轉換為BlobFiled並保存至內存流
mStream.Position :=0;
jpgfile.LoadFromStream(MStream);
image2.Picture.Assign(JpgFile);
end
else begin
image2.Picture :=nil;
end;
end;


将bmp图保存到Access数据库中
var
mem: TMemoryStream;
begin
mem := TMemoryStream.Create;
mem.LoadFromFile('图.bmp');
TBlobField(FiledByName('Data')).LoadFromStream(mem);
mem.Free;
end;
 
岂有此理,有家用我刚才发的代码来争分??!!
 
不过你所说的还是存到库中了,
如果只存一个路径的话只要存openpicturedialog.filename就可以了
 
楼主看看我以下收藏的东东,有价值的:
如何实现在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--Bina
ry 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。


//BMP格式转化为JPEG格式uses Jpeg;

procedure CopyBmpToJpeg(BmpFile,JpegFile:string);
var
Bmp:TBitmap;
Jpeg:TJPEGImage;
begin
Bmp:=TBitmap.create;
Jpeg:= TJpegImage.Create;
try
Bmp.LoadFromFile(BmpFile);
Jpeg.Assign(Bmp);
Jpeg.SaveToFile(JpegFile);
finally
Bmp.Free;
Jpeg.Free;
end;
end;



2003-10-7 14:28:34 图片缩放Var B:Tbitmap; //临时位图
Begin
B:=Tbitmap.Create; //建立临时位图
B.Assign(YourBitmap); //采用相同色彩深度
With B do
Begin
Width:=90; //临时位图的大小为90x90
Height:=90;
End;
B.canvas.StretchDraw(B.canvas.Cliprect,YourBitmap); //缩放适应
B.SavetoFile(YourFileName); //保存
B.Free;
End; //搞定




2003-10-22 10:33:33 JPEG和BMP同时存入,两种不同的方法,文件流和内存流procedure TForm1.Button1Click(Sender: TObject);
var
fs:TFileStream;
MS: TMemoryStream;
Bmp:TBitmap;
MYJpeg:TJPEGImage;
begin
if OpenPictureDialog1.Execute then
begin
if ExtractFileExt(OpenPictureDialog1.FileName) = '.bmp' then
begin
Bmp:=TBitmap.create;
MYJpeg:= TJpegImage.Create;
MS:=TMemoryStream.create;
try
Bmp.LoadFromFile(OpenPictureDialog1.FileName);
with MYJpeg do
begin
Assign(Bmp);
MS.Position:=0;
SaveToStream(MS);
Table1.Edit;
TBlobField(Table1.FieldByName('ZGZP')).LoadFromStream(MS);
Table1.Post;
end;
finally
Bmp.Free;
MYJpeg.Free;
MS.Free;
end;
end
else
begin
fs:=TFileStream.Create(OpenPictureDialog1.FileName,fmOpenRead);
Try
Table1.Edit;
TBlobField(Table1.FieldByName('ZGZP')).LoadFromStream(fs);
Table1.Post;
Finally
fs.free;
end;
end;
end;


2003-11-13 21:03:18 图片的缩放procedure TForm1.Button1Click(Sender: TObject);
var
b: TBitmap;//原图片
nb: TBitmap;//Resize以后的图片
r: TRect;
begin
b := TBitmap.Create;

if OpenDialog1.Execute then
begin
b.LoadFromFile(OpenDialog1.FileName);
nb := TBitmap.Create;

//你可以自己定义高度和宽度,这里是都变成一半
nb.Height := b.Height div 2; //高度变为原来的一半
nb.Width := b.Width div 2; //宽度变为原来的一半
r.TopLeft := Point(0, 0);
r.BottomRight := Point(nb.Width, nb.Height);

with nb.Canvas do
begin
Pen.Style := psDash;
Brush.Style := bsClear;
Rectangle(0, 0, nb.Width, nb.Height);
StretchDraw(r, TGraphic(b));
end;
if SaveDialog1.Execute then nb.SaveToFile(SaveDialog1.FileName);
nb.Free;
end;
b.Free;
end;
 
字符串保存路径可行
 
保存相对路径好维护些
 
感谢大家的指点,我的意思图片还要经常更换的,另外在存入时要能够预览,该怎么做,我试过了效果不理想啊
 
预览的话,我不知道你说的数据库预览还是别的什么预览,要是数据库的话偶不清楚,如果不是的话,应用组件TSavePictureDialog就行
 
[red]友情提示:[/red]
存储文件路径时建议用nchar类型,用varchar或nvanchar的话你会遇到麻烦,如中文带空格长文件路径。
 
谢谢大家,存的问题解决了,还有怎么取的问题,就是在DBGIRD1中随着记录的选择,图片怎么样显示?注意我只保存了JPEG图片的路径,请写出具体代码及在什么事件中?
 
主要是在数据表中你想图片与相应的数据显示,,首先存储图片相对路径字段所在的行,还有一些字段用来与相应的数据相关联,这样就可以同时显示了。
 
感谢大家指点,存储问题已解决,但读取问题好没有,另发新贴求解。
 
多人接受答案了。
 
后退
顶部