写完这篇文章这个月就不在更新文章了,回家过年了!这里向关注我的和我关注的博友们,说一声新春快乐,合家幸福,感谢你们的支持和帮助。
下面是用Directshow转换图片格式的函数,年后我再将其封装成一个类方便日后的使用。
/* *函数介绍:根据编码器类型名称,得到指定的编码器CLSID *入口参数:pImagingFactory: Image工厂接口对象 wszMimeType : Image编码格式名称 *出口参数:pclsid :编码器的CLSID *返回值:TRUE : 成功; FALSE: 失败 */ BOOL GetEnCodecCLSID(IImagingFactory* pImagingFactory,LPCTSTR strMimeType ,CLSID * pclsid ) { UINT uiCount; ImageCodecInfo * codecs; HRESULT hr; BOOL fRet = FALSE; //枚举系统已经安装的编码器 hr = pImagingFactory->GetInstalledEncoders(&uiCount, &codecs); //查找制定编码器的CLSID for (UINT i = 0; i < uiCount; i++) { if (strMimeType && !_tcscmp(strMimeType, codecs[i].MimeType)) { *pclsid = codecs[i].Clsid; fRet = TRUE; break; } } //释放内存 CoTaskMemFree(codecs); //返回 return fRet; } /* *函数介绍:将文件加载到内存流中 *入口参数:tszFilename:表示要打开的文件 *出口参数:ppStream : 表示内存流,将文件中的内容输出到此内存流中 *返回值:S_OK :表示成功,否则失败 */ HRESULT CreateStreamOnFile(const TCHAR * tszFilename, IStream ** ppStream) { HRESULT hrRet = S_FALSE; HGLOBAL hg = NULL; HANDLE hFile = NULL; DWORD dwSize, dwRead; BYTE* pbLocked = NULL; //打开文件 hFile = CreateFile(tszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == hFile) { goto END; } //得到文件大小 dwSize = GetFileSize(hFile, NULL); if (0xffffffff == dwSize) { goto END; } //分配内存 hg = GlobalAlloc(GMEM_MOVEABLE, dwSize); if (NULL == hg) { goto END; } //得到已经分配的内存指针 pbLocked = (BYTE*) GlobalLock(hg); if (NULL == pbLocked) { goto END; } //读取文件内容到内存中 if (!ReadFile(hFile, pbLocked, dwSize, &dwRead, NULL)) { goto END; } //解锁已经分配全局内存,对应GlobalLock(hg) GlobalUnlock(hg); //创建Stream对象 hrRet = CreateStreamOnHGlobal(hg, TRUE, ppStream); //关闭文件流 CloseHandle(hFile); return hrRet; //错误处理,并释放内存 END: if (pbLocked) GlobalUnlock(hg); if (hg) GlobalFree(hg); if (hFile) CloseHandle(hFile); return hrRet; } /* *解释:将图片转换为指定格式的图片 *参数: strInFileName [in] : 指定待转换的图象文件 strOutFileName [in] : 指定转换后的图象文件 strMimeType [in] : 指定转换后,图象文件的格式 TEXT("image/xxx") 如:(TEXT("image/bmp")) *返回值: void */ void ConvertImageFormat(LPCTSTR strInFileName,LPCTSTR strOutFileName,LPCTSTR strMimeType) { HRESULT hr; IImagingFactory * pImagingFactory = NULL ; //Image工厂接口对象 IStream *pStream = NULL; // 流接口对象 IImageSink *pImageSink = NULL; //Image Sink接口对象 IImageDecoder *pImageDecoder = NULL; //解码器接口对象 IImageEncoder *pImageEncoder = NULL; //编码器接口对象 CLSID clsidEncoder; //编码器CLSID //初始化COM环境 if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED))) { return; } //得到Image工厂接口对象 hr = CoCreateInstance(CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void**) &pImagingFactory); if (FAILED(hr)) { goto END; } //将文件内容加载到流中 if (FAILED(hr = CreateStreamOnFile(strInFileName, &pStream))) { goto END; } //根据编码器类型名称得到编码器CLSID if (!GetEnCodecCLSID(pImagingFactory,strMimeType, &clsidEncoder )) { goto END; } //创建编码器接口,并关联到输出文件中 if (FAILED(hr = pImagingFactory->CreateImageEncoderToFile(&clsidEncoder, strOutFileName, &pImageEncoder))) { goto END; } //创建解码器接口 if (FAILED(hr = pImagingFactory->CreateImageDecoder(pStream, DecoderInitFlagBuiltIn1st, &pImageDecoder))) { goto END; } //得到编码器接口的sink对象。此ImageSink接口作为一个槽或者管道来理解; //是用于负责pImageEncoder和pImageDecoder之间的传输 if (FAILED(hr = pImageEncoder->GetEncodeSink(&pImageSink))) { goto END; } //开始解码 if (FAILED(hr = pImageDecoder->BeginDecode(pImageSink, NULL))) { goto END; } //循环解码,直到结束 for(;;) { //解码 hr = pImageDecoder->Decode(); //继续解码后面的部分 if (E_PENDING == hr) { Sleep(500); } else if (FAILED(hr)) //失败 { //终止解码 pImageDecoder->EndDecode(hr); goto END; } else { //解码成功 break; } } //结束解码 pImageDecoder->EndDecode(hr); //释放pImageSink对象 pImageSink->Release(); pImageSink = NULL; //结束编码,此时就已经完成了文件格式的转换 pImageEncoder->TerminateEncoder(); END: //释放pStream对象 if (pStream) pStream->Release(); //释放pImageSink对象 if (pImageSink) pImageSink->Release(); //释放pImageDecoder对象 if (pImageDecoder) pImageDecoder->Release(); //释放pImageEncoder对象 if (pImageEncoder) pImageEncoder->Release(); //释放IImagingFactory接口对象 if (pImagingFactory) pImagingFactory->Release(); //释放程序占用的COM资源 CoUninitialize(); }