最近一直在更新Qt框架下的内容,这两天来总结下对MFC框架下的使用吧,上一章节介绍了QT框架下的图片功能,那么今天就继续来讲述下图片功能,在MFC框架下是如何实现加密图片的操作的。
在实际的工作中,如果你所做的产品主要是针对教学系列的,那么在软件使用过程中,对图片视频以及文档的资料保密性肯定要强一些,今天就来举例简单的例子吧,如何加载一张加密图片,并展示出来吧~
开发环境:vs2010
既然要用MFC框架,咱们就从低版本的开始吧,毕竟高版本是兼容低版本的,不过也不能再低了,VC6.0咱肯定是不会用的~
无论是什么环境下,加载图片的过程无外乎是这种流程:
1:加载图片路径
2:使用对应的图片类进行转换
3:将转换后的类附着到显示位置
当前,对于加密图片来说也是同样的道理。
为了简单实现这里的图片打开类采用了CImage
该类提供增强的位图支持,包括加载和保存采用JPEG、GIF、BMP和可移植网络图形格式的图像(PNG)格式。
但是,在这里CImage有一个缺点,如果加载的图片与给定的位置不一致时,就会造成失真,真是一个很严重的问题。
如果想要实现特别炫酷的图片展示以及页面风格,可以采用GDI的方式,这里就不再过多说明,改天详细来讲解GDI如何加载图片吧!
1:打开指定的文件,并判断是否图片有效
2:对指定图片进行解密操作
3:将二进制图片流转成CImage可识别的IStream流
4:读取的图片流映加载到CImage类中
5:释放流操作
6:图片展示
看着加载步骤很多,实际上操作起来不是很难,最难的步骤在于第三步,也是加载核心,有需要的可以小本本记录下哟~
这里的打开文件并没有做任何的实际处理,只是为了判断该路径是否存在。
C++加载文件,或者是判断文件有效的方法很多,假设,我们这里使用CFile的方式为例子:
CFile file;
if (file.Open(strFilename , CFile::modeRead) == FALSE)
{
file.Close();
VERIFY(!strFilename);
return NULL;
}
else
file.Close();
其实,我倒不是很喜欢用这种方式,每次还得打开文件,再关闭文件,在实际判断的时候我会采用:_access方式判断的。
加解密类叫做:CArithmeticBase pBase;
具体的加解密方式不做过多说明
int nFileLen = 0;
unsigned char* fileInfo;
m_base.decodeFile(strFilename , L"" , nFileLen , fileInfo);
解密操作后,可以获取到图片文件的大小以及流信息,这里的二进制流采用了unsigned char*存储。
到了功能核心的部分啦!
在CImage类中,接收的流只能是IStream,那么该如何将unsigned char*类型的二进制流转换成CImage可识别的流信息呢?
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE ,nFileLen);
在分配内容的时候,一般都采用GMEM_MOVEABLE可移动方式。比如说当堆中有很多一小块一小块的内存时,当再申请一块比较大的内存时,操作系统就会移动带有GMEM_MOVEABLE标识的内容合并出一块大内存出来。
所以,在使用具有GMEM_MOVEABLE标识的内存时,不能用内存地址做标识,而是要用返回的句柄做标识,这一点非常重要,否则崩溃了,你可就找错误吧!
void *pData = GlobalLock(hGlobal);
memcpy(pData , fileInfo , nFileLen);
GlobalUnlock(hGlobal);
唯一需要注意的是:上锁后一定要解锁,这是使用C++比较麻烦的地方。
IStream *pStream = NULL;
if (CreateStreamOnHGlobal(hGlobal , TRUE , &pStream) == S_OK)
{
//流加载成功
}
else
{
//加载失败
}
只有第三步正确加载流对象之后,才能将流对象加载到CImage中。
image.Load(pStream);
加载流信息后,将CImage返回给外部调用地方,在这里可以使用&的方式将CImage对象返回出去。
无论是否加载成功,只要在内存中创建了流对象,就必须要在最后进行销毁,以及内存的销毁。
pStream->Release();
GlobalFree(hGlobal);
到这一步就已经将加密的图片资源变成了程序可识别的CImage类,假设我们在onpaint中加载图片资源
m_Image.Draw(pDC->GetSafeHdc(),rect);
到这里,一个完整的加密图片流程已经实现完成了。
对于这一部分图片加载来说,功能不难,CImage::load方式可以直接加载图片,难点就在于加密图片,读取文件的时候不再是任何图片格式,不再是简单的加载路径的方式,而是采用字符流的方式,这里涉及到了内存分配以及加锁解密等底层操作。
当我们看到代码的时候就会觉得,原来是这么简单,实际上难的如何将二进制流转换成可识别的流信息。
我是糯诺诺米团,一名C++开发程序媛~