我正在尝试制作一个将图像保存在数据库中的程序。我收集了网上的一些信息并编写了我认为应该有效的代码,但在任何一方(保存和加载)都以完全独特的方式失败了。
这是我的代码,你能告诉我我做错了什么吗?
从数据库加载,给我一个内存地址访问冲突错误:
procedure TfrmMain.btnAddPickT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
begin
if cbxDeelnemerT4.ItemIndex < 0 then
begin
MessageDlg('Kies asseblief ''n deelnemer!',mtInformation,[mbOK],1);
Exit;
end;
if OpenPictureDialog1.Execute then
if FileExists(OpenPictureDialog1.FileName) then
Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName)
else
MessageDlg('Die lêer bestaan nie!',mtError,[mbOK],1);
ikode := cbxDeelnemerT4.ItemIndex + 1;
S := TMemoryStream.Create;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = '+inttostr(ikode);
ADOQuery1.Open;
try
Image1.Picture.Graphic.SaveToStream(S);
S.Position := 1;
ADOQuery1.Insert;
TBLobfield(ADOQuery1.FieldByName('Foto')).LoadFromStream(S);
finally
S.Free;
end;
end;
保存到数据库。此代码不会给出这样的错误,但它不会将图像保存到数据库中:
procedure TfrmMain.btnOpenProfileT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
begin
ikode := cbxDeelnemerT4.ItemIndex + 1;
S := TMemoryStream.Create;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = '+inttostr(ikode);
ADOQuery1.Open;
try
TBlobField(ADOQuery1.FieldByName('Foto')).SaveToStream(S);
S.Position := 0;
Image1.Picture.Graphic.LoadFromStream(S);
finally
s.Free;
end;
end;
最佳答案
您正在调用 TGraphic.LoadFromStream()
但您没有使用有效的 TGraphic
派生对象预先初始化 TPicture.Graphic
属性,因此该属性可能是 nil
,导致崩溃。
此外,将 TPicture.Graphic
保存到 TMemoryStream
时,将图形保存到数据库时会跳过图形的第一个字节。所有字节都很重要,所以不要跳过任何一个。
假设您的图像是专门的 JPEG 而不是其他(您的保存代码不限制文件类型),那么试试这个:
procedure TfrmMain.btnAddPickT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
begin
if cbxDeelnemerT4.ItemIndex < 0 then
begin
MessageDlg('Kies asseblief ''n deelnemer!',mtInformation,[mbOK],1);
Exit;
end;
if not OpenPictureDialog1.Execute then
Exit;
Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
if not (Image1.Picture.Graphic is TJpegImage) then
raise Exception.Create('Sorry, only JPG images can be saved in the DB');
ikode := cbxDeelnemerT4.ItemIndex + 1;
S := TMemoryStream.Create;
try
Image1.Picture.Graphic.SaveToStream(S);
S.Position := 0;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = '+IntToStr(ikode);
ADOQuery1.Open;
ADOQuery1.Insert;
try
TBlobField(ADOQuery1.FieldByName('Foto')).LoadFromStream(S);
ADOQuery1.Post;
except
ADOQuery1.Cancel;
raise;
end;
finally
S.Free;
end;
end;
uses
..., Jpeg;
procedure TfrmMain.btnOpenProfileT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
Jpg: TJPEGImage;
begin
ikode := cbxDeelnemerT4.ItemIndex + 1;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = ' + IntToStr(ikode);
ADOQuery1.Open;
S := TMemoryStream.Create;
try
TBlobField(ADOQuery1.FieldByName('Foto')).SaveToStream(S);
S.Position := 0;
Jpg := TJPEGImage.Create;
try
Jpg.LoadFromStream(S);
Image1.Picture.Assign(Jpg);
finally
Jpg.Free;
end;
finally
S.Free;
end;
end;
但是如果你的图像可以是 JPEG 以外的其他格式,那么你还需要将图像类型存储在数据库中,以便你可以读取它并实例化正确的 TGraphic
类类型(TBitmap
, TJpegImage
, TGifImage
, TPNGImage
等)根据需要进行处理,例如:
procedure TfrmMain.btnAddPickT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
begin
if cbxDeelnemerT4.ItemIndex < 0 then
begin
MessageDlg('Kies asseblief ''n deelnemer!',mtInformation,[mbOK],1);
Exit;
end;
if not OpenPictureDialog1.Execute then
Exit;
Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
ikode := cbxDeelnemerT4.ItemIndex + 1;
S := TMemoryStream.Create;
try
Image1.Picture.Graphic.SaveToStream(S);
S.Position := 0;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = '+IntToStr(ikode);
ADOQuery1.Open;
ADOQuery1.Insert;
try
// this is just an example, there are other ways to do this
if Image1.Picture.Graphic is TJPEGImage then
ADOQuery1.FieldByName('FotoType').AsString := 'jpg'
else if Image1.Picture.Graphic is TPNGImage then
ADOQuery1.FieldByName('FotoType').AsString := 'png'
else if Image1.Picture.Graphic is TGIFImage then
ADOQuery1.FieldByName('FotoType').AsString := 'gif'
else if Image1.Picture.Graphic is TBitmap then
ADOQuery1.FieldByName('FotoType').AsString := 'bmp'
else
raise Exception.Create('Cannot save unsupported image type to DB');
TBlobField(ADOQuery1.FieldByName('Foto')).LoadFromStream(S);
ADOQuery1.Post;
except
ADOQuery1.Cancel;
raise;
end;
finally
S.Free;
end;
end;
uses
..., Jpeg, GifImg, PngImg;
procedure TfrmMain.btnOpenProfileT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
Graphic: TGraphic;
GraphicType: String;
begin
ikode := cbxDeelnemerT4.ItemIndex + 1;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = ' + IntToStr(ikode);
ADOQuery1.Open;
S := TMemoryStream.Create;
try
TBlobField(ADOQuery1.FieldByName('Foto')).SaveToStream(S);
S.Position := 0;
GraphicType := ADOQuery1.FieldByName('FotoType').AsString;
if GraphicType = 'jpg' then
Graphic := TJPEGImage.Create
ADOQuery1.FieldByName('FotoType').AsString := 'jpg'
else if GraphicType = 'png' then
Graphic := TPNGImage.Create
else if GraphicType = 'gif' then
Graphic := TGifImage.Create
else if GraphicType = 'bmp' then
Graphic := TBitmap.Create
else
raise Exception.Create('Cannot load unsupported image type from DB');
try
Graphic.LoadFromStream(S);
Image1.Picture.Assign(Graphic);
finally
Graphic.Free;
end;
finally
S.Free;
end;
end;
话虽如此,您不应该直接访问 TBlobField
。请改用 TDataSet.CreateBlobStream()
方法,让 ADO 为您提供一个为访问 ADO blob 数据而优化的 TStream
对象,例如:
procedure TfrmMain.btnAddPickT4Click(Sender: TObject);
var
S : TStream;
ikode : integer;
begin
if cbxDeelnemerT4.ItemIndex < 0 then
begin
MessageDlg('Kies asseblief ''n deelnemer!',mtInformation,[mbOK],1);
Exit;
end;
if not OpenPictureDialog1.Execute then
Exit;
Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
ikode := cbxDeelnemerT4.ItemIndex + 1;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = '+IntToStr(ikode);
ADOQuery1.Open;
ADOQuery1.Insert;
try
...
S := ADOQuery1.CreateBlobStream(ADOQuery1.FieldByName('Foto'), bmWrite);
try
Image1.Picture.Graphic.SaveToStream(S);
finally
S.Free;
end;
ADOQuery1.Post;
except
ADOQuery1.Cancel;
raise;
end;
end;
procedure TfrmMain.btnOpenProfileT4Click(Sender: TObject);
var
S : TStream;
ikode : integer;
Graphic: TGraphic;
begin
ikode := cbxDeelnemerT4.ItemIndex + 1;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = ' + IntToStr(ikode);
ADOQuery1.Open;
...
Graphic := ...;
try
S := ADOQuery1.CreateBlobStream(ADOQuery1.FieldByName('Foto'), bmRead);
try
Graphic.LoadFromStream(S);
finally
S.Free;
end;
Image1.Picture.Assign(Graphic);
finally
Graphic.Free;
end;
end;
关于database - 将 jpeg 图像保存和加载到数据库不工作 DELPHI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18214686/