实现 IWICBitmapEncoder

IWICBitmapEncoder

此接口是 IWICBitmapDecoder 接口的对应接口,是对图像文件进行编码的起点。 正如 IWICBitmapDecoder 用于从映像容器检索容器级属性和单个帧一样, IWICBitmapEncoder 用于设置容器级属性并将单个映像帧序列化到容器中。 可以在容器级编码器类上实现此接口。

interface IWICBitmapEncoder : public IUnknown
{
   // Required methods
   HRESULT Initialize ( IStream *pIStream,
              WICBitmapEncoderCacheOption cacheOption );
   HRESULT GetContainerFormat ( GUID *pguidContainerFormat );
   HRESULT GetEncoderInfo ( IWICBitmapEncoderInfo **pIEncoderInfo );
   HRESULT CreateNewFrame ( IWICBitmapFrameEncode **ppIFrameEncode,
              IPropertyBag2 **ppIEncoderOptions );
   HRESULT Commit ( void );

   // Optional methods
   HRESULT SetPreview ( IWICBitmapSource *pIPreview );
   HRESULT SetThumbnail ( IWICBitmapSource *pIThumbnail );
   HRESULT SetColorContexts ( UINT cCount,
              IWICColorContext **ppIColorContext );
   HRESULT GetMetadataQueryWriter ( IWICMetadataQueryWriter 
              **ppIMetadataQueryWriter );
   HRESULT SetPalette ( IWICPalette *pIPalette);
};

实现 IWICBitmapDecoder 中所述,某些图像格式具有全局缩略图、颜色上下文或元数据,而许多图像格式仅按帧提供这些格式。 因此,设置这些方法在 IWICBitmapEncoder 上是可选的,但在 IWICBitmapFrameEncode 上是必需的。 我们将在 IWICBitmapFrameEncode 部分讨论 IWICBitmapEncode 上的可选方法,这些方法最常实现。

如果不支持全局缩略图,请从 IWICBitmapEncoder 上的 SetThumbnail 方法返回WINCODEC_ERR_CODECNOTHUMBNAIL。 如果不支持容器级调色板,或者编码的图像没有索引格式,请从 SetPalette 方法返回WINCODEC_ERR_PALETTEUNAVAILABLE。 对于任何其他不受支持的方法,返回 WINCODEC_ERR_UNSUPPORTEDOPERATION。

Initialize

Initialize 是实例化 IWICBitmapEncoder 后在 IWICBitmapEncoder 上调用的第一个方法。 图像流将传递到编码器,调用方可以选择指定缓存选项。 对于解码器,流是只读的,但传递给编码器的流是可写流,编码器将序列化所有图像数据和元数据。 编码器上的缓存选项也不同。

enum WICBitmapEncoderCacheOption
{
   WICBitmapEncoderCacheInMemory,
   WICBitmapEncoderCacheTempFile,
   WICBitmapEncoderNoCache
}

应用程序可以选择请求编码器将图像数据缓存在内存中,将其缓存在临时文件中,或者直接将其写入磁盘文件,而无需缓存。 当系统要求在临时文件中缓存数据时,编码器应在磁盘上创建一个临时文件,并直接写入该文件,而无需在内存中缓存。 当调用方选择“无缓存”选项时,必须按顺序提交每个帧,然后才能创建下一帧。

GetContainerFormat

GetContainerFormat 的实现方式与实现 IWICBitmapDecoder 中的 GetContainerFormat 方法相同。

GetEncoderInfo

GetEncoderInfo 返回 IWICBitmapEncoderInfo 对象。 若要获取 IWICBitmapEncoderInfo 对象,只需将编码器的 GUID 传递到 IWICImagingFactory 上的 CreateComponentInfo 方法,然后请求其上的 IWICBitmapEncoderInfo 接口。

请参阅 GetDecoderInfo 下的实现 IWICBitmapDecoder 中的示例。

CreateNewFrame

CreateNewFrameIWICBitmapDecoder 上的 GetFrame 的编码器对应项。 此方法返回 一个 IWICBitmapFrameEncode 对象,该对象是实际序列化容器中特定帧的图像数据的对象。

Windows 映像组件 (WIC) 的一个优点是,它为应用程序提供了一个抽象层,使应用程序能够以相同的方式处理所有图像格式。 但是,并非所有图像格式都完全相同。 某些图像格式具有其他格式所没有的功能。 对于能够利用这些独特功能的应用程序,必须提供一种让编解码器公开它们的方法。 这是编码器选项的目的。 如果编解码器支持任何编码器选项,则应创建一个 IPropertyBag2 对象来公开你支持的编码器选项,并在此方法的 ppIEncoderOptions 参数中返回它。 然后,调用方可以使用此 IPropertyBag2 对象来确定编解码器支持的编码器选项。 如果调用方想要为任何受支持的编码器选项指定值,则会将该值分配给 IPropertyBag2 对象中的相关属性,并将其传递到其 Initialize 方法中新创建的 IWICBitmapFrameEncode 对象。

若要实例化 IPropertyBag2 对象,首先需要创建 PROPBAG2 结构,以指定编码器支持的每个编码器选项及其针对每个属性的数据类型。 然后,必须实现 IPropertyBag2 对象,该对象在写入时强制每个属性的值范围,并协调任何冲突或重叠的值。 对于不冲突的编码器选项的简单集,可以调用 CreateEncoderPropertyBag 方法,该方法将使用在 PROPBAG2 结构中指定的属性创建简单的 IPropertyBag2 对象。 仍必须强制实施值范围。 对于更高级的编码器选项,或者如果需要协调冲突值,则应编写自己的 IPropertyBag2 实现。

UINT cuiPropertyCount = 0;
IPropertyBag2* pPropertyBag = NULL;
PROPBAG2* pPropBagOptions;
HRESULT hr;

// Insert code here to initialize piPropertyBag with the 
// supported options for your encoder, and to initialize 
// cuiPropertyCount to the number of encoder option properties
// you are exposing.
...

hr = pComponentFactory->CreateEncoderPropertyBag( 
   pPropBagOptions, cuiPropertyCount, &pPropertyBag);

WIC 提供一小组规范编码器选项,这些选项由某些常见图像格式使用。 所有规范编码器选项都是可选的,无需编解码器即可支持其中任何选项。 它们作为规范选项提供的原因是,许多应用程序公开用户界面,供用户在保存支持这些选项的格式保存图像文件时指定这些选项。 提供指定这些选项的规范方式使应用程序可以轻松地以一致的方式将它们与编码器通信。 下表中列出了规范编码器选项。

编码器选项 VARTYPE 值范围
无损 VT_BOOL True/False
ImageQuality VT_R4 0.0-1.0
CompressionQuality VT_R4 0.0-1.0
BitmapTransform VT_UI1 WICBitmapTransformOptions

 

如果编解码器支持无损编码,则应公开无损编码器选项,以便应用程序请求对图像进行无损编码。 如果调用方将此属性设置为 True,则应忽略 ImageQuality 选项并无损地对图像进行编码。

ImageQuality 选项允许应用程序指定对图像进行编码的保真度。 此选项允许用户在图像质量与速度和/或文件大小之间进行权衡。 JPEG 是支持此权衡的图像格式的示例。 值为 0.0 表示保真度重要性较低,编码器应使用其最有损算法。 值为 1.0 表示保真度最为重要,编码器应尽可能保留最高保真度。 (根据编解码器,这可能与“无损”选项同义。但是,如果编解码器支持无损编码,并且“无损”选项设置为 True,则应忽略 ImageQuality 选项。)

使用 CompressionQuality 选项,应用程序可以指定在对图像进行编码时要使用的压缩效率。 非常高效的算法可能会生成较小的图像文件,其质量与效率较低的压缩算法相同,但可能需要更长的时间进行编码。 此选项允许用户指定文件大小与编码速度之间的权衡,同时保留相同的质量级别。 TIFF 是支持此权衡的图像格式的示例。 (请注意,JPEG 等格式支持不同级别的压缩,但较高的压缩率会导致图像质量降低。因此,JPEG 图像格式会公开 ImageQuality 选项,而不是 CompressionQuality 选项。) 此选项的值为 0.0 表示应尽快压缩图像,而不会降低保真度,代价是更大的文件大小。 值为 1.0 表示应以相同的质量) 级别创建尽可能小的文件大小 (,而不考虑编码所需的时间。 编解码器可以同时支持 ImageQuality 选项和 CompressionQuality 选项,其中 ImageQuality 选项指定可接受的损失程度,CompressionQuality 选项在指定的质量级别提供大小/速度权衡。

BitmapTransform 选项为调用方提供了一种在编码时指定旋转角度或垂直或水平翻转方向的方法。 用于指定所请求转换的 WICBitmapTransformOptions 枚举与通过 IWICBitmapSourceTransform 接口进行解码期间请求转换时使用的枚举相同。

请注意,编码器不限于规范编码器选项。 编码器选项的目的是使编码器能够公开其功能,并且可以公开的功能类型没有限制。 确保编码器选项记录良好。 即使应用程序可以使用从此方法返回的属性包来发现你支持的选项的名称、类型和值范围,但要了解它们的含义或如何在用户界面中公开它们,唯一的方法就是从文档中获取。

提交

提交 是所有图像数据和元数据序列化到流后调用的方法。 应使用此方法将预览图像数据序列化到流中,以及任何全局缩略图、元数据、调色板或其他项(如果适用)。 此方法不应关闭文件流,因为打开流的应用程序应关闭它。

IWICBitmapFrameEncode:Commit 方法部分详细介绍了 IWICBitmapEncoderCacheOptions 如何影响此方法的行为。

SetPreview

SetPreview 用于创建图像的预览。 虽然并非严格要求每个图像都有预览,但强烈建议这样做。 现代数码相机和扫描仪生成分辨率非常高的图像,这些图像往往非常大,因此需要大量的处理时间才能解码。 来自下一代相机的图像将更大。 最好提供更小、分辨率较低的图像版本(通常采用 JPEG 格式),当用户请求图像时,可以“立即”快速解码并显示该图像。 应用程序可以在请求解码实际图像之前请求预览,以便为用户提供更好的体验,并在他们等待解码实际图像时向他们显示图像的屏幕大小表示形式。 尽管编解码器应提供预览,但不支持 IWICBitmapSourceTransform 的 编解码器肯定应该这样做。

如果提供 JPEG 预览版,则无需编写 JPEG 编码器来对其进行编码。 应委托给 WIC 平台随附的 JPEG 编码器,以便对预览和缩略图进行编码。

参考

IWICBitmapEncoder

IWICBitmapFrameEncode

概念性

编码器接口

实现 IWICBitmapCodecProgressNotification (Encoder)

如何编写WIC-Enabled CODEC

Windows 映像组件概述