因为最近涉及将大的jpg缩小后再在网络上传输,所以需要将大的jpg转小的JPG。首先用Opencv将jpg读取到内存,缩小后,保存为bmp,再将bmp转JPG。如果直接是bmp文件也可以的。7万张图片从枚举到转换保存一共使用了半个小时。内存无泄露。

读取文件数据后创建IStream对象,再调用IStream类方法read将JPG数据以二进制流读取出来。

使用GetImageEncodersSize之前一定要初始化GDIplus。最好在函数里面

ULONG_PTR gdiplusToken;

Gdiplus::GdiplusStartupInput gdiplusStartupInput;

Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

退出的时候记得

Gdiplus::GdiplusShutdown(gdiplusToken);

1.添加GDI头文件

[cpp] view plaincopy
  1. #include < Gdiplus.h>
  2. #pragma comment(lib, "Gdiplus.lib")
  3. using namespace Gdiplus;
[cpp] view plaincopy
  1. #include <Objbase.h>
  2. #include <Objidl.h>
  3. #pragma comment(lib, "Ole32.lib")
  4. #pragma comment(lib, "Uuid.lib")

2.定义两个公共函数:

[cpp] view plaincopy
  1. INT GetEncoderClsid(const WCHAR *format, CLSID *pClsid)
  2. {
  3. UINT  num = 0;          // number of image encoders
  4. UINT  size = 0;         // size of the image encoder array in bytes
  5. ImageCodecInfo* pImageCodecInfo = NULL;
  6. GetImageEncodersSize(&num, &size);
  7. if (size == 0){
  8. return -1;  // Failure
  9. }
  10. pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
  11. if (pImageCodecInfo == NULL){
  12. return -1;  // Failure
  13. }
  14. GetImageEncoders(num, size, pImageCodecInfo);
  15. for (UINT j = 0; j < num; ++j){
  16. if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0){
  17. *pClsid = pImageCodecInfo[j].Clsid;
  18. free(pImageCodecInfo);
  19. return j;  // Success
  20. }
  21. }
  22. free(pImageCodecInfo);
  23. return -1;  // Failure
  24. }
int n = 0;
void WriteJPGFile(BYTE *pData, DWORD dwLen)
{WCHAR wcPath[MAX_PATH] = {0};wsprintf(wcPath, L"F:\\test\\%d.jpg", ++n);HANDLE hFile = CreateFile(wcPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile != INVALID_HANDLE_VALUE){DWORD dwWrite = 0;WriteFile(hFile, pData, dwLen, &dwWrite, NULL);CloseHandle(hFile);}
}

这个函数是将ipl缩小到指定宽高的上限。

void ResizeImage(IplImage **ipl, int nWidth, int nHeight)
{if (*ipl){while ((*ipl)->width >= nWidth || (*ipl)->height >= nHeight){DWORD dwWidth = (*ipl)->width / 2;DWORD dwHeight = (*ipl)->height / 2;IplImage* iplResize = cvCreateImage(cvSize(dwWidth, dwHeight), 8, 3);if (iplResize){cvResize((*ipl), iplResize);cvReleaseImage(&(*ipl));(*ipl) = cvCloneImage(iplResize);cvReleaseImage(&iplResize);}}}
}

转换函数:

Bitmap* IplImage2Bitmap(IplImage* pIplImg)
{if (!pIplImg){return NULL;}Gdiplus::Bitmap *pBitmap = ::new Gdiplus::Bitmap((int)pIplImg->width, (int)pIplImg->height, PixelFormat24bppRGB);if (!pBitmap){return NULL;}BitmapData bmpData;Rect rect(0, 0, pIplImg->width, pIplImg->height);pBitmap->LockBits(&rect, ImageLockModeWrite, PixelFormat24bppRGB, &bmpData);BYTE *pByte = (BYTE*)bmpData.Scan0;if (pIplImg->widthStep == bmpData.Stride){memcpy(bmpData.Scan0, pIplImg->imageDataOrigin, pIplImg->imageSize);}pBitmap->UnlockBits(&bmpData);return pBitmap;
}
void bmp2jpg(char cPath[MAX_PATH])
{IplImage *ipl = cvLoadImage(cPath);if (ipl){ResizeImage(&ipl, 300, 300);CLSID codecClsid;GetEncoderClsid(L"image/jpeg", &codecClsid);int iQuality = 100;EncoderParameters encoderParameters;encoderParameters.Count = 1;encoderParameters.Parameter[0].Guid = EncoderQuality;encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;encoderParameters.Parameter[0].NumberOfValues = 1;encoderParameters.Parameter[0].Value = &iQuality;Bitmap*pBitmap = IplImage2Bitmap(ipl);if (pBitmap){IStorage* pIStorage = NULL;IStream* pJPGStream = NULL;HRESULT hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);if (SUCCEEDED(hr)){hr = pIStorage->CreateStream(L"StreamImage2", STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pJPGStream);DWORD dwErr = GetLastError();if (SUCCEEDED(hr)){Status bStatus = pBitmap->Save(pJPGStream, &codecClsid);//将bmp转jpg后保存在内存中//Status bStatus = pImage.Save(L"f:\\1.jpg", &codecClsid);//如果是保存为文件则把注释去掉BYTE * pJPGData = NULL;while (!pJPGData){try{pJPGData = new BYTE[1024 * 1024];}catch (...){}}memset(pJPGData, 0, 1024 * 1024);LARGE_INTEGER move;move.QuadPart = 0;pJPGStream->Seek(move, STREAM_SEEK_SET, NULL);//定位到流的起始位置DWORD dwRead = 0;hr = pJPGStream->Read(pJPGData, 1024 * 1024, &dwRead);//在read之前必须seek。否则读取不出来数据WriteJPGFile(pJPGData, dwRead);delete[] pJPGData;}}// Get the class identifier for the JPEG encoder.if (pJPGStream){pJPGStream->Release();}if (pIStorage){pIStorage->Release();}::delete pBitmap;}else{OutputDebugString(L"图片转换失败");}cvReleaseImage(&ipl);}else{OutputDebugStringA(cPath);}
}

调用函数:

void CIplimageToBmpDlg::OnBnClickedButton1()
{WCHAR wcModule[MAX_PATH * 2] = { 0 };GetModuleFileName(NULL, wcModule, MAX_PATH * 2);::PathRemoveFileSpec(wcModule);if (::PathFileExistsW(wcModule)){wsprintf(wcModule + wcslen(wcModule), L"\\AD\\7万Bmp\\*.*");WIN32_FIND_DATAW FindFileData;HANDLE hFind = FindFirstFileW(wcModule, &FindFileData);if (hFind == INVALID_HANDLE_VALUE){return;}else{int nMAX_Ad_Pictures = 0;while (FindNextFileW(hFind, &FindFileData) != 0){WCHAR *p = PathFindExtension(FindFileData.cFileName);if (p){if (_wcsicmp(p, L".bmp") == 0 || _wcsicmp(p, L".jpg") == 0 || _wcsicmp(p, L".png") == 0){char cPath[MAX_PATH] = { 0 };WCHAR wcFilePath[MAX_PATH * 2] = { 0 };GetModuleFileName(NULL, wcFilePath, MAX_PATH * 2);::PathRemoveFileSpec(wcFilePath);wsprintf(wcFilePath + wcslen(wcFilePath), L"\\AD\\7万Bmp\\%s", FindFileData.cFileName);WideCharToMultiByte(CP_ACP, 0, wcFilePath, MAX_PATH, cPath, MAX_PATH, NULL, NULL);bmp2jpg(cPath);/*//将jpg转bmpwsprintf(wcFilePath + wcslen(wcFilePath), L"\\AD\\7万Bmp\\%s", FindFileData.cFileName);WideCharToMultiByte(CP_ACP, 0, wcFilePath, MAX_PATH, cPath, MAX_PATH, NULL, NULL);IplImage *ipl = cvLoadImage(cPath);if (ipl){char cPathPic[MAX_PATH] = {0};sprintf_s(cPathPic, "f:\\test\\%d.bmp", ++n);cvSaveImage(cPathPic, ipl);cvReleaseImage(&ipl);}*/}}}}// 查找结束FindClose(hFind);}AfxMessageBox(L"操作完成");
}

图片路径及图片都删除了
demo下载地址:http://download.csdn.net/detail/sz76211822/9819193

C++ BMP转JPG方法三相关推荐

  1. boostrap 鼠标滚轮滑动图片_BootStrap 轮播插件(carousel)支持左右手势滑动的方法(三种)...

    Bootstrap 轮播(Carousel)插件是一种灵活的响应式的向站点添加滑块的方式.除此之外,内容也是足够灵活的,可以是图像.内嵌框架.视频或者其他您想要放置的任何类型的内容. 因为最近开发的项 ...

  2. Flash Builder4.7极其简单破解方法-三步搞定(亲测)

    资讯类型: 转载 来源页面: http://weibo.com/2101024913/yvmR0D9Df 资讯原标题: 资讯原作者: 丿卓越丶星辰 翻译词数: 词 我的评论: 对这篇文你有啥看法,跟贴 ...

  3. python类的方法三种访问权_Python基础33-面向对象(继承资源(属性与方法)的使用注意)...

    在Python中, 继承是指子类对父类资源的使用权 1 继承-属性与方法的使用权限 1.1 测试属性与方法分别如下 公有属性/方法 受保护属性/方法 私有属性/方法 class Animal: a = ...

  4. 垂直居中重要方法理解---重点是方法三

    方法一 这个方法把一些 div 的显示方式设置为表格,因此我们可以使用表格的 vertical-align property 属性. <div id="wrapper"> ...

  5. 10038 mysql,关于MySql 10038错误的完美解决方法(三种)

    第一种方法: 第一步: 先看报错窗口 2003 can't connect to MySQL server on '127.0.0.1'(10038). 第二步: 原因是:远程3306端口未对外开放操 ...

  6. FPGA复位激励编写(方法三)

    1.1 FPGA复位激励编写(方法三) 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)FPGA复位激励编写(方法三): 5)结束语. 1.1.2 本节引言 " ...

  7. FPGA时钟激励编写(方法三)

    1.1 FPGA时钟激励编写(方法三) 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)FPGA时钟激励编写(方法三) 5)结束语. 1.1.2 本节引言 "不 ...

  8. mysql 2003 10038_关于MySql10038错误的完美解决方法(三种)

    第一种方法: 第一步: 先看报错窗口 2003 can't connect to MySQL server on '127.0.0.1'(10038). 第二步: 原因是:远程3306端口未对外开放操 ...

  9. Maven 无法下载依赖包的解决方法---三步dao!!!

    Maven 无法下载依赖包的解决方法---三步dao!!! 参考文章: (1)Maven 无法下载依赖包的解决方法---三步dao!!! (2)https://www.cnblogs.com/WLCY ...

  10. 通俗易懂的Monte Carlo的积分方法(三)

    通俗易懂的Monte Carlo的积分方法(三) 考虑曾经在参加MCM时的一个多重积分的计算难题 ∫∫D(H−z(x,y))21+zx2+zy2dσ\int\int_{D}(H-z(x,y))^2\s ...

最新文章

  1. 论如何优雅地进行工作安排
  2. 云栖大会变迁史(2009-2017)
  3. Python:if判断与while、for循环语句
  4. 无监督学习和半监督学习
  5. php 判断两个数组差集,php array_udiff_assoc 计算两个数组的差集实例
  6. python在工厂中的运用_在python中使用元类实现工厂设计模式
  7. 手机上网流量统计_数据统计 | 上半年手机流量同比增110.2%,你贡献了多少?
  8. mysql导入的excel更新_excel导入数据库,存在则更新不存在添加
  9. __attribute__((weak)):弱引用,可以不实现
  10. Tomcat学习总结(17)—— Tomcat生产环境中域名访问和连接MySQL
  11. struts环境搭建以及登陆功能的书写
  12. Kotlint集合简单总结
  13. 成都信息工程大学 809 软件工程导论简答题必背
  14. libcef-框架架构中概念介绍-命令行参数-元素布局-应用程序结构(二)
  15. Jenkins:安装出现“该jenkins实例似乎已离线”问题解决
  16. js 浏览器永久保存数据:localStorage
  17. Python办公自动化之文件读写操作与Excel,csv,PDF文件
  18. 抽取word中的背景图
  19. 菜狗杯Web签到wp
  20. mysql 最大值65536_SQL server事物复制报错:要复制的 LOB 数据的长度(xxxxx)超出了配置的最大值 65536...

热门文章

  1. 探究CSS3中的transition和transform属性方法使用
  2. asp.net md5加密
  3. plsql报错:Not logged on
  4. 计算机文档我的文档丢失,我的文档不见了怎么办?我的文档图标不见了找回方案...
  5. wordpress企业主题安装
  6. 浙大何越扬计算机系2 2,浙江大学第十一届大学生数学建模竞赛获奖名单.doc
  7. 圣丹斯电影节2019:讲故事,不断发展。
  8. 如何 自定义starter?
  9. strtok函数详解
  10. mysql创建表插入随机数_插入随机数到MySQL数据库