我需要从一个XML文件中加载一张图片,但是在XML文件中没有关于这个图片是JPG/GIF/BMP的信息。加载完图片后,我需要将其转换为位图。
有人知道如何在不知道实际文件格式的情况下将图片转换为位图吗?我正在使用Delphi 2007/2009。
谢谢。
我需要从一个XML文件中加载一张图片,但是在XML文件中没有关于这个图片是JPG/GIF/BMP的信息。加载完图片后,我需要将其转换为位图。
有人知道如何在不知道实际文件格式的情况下将图片转换为位图吗?我正在使用Delphi 2007/2009。
谢谢。
Delphi 2009内置了对JPEG、BMP、GIF和PNG的支持。
如果你使用的是早期版本的Delphi,可能需要寻找第三方实现的PNG和GIF,但在Delphi 2009中,你只需要将Jpeg
、pngimage
和GIFImg
单元添加到你的uses子句中即可。
如果文件有扩展名,你可以使用以下代码,如其他人所指出的,TPicture.LoadFromFile会查看由继承类注册的扩展来确定要加载哪个图像。
uses
Graphics, Jpeg, pngimage, GIFImg;
procedure TForm1.Button1Click(Sender: TObject);
var
Picture: TPicture;
Bitmap: TBitmap;
begin
Picture := TPicture.Create;
try
Picture.LoadFromFile('C:\imagedata.dat');
Bitmap := TBitmap.Create;
try
Bitmap.Width := Picture.Width;
Bitmap.Height := Picture.Height;
Bitmap.Canvas.Draw(0, 0, Picture.Graphic);
Bitmap.SaveToFile('C:\test.bmp');
finally
Bitmap.Free;
end;
finally
Picture.Free;
end;
end;
如果文件扩展名未知,一种方法是查看前几个字节以确定图像类型。
procedure DetectImage(const InputFileName: string; BM: TBitmap);
var
FS: TFileStream;
FirstBytes: AnsiString;
Graphic: TGraphic;
begin
Graphic := nil;
FS := TFileStream.Create(InputFileName, fmOpenRead);
try
SetLength(FirstBytes, 8);
FS.Read(FirstBytes[1], 8);
if Copy(FirstBytes, 1, 2) = 'BM' then
begin
Graphic := TBitmap.Create;
end else
if FirstBytes = #137'PNG'#13#10#26#10 then
begin
Graphic := TPngImage.Create;
end else
if Copy(FirstBytes, 1, 3) = 'GIF' then
begin
Graphic := TGIFImage.Create;
end else
if Copy(FirstBytes, 1, 2) = #$FF#$D8 then
begin
Graphic := TJPEGImage.Create;
end;
if Assigned(Graphic) then
begin
try
FS.Seek(0, soFromBeginning);
Graphic.LoadFromStream(FS);
BM.Assign(Graphic);
except
end;
Graphic.Free;
end;
finally
FS.Free;
end;
end;
我发现了一个更简单的方法!它会自动加载JPG/GIF/BMP等文件,甚至不用知道/检查文件格式,并相应地进行转换。 对我来说完全奏效。
在这里分享一下 :)
Uses
Classes, ExtCtrls, Graphics, axCtrls;
Procedure TForm1.Button1Click(Sender: TObject);
Var
OleGraphic : TOleGraphic;
fs : TFileStream;
Source : TImage;
BMP : TBitmap;
Begin
Try
OleGraphic := TOleGraphic.Create; {The magic class!}
fs := TFileStream.Create('c:\testjpg.dat', fmOpenRead Or fmSharedenyNone);
OleGraphic.LoadFromStream(fs);
Source := Timage.Create(Nil);
Source.Picture.Assign(OleGraphic);
BMP := TBitmap.Create; {Converting to Bitmap}
bmp.Width := Source.Picture.Width;
bmp.Height := source.Picture.Height;
bmp.Canvas.Draw(0, 0, source.Picture.Graphic);
image1.Picture.Bitmap := bmp; {Show the bitmap on form}
Finally
fs.Free;
OleGraphic.Free;
Source.Free;
bmp.Free;
End;
End;
TOleGraphic
构造函数失败,则会在随机指针上尝试 fs.Free
、OleGraphic.Free
、Source.Free
和 bmp.Free
,这非常糟糕!同样,如果 TFileStream
构造函数失败,则会在随机指针上尝试 fs.Free
、Source.Free
和 bmp.Free
。等等,直到 bmp.Width := ...
。这一行是第一行正确的代码。始终使用习语 X := TX.Create; try {use X} finally X.Free; end
,或者至少在 try
之前将指针初始化为 nil
。在此问题得到解决之前,我会扣除1分。 - Andreas RejbrandTPicture.LoadFromFile
,因为该方法使用文件扩展名来确定需要加载哪个注册图形格式。这就是为什么没有匹配的TPicture.LoadFromStream
方法的原因。function TryLoadPicture(const AFileName: string; APicture: TPicture): boolean;
const
GraphicClasses: array[0..3] of TGraphicClass = (
TBitmap, TJPEGImage, TGIFImage, TPngImage);
var
FileStr, MemStr: TStream;
ClassIndex: integer;
Graphic: TGraphic;
begin
Assert(APicture <> nil);
FileStr := TFileStream.Create('D:\Temp\img.dat', fmOpenRead);
try
MemStr := TMemoryStream.Create;
try
MemStr.CopyFrom(FileStr, FileStr.Size);
// try various
for ClassIndex := Low(GraphicClasses) to High(GraphicClasses) do begin
Graphic := GraphicClasses[ClassIndex].Create;
try
try
MemStr.Seek(0, soFromBeginning);
Graphic.LoadFromStream(MemStr);
APicture.Assign(Graphic);
Result := TRUE;
exit;
except
end;
finally
Graphic.Free;
end;
end;
finally
MemStr.Free;
end;
finally
FileStr.Free;
end;
Result := FALSE;
end;
编辑:
GraphicEx库有一个示例转换,使用以下内容:
GraphicClass := FileFormatList.GraphicFromContent(...);
确定图形格式。这似乎与您提到的VB6方式非常相似。也许您可以使用此库来实现您的目的。
我没有Delphi 2007或2009版本,无法确定该方法是否适用于这两个版本。然而,在XE2中,Vcl.Graphics
中有另一个类TWICImage
,它处理由Microsoft Imaging Component支持的图像格式,包括BMP,GIF,ICO,JPEG,PNG,TIF和Windows Media Photo 。它能够从数据流中检测图像类型。假设你在窗体上有一个名为的TImage
:
procedure LoadImageFromStream(Stream: TStream; Image: TImage);
var
wic: TWICImage;
begin
Stream.Position := 0;
wic := TWICImage.Create;
try
wic.LoadFromStream(Stream);
Image.Picture.Assign(wic);
finally
wic.Free;
end;
end;
procedure RenderImage(const Filename: string);
var
fs: TFileStream;
begin
fs := TFileStream.Create(Filename, fmOpenRead);
try
LoadImageFromStream(fs, Image1);
finally
fs.Free;
end;
end;
无需将 PNGImage
, GIFImg
, 或 JPEG
添加到你的 uses
语句中,就可以正常工作。
其他答案展示了如何将 TImage
转换为 BMP,因此我在这里不包括它。 我只是展示了另一种方法,可以在不预先知道图像类型或文件扩展名的情况下,将各种图形类型加载到 TImage
中...
TPicture::Assign
会将图像数据复制到Picture中吗?(我担心在wic.Free
之后会出现悬空指针) - M.M