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

📄 coding.cpp

📁 电子书《数字图像处理学》Visual C++实现 郎锐编写 所附源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// ************************************************************************
//  文件名:Coding.cpp
//
//  图像编码压缩、解压缩函数库:
//
//	LoadJPG()			- 装载JPEG图象(解压用)
//	SaveJPG()			- 保存JPEG图象(压缩用)
//	SaveBMP()			- 保存BMP图象到文件(解压用)
//	LoadBMP()			- 从文件装载BMP图象(压缩用)
//  DIBToPCX()			- 将DIB保存为PCX文件
//  PCXToDIB()			- 读取PCX文件
//	Huffman()			- 哈夫曼编码
//	Shannon_Fannon()	- 仙农-弗诺编码
//	DIBToGIF()			- 将DIB保存到GIF文件
//	LZW_Encode()		- 对图象进行LZW编码
//	OutputCode()		- 为GIF-LZW算法输出一个编码
//	GIFToDIB()			- 读取GIF到DIB
//	LZW_Decode()		- 对LZW编码进行解码
//	ReadGIF()			- 读取指定GIF文件中的图像编码
//
//*************************************************************************

#include "stdafx.h"
#include "dip_system.h"
#include "Coding.h"
#include "JPEGfile.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//	Dib文件头标志(字符串"BM",写DIB时用到该常数)
#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')

/////////////////////////////////////////////////////////////////////////////
// CCoding

CCoding::CCoding()
{
}

CCoding::~CCoding()
{
}


BEGIN_MESSAGE_MAP(CCoding, CWnd)
	//{{AFX_MSG_MAP(CCoding)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CCoding message handlers

/*************************************************************************
 *
 * 函数名称:
 *   SaveJPG()
 *
 * 参数:
 *   CDIP_SystemDoc* pDoc	- 文档指针
 *	 CString fileName		- 保存文件路径
 *
 * 返回值:
 *   void			    - 无返回值
 *
 * 说明:
 *   该函数对图象进行JPEG编码压缩
 *
 ************************************************************************/

void CCoding::SaveJPG(CDIP_SystemDoc* pDoc, CString fileName)
{
	// 临时缓存
	BYTE *buf;
	buf = NULL;

	// 获取文档尺寸
	CSize size = pDoc->GetDocSize();
	UINT width = size.cx;
	UINT height = size.cy;

	buf = LoadBMP(pDoc->m_strCurrentFile, &width, &height);

	// 压缩位图到JPEG文件,函数的最后参数标明压缩质量(1 - 100)
	JpegFile::RGBToJpegFile(fileName, buf, width, height, TRUE, 50);
}


/*************************************************************************
 *
 * 函数名称:
 *   LoadJPG()
 *
 * 参数:
 *   HDIB hDIB				- DIB句柄
 *   CDIP_SystemDoc* pDoc	- 文档指针
 *	 CString fileName		- 装载文件路径
 *
 * 返回值:
 *   void			    - 无返回值
 *
 * 说明:
 *   该函数对图象进行JPEG编码解压缩
 *
 ************************************************************************/

void CCoding::LoadJPG(HDIB hDIB, CDIP_SystemDoc* pDoc, CString fileName)
{
	// 临时缓存
	BYTE *buf;
	buf = NULL;

	// JPEG图象高度、宽度
	UINT width = 0;
	UINT height = 0;

	// 读到临时缓存
	buf = JpegFile::JpegFileToRGB(fileName, &width, &height);

	// 交换红绿象素
	JpegFile::BGRFromRGB(buf, width, height);

	// 垂直翻转显示
	JpegFile::VertFlipBuf(buf, width * 3, height);

	// 保存解压后的数据到临时位图文件
	SaveBMP("Temp.bmp", buf, width, height);

	// 装载临时位图文件
	pDoc->OnOpenDocument("Temp.bmp");

	// 删除临时文件
	::DeleteFile("Temp.bmp");

	// 初始化标记为FALSE
	pDoc->SetModifiedFlag(TRUE);
}


/*************************************************************************
 *
 * 函数名称:
 *   SaveBMP()
 *
 * 参数:
 *	 CString fileName		- 保存文件路径
 *	 BYTE* buf				- BGR缓存
 *	 UINT width				- 宽度
 *	 UINT height			- 高度
 *
 * 返回值:
 *   void			    - 无返回值
 *
 * 说明:
 *   该函数把BMP图象从内存保存到文件
 *
 ************************************************************************/

void CCoding::SaveBMP(CString fileName,	BYTE * buf,	UINT width,	UINT height)
{
	// 位图文件头
	char m1 = 'B';
	char m2 = 'M';
	short res1 = 0;
    short res2 = 0;
    long pixoff = 54;

	// 宽度
	DWORD widthDW = WIDTHBYTES(width * 24);

	// 文件长度
	long bmfsize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + widthDW * height;	
	
	// 文件指针
	long byteswritten = 0;

	// 位图信息头
	BITMAPINFOHEADER header;
  	header.biSize = 40; 		   		    // 头大小
	header.biWidth = width;
	header.biHeight = height;
	header.biPlanes = 1;
	header.biBitCount = 24;					// 24位
	header.biCompression = BI_RGB;			// 非压缩
	header.biSizeImage = 0;
	header.biXPelsPerMeter = 0;
	header.biYPelsPerMeter = 0;
	header.biClrUsed = 0;
	header.biClrImportant = 0;

	// 二进制写方式打开文件
	FILE *fp;	
	fp = fopen(fileName, "wb");

	// 写文件头
	fwrite((BYTE*)&(m1), 1, 1, fp); 
	byteswritten += 1;
	fwrite((BYTE*)&(m2), 1, 1, fp); 
	byteswritten += 1;
	fwrite((long*)&(bmfsize), 4, 1, fp);
	byteswritten += 4;
	fwrite((int*)&(res1), 2, 1, fp);
	byteswritten += 2;
	fwrite((int*)&(res2), 2, 1, fp);
	byteswritten += 2;
	fwrite((long*)&(pixoff), 4, 1, fp);
	byteswritten += 4;

	// 写位图信息头
	fwrite((BITMAPINFOHEADER *)&header, sizeof(BITMAPINFOHEADER), 1, fp);
	
	// 移动指针
	byteswritten += sizeof(BITMAPINFOHEADER);
	
	// 临时变量
	long row = 0;
	long rowidx;
	long row_size;
    long rc;

	// 行大小
	row_size = header.biWidth * 3;
	
	// 保存位图阵列
	for (row = 0; row < header.biHeight; row++)
	{
		rowidx = (long unsigned)row * row_size;						      

		// 写一行
		rc = fwrite((void *)(buf + rowidx), row_size, 1, fp);
		if (rc != 1) 
			break;
		byteswritten += row_size;	

		for (DWORD count = row_size; count < widthDW; count++) 
		{
			char dummy = 0;
			fwrite(&dummy, 1, 1, fp);
			byteswritten++;							  
		}
	}

	// 关闭文件
	fclose(fp);
}


/*************************************************************************
 *
 * 函数名称:
 *   LoadBMP()
 *
 * 参数:
 *	 CString fileName		- 装载路径
 *	 UINT width				- 宽度
 *	 UINT height			- 高度
 *
 * 返回值:
 *   BYTE*					- 读取图象缓存首地址
 *
 * 说明:
 *   该函数把BMP图象从文件装载到内存
 *
 ************************************************************************/

BYTE* CCoding::LoadBMP(CString fileName, UINT *width, UINT *height)
{
	BITMAP inBM;
	BYTE m1,m2;
    long filesize;
    short res1,res2;
    long pixoff;
    long bmisize;                    
    long compression;
    unsigned long sizeimage;
    long xscale, yscale;
    long colors;
    long impcol;
    
	// 初始化
	BYTE *outBuf = NULL;
	*width = 0;
	*height = 0;
	DWORD m_bytesRead = 0;

	// 以二进制读方式打开文件
	FILE *fp;
	fp = fopen(fileName, "rb");
	
	// 读取文件
	if (fp != NULL)
	{
		// 检验BMP标志
	    long rc;
		rc = fread((BYTE*)&(m1), 1, 1,fp);
		m_bytesRead += 1;
		if (rc == -1) 
		{
			fclose(fp); 
			return NULL;
		}

		rc = fread((BYTE*)&(m2), 1, 1,fp);
		m_bytesRead += 1;
		if ((m1!='B') || (m2!='M')) 
		{
			fclose(fp);
			return NULL;
        }
        
		// 读文件头信息
		rc = fread((long*)&(filesize), 4, 1, fp); 
		m_bytesRead += 4;

		if (rc != 1)
		{
			fclose(fp); 
			return NULL;
		}

		rc = fread((int*)&(res1), 2, 1, fp); 
		m_bytesRead += 2;

		if (rc != 1) 
		{
			fclose(fp); 
			return NULL;
		}

		rc = fread((int*)&(res2), 2, 1, fp); 
		m_bytesRead += 2;
		if (rc != 1)
		{
			fclose(fp); 
			return NULL;
		}

		rc = fread((long*)&(pixoff), 4, 1, fp);
		m_bytesRead += 4;
		if (rc != 1) 
		{ 
			fclose(fp); 
			return NULL;
		}

		rc = fread((long*)&(bmisize), 4, 1, fp);
		m_bytesRead += 4;
		if (rc != 1) 
		{
			fclose(fp); 
			return NULL;
		}

		rc = fread((long*)&(inBM.bmWidth), 4, 1, fp);
		m_bytesRead += 4;
		if (rc != 1) 
		{
			fclose(fp);
			return NULL;
		}

		rc = fread((long*)&(inBM.bmHeight), 4, 1, fp);
		m_bytesRead += 4;
		if (rc != 1)
		{
			fclose(fp); 
			return NULL;
		}

		rc = fread((int*)&(inBM.bmPlanes), 2, 1, fp); 
		m_bytesRead += 2;
		if (rc != 1) 
		{
			fclose(fp);
			return NULL;
		}

		rc = fread((int*)&(inBM.bmBitsPixel), 2, 1, fp);
		m_bytesRead += 2;
		if (rc != 1)
		{
			fclose(fp); 
			return NULL;
		}

		rc = fread((long*)&(compression), 4, 1, fp);
		m_bytesRead += 4;
		if (rc != 1) 
		{
			fclose(fp);
			return NULL;
		}

		rc = fread((long*)&(sizeimage), 4, 1, fp);
		m_bytesRead += 4;
		if (rc != 1) 
		{
			fclose(fp); 
			return NULL;
		}

		rc = fread((long*)&(xscale), 4, 1, fp);
		m_bytesRead += 4;

		if (rc != 1) 
		{
			fclose(fp);
			return NULL;
		}

		rc = fread((long*)&(yscale), 4, 1, fp); 
		m_bytesRead += 4;
		if (rc != 1)
		{
			fclose(fp);
			return NULL;
		}

		rc = fread((long*)&(colors), 4, 1, fp);
		m_bytesRead += 4;
		if (rc != 1)
		{
			fclose(fp); 
			return NULL;
		}

		rc = fread((long*)&(impcol), 4, 1, fp);
		m_bytesRead += 4;
		if (rc != 1)
		{
			fclose(fp);
			return NULL;
		}

		// 对RLE文件不做处理
		if (compression != BI_RGB) 
		{
	    	fclose(fp);
	    	return NULL;
	    }

		if (colors == 0) 
			colors = 1 << inBM.bmBitsPixel;
		
		// 读取颜色表
		RGBQUAD *colormap = NULL;

		if ((long)m_bytesRead > pixoff) 
		{
			fclose(fp);
			delete [] colormap;
			fclose(fp);
			return NULL;
		}

		while ((long)m_bytesRead < pixoff) 
		{
			char dummy;
			fread(&dummy,1,1,fp);
			m_bytesRead++;
		}

		int w = inBM.bmWidth;
		int h = inBM.bmHeight;

		// 设置输出参数
		*width = w;
		*height = h;

		long row_size = w * 3;

		long bufsize = (long)w * 3 * (long)h;

		// 分配内存
		outBuf = (BYTE*) new BYTE [bufsize];
		if (outBuf != NULL) 
		{
			long row = 0;
			long rowOffset = 0;

			// 读取点阵数据
			for (row = inBM.bmHeight - 1; row >= 0;row--) 
			{
				rowOffset = (long unsigned)row*row_size;						      

				if (inBM.bmBitsPixel == 24)
				{
					for (int col = 0; col < w; col++) 
					{
						long offset = col * 3;
						char pixel[3];

						if (fread((void  *)(pixel), 1, 3, fp) == 3)
						{
							//交换R、B信息
							*(outBuf + rowOffset + offset + 0) = pixel[2];		// r
							*(outBuf + rowOffset + offset + 1) = pixel[1];		// g
							*(outBuf + rowOffset + offset + 2) = pixel[0];		// b
						}

					}

					m_bytesRead += row_size;
					
					while ((m_bytesRead - pixoff) & 3)
					{
						char dummy;
						if (fread(&dummy, 1, 1, fp) != 1)
						{
							delete [] outBuf;
							fclose(fp);
							return NULL;
						}
						m_bytesRead++;
					}
				} 
			}
		}

		if (colormap) 
			delete [] colormap;

		fclose(fp);
    }
	return outBuf;
}

/*************************************************************************
 *
 * 函数名称:
 *   DIBToPCX()
 *
 * 参数:
 *   HDIB hDIB				- DIB句柄
 *   CString strPath	    - 要保存的文件路径
 *
 * 返回值:
 *   BOOL               - 成功返回True,否则返回False。
 *
 * 说明:
 *   该函数将DIB保存为PCX文件。
 *
 *************************************************************************/

BOOL CCoding::DIBToPCX(HDIB hDIB, CString strPath)
{
	// 循环变量
	LONG	i;
	LONG	j;
	LONG	k;
	
	// 中间变量
	BYTE	bChar1;
	BYTE	bChar2;
	
	// 指向源图像象素的指针
	BYTE*	lpSrc;
	
	// 指向编码后图像数据的指针
	BYTE*	lpDst;
	
	// 重复像素计数
	int		iCount;
	
	// 调整顺序:B、G、R
	int	RGB[3] = {2, 1, 0};

	// 打开文件
	CFile file;
	file.Open(strPath, CFile::modeCreate | CFile::modeReadWrite);
	
	// 缓冲区已使用的字节数
	DWORD	dwBuffUsed;
	

⌨️ 快捷键说明

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