求问:程序解决图片合成和改变大小问题 有三张大小一样的bmp图片,我想让这三张图片合拼成一张图片,然后改变大小保存下来,转换成jpg,请问有什么方法?要程序里能用的,目的是达到自动处理,因为需要处理的图片比较多,每天都有。如果有命令行能用的工具也可以,我程序里直接调用他。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 用GDI+,非常方便通过Image直接读取BMP文件创建另一个大小为3倍的Image,在把BMP画到上面,保存就行了 以下是用GDI+写的int GetEncoderClsid(LPCWSTR format, CLSID* pClsid) { UINT num = 0; UINT size = 0; ImageCodecInfo* pImageCodecInfo = NULL; GetImageEncodersSize(&num, &size); if(size == 0) return -1; pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); if(pImageCodecInfo == NULL) return -1; GetImageEncoders(num, size, pImageCodecInfo); for(UINT j = 0; j < num; ++j) { if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) { *pClsid = pImageCodecInfo[j].Clsid; free(pImageCodecInfo); return j; } } free(pImageCodecInfo); return -1; } void CDlgToolBar::OnButton1() { // TODO: Add your control notification handler code here Bitmap bmp1(L"C:\\aa.bmp"); Bitmap bmp2(L"C:\\bb.bmp"); Bitmap bmp3(L"C:\\cc.bmp"); Bitmap bmpDes(100, 100 * 3); Graphics g(&bmpDes); g.DrawImage(&bmp1, 0, 0); g.DrawImage(&bmp2, 0, 100); g.DrawImage(&bmp3, 0, 200); CLSID encoderClsid; GetEncoderClsid(L"image/jpeg", &encoderClsid); bmpDes.Save(L"C:\\dd.bmp", &encoderClsid);} 另外:在VC中使用GDI+[转] 色彩鲜艳漂亮的高品质图像,一个个形象生动的Windows图标,高速运动、活灵活现的三维动画,这些无一不显示出程序设计者的艺术才华。在程序设计中,图像处理已经成为每个程序员的必修课。 在VC中编程显示一幅位图,下列步骤是不可缺少的: 装入位图、获得位图的大小信息、启用设备环境、位传输等,所需的程序代码一般比较冗长而且复杂。如果想将装入的位图另存为其他格式的图像文件,代码就更长了。这一切都是因为GDI本身的局限性造成的。 GDI+技术 随着Windows 2000的推出,上述情况有了极大的改观: 程序员不必了解每种图像格式的具体含义,照样可以写出多格式图像浏览或转换程序,这一切全都依赖于Windows 2000及后继版中所使用的GDI+技术。 和传统的GDI不同,GDI+中引入了对COM(组件对象模型)技术的支持,通过COM技术,GDI+简化了对图像文件的访问(打开、保存)。它是通过调用COM组件来实现的,GDI+扮演的只是指挥者,而非操作员。对于图像文件,GDI+所关心的不是图像文件的文件头信息,不论要打开的文件格式是什么类型,GDI+首先要做的是在注册表中查看该图像格式的编码(或解码)信息是否已经注册(HKEY_CLASSES_ROOT\MIME\Database\Content Type)。如果已经注册,就通过该编码信息调用COM组件,就这么简单。这种技术早就在微软的其他软件中使用了(如IE)。“体验”过Nimda病毒的朋友可能对“audio/wav”这段代码并不陌生,Nimda就是靠它来伪装自己的:让IE认为附件是WAV文件而自动打开可执行程序,这其实也是IE使用COM技术的一个突出表现。 配合GDI+的推出,微软也同时发布了相应的SDK,如果已经安装了最新的Microsoft PlatForm SDK或已经开始使用VS.NET,GDI+的SDK就已经在系统中了。如果没有的话,可以到http: //noner.top263.net/progtool上去下载GDI+的头文件和库文件。有了GDI+之后,只需简单地创建一个图形对象(Graphics object),然后直接调用该对象的方法(methods)进行绘图即可。图形对象是GDI+中的核心,正如DC之于GDI那样。图形对象和DC有许多相似的地方,在使用上遵循着相同的使用规则,但是两者在本质上已经有很大的区别。一个是基于句柄的GDI,一个是基于组件对象模型的GDI+。使用GDI+的SDK编程,必须按照下面的规范来进行:使用GDI+的命名空间(namespace Gdiplus),在使用GDI+函数时必须进行GDI+的初始化,使用完毕要销毁GDI+,这些规范在下面所列的程序中有详细的说明。 访问注册表编码信息 上面说到GDI+是通过在注册表中查看编码信息来访问图像文件的,在GDI+的SDK中,编码信息是存储在 ImageCodecInfo类中的,在这个类中,有编码的CLSID(COM组件的GUID标识码)、编码方式描述等。对于GDI,在注册表中访问编码信息通常使用以下两个函数来实现: 1. 查看系统中可用的图像编码信息(数量及大小) Status GetImageEncodersSize( UINT* numEncoders, //存储编码器数量的地址 UINT* size //存储编码信息所需内存大小 ); 2. 得到所有的编码信息 Status GetImageEncoders( UINT numEncoders,//可用编码器数量 UINT size,//存储编码器信息所需内存(由ImageCodecInfo类组成的数组的大小) ImageCodecInfo* encoders//编码器信息指针 ); 在GetImageEncoders函数中,参数numEncoders和size都是由GetImageEncodersSize返回的。下面的代码在注册表中查找具体格式图像的编码方式: int GetImageCLSID(const WCHAR* format, CLSID* pCLSID) { //得到格式为format的图像文件的编码值,访问该格式图像的COM组件的GUID值保存在pCLSID中 UINT num = 0; UINT size = 0; ImageCodecInfo* pImageCodecInfo = NULL; GetImageEncodersSize(&num, &size); if(size == 0) return FALSE; // 编码信息不可用 //分配内存 pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); if(pImageCodecInfo == NULL) return FALSE; // 分配失败 //获得系统中可用的编码方式的所有信息 GetImageEncoders(num, size, pImageCodecInfo); //在可用编码信息中查找format格式是否被支持 for(UINT i = 0; i < num; ++i) { //MimeType:编码方式的具体描述 if( wcscmp(pImageCodecInfo[i] .MimeType, format) == 0 ) { *pCLSID = pImageCodecInfo[i] .Clsid; free(pImageCodecInfo); return TRUE; } } free(pImageCodecInfo); return FALSE; } 实现多格式的图像浏览和转换 有了前面的知识,实现多格式的图像的浏览与转换就不是什么难事了。 1.在VC中创建一个SDI项目ImageShow,对GDI+声明和初始化及销毁进行代码编制,具体代码如下: #include “Gdiplus.h” using namespace Gdiplus; CImageShowView::CImageShowView() { //初始化GDI+ GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); } CImageShowView::~CImageShowView() { //销毁GDI+ ULONG_PTR gdiplusToken; GdiplusShutdown(gdiplusToken); } 2. 通过类向导(Class Wizard),重载“文件”菜单中的“打开”和“另存为”两项。为了编程的简单,本程序只将当前打开的图像文件直接存为BMP文件(实际上保存为其他格式的文件也很简单,只不过是对文件名进行分析而已)。另外,为了在打开和保存文件时进行文件名的传递,还应在CImageShowView类中加入一全局变量“CString strOpenFileName”。“打开”和“另存为”两菜单的对应代码如下: WCHAR* ToWChar(char * str) { //在GDI+中,有关字符的参数类型全部都是WCHAR类型 //该函数是将传统字符串进行转换 static WCHAR buffer[1024]; wcsset(buffer,0); MultiByteToWideChar(CP_ACP,0,str,strlen(str),buffer,1024); return buffer; } void CImageShowView::OnFileOpen() { //本程序能够打开各类常见格式的图像文件 static char szFilter[]=“常见格式图像文件(*.*)|*.*|”; CFileDialog dlgChoseImage(1,NULL,NULL,NULL,szFilter); if(dlgChoseImage.DoModal()==IDOK) { strOpenFileName=dlgChoseImage .GetPathName(); //打开文件后立即在窗口中显示(重绘客户窗口) this->Invalidate(); } } void CImageShowView::OnFileSaveAs() { if(strOpenFileName.IsEmpty()) { AfxMessageBox(“当前没有打开图像文件,不能进行保存!”); return; } //建立图形对象 Graphics graphics(GetDC()->m_hDC); //装入当前已经打开的图像文件 Image image(ToWChar(strOpenFileName.GetBuffer(strOpenFileName.GetLength()))); CString strFileSave; //将其他格式的图像全部另存为BMP文件 static char szFilter[]=“位图(*.BMP)|*.BMP|”; CFileDialog dlgChoseImage(0,“BMP”,NULL,NULL,szFilter); if(dlgChoseImage.DoModal()==IDOK) { strFileSave=dlgChoseImage.GetPathName(); CLSID clsid; if(GetImageCLSID(L“image/bmp”,&clsid)) { image.Save(ToWChar(strFileSave.GetBuffer(strFileSave.GetLength())), &clsid, NULL); //将保存后的图像进行显示 strOpenFileName=strFileSave; this->Invalidate(); } } } 3.为了浏览图像转换前后的效果,还应该在窗口中分别绘制转换前后的图像,这需要在OnDraw函数中添加绘制代码,如下所示: void CImageShowView::OnDraw(CDC* pDC) { CImageShowDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //如果没有选择显示图像文件,则不用重绘 if(strOpenFileName.IsEmpty()) return; //显示当前打开的图像文件的全名 this->GetParent()->SetWindowText(strOpenFileName); //建立图像对象 Graphics graphics(pDC->m_hDC); //装入图形文件 Image image(ToWChar(strOpenFileName.GetBuffer(strOpenFileName.GetLength()))); Point destPoints[3] = { Point(0, 0), Point(image.GetWidth(), 0), Point(0, image.GetHeight()) }; Point* pdestPoints = destPoints; //在指定区域pdestPoints显示图像 graphics.DrawImage(&image, pdestPoints, 3); } 在编译上面的程序之前,应该将Gdiplus.lib文件连编到项目中去,否则将会出现“LINK 2001”编译错误。上述程序在Visual Studio 6.0、Windows 2000/XP下调试通过,它能够显示或转换的图像格式有BMP、GIF、JPEG、Exif、PNG、TIFF、ICON、WMF、EMF等等。需要说明的是,本文只就GDI+编程的基本原理进行了阐述,事实上,GDI+的应用远不止此。 金山卫士开源项目中有类RichEdit的文本控件吗? web使用Activex控件,控件读取配置文件的问题 我写了一堆画圆和填充的代码 但是报错说什么不需要三个 教教我那 谢谢 IFilter类的使用 关于网络的几个疑问 如何将Resource中添加的Control与对应的MFC类对象关联? 如何在VC程序中调用console程序? 单文档框架中的dialogbar如何使用 怎样求解一个组合问题?急!急!急! 我想在我的程序中得到IE光标所在条目的文本,请大虾指条明路! 刚刚学VC++ ADO连接数据库不断打开表(不读)有内存泄漏
{
UINT num = 0;
UINT size = 0;
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if(size == 0)
return -1;
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1;
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j = 0; j < num; ++j)
{
if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;
}
}
free(pImageCodecInfo);
return -1;
} void CDlgToolBar::OnButton1()
{
// TODO: Add your control notification handler code here
Bitmap bmp1(L"C:\\aa.bmp");
Bitmap bmp2(L"C:\\bb.bmp");
Bitmap bmp3(L"C:\\cc.bmp");
Bitmap bmpDes(100, 100 * 3);
Graphics g(&bmpDes);
g.DrawImage(&bmp1, 0, 0);
g.DrawImage(&bmp2, 0, 100);
g.DrawImage(&bmp3, 0, 200);
CLSID encoderClsid;
GetEncoderClsid(L"image/jpeg", &encoderClsid); bmpDes.Save(L"C:\\dd.bmp", &encoderClsid);
}