引言

前面的一篇博文中总结了开发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

CoCreateInstance调用返回代码0x80040154的一种解决方法的更多相关文章

  1. 调用MediaScannerConnection 发生内存泄露的解决方法

    调用MediaScannerConnection发起扫描时经常会发生内存泄露,例如: E ActivityThread: Activity FolderListActivity has leaked ...

  2. WORD 的 Open 和Workbook 的 LoadFromFile 函数返回null的一种解决方法

    WORD Application.Documents.Open 和 Workbook workbookExcel.LoadFromFile 函数返回null的一种解决方法 DCOM Config Se ...

  3. JavaScript监听手机物理返回键的两种解决方法

    JavaScript没有监听物理返回键的API,所以只能使用 popstate 事件监听. 有两个解决办法: 1.返回到指定的页面 pushHistory(); window.addEventList ...

  4. 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结

    史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...

  5. uni-app开发经验分享一: 多页面传值的三种解决方法

    开发了一年的uni-app,在这里总结一些uni-app开发中的问题,提供几个解决方法,分享给大家: 问题描述:一个主页面,需要联通一到两个子页面,子页面传值到主页面,主页面更新 问题难点: 首先我们 ...

  6. 火狐浏览器如何js关闭窗口的几种解决方法

    今天在项目上有一个页面要求在几秒后自动关闭,想着还比较简单,用window.close()就可以了,但是用IE/谷歌/火狐浏览器试了一下,发现IE可以,谷歌用网上的兼容方法也可以实现,但是火狐这里卡住 ...

  7. mysql主从数据库不同步的2种解决方法(转)

    今天发现Mysql的主从数据库没有同步 先上Master库: mysql>show processlist; 查看下进程是否Sleep太多.发现很正常. show master status; ...

  8. php 生成唯一id的几种解决方法

    php 生成唯一id的几种解决方法   网上查了下,有很多的方法 1.md5(time() . mt_rand(1,1000000)); 这种方法有一定的概率会出现重复 2.php内置函数uniqid ...

  9. [转]unable to resolve superclass of 的奇怪问题和一种解决方法!

    [转]unable to resolve superclass of 的奇怪问题和一种解决方法! http://blog.csdn.net/jackymvc/article/details/90015 ...

随机推荐

  1. AJAX学习随笔

    AJAX名为“啊,贾克斯”,听着挺怪的哈. 主要的技术就是XMLHttpRequest对象和Javascript 度娘的解答: AJAX即“AsynchronousJavascriptAndXML”( ...

  2. win 8 换 win7 注意事项

    win8 换win7 硬盘格式修改一下gpt 格式转换为mbr模式 当进入到要选择安装到某一个盘时,由于磁盘的类型不同,会提示:“选中的磁盘采用GPT分区形式无法安装系统”.这时需要重新设置分区形式( ...

  3. python网页抓取练手代码

    from urllib import request import html.parser class zhuaqu(html.parser.HTMLParser): blogHtml = " ...

  4. SQL Server 2016 CTP2.2 安装手记

    SQL Server 2016 CTP2.2 安装手记 下载一个iso文件,解压出来(大约2.8G左右),在该路径下双击Setup.exe即可开始安装. 安装之前请先安装.NET 3.5 SP1,在服 ...

  5. 玩转JavaScript OOP[3]——彻底理解继承和原型链

    概述 上一篇我们介绍了通过构造函数和原型可以实现JavaScript中的“类”,由于构造函数和函数的原型都是对象,所以JavaScript的“类”本质上也是对象.这一篇我们将介绍JavaScript中 ...

  6. Hadoop学习笔记—12.MapReduce中的常见算法

    一.MapReduce中有哪些常见算法 (1)经典之王:单词计数 这个是MapReduce的经典案例,经典的不能再经典了! (2)数据去重 "数据去重"主要是为了掌握和利用并行化思 ...

  7. ECMAScript 6入门

    预计在2014年底,ECMAScript 6将会正式发布,他的草案在13年3月份被冻结,后续提出新特性将会移至ECMASript 7中.目前还没有哪款浏览器实现了ES6的全部内容,兼容性最强的一款要数 ...

  8. 为jQuery添加Webkit的触摸方法支持

    前些日子收到邮件,之前兼职的一个项目被转给了其他人,跟进的人来问我相关代码的版权问题. 我就呵呵了. 这段代码是我在做13年一份兼职的时候无聊加上去的,为jQuery添加触摸事件的支持.因为做得有点无 ...

  9. ASP.NET Web API的Controller是如何被创建的?

    Web API调用请求的目标是定义在某个HttpController类型中的某个Action方法,所以消息处理管道最终需要激活目标HttpController对象.调用请求的URI会携带目标HttpC ...

  10. Aspose.Words 16.8 破解版、添加自定义HTML导出Jpeg压缩质量配置

    0x01 Aspose.Words 介绍Aspose.Words是一个商业.NET类库,可以使得应用程序处理大量的文件任务.Aspose.Words支持Doc,Docx,RTF,HTML,OpenDo ...