Windows 映像组件的工作原理

发现和仲裁

在解码图像之前,必须找到可以解码该图像格式的相应编解码器。 在大多数系统中,由于支持的映像格式是硬编码的,因此不需要发现过程。 由于 Windows 映像组件 (WIC) 平台是可扩展的,因此必须能够识别图像的格式并将其与相应的编解码器匹配。

为了支持运行时发现,每个图像格式必须具有一个标识模式,该模式可用于标识该格式的相应解码器。 (强烈建议对新的文件格式使用 GUID 进行标识模式,因为它保证是唯一的。) 标识模式必须嵌入到符合该图像格式的每个图像文件中。 每个解码器都有一个注册表项,指定可以解码的图像格式的标识模式或模式。 当应用程序需要打开映像时,它会从 WIC 请求解码器。 WIC 在注册表中查找可用的解码器,并检查每个注册表项中是否存在与映像文件中嵌入的模式匹配的标识模式。 有关解码器注册表项的详细信息,请参阅 特定于编码器的注册表项

当 WIC 找到与图像中的标识模式匹配的单个解码器时,它会创建解码器的实例,并将图像文件传递给该解码器。 如果 WIC 找到多个匹配项,它会在每个匹配解码器上调用一个名为 QueryCapability 的方法,以在它们之间进行仲裁,并找到最佳匹配项。 有关详细信息,请参阅实现 IWICBitmapDecoder 中的 QueryCapabilities 部分。

解码

选择并实例化相应的解码器后,应用程序会直接与解码器对话。 解码器具有多个责任,它通过各种接口实现。 可以将这些服务分类为:

  • 容器级服务
  • 帧级服务
  • 元数据枚举服务
  • 本机解码器转换
  • 进度通知和取消支持
  • 原始处理服务

容器级服务包括检索顶级缩略图 ((如果受支持的) 、预览、颜色上下文、调色板 ((如果适用) )和容器格式,以及提供对容器中各个图像帧的访问。 (某些容器仅包含单个帧,而其他容器(如标记图像文件格式 (TIFF) )可以包含多个帧。) 此服务集还包括提供有关解码器本身的信息及其有关特定图像文件的功能。

单个帧具有自己的缩略图,并且也可能有自己的颜色上下文、调色板和其他属性,这些属性在帧级别公开。 不过,在帧级别执行的最重要操作是该帧的图像位的实际解码。

WIC 为最常见的元数据格式提供元数据读取器, (IFD、EXIF、IPTC、XMP、APP0、APP1 和其他格式) ,还支持第三方元数据格式的扩展性。 这样就释放了分析元数据的责任的编解码器。 但是,编解码器负责枚举元数据块并请求每个块的元数据读取器。 WIC 根据与元数据处理程序的注册表项中的模式匹配的块标头中的模式,对元数据处理程序的元数据处理程序执行发现的方式相同。 有关详细信息,请参阅 特定于编码器的注册表项

解码器不需要本机支持转换操作,但这样做可实现显著的性能优化,从而提供更好的最终用户体验。 例如,应用程序可以创建各种转换的管道, (缩放、裁剪、旋转和像素格式转换) 在呈现图像之前对图像执行。 有关转换管道的详细信息,请参阅 IWICBitmapSource。 创建转换管道后,应用程序请求管道中的最终转换,以生成从将所有转换应用到图像源生成的位图。 此时,如果解码器本身能够执行转换操作,WIC 会询问它可以执行的所请求转换中的哪一个。 解码器无法执行的任何请求转换都将由解码图像上的 WIC 执行,然后再将其返回到调用方。 此优化的转换管道比按顺序在内存中执行每个转换提供更好的性能,尤其是在解码过程中可以完成部分或全部转换时。

进度通知和取消支持使应用程序能够请求长时间操作的进度通知,并使应用程序有机会取消花费太长时间的操作。 这一点很重要,因为如果用户无法取消操作,他或她可能会觉得该过程已挂起,并尝试通过关闭应用程序来取消它。

有关 实现 WIC 的解码器部分详细介绍了这些接口。

原始处理服务包括调整相机设置,例如曝光、对比度和锐化,或在处理原始位之前更改颜色空间。

编码

与解码器一样,编码器有责任通过接口实现。 编码器提供的服务是解码器提供的服务的补充,只是它们写出图像数据而不是读取图像数据。 编码器还提供以下类别中的服务:

  • 容器级服务
  • 帧级服务
  • 元数据枚举和更新服务
  • 进度通知和取消支持

编码器的容器级服务包括设置顶级缩略图 ((如果受支持的) 、预览和调色板 ((如果适用)) ,并循环访问各个图像帧,以便将其序列化到容器中。

编码器的帧级服务镜像解码器的帧级服务,只不过它们会写出图像数据、缩略图以及任何关联的调色板或其他组件,而不是读取它们。

此外,编码器的元数据枚举服务包括循环访问要写入的元数据块,并调用相应的元数据编写器将元数据序列化为磁盘。

有关 实现 WIC 的编码器的部分详细介绍了这些接口。

编解码器的生存期

WIC 编解码器被实例化以处理单个映像,并且通常具有较短的生存期。 它在加载映像时创建,并在关闭映像时释放。 应用程序可能会同时使用大量编解码器与重叠的生存期, (考虑滚动浏览包含数百个图像的目录) ,并且多个应用程序可能同时执行此操作。

尽管某些编解码器的生存期限定为生存期,但 WIC 编解码器的情况并非如此。 Windows Vista 照片库、Windows 资源管理器和照片查看器以及其他许多应用程序基于 WIC 构建,并将使用编解码器显示图像和缩略图。 如果编解码器的生存期限定为进程的生存期,则每次在 Windows Vista 资源管理器中显示图像或缩略图时,该编解码器实例化为解码该图像将保留在内存中,直到下次用户重启其计算机为止。 如果从未卸载编解码器,则其资源实际上“泄漏”,因为它们不能由系统中的任何其他组件使用。

如何启用编解码器

  1. 实现容器级解码器类和帧级解码器类,该类公开用于解码图像和循环访问元数据块所需的 WIC 接口。 这样,所有基于 WIC 的应用程序就可以像与标准图像格式交互的编解码器一样与编解码器进行交互。
  2. 实现容器级编码器类和帧级编码器类,该类公开用于对图像进行编码并将元数据块序列化为图像文件所需的 WIC 接口。
  3. 如果容器格式不是基于 TIFF 或 JPEG 容器,则可能需要为 EXIF、XMP) 的常见元数据 (格式编写元数据处理程序。 但是,如果使用基于 TIFF 或基于 JPEG 的容器格式,则不需要这样做,因为可以委托给系统提供的元数据处理程序。
  4. 嵌入唯一标识模式 (我们建议在所有图像文件中) GUID。 这样,图像格式就可以在发现过程中与编解码器匹配。 如果要为现有图像格式编写 WIC 包装器,则必须找到编码器始终写入其图像文件(该图像格式唯一)的位模式,并将其用作标识模式。)
  5. 在安装时注册编解码器。 这使编解码器能够在运行时发现,方法是将注册表中的标识模式与嵌入在映像文件中的模式相匹配。
  6. 从 Windows 7 开始,WIC 要求编解码器采用 COM 单元类型“两者”。 这意味着必须在多线程方案中执行适当的锁定来处理跨单元调用方和调用方。 有关详细信息,请参阅有关多线程单元支持的下一部分。
  7. 支持 64 位平台:对于 Windows 7,WIC 要求将第三方 WIC 编解码器作为 32 位和 64 位本机二进制文件传送。 此外,32 位窗体必须在 64 位系统上安装和运行,第三方 Windows 7 编解码器安装程序必须在 64 位系统上同时安装 32 位和 64 位二进制文件。

WIC 中的多线程单元支持

多线程单元中的对象 (MTA) 可由 MTA 中的任意数目线程同时调用。 这允许在多核系统和某些服务器方案中获得更好的性能。 此外,MTA 中的 WIC 编解码器可以调用 MTA 中的其他对象,而无需将与在不同 STA 单元中的线程之间调用关联的封送成本。 在 Windows 7 中,所有现成 WIC 编解码器都已更新,以支持 MTA,包括 JPEG、TIFF、PNG、GIF、ICO 和 BMP。 强烈建议编写第三方编解码器以支持 MTA。 不支持 MTA 的第三方编解码器由于封送而导致多线程应用程序中的性能成本显著。 启用 MTA 支持需要在第三方编解码器中实现适当的同步。 这些同步技术的确切实现超出了本文的范围。 有关同步 COM 对象的详细信息,请参阅 了解和使用 COM 线程模型

概念性

简介 (如何编写已启用 WIC 的编解码器)

实现已启用 WIC 的解码器

如何编写已启用 WIC 的编解码器

Windows 映像组件概述

WIC 元数据概述