目录
序言
使用TImageCollection和TVirtualImageList组件支持高分辨率图像
一、总览
二、使用图像收集组件TImageCollection
2.1 图像收集组件编辑器
2.2 将现有 TImageList 载入 TImageCollection
三、使用Virtual ImageList 组件
3.1 Virtual ImageList Component 编辑器
四、多分辨率下使用图像组件 TVirtualImage
五、最佳实践
5.1 多种尺寸(Multiple sizes)
5.2 在应用程序中支持高 DPI 并转换旧版 TImageLists
5.3 在 TCanvas 上绘图时平滑缩放
delphi开发者都知道,显示图片都会使用TImage,非常方便,支持很多种图片格式,但是技术发展到今天,高分辨率显示器(4K 3840x2160)已经逐步在普及,那么TImage就显得力不从心了,所谓力不从心并不是说不能显示,TImage无论是在2K分辨率还是4K分辨率显示器上,都能正常的按照实际大小显示图像,但是,如果我们在4K分辨率上显示的图像,感觉比例调整的可以,但是到了2K(1920x1080)上图像就感觉放大了一倍。如下图:
注意看,在4K分辨率下开发的程序(左图)到了2K分辨率下运行,TImage显示的图片明显变大2倍。这就是说TImage并不支持多分辨率下自动缩放并显示一致的功能。那么哪个控件可以实现呢,就是上图种的TVirtualImage控件,这个控件可以完全实现在不同分辨率下自动缩放,从而实现一致的的UI效果。
大多数delphi开发者可能还没有使用TVirtualImage控件,本片详细介绍高清分辨率下Delphi图片显示相关控件。Delphi 11开始支持高分辨率显示器,包括开发环境IDE。
通过结合使用 TImageCollection 组件和 TVirtualImageList 组件,RAD Studio 可以在 Windows VCL 应用程序中包含缩放、高 DPI 和多分辨率图像。
请注意
如果您在跨平台应用程序中使用 FireMonkey,请参阅 TImageList 组件和将 TImageLists 用作中央图像存储库的 FireMonkey 指南。
这些配对组件将图像集合(每个逻辑图像可以有多种分辨率)的概念与用于控件的单一特定尺寸的图像列表区分开来。简而言之,将多个分辨率的图像加载到一个图像集合中。图像列表包含一组来自图像集的图像,并以特定尺寸(如 16x16)显示。图像可平滑调整大小和缩放比例,图像列表的实际显示分辨率可根据 DPI 变化。它与传统的图像列表完全兼容,可以直接替代传统的图像列表,包括提供 HIMAGELIST 句柄,VCL 控件和任何使用 Windows API 图像列表调用的代码都可以使用它。
图像支持 alpha 通道,并可将 PNG 载入图像集。您还可以加载旧式的彩色抠像透明位图。
通过 TImageCollection,可以使用原生 TWICImage 类存储、缩放和绘制本地格式的图像。
集合中的每张图片都可以有多个不同尺寸的版本。该组件会选择最佳尺寸进行缩放,或者在可用尺寸等于所需尺寸时使用图像。它还可以创建带 alpha 通道的 32 位 TBitmap 缩放版本,该版本可直接添加到 TCustomImageList 中。
TImageCollection 继承自 TCustomImageCollection 类(Vcl.BaseImageCollection 单元),该类定义了集合的基本方法。
要打开图像集合编辑器,请将 TImageCollection 放置在表单或数据模块上,然后双击表单中的组件或右键单击该组件并从上下文菜单中选择 "Show collection editor… "选项。也可以双击对象检查器中的 TImageCollection.Images 属性。当然也可以通过右键菜单"Load from existing TIamgeLists"从TImageList控件中导入。
在 "图像集合编辑器 "窗口中,您可以将图像添加到组件中,并将它们分门别类。
单击 "添加 "显示 "打开 "对话框,并浏览到存储图片的文件夹。您可以一次添加一张图片,也可以从文件夹中选择多张图片同时添加。图像收藏编辑器按字母顺序显示图像。
添加图像时,您可能需要添加同一图像的多种尺寸。例如,你可能会有一个像素调整后的 16x16 版本的图片,然后还有一个更大的图片,需要根据其他尺寸进行绘制和缩放。要做到这一点,可以给单个图像的多个版本设置相同的文件名,加上一个分隔符(如连字符),然后再加上一个表示像素大小的数字:例如,foo-16.png 和 foo-64.png。然后选中 "检查文件名中的大小 "复选框,并从下拉选项中将图像大小分隔符更改为图像用于分隔通用名称和图像大小的字符(在上一示例中为连字符"-")。这样就能自动识别出文件名相似但像素大小不同的同一图像的多个分辨率,并将它们作为单一图像的多个分辨率添加到收藏中。
图像尺寸分隔符(Image size separator)设置可控制如何解析以分隔常用名称和图像尺寸,并包含常用图标和图像尺寸文件名约定的选项。
注意:
"图像收集编辑器 "要求在文件名的编号中使用分隔符,以便识别同一图像的不同尺寸。
分类目前仅用于组织。(在 VCL 控件中,图像仍然只能通过索引来引用)。
要按类别组织图像,请选择图像并单击 "Set Category"。
使用顶部的 "Delete"按钮从集合中删除特定图像,使用 "Clear"按钮删除集合中的所有图像。
请注意: 从集合中删除图像时,VirtualImageList 会按索引查找图像。
将图片添加到图片集中后,您可以选择任何可用的图片并执行以下操作:
请注意
重命名和替换图像时,请按照以下步骤操作:
- 更改index[name]并应用更改(VirtualImageList 使用集合中的名称[索引]按索引[名称]更新图像)。
- 更改name[index]并应用更改(VirtualImageList 使用集合中的索引[名称]按名称[索引]更新图像)。
提示:您还可以单击并拖动图像到不同的位置来修改其索引值。
为了帮助将旧式图像列表转换到新系统,您可以将旧 TImageList 中的图像加载到 TImageCollection 中。当您在不同的 TImageList 中拥有同一图像的多个尺寸时,您可以同时加载这两种图像;图像会被合并,从而使图像集合包含同一图像的多个分辨率。
要将 TImageList 中的图片加载到 TImageCollection 中,需要将这两个组件置于同一窗体中。
请按照以下步骤将表单中现有 TImageList 中的图像加载到 TImageCollection 中:
请注意
从传统 TImageList 导入 TImageCollection 或 TVirtualImageList 后,如果发现图像无法正确呈现,例如出现白边或其他伪影,请检查 TImageList 的 ColorDepth 属性。有时,FMX TImageList 的 ColorDepth 属性会设置为 cd32Bit,而它所保存的图像实际上是 24 位或 16 位的。请确保 ImageList 的颜色深度设置为 cd32Bit,如果它保存的位图是真正的 32 位,包括 Alpha 通道。
TVirtualImageList 允许您生成一个图像列表,并同时对所有图像应用更改。
TVirtualImageList 使用 TCustomImageCollection (TImageCollection) 来生成内部图像的动态列表。
通过 TVirtualImageList,您可以设置自定义的宽度和高度属性,而且该组件会自动缩放所有图片。当 DPI 发生变化时,它会对图像进行缩放,以便在高 DPI 显示器上正常显示。
注意:
TVirtualImageList 在缩放时会自动继承其所有者(TCustomForm 或 TCustomFrame)的 DPI。
由于 TVirtualImageList 继承自 TCustomImageList,因此 VCL 控件无需修改即可使用 TVirtualImageList。
注意:
要在 TVirtualImageList 中添加、插入和/或替换位图,必须使用从 ImageCollection 中添加、插入和/或替换项的方法。
要使用Virtual ImageList 组件和组件编辑器,首先需要在对象属性中设置 ImageCollection 属性。
要打开VirtualImageList虚拟图像列表编辑器,可双击表单中的组件,或右击该组件并从上下文菜单中选择 "Show image list editor… "选项。
如果将AutoFill(自动填充)属性设置为 True,虚拟图像列表将自动填充集合中的所有图像。否则,您可以使用图像列表编辑器将图像从集合中手动添加到列表中。
VirtualImageList虚拟图像列表编辑器窗口允许您将图像添加到组件中,包括图像的禁用版本,并将它们分门别类。
单击Add打开相关的图像集,并选择要包含在虚拟图像列表中的图像。您可以从图像集中选择特定图像,也可以从图像集中或现有类别中选择所有图像。
此外,虚拟图像列表编辑器窗口还有以下选项:
注意
只能用图像收藏组件中的图像替换虚拟图像列表组件中的图像,且该图像不在之前添加的图像列表中。
将图像添加到虚拟图像列表组件后,可以执行以下操作:
TVirtualImage 组件支持类似 TImage 组件的多种分辨率。图像源来自图像集合(ImageCollection),根据屏幕 DPI 的不同,可以有多种分辨率。该组件会根据显示的显示器使用适当的版本。
VirtualImage 组件的一些配置设置和关键属性如下: ImageCollection、ImageHeight、ImageIndex、ImageName 和 ImageWidth。
当您使用位图缩放逻辑来平滑绘制任何 VCL TGraphic 时(例如 StretchDraw),有一个 TScaledGraphicDrawer 类可以为不同的 TGraphic 类启用 HQ 缩放绘图,调用方式如下:
MyBitmap.EnableScaler(TD2DGraphicScaler);
Image1.Picture.Graphic.EnableScaler(TWICGraphicScaler);
不同的解决方案可提供更好或更差的渲染效果以及更慢或更快的性能组合。您可以编写自定义的 TScaledGraphicDrawer 派生类,定义额外的缩放算法。
TVirtualImageList 组件会根据其所在表单的 DPI 缩放。这样,该窗体上与图像列表一起绘制的控件就能始终以正确的缩放分辨率绘制。不过,这意味着两件事:
因此,如果窗体上的控件使用图像列表,则应始终在该窗体上放置一个或多个TVirtualImageLists,并让控件仅引用这些本地的同一窗体图像列表。这些 TVirtualImageLists 可以全部引用同一个 TImageCollection。
虚拟图像集合是一个非常有用的控件,它将图像集合(TImageCollection)的概念与特定尺寸(尽管可随 DPI 缩放)的图像集(TVirtualImageList)区分开来。图像集合不受 DPI 变化的影响,因为它只是一个容器。TVirtualImageList 虚拟图像列表可以引用另一个表单或数据模块上TImageCollection图像集合中的图像。好的设计是在应用程序的主表单或共享数据模块上为相关图像(如所有工具栏和菜单图像)建立一个图像集合。其他表单将拥有各自的虚拟图像列表,这些图像列表使用中央图像集。
如果您需要同一图像的多种尺寸,例如具有 SmallImages 和 LargeImages 属性的 TListView,请使用两个 TVirtualImageLists,就像使用传统的 TImageLists 一样。两个虚拟图像列表都会引用同一个图像集合。
将 VCL 应用程序从使用 TImageLists 转换为 TVirtualImageLists 是很常见的,这样可以提升视觉质量,并有助于支持高 DPI。
TVirtualImageList 是 TCustomImageList 的后代,因此在代码级别上可以直接替换,还提供了一个 HIMAGELIST Handle 属性,用于直接调用 Windows API 方法。
建议采用两种方法将应用程序转换为使用新的高 DPI 图像列表。
这将使您的图像集包含旧图像。虽然使用旧图片不会像使用新设计的图片那样提高图片质量或透明度,但这确实可以让图片根据每个表单的 DPI 进行缩放。在每个表单上创建新的 TVirtualImageList 组件,并从集合中添加图片:它们将保持相同的相对顺序,因此,除非集合中已有图片,否则索引也是相同的。然后,更改组件以使用新的 TVirtualImageLists。
TCanvas.StretchDraw 允许将 TGraphic 绘制到任意矩形上。虽然 TGraphic 子类的实现决定了如何做到这一点,但在实践中,VCL 绘图(如 TBitmap)通常通过 GDI 使用近邻重采样,通常无法获得理想的缩放或拉伸图像质量。
您可以使用 TImageCollection 来保存图像(内部存储为 WIC 并使用 WIC 绘制),并将其绘制为任意矩形。这样做将使用高质量的重采样。
显示图片请放弃TImage,请使用TImageCollection、TVirtualImageList、TVirtualImage
你将跟上4K的步骤!