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

📄 复件 jpegdoc.cpp

📁 图象压缩算法的实现,十分具有参考价值的,赫赫有名
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// JPEGDoc.cpp : implementation of the CJPEGDoc class
//

#include "stdafx.h"
#include "JPEG.h"
#include "math.h"
#include "JPEGDoc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define PI (double)3.1415926535
unsigned char LumQuantTable[64]={				//luminance标准亮度量化表
/*		16,11,10,16,24, 40, 51, 61,
		12,12,14,19,26, 58, 60, 55,
		14,13,16,24,40, 57, 69, 56,
		14,17,22,29,51, 87, 80, 62,
		18,22,37,56,68, 109,103,77,
		24,35,55,64,81, 104,113,92,
		49,64,78,87,103,121,120,101,
		72,92,95,98,112,100,103,99
*/
		0x8, 0x6, 0x6, 0x7, 0x6, 0x5, 0x8, 0x7,
		0x7, 0x7, 0x9, 0x9, 0x8, 0xa, 0xc, 0x14,
		0xd, 0xc, 0xb, 0xb, 0xc, 0x19,0x12,0x13,
		0xf, 0x14,0x1d,0x1a,0x1f,0x1e,0x1d,0x1a,
		0x1c,0x1c,0x20,0x24,0x2e,0x27,0x20,0x22,
		0x2c,0x23,0x1c,0x1c,0x28,0x37,0x29,0x2c,
		0x30,0x31,0x34,0x34,0x34,0x1f,0x27,0x39,
		0x3d,0x38,0x32,0x3c,0x2e,0x33,0x34,0x32

	};
unsigned char ChrQuantTable[64]={				//chrominance标准色度量化表
/*		17,18,24,47,99,99,99,99,
		18,21,26,66,99,99,99,99,
		24,26,56,99,99,99,99,99,
		47,66,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99
*/
		12,13,13,17,16,17,33,18,
		18,33,69,46,39,46,69,69,
		69,69,69,69,69,69,69,69,
		69,69,69,69,69,69,69,69,
		69,69,69,69,69,69,69,69,
		69,69,69,69,69,69,69,69,
		69,69,69,69,69,69,69,69,
		69,69,69,69,69,69,69,69
/*
		4, 5, 5, 8, 6, 8, 13,10,
		10,13,39,26,19,26,49,49,
		49,49,49,49,49,49,49,49,
		49,49,49,49,49,49,49,49,
		49,49,49,49,49,49,49,49,
		49,49,49,49,49,49,49,49,
		49,49,49,49,49,49,49,49,
		49,49,49,49,49,49,49,49
*/
	};
unsigned char LumDCHuffmanBit[17]={0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};		//亮度DC哈夫曼表的位值	
unsigned char LumDCHuffmanVal[12]={0,1,2,3,4,5,6,7,8,9,10,11};				//亮度DC哈夫曼表的码值
unsigned char LumACHuffmanBit[17]={0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d};	//亮度AC哈夫曼表的位值
unsigned char LumACHuffmanVal[162]={										//亮度AC哈夫曼表的码值
		0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,
		0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
		0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
		0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,
		0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,
		0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
		0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,
		0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
		0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
		0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
		0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,
		0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
		0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
		0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
		0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
		0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,
		0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,
		0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
		0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,
		0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
		0xf9,0xfa
		}; 
unsigned char ChrDCHuffmanBit[17]={0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
unsigned char ChrDCHuffmanVal[12]={0,1,2,3,4,5,6,7,8,9,10,11};
unsigned char ChrACHuffmanBit[17]={0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};
unsigned char ChrACHuffmanVal[162]={		
		0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,	
		0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
		0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
		0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,
		0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,
		0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
		0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,
		0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,
		0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
		0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,
		0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,
		0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
		0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,
		0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,
		0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
		0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,
		0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,
		0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
		0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,
		0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
		0xf9,0xfa
		}; 

static const short zig[8*8]={					//Z型扫描的顺序
		0,1,5,6,14,15,27,28,
		2,4,7,13,16,26,29,42,
		3,8,12,17,25,30,41,43,
		9,11,18,24,31,40,44,53,
		10,19,23,32,39,45,52,54,
		20,22,33,38,46,51,55,60,
		21,34,37,47,50,56,59,61,
		35,36,48,49,57,58,62,63
	};

int ehufco[251],ehufsi[251];
#define WaitCursorBegin()	HCURSOR hcURSOR = SetCursor(LoadCursor(NULL, IDC_WAIT))//定义为等待光标
#define WaitCursorEnd()		SetCursor(hcURSOR)	//定义的等待光标结束,回到默认光标

/////////////////////////////////////////////////////////////////////////////
// CJPEGDoc

IMPLEMENT_DYNCREATE(CJPEGDoc, CDocument)

BEGIN_MESSAGE_MAP(CJPEGDoc, CDocument)
	//{{AFX_MSG_MAP(CJPEGDoc)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CJPEGDoc construction/destruction

CJPEGDoc::CJPEGDoc()
{
	// TODO: add one-time construction code here
	
}

CJPEGDoc::~CJPEGDoc()
{
}

BOOL CJPEGDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)

	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CJPEGDoc serialization

void CJPEGDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

CDib::CDib()
{
	m_pDib=NULL;	//	先设置DIB位图指针为NULL,以便知道位图是否被装载
	m_bit24=0;		//	颜色数初值设为0
	surplus=32;		//	
	EncodeJpeg=0;	//
	for(int i=0;i<64;i++)
		table[i]=0;
}
CDib::~CDib()
{
//	如果位图的指针不为空,将它删除
	if(m_pDib!=NULL)
		delete [] m_pDib;
}

//////////////////////////////////////////////////////
//
//
//
//////////////////////////////////////////////////////
BOOL CDib::Load(const char *pszFilename)
{
	CFile cf;
//	打开一个名为pszFilename的位图文件
	if(!cf.Open(pszFilename,CFile::modeRead))
		return(FALSE);
//	获得文件的大小,并且减去BITMAPFILEHEADER结构,因为不析算把它留在内存中
	DWORD dwDibSize;
	dwDibSize=cf.GetLength()-sizeof(BITMAPFILEHEADER);
	unsigned char *pDib;
	pDib=new unsigned char [dwDibSize];
	if(pDib==NULL)
		return(FALSE);
	BITMAPFILEHEADER BFH;
//	读取文件的头和数据
	if(cf.Read(&BFH,sizeof(BITMAPFILEHEADER))!=sizeof(BITMAPFILEHEADER)||
		BFH.bfType!='MB'||cf.Read(pDib,dwDibSize)!=dwDibSize)		//MB为BMP文件的标识符
	{
//		如果出现错误,释放DIB位图的存储空间
		delete [] pDib;
		return(FALSE);
	}
//	如果类中的位图指针不为空,释放它
	if(m_pDib!=NULL)
		delete m_pDib;
//	将位图结构的指针和大小赋给成员变量
	m_pDib=pDib;
	m_dwDibSize=dwDibSize;
	m_pBIH=(BITMAPINFOHEADER *)m_pDib;
	m_pPalette=(RGBQUAD *)&m_pDib[sizeof(BITMAPINFOHEADER)];
//	计算调色板的颜色数目
	m_nPaletteEntries=1<<m_pBIH->biBitCount;
	if(m_pBIH->biBitCount>8)
		m_nPaletteEntries=0;
	else if(m_pBIH->biClrUsed!=0)
		m_nPaletteEntries=m_pBIH->biClrUsed;
//	让m_pDibBits指向实际的DIB位数据
	m_pDibBits=&m_pDib[sizeof(BITMAPINFOHEADER)+m_nPaletteEntries*sizeof(RGBQUAD)];
//	如果有一个调色板,释放它
	if(m_Palette.GetSafeHandle()!=NULL)
		m_Palette.DeleteObject();
//	创建调色板
	if(m_nPaletteEntries!=0)
	{
//		分配LOGPALETTE结构的存储空间
		LOGPALETTE *pLogPal=(LOGPALETTE *)new char [sizeof(LOGPALETTE)+
			m_nPaletteEntries*sizeof(PALETTEENTRY)];
		if(pLogPal!=NULL)
		{
//			设置调色板的版本为0x300,保存调色板的数目
			pLogPal->palVersion=0x300;
			pLogPal->palNumEntries=m_nPaletteEntries;
//			将RGB值放入每个PALETTEENTRY项
			for(int i=0;i<m_nPaletteEntries;i++)
			{
				pLogPal->palPalEntry[i].peRed=m_pPalette[i].rgbRed;
				pLogPal->palPalEntry[i].peGreen=m_pPalette[i].rgbGreen;
				pLogPal->palPalEntry[i].peBlue=m_pPalette[i].rgbBlue;
			}
//			创建调色板对象并删除PALETTEENTRY的内存
			m_Palette.CreatePalette(pLogPal);
			delete [] pLogPal;
		}
	}
//	如果是24位图,设置m_bit24=1,并读入位数据给data数组,不是24位图,m_bit24=0
	if(m_pBIH->biBitCount==8)
	{
//		AfxMessageBox("此文件不是24位的位图文件夹!!!");
		m_bit24=0;
	}
	else if(m_pBIH->biBitCount==24)
		m_bit24=1;

	width=m_pBIH->biWidth;			//得到BMP文件的宽度
	height=m_pBIH->biHeight;		//得到BMP文件的高度
	DWORD offset=BFH.bfOffBits;		//得到BMP文件的数据偏移量
	if(width>1024||height>1024)
	{
		AfxMessageBox("本软件目前只能显示小于等于1024*1024的BMP图像,请确认图像!!!");
//		exit(0);
		return(FALSE);
	}

/*	CString x;
	x.Format("m_bit24=%d",m_bit24);
	AfxMessageBox(x);


	DWORD filesize=BFH.bfSize;
	WORD type=BFH.bfType;
	int first=type;
	int second=type>>8;
	CString st;
	st.Format("BMP文件标识符:%c%c  图像宽度为:%ld  图像高度为:%ld  偏移量为:%ld  文件大小:%ld字节",first,second,width,height,offset,filesize);
	AfxMessageBox(st);
*/

	LONG i,j;
	if(m_bit24==1)
	{
		for(i=0;i<1024;i++)
		{
			data[i]=new RGBData[1024];
			for(j=0;j<1024;j++)			
			{
				data[i][j].Blue=0;
				data[i][j].Green=0;
				data[i][j].Red=0;
			}
		}
		cf.Seek(offset,CFile::begin);	//定位至位数据的开始处
		for(LONG y=height-1;y>=0;y--)
		{
			cf.Read(data[y],width*3);	//数组data存储24位色BMP文件的图像数据
			cf.Seek(width%4,CFile::current);	//*****  此处很重要,位图行的字节数等于
		}										//行除以4乘以3,再加上行除以4的余。
		cf.Close();
	}
	else if(m_bit24==0)
	{
		for(i=0;i<1024;i++)
		{
			hdata[i]=new unsigned char [1024];
			for(j=0;j<1024;j++)
				hdata[i][j]=0;
		}
		cf.Seek(offset,CFile::begin);	//定位至位数据的开始处
//		从最后一行开始读数据,BMP图像文件依次从最后一行到第一行进行存储
		for(LONG y=height-1;y>=0;y--)
		{
			cf.Read(hdata[y],width);	//数组hdata存储灰度图像的数据
//			cf.Seek(width%4,CFile::current);	//灰度图像不用考虑这种情况
		}
		cf.Close();	
	}
	return(TRUE);
}

/*CFile类
		CFile与CArchive类一起支持对MFC对象的串行化,常用的成员函数为:
		Open函数		用一个错误测试安全地打开一个文件
		Close函数		关闭一个文件并删除该文件
		Read函数		从文件的当前位置处读出一段数据给缓冲区
		ReadHuge函数	从文件的当前位置处读出一段可大于64K的数据给缓冲区
		Write函数		将一段数据写入文件的当前位置处
		WriteHuge函数	将一段可大于64K的数据写入文件的当前位置处
		Seek函数		用于定位当前文件指针至任意处
		GetLength函数	函数用一获取文件长(以字节计)
*/
////////////////////////////////////////
//
//				BMP文件的存储
//
////////////////////////////////////////
BOOL CDib::Save(const char *pszFilename)
{
//如果没有数据,不能保存
	if(m_pDib==NULL)
		return(FALSE);
	CFile cf;
	if(!cf.Open(pszFilename,CFile::modeCreate|CFile::modeWrite))
		return(FALSE);
	BITMAPFILEHEADER BFH;
//	预设BITMAPFILEHEADER结构的所有量全为0
	memset(&BFH,0,sizeof(BITMAPFILEHEADER));
	BFH.bfType='MB';
	BFH.bfSize=sizeof(BITMAPFILEHEADER)+m_dwDibSize;
	BFH.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
		m_nPaletteEntries*sizeof(RGBQUAD);
//	写具体数据到指定文件
	cf.Write(&BFH,sizeof(BITMAPFILEHEADER));
	cf.Write(m_pDib,m_dwDibSize);
	return(TRUE);
}

/////////////////////////////////////////
//    
//				JPEG文件的存储  
//
/////////////////////////////////////////
BOOL CDib::SaveJpeg(const char *pszFilename)
{
	WaitCursorBegin();									//显示等待光标
	if(!file.Open(pszFilename,CFile::modeCreate|CFile::modeWrite))
		return(FALSE);
	unsigned short int filehead=0xd8ff;					//JPEG标识符FFD8(16bit)
	unsigned char app0[18]={0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46,0x00,0x01,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x00};
	unsigned char quant0[5]={0xFF,0xDB,0x00,0x43,0x00};	//量化表标记头的前几个字节,后接具体的量化表。
	unsigned char quant1[5]={0xFF,0xDB,0x00,0x43,0x01};
	unsigned char GreyFrame[13]={0xff,0xc0,0x00,0x0b,0x08,0,0,0,0,0x01,0x01,0x11,0x00};
	unsigned char ColorFrame[19]={0xff,0xc0,0x00,0x11,0x08,0,0,0,0,0x03,0x01,0x22,0x00,
								0x02,0x11,0x01,0x03,0x11,0x01 };	//真彩色帧开始的标识符
	unsigned char LumDchuffman[5]={0xff,0xc4,0x00,0x1f,0x00};
	unsigned char LumAchuffman[5]={0xff,0xc4,0x00,0xb5,0x10};
	unsigned char ChrDchuffman[5]={0xff,0xc4,0x00,0x1f,0x01};
	unsigned char ChrAchuffman[5]={0xff,0xc4,0x00,0xb5,0x11};
	unsigned char GreySos[10]={0xff,0xda,0x00,0x08,0x01,0x01,0x00,0x00,0x3f,0x00};//扫描开始(SOS)标记符
	unsigned char ColorSos[14]={0xff,0xda,0x00,0x0c,0x03,0x01,0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00};//扫描开始(SOS)标记符
	unsigned char eoi[2]={0xff,0xd9};					//文件结束标识符End of Image
	GreyFrame[5]=ColorFrame[5]=height/256;
	GreyFrame[6]=ColorFrame[6]=height%256;	//图像的高度
	GreyFrame[7]=ColorFrame[7]=width/256;
	GreyFrame[8]=ColorFrame[8]=width%256;	//图像的宽度	
/////////////////////////////////////////////////////////////////////////////////
	file.Write(&filehead,sizeof(unsigned short int));	//写JPEG标识符FF D8
	file.Write(app0,18);								//写app0
	file.Write(quant0,5);									//写量化表标记头前5个字节
	file.Write(LumQuantTable,64);						//写量化表的64个字节
	if(m_bit24==1)

⌨️ 快捷键说明

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