database - 将 jpeg 图像保存和加载到数据库不工作 DELPHI

标签 database image delphi pascal

我正在尝试制作一个将图像保存在数据库中的程序。我收集了网上的一些信息并编写了我认为应该有效的代码,但在任何一方(保存和加载)都以完全独特的方式失败了。

这是我的代码,你能告诉我我做错了什么吗?

从数据库加载,给我一个内存地址访问冲突错误:

    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/

相关文章:

database - 将图像存储在数据库中

delphi - Delphi 6中如何检测鼠标何时离开TPanel?

delphi - 我可以将某个对象的类注释为类型吗?

php - 在网页的 HTML 表中显示 MySQL 数据库表中的值

python - Django检查数据库中是否存在值,如果不存在则创建并保存

mysql - 用于存储用户多种爱好的关系数据库结构

delphi - Indy 10 中的 TIdHTTP

mysql - 选择语句

image - 将图像导入 intelliJ Java 项目

java - 在桌面应用程序中使用动画 GIF