www.pudn.com > henclib263.rar > image.cxx


/* 
* image.cxx 
* 
* implementation for image-processing functions. 
* 
* Copyright (c) 2002-2004 Li Chun-lin(li_chunlin@263.net) 
* 
* This program is free software; you can redistribute it and/or 
* modify it under the terms of the GNU General Public License 
* as published by the Free Software Foundation; either version 2 
* of the License, or (at your option) any later version. 
*  
* This program is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
* GNU General Public License for more details. 
 
* You should have received a copy of the GNU General Public License 
* along with this program; if not, write to the Free Software 
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
*/ 
 
#include "../include/HEnc.h" 
#include  
#include  
 
 
 
#ifdef  __cplusplus 
extern "C" { 
#endif 
 
 
 
/*! 
*  Hfilter: filter of horizontal direction 
*  optimization: NO  
*/ 
void Hfilter(unsigned char *rec, int width, int height, int lx, int chr, 
			 int coded_tab[MBR+1][MBC+1], int quant_tab[MBR+1][MBC+1]) 
{ 
	int i, j, k; 
	int delta, d1, d2; 
	int mbc, mbr, do_filter; 
	int QP; 
	int bquant[] = {5, 6, 7, 8}; 
	int mbr_above; 
	int STRENGTH[] = {1,1,2,2,3,3,4,4,4,5,5,6,6,7,7,7,8,8,8,9,9,9,10,10,10,11,11,11,12,12,12}; 
	/* horizontal edges */ 
	for (j = 8; j < height; j += 8) 
	{ 
		for (i = 0; i < width; i += 8) 
		{ 
			if (!chr) 
			{ 
				mbr = j >> 4; 
				mbc = i >> 4; 
				mbr_above = (j - 8) >> 4; 
			} else 
			{ 
				mbr = j >> 3; 
				mbc = i >> 3; 
				mbr_above = mbr - 1; 
			} 
			 
			do_filter = coded_tab[mbr + 1][mbc + 1] || coded_tab[mbr_above + 1][mbc + 1]; 
			 
			if (do_filter) 
			{ 
				QP = coded_tab[mbr + 1][mbc + 1] ? quant_tab[mbr + 1][mbc + 1] : quant_tab[mbr_above + 1][mbc + 1]; 
			    for (k = i; k < i+8; k ++) 
				{ 
					delta = (int) (((int) (*(rec + k + (j - 2) * lx)) + 
						(int) (*(rec + k + (j - 1) * lx) * (-4)) + 
						(int) (*(rec + k + (j) * lx) * (4)) + 
						(int) (*(rec + k + (j + 1) * lx) * (-1))) / 8.0); 
					d1 = sign (delta) * mmax (0, absm (delta) - mmax (0, 2 * (absm (delta) - STRENGTH[QP - 1]))); 
					d2 = mmin (absm (d1 / 2), mmax (-absm (d1 / 2), (int) (((*(rec + k + (j - 2) * lx) - 
						*(rec + k + (j + 1) * lx))) / 4))); 
					*(rec + k + (j + 1) * lx) = (int) (*(rec + k + (j + 1) * lx)) + d2; 
					*(rec + k + (j) * lx) = 
						mmin (255, mmax (0, (int) (*(rec + k + (j) * lx)) - d1)); 
					*(rec + k + (j - 1) * lx) = 
						mmin (255, mmax (0, (int) (*(rec + k + (j - 1) * lx)) + d1)); 
					*(rec + k + (j - 2) * lx) = (int) (*(rec + k + (j - 2) * lx)) - d2; 
				} 
			} 
		} 
	} 
} 
/* 
* Vfilter:      filter of vertical direction 
* optimization: NO 
*/ 
void Vfilter(unsigned char *rec, int width, int height, int lx, int chr,  
			 int coded_tab[MBR+1][MBC+1], int quant_tab[MBR+1][MBC+1]) 
{ 
	int i, j, k; 
	int delta, d1, d2; 
	int mbc, mbr; 
	int do_filter; 
	int bquant[] = {5, 6, 7, 8}; 
	int QP; 
	int mbc_left; 
	int STRENGTH[] = {1,1,2,2,3,3,4,4,4,5,5,6,6,7,7,7,8,8,8,9,9,9,10,10,10,11,11,11,12,12,12}; 
	 
	/* vertical edges */ 
	for (i = 8; i < width; i += 8) 
	{ 
		for (j = 0; j < height; j += 8) 
		{ 
			if (!chr) 
			{ 
				mbr = j >> 4; 
				mbc = i >> 4; 
				mbc_left = (i - 8) >> 4; 
			} else 
			{ 
				mbr = j >> 3; 
				mbc = i >> 3; 
				mbc_left = mbc - 1; 
			} 
			do_filter = coded_tab[mbr + 1][mbc + 1] || coded_tab[mbr + 1][mbc_left + 1]; 
			 
			if (do_filter) 
			{ 
				QP = coded_tab[mbr + 1][mbc + 1] ? quant_tab[mbr + 1][mbc + 1] : quant_tab[mbr + 1][mbc_left + 1]; 
				for (k = j; k < j+8; k++) 
				{ 
					delta = (int) (((int) (*(rec + i - 2 + k * lx)) + 
						(int) (*(rec + i - 1 + k * lx) * (-4)) + 
						(int) (*(rec + i + k * lx) * (4)) + 
						(int) (*(rec + i + 1 + k * lx) * (-1))) / 8.0); 
					 
					d1 = sign (delta) * mmax (0, absm (delta) - mmax (0, 2 * (absm (delta) - STRENGTH[QP - 1]))); 
					d2 = mmin (absm (d1 / 2), mmax (-absm (d1 / 2), (int) ((*(rec + i - 2 + k * lx) - 
						*(rec + i + 1 + k * lx)) / 4))); 
					 
					*(rec + i + 1 + k * lx) = (int) (*(rec + i + 1 + k * lx)) + d2; 
					*(rec + i + k * lx) = 
						mmin (255, mmax (0, (int) (*(rec + i + k * lx)) - d1)); 
					*(rec + i - 1 + k * lx) = 
						mmin (255, mmax (0, (int) (*(rec + i - 1 + k * lx)) + d1)); 
					*(rec + i - 2 + k * lx) = (int) (*(rec + i - 2 + k * lx)) - d2; 
				} 
			} 
		} 
	} 
} 
 
/*! 
    EdgeFilter:   Edge filter for reducing blocking artifact 
    optimization: NO 
*/ 
void EdgeFilter(H263VencStatus *encoder) 
{ 
	int lx = encoder->mv_outside_frame ? (encoder->pels + 32) : encoder->pels; 
 
	/* Lum */ 
	Hfilter(encoder->frame_buf[encoder->zero_index].pLum, encoder->pels, encoder->lines, lx, 0, encoder->coded_tab, encoder->quant_tab); 
	Vfilter(encoder->frame_buf[encoder->zero_index].pLum, encoder->pels, encoder->lines, lx, 0, encoder->coded_tab, encoder->quant_tab); 
    /* Chrom */ 
	Hfilter(encoder->frame_buf[encoder->zero_index].pCb, encoder->pels/2, encoder->lines/2, lx/2, 1, encoder->coded_tab, encoder->quant_tab); 
	Vfilter(encoder->frame_buf[encoder->zero_index].pCb, encoder->pels/2, encoder->lines/2, lx/2, 1, encoder->coded_tab, encoder->quant_tab); 
	Hfilter(encoder->frame_buf[encoder->zero_index].pCr, encoder->pels/2, encoder->lines/2, lx/2, 1, encoder->coded_tab, encoder->quant_tab); 
	Vfilter(encoder->frame_buf[encoder->zero_index].pCr, encoder->pels/2, encoder->lines/2, lx/2, 1, encoder->coded_tab, encoder->quant_tab); 
} 
 
/*! 
    MakeEdge:     for expansion of reference picture though making edge 
    optimization: NO 
*/ 
void MakeEdge(unsigned char *pic, int width, int height, int edge) 
{ 
	int i,j; 
	unsigned char *p1,*p2,*p3,*p4; 
	unsigned char *o1,*o2,*o3,*o4; 
	 
	/* left and right edges */ 
	p1 = pic - 1; 
	o1 = pic; 
	for (j = 0; j < height;j++)  
	{ 
		for (i = 0; i < edge; i++)  
		{ 
			*(p1 - i) = *o1; 
			*(p1 + width + i + 1) = *(o1 + width - 1); 
		} 
		p1 += width + (edge<<1); 
		o1 += width + (edge<<1); 
	}     
     
	/* top and bottom edges */ 
	p1 = pic; 
	p2 = pic + (width + (edge<<1))*(height-1); 
	o1 = pic; 
	o2 = pic + (width + (edge<<1))*(height-1); 
	for (j = 0; j < edge;j++)  
	{ 
		p1 = p1 - (width + (edge<<1)); 
		p2 = p2 + (width + (edge<<1)); 
		for (i = 0; i < width; i++)  
		{ 
			*(p1 + i) = *(o1 + i); 
			*(p2 + i) = *(o2 + i); 
		} 
	}     
	 
	/* corners */ 
	p1 = pic - (width+(edge<<1)) - 1; 
	p2 = p1 + width + 1; 
	p3 = pic + (width+(edge<<1))*(height)-1; 
	p4 = p3 + width + 1; 
	 
	o1 = pic; 
	o2 = o1 + width - 1; 
	o3 = pic + (width+(edge<<1))*(height-1); 
	o4 = o3 + width - 1; 
	for (j = 0; j < edge; j++)  
	{ 
		for (i = 0; i < edge; i++)  
		{ 
			*(p1 - i) = *o1; 
			*(p2 + i) = *o2; 
			*(p3 - i) = *o3; 
			*(p4 + i) = *o4;  
		} 
		p1 = p1 - (width + (edge<<1)); 
		p2 = p2 - (width + (edge<<1)); 
		p3 = p3 + width + (edge<<1); 
		p4 = p4 + width + (edge<<1); 
	} 
} 
/*! 
  MakeEdgeImage, for use with motion vector outside picture 
*/ 
void MakeEdgeImage(H263VencStatus *encoder) 
{ 
	/* Lum */ 
	MakeEdge(encoder->frame_buf[encoder->zero_index].pLum, encoder->pels, encoder->lines, 16); 
	/* Chrom */ 
	MakeEdge(encoder->frame_buf[encoder->zero_index].pCb, encoder->pels/2, encoder->lines/2, 8); 
	MakeEdge(encoder->frame_buf[encoder->zero_index].pCr, encoder->pels/2, encoder->lines/2, 8); 
} 
 
/*  
   WriteRec : Write Reconstructed Image, for test 
*/ 
void WriteRec(H263VencStatus *encoder, FILE *fp) 
{ 
	int j; 
	int lx = encoder->mv_outside_frame ? (encoder->pels+32) : encoder->pels; 
	unsigned char *pTmp; 
 
	pTmp = encoder->frame_buf[encoder->zero_index].pLum; 
	for (j = 0; j < encoder->lines; j++) 
	{ 
		fwrite(pTmp, sizeof(unsigned char)*encoder->pels, 1, fp); 
		pTmp += lx; 
	} 
	pTmp = encoder->frame_buf[encoder->zero_index].pCb; 
	for (j = 0; j < encoder->lines/2; j++) 
	{ 
		fwrite(pTmp, sizeof(unsigned char)*encoder->pels/2, 1, fp); 
		pTmp += lx/2; 
	} 
	pTmp = encoder->frame_buf[encoder->zero_index].pCr; 
	for (j = 0; j < encoder->lines/2; j++) 
	{ 
		fwrite(pTmp, sizeof(unsigned char)*encoder->pels/2, 1, fp); 
		pTmp += lx/2; 
	} 
} 
 
#ifdef  __cplusplus 
} 
#endif