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

📄 dib.cpp

📁 利用一组样本之间的相关性
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	TRACE("Compress: new palette size = %d\n", m_nColorTableEntries); 

	// 返回
	return TRUE;
}


/*************************************************************************
 *
 * \函数名称:
 *   Read()
 *
 * \输入参数:
 *   CFile*	pFile			- 指向CFile对象的指针
 *
 * \返回值:
 *   BOOL				- 如果成功,则返回TRUE
 *
 * \说明:
 *   该函数DIB从一个文件读入CDib对象。该文件必须成功打开。如果该文件是BMP文件
 *   读取工作从文件头开始。如果该文件是一个文档,读取工作则从当前文件指针处开始 
 *
 ************************************************************************
 */
BOOL CDib::Read(CFile* pFile)
{
	// 释放已经分配的内存
	Empty();

	// 临时存放信息的变量
	int nCount, nSize;
	BITMAPFILEHEADER bmfh;

	// 进行读操作
	try 
	{
		// 读取文件头
		nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
		if(nCount != sizeof(BITMAPFILEHEADER)) {
			throw new CException;
		}

		// 如果文件类型部位"BM",则返回并进行相应错误处理
		if(bmfh.bfType != 0x4d42) 
		{
//			throw new CException;
			char filename[256];	
			GetTempPath(256, filename);
			strcat(filename, pFile->GetFileName());
			FILE *tmp;
			tmp = fopen(filename, "wb");
			fwrite(&bmfh, sizeof(BITMAPFILEHEADER), 1, tmp);
			char buf[8192];
			int len;

			len = pFile->Read(buf, 8192);
			while(len!=0)
			{
				fwrite(buf, len, 1, tmp);
				len = pFile->Read(buf, 8192);
			}
			fclose(tmp);
			
		}
		else
		{
			// 计算信息头加上调色板的大小,并分配相应的内存
			nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
			m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize];
			m_nBmihAlloc = m_nImageAlloc = crtAlloc;

			// 读取信息头和调色板
			nCount = pFile->Read(m_lpBMIH, nSize); 

			// 计算图象数据大小并设置调色板指针
			ComputeMetrics();

			// 计算调色板的表项数
			ComputePaletteSize(m_lpBMIH->biBitCount);

			// 如果DIB中存在调色板,则创建一个Windows调色板
			MakePalette();

			// 分配图象数据内存,并从文件中读取图象数据
			m_lpImage = (LPBYTE) new char[m_dwSizeImage];
			nCount = pFile->Read(m_lpImage, m_dwSizeImage); 
		}
	}

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

	pSourceFile = pFile->Duplicate();

	// 返回
	return TRUE;
}


/*************************************************************************
 *
 * \函数名称:
 *   ReadSection()
 *
 * \输入参数:
 *   CFile*	pFile			- 指向CFile对象的指针;对应的磁盘
 *					- 文件中包含DIB
 *   CDC*	pDC			- 设备上下文指针
 *
 * \返回值:
 *   BOOL				- 如果成功,则返回TRUE
 *
 * \说明:
 *   该函数从BMP文件中读取信息头,调用CreateDIBSection来分配图象内存,然后将
 *   图象从该文件读入刚才分配的内存。如果你想从磁盘读取一个DIB,然后通过调用
 *   GDI函数编辑它的话,可以使用该函数。你可以用Write或CopyToMapFile将DIB写
 *   回到磁盘
 *
 ************************************************************************
 */
BOOL CDib::ReadSection(CFile* pFile, CDC* pDC /* = NULL */)
{
	
	// 释放已经分配的内存
	Empty();

	// 临时变量
	int nCount, nSize;
	BITMAPFILEHEADER bmfh;

	// 从文件中读取数据
	try {
		// 读取文件头
		nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
		if(nCount != sizeof(BITMAPFILEHEADER)) {
			throw new CException;
		}

		// 如果文件类型部位"BM",则返回并进行相应错误处理
		if(bmfh.bfType != 0x4d42) {
			throw new CException;
		}

		// 计算信息头加上调色板的大小,并分配相应的内存
		nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
		m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize];
		m_nBmihAlloc = crtAlloc;
		m_nImageAlloc = noAlloc;

		// 读取信息头和调色板
		nCount = pFile->Read(m_lpBMIH, nSize); 

		// 如果图象为压缩格式,则不进行后续处理
		if(m_lpBMIH->biCompression != BI_RGB) {
			throw new CException;
		}

		// 计算图象数据大小并设置调色板指针
		ComputeMetrics();

		// 计算调色板的表项数
		ComputePaletteSize(m_lpBMIH->biBitCount);

		// 如果DIB中存在调色板,则创建一个Windows调色板
		MakePalette();

		// 将CDib对象的逻辑调色板选入设备上下文		
		UsePalette(pDC);

		// 创建一个DIB段,并分配图象内存
		m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH,
			DIB_RGB_COLORS,	(LPVOID*) &m_lpImage, NULL, 0);
		ASSERT(m_lpImage != NULL);

		// 从文件中读取图象数据
		nCount = pFile->Read(m_lpImage, m_dwSizeImage); 
	}

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


/*************************************************************************
 *
 * \函数名称:
 *   Write()
 *
 * \输入参数:
 *   CFile*	pFile			- 指向CFile对象的指针
 *
 * \返回值:
 *   BOOL				- 如果成功,则返回TRUE
 *
 * \说明:
 *   该函数把DIB从CDib对象写进文件中。该文件必须成功打开或者创建
 *
 ************************************************************************
 */
BOOL CDib::Write(CFile* pFile)
{
	BITMAPFILEHEADER bmfh;

	// 设置文件头中文件类型为"BM"
	bmfh.bfType = 0x4d42;  

	// 计算信息头和调色板的大小尺寸
	int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;

	// 设置文件头信息
	bmfh.bfSize = sizeof(BITMAPFILEHEADER) + nSizeHdr + m_dwSizeImage;
	bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
	bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
			sizeof(RGBQUAD) * m_nColorTableEntries;	
	
	// 进行写操作
	try {
		pFile->Write((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
		pFile->Write((LPVOID) m_lpBMIH,  nSizeHdr);
		pFile->Write((LPVOID) m_lpImage, m_dwSizeImage);
	}

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

	// 返回
	return TRUE;
}


/*************************************************************************
 *
 * \函数名称:
 *   Serialize()
 *
 * \输入参数:
 *   CArchive&	ar			- 指向应用程序归档对象
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   该函数进行串行化过程,将CDib数据进行读入或者写出
 *
 ************************************************************************
 */
void CDib::Serialize(CArchive& ar)
{
	DWORD dwPos;

	// 获得此归档文件的CFile对象指针
	dwPos = ar.GetFile()->GetPosition();
	TRACE("CDib::Serialize -- pos = %d\n", dwPos);

	// 从归档文件缓冲区中冲掉未写入数据
	ar.Flush();

	// 重新获得此归档文件的CFile对象指针
	dwPos = ar.GetFile()->GetPosition();
	TRACE("CDib::Serialize -- pos = %d\n", dwPos);

	// 确定归档文件是否被存储,是则进行存储	
	if(ar.IsStoring()) {
		Write(ar.GetFile());
	}

	// 否则进行加载
	else {
		Read(ar.GetFile());
	}
}


/*************************************************************************
 *
 * \函数名称:
 *   ComputePaletteSize()
 *
 * \输入参数:
 *   int	nBitCount		- 指向CFile对象的指针
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   该函数根据位图象素位数计算调色板的尺寸
 *
 ************************************************************************
 */
void CDib::ComputePaletteSize(int nBitCount)
{
	// 如果biClrUsed为零,则用到的颜色数为2的biBitCount次方
	if((m_lpBMIH == NULL) || (m_lpBMIH->biClrUsed == 0)) {
		switch(nBitCount) {
			case 1:
				m_nColorTableEntries = 2;
				break;
			case 4:
				m_nColorTableEntries = 16;
				break;
			case 8:
				m_nColorTableEntries = 256;
				break;
			case 16:
			case 24:
			case 32:
				m_nColorTableEntries = 0;
				break;
			default:
				ASSERT(FALSE);
		}
	}

	// 否则调色板的表项数就是用到的颜色数目
	else {
		m_nColorTableEntries = m_lpBMIH->biClrUsed;
	}

	ASSERT((m_nColorTableEntries >= 0) && (m_nColorTableEntries <= 256)); 
}


/*************************************************************************
 *
 * \函数名称:
 *   ComputeMetrics()
 *
 * \输入参数:
 *   无
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   该函数计算图象位图的尺寸,并对DIB中的调色板的指针进行赋值
 *
 ************************************************************************
 */
void CDib::ComputeMetrics()
{
	// 如果结构的长度不对,则进行错误处理
	if(m_lpBMIH->biSize != sizeof(BITMAPINFOHEADER)) {
		TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmap\n");
		throw new CException;
	}

	// 保存图象数据内存大小到CDib对象的数据成员中
	m_dwSizeImage = m_lpBMIH->biSizeImage;

	// 如果图象数据内存大小为0,则重新计算
	if(m_dwSizeImage == 0) {
		DWORD dwBytes = ((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) / 32;
		if(((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) % 32) {
			dwBytes++;
		}
		dwBytes *= 4;
		m_dwSizeImage = dwBytes * m_lpBMIH->biHeight;	
	}

	// 设置DIB中的调色板指针
	m_lpvColorTable = (LPBYTE) m_lpBMIH + sizeof(BITMAPINFOHEADER);
}


/*************************************************************************
 *
 * \函数名称:
 *   Empty()
 *
 * \输入参数:
 *   无
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   该函数清空DIB,释放已分配的内存,并且必要的时候关闭映射文件
 *
 ************************************************************************
 */
void CDib::Empty()
{
	// 关闭内存映射文件的连接
	DetachMapFile();

	// 根据内存分配的状态,调用相应的函数释放信息头
	if(m_nBmihAlloc == crtAlloc) {
		delete [] m_lpBMIH;
	}
	else if(m_nBmihAlloc == heapAlloc) {
		::GlobalUnlock(m_hGlobal);
		::GlobalFree(m_hGlobal);
	}

	// 释放图象数据内存
	if(m_nImageAlloc == crtAlloc) delete []m_lpImage;

	// 释放调色板句柄
	if(m_hPalette != NULL) ::DeleteObject(m_hPalette);

	// 如果创建了BITMAP,则进行释放
	if(m_hBitmap != NULL) ::DeleteObject(m_hBitmap);

	// 重新设置内存分配状态
	m_nBmihAlloc = m_nImageAlloc = noAlloc;

	// 释放内存后,还需要将指针设置为NULL并将相应的数据设置为0
	m_hGlobal = NULL;
	m_lpBMIH = NULL;
	m_lpImage = NULL;
	m_lpvColorTable = NULL;
	m_nColorTableEntries = 0;
	m_dwSizeImage = 0;
	m_lpvFile = NULL;
	m_hMap = NULL;
	m_hFile = NULL;
	m_hBitmap = NULL;
	m_hPalette = NULL;
}


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

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

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


/*************************************************************************
 *
 * \函数名称:
 *   PaletteSize()
 *
 * \输入参数:

⌨️ 快捷键说明

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