几个月前我写了和篇文章

细心的网友也注意到了这个问题:

……但后来他备注说“已解决”,我当时也不知道该怎么解决的,所以我追问了一下,但他一直没有回复。但思路肯定是有的,再不济,也可以将保存为字节数组的数据,用其它的库进行重新解析,然后指定循环次数即可,当然这个方法肯定很搓,想象中较好的办法应该是调用SharpDX内置的API来完成。

踩坑之路

就此我开始了SharpDX的踩坑之路,我找到了许多资料,找到不少示例代码,最后不断实验,最终成功。

C++示例

首先我在网上找到了SharpDX生成循环gif文件的C++开源代码示例,代码源自于https://github.com/GarethRichards/GifSaver/blob/master/GifSaver.cpp

PROPVARIANT propValue; PropVariantInit(&propValue); propValue.vt = VT_UI1 | VT_VECTOR; propValue.caub.cElems = 11;  DX::ThrowIfFailed(m_imagingFactory->CreateEncoder(GUID_ContainerFormatGif, &GUID_VendorMicrosoft, &m_wicBitmapEncoder)); DX::ThrowIfFailed(m_wicBitmapEncoder->Initialize(m_stream.Get(), WICBitmapEncoderNoCache)); ComPtr<IWICMetadataQueryWriter> pEncoderMetadataQueryWriter; DX::ThrowIfFailed(m_wicBitmapEncoder->GetMetadataQueryWriter(&pEncoderMetadataQueryWriter)); string elms = "NETSCAPE2.0"; propValue.caub.pElems = const_cast<UCHAR *>(reinterpret_cast<const UCHAR *>(elms.c_str())); DX::ThrowIfFailed(pEncoderMetadataQueryWriter->SetMetadataByName(L"/appext/Application", &propValue));  // Set animated GIF format  propValue.vt = VT_UI1 | VT_VECTOR; propValue.caub.cElems = 5; UCHAR buf[5]; propValue.caub.pElems = &buf[0]; *(propValue.caub.pElems) = 3; // must be > 1,  *(propValue.caub.pElems + 1) = 1; // defines animated GIF  *(propValue.caub.pElems + 2) = 0; // LSB 0 = infinite loop.  *(propValue.caub.pElems + 3) = 0; // MSB of iteration count value  *(propValue.caub.pElems + 4) = 0; // NULL == end of data   DX::ThrowIfFailed(pEncoderMetadataQueryWriter->SetMetadataByName(L"/appext/Data", &propValue)); // ...

注意其中/appext/Data实际本质是一个字节数组,其内容为3 1 0 0 0,代表无限循环gif(注释中说得很清楚),这就应该是循环gif的关键所在。

可见,首先需要创建一个PROPVARIANT对象,然后调用IWICBitmapEncoder中的GetMetadataQueryWriter方法,获取IWICMetadataQueryWriter,然后通过该方法中的SetMetadataByName,将/appext/Application以及/appext/Data按照指定的格式传入即可,还能有问题什么呢?

问题可大咯!

坑人的Variant

刚好