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 资源管理器中显示图像或缩略图时,为解码该图像而实例化的编解码器将保留在内存中,直到用户下次重启其计算机为止。 如果编解码器从未卸载,则其资源实际上已“泄漏”,因为它们不能由系统中的任何其他组件使用。
如何启用 WIC 编解码器
- 实现容器级解码器类和帧级解码器类,该类公开解码图像和循环访问元数据块所需的 WIC 接口。 这样,所有基于 WIC 的应用程序都可以以与标准图像格式交互的相同方式与编解码器交互。
- 实现容器级编码器类和帧级编码器类,该类公开对图像进行编码和将元数据块序列化为图像文件所需的 WIC 接口。
- 如果容器格式不基于 TIFF 或 JPEG 容器,则可能需要为 EXIF、XMP) (常见元数据格式编写元数据处理程序。 但是,如果使用基于 TIFF 或基于 JPEG 的容器格式,则没有必要这样做,因为可以委托给系统提供的元数据处理程序。
- 建议在所有图像文件中嵌入唯一标识模式 (GUID) 。 这使你的图像格式能够在发现过程中与编解码器匹配。 如果要为现有图像格式编写 WIC 包装器,则必须找到编码器始终写入其图像文件中的位模式,该模式对于该图像格式是唯一的,并将其用作标识 pattern.)
- 在安装时注册编解码器。 这样,通过在注册表中将标识模式与嵌入在映像文件中的模式匹配,可以在运行时发现编解码器。
- 从 Windows 7 开始,WIC 要求编解码器为 COM 单元类型“Both”。 这意味着必须执行适当的锁定,以处理多线程方案中的跨单元调用方和调用方。 有关详细信息,请参阅有关多线程单元支持的下一部分。
- 支持 64 位平台:对于 Windows 7,WIC 要求第三方 WIC 编解码器作为 32 位和 64 位本机二进制文件提供。 此外,32 位窗体必须在 64 位系统上安装并运行,第三方 Windows 7 编解码器安装程序必须在 64 位系统上同时安装 32 位和 64 位二进制文件。
WIC 中的多线程单元支持
多线程单元 (MTA) 的对象可由 MTA 内任意数量的线程同时调用。 这可以在多核系统和某些服务器方案中实现更好的性能。 此外,MTA 中的 WIC 编解码器可以调用 MTA 中的其他对象,而无需在不同 STA 单元中的线程之间调用相关的封送处理成本。 在 Windows 7 中,所有内置 WIC 编解码器都已更新为支持 MDA,包括 JPEG、TIFF、PNG、GIF、ICO 和 BMP。 强烈建议编写第三方编解码器以支持 MDA。 由于封送处理,不支持 MDA 的第三方编解码器在多线程应用程序中会产生巨大的性能成本。 启用 MTA 支持需要在第三方编解码器中实现适当的同步。 这些同步技术的确切实现超出了本文的范围。 有关同步 COM 对象的详细信息,请参阅 了解和使用 COM 线程模型。