关于 TImage 的一个问题

delphi1234567 2004-08-07 05:48:38

问题描述:

在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的实例,导致地址存取失败,请问如何解决之.

(请不要回答说事先加载一张图片).

...全文
128 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
ehom 2004-08-07
  • 打赏
  • 举报
回复
答案见

destructor TPicture.Destroy;
begin
FGraphic.Free;
inherited Destroy;
end;
delphi1234567 2004-08-07
  • 打赏
  • 举报
回复


谢谢,成功了.

image1.picture.Graphic := TJpegImage.Create();

不过,关闭form的时候, image1.picture.Graphic 会自动Free么?

如何测试已经被Free了??
ehom 2004-08-07
  • 打赏
  • 举报
回复
另外TPicture在没加载图像格式前它只是一个空指针~~~

你要把它实例化为TBitmap,TJPEGImage...
ehom 2004-08-07
  • 打赏
  • 举报
回复
晕~~~

LoadFromFile中调用了LoadFromStream,而TGraphic中的成员函数LoadFromStream是纯虚函数,当然出错

为什么要这么用呢?我们只用TGraphic的派生类,要把虚函数实现了才能用~~~
hkbarton 2004-08-07
  • 打赏
  • 举报
回复
呵呵,这个问题应该是使用流的一个常被忽视的问题,那就是在往流里写了数据后,流的数据指针是指向最后的,这个时候你应该先把数据指针设置为流的开头:
Stream.Position:=0
delphi1234567 2004-08-07
  • 打赏
  • 举报
回复
不懂,直接用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(痛,很痛,但还是深深的爱你,默默的。)

谢谢你给出的代码.我看看能否实现.
zzlingaaa 2004-08-07
  • 打赏
  • 举报
回复
不懂,直接用image来loadfromfile不行么?
解决问题的办法是Stream.Position := 0;
然后再用image装载
Kerac 2004-08-07
  • 打赏
  • 举报
回复
[转贴]存取四种图形格式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;

interface

uses
 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.Pas

unit 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;

implementation

constructor 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.

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧