问题描述:在form上放一个 TImage控件(Image1),一个 Button 控件, 加入 JPEG单元,
当按下此 button 时,执行如下代码 Stream.LoadFromFile('d:\kk.jpg');    // d:\kk.jpg 存在
 Image1.Picture.Graph.LoadFromStream(Stream);    <= 此句出错,意思是说地址存取出错 而如果此Image1事先装载有任何一张图片,然后 Image1.Picture.Graph.LoadFromStream(Stream) 则执行正确我估计出错的原因是image1没有生成一个picture或Graph的实例,导致地址存取失败,请问如何解决之.(请不要回答说事先加载一张图片).

解决方案 »

  1.   

    [转贴]存取四种图形格式BMP、EMF、WMF、ICO、JPEG到SQL Server 数据库 
    程序根据图形文件的属性,在流文件的头上写入属性和文件长,而后再写入数据库,从数据库中读出数据后根据图形文件的格式,调用相应的驱动。此程序原是写来自用的,觉得我的思路和他的有很大的不同,希望对大家有点启发,有任何问题,概不负责。LSI.DMF
    object Form1: TForm1
     Left = 256
     Top = 115
     Width = 452
     Height = 380
     Caption = ’Form1’
     Color = clBtnFace
     Font.Charset = DEFAULT_CHARSET
     Font.Color = clWindowText
     Font.Height = -11
     Font.Name = ’MS Sans Serif’
     Font.Style = []
     OldCreateOrder = False
     OnCreate = FormCreate
     PixelsPerInch = 96
     TextHeight = 13
     object Image1: TImage
      Left = 152
      Top = 24
      Width = 145
      Height = 177
      Stretch = True
     end
     object ButtonLoadImg: TButton
      Left = 56
      Top = 272
      Width = 105
      Height = 25
      Caption = ’Load Img To DB’
      TabOrder = 0
      onClick = ButtonLoadImgClick
     end
     object ButtonSaveImg: TButton
      Left = 264
      Top = 272
      Width = 113
      Height = 25
      Caption = ’Read Img From DB’
      TabOrder = 1
      onClick = ButtonSaveImgClick
     end
     object ADOConnection1: TADOConnection
      Connected = True
      ConnectionString = 
       ’Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security In’ +
       ’fo=False;Initial Catalog=MYDB;Use Procedure for Prepare=1;Auto T’ +
       ’ranslate=True;Packet Size=4096;Workstation ID=MY-SERVER;Use E’ +
       ’ncryption for Data=False;Tag with column collation when possible’ +
       ’=False’
      LoginPrompt = False
      Mode = cmShareDenyNone
      Provider = ’SQLOLEDB.1’
      Left = 32
      Top = 40
     end
     object ADOTable1: TADOTable
      Connection = ADOConnection1
      CursorType = ctStatic
      TableName = ’Img’
      Left = 32
      Top = 80
     end
     object OpenPictureDialog1: TOpenPictureDialog
      Left = 32
      Top = 128
     end
    end//……………………………………………………………………………………..
    LSI.PAS
    unit LSI;interfaceuses
     Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
     StdCtrls, ExtCtrls, Db, ADODB, Jpeg, ExtDlgs, LoadSaveImg;type
     TForm1 = class(TForm)
      Image1: TImage;
      ButtonLoadImg: TButton;
      ButtonSaveImg: TButton;
      ADOConnection1: TADOConnection;
      ADOTable1: TADOTable;
      OpenPictureDialog1: TOpenPictureDialog;
      procedure FormCreate(Sender: TObject);
      procedure ButtonLoadImgClick(Sender: TObject);
      procedure ButtonSaveImgClick(Sender: TObject);
     private
      TS: TMemoryStream;
      LSI: TLSImg;
     end;var
     Form1: TForm1;implementation{$R *.DFM}procedure TForm1.FormCreate(Sender: TObject);
    begin
     if not ADOTable1.Active then
      ADOTable1.Active := True;
    end;procedure TForm1.ButtonLoadImgClick(Sender: TObject);
    var
     FName, FType: string;
    begin
     OpenPictureDialog1.Filter := GraphicFilter(TGraphic);
     if OpenPictureDialog1.Execute then
     begin
      FName := OpenPictureDialog1.Files.Strings[0];
      FType := Copy(FName, LastDelimiter(’.’, FName) + 1, Length(Fname) - LastDelimiter(’.’, Fname));
      LSI := TLSImg.Create;
      if LSI.GetImgType(FType) <> 0 then
      begin
       TS := TMemoryStream.Create;
       LSI.Picture.Graphic.LoadFromFile(FName);
       LSI.SaveToStream(TS);
       with ADOTable1 do
       begin
        try
         Append;
         (Fields[1] as TBlobField).LoadFromStream(TS);
         Post;
        except
         raise
        end;
       end;
       TS.Free;
      end;
      LSI.Free;
     end;
    end;procedure TForm1.ButtonSaveImgClick(Sender: TObject);
    begin
     with ADOTable1 do
     begin
      if not Eof then
      begin
       LSI := TLSImg.Create;
       TS := TMemoryStream.Create;
       (Fields[1] as TBlobField).SaveToStream(TS);
       LSI.LoadFromStream(TS);
       Image1.Picture := LSI.Picture;
       TS.Free;
       LSI.Free;
      end;
     end;
    end;
    end.
    //…………………………………………………………………………………..
    LoadSaveImg.Pasunit LoadSaveImg;interface
    uses
     SysUtils, Classes, Graphics, Jpeg, DB, ADODB;//这里的图形属性顺序是随意安排的,可自行修改,现在的顺序和FastReport相同,在FastReport中打印图像//时可用返回的图形属性设置 FastReport 的Picture 组件的 BlobType。
    //procedure TForm1.frReportBeforePrint(Memo: TStringList; View: TfrView);
    //begin
    // if (View is TfrPictureView) and ((View as TfrPictureView).Name = ’Picture1’) then
    // begin
    //  (View as TfrPictureView).BlobType := LSImg.LoadFromStream(Stream);
    //  (View as TfrPictureView).Picture.Assign(LSImg.Picture1.Picture);
    // end;
    //end;const
     pkBitmap = 0;
     pkJPEG = 1;
     pkIcon = 2;
     pkMetafile = 3;
     pkNone = 4;type
     TLSImg = class(TObject)
     private
     public
      Picture: TPicture;
      Graphic: TGraphic;
      constructor Create;
      destructor Destroy; override;
      function GetImgType(const FileType: string): Byte;
      function LoadFromStream(Stream: TMemoryStream): byte;
      function SaveToStream(Stream: TMemoryStream): byte;
     end;implementationconstructor TLSImg.Create;
    begin
     Picture := TPicture.Create;
     inherited Create;
    end;destructor TLSImg.Destroy;
    begin
     Picture.Free;
     inherited Destroy;
    end;//根据输入的文件类型调用相应的驱动程序function TLSImg.GetImgType(const FileType: string): Byte;
    begin
     Result := pkNone;
     if FileType <> ’’ then
      if UpperCase(FileType) = ’BMP’ then
       Result := pkBitmap
      else if (UpperCase(FileType) = ’EMF’) or (UpperCase(FileType) = ’WMF’) then
       Result := pkMetafile
      else if UpperCase(FileType) = ’ICO’ then
       Result := pkIcon
      else if (UpperCase(FileType) = ’JPE’) or (UpperCase(FileType) = ’JPG’) or
       (UpperCase(FileType) = ’JPEG’) then
       Result := pkJPEG;
     Graphic := nil;
     case Result of
      pkBitmap: Graphic := TBitmap.Create;
      pkMetafile: Graphic := TMetafile.Create;
      pkIcon: Graphic := TIcon.Create;
      pkJPEG: Graphic := TJPEGImage.Create;
     end;
     if Graphic <> nil then
     begin
      Picture.Graphic := Graphic;
      Graphic.Free;
     end;
    end;//从文件头读图像的种类,然后加载相应的驱动,这里文件长度暂时没有使用
    function TLSImg.LoadFromStream(Stream: TMemoryStream): byte;
    var
     n: Integer;
    begin
     Stream.Seek(0, soFromBeginning);
     //读文件属性
     Stream.Read(Result, 1);
     //读文件长
     Stream.Read(n, 4);
     Graphic := nil;
     //调用相应的驱动
     case Result of
      pkBitmap: Graphic := TBitmap.Create;
      pkMetafile: Graphic := TMetafile.Create;
      pkIcon: Graphic := TIcon.Create;
      pkJPEG: Graphic := TJPEGImage.Create;
     end;
     Picture.Graphic := Graphic;
     if Graphic <> nil then
     begin
      Graphic.Free;
      Picture.Graphic.LoadFromStream(Stream);
     end;
    end;//将图像的属性写入Offset 0 位,长一个字节。文件长写入 Offset 1,长四个字节。
    function TLSImg.SaveToStream(Stream: TMemoryStream): byte;
    var
     n, o: Integer;
    begin
     Result := pkNone;
     //确定图像的属性
     if Picture.Graphic <> nil then
      if Picture.Graphic is TBitmap then
       Result := pkBitmap
      else if Picture.Graphic is TMetafile then
       Result := pkMetafile
      else if Picture.Graphic is TIcon then
       Result := pkIcon
      else if Picture.Graphic is TJPEGImage then
       Result := pkJPEG;
     Stream.Seek(0, soFromBeginning);
     //在 Offset 0位置上写入图像属性,字长1 Byte。
     Stream.Write(Result, 1);
     n := Stream.Position;
     Stream.Write(n, 4);
     if Result <> pkNone then
      Picture.Graphic.SaveToStream(Stream);
     o := Stream.Position;
     Stream.Seek(n, soFromBeginning);
     //在 Offset 1位置上写入图像的长度,字长 4 Byte。
     Stream.Write(o, 4);
     Stream.Seek(0, soFromBeginning);
    end;end.
      

  2.   

    不懂,直接用image来loadfromfile不行么?
    解决问题的办法是Stream.Position := 0;
    然后再用image装载
      

  3.   

    不懂,直接用image来loadfromfile不行么?=> 是不行,非要在 Stream 中装载不可!!!
    解决问题的办法是Stream.Position := 0;=> 此解无效,
    另,我试了一下,果然, Image1.Picture.Graphic 没有实例.
    if Assigned(Image1.Picture.Graphic) then
      Caption := 'YES'
    else
      Caption := 'NO';此时,Caption的值是'NO',可以证明Graphic没有实例.
    TO : Kerac(痛,很痛,但还是深深的爱你,默默的。) 谢谢你给出的代码.我看看能否实现.
      

  4.   

    呵呵,这个问题应该是使用流的一个常被忽视的问题,那就是在往流里写了数据后,流的数据指针是指向最后的,这个时候你应该先把数据指针设置为流的开头:
    Stream.Position:=0
      

  5.   

    晕~~~LoadFromFile中调用了LoadFromStream,而TGraphic中的成员函数LoadFromStream是纯虚函数,当然出错为什么要这么用呢?我们只用TGraphic的派生类,要把虚函数实现了才能用~~~
      

  6.   

    另外TPicture在没加载图像格式前它只是一个空指针~~~你要把它实例化为TBitmap,TJPEGImage...
      

  7.   

    谢谢,成功了.image1.picture.Graphic := TJpegImage.Create();不过,关闭form的时候, image1.picture.Graphic 会自动Free么?如何测试已经被Free了??
      

  8.   

    答案见destructor TPicture.Destroy;
    begin
      FGraphic.Free;
      inherited Destroy;
    end;