使用WIC(Windows Imaging Component)中遇到的问题

ULTRON19 2020-03-06 02:36:06
各位大佬们!
最近我使用了WIC来解析GIF,代码写好了,能在Win10和Win7上完美运行,但是却在WinXP上失败了,我排除了很久,最终在这一行代码上找到了原因:

// pBitmapFrameDecode 是一个 IWICBitmapFrameDecode
hr = pBitmapFrameDecode->GetMetadataQueryReader(&pFrameMetadataQueryReader);
if (hr == WINCODEC_ERR_UNSUPPORTEDOPERATION && I == 0) MessageBox(NULL, "WINCODEC_ERR_UNSUPPORTEDOPERATION", "Error!", MB_OK); // I == 0 是第一帧

在这一行代码里,GetMetadataQueryReader 失败了,导致下面的 GetMetadataByName 通通 Get 不到,我就感觉很奇怪,于是去翻了翻 MSDN https://docs.microsoft.com/en-us/windows/win32/api/wincodec/nf-wincodec-iwicbitmapframedecode-getmetadataqueryreader ,发现我的XP电脑是符合MSDN中写的最低配置要求的(SP3),更加诡异的是,这个函数还返回了 WINCODEC_ERR_UNSUPPORTEDOPERATION ,我明明就解析的GIF然后还返回这玩意,及其诡异……
更加诡异的是,除了这行代码以及所有关于IWICMetadataQueryReader 的操作之外,其它的函数例如图片解码,拷贝像素什么的都很顺利。也就是说,我可以把GIF的每一帧都打印出来,唯独每一帧的相对位置和延迟时间读不出来(这一部分也就需要用到IWICMetadataQueryReader了)
我特别地懵逼,一开始以为是我自己的设备问题,就东借西凑了几台XP电脑,然后它们都极其一致地返回了WINCODEC_ERR_UNSUPPORTEDOPERATION,特别的诡异………… 也就是说,XP的SP3 都没得办法,难道MSDN真就骗人的?
于是特此发张贴,来寻找是否有在XP上使用过WIC的大佬(感觉是没有的,不过还是碰碰运气看看),不知道有哪位大佬遇到过这种问题,我应该怎么去解决,如果需要源码的话可以说一下,我可以发出来的。(我上传的两张图片,一张是Win10的,一张是WinXP的)
感激不尽!
...全文
903 47 打赏 收藏 转发到动态 举报
写回复
用AI写文章
47 条回复
切换为时间正序
请发表友善的回复…
发表回复
ULTRON19 2020-03-14
  • 打赏
  • 举报
回复
引用 46 楼 捡破烂程序员 的回复:
[quote=引用 45 楼 ULTRON19的回复:][quote=引用 44 楼 捡破烂程序员 的回复:] [quote=引用 41 楼 ULTRON19的回复:][quote=引用 40 楼 捡破烂程序员 的回复:] [quote=引用 39 楼 捡破烂程序员的回复:][quote=引用 38 楼 ULTRON19的回复:][quote=引用 37 楼 qybao 的回复:] 用一个比较幼稚的方式试试 把win7的Windowscodecs.dll拷贝到xp去(或者找个vista版本的dll拷贝到xp,官方说最低支持xp的sp2和vista,就把比它高的版本的dll拷贝错去),然后是运行看看能不能跑起来
试了一下,出错了:无法定位程序输入点_seh_longjmp_unwind4于动态链接库msvcrt.dll上,并且,我的xp电脑上是有msvcrt.dll的…………[/quote] 引用高版本的库容易出现这种错误。因为那个库是为高版本操作系统设计的,他使用高版本内核的API[/quote] 你可以尝试在win2003上面试试,他的内核主版本个XP一致,不行估计就没戏了[/quote] 我手头好像没有win2003,不过估计也是不行的……这几天研究了一下GIF的储存结构,自己写了一个函数,能读取每一帧的相对位置以及延迟时间[/quote] 安装2003虚拟机去试试[/quote] 突然想起MSDN里写着需要支持Windows Server 2008及其以上的…………[/quote] 我先石化一会儿。嗯好了,你赢了[/quote] 还是很奇怪呀……其它的函数也写着 Minimum supported server:Windows Server 2008,比如说IWICBitmapSource::CopyPixels等等,但是都能运行并成功返回……
捡破烂攻城狮 2020-03-14
  • 打赏
  • 举报
回复
引用 45 楼 ULTRON19的回复:
[quote=引用 44 楼 捡破烂程序员 的回复:] [quote=引用 41 楼 ULTRON19的回复:][quote=引用 40 楼 捡破烂程序员 的回复:] [quote=引用 39 楼 捡破烂程序员的回复:][quote=引用 38 楼 ULTRON19的回复:][quote=引用 37 楼 qybao 的回复:] 用一个比较幼稚的方式试试 把win7的Windowscodecs.dll拷贝到xp去(或者找个vista版本的dll拷贝到xp,官方说最低支持xp的sp2和vista,就把比它高的版本的dll拷贝错去),然后是运行看看能不能跑起来
试了一下,出错了:无法定位程序输入点_seh_longjmp_unwind4于动态链接库msvcrt.dll上,并且,我的xp电脑上是有msvcrt.dll的…………[/quote] 引用高版本的库容易出现这种错误。因为那个库是为高版本操作系统设计的,他使用高版本内核的API[/quote] 你可以尝试在win2003上面试试,他的内核主版本个XP一致,不行估计就没戏了[/quote] 我手头好像没有win2003,不过估计也是不行的……这几天研究了一下GIF的储存结构,自己写了一个函数,能读取每一帧的相对位置以及延迟时间[/quote] 安装2003虚拟机去试试[/quote] 突然想起MSDN里写着需要支持Windows Server 2008及其以上的…………[/quote] 我先石化一会儿。嗯好了,你赢了
ULTRON19 2020-03-14
  • 打赏
  • 举报
回复
引用 44 楼 捡破烂程序员 的回复:
[quote=引用 41 楼 ULTRON19的回复:][quote=引用 40 楼 捡破烂程序员 的回复:] [quote=引用 39 楼 捡破烂程序员的回复:][quote=引用 38 楼 ULTRON19的回复:][quote=引用 37 楼 qybao 的回复:] 用一个比较幼稚的方式试试 把win7的Windowscodecs.dll拷贝到xp去(或者找个vista版本的dll拷贝到xp,官方说最低支持xp的sp2和vista,就把比它高的版本的dll拷贝错去),然后是运行看看能不能跑起来
试了一下,出错了:无法定位程序输入点_seh_longjmp_unwind4于动态链接库msvcrt.dll上,并且,我的xp电脑上是有msvcrt.dll的…………[/quote] 引用高版本的库容易出现这种错误。因为那个库是为高版本操作系统设计的,他使用高版本内核的API[/quote] 你可以尝试在win2003上面试试,他的内核主版本个XP一致,不行估计就没戏了[/quote] 我手头好像没有win2003,不过估计也是不行的……这几天研究了一下GIF的储存结构,自己写了一个函数,能读取每一帧的相对位置以及延迟时间[/quote] 安装2003虚拟机去试试[/quote] 突然想起MSDN里写着需要支持Windows Server 2008及其以上的…………
捡破烂攻城狮 2020-03-14
  • 打赏
  • 举报
回复
引用 41 楼 ULTRON19的回复:
[quote=引用 40 楼 捡破烂程序员 的回复:] [quote=引用 39 楼 捡破烂程序员的回复:][quote=引用 38 楼 ULTRON19的回复:][quote=引用 37 楼 qybao 的回复:] 用一个比较幼稚的方式试试 把win7的Windowscodecs.dll拷贝到xp去(或者找个vista版本的dll拷贝到xp,官方说最低支持xp的sp2和vista,就把比它高的版本的dll拷贝错去),然后是运行看看能不能跑起来
试了一下,出错了:无法定位程序输入点_seh_longjmp_unwind4于动态链接库msvcrt.dll上,并且,我的xp电脑上是有msvcrt.dll的…………[/quote] 引用高版本的库容易出现这种错误。因为那个库是为高版本操作系统设计的,他使用高版本内核的API[/quote] 你可以尝试在win2003上面试试,他的内核主版本个XP一致,不行估计就没戏了[/quote] 我手头好像没有win2003,不过估计也是不行的……这几天研究了一下GIF的储存结构,自己写了一个函数,能读取每一帧的相对位置以及延迟时间[/quote] 安装2003虚拟机去试试
ULTRON19 2020-03-14
  • 打赏
  • 举报
回复
哦对,关于GIF的储存结构,顺便附一下参考链接: https://blog.csdn.net/MoGuanXiao/article/details/52992009 https://zhidao.baidu.com/question/16263104.html http://blog.chinaunix.net/uid-23065002-id-4067026.html https://segmentfault.com/a/1190000011425787
ULTRON19 2020-03-13
  • 打赏
  • 举报
回复
感谢各位给我支招,虽然好像没什么卵用,不过学到了很多有用的东西,比如说GIF中使用的LZW压缩算法,还有通过dll显式调用函数等等。看来鄙人还有很多要学 虽然问题的根源没有解决(如果后来人有见解可以私信我),但还是多谢各位大佬,结帖了
ULTRON19 2020-03-13
  • 打赏
  • 举报
回复
由于我在win32那个工程里是从资源文件读取的GIF,而且中间使用了BYTE数组来储存GIF的信息,故我自己的这个函数的参数是BYTE指针,贴一下代码方便后来人吧:
bool GIF_Get_Frame_Data (PBYTE buffer, int buffer_count) 
{
	//	freopen("Get_Frame_Debug.txt", "w+", stdout);
	
	int i = 10; // 舍弃前 10 Bytes 
	
	bool Global_Color_TableFlag = buffer[i] >> 7;										// 全局颜色列表标志
	int Global_Pixel_Index_Count = Global_Color_TableFlag ? 2 << (buffer[i] % 8) : 0;	// 全局颜色列表索引数 
	
	i += 3 + Global_Pixel_Index_Count * 3; // 跳过这 1 Byte 和接下来的 2 Bytes 并且如果有,跳过全局色表
	
	while (i < buffer_count)
	{
		int cnt;
		switch (buffer [i++])
		{
			case 0x21:
			{
				switch (buffer [i++])
				{
					case 0xfe: // 注解块
                    case 0x01: // 普通文本块
                    case 0xff: // 应用程序块
                    	while (cnt = buffer [i++])
                            i += cnt;
                        break;
                    case 0xf9: // 图形控制扩展块
                    {
                    	static int Frame_Index = 0; // 第 n 帧 
						printf("\nFrame - %d:\n", Frame_Index++);
						
                    	i += 2;
                    	int Frame_Delay = ((buffer [i+1] << 8) | buffer [i]) * 10;	i+=4;	// 帧延迟时间 (单位:ms)
                    	printf("  Frame_Delay: %d\n", Frame_Delay);
                    	
                    	break;
					}
                    default:
                        printf("Bad Format!\n");
                        break;
				}
				break;
			}
			
			case 0x2c: // 图象标识符
			{
				// 读取元数据并输出 
				int Frame_X_Offset	=	(buffer [i+1] << 8) | buffer [i];	i+=2;	// X 轴偏移量 
				int Frame_Y_Offset	=	(buffer [i+1] << 8) | buffer [i];	i+=2;  	// Y 轴偏移量 
				int Frame_Width		=	(buffer [i+1] << 8) | buffer [i];	i+=2;	// 帧宽度 
				int Frame_Height	=	(buffer [i+1] << 8) | buffer [i];	i+=2;	// 帧高度 
				
				printf ("  Frame_Width: %d\n",	Frame_Width);
				printf ("  Frame_Height: %d\n", Frame_Height);
				printf ("  X_Offset: %d\n",		Frame_X_Offset);
				printf ("  Y_Offset: %d\n",		Frame_Y_Offset);
				
				bool Local_Color_TableFlag = buffer[i] >> 7;										// 局部颜色列表标志
				int Local_Pixel_Index_Count = Local_Color_TableFlag ? 2 << (buffer[i] % 8) : 0;		// 局部颜色列表索引数 
				
				i += 1 + Local_Pixel_Index_Count * 3; // 跳过这 1 Byte 并且如果有,跳过局部色表 
				
				// LZW
				int LZW_Min_Code_Size = buffer [i++]; // 读取 LZW 编码初始码表大小的位数  
				
				while(cnt = buffer[i++]) // 跳过子块 
					i+= cnt;
				
				break;
			}
			
			case 0x3b:
			{
            	printf("\nDecode End!\n");
                break;
			}
                
            default:
			{
            	printf("Unkown Type: %d: %u\n", i, buffer[i - 1]);
                break;
			}
		}
	}
	
	//	fclose(stdout);
	
	return true;
}
这样的话也就能满足我的需求了,目前看来这应该是唯一的替代方法了吧……我觉得后来人应该不会去探究这个问题了,现在连win7都停止支持了,估计没几个人会继续用着XP吧……
ULTRON19 2020-03-13
  • 打赏
  • 举报
回复
引用 40 楼 捡破烂程序员 的回复:
[quote=引用 39 楼 捡破烂程序员的回复:][quote=引用 38 楼 ULTRON19的回复:][quote=引用 37 楼 qybao 的回复:] 用一个比较幼稚的方式试试 把win7的Windowscodecs.dll拷贝到xp去(或者找个vista版本的dll拷贝到xp,官方说最低支持xp的sp2和vista,就把比它高的版本的dll拷贝错去),然后是运行看看能不能跑起来
试了一下,出错了:无法定位程序输入点_seh_longjmp_unwind4于动态链接库msvcrt.dll上,并且,我的xp电脑上是有msvcrt.dll的…………[/quote] 引用高版本的库容易出现这种错误。因为那个库是为高版本操作系统设计的,他使用高版本内核的API[/quote] 你可以尝试在win2003上面试试,他的内核主版本个XP一致,不行估计就没戏了[/quote] 我手头好像没有win2003,不过估计也是不行的……这几天研究了一下GIF的储存结构,自己写了一个函数,能读取每一帧的相对位置以及延迟时间
捡破烂攻城狮 2020-03-13
  • 打赏
  • 举报
回复
引用 39 楼 捡破烂程序员的回复:
[quote=引用 38 楼 ULTRON19的回复:][quote=引用 37 楼 qybao 的回复:] 用一个比较幼稚的方式试试 把win7的Windowscodecs.dll拷贝到xp去(或者找个vista版本的dll拷贝到xp,官方说最低支持xp的sp2和vista,就把比它高的版本的dll拷贝错去),然后是运行看看能不能跑起来
试了一下,出错了:无法定位程序输入点_seh_longjmp_unwind4于动态链接库msvcrt.dll上,并且,我的xp电脑上是有msvcrt.dll的…………[/quote] 引用高版本的库容易出现这种错误。因为那个库是为高版本操作系统设计的,他使用高版本内核的API[/quote] 你可以尝试在win2003上面试试,他的内核主版本个XP一致,不行估计就没戏了
捡破烂攻城狮 2020-03-13
  • 打赏
  • 举报
回复
引用 38 楼 ULTRON19的回复:
[quote=引用 37 楼 qybao 的回复:] 用一个比较幼稚的方式试试 把win7的Windowscodecs.dll拷贝到xp去(或者找个vista版本的dll拷贝到xp,官方说最低支持xp的sp2和vista,就把比它高的版本的dll拷贝错去),然后是运行看看能不能跑起来
试了一下,出错了:无法定位程序输入点_seh_longjmp_unwind4于动态链接库msvcrt.dll上,并且,我的xp电脑上是有msvcrt.dll的…………[/quote] 引用高版本的库容易出现这种错误。因为那个库是为高版本操作系统设计的,他使用高版本内核的API
qybao 2020-03-11
  • 打赏
  • 举报
回复
用一个比较幼稚的方式试试
把win7的Windowscodecs.dll拷贝到xp去(或者找个vista版本的dll拷贝到xp,官方说最低支持xp的sp2和vista,就把比它高的版本的dll拷贝错去),然后是运行看看能不能跑起来
ULTRON19 2020-03-11
  • 打赏
  • 举报
回复
引用 35 楼 捡破烂程序员 的回复:
有没有尝试反汇编调试方式,如果你了解汇报的话(我不懂)
这个我也不太会,我觉得花在这个东西上的时间太多了,不如直接解析GIF的内容好了……
ULTRON19 2020-03-11
  • 打赏
  • 举报
回复
引用 37 楼 qybao 的回复:
用一个比较幼稚的方式试试 把win7的Windowscodecs.dll拷贝到xp去(或者找个vista版本的dll拷贝到xp,官方说最低支持xp的sp2和vista,就把比它高的版本的dll拷贝错去),然后是运行看看能不能跑起来
试了一下,出错了:无法定位程序输入点_seh_longjmp_unwind4于动态链接库msvcrt.dll上,并且,我的xp电脑上是有msvcrt.dll的…………
捡破烂攻城狮 2020-03-10
  • 打赏
  • 举报
回复
有没有尝试反汇编调试方式,如果你了解汇报的话(我不懂)
捡破烂攻城狮 2020-03-09
  • 打赏
  • 举报
回复
引用 30 楼 ULTRON19 的回复:
[quote=引用 23 楼 ULTRON19 的回复:] 刚刚调用了下GetLastError,很有趣的是无论是直接调用 IWICBitmapFrameDecode::GetMetadataQueryReader 还是通过 LoadLibrary 和 GetProcAddress 显式调用 IWICBitmapFrameDecode_GetMetadataQueryReader_Proxy,GetLastError都是返回127(找不到指定的程序),而 LoadLibrary 和 GetProcAddress 却是没有问题的,并且DLL中也确实存在代理函数,更加的诡异了……
最新补充:刚刚发现这个GetLastError并不是来自GetMetadataQueryReader的,经过排查后发现这个Error来自于解码器的创建函数CreateDecoderFromStream(CreateDecoderFromFileName也是一样的),IWICImagingFactory::CreateDecoderFromStream这个函数成功返回了S_OK,但是GetLastError居然不是0而是127!!![/quote]如果解决了,分享一下
ULTRON19 2020-03-09
  • 打赏
  • 举报
回复
引用 32 楼 捡破烂程序员 的回复:
[quote=引用 30 楼 ULTRON19 的回复:] [quote=引用 23 楼 ULTRON19 的回复:] 刚刚调用了下GetLastError,很有趣的是无论是直接调用 IWICBitmapFrameDecode::GetMetadataQueryReader 还是通过 LoadLibrary 和 GetProcAddress 显式调用 IWICBitmapFrameDecode_GetMetadataQueryReader_Proxy,GetLastError都是返回127(找不到指定的程序),而 LoadLibrary 和 GetProcAddress 却是没有问题的,并且DLL中也确实存在代理函数,更加的诡异了……
最新补充:刚刚发现这个GetLastError并不是来自GetMetadataQueryReader的,经过排查后发现这个Error来自于解码器的创建函数CreateDecoderFromStream(CreateDecoderFromFileName也是一样的),IWICImagingFactory::CreateDecoderFromStream这个函数成功返回了S_OK,但是GetLastError居然不是0而是127!!![/quote]如果解决了,分享一下[/quote] 一定,只是……看起来应该是很难解决了
weixin_46510784 2020-03-08
  • 打赏
  • 举报
回复
水电费水电费水电费
捡破烂攻城狮 2020-03-08
  • 打赏
  • 举报
回复
一个思路,试一下:https://www.cnblogs.com/passedbylove/p/5979927.html
ULTRON19 2020-03-08
  • 打赏
  • 举报
回复
引用 23 楼 ULTRON19 的回复:
刚刚调用了下GetLastError,很有趣的是无论是直接调用 IWICBitmapFrameDecode::GetMetadataQueryReader 还是通过 LoadLibrary 和 GetProcAddress 显式调用 IWICBitmapFrameDecode_GetMetadataQueryReader_Proxy,GetLastError都是返回127(找不到指定的程序),而 LoadLibrary 和 GetProcAddress 却是没有问题的,并且DLL中也确实存在代理函数,更加的诡异了……
最新补充:刚刚发现这个GetLastError并不是来自GetMetadataQueryReader的,经过排查后发现这个Error来自于解码器的创建函数CreateDecoderFromStream(CreateDecoderFromFileName也是一样的),IWICImagingFactory::CreateDecoderFromStream这个函数成功返回了S_OK,但是GetLastError居然不是0而是127!!!
ULTRON19 2020-03-08
  • 打赏
  • 举报
回复
引用 27 楼 捡破烂程序员 的回复:
是否需要相关的图形编码解码库
倒是不需要的,因为整个程序就只有那行代码过不去,其它的代码,比如说图片解码,拷贝像素等均能正常运行,就偏偏要读这个帧的偏移量和延迟时间出毛病……
加载更多回复(27)

64,281

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧