Delphi: Timage组件如何逐张显示
Delphi: How to display an image by image in Timage component
我有一个包含 4 张图像的图像文件 (.tiff)。
我无法在 TImage 中查看或显示这 4 张图像。
TImage 组件仅显示第一帧。
如何逐张显示?
VCL 通过 Windows Imaging Component 支持 tif 图像,该组件由 TWICImage
. However, although trivial, VCL has left out frame support of WIC (which is the term MS documentation 封装,用于引用图像中的多个图像。
以下引用来自 XE2 的 'Vcl.Graphics.pas'。
procedure TWICImage.LoadFromStream(Stream: TStream);
var
..
BitmapDecoder: IWICBitmapDecoder;
...
begin
...
WicCheck(BitmapDecoder.GetFrame(0, LBitmapFrame));
...
end;
我只引用了一行,立即显示了问题。 'decoder' 能够提供总帧数信息并检索其中的任何一个。但是,按照编码,只有第一个被使用过。
还是可以用TWICImage
自己取帧,然后赋给一个TImage
的图片。下面是我这样做的尝试,它基本上复制了 TWICImage.LoadFromStream
中的代码,不同之处在于只使用了第二帧 :)。无论如何,模块化应该很容易,以便能够得到 frame count 并显示所需的
type
TForm1 = class(TForm)
Image1: TImage;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
WICImage: TWICImage;
end;
var
Form1: TForm1;
implementation
uses
activex, wincodec, consts;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
procedure Check(Result: HRESULT);
begin
if Failed(Result) then
raise EInvalidGraphic.Create(SInvalidImage);
end;
var
fs: TFileStream;
Adapter: IStream;
Decoder: IWICBitmapDecoder;
Frame: IWICBitmapFrameDecode;
WICBmp: IWICBitmap;
Width, Height: DWORD;
begin
fs := TFileStream.Create('....tif', fmShareDenyWrite);
try
Adapter := TStreamAdapter.Create(fs);
Check(WICImage.ImagingFactory.CreateDecoderFromStream(Adapter,
GUID_ContainerFormatTiff, WICDecodeMetadataCacheOnDemand, Decoder));
Check(Decoder.GetFrame(1, Frame));
Check(WICImage.ImagingFactory.CreateBitmapFromSource(Frame,
WICBitmapCacheOnLoad, WICBmp));
Check(WICBmp.GetSize(Width, Height));
Image1.Width := Width;
Image1.Height := Height;
WICImage.Handle := WICBmp;
Image1.Picture.Bitmap.Assign(WICImage);
finally
fs.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
WICImage := TWICImage.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
WICImage.Free;
end;
请注意,我不喜欢将 WIC 图像作为表单的字段而不是局部变量。但是我在程序关闭时不断收到 AV 和运行时错误,当它是本地时我无法解决。
我有一个包含 4 张图像的图像文件 (.tiff)。 我无法在 TImage 中查看或显示这 4 张图像。 TImage 组件仅显示第一帧。
如何逐张显示?
VCL 通过 Windows Imaging Component 支持 tif 图像,该组件由 TWICImage
. However, although trivial, VCL has left out frame support of WIC (which is the term MS documentation 封装,用于引用图像中的多个图像。
以下引用来自 XE2 的 'Vcl.Graphics.pas'。
procedure TWICImage.LoadFromStream(Stream: TStream);
var
..
BitmapDecoder: IWICBitmapDecoder;
...
begin
...
WicCheck(BitmapDecoder.GetFrame(0, LBitmapFrame));
...
end;
我只引用了一行,立即显示了问题。 'decoder' 能够提供总帧数信息并检索其中的任何一个。但是,按照编码,只有第一个被使用过。
还是可以用TWICImage
自己取帧,然后赋给一个TImage
的图片。下面是我这样做的尝试,它基本上复制了 TWICImage.LoadFromStream
中的代码,不同之处在于只使用了第二帧 :)。无论如何,模块化应该很容易,以便能够得到 frame count 并显示所需的
type
TForm1 = class(TForm)
Image1: TImage;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
WICImage: TWICImage;
end;
var
Form1: TForm1;
implementation
uses
activex, wincodec, consts;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
procedure Check(Result: HRESULT);
begin
if Failed(Result) then
raise EInvalidGraphic.Create(SInvalidImage);
end;
var
fs: TFileStream;
Adapter: IStream;
Decoder: IWICBitmapDecoder;
Frame: IWICBitmapFrameDecode;
WICBmp: IWICBitmap;
Width, Height: DWORD;
begin
fs := TFileStream.Create('....tif', fmShareDenyWrite);
try
Adapter := TStreamAdapter.Create(fs);
Check(WICImage.ImagingFactory.CreateDecoderFromStream(Adapter,
GUID_ContainerFormatTiff, WICDecodeMetadataCacheOnDemand, Decoder));
Check(Decoder.GetFrame(1, Frame));
Check(WICImage.ImagingFactory.CreateBitmapFromSource(Frame,
WICBitmapCacheOnLoad, WICBmp));
Check(WICBmp.GetSize(Width, Height));
Image1.Width := Width;
Image1.Height := Height;
WICImage.Handle := WICBmp;
Image1.Picture.Bitmap.Assign(WICImage);
finally
fs.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
WICImage := TWICImage.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
WICImage.Free;
end;
请注意,我不喜欢将 WIC 图像作为表单的字段而不是局部变量。但是我在程序关闭时不断收到 AV 和运行时错误,当它是本地时我无法解决。