首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 平面设计 > 图形图像 >

wince5.0, eVC4.0上bmp到jpg格式转换,使用Imagefactory,两头都是Stream内存

2012-10-21 
wince5.0, eVC4.0下bmp到jpg格式转换,使用Imagefactory,两头都是Stream内存原先的编码太慢了,jpg编码要800

wince5.0, eVC4.0下bmp到jpg格式转换,使用Imagefactory,两头都是Stream内存

原先的编码太慢了,jpg编码要800ms,解码要1000ms,疯了。

于是开始用Imagefactory,经测试320x240的图片jpg编码67ms,解码38ms,太帅了,差距竟然这么大,经过的过程见:

http://topic.csdn.net/u/20121009/00/a4c385d9-62a4-48d7-ba03-a48495ecd068.html

代码如下:
将如下文件放到StdAfx.h中:

#include "StdAfx.h"#include "jpgimgfaclib.h"DEFINE_GUID(IID_IImagingFactory, 0x327abda7,0x072b,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);DEFINE_GUID(CLSID_ImagingFactory, 0x327abda8,0x072b,0x11d3,0x9d,0x7b,0x00,0x00,0xf8,0x1e,0xf3,0x2e);void ConvBmp2jpg(char *bmpbuf, int bmpsize, char *jpgbuf, int *jpgsize){HRESULT hr;IImagingFactory * pImagingFactory = NULL ; //Image工厂接口对象IStream *pStream = NULL;// 流接口对象IStream *pOutStream = NULL;// 流接口对象LARGE_INTEGER liTemp = {0};STATSTG stats={0};IImageSink *pImageSink = NULL; //Image Sink接口对象IImageDecoder *pImageDecoder = NULL;   //解码器接口对象IImageEncoder *pImageEncoder = NULL;//编码器接口对象CLSID clsidEncoder;  //编码器CLSIDTCHAR *tszMime = L"image/jpeg";   //指定转换后,图象文件的格式// tszMime = L"image/bmp";   //指定转换后,图象文件的格式//初始化COM环境if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED))){TRACE(L"COINIT_MULTITHREADED ERROR");return;}//得到Image工厂接口对象 hr = CoCreateInstance(CLSID_ImagingFactory,   NULL,   CLSCTX_INPROC_SERVER,   IID_IImagingFactory,   (void**) &pImagingFactory);if (FAILED(hr)){TRACE(L"IMAGE FACTORY CREATED ERROR");goto finish;}if (FAILED(hr = CreateStreamOnBuffer(bmpbuf, bmpsize, &pStream))){goto finish;}//根据编码器类型名称得到编码器CLSIDif (!GetEnCodecCLSID(pImagingFactory,tszMime, &clsidEncoder )){goto finish;}if (FAILED(hr = CreateStreamOnHGlobal(NULL,TRUE,&pOutStream))){goto finish;    }//创建编码器接口,并关联到输出流中if (FAILED(hr = pImagingFactory->CreateImageEncoderToStream(&clsidEncoder, pOutStream, &pImageEncoder))){goto finish;}//创建解码器接口if (FAILED(hr = pImagingFactory->CreateImageDecoder(pStream, DecoderInitFlagBuiltIn1st, &pImageDecoder))){goto finish;}//得到编码器接口的sink对象。此ImageSink接口作为一个槽或者管道来理解;//是用于负责pImageEncoder和pImageDecoder之间的传输if (FAILED(hr = pImageEncoder->GetEncodeSink(&pImageSink))){goto finish;}//开始解码if (FAILED(hr = pImageDecoder->BeginDecode(pImageSink, NULL))){goto finish;}//循环解码,直到结束for(;;){//解码hr = pImageDecoder->Decode();//继续解码后面的部分if (E_PENDING == hr){Sleep(500);}//失败else if (FAILED(hr)){//终止解码pImageDecoder->EndDecode(hr);goto finish;}else{//解码成功break;}}//结束解码pImageDecoder->EndDecode(hr);//释放pImageSink对象pImageSink->Release();pImageSink = NULL;//结束编码,此时就已经完成了文件格式的转换pImageEncoder->TerminateEncoder();pOutStream->Stat(&stats, 0);*jpgsize = (int)stats.cbSize.QuadPart;pOutStream->Seek(liTemp, STREAM_SEEK_SET, NULL);pOutStream->Read(jpgbuf, (unsigned long)stats.cbSize.QuadPart, NULL);finish:        //释放pStream对象    if (pStream)        pStream->Release();if (pOutStream)        pOutStream->Release();        //释放pImageSink对象    if (pImageSink)        pImageSink->Release();//释放pImageDecoder对象    if (pImageDecoder)        pImageDecoder->Release();//释放pImageEncoder对象    if (pImageEncoder)        pImageEncoder->Release();//释放IImagingFactory接口对象    if (pImagingFactory)        pImagingFactory->Release();//释放程序占用的COM资源    CoUninitialize();}//虽然是到Stream,但转换出来是完整的图像文件,可能需要用完整的图像文件获取图像参数之类的void ConvJpg2bmp(char *jpgbuf, int jpgsize, char *bmpbuf, int *bmpsize){HRESULT hr;IImagingFactory * pImagingFactory = NULL ; //Image工厂接口对象IStream *pStream = NULL;// 流接口对象IStream *pOutStream = NULL;// 流接口对象LARGE_INTEGER liTemp = {0};STATSTG stats={0};IImageSink *pImageSink = NULL; //Image Sink接口对象IImageDecoder *pImageDecoder = NULL;   //解码器接口对象IImageEncoder *pImageEncoder = NULL;//编码器接口对象CLSID clsidEncoder;  //编码器CLSIDTCHAR *tszMime = L"image/bmp";   //指定转换后,图象文件的格式// tszInFileName = L"\\1.jpg";  //指定待转换的图象文件// tszOutFileName = L"\\11.bmp"; //指定转换后的图象文件// tszMime = L"image/bmp";   //指定转换后,图象文件的格式//初始化COM环境if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED))){TRACE(L"COINIT_MULTITHREADED ERROR");return;}//得到Image工厂接口对象 hr = CoCreateInstance(CLSID_ImagingFactory,   NULL,   CLSCTX_INPROC_SERVER,   IID_IImagingFactory,   (void**) &pImagingFactory);if (FAILED(hr)){TRACE(L"IMAGE FACTORY CREATED ERROR");goto finish;}if (FAILED(hr = CreateStreamOnBuffer(jpgbuf, jpgsize, &pStream))){goto finish;}//根据编码器类型名称得到编码器CLSIDif (!GetEnCodecCLSID(pImagingFactory,tszMime, &clsidEncoder )){goto finish;}if (FAILED(hr = CreateStreamOnHGlobal(NULL,TRUE,&pOutStream))){goto finish;    }//创建编码器接口,并关联到输出流中if (FAILED(hr = pImagingFactory->CreateImageEncoderToStream(&clsidEncoder, pOutStream, &pImageEncoder))){goto finish;}//创建解码器接口if (FAILED(hr = pImagingFactory->CreateImageDecoder(pStream, DecoderInitFlagBuiltIn1st, &pImageDecoder))){goto finish;}//得到编码器接口的sink对象。此ImageSink接口作为一个槽或者管道来理解;//是用于负责pImageEncoder和pImageDecoder之间的传输if (FAILED(hr = pImageEncoder->GetEncodeSink(&pImageSink))){goto finish;}//开始解码if (FAILED(hr = pImageDecoder->BeginDecode(pImageSink, NULL))){goto finish;}//循环解码,直到结束for(;;){//解码hr = pImageDecoder->Decode();//继续解码后面的部分if (E_PENDING == hr){Sleep(500);}//失败else if (FAILED(hr)){//终止解码pImageDecoder->EndDecode(hr);goto finish;}else{//解码成功break;}}//结束解码pImageDecoder->EndDecode(hr);//释放pImageSink对象pImageSink->Release();pImageSink = NULL;//结束编码,此时就已经完成了文件格式的转换pImageEncoder->TerminateEncoder();pOutStream->Stat(&stats, 0);*bmpsize = (int)stats.cbSize.QuadPart;pOutStream->Seek(liTemp, STREAM_SEEK_SET, NULL);pOutStream->Read(bmpbuf, (unsigned long)stats.cbSize.QuadPart, NULL);finish:        //释放pStream对象    if (pStream)        pStream->Release();if (pOutStream)        pOutStream->Release();        //释放pImageSink对象    if (pImageSink)        pImageSink->Release();//释放pImageDecoder对象    if (pImageDecoder)        pImageDecoder->Release();//释放pImageEncoder对象    if (pImageEncoder)        pImageEncoder->Release();//释放IImagingFactory接口对象    if (pImagingFactory)        pImagingFactory->Release();//释放程序占用的COM资源    CoUninitialize();}/**函数介绍:将文件加载到内存流中*入口参数:pBuffer:表示要打开的文件*出口参数: ppStream : 表示内存流,将文件中的内容输出到此内存流中*返回值:S_OK :表示成功,否则失败*/BOOL CreateStreamOnBuffer(const char * pBuffer, DWORD bufsize, IStream ** ppStream){    HGLOBAL hg = NULL;    BYTE* pbLocked = NULL;    //分配内存    hg = GlobalAlloc(GMEM_MOVEABLE, bufsize);    if (NULL == hg)    {        goto error;    }    //得到已经分配的内存指针    pbLocked = (BYTE*) GlobalLock(hg);    if (NULL == pbLocked)    {        goto error;    }    //读取文件内容到内存中memcpy(pbLocked, pBuffer, bufsize);//解锁已经分配全局内存,对应GlobalLock(hg)    GlobalUnlock(hg);    //创建Stream对象    CreateStreamOnHGlobal(hg, TRUE, ppStream);    return TRUE;error: //错误处理,并释放内存    if (pbLocked)        GlobalUnlock(hg);    if (hg)        GlobalFree(hg);    return TRUE;}/**函数介绍:根据编码器类型名称,得到指定的编码器CLSID*入口参数:pImagingFactory: Image工厂接口对象           wszMimeType : Image编码格式名称  *出口参数:pclsid :编码器的CLSID*返回值:TRUE : 成功; FALSE: 失败*/BOOL GetEnCodecCLSID(IImagingFactory* pImagingFactory,WCHAR * wszMimeType ,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 (wszMimeType && !wcscmp(wszMimeType, codecs[i].MimeType))        {            *pclsid = codecs[i].Clsid;            fRet = TRUE;            break;        }    }//释放内存    CoTaskMemFree(codecs);//    return fRet;}



热点排行