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

📄 cdib.cpp

📁 可用的基于小波的spiht算法
💻 CPP
📖 第 1 页 / 共 3 页
字号:
BOOL CDib::IsEmpty()
{
	if(m_lpBMIH == NULL && m_lpImage == NULL)
		return TRUE;
	else
		return FALSE;
}

/***********************************************************
* \函数名称:
*          Draw()
* \输入参数:
*         CDC* pDC          -指向将要接收DIB图像的设备上下文指针
*         CPoint origin     -显示DIB的逻辑坐标
*         CSize size        -显示矩形的宽度和高度
* \返回值:
*         BOOL              -如果成功,则返回TRUE
* \说明:
*       通过调用Win32 SDK的StretchDIBits函数将CDib对象输出到显示器
*       为了合适指定的矩形,位图可以进行必要的拉伸
************************************************************
*/
BOOL CDib::Draw(CDC* pDC,CPoint origin,CSize size)
{
	//如果信息头为空,表示尚未有数据,返回FALSE
	if(m_lpBMIH == NULL) return FALSE;

	//如果调色板不为空,则将调色板选入设备上下文
	if(m_hPalette!=NULL){
		::SelectPalette(pDC->GetSafeHdc(),m_hPalette,TRUE);
	}

	//设置显示模式
	pDC->SetStretchBltMode(COLORONCOLOR);

	//在设备的origin位置上画出大小为size的图像
	::StretchDIBits(pDC->GetSafeHdc(),origin.x,origin.y,size.cx,size.cy,
		0,0,m_lpBMIH->biWidth,m_lpBMIH->biHeight,m_lpImage,
		(LPBITMAPINFO)m_lpBMIH,DIB_RGB_COLORS,SRCCOPY);

	//返回
	return TRUE;
}

/***********************************************************
* \函数名称:
*         Compress()
* \输入参数:
*         CDC* pDC          -指向将要接收DIB图像的设备上下文指针
*         BOOL bCompress    -TRUE对应于压缩的DIB,FALSE对应于不压缩的DIB
* \返回值:
*         BOOL              -如果成功,则返回TRUE
* \说明:
*       该函数将DIB重新生成为压缩或者不压缩的DIB,在内部,它转换已有的DIB为DDB位图
*       然后生成一个新的DIB。压缩仅为4bpp和8bpp的DIB所支持
************************************************************
*/
BOOL CDib::Compress(CDC* pDC,BOOL bCompress/*=TRUE*/)
{
	//判断是否为4bpp或者8bpp位图,否则不进行压缩,返回FALSE
	if((m_lpBMIH->biBitCount!=4)&&(m_lpBMIH->biBitCount!=8))
		return FALSE;

	//如果为DIB段,也不能支持压缩,返回FALSE
	if(m_hBitmap) return FALSE;

	TRACE("Compress:original palette size = %d\n",m_nColorTableEntries);

	//获得设备上下文句柄
	HDC hdc = pDC->GetSafeHdc();

	//将此DIB的调色板选入设备上下文,并保存以前的调色板句柄
	HPALETTE hOldPalette = ::SelectPalette(hdc,m_hPalette,FALSE);

	HBITMAP hBitmap;

	//创建一个DDB位图,如果不成功,则返回FALSE
	if((hBitmap = CreateBitmap(pDC)) = NULL)
		return FALSE;

	//计算信息头加上调色板的大小尺寸,并给它们分配内存
	int nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
	LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) new char [nSize];

	//将信息头和调色板拷贝到内存中
	memcpy(lpBMIH,m_lpBMIH,nSize);

	//如需要压缩,设置相应的信息,并创建压缩格式的DIB
	if(bCompress){
		switch (lpBMIH->biBitCount){
		case 4:
			lpBMIH->biCompression = BI_RLE4;
			break;
		case 8:
			lpBMIH->biCompression = BI_RLE8;
			break;
		default:
			ASSERT(FALSE);
		}

		//设置位图数据指针为NULL,调用GetDIBits来得到压缩格式的DIB的尺寸
		//如果不能创建DIB,则进行相应的错误处理
		if(!::GetDIBits(pDC->GetSafeHdc(),hBitmap,0,(UINT)lpBMIH->biHeight,
			NULL,(LPBITMAPINFO)lpBMIH,DIB_RGB_COLORS)){
			AfxMessageBox("Unable to compress this DIB");

			//删除临时变量,并释放已分配内存
			::DeleteObject(hBitmap);
			delete[] lpBMIH;

			//重新将以前的调色板选入,并返回FALSE
			::SelectPalette(hdc,hOldPalette,FALSE);
			return FALSE;
		}

		//如果位图数据为空,则进行相应的错误处理
		if(lpBMIH->biSizeImage == 0){
			AfxMessageBox("Driver can't do compression");

			//删除临时变量,并释放已分配内存
			::DeleteObject(hBitmap);
			delete [] lpBMIH;

			//重新将以前的调色板选入,并返回FALSE
			::SelectPalette(hdc,hOldPalette,FALSE);
			return FALSE;
		}

		//将位图数据尺寸赋值给类的成员变量
		else{
			m_dwSizeImage = lpBMIH->biSizeImage;
		}
	}
	//如果是解压缩,进行相应的处理
	else{
		//设置压缩格式为不压缩
		lpBMIH->biCompression = BI_RGB;

		//根据位图的宽度和高度计算位图数据内存的大小
		DWORD dwBytes = ((DWORD)lpBMIH->biWidth * lpBMIH->biBitCount)/32;
		if(((DWORD)lpBMIH->biWidth * lpBMIH->biBitCount)%32){
			dwBytes++;
		}
		dwBytes *=4;

		//将得到位图数据的大小尺寸保存在类的成员变量中
		m_dwSizeImage = dwBytes * lpBMIH->biHeight;

		//将位图数据内存的大小赋值给临时的信息头中的相应的变量
		lpBMIH->biSizeImage = m_dwSizeImage;
	}
	//再次调用GetDIBits来生成DIB数据

	//分配临时存放位图数据
	LPBYTE lpImage = (LPBYTE)new char[m_dwSizeImage];

	//再次调用GetDIBits来生成DIB数据,注意此时位图数据指针不为空
	VERIFY(::GetDIBits(pDC->GetSafeHdc(),hBitmap,0,(UINT)lpBMIH->biHeight,
		lpImage,(LPBITMAPINFO)lpBMIH,DIB_RGB_COLORS));
	TRACE("dib successfully create-height = %d\n",lpBMIH->biHeight);

	//压缩转换完毕,进行相应的其他处理

	//删除临时的DDB位图
	::DeleteObject(hBitmap);

	//释放原来的DIB分配的内存
	Empty();

	//重新设置图像信息头和图像数据内存分配状态
	m_nBmihAlloc = m_nImageAlloc = crtAlloc;

	//重新定位信息头和图像数据指针
	m_lpBMIH = lpBMIH;
	m_lpImage = lpImage;

	//计算图像数据尺寸,并设置DIB中的调色板的指针
	ComputeMetrics();

	//计算DIB中调色板的尺寸
	ComputePaletteSize(m_lpBMIH->biBitCount);

	//如果DIB中调色板存在的话,读取并创建一个Windows调色板
	MakePalette();

	//恢复以前的调色板
	::SelectPalette(hdc,hOldPalette,FALSE);
	TRACE("Compress:new palette size = %d\n",m_nColorTableEntries);

	//返回
	return TRUE;
}

/***********************************************************
* \函数名称:
*         AttachMapFile()
* \输入参数:
*         const char* strPathname    -映射文件的路径名
*         BOOL bShare                -如果文件以共享形式打开,设置为TRUE; 默认值为FALSE
* \返回值:
*         BOOL                       -如果成功,则返回TRUE
* \说明:
*       以读模式打开内存映射文件,并将其与CDib对象关联,因为在文件使用前并没有读入内存
*       故它立即返回,因为文件是分页的,所以当访问这个DIB的时候,可能会有一些延迟
************************************************************
*/
BOOL CDib::AttachMapFile(const char* strPathname,BOOL bShare)
{
	//获取文件句柄,并设置打开模式为共享
	HANDLE hFile = ::CreateFile(strPathname,GENERIC_WRITE|GENERIC_READ,bShare?FILE_SHARE_READ:0,
		NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	ASSERT(hFile!=INVALID_HANDLE_VALUE);

	//获取文件的尺寸
	DWORD dwFileSize = ::GetFileSize(hFile,NULL);

	//创建文件映射对象,并设置文件映射的模式为读写
	HANDLE hMap = ::CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,NULL);
	DWORD dwErr = ::GetLastError();
	if(hMap == NULL){
		AfxMessageBox("Empty bitmap file");
		return FALSE;
	}

	//映射整个文件,注意FILE_MAP_WRITE为读写模式
	LPVOID lpvFile = ::MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
	ASSERT(lpvFile!=NULL);
	if(((LPBITMAPFILEHEADER)lpvFile)->bfType!=0x4d42){
		AfxMessageBox("Invalid bitmap file");
		DetachMapFile();
		return FALSE;
	}

	//将内存中的DIB与已有的CDib对象关联
	AttachMemory((LPBYTE)lpvFile + sizeof(BITMAPFILEHEADER));

	//将这些有用的句柄设置为类数据成员
	m_lpvFile = lpvFile;
	m_hFile = hFile;
	m_hMap = hMap;

	//返回
	return TRUE;
}

/***********************************************************
* \函数名称:
*         AttachMemory()
* \输入参数:
*         LPVOID lpvMem          -要关联的内存地址
*         BOOL bMustDelete       -如果CDib负责删除这个内存,标记为TRUE; 默认值为FALSE
*         HGLOBAL hGlobal        -如果内存是通过Win32 GlobalAlloc得到的,则CDib对象必须
*                                -保存该句柄,这样以后可以释放该句柄。这里假设bMustDelete为TRUE
* \返回值:
*         BOOL                       -如果成功,则返回TRUE
* \说明:
*       用内存中的DIB与已有的CDib对象关联。此内存可能是程序的资源或可能是剪贴板或OLE数据对象内存
*       内存可能已经由CRT堆栈用new运算符分配了,或者可能由Windows堆栈用GlobalAlloc分配了
************************************************************
*/
BOOL CDib::AttachMemory(LPVOID lpvMem,BOOL bMustDelete,HGLOBAL hGlobal)
{
	//释放已经分配的内存
	Empty();

	m_hGlobal = hGlobal;

	//bMustDelete为TRUE表示此CDib类分配的内存,负责删除
	//否则的设置信息头分配状态为noAlloc
	if(bMustDelete == FALSE){
		m_nBmihAlloc = noAlloc;
	}
	else{
		m_nBmihAlloc = ((hGlobal == NULL)?crtAlloc:heapAlloc);
	}
	try{
		//设置信息头指针
		m_lpBMIH = (LPBITMAPINFOHEADER)lpvMem;

		//重新计算得到图像数据块的大小,并设置调色板的指针
		ComputeMetrics();

		//计算调色板的尺寸
		ComputePaletteSize(m_lpBMIH->biBitCount);

		//设置图像数据指针
		m_lpImage = (LPBYTE)m_lpvColorTable + sizeof(RGBQUAD) * m_nColorTableEntries;

		//如果调色板存在的话,读取它,并创建一个Windows调色板
		//并将调色板的句柄存放在数据成员中
		MakePalette();
	}

	//错误处理
	catch(CException* pe){
		AfxMessageBox("AttachMemory error");
		pe->Delete();
		return FALSE;
	}

	//返回
	return TRUE;
}

/***********************************************************
* \函数名称:
*         CopyToMapFile()
* \输入参数:
*         const char* strPathname    -映射文件的路径名
* \返回值:
*         BOOL                       -如果成功,则返回TRUE
* \说明:
*       该函数创建一个新的内存映射文件,并将现有的CDib数据复制到该文件的内存
*       释放以前的所有内存。并关闭现有的所有内存映射文件。
************************************************************
*/
BOOL CDib::CopyToMapFile(const char* strPathname)
{
	BITMAPFILEHEADER bmfh;

	//设置文件头信息
	bmfh.bfType = 0x4d42;
	bmfh.bfSize = m_dwSizeImage + sizeof(BITMAPINFOHEADER) +
		sizeof(RGBQUAD) * m_nColorTableEntries + sizeof(BITMAPFILEHEADER);
	bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
	bmfh.bfOffBits =sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) +
		sizeof(RGBQUAD) * m_nColorTableEntries;

	//创建接收数据的文件
	HANDLE hFile = ::CreateFile(strPathname,GENERIC_WRITE|GENERIC_READ,0,NULL,
		CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
	ASSERT(hFile!= INVALID_HANDLE_VALUE);

	//计算文件的大小尺寸
	int nSize = m_dwSizeImage + sizeof(BITMAPINFOHEADER) +
		sizeof(RGBQUAD) * m_nColorTableEntries + sizeof(BITMAPFILEHEADER);

	//创建内存映射文件对象
	HANDLE hMap = ::CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,nSize,NULL);
	DWORD dwErr = ::GetLastError();
	ASSERT(hMap!=NULL);

	//映射整个文件
	LPVOID lpvFile = ::MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
	ASSERT(lpvFile != NULL);

	//临时文件指针
	LPBYTE lpbCurrent = (LPBYTE)lpvFile;

	//拷贝文件头信息到内存映射文件中
	memcpy(lpbCurrent,&bmfh,sizeof(BITMAPFILEHEADER));

	//计算信息头在文件中的地址,并拷贝信息头信息
	lpbCurrent += sizeof(BITMAPFILEHEADER);
	LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER)lpbCurrent;
	memcpy(lpbCurrent,m_lpBMIH,
		sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries);

	//计算调色板在文件中的地址,并拷贝调色板
	lpbCurrent += sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
	memcpy(lpbCurrent,m_lpImage,m_dwSizeImage);

	//暂时存放图像数据尺寸变量
	DWORD dwSizeImage = m_dwSizeImage;

	//释放一起分配的所有内存
	Empty();

	//设置图像数据尺寸并设置内存分配状态
	m_dwSizeImage = dwSizeImage;
	m_nBmihAlloc = m_nImageAlloc = noAlloc;

	//信息头指针重新指向文件中的位置
	m_lpBMIH = lpBMIH;

	//图像数据指针重新指向文件中的数据地址
	m_lpImage = lpbCurrent;

	//设置文件句柄
	m_hFile = hFile;

	//设置映射对象句柄
	m_hMap = hMap;

	//设置映射文件指针
	m_lpvFile = lpvFile;

	//重新计算得到调色板尺寸
	ComputePaletteSize(m_lpBMIH->biBitCount);

	//重新计算图像数据块大小,并设置调色板指针
	ComputeMetrics();

	//如果调色板存在的话,读取并创建一个Windows调色板
	MakePalette();

	//返回
	return TRUE;
}

/***********************************************************
* \函数名称:
*         DetachMapFile()
* \输入参数:
*         无
* \返回值:
*         无
* \说明:
*       函数可以释放现有的已分配的内存,并关闭以前关联的任何内存映射文件
************************************************************
*/
void CDib::DetachMapFile()
{
	//如果没有进行内存映射,则不进行处理
	if(m_hFile == NULL) return;

	//关闭内存映射
	::UnmapViewOfFile(m_lpvFile);

	//关闭内存映射对象和文件
	::CloseHandle(m_hMap);
	::CloseHandle(m_hFile);
	m_hFile = NULL;
}

/***********************************************************
* \函数名称:
*         MakePalette()
* \输入参数:
*         无
* \返回值:
*         BOOL           -如果成功,则返回TRUE
* \说明:
*       如果颜色表存在的话,该函数读取它,并创建一个Windows调色板。
*       HPALETTE存储在一个数据成员中
************************************************************
*/
BOOL CDib::MakePalette()
{
	//如果不存在调色板,则返回FALSE
	if(m_nColorTableEntries == 0) return FALSE;

	if(m_hPalette != NULL) ::DeleteObject(m_hPalette);
	TRACE("CDib::MakePalette -- m_nColorTableEntries = %d\n",m_nColorTableEntries);

	//给逻辑调色板分配内存
	LPLOGPALETTE pLogPal = (LPLOGPALETTE)new char[2*sizeof(WORD) +
		m_nColorTableEntries * sizeof(PALETTEENTRY)];

	//设置逻辑调色板的信息
	pLogPal->palVersion = 0x300;
	pLogPal->palNumEntries = m_nColorTableEntries;

	//拷贝DIB中的颜色表到逻辑调色板
	LPRGBQUAD pDibQuad = (LPRGBQUAD)m_lpvColorTable;
	for(int i = 0; i < m_nColorTableEntries; i++){
		pLogPal->palPalEntry[i].peRed = pDibQuad->rgbRed;
		pLogPal->palPalEntry[i].peGreen = pDibQuad->rgbGreen;
		pLogPal->palPalEntry[i].peBlue =pDibQuad->rgbBlue;
		pLogPal->palPalEntry[i].peFlags = 0;
		pDibQuad++;
	}

	//创建逻辑调色板
	m_hPalette = ::CreatePalette(pLogPal);
	
	//删除临时变量并返回TRUE
	delete pLogPal;
	return TRUE;
}

/***********************************************************
* \函数名称:
*         SetSystemPalette()
* \输入参数:
*         CDC* pDC            -设备上下文指针
* \返回值:
*         BOOL                -如果成功,则返回TRUE
* \说明:
*       如果16bpp、24bpp或者32bppDIB不具备调色板,则该函数为CDib对象创建一个。
*       它与由CreateHalftonePalette函数返回的调色板相匹配
************************************************************

⌨️ 快捷键说明

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