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