引言

前面的一篇博文中总结了开发Windows Thumbnail Handler的一些经验。在公司实际项目中,需要同时针对图片和视频实现缩略图。同时还要在图片和视频文件的顶部加上LOGO。像如下这样的:

      于是考虑了一下实现方案:
      (1)LOGO资源采用Base64编码编译到DLL中去
      (2)公司自有的图片和视频文件进行全景拼接时依赖一串参数,而这串参数需要从文件中提取。因此采用RecipeThumbnailProvider实现IInitializeWithFile接口比较合适,这样能得到文件路径,具备更灵活的可操作性。
      (3)LOGO资源使用Windows自带的解码库来进行解码,也就是Windows Image Component(WIC).
      这么一思考,还是挺靠谱的。于是就动手开始编码,编写了一个解码LOGO资源的函数:
/**
* Decode the Base64-encoded string to get logo resources.
*/
HRESULT RecipeThumbnailProvider::GetLogoFromString(LPCWSTR encodedString, UINT* width, UINT* height, PBYTE* rawPixels)
{
IStream* pImageStream = NULL;
HRESULT hr = E_FAIL;
DWORD dwDecodedImageSize = 0;
DWORD dwSkipChars = 0;
DWORD dwActualFormat = 0; if (CryptStringToBinary(encodedString, NULL, CRYPT_STRING_BASE64, NULL, &dwDecodedImageSize, &dwSkipChars, &dwActualFormat))
{
BYTE* pbDecodedImage = static_cast<BYTE*>(LocalAlloc(LPTR, dwDecodedImageSize));
if (pbDecodedImage)
{
if (CryptStringToBinary(encodedString, lstrlen(encodedString), CRYPT_STRING_BASE64, pbDecodedImage, &dwDecodedImageSize, &dwSkipChars, &dwActualFormat))
{
pImageStream = SHCreateMemStream(pbDecodedImage, dwDecodedImageSize);
if (pImageStream != NULL)
{
IWICImagingFactory* pImageFactory;
hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImageFactory));
LOGINFO(L"CoCreateIntance() returns 0x%x", hr);
if (SUCCEEDED(hr))
{
IWICBitmapDecoder* pDecoder;
hr = pImageFactory->CreateDecoderFromStream(pImageStream, &GUID_VendorMicrosoft, WICDecodeMetadataCacheOnDemand, &pDecoder);
if (SUCCEEDED(hr))
{
IWICBitmapFrameDecode* pBitmapFrameDecode;
hr = pDecoder->GetFrame(0, &pBitmapFrameDecode);
if (SUCCEEDED(hr))
{
IWICBitmapSource* pBitmapSourceConverted = NULL;
WICPixelFormatGUID guidPixelFormatSource;
hr = pBitmapFrameDecode->GetPixelFormat(&guidPixelFormatSource);
if (SUCCEEDED(hr) && (guidPixelFormatSource != GUID_WICPixelFormat24bppBGR))
{
IWICFormatConverter* pFormatConverter;
hr = pImageFactory->CreateFormatConverter(&pFormatConverter);
if (SUCCEEDED(hr))
{
hr = pFormatConverter->Initialize(pBitmapFrameDecode, GUID_WICPixelFormat24bppBGR, WICBitmapDitherTypeNone, NULL, 0, WICBitmapPaletteTypeCustom);
if (SUCCEEDED(hr))
{
hr = pFormatConverter->QueryInterface(&pBitmapSourceConverted);
}
pFormatConverter->Release();
}
}
else
{
hr = pBitmapFrameDecode->QueryInterface(&pBitmapSourceConverted);
}
if (SUCCEEDED(hr))
{
hr = pBitmapSourceConverted->GetSize(width, height);
if (SUCCEEDED(hr))
{
WICRect rect = { 0, 0, *width, *height };
*rawPixels = static_cast<BYTE*>(LocalAlloc(LPTR, (*width)*(*height)*3));
hr = pBitmapSourceConverted->CopyPixels(&rect, (*width) * 3, (*width)*(*height) * 3, *rawPixels);
}
else
{
*width = 0;
*height = 0;
*rawPixels = NULL;
}
pBitmapSourceConverted->Release();
}
pBitmapFrameDecode->Release();
}
pDecoder->Release();
}
pImageFactory->Release();
}
pImageStream->Release();
}
}
} LocalFree(pbDecodedImage);
}
return hr;
}

  当我注册好COM组件开始使用时,在本机上测试简直完美。满以为就这么搞定了,然而并么有。在另外一台Win7机器上测试时,缩略图中并没有出现想象中的LOGO。一看日志文件,发现一直在报:CoCreateInstance()调用返回0x80040154。于是下面的代码都没执行,LOGO资源自然没有加载成功了。那么CoCreateInstance()为啥会返回0x80040154呢?这个代码又意味着什么嗯?从网上的搜索结果来看,0x80040154是表示"Class Not Registered"。也就是说COM类并没有注册,在注册表\HKEY_CLASSES_ROOT\CLSID\下面也就没有类ID了。我们程序中使用了WIC组件来解码图片,那么难道是WIC组件类没有注册吗?

      再一想,开发时采用的一直是Windows10,可以正常运行。到了Windows7上为啥就不行了呢?难道是WIC在Windows7上不支持?这个怀疑显然是不成立的,从MSDN上来看从XP SP2就开始支持了啊:
      那么难道是参数给的不对?以CLSID_WICImagingFactory为关键字一搜索果然搜到了一篇帖子CLSID_WICImagingFactory在Windows10上被解析为了CLSID_WICImagingFactory2:
      而这个GUID在Windows7上是不存在的(搜索注册表即可看到结果):
      自然CoCreateInstance()调用就会返回0x80040154了。解决方案就是传递CLSID_WICImagingFactory1给CoCreateInstance()。这样就能同时兼容Windows10和Windows7了。

参考链接

  1. http://stackoverflow.com/questions/16697112/why-using-wic-in-my-32-bit-application-fails-in-windows-7-32-bit

最新文章

  1. WCF Restful 服务器配置文件
  2. array&#39;s filter
  3. jQuery—一些常见方法(3)【width(),innerWidth(),outerWidth()】
  4. 10.21_Nutz批量插入顺序,POI,wiki持续关注,POI,SSH,数据库优先
  5. flv网页播放器播放失败
  6. Jquery揭秘系列:谈谈bind,one,live,delegate,on事件及实现
  7. CURD特性
  8. POJ 1873 The Fortified Forest [凸包 枚举]
  9. 85、int 、NSInteger、NSUInteger、NSNumber的区别和联系
  10. 无向图的 DFS 和 BFS实现 (以邻接表存储的图)
  11. CareerCup All in One 题目汇总
  12. AbstractQueuedSynchronizer同步队列与Condition等待队列协同机制
  13. eclipse环境搭建(插件安装)
  14. WPF自定义控件的自定义属性绑定后不更新问题
  15. Java实现在线预览Word,Excel,Ppt文档
  16. mysqlsla 安装
  17. SQL SERVER2014的安装
  18. c++ poco 使用mysql中文乱码问题
  19. php uncode 转汉字编码
  20. mysql 5.1.7.17 zip安装 和 隔段时间服务不见了处理

热门文章

  1. laravel 生成验证码的方法
  2. GDB十分钟教程
  3. 初识Opserver,StackExchange的监控解决方案
  4. (翻译)《Hands-on Node.js》—— Introduction
  5. JavaScript面向对象之我见
  6. Angular 2 最终版正式发布
  7. Android开发学习之路-Android Studio真神器!
  8. Atitit 查询优化器的流程attilax总结
  9. Java面试(1)-- Java逻辑运算符
  10. Android笔记——提升ListView的运行效率