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 和运行时错误,当它是本地时我无法解决。