📄 timgfilterlogoaway.cpp
字号:
/*
* Copyright (c) 2004-2006 Milan Cutka
* Based of Logoaway plugin filter for VirtualDub by Krzysztof Wojdon
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "stdafx.h"
#include "TimgFilterLogoaway.h"
#include "TlogoawaySettings.h"
//===================================== TimgFilterLogoaway::Tplane =====================================
inline unsigned char* TimgFilterLogoaway::Tplane::getPixelAddr(int x,int y)
{
return dst+stride2*(y>>shiftY)+(x>>shiftX);
}
unsigned char* TimgFilterLogoaway::Tplane::getCornerAddr(const TlogoawaySettings *cfg,int corner)
{
switch (corner)
{
case TlogoawaySettings::NW:
return getPixelAddr(cfg->x,cfg->y);
case TlogoawaySettings::NE:
return getPixelAddr(cfg->x+cfg->dx-1,cfg->y);
case TlogoawaySettings::SW:
return getPixelAddr(cfg->x,cfg->y+cfg->dy-1);
case TlogoawaySettings::SE:
return getPixelAddr(cfg->x+cfg->dx-1,cfg->y+cfg->dy-1);
default:
return NULL;
}
}
void TimgFilterLogoaway::Tplane::selectPoints(const TlogoawaySettings *cfg,
int bmode,
unsigned char **s,unsigned char **e,
int psd,int ped,
int pso,int peo,
int psi,int pei
)
{
switch (bmode)
{
case TlogoawaySettings::BM_DIRECT:
*s=getCornerAddr(cfg,psd);
*e=getCornerAddr(cfg,ped);
break;
case TlogoawaySettings::BM_OPPOSITE:
*s=getCornerAddr(cfg,pso);
*e=getCornerAddr(cfg,peo);
break;
case TlogoawaySettings::BM_INTERPOLATE:
*s=getCornerAddr(cfg,psi);
*e=getCornerAddr(cfg,pei);
break;
default:
*s=*e=NULL;
break;
}
}
void TimgFilterLogoaway::Tplane::calcGradient(const unsigned char *s,const unsigned char *e,int len,FIX *r,FIX *rd)
{
*r=*s<<16;
*rd=(FIX(*e)-FIX(*s))<<16;
*rd/=len-1;
}
void TimgFilterLogoaway::Tplane::createBorderH(unsigned char *border,const unsigned char *s,const unsigned char *e,int width,int bmode)
{
int i;
FIX rt,rd;
switch (bmode)
{
case TlogoawaySettings::BM_INTERPOLATE:
calcGradient(s,e,width,
&rt,
&rd);
for (i=0;i<width;i++)
{
*border++=uint8_t(rt>>16);
rt+=rd;
}
break;
case TlogoawaySettings::BM_DIRECT:
case TlogoawaySettings::BM_OPPOSITE:
memcpy(border,s,width);
break;
}
}
void TimgFilterLogoaway::Tplane::createBorderV(unsigned char *border,const unsigned char *s,const unsigned char *e,int h,stride_t pitch,int bmode)
{
int i;
switch (bmode)
{
case TlogoawaySettings::BM_INTERPOLATE:
{
FIX rt,rd;
calcGradient(s,e,h,
&rt,
&rd);
for (i=0;i<h;i++)
{
*border++=uint8_t(rt>>16);
rt+=rd;
}
break;
}
case TlogoawaySettings::BM_DIRECT:
case TlogoawaySettings::BM_OPPOSITE:
for (i=0;i<h;i++)
{
*border++=*s;
s+=pitch;
}
break;
}
}
void TimgFilterLogoaway::Tplane::createBorder(const TlogoawaySettings *cfg,int side,int bmode)
{
unsigned char *s,*e;
switch (side)
{
case TlogoawaySettings::NORTH:
selectPoints(cfg,bmode,&s,&e,
TlogoawaySettings::NW,TlogoawaySettings::NE,
TlogoawaySettings::SW,TlogoawaySettings::SE,
cfg->pointnw,cfg->pointne);
createBorderH(bordn,s,e,cfg->dx>>shiftX,bmode);
break;
case TlogoawaySettings::EAST:
selectPoints(cfg,bmode,&s,&e,
TlogoawaySettings::NE,TlogoawaySettings::SE,
TlogoawaySettings::NW,TlogoawaySettings::SW,
cfg->pointne,cfg->pointse);
createBorderV(borde,s,e,cfg->dy>>shiftY,stride2,bmode);
break;
case TlogoawaySettings::SOUTH:
selectPoints(cfg,bmode,&s,&e,
TlogoawaySettings::SW,TlogoawaySettings::SE,
TlogoawaySettings::NW,TlogoawaySettings::NE,
cfg->pointsw,cfg->pointse);
createBorderH(bords,s,e,cfg->dx>>shiftX,bmode);
break;
case TlogoawaySettings::WEST:
selectPoints(cfg,bmode,&s,&e,
TlogoawaySettings::NW,TlogoawaySettings::SW,
TlogoawaySettings::NE,TlogoawaySettings::SE,
cfg->pointnw,cfg->pointsw);
createBorderV(bordw,s,e,cfg->dy>>shiftY,stride2,bmode);
break;
}
}
void TimgFilterLogoaway::Tplane::saveLogoBorder(int border)
{
int i;
switch( border )
{
case TlogoawaySettings::NORTH:
memcpy(logotempdata,bordn,w);
break;
case TlogoawaySettings::SOUTH:
{
unsigned char *buffer=logotempdata+logotempstride*(h-1);
memcpy(buffer,bords,w);
break;
}
case TlogoawaySettings::WEST:
{
unsigned char *buffer=logotempdata;
for (i=0;i<h;i++)
buffer[logotempstride*i]=bordw[i];
break;
}
case TlogoawaySettings::EAST:
{
unsigned char *buffer=logotempdata;
for (i=0;i<h;i++)
buffer[logotempstride*i+w-1]=borde[i];
break;
}
}
}
void TimgFilterLogoaway::Tplane::setAverageVH(const TlogoawaySettings *cfg)
{
int i,j;
int vstart,vend;
int hstart,hend;
FIX px,py;
// Precalculate vertical (north->south) gradient parameters:
// For each column: starting R,G,B and per-row deltas R,G,B
for(i=0;i<w;i++)
calcGradient(&bordn[i],&bords[i],h,
&vt[i],
&vd[i]);
// CALCULATE RECTANGLE START AND END
// BM_INTERPOLATE overwrites border
// other methods do not - just leave border alone.
if(cfg->bordn_mode==TlogoawaySettings::BM_INTERPOLATE)
vstart=0;
else
vstart=1;
if(cfg->bords_mode==TlogoawaySettings::BM_INTERPOLATE)
vend=h;
else
vend=h-1;
if(cfg->bordw_mode==TlogoawaySettings::BM_INTERPOLATE)
hstart=0;
else
hstart=1;
if(cfg->borde_mode==TlogoawaySettings::BM_INTERPOLATE)
hend=w;
else
hend=w-1;
unsigned char *pRow=logotempdata;
// If north border unused
// we need to skip this border with
// one empty vertical gradient step
if (vstart==1)
{
pRow+=logotempstride; // fix added on
for (i=0;i<w;i++)
vt[i]+=vd[i];
}
// Now fill logo area by walking each scanline
// step by step through the logo h
for (i=vstart;i<vend;i++)
{
int r,rd;
// Horizontal gradient for this row
calcGradient(&bordw[i],&borde[i],w,&r,&rd);
if (hstart==1) // First column step skip
r+=rd;
// Make whole logo row
for (j=hstart;j<hend;j++)
{
// Update vertical gradient current component
// Next row we will need next vertical step
vt[j]+=vd[j];
// Make weighted H gradient component
px=r*(10-cfg->vhweight);
// Make weighted V gradient component
py=vt[j]*cfg->vhweight;
// Calc
pRow[j]=uint8_t(((px+py)/10)>>16);
// Next pixel, one gradient step
r+=rd;
}
// Get next row start Real UP->DOWN, not VirtualDub down->up
pRow+=logotempstride;
}
}
void TimgFilterLogoaway::Tplane::blurLogotemp(bool useparambitmap)
{
unsigned char *rowp, *row, *rown;
unsigned char *rowbkup;
rowp =(unsigned char*)_alloca(w);
rowbkup=(unsigned char*)_alloca(w);
memcpy(rowp,logotempdata,w);
row=logotempdata+logotempstride;
rown=row+logotempstride;
for (int i=1;i<=h-2;i++)
{
// 1 ... X+
memcpy(rowbkup,row,w);
for (int j=1;j<=w-2;j++)
if (!useparambitmap ||
(parambitmapdata[i*parambitmapstride+j]>SHAPEMAP_NOCHANGE &&
parambitmapdata[i*parambitmapstride+j]<SHAPEMAP_CONTOUR))
{
int r=rowp[j-1]+
rowp[j+1]+
(row[j]<<2)+
rown[j-1]+
rown[j+1];
row[j]=uint8_t(r/8);
}
row=rown;
rown=rown+logotempstride;
memcpy(rowp,rowbkup,w);
}
}
void TimgFilterLogoaway::Tplane::calcUweWeightTable(int w,int h,int power)
{
double e = 1.0 + (0.3 * power);
int x;
for (x=0;x<w;x++)
for (int y=0;y<h;y++)
if(x+y!=0)
{
double d=pow(sqrt(double(x*x+y*y)),e);
uwetable[x+y*w]=1.0/d;
}
else
uwetable[x+y*w]=1.0;
for (x=1;x<w-1;x++)
for (int y=1;y<h-1;y++)
{
double weightsum=0;
for (int bx=0;bx<w;bx++)
{
weightsum+=uwetable[abs(bx-x)+y*w];
weightsum+=uwetable[abs(bx-x)+abs(h-1-y)*w];
}
for (int by=1;by<h-1;by++)
{
weightsum+=uwetable[x+abs(by-y)*w];
weightsum+=uwetable[abs(w-1-x)+abs(by-y)*w];
}
uweweightsum[y*w+x]=weightsum;
}
}
void TimgFilterLogoaway::Tplane::uwe(const TlogoawaySettings *cfg)
{
if (!uwetable)
{
uwetable=(double*)aligned_malloc(w*h*sizeof(double));
uweweightsum=(double*)aligned_malloc(w*h*sizeof(double));
calcUweWeightTable(w,h,cfg->blur);
}
for (int x=1;x<w-1;x++)
for (int y=1;y<h-1;y++)
{
double r=0;
const unsigned char *lineN=bordn,*lineS=bords;
for (int bx=0;bx<w;bx++)
{
r+=lineN[bx]*uwetable[abs(bx-x)+y*w];
r+=lineS[bx]*uwetable[abs(bx-x)+abs(h-1-y)*w];
}
const unsigned char *lineW=bordw,*lineE=borde;
for (int by=1;by<h-1;by++)
{
r+=lineW[by]*uwetable[x+abs(by-y)*w];
r+=lineE[by]*uwetable[abs(w-1-x)+abs(by-y)*w];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -