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

时间:2013-08-13 16:42:55

标签: 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;

1 个答案:

答案 0 :(得分:4)

您正在调用TGraphic.LoadFromStream(),但您没有预先使用有效的TPicture.Graphic派生对象初始化TGraphic属性,因此该属性很可能是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类类型({{1} },TBitmapTJpegImageTGifImage等)根据需要处理它,例如:

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方法,让ADO为您提供一个优化用于访问ADO blob数据的TDataSet.CreateBlobStream()对象,例如:

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;