⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dibapi.cpp

📁 vc++编写的图片验证系统 vc++编写的图片验证系统
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	
	// 中间变量
	BYTE	bChar;
	
	// 指向源图像像素的指针
	BYTE *	lpSrc;
	
	// 指向编码后图像数据的指针
	BYTE *	lpDst;
	
	// 临时指针
	BYTE *	lpTemp;
	
	// 尝试读取PCX文件头
	if (file.Read((LPSTR)&pcxHdr, sizeof(PCXHEADER)) != sizeof(PCXHEADER))
	{
		// 大小不对,返回NULL。
		return NULL;
	}
	
	// 判断是否是256色PCX文件,检查第一个字节是否是0x0A
	if ((pcxHdr.bManufacturer != 0x0A) || (pcxHdr.bBpp != 8) || (pcxHdr.bPlanes != 1))
	{
		// 非256色PCX文件,返回NULL。
		return NULL;
	}
	
	// 获取图像高度
	wHeight = pcxHdr.wBottom - pcxHdr.wTop + 1;
	
	// 获取图像宽度
	wWidth  = pcxHdr.wRight - pcxHdr.wLeft + 1;
	
	// 计算图像每行的字节数
	lLineBytes = WIDTHBYTES(wWidth * 8);
	
	// 计算DIB长度(字节)
	dwDIBSize = sizeof(BITMAPINFOHEADER) + 1024 + wHeight * lLineBytes;
	
	// 为DIB分配内存
	hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIBSize);
	if (hDIB == 0)
	{
		// 内存分配失败,返回NULL
		return NULL;
	}
	
	// 锁定
	pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
	
	// 指向BITMAPINFOHEADER的指针
	LPBITMAPINFOHEADER lpBI;
	
	// 赋值
	lpBI = (LPBITMAPINFOHEADER) pDIB;
	
	// 给lpBI成员赋值
	lpBI->biSize = 40;
	lpBI->biWidth = wWidth;
	lpBI->biHeight = wHeight;
	lpBI->biPlanes = 1;
	lpBI->biBitCount = 8;
	lpBI->biCompression = BI_RGB;
	lpBI->biSizeImage = wHeight * lLineBytes;
	lpBI->biXPelsPerMeter = pcxHdr.wXResolution;
	lpBI->biYPelsPerMeter = pcxHdr.wYResolution;
	lpBI->biClrUsed = 0;
	lpBI->biClrImportant = 0;
	
	// 分配内存以读取编码后的像素
	lpSrc = new BYTE[file.GetLength() - sizeof(PCXHEADER) - 769];
	lpTemp = lpSrc;
	
	// 读取编码后的像素
	if (file.ReadHuge(lpSrc, file.GetLength() - sizeof(PCXHEADER) - 769) !=
		file.GetLength() - sizeof(PCXHEADER) - 769 )
	{
		// 大小不对
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 释放内存
		::GlobalFree((HGLOBAL) hDIB);
		
		// 返回NULL
		return NULL;
	}
	
	// 计算DIB中像素位置
	lpDst = (BYTE *) FindDIBBits(pDIB);
	
	// 一行一行解码
	for (j = 0; j <wHeight; j++)
	{
		i = 0;
		while (i < wWidth)
		{
			// 读取一个字节
			bChar = *lpTemp;
			lpTemp++;
			
			if ((bChar & 0xC0) == 0xC0)
			{
				// 行程
				iCount = bChar & 0x3F;
				
				// 读取下一个字节
				bChar = *lpTemp;
				lpTemp++;
				
				// bChar重复iCount次保存
				memset(&lpDst[(wHeight - j - 1) * lLineBytes + i], bChar, iCount);

				// 已经读取像素的个数加iCount
				i += iCount;
			}
			else
			{
				// 保存当前字节
				lpDst[(wHeight - j - 1) * lLineBytes + i] = bChar;
				
				// 已经读取像素的个数加1
				i += 1;
			}
		}
	}
	
	// 释放内存
	delete lpSrc;
	
	//*************************************************************
	// 调色板
	
	// 读调色板标志位
	file.Read(&bChar, 1);
	if (bChar != 0x0C)
	{
		// 出错
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 释放内存
		::GlobalFree((HGLOBAL) hDIB);
		
		// 返回NULL。
		return NULL;
	}
	
	// 分配内存以读取编码后的像素
	lpSrc = new BYTE[768];
	
	// 计算DIB中调色板的位置
	lpDst = (BYTE *) pDIB + sizeof(BITMAPINFOHEADER);
	
	// 读取调色板
	if (file.Read(lpSrc, 768) != 768)
	{
		// 大小不对
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 释放内存
		::GlobalFree((HGLOBAL) hDIB);
		
		// 返回NULL
		return NULL;
	}
	
	// 给调色板赋值
	for (i = 0; i < 256; i++)
	{
		lpDst[i * 4] = lpSrc[i * 3 + 2];
		lpDst[i * 4 + 1] = lpSrc[i * 3 + 1];
		lpDst[i * 4 + 2] = lpSrc[i * 3];
		lpDst[i * 4 + 3] = 0;
	}
	
	// 释放内存
	delete lpSrc;
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDIB);
	
	// 返回DIB句柄
	return hDIB;
}

DWORD WINAPI BytesPerLine(LPBYTE lpDIB)
{
  
  return WIDTHBYTES(
	  (((LPBITMAPINFOHEADER)lpDIB)->biWidth)
	  *(((LPBITMAPINFOHEADER)lpDIB)->biPlanes)
	  *(((LPBITMAPINFOHEADER)lpDIB)->biBitCount)
	  );


}

void WINAPI DestroyDIB(HDIB hDib)
{
 GlobalFree(hDib);
}




//合并lpDIB1,lpDIB2所代表的BINARY类型的资源
//该函数是基本的位图合并函数学,其他的函数将调用该基本函数
//合并是将两个图片连接起来,是图A+图B=图A图B的合并


HGLOBAL WINAPI MergeDIB(LPSTR lpDIB1, LPSTR lpDIB2)

{

	

	// 源图像1的宽度和高度

	LONG	lWidth1;

	LONG	lHeight1;

	// 源图像2的宽度和高度

	LONG	lWidth2;

	LONG	lHeight2;	

	// 缩放后图像的宽度和高度

	LONG	lNewWidth;

	LONG	lNewHeight;

	

	// 缩放后图像的宽度(lNewWidth',必须是4的倍数)

	LONG	lNewLineBytes;

	

	// 指向源图像1的指针

	LPSTR	lpDIBBits1;

	// 指向源图像2的指针

	LPSTR	lpDIBBits2;	

	// 指向源像素的指针,可指向图像1或图像2

	LPSTR	lpSrc;


	

	// 缩放后新DIB句柄

	HDIB	hDIB;

	

	// 指向缩放图像对应像素的指针

	LPSTR	lpDst;

	

	// 指向缩放图像的指针

	LPSTR	lpNewDIB;

	LPSTR	lpNewDIBBits;

	

	// 指向BITMAPINFO结构的指针(Windows 3.0)

	LPBITMAPINFOHEADER lpbmi;

	

	// 指向BITMAPCOREINFO结构的指针

	LPBITMAPCOREHEADER lpbmc;

	

	// 循环变量(像素在新DIB中的坐标)

	LONG	i;

	LONG	j;

	

	// 像素在源DIB1中的坐标

	LONG	i0_1;

	LONG	j0_1;
	// 像素在源DIB2中的坐标

	LONG	i0_2;

	LONG	j0_2;
	

	// 图像1每行的字节数

	LONG lLineBytes1;

	// 图像2每行的字节数

	LONG lLineBytes2;
	

	// 找到源DIB1图像像素起始位置

	lpDIBBits1 = ::FindDIBBits(lpDIB1);

	
	// 找到源DIB2图像像素起始位置

	lpDIBBits2 = ::FindDIBBits(lpDIB2);


	// 获取图像1的宽度

	lWidth1 = ::DIBWidth(lpDIB1);
	// 获取图像2的宽度

	lWidth2 = ::DIBWidth(lpDIB2);
	

	// 计算图像1每行的字节数

	lLineBytes1 = WIDTHBYTES(lWidth1 * 8);
	// 计算图像2每行的字节数

	lLineBytes2 = WIDTHBYTES(lWidth2 * 8);
	

	// 获取图像1的高度

	lHeight1 = ::DIBHeight(lpDIB1);
	// 获取图像2的高度

	lHeight2 = ::DIBHeight(lpDIB2);
	

	// 计算缩放后的图像实际宽度

	// 此处直接将两个图像的宽度相加

	lNewWidth = (LONG) (::DIBWidth(lpDIB1) +::DIBWidth(lpDIB2));

	

	// 计算新图像每行的字节数

	lNewLineBytes = WIDTHBYTES(lNewWidth * 8);

	

	// 计算新图像高度,高度不取两者最大值
    if(lHeight1>lHeight2){
	   lNewHeight = (LONG) (lHeight1);
	}else{
	   lNewHeight = (LONG) (lHeight2);
	}


	

	// 分配内存,以保存新DIB,结构参数取第一个的

	hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight + *(LPDWORD)lpDIB1 + ::PaletteSize(lpDIB1));

	

	// 判断是否内存分配失败

	if (hDIB == NULL)

	{

		// 分配内存失败

		return NULL;

	}

	

	// 锁定内存

	lpNewDIB =  (char * )::GlobalLock((HGLOBAL) hDIB);

	

	// 复制DIB信息头和调色板,此处取第一个图的数据
    // 需要保证系统提供的图片为256色图片
	memcpy(lpNewDIB, lpDIB1, *(LPDWORD)lpDIB1 + ::PaletteSize(lpDIB1));



	// 找到新DIB像素起始位置

	lpNewDIBBits = ::FindDIBBits(lpNewDIB);

	

	// 获取指针

	lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;

	lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;

	

	// 更新DIB中图像的高度和宽度

	if (IS_WIN30_DIB(lpNewDIB))

	{

		// 对于Windows 3.0 DIB

		lpbmi->biWidth = lNewWidth;

		lpbmi->biHeight = lNewHeight;

	}

	else

	{

		// 对于其它格式的DIB

		lpbmc->bcWidth = (unsigned short) lNewWidth;

		lpbmc->bcHeight = (unsigned short) lNewHeight;

	}

	

	// 针对图像每行进行操作

	for(i = 0; i < lNewHeight; i++)

	{

		// 针对图像每列进行操作

		for(j = 0; j < lNewWidth; j++)

		{

			

			// 指向新DIB第i行,第j个像素的指针

			// 注意此处宽度和高度是新DIB的宽度和高度

			lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j;

			
          
            if(j<lWidth1)//在第一个图中
			{		
				    // 计算该像素在源DIB中的坐标

					i0_1 = (LONG) (i );

					j0_1 = (LONG) (j );

					

					// 判断是否在源图范围内

					if( (j0_1 >= 0) && (j0_1 < lWidth1) && (i0_1 >= 0) && (i0_1 < lHeight1))

					{

						

						// 指向源DIB第i0行,第j0个像素的指针

						lpSrc = (char *)lpDIBBits1 + lLineBytes1 * (lHeight1 - 1 - i0_1) + j0_1;

						

						// 复制像素

						*lpDst = *lpSrc;

					}

					else

					{

						// 对于源图中没有的像素,直接赋值为255

						* ((unsigned char*)lpDst) = 255;

					}

			}
			else
			{//在第二个图中

				    // 计算该像素在源DIB中的坐标

					i0_2 = (LONG) (i);

					j0_2 = (LONG) (j-lWidth1);

					

					// 判断是否在源图范围内

					if( (j0_2 >= 0) && (j0_2 < lWidth2) && (i0_2 >= 0) && (i0_2 < lHeight2))

					{

						

						// 指向源DIB第i0行,第j0个像素的指针

						lpSrc = (char *)lpDIBBits2 + lLineBytes2 * (lHeight2 - 1 - i0_2) + j0_2;

						

						// 复制像素

						*lpDst = *lpSrc;

					}

					else

					{

						// 对于源图中没有的像素,直接赋值为255

						* ((unsigned char*)lpDst) = 255;

					}

			}
            


			

		}

		

	}

	

	// 返回

	return hDIB;

}


//***********************************************
//函数名:LoadDIBFromResource
//功能:装载资源中的DIB图
//参数:cImage --存放在资源"BINARY"段中的DIB位图资源名
//成功:成功-返回指向DIB的数据区的指针
//    失败-返回NUll
//************************************************
HDIB   WINAPI LoadDIBFromResource(CString cImage)//位图资源ID
{
		//获取存放资源的实例句柄
		HINSTANCE hInst=AfxGetInstanceHandle();

		//装入资源
		HRSRC hRes=FindResource( hInst, cImage,"BINARY");
		if(hRes==NULL)
			return NULL;
	    HGLOBAL	hGlob;
		CMemFile file; 

	    DWORD	dwResSize = SizeofResource(hInst,hRes);
        file.Attach( (LPBYTE)LockResource( hGlob = LoadResource(hInst,hRes)), dwResSize );

	    HDIB hDIB=::ReadDIBFile(file);

		file.Detach();
		DeleteObject( hGlob );


		return hDIB;

		/*	*/
	
}









/*************************************************************************

 *

 * 函数名称:

 *   HDIB2ByteArray()

 *

 * 参数:

 *   HDIB hDib          - 要保存的DIB

 *   CByteArray* pByteArray       - 保存字节数组指针

 *

 * 返回值:

 *   BOOL               - 成功返回TRUE,否则返回FALSE

 *

 * 说明:

 *   该函数将指定的DIB对象转换到指定的字节数组中。

 *

 *************************************************************************/





BOOL WINAPI HDIB2ByteArray(HDIB hDib,CByteArray* pByteArray)

{

	// Bitmap文件头

	BITMAPFILEHEADER bmfHdr;

	

	// 指向BITMAPINFOHEADER的指针

	LPBITMAPINFOHEADER lpBI;

	

	// DIB大小

	DWORD dwDIBSize;



	if (hDib == NULL)

	{

		// 如果DIB为空,返回FALSE

		return FALSE;

	}



	// 读取BITMAPINFO结构,并锁定

	lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);

	

	if (lpBI == NULL)

	{

		// 为空,返回FALSE

		return FALSE;

	}

	

	// 判断是否是Windows 3.0 DIB

	if (!IS_WIN30_DIB(lpBI))

	{

		// 不支持其它类型的DIB保存

		

		// 解除锁定

		::GlobalUnlock((HGLOBAL) hDib);

		

		// 返回FALSE

		return FALSE;

	}



	// 填充文件头



	// 文件类型BM

	bmfHdr.bfType = DIB_HEADER_MARKER;



	// 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并

	// 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小

	

	// 文件头大小+颜色表大小

	// (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个DWORD都是该结构的大小)

	dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);

	

	// 计算图像大小

	if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))

	{

		// 对于RLE位图,无法计算大小,只能信任biSizeImage内的值

		dwDIBSize += lpBI->biSizeImage;

	}

	else

	{

		// 像素的大小

		DWORD dwBmBitsSize;



		// 大小为Width * Height

		dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;

		

		// 计算出DIB真正的大小

		dwDIBSize += dwBmBitsSize;



		// 更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的)

		lpBI->biSizeImage = dwBmBitsSize;

	}





	// 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小

	bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);

	

	// 两个保留字

	bmfHdr.bfReserved1 = 0;

	bmfHdr.bfReserved2 = 0;



	// 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小

	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize

											  + PaletteSize((LPSTR)lpBI);

		  //设置字节数组大小 
		  pByteArray->SetSize(bmfHdr.bfSize);

	   // 写文件头

 		//file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
        long iCount;
        for (iCount = 0; iCount<sizeof(BITMAPFILEHEADER); iCount=iCount+1)
		{
	      pByteArray->ElementAt(iCount)=((BYTE*)(&bmfHdr))[iCount];
		}
	

		// 写DIB头和像素

		//file.WriteHuge(lpBI, dwDIBSize);
        for (iCount = 0; iCount < (long)dwDIBSize; iCount=iCount+1)
		{
	      pByteArray->ElementAt(sizeof(BITMAPFILEHEADER)+iCount)=((BYTE*)lpBI)[iCount];
		}
	


	

	// 解除锁定

	::GlobalUnlock((HGLOBAL) hDib);

	

	// 返回TRUE

	return TRUE;

}
//res1,res2是资源名称的"IDR_NUMBER0","IDR_NUMBER1"...
//合并res1和res2所代表的"BINARY"类型的资源
BOOL WINAPI MergeDIB(CString res1, CString res2,HDIB* pHDib)
{

	HDIB	hDIB1=::LoadDIBFromResource(res1);
	HDIB	hDIB2=::LoadDIBFromResource(res2);
	// 指向DIB1的指针
	LPSTR lpDIB1;
	// 锁定DIB1
	lpDIB1 = (LPSTR) ::GlobalLock((HGLOBAL)hDIB1);
	// 指向DIB2的指针
	LPSTR lpDIB2;
	// 锁定DIB1
	lpDIB2 = (LPSTR) ::GlobalLock((HGLOBAL)hDIB2);
	//在此可以判断是否是256色
	//高与256色的位图其数据进行了压缩,合并函数可能并未考虑改压缩情况
	//低于256色会由于图片资料问题显示不清楚
    

     *pHDib=(HDIB)::MergeDIB(lpDIB1,lpDIB2);
	// 解除锁定
	::GlobalUnlock((HGLOBAL)hDIB1);
	::GlobalUnlock((HGLOBAL)hDIB2);
	//释放内存
	::GlobalFree((HGLOBAL)hDIB1);
	::GlobalFree((HGLOBAL)hDIB2);
    
	return TRUE;
}

//res是资源名称的"IDR_NUMBER0","IDR_NUMBER1"...
//合并res所代表的"BINARY"类型的资源和hDib所代表的资源
BOOL WINAPI MergeDIB(HDIB hDib, CString res,HDIB* pHDib)
{

    HDIB    hDIB1=hDib;
	//保存该指针,因为可能*pHDib和hDib指向同一对象,
	//在以下的计算中可能会失去该*pHDib指针,
	//此处保存以使得hDib对象能释放内存

	HDIB	hDIB2=::LoadDIBFromResource(res);
	// 指向DIB1的指针
	LPSTR lpDIB1;
	// 锁定DIB1
	lpDIB1 = (LPSTR) ::GlobalLock((HGLOBAL)hDIB1);
	// 指向DIB2的指针
	LPSTR lpDIB2;
	// 锁定DIB1
	lpDIB2 = (LPSTR) ::GlobalLock((HGLOBAL)hDIB2);
	//在此可以判断是否是256色
	//高与256色的位图其数据进行了压缩,合并函数可能并未考虑改压缩情况
	//低于256色会由于图片资料问题显示不清楚

     *pHDib=(HDIB)::MergeDIB(lpDIB1,lpDIB2);
	// 解除锁定
	::GlobalUnlock((HGLOBAL)lpDIB1);
	::GlobalUnlock((HGLOBAL)hDIB2);
	//释放内存
	::GlobalFree((HGLOBAL)lpDIB1);
	::GlobalFree((HGLOBAL)hDIB2);
    
	return TRUE;
}

//合并num1、num2所代表的"BINARY"类型的资源
//其中num1、num2是资源名称的"IDR_NUMBER0","IDR_NUMBER1"...中的0,1,2,..
//的0~9的数字

BOOL WINAPI MergeDIB(int num1, int num2,HDIB* pHDib)
{   
	CString res1;
	CString res2;
	res1.Format("IDR_NUMBER%i",num1);
	res2.Format("IDR_NUMBER%i",num2);
    return MergeDIB(res1,res2,pHDib);

}
//合并num所代表的BINARY类型的资源和hDib所代表的资源
//其中num是资源名称的"IDR_NUMBER0","IDR_NUMBER1"...中的0,1,2,..
//的0~9的数字
BOOL WINAPI MergeDIB(HDIB hDib, int num,HDIB* pHDib)
{
	CString res;
	res.Format("IDR_NUMBER%i",num);
    return MergeDIB(hDib,res,pHDib);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -