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

📄 encode.cpp

📁 基于块方向的图像无损压缩代码
💻 CPP
字号:
#include "stdafx.h"
#include "fp_preprocess.h"
#include "fpdirectionimage.h"

BOOL		ErrorSet ;
short int **TempData;
extern void EncodingImage(short int **ImageData,PBYTE DirectionBlock[BLOCK_NO*2],long width,long height,CString OutputFileName);
/////////////////////////////////////////////////////
///used in coding
	FILE     *ifp,*ofp;
	int      **in_buf;
	int	     **out_buf;

	struct Image_Coord { int x, y; };

	struct Image_Coord pdim, dim, x, a, b, c, d;


	int bit_set_mask[] =
	{0x00000001,0x00000002,0x00000004,0x00000008,
	0x00000010,0x00000020,0x00000040,0x00000080,
	0x00000100,0x00000200,0x00000400,0x00000800,
	0x00001000,0x00002000,0x00004000,0x00008000,
	0x00010000,0x00020000,0x00040000,0x00080000,
	0x00100000,0x00200000,0x00400000,0x00800000,
	0x01000000,0x02000000,0x04000000,0x08000000,
	0x10000000,0x20000000,0x40000000,0x80000000};

	int current_write_byte;
	int current_read_byte;
	int read_position;
	int write_position;
	int  count;

	int J[] = {0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,
           4,5,5,6,6,7,7,8,9,10,11,12,13,14,15};

	int P, T1, T2, T3, MAXVAL;
	int Ix, Ra, Rb, Rc, Rd;
	int EOLine;
	int RANGE;
	int A[367], B[365], C[365], N[367], Nn[367];
	int RUNindex, RUNval, RUNcnt;
	int D[3], Q[3], q;
	int SIGN;
	int Px, Rx;
	int Errval, MErrval, EMErrval;
	int k, TEMP;
	int RItype, map;
	/* updated variables */
	int LIMIT, qbpp, bpp;
///////////////////////////////////////////

void predictor(short int **image,short int *DPCM,short int startx,
			   short int starty, short int width,short int height,short int deta)
{
	short int i,j;

	DPCM[0]=image[starty][startx];
	for(i=1;i<width;i++)
		DPCM[i]=image[starty][startx+i]-image[starty][startx+i-1];
	for(j=1;j<height;j++)
	{
		DPCM[j*width]=image[starty+j][startx]-image[starty+j-1][startx];
		for(i=1;i<width;i++)
		{
			switch(deta)
			{
				case 0://direction:0
					DPCM[j*width+i]=image[starty+j][startx+i-1];
					break;
				case 1://direction:22.5
					DPCM[j*width+i]=(image[starty+j-1][startx+i+2]+image[starty+j-1][startx+i+3])/2;
					break;
				case 2://direction:45
					DPCM[j*width+i]=image[starty+j-1][startx+i+1];
					break;
				case 3://direction:67.5
					DPCM[j*width+i]=(image[starty+j-1][startx+i]+image[starty+j-1][startx+i+1])/2;
					break;
				case 4://direction:90
					DPCM[j*width+i]=image[starty+j-1][startx+i];
					break;
				case 5://direction:112.5
					DPCM[j*width+i]=(image[starty+j-1][startx+i-1]+image[starty+j-1][startx+i])/2;
					break;
				case 6://direction:135
					DPCM[j*width+i]=image[starty+j-1][startx+i-1];
					break;
				case 7://direction:157.5
					DPCM[j*width+i]=(image[starty+j][startx+i-1]+image[starty+j-1][startx+i-1])/2;
					break;
				case 8://direction:nothing
					DPCM[j*width+i]=image[starty+j][startx+i-1]+(image[starty+j-1][startx+i]-image[starty+j-1][startx+i-1])/2;
					break;
				default:
					break;
			}
			DPCM[j*width+i]=image[starty+j][startx+i]-DPCM[j*width+i];
		}
	}
	for(j=0;j<height;j++)
		for(i=0;i<width;i++)
			TempData[starty+j][startx+i]=DPCM[j*width+i];

}

void SmoothDirection2(PBYTE DirectionBlock[BLOCK_NO*2])
{
	HANDLE hBlock; 
	BYTE *Block;
	short x,y;           
	BYTE i,k; 
	short n1,n2;             
	short ax,ay;
	BYTE Direction[9]; 
	BYTE FirstDirection,SecondDirection;
	
	hBlock = GlobalAlloc(GHND,BLOCK_NO*BLOCK_NO*4);
	if (!hBlock)
	{
		AfxMessageBox("not enough memory1 in preproc!");
		return;
	}
	Block = (BYTE *)GlobalLock(hBlock);
	if (Block==NULL)
	{
		AfxMessageBox( "not enough memory1 in preproc!");
		return;
	}
	for(x=0;x<BLOCK_NO*2;x++)
		for(y=0;y<BLOCK_NO*2;y++)
			Block[x*BLOCK_NO*2+y]=DirectionBlock[x][y];
	for(x=1;x<BLOCK_NO*2-1;x++)
		for(y=1;y<BLOCK_NO*2-1;y++)
		{
			for(i=0;i<8;i++)
				Direction[i]=0;
			for(ax=-1;ax<2;ax++)
				for(ay=-1;ay<2;ay++)
				{      
					k=Block[(x+ax)*BLOCK_NO*2+y+ay];
					Direction[k]++;
				}
			FirstDirection=0;  
			SecondDirection=1;
			for(i=1;i<8;i++)
				if(Direction[i]>Direction[FirstDirection])
				{
					SecondDirection=FirstDirection;
					FirstDirection=i;
				}
				else 
				{
					if(Direction[i]>Direction[SecondDirection])
						SecondDirection=i;                
				}
		    k=DirectionBlock[x][y];
			if(Direction[FirstDirection]>=7)//5) 
				 DirectionBlock[x][y]=FirstDirection; 
			else if(Direction[FirstDirection]>=5 && 
				 Direction[k] < 2 && k != SecondDirection)
			 	DirectionBlock[x][y]=FirstDirection;
			else if(Direction[FirstDirection]>=5 && 
 				 		abs( (short)FirstDirection-k) != 1 &&
 				 		abs( (short)FirstDirection-k) != 7)
			 	DirectionBlock[x][y]=FirstDirection;		
 			else 
			{
				n1=(short)FirstDirection-1;
				if(n1==-1)
					n1=7;
				n2=(short)FirstDirection+1;
				if(n2==8)
					n2=0;	
				if( (Direction[FirstDirection]
					+Direction[n1] >= 6 &&
					DirectionBlock[x][y] != n1) ||
					(Direction[FirstDirection]
					+Direction[n2] >= 6 &&
					DirectionBlock[x][y] != n2) )
					DirectionBlock[x][y]=FirstDirection;
			}	  
		} 
	GlobalUnlock(hBlock);
	GlobalFree(hBlock);
}

void CalculateBlockDirection(unsigned char *lpSourceImage,PBYTE DirectionBlock[BLOCK_NO*2])
{
	HANDLE hImage[DIR_IMAGE_SIZE];
	PBYTE lpImage[DIR_IMAGE_SIZE];
	HANDLE hWeight[DIR_IMAGE_SIZE]; 
	WEIGHT *lpWeight[DIR_IMAGE_SIZE];             //求方向图的权值
	HANDLE 	hDirectionImage[DIR_IMAGE_SIZE];
	PBYTE  lpDirectionImage[DIR_IMAGE_SIZE];
    int AllocSize;  
	int i,j;
	
	for(i=0; i<DIR_IMAGE_SIZE; i++)
	{
		hImage[i] = (HGLOBAL)GlobalAlloc(GHND,DIR_IMAGE_SIZE);
		if(!hImage[i])
		{
			AfxMessageBox("not enough memory in preprocess to hImage!");
			return;
		}
		lpImage[i] = (PBYTE)GlobalLock(hImage[i]);
		if(lpImage[i]==NULL)
		{
			AfxMessageBox("not enough memory to lpImage!");
			return ;  
		}
    }

	AllocSize=(unsigned long)DIR_IMAGE_SIZE*sizeof(WEIGHT);
	for(i=0; i<DIR_IMAGE_SIZE; i++)
	{
		hWeight[i] = (HGLOBAL)GlobalAlloc(GHND,AllocSize);
		if(!hWeight[i])
		{
			AfxMessageBox("not enough memory1 in preproc!");
			return;
		}									
		lpWeight[i] = (WEIGHT *)GlobalLock(hWeight[i]);									
		if(lpWeight[i] == NULL)
		{                    
			AfxMessageBox("not enough memory13!");
			return;
		}  
	}

	AllocSize=(ULONG)DIR_IMAGE_SIZE*sizeof(BYTE);
    for(i=0; i<DIR_IMAGE_SIZE; i++)
	{
		hDirectionImage[i]=(HGLOBAL)GlobalAlloc(GHND,AllocSize);
		if(!hDirectionImage[i])
		{
			AfxMessageBox("not enough memory1 in preproc!");
			return;
		}									
		lpDirectionImage[i] = (BYTE *)GlobalLock(hDirectionImage[i]);									
		if(lpDirectionImage[i] == NULL)
		{                    
			AfxMessageBox("not enough memory14!");
			return;
		}        
    }

	for(j=0;j<DIR_IMAGE_SIZE;j++)
		for(i=0;i<DIR_IMAGE_SIZE;i++)
			lpImage[j][i]=lpSourceImage[(j+48)*DIR_IMAGE_SIZE+i+48];

	DirectionProcess(lpImage, lpWeight, DirectionBlock,lpDirectionImage);     

    SmoothDirection2(DirectionBlock); 
    SmoothDirection2(DirectionBlock);
	SmoothDirection2(DirectionBlock);    //DirectionBlock中为文线垂直方向

	for(i=0;i<DIR_IMAGE_SIZE;i++)
	{
		GlobalUnlock(hImage[i]);
		GlobalFree(hImage[i]);

		GlobalUnlock(hWeight[i]);
		GlobalFree(hWeight[i]);

		GlobalUnlock(hDirectionImage[i]);
		GlobalFree(hDirectionImage[i]);

	}
}

//read the data from the input file
unsigned char *ReadBMPFile(CString InputFileName,long *wide,long *deep)
{
    CFile	 cFile;
	unsigned char *buff;

    DWORD  dwTime1,dwTime2,count=0;
    BOOL bOpen=FALSE;
	long i,length;

	do
	{
		bOpen = cFile.Open(InputFileName,CFile::modeRead|CFile::shareExclusive);
		dwTime1 = GetTickCount();   
		do
		{
			dwTime2 = GetTickCount();
		}while ((dwTime2-dwTime1)<300);
		
		count ++;
		if (count>=15) break;
	}while(bOpen == 0);
                
    if (bOpen==0)
    {
		ErrorSet = TRUE;
		return NULL;
	}

	BITMAPFILEHEADER bHead;
	BITMAPINFOHEADER bi;

	//read the header of the BITMAP file
	cFile.Read(&bHead,sizeof(BITMAPFILEHEADER));
	cFile.Read(&bi,sizeof(BITMAPINFOHEADER));
	cFile.Seek(4*256,CFile::current);

	*wide=bi.biWidth;
	*deep=bi.biHeight;

	//allocate the work buffer
	length=(*wide)*(*deep);

	buff=new unsigned char [length];
	if(buff==NULL)
	{
		AfxMessageBox("not enough memory to pc!");
		return NULL;  
	}

	//read the data stream of the file
	if((*wide)%4==0)
		cFile.ReadHuge(buff,length);
	else
	{
		long temp=(*wide+3)/4*4-(*wide);
		long temp1;
		temp1=0;
		for(i=0;i<*deep;i++)
		{

			cFile.ReadHuge(buff+temp1,*wide);
			cFile.Seek(temp,CFile::current);
			temp1+=(*wide);
		}
	}
	cFile.Close();
	return buff;
}

//according the block direction,encode the image data
/*void EncodingImage(short int **ImageData,PBYTE DirectionBlock[BLOCK_NO*2],long width,long height,CString OutputFileName)
{
	int i,j;
	short int deta;
	short int BlockSize=8;
	long XSize,YSize;
	long StartX,StartY;
	short int *DPCM;
	
	DPCM=new short int [BlockSize*BlockSize];

	if((TempData=new short int *[height])==NULL)
    {
		AfxMessageBox("not enough memory to TempData");
		return ;
	}
		
	for(j=0;j<height;j++)
	{
		if((TempData[j]=new short int [width])==NULL)
		{
			AfxMessageBox("not enough memory to TempData");
			return ;
		}
	}

	XSize=width/BlockSize;
	YSize=height/BlockSize;

	for(j=0;j<YSize;j++)
	{
		StartY=j*BlockSize;
		for(i=0;i<XSize;i++)
		{
			StartX=i*BlockSize;
			if(j<8 || j>YSize-8) deta=8;
			else if(i<8 || i>XSize-8) deta=8;
			else deta=DirectionBlock[j-8][i-8];
			predictor(ImageData,DPCM,StartX,StartY,BlockSize,BlockSize,deta);
		}
	}
	delete[] DPCM;

	CFile cTempFile;
	BOOL bOpen;

	bOpen=cTempFile.Open("temp.dat",CFile::modeCreate |CFile::modeWrite);
	if(bOpen==0)      
	{
		AfxMessageBox("Can not create file temp.dat!");
		return ;
    }

	for(j=0;j<height;j++)
	{
		cTempFile.Write(TempData[j],width*sizeof(short int));
	}
	cTempFile.Close();


	//delete the memory space
	for(j=0;j<height;j++)
		delete[] TempData[j];
	delete[] TempData;

}
*/

//encoding the image file
void _GA_Compress(CString InputFileName,CString OutputFileName)
{
    HANDLE hDirectionBlock[BLOCK_NO*2];          //8*8块方向图
	PBYTE DirectionBlock[BLOCK_NO*2];
	int i,j;
	int  AllocSize=BLOCK_NO*2;
	long width,height;
	unsigned char *pc;
	short int **ImageData;

	for(i=0; i<BLOCK_NO*2; i++)
	{
		hDirectionBlock[i] = (HGLOBAL)GlobalAlloc(GHND,AllocSize);
		if(!hDirectionBlock[i])
		{
			AfxMessageBox("not enough memory in preprocess to hDirectionBlock!");
			return;
		}
		DirectionBlock[i] = (PBYTE)GlobalLock(hDirectionBlock[i]);
		if(DirectionBlock[i]==NULL)
		{
			AfxMessageBox("not enough memory to DirectionBlock!");
			return ;  
		}
    }

	pc=ReadBMPFile(InputFileName,&width,&height);

	if((ImageData=new short int *[height])==NULL)
    {
		AfxMessageBox("not enough memory to ImageData");
		return ;
	}
		
	for(j=0;j<height;j++)
	{
		if((ImageData[j]=new short int [width])==NULL)
		{
			AfxMessageBox("not enough memory to ImageData");
			return ;
		}
	}
	
	//give the value of pc to lpSourceImage
	for(j=0;j<height;j++)
		for(i=0;i<width;i++)
			ImageData[j][i]=pc[j*width+i];//-128;
/*
	CFile cTempFile;
	BOOL bOpen;

	bOpen=cTempFile.Open("temp.pgm",CFile::modeCreate |CFile::modeWrite);
	if(bOpen==0)      
	{
		AfxMessageBox("Can not create file temp.dat!");
		return ;
    }
	cTempFile.WriteHuge(pc,width*height);
	cTempFile.Close();
*/
	//calculate the block direction(0-7)
	CalculateBlockDirection(pc,DirectionBlock);
	delete[] pc;
	//according the block direction,encode the image data
	EncodingImage(ImageData,DirectionBlock,width,height,OutputFileName);

	//delete the memory space
	for(j=0;j<height;j++)
		delete[] ImageData[j];
	delete[] ImageData;

	//free the memory space
	for(i=0;i<BLOCK_NO*2;i++)
	{
		GlobalUnlock(hDirectionBlock[i]);
		GlobalFree(hDirectionBlock[i]);
	}
}


⌨️ 快捷键说明

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