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

问题描述 投票:0回答:2

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

如何按图显示?

delphi tiff
2个回答
4
投票

VCL 通过 Windows Imaging 组件支持 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
中的代码,不同之处在于只使用了第二帧:)。无论如何,应该很容易模块化,以便能够获取帧数并显示所需的帧数。

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


0
投票

在Delphi 11中,你可以在Graphics单元中使用TWicImage

首先要获取TIFF文件的页数,检查是否可以加载,然后加载页面(FrameIndex范围是0到FrameCount-1):

会是这样的:

procedure loadTiff(imagen:TImage; tiffFilename: String; pagenumber: integer);
var
  wicImg: TWicImage;
begin
  wicImg:= TWicImage.create;
  wicImg.loadFromFile(tiffFilename);
  if wicImg.frameCount > pageNumber then
     begin
     wicImg.frameIndex:= pageNumber-1;
     wicImg.loadFromFile(tiffFilename);
     end;
  imagen.picture.bitmap.assign(wic);
  wicImg.free;
  
end; 

如果您已经知道页数,则可以加载图像而无需检查其是否超出范围

© www.soinside.com 2019 - 2024. All rights reserved.