高手帮帮忙:关于stream图存SQL库的问题(100分)

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

drmy

Unregistered / Unconfirmed
GUEST, unregistred user!
我下面这段程序是把stream的图片存到sql数据库中,然后再读出来。
问题是如果把Width和Height设得大了,显示的图片就不完整。
我觉得可能是存库的方法不对,造成了只有部分图象数据存入,所以显示不完整。
高手帮帮忙吧!最后用C++Builder。
{
IdmGrayBmp* pBitmap = new IdmGrayBmp();
int Width = 100;
int Height = 100;
LPBYTE Buf = new BYTE[Width*Height];
memset(Buf, 255, Width*Height);
pBitmap->Set(Buf, Width, Height);

Coil_Query->SQL->Clear();
Coil_Query->SQL->Add("SELECT Max(CoilID) FROM dbo.Image");
Coil_Query->Open();
DWORD dwCoilID = Coil_Query->Fields->Fields[0]->AsInteger + 1;

Coil_Query->SQL->Clear();

Coil_Query->SQL->Add("INSERT INTO dbo.Image ");
Coil_Query->SQL->Add("VALUES(:Coil_Id, :Image)");
Coil_Query->Params->ParamByName("Coil_Id")->AsInteger = dwCoilID;
Coil_Query->Params->ParamByName("Image")->Assign(pBitmap->GetBitmap());

if (!Coil_Query->Prepared)
{
Coil_Query->Close();
Coil_Query->Prepare();
}
Coil_Query->ExecSQL();

delete pBitmap;
delete[] Buf;

Coil_Query->SQL->Clear();
Coil_Query->SQL->Add("SELECT Image FROM dbo.Image where CoilID = " + AnsiString(dwCoilID));
Coil_Query->Open();

TStream *pStream;
pStream = Coil_Query->CreateBlobStream(Coil_Query->FieldByName("Image"), bmRead);
ImageEn1->LoadFromStream(pStream);
}
 
var
stream :TMemoryStream;
begin
stream :=TMemoryStream.Create;
stream.loadFromFile('c:/11.jpg');
Table1.append
(table1.Fieldbyname('zd') as TBLOBFIELD).loadFromstream(stream);
或者
(table1.Fieldbyname('zd') as TBLOBFIELD).loadFromFile('c:/11.jpg');

Table1.Post;
Stream.free;
 
phosphor:
我已经知道了怎么用Table打开硬盘文件存到库中,我不知道的是如何把从网络中
传来的内存图象存到数据库中阿,谢谢多费心了。
 
可不可以用内存流来读取内存图象,再转成文件流写到硬盘中做中转,
或是直接转化成BLOB写进数据库。
 
不要中转成硬盘文件了,我们原来就是直接存到文件的,这样效率太低,怎么能直接存到
库中呢?最好用sql语句实现。
这个问题这么难吗?
 
此例采用JPEG图片,用BMP也可。

#include <jpeg.hpp>

//从数据库中读取图片
void __fastcall TForm1::ReadBtnClick(TObject *Sender)
{
TJPEGImage *jpg;
TADOBlobStream *bs;
AnsiString FileName="C://temp//Image01.jpg";

qr->Close();
qr->SQL->Clear();
qr->SQL->Add("SELECT * FROM Images");
qr->Open();
if (!qr->Eof)
//为了简化,这里只读取数据库表中的第一条记录,读其它记录请自行修改
try{
jpg = new TJPEGImage();
bs = new TADOBlobStream((TBlobField *)qr->Fields->Fields[1], bmRead);
jpg->LoadFromStream(bs);
jpg->SaveToFile(FileName); //这一句没有实际意义,可以删除
Image1->Canvas->Draw(0,0,jpg);
qr->Close();
}__finally{
delete jpg;
delete bs;
}
}
//---------------------------------------------------------------------------
//将图片写入数据库
void __fastcall TForm1::WriteBtnClick(TObject *Sender)
{
TJPEGImage *jpg;
AnsiString FileName;

if (OpenPictureDialog1->Execute())
FileName = OpenPictureDialog1->FileName;
try{
jpg = new TJPEGImage();
jpg->LoadFromFile(FileName);
qr->Close();
qr->SQL->Clear();
qr->SQL->Add("SELECT * FROM Images");
qr->Open();
qr->Append();
qr->Fields->Fields[1]->Assign(jpg);
qr->Post();
qr->Close();
}
__finally{
delete jpg;
}
}
//---------------------------------------------------------------------------
 
谁能告诉我怎么修改上面的程序,把从网络传过来的内存图象(Byte流)直接存到数据库
中呢?
 
我有个新的发现,就是用BDE处理这个问题会出现储存数据不完整的情况,用ADO连接就一切正常,为什么?用ODBC呢,怎么用呢?
能改改BDE使它能用吗?
 
没有发现这个问题。我去试一试。
好长时间没有用BDE了,如果你用SQL Server数据库的话,ADO是最好的选择,不要去想什么
ODBC了,它只有一个用途——就是在找不到相关数据库的客户端驱动程序时临时代用一下。
 
Sachow:
这个问题我目前也只能算是基本解决了,我的发现是:同样的方法BDE保存不完整,
ADO就一切正常,如果用存储过程就需要用到SQL语句,用到Assign函数,
所以BDE和ADO都不成功,所以只能用table来存数据了。
由于我们必须用BDE,所以我干脆把源stream进行了无损压缩处理,然后存库,
读库后,先解压缩再显示图片。
因为我们的程序规模比较大,全改成ADO没有时间了,所以还是进量用BDE,当然我考虑
只是在这个功能上使用一下。老板说试试这个功能用ODBC来实现,我还不会用?
还有别人能有更好的办法吗?
 
我BDE也试也试了一下,存进去和读出来的图片大小完全是一样的,不会有不完整的问题。
我用的是Oracle 8.1.7客户端连接Oracle 7.3.4数据库,存放图片的字段用的是
LONG RAW类型,而且我用的是TQuery来干的这件事,但是BDE默认的Blob Size是32K,文件
大于这个值就不能传,要修改连接数据库的TDababase的Params值,将Blob Size和Blobs
To Cache改大一点才行,用ADO没有这个问题。
void __fastcall TForm1::WriteBtnClick(TObject *Sender)
{
TJPEGImage *jpg;
AnsiString FileName;
int i=0;

if (OpenPictureDialog1->Execute())
FileName = OpenPictureDialog1->FileName;
try{
jpg = new TJPEGImage();
jpg->LoadFromFile(FileName);

Query1->Close();
Query1->SQL->Clear();
Query1->SQL->Add("SELECT * FROM IMAGES");
Query1->RequestLive = true;
Query1->Open();
while(!Query1->Eof){ //计算记录数
Query1->Next();
i++;
}
Query1->Append();
Query1->FieldByName("IMG_ID")->AsInteger = i+1;
Query1->FieldByName("IMG_DATA")->Assign(jpg);
Query1->Post();
Query1->Close();
}
__finally{
delete jpg;
}
}
//---------------------------------------------------------------------------
 
Sachow:
你说得非常对,BDE默认的Blob Size是32K,文件大于这个值仍然可以存库,但是只能读
那么大的图,所以不完整。我在控制面板中修改了这个数值,就可以了,请问怎么用程序
修改连接数据库的TDababase的Params值,将Blob Size和Blobs To Cache改大一点?
我上午自己发现这个解决方法,老兄你要是早告诉我就好了,呵呵。
不过分数肯定是你的了(先帮我看看上面的问题吧:)
 
双击你窗体上(或数据模块中)的TDatabase控件,出现属性编辑对话框,填好Database Name
和选好Alias属性,点击Defaults对话框,该数据库别名的默认值就会被导入到Parameter
Overrides的文本框内,修改了其中的“BLOBS TO CACHE”和“BLOB SIZE”两个值,确定即可。
 
后退
顶部