如何把一个BMP文件读入流,然后又从流中取出显示在IMAGE控件上? ( 积分: 100 )

  • 主题发起人 主题发起人 火龙真人
  • 开始时间 开始时间

火龙真人

Unregistered / Unconfirmed
GUEST, unregistred user!
解析一个文件里面包含有多个BMP文件格式,分别截取至流后,用IMAGE1的LOADFROMSTREAM
报错,应该如何写呢?
 
代码?
使用内存流要注意流的指针位置
 
嘿嘿,请看以下代码,可以存取任意格式的文件

SQL Server 数据库存取文件s
注意:请先连接数据库!然后打开数据库表

}
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, ADODB, Grids, DBGrids, ExtCtrls, ComCtrls,
RzPanel, RzButton, Mask, RzEdit, SkinCaption, WinSkinStore, WinSkinData;

type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
OpenDialog1: TOpenDialog;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
btnView: TButton;
ADOTable1: TADOTable;
Panel1: TPanel;
edtServer: TEdit;
edtUser: TEdit;
edtPwd: TEdit;
edtDB: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Button1: TButton;
GroupBox1: TGroupBox;
Label8: TLabel;
Label9: TLabel;
ADOQuery1: TADOQuery;
Button2: TButton;
Button3: TButton;
StatusBar1: TStatusBar;
RzBitBtn1: TRzBitBtn;
RzBitBtn2: TRzBitBtn;
RzBitBtn3: TRzBitBtn;
RzBitBtn4: TRzBitBtn;
Label5: TLabel;
RzGroupBox1: TRzGroupBox;
edtFileName: TEdit;
btnBrowse: TButton;
btnAdd: TButton;
Label7: TLabel;
Label10: TLabel;
Label11: TLabel;
Label12: TLabel;
Label13: TLabel;
RzEdit1: TRzEdit;
RzEdit2: TRzEdit;
ComboBox1: TComboBox;
RzDateTimeEdit1: TRzDateTimeEdit;
SkinData1: TSkinData;
SkinStore1: TSkinStore;
SkinCaption1: TSkinCaption;
procedure btnBrowseClick(Sender: TObject);
procedure btnAddClick(Sender: TObject);
procedure btnViewClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure ADOConnection1AfterConnect(Sender: TObject);
procedure ADOTable1AfterOpen(DataSet: TDataSet);
procedure RzBitBtn1Click(Sender: TObject);
procedure RzBitBtn4Click(Sender: TObject);
procedure RzBitBtn2Click(Sender: TObject);
procedure RzBitBtn3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
const SQLCSTR = 'Provider=SQLOLEDB.1;' +
'Password=%s;' //密码
+ 'Persist Security Info=True;'
+ 'User ID=%s;' //用户名
+ 'Initial Catalog=%s;' //数据库
+ 'Data Source=%s'; //服务器

implementation
uses ShellAPI;
{$R *.dfm}

procedure TForm1.btnBrowseClick(Sender: TObject);
begin
if OpenDialog1.Execute then
edtFileName.Text := OpenDialog1.FileName;

end;

procedure TForm1.btnAddClick(Sender: TObject);
var
fs: TFileStream;
ext: string;
filesize : integer;
begin
if not FileExists(edtFileName.Text) then
begin
Application.MessageBox(PChar('找不到文件' + edtFileName.Text), '错误', MB_ICONERROR);
Exit;
end;
ext := ExtractFileExt(edtFileName.Text); //取出文件的扩展名
fs := TFileStream.Create(edtFileName.Text, fmOpenRead);
filesize := fs.Size;


if filesize>204857600 then
begin
showmessage('对不起,您的文件为'+inttostr(filesize)+'个字节,您的作业容量一般不要超过10M字节 !!!');
exit;
end
else
begin

ADOTable1.Append;
try
ADOTable1.FieldByName('学号').AsString := rzedit1.Text;
ADOTable1.FieldByName('姓名').AsString := rzedit2.Text;
ADOTable1.FieldByName('上机科目').AsString := combobox1.Text;
ADOTable1.FieldByName('上机时间').AsString := rzdatetimeedit1.Text;
ADOTable1.FieldByName('作业提交时间').AsString := datetimetostr(now);
ADOTable1.FieldByName('作业文件类型').AsString := ext;
ADOTable1.FieldByName('文件大小(字节)').AsString := inttostr(filesize);

fs.Position := 0;
TBlobField(ADOTable1.FieldByName('作业详细内容')).LoadFromStream(fs);
ADOTable1.Post;
finally
fs.Free;
end;
end;
end;

procedure TForm1.btnViewClick(Sender: TObject);
var filename, dir: string;
begin
dir := ExtractFilePath(ParamStr(0)) + 'temp';
if not DirectoryExists(dir) then
CreateDir(dir);
try
fileName := dir + '/temp' + ADOTable1.FieldByName('id').AsString
+ ADOTable1.FieldByName('作业文件类型').AsString;
TBlobField(ADOTable1.FieldByName('作业详细内容')).SaveToFile(fileName);
ShellExecute(handle, 'Open', PChar(fileName), nil, nil, SW_NORMAL);
finally
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
try
ADOConnection1.ConnectionString := Format(SQLCSTR, [edtPwd.Text, edtUser.Text, edtDB.Text, edtServer.Text]);
ADOConnection1.Open;
except
on E: Exception do
Application.MessageBox(PChar('无法连接数据库!请检查数据库服务器是否打开以及数据库名称是否存在!'
+ #10#13 + '系统错误信息:' + E.Message), PChar(Caption), MB_ICONWARNING);
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
try
//如果表不存在则创建一张表Table_work
ADOQuery1.SQL.Text := 'CREATE TABLE [Table_work] ('
+ ' [ID] [smallint] IDENTITY (1, 1) NOT NULL ,'
+ ' [学号] [char] (10) not NULL ,'
+ ' [姓名] [char] (10) not NULL ,'
+ ' [上机科目] [char] (15) not NULL ,'
+ ' [上机时间] [datetime] not NULL ,'
+ ' [作业详细内容] [image] NULL ,'
+ ' [作业文件类型] [char] (10) COLLATE Chinese_PRC_CI_AS NULL,'
+ ' [文件大小(字节)] [char] (10) ,'
+ ' [作业提交时间] [datetime] not NULL,'
// + ' [成绩] [int] (4) NULL'
+ ') ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] ';
ADOQuery1.ExecSQL;
Application.MessageBox('数据表创建成功!', '', MB_ICONINFORMATION);

except
Application.MessageBox('数据表创建失败!请确认数据库中是否已经存在数据表Table_work!', '', MB_ICONWARNING);
end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
//打开这张表
ADOTable1.TableName := 'Table_work';
ADOTable1.Open;
end;

procedure TForm1.ADOConnection1AfterConnect(Sender: TObject);
begin
StatusBar1.Panels.Items[0].Text := 'SQLServer数据库服务器连接成功!'
end;

procedure TForm1.ADOTable1AfterOpen(DataSet: TDataSet);
begin
StatusBar1.Panels.Items[1].Text := '数据表Table_work连接成功!'
end;

procedure TForm1.RzBitBtn1Click(Sender: TObject);
begin
adotable1.First;
end;

procedure TForm1.RzBitBtn4Click(Sender: TObject);
begin
adotable1.Last;
end;

procedure TForm1.RzBitBtn2Click(Sender: TObject);
begin
adotable1.Prior;
end;

procedure TForm1.RzBitBtn3Click(Sender: TObject);
begin
adotable1.Next;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
AnimateWindow(Handle,1500,AW_HOR_NEGATIVE+AW_ACTIVATE+AW_CENTER);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
AnimateWindow(Handle,1200,AW_HOR_NEGATIVE+AW_HIDE+AW_CENTER);
end;

end.
 
我上传分析Tektronix的报告,就是这样搞的,以前需要人工1个星期才能完成的报告,用delphi写的工具,10分钟就搞定了。
你把代码贴出来,比较容易看问题。
我猜想出错的是第一,你是否完整的读取了BMP的信息,你要确定,第二,很有可能流的position你没有设置准确。
 
这么多代码,跟问题相关的没几行,我来简化一下:
var
bmp:tbitmap;
ss:tmemorystream;
begin
bmp:=tbitmap.create;
ss:=tmemorystream.create;
bmp.loadfromfile('X;/xxx/xxx.bmp');
bmp.savetostream(ss);
image1.pictrue.bitmap.loadfromstream(ss);
ss.free;
bmp.free;
end;
 
你要知道文件的格式才行,多个BMP文件打包在一个文件内,需要知道 文件的 大小,移动 stream 的 position 用 readBuff 或者 或者 copyStream 老分开 每个人文件 的 Stream,然后loadStream 就可以啦
 
我已经解读成功. 将文件内BMP读到
一个MEMORYSTREAM里也就是从BM开头读到此BMP完结
也就是不是用方法 bmp.loadfromfile('X;/xxx/xxx.bmp' 得来

HFIEL的指针在BMP包文件, BMP文件开头处
MEMORYSTREAM1:=TMEMORYSTREAM.CREAT;
FILEREAD(HFIEL,MEMORYSTREAM1,4000) (假设第一个BMP结尾是在4000处)
我将其写成单个文件既可用画笔打开,说明读入是正确的,
但直接用IMAGE1显示不知道如何处理.希望高人指教.
 
Image1.Picture.Bitmap.LoadFromStream();
 
楼上正解。
 
楼上不行啊,,,,
 
能写一个将文件用FILEREAD方式读入流后再显示如IMAGE的例子吗
 
uses
Jpeg

打开图片:
procedure TForm1.ToolButton1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
image1.Picture.LoadFromFile(opendialog1.FileName );
end;

导入到数据库:
procedure TForm1.ToolButton2Click(Sender: TObject);
var
MyJPEG: TJPEGImage;
MS: TMemoryStream;
begin
MyJpeg := TJpegImage.Create;
try
MyJpeg.Assign(Image1.Picture.Graphic);
MS := TMeMoryStream.Create;
MyJpeg.SaveToStream(Ms);
Ms.Position := 0;
ADOQuery1.Edit;
TBlobField(ADOQuery1.FieldByName('Image')).LoadFromStream(MS);
ADOQuery1.Post;
finally
MyJpeg.Free;
Ms.Free;
end;
//image1.Picture.Graphic:=nil;
end;

从数据库中提取显示到image:
procedure TForm1.ToolButton3Click(Sender: TObject);
var
str:Tmemorystream;
begin
//从数据库中取出流转换成图形
if ADOQuery1.FieldByName('Image').value='' then
image2.Picture.Graphic:=nil
else
begin
try
str:=Tmemorystream.Create;
Tblobfield(ADOQuery1.FieldByName('Image')).SaveToStream(str);
str.Position:=0;
image2.Picture.Graphic:=nil;
image2.Picture.Graphic:=TJpegImage.Create; //这里是jpeg的,可以改成bmp
image2.Picture.Graphic.LoadFromStream(str);
except
Image2.Picture.Bitmap.LoadFromStream(str);
end;
str.Free;
end;
end;
 
先把存储图像的内存流的指针移到开头。
a:Tmemorystream;
a.position:=0;
 
我是这样读的啊
procedure TForm1.Button1Click(Sender: TObject);
VAR A1,A2:CHAR;
I,M:INTEGER;
sr: TSearchRec;
FL:BOOLEAN;
DS:STRING;
WS2:TSTREAM;

begin
IF OpenDialog1.Execute THEN
BEGIN
IF HFILE<>null then FileClose(hFile);
HFILE:=FILEOPEN(OpenDialog1.FileName,fmOpenReadWrite);
form1.Caption:=OpenDialog1.FileName;
FileSeek(hFile, 0,0 );
if FindFirst(OpenDialog1.FileName, faAnyFile, sr) = 0 then
M:=sr.Size;
ws2:=Tmemorystream.Create;
FILEREAD(HFILE,WS2,m);
ws2.Position:=0;
image1.Picture.Bitmap.LoadFromStream(ws2);
end;
end;
我想用FILEREAD的方式读到流里,,可执行后无效果
 
后退
顶部