windows WIC 简介

来源:互联网 发布:西门淘宝店网址 编辑:程序博客网 时间:2024/06/07 04:14

windows 图片组件 (windows image component,WIC)

特性

  1. 一个同意的图片处理接口,使我们不需要了解每一种图片格式的标准
  2. 提供即插即用(plug and play”)的模式。可以自由增加新的解码器和编码器
  3. 内建了大多数流行格式的解码器和编码器
  4. >Preserves high bit depth image data, up to 32 bits per channel, throughout the image processing pipeline.(太专业,不懂)

内建的图片格式参考下面链接
https://msdn.microsoft.com/zh-cn/library/windows/desktop/ee719654(v=vs.85).aspx

所需环境

wincodec.h 解码器和编码其的头文件

windowscodecs.lib 需要的库文件
windowscodecs.dll 动态链接库 (win7和之后版本都是内建的)

使用

因为WIC使通过COM组件提供支持的。所以使用和其他COM组件一样。

WIC提供了两个工厂类。
IWICImagingFactory:一般软件开发者用的。通过它来得到相应的解码器和编码器
IWICComponentFactory 给写解码器和编码器的开发着用的。
来自msdn 的初始化例子

// Initialize COMCoInitialize(NULL);// The factory pointerIWICImagingFactory *pFactory = NULL;// Create the COM imaging factoryHRESULT hr = CoCreateInstance(    CLSID_WICImagingFactory,    NULL,    CLSCTX_INPROC_SERVER,    IID_PPV_ARGS(&pFactory));

解码图片

为了某些原因,现在的图片中不光保存着图片的数据信息同时还保存了很多别的信息。如
global thumbnails(全局缩略图), previews(预览), color contexts,(显色上下文) metadata(元数据)。

然而。我们主流格式(BMP,GIF,ICO,JPEG,PNG,TIFF)是没有这些东西的。所以WIC内建的解码器是不支持这些东西的。如果你想让你的软件解码带有这些属性的图片请装在相应的解码器(链接)。或者你希望个主流图片格式写入这些信息请使用相应的编码。(链接)

说回解码。IWICImagingFactory工厂接为我们提供的方法如下方法生成 IWICBitmapDecoder。看见没有这是一个位图解码器。

  • CreateDecoder
  • CreateDecoderFromFileHandle
  • CreateDecoderFromFilename
  • CreateDecoderFromStream

通过名字就知道方法怎么用了。WICImagingFactory只能解码成bitmap 如果想解码成别的格式只能自己调用别的解码器了(链接)

//例子在上面// Create a decoder   IWICBitmapDecoder *pDecoder = NULL;   hr = m_pIWICFactory->CreateDecoderFromFilename(       szFileName,                      // Image to be decoded,文件名       NULL,                            // Do not prefer a particular vendor 非内建的解码器       GENERIC_READ,                    // Desired read access to the file 访问权限       WICDecodeMetadataCacheOnDemand,  // Cache metadata when needed        &pDecoder                        // Pointer to the decoder        );   // Retrieve the first frame of the image from the decoder   IWICBitmapFrameDecode *pFrame = NULL;   if (SUCCEEDED(hr))   {       hr = pDecoder->GetFrame(0, &pFrame);   }

通过代码我们可以才出来IWICBitmapFrameDecode 就是图片实体。但是为什么叫这个名字呢。

frame 帧,稍微了解图片格式的人都知道有一种图片格式叫做gif格式的(当然还有别的格式)。它是可以动的。而这个类型的照片就有很多帧,每一帧表示一张照片。IWICBitmapFrameDecode 就是其中的帧。

很多情况下我们的图片都是只有一针。所以像上面那样就ok了。而对于多帧的照片就需要下面的代码了

    IWICBitmapFrameDecode *pFrame = NULL;        if (SUCCEEDED(hr))        {            hr = pDecoder->GetFrame(0, &pFrame);        }        size_t framCount;        // Retrieve the frame count of the image.        if (SUCCEEDED(hr))        {            hr = pDecoder->GetFrameCount(&framCount);        }        for (UINT i = 0; i < framCount; i++)        {            // Retrieve the next bitmap frame.            if (SUCCEEDED(hr))            {                hr = pDecoder->GetFrame(i, &pFrame);            }            // Retrieve the size of the bitmap frame.            if (SUCCEEDED(hr))            {                hr = pFrame->GetSize(&uiWidth, &uiHeight);            }            // Additional frame processing.            // ...            pFrame->Release();        }

逐步解码

Progressive Decoding ,逐步解码是一种分步解码图片的技术。举个例子,以前上网浏览照片的时候,都是等照片载入完毕之后在显示的。但是现在我们在某些网站上浏览照片的时候,可以明显感觉到照片由模糊变清楚(感觉不到!你家网太好了吧)。这个实现就就需要Progressive Decoding 。
下面是我从msdn 拔下来的例子,下面就是分步提高图片分辨率的方法。
这里写图片描述

着项技术很酷炫,但是需要满足三个条件

  • 解码器支持
  • 编码器支持
  • 图片格式支持
    坏消息大部分图片格式是不支持的如 JPEG, PNG,GIF。
    但是好消息是win7和之后的版本内置的解码器和编码器都是支持逐步解码,也就是我们可以使用这种解码器和编码器来加工我们的主流图片使它可以逐步解码。

在win7中实现如下。首先编码器会为每一个像素指定一个progressive level 。想下面这样

这里写图片描述

然后传输照片时,先传输低progressive level 像素再传输高progressive level的像素。而我们的解码器先就会按照由低到高一步一步解码图片。每一步的解码叫做decoding pass 。

对于解码来说想使用这个酷炫的技术就需要 IWICProgressiveLevelControl接口了。

例子

//前面是初始化工作// Retrieve the frame count of the image.if (SUCCEEDED(hr)){   hr = pIDecoder->GetFrameCount(&nFrameCount);//获得帧数量}// Process each frame in the image.for (UINT i=0; i < nFrameCount; i++){//获得每一帧   // Retrieve the next bitmap frame.   if (SUCCEEDED(hr))   {      hr = pIDecoder->GetFrame(i, &pIDecoderFrame);   }   // Retrieve the size of the bitmap frame.   if (SUCCEEDED(hr))   {      hr = pIDecoderFrame->GetSize(&uiWidth, &uiHeight);   }   // Additional frame processing.   // ...    //结尾别忘了释放帧对象   SafeRelease(&pIDecoderFrame);}