Delphi:如何在Timage组件中按图像显示图像

时间:2016-11-09 17:20:00

标签: delphi tiff

我有一个有4张图像的图像文件(.tiff)。 我无法在TImage中查看或显示这4个图像。 TImage组件仅显示第一帧。

如何按图像显示图像?

1 个答案:

答案 0 :(得分:4)

VCL通过Windows映像组件支持tif映像,该映像由TWICImage封装。但是,虽然微不足道,但VCL已经忽略了WIC的 frame 支持(这是MS documentation用来指代图像中多个图像的术语)。

以下引用来自XE2的'Vcl.Graphics.pas'。

procedure TWICImage.LoadFromStream(Stream: TStream);
var
  ..
  BitmapDecoder: IWICBitmapDecoder;
  ...
begin
  ...
  WicCheck(BitmapDecoder.GetFrame(0, LBitmapFrame));
  ...
end;

我只引用一行,立即显示问题。 “解码器”能够提供总帧数信息并检索它们中的任何一个。但是,按照编码,只使用第一个。

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