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

📄 cdib.cpp

📁 做成界面的基于小波的spiht算法压缩解压缩编码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//cdib.cpp 

#include "StdAfx.h"
#include "cdib.h"



IMPLEMENT_SERIAL(CDib,CObject,0);
/***********************************************************
* \函数名称:
*          CDib()
* \输入参数:
*           无
* \返回值:
*           无
* \说明:
*        构造函数
*************************************************************
*/
CDib::CDib()
{
	m_hFile = NULL;
	m_hBitmap = NULL;
	m_hPalette = NULL;
	m_nBmihAlloc = m_nImageAlloc = noAlloc;
	Empty();
}

/***********************************************************
* \函数名称:
*          CDib()
* \输入参数:
*           CSize size   -位图尺寸
*			int nBitCount -像素位数
* \返回值:
*           无
* \说明:
*        构造函数
*        根据给定尺寸和像素位数构造CDib对象,并对信息头和调色板分配内存
*        但并没有给位图数据分配内存
************************************************************
*/
CDib::CDib(CSize size,int nBitCount)
{
	m_hFile = NULL;
	m_hBitmap = NULL;
	m_hPalette = NULL;
	m_nBmihAlloc = m_nImageAlloc = noAlloc;
	Empty();

	ComputePaletteSize(nBitCount);       //根据像素位数计算调色板尺寸
    //分配DIB信息头和调色板的内存
	m_lpBMIH = (LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFOHEADER) 
		+ sizeof(RGBQUAD) * m_nColorTableEntries];	
	m_nBmihAlloc = crtAlloc;            //设置信息头内存分配状态
	//设置信息头中的信息
	m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER);
	m_lpBMIH->biWidth = size.cx;
	m_lpBMIH->biHeight = size.cy;
	m_lpBMIH->biPlanes = 1;
	m_lpBMIH->biBitCount = nBitCount;
	m_lpBMIH->biCompression = BI_RGB;
	m_lpBMIH->biSizeImage = 0;
	m_lpBMIH->biXPelsPerMeter = 0;
	m_lpBMIH->biYPelsPerMeter = 0;
	m_lpBMIH->biClrUsed = m_nColorTableEntries;
	m_lpBMIH->biClrImportant = m_nColorTableEntries;

	ComputeMetrics();                  //计算图像数据内存的大小,并设置DIB的调色板的指针
    //将此DIB的调色板初始化为0
	memset(m_lpvColorTable,0,sizeof(RGBQUAD) * m_nColorTableEntries);

	//暂时不分配图像数据内存
	m_lpImage = NULL;
}

/***********************************************************
* \函数名称:
*          ~CDib()
* \输入参数:
*           无
* \返回值:
*           无
* \说明:
*        析构函数,并释放所有分配的DIB内存
************************************************************
*/
CDib::~CDib()
{
	Empty();
}

/***********************************************************
* \函数名称:
*          Read()
* \输入参数:
*           CFile* pFile   -指向CFile对象的指针
* \返回值:
*         BOOL             -如果成功,则返回TRUE
* \说明:
*       该函数从一个文件读入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;
		}
		//计算信息头加上调色板的大小,并分配内存
		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;
	}
	//返回
	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("Read 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());
	}
}

/***********************************************************
* \函数名称:
*          GetDibSaveDim()
* \输入参数:
*         无
* \返回值:
*         CSize         -DIB实际存储的高度和宽度
* \说明:
*       该函数用来得到dib的实际存储宽度(DWORD对齐)
************************************************************
*/
CSize CDib::GetDibSaveDim()
{
	CSize sizeSaveDim;
	sizeSaveDim.cx = (m_lpBMIH->biWidth * m_lpBMIH->biBitCount + 31)/32*4;
	sizeSaveDim.cy = m_lpBMIH->biHeight;
	return sizeSaveDim;
}

/***********************************************************
* \函数名称:
*          GetDimensions()
* \输入参数:
*         无
* \返回值:
*         CSize         -DIB的高度和宽度
* \说明:
*       该函数返回以像素表示的dib的宽度和高度
************************************************************
*/
CSize CDib::GetDimensions()
{
	if(m_lpBMIH == NULL) return CSize(0,0);
	return CSize((int)m_lpBMIH->biWidth,(int)m_lpBMIH->biHeight);
}

/***********************************************************
* \函数名称:
*          GetPixel()
* \输入参数:
*         int x         -像素在X轴的坐标
*         int y         -像素在Y轴的坐标
* \返回值:
*         RGBQUAD       -返回DIB在该点真实的颜色
* \说明:
*       该函数得到DIB图像在该点真实的颜色
************************************************************
*/
RGBQUAD CDib::GetPixel(int x, int y)
{
	RGBQUAD cColor;
	//CPalette* pPaletteTemp;
	switch(m_lpBMIH->biBitCount)
	{
	case 1:
		if(1<<(7-x%8)&*(LPBYTE)(m_lpImage + GetPixelOffset(x,y)))
		{
			cColor.rgbBlue = 255;
			cColor.rgbGreen = 255;
			cColor.rgbRed = 255;
			cColor.rgbReserved =0;
		}
		else
		{
			cColor.rgbBlue = 0;
			cColor.rgbGreen = 0;
			cColor.rgbRed = 0;
			cColor.rgbReserved = 0;
		}
		break;
	case 4:
		{
			int nIndex = (*(LPBYTE)(m_lpImage + GetPixelOffset(x,y))&
				(x%2?0x0f:0xf0))>>(x%2?0:4);
			LPRGBQUAD pDibQuad = (LPRGBQUAD)(m_lpvColorTable) + nIndex;
			cColor.rgbBlue = pDibQuad->rgbBlue;
			cColor.rgbGreen = pDibQuad->rgbGreen;
			cColor.rgbRed = pDibQuad->rgbRed;
			cColor.rgbReserved = 0;
		}
		break;
	case 8:
		{
			int nIndex = *(BYTE*)(m_lpImage + GetPixelOffset(x,y));
			LPRGBQUAD pDibQuad = (LPRGBQUAD)(m_lpvColorTable) + nIndex;
			cColor.rgbBlue = pDibQuad->rgbBlue;
			cColor.rgbGreen = pDibQuad->rgbGreen;
			cColor.rgbRed = pDibQuad->rgbRed;
			cColor.rgbReserved = 0;
		}
		break;
	default:
		int nIndex = *(BYTE*)(m_lpImage + GetPixelOffset(x,y));

		cColor.rgbBlue = m_lpImage[nIndex];
		cColor.rgbGreen = m_lpImage[nIndex+1];
		cColor.rgbRed = m_lpImage[nIndex+2];
		cColor.rgbReserved = 0;
		break;
	}
	return cColor;
}

/***********************************************************
* \函数名称:
*          GetPixelOffset()
* \输入参数:
*         int x         -像素在X轴的坐标
*         int y         -像素在Y轴的坐标
* \返回值:
*         int           -返回像素在图像数据块中的真实地址
* \说明:
*       由于DIB结构中对图像数据排列的方式从下到上,从左到右的,所以需要转换
************************************************************
*/
LONG CDib::GetPixelOffset(int x, int y)
{
	CSize sizeSaveDim;
	sizeSaveDim =GetDibSaveDim();

	LONG lOffset = (LONG)(sizeSaveDim.cy - y - 1) * sizeSaveDim.cx +
		x/(8/m_lpBMIH->biBitCount);
	return lOffset;
}

/***********************************************************
* \函数名称:
*          PaletteSize()
* \输入参数:
*         无
* \返回值:
*         DWORD         -返回调色板的尺寸
* \说明:
*       该函数计算调色板所需的尺寸
************************************************************
*/
WORD CDib::PaletteSize()
{
	//临时变量
	WORD NumColors;
	LPBITMAPINFOHEADER lpbi = m_lpBMIH;

	//如果biClrUsed为零,且图像像素位数<8,则计算调色板用到的表项数
	NumColors = ((lpbi)->biClrUsed == 0&&(lpbi)->biBitCount<=8
		?(int)(1<<(int)(lpbi)->biBitCount):(int)(lpbi)->biClrUsed);

	//根据颜色表表示的字节数计算调色板的尺寸
	if(lpbi->biSize == sizeof(BITMAPCOREHEADER))
		return NumColors * sizeof(RGBTRIPLE);
	else
		return NumColors * sizeof(RGBQUAD);
}

/***********************************************************
* \函数名称:
*          IsEmpty()
* \输入参数:
*         无
* \返回值:
*         BOOL         -如果为空,则返回TRUE
* \说明:
*       判断信息头和图像数据是否为空
************************************************************
*/

⌨️ 快捷键说明

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