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

📄 dibapi.cpp

📁 AppWizard has created this DigitRec application for you. This application not only demonstrates the
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
		void* lp     = ::GlobalLock((HGLOBAL) h);
		
		// 复制
		memcpy(lpCopy, lp, dwLen);
		
		// 解除锁定
		::GlobalUnlock(hCopy);
		::GlobalUnlock(h);
	}

	return hCopy;
}



/*************************************************************************
 *
 * 函数名称:
 *   SaveDIB()
 *
 * 参数:
 *   HDIB hDib          - 要保存的DIB
 *   CFile& file        - 保存文件CFile
 *
 * 返回值:
 *   BOOL               - 成功返回TRUE,否则返回FALSE或者CFileException
 *
 * 说明:
 *   该函数将指定的DIB对象保存到指定的CFile中。该CFile由调用程序打开和关闭。
 *
 *************************************************************************/


BOOL WINAPI SaveDIB(HDIB hDib, CFile& file)
{
	// 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;
	}
	
	// 判断是否是WIN3.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);
	// 尝试写文件
	TRY
	{
		// 写文件头
		file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
		
		// 写DIB头和象素
		file.WriteHuge(lpBI, dwDIBSize);
	}
	CATCH (CFileException, e)
	{
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDib);
		
		// 抛出异常
		THROW_LAST();
	}
	END_CATCH
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDib);
	
	// 返回TRUE
	return TRUE;
}


/*************************************************************************
 *
 * 函数名称:
 *   ReadDIBFile()
 *
 * 参数:
 *   CFile& file        - 要读取得文件文件CFile
 *
 * 返回值:
 *   HDIB               - 成功返回DIB的句柄,否则返回NULL。
 *
 * 说明:
 *   该函数将指定的文件中的DIB对象读到指定的内存区域中。除BITMAPFILEHEADER
 * 外的内容都将被读入内存。
 *
 *************************************************************************/

HDIB WINAPI ReadDIBFile(CFile& file)
{
	BITMAPFILEHEADER bmfHeader;
	DWORD dwBitsSize;
	HDIB hDIB;
	LPSTR pDIB;

	// 获取DIB(文件)长度(字节)
	dwBitsSize = file.GetLength();

	// 尝试读取DIB文件头
	if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
	{
		// 大小不对,返回NULL。
		return NULL;
	}

	// 判断是否是DIB对象,检查头两个字节是否是"BM"
	if (bmfHeader.bfType != DIB_HEADER_MARKER)
	{
		// 非DIB对象,返回NULL。
		return NULL;
	}

	// 为DIB分配内存
	hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
	if (hDIB == 0)
	{
		// 内存分配失败,返回NULL。
		return NULL;
	}
	
	// 锁定
	pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);

	// 读象素
	if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
		dwBitsSize - sizeof(BITMAPFILEHEADER) )
	{
		// 大小不对。
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 释放内存
		::GlobalFree((HGLOBAL) hDIB);
		
		// 返回NULL。
		return NULL;
	}
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDIB);
	
	// 返回DIB句柄
	return hDIB;
}

/*************************************************************************
 *
 * 函数名称:
 *   NewDIB()
 *
 * 参数:
 *   width			- 将要创建DIB的宽
 *   height			- 将要创建DIB的高
 *   biBitCount		- 将要创建DIB的位数。比如,如果要创建256色DIB,则此值为8
 * 返回值:
 *   HDIB           - 成功返回DIB的句柄,否则返回NULL。
 *
 * 说明:
 *   该函数指定宽、高、颜色位数来创建一个新的DIB,并返回其句柄
 *************************************************************************/
/*******************************************************************
*函数名称:
* NewDIB()
*
* 参数:
* width			- 将要创建DIB的宽
* height			- 将要创建DIB的高
* biBitCount		- 将要创建DIB的位数。比如,如果要创建256色DIB,则此值为8
*
*返回值:
*  HDIB           - 成功返回DIB的句柄,否则返回NULL。
*
*说明:
*  该函数指定宽、高、颜色位数来创建一个新的DIB,并返回其句柄
*
***************************************************************/
HDIB WINAPI NewDIB(long width, long height,unsigned short biBitCount) 
{
	
//计算新建的DIB每行所占的字节数
long dwindth = (width*biBitCount/8+3)/4*4;

//新建的DIB调色板中表项的数目 
	 WORD color_num;
   
     //通过输入的biBitCount值来确定调色板的表项数目 
	switch(biBitCount)
	{   

       //如果用1 bit来表示一个象素那么调色板中有两个表项 
		case 1:
         color_num=2;
		break;

       //如果用4 bit来表示一个象素那么调色板中有16个表项
		case 4:
		color_num=16;
		break;

       //如果用8bit来表示一个象素,那么调色板中得表项有256中(本程序大多采用这种形式)
		case 8:
		color_num=256;
		break;

       //其他的情况调色扳中没有表项,即真彩位图
		default:
		color_num=0;
		break;
	}

//计算位图数据所占的空间
//dwindth *height为象素数据所占的空间
//40为位图信息头占的空间
//color_num*4为调色板的表项所占的空间(调色板每个表项占4各个字节)

 long   dwBitsSize = dwindth *height + 40 + color_num*4;

//建立指向位图文件的指针 
LPSTR pDIB;

//申请存储空间,并建立指向位图的句柄
HDIB hDIB=(HDIB) ::GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, dwBitsSize);

//如果申请空间不成功返回错误信息
	if (hDIB == 0)
	{
		return NULL;
	}

   //如果申请空间成功锁定内存,并将内存的指针传给pDIB
	pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
	
   //建立指向位图信息头结构的指针
	LPBITMAPINFO lpmf = (LPBITMAPINFO)pDIB;

   //给位图信息头内的各个参量赋值

   //指定位图信息头结构的大小为40字节
	lpmf->bmiHeader.biSize = 40;

   //指定新建位图的宽度
	lpmf->bmiHeader.biWidth = width;

   //指定新建位图的高度
lpmf->bmiHeader.biHeight = height;

   //位平面数必须为1
lpmf->bmiHeader.biPlanes = 1;

//确定新建位图表示颜色是要用到的bit数
lpmf->bmiHeader.biBitCount = biBitCount;

    //是否进行压缩
	lpmf->bmiHeader.biCompression = 0;

    //新建的位图中实际的位图数据所占的字节数
lpmf->bmiHeader.biSizeImage = dwindth *height;

//指定目标设备的水平分辨率
	lpmf->bmiHeader.biXPelsPerMeter = 2925;

    //指定目标设备的垂直分辨率
lpmf->bmiHeader.biYPelsPerMeter = 2925;

//新建图像实际用到的颜色数 如果为0则用到的颜色数为2的biBitCount次
lpmf->bmiHeader.biClrUsed = 0;
 
//指定新建图像中重要的颜色数,如果为0则所有的颜色都重要
	lpmf->bmiHeader.biClrImportant= 0; 	
    
    //如果新建的图像中含有调色板,则接下来对调色板的各种颜色分量赋初始值
	if(color_num!=0)
	{
		for(int i=0;i<color_num;i++)
		{
			lpmf->bmiColors[i].rgbRed =(BYTE)i;
			lpmf->bmiColors[i].rgbGreen =(BYTE)i;
			lpmf->bmiColors[i].rgbBlue =(BYTE)i;
		}
	}

//解除锁定
::GlobalUnlock((HGLOBAL) hDIB);

//返回新建位图的句柄
	 return hDIB;

}


/*************************************************************************
 *
 * 函数名称:
 *   PaletteSize()
 *
 * 参数:
 *   LPSTR lpbi         - 指向DIB对象的指针
 *
 * 返回值:
 *   WORD               - DIB中调色板的大小
 *
 * 说明:
 *   该函数返回DIB中调色板的大小。对于Windows 3.0 DIB,返回颜色数目×
 * RGBQUAD的大小;对于其它返回颜色数目×RGBTRIPLE的大小。
 *
 ************************************************************************/
WORD WINAPI PaletteSize(LPSTR lpbi)
{
	// 计算DIB中调色板的大小
	if (IS_WIN30_DIB (lpbi))
	{
		//返回颜色数目×RGBQUAD的大小
		return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
	}
	else
	{
		//返回颜色数目×RGBTRIPLE的大小
		return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
	}
}

⌨️ 快捷键说明

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