📄 timgfilterlogoaway.cpp
字号:
logotempdata[y*logotempstride+x]=uint8_t(r/uweweightsum[y*w+x]);
}
}
void TimgFilterLogoaway::Tplane::setSolid(const TlogoawaySettings *cfg)
{
for (int y=0;y<cfg->dy>>shiftY;y++)
memset(logotempdata+y*logotempstride,solidcolor,cfg->dx>>shiftX);
}
void TimgFilterLogoaway::Tplane::loadLogo(const TlogoawaySettings *cfg,bool withborderN,bool withborderE,bool withborderS,bool withborderW)
{
int Vstart, Vend;
int Hstart, Hend;
const unsigned char *buffer=logotempdata;
if (withborderN)
Vstart=0;
else
{
Vstart=1;
buffer+=logotempstride;
}
if (withborderS)
Vend=h;
else
Vend=h-1;
if (withborderW)
Hstart=0;
else
Hstart=1;
if (withborderE)
Hend=w;
else
Hend=w-1;
unsigned char *p=getPixelAddr(cfg->x,cfg->y);
for (int i=Vstart;i<Vend;i++)
{
memcpy(p+Hstart,buffer+(withborderW==false?1:0),Hend-Hstart);
buffer+=logotempstride;
p+=stride2;
}
}
void TimgFilterLogoaway::Tplane::init(const TlogoawaySettings *cfg)
{
bordn=(unsigned char*)aligned_malloc(w);
bords=(unsigned char*)aligned_malloc(w);
borde=(unsigned char*)aligned_malloc(h);
bordw=(unsigned char*)aligned_malloc(h);
vd=(FIX*)aligned_malloc(sizeof(FIX)*(w));
vt=(FIX*)aligned_malloc(sizeof(FIX)*(w));
if (parambitmapdata && (cfg->mode==TlogoawaySettings::MODE_SHAPEXY || cfg->mode==TlogoawaySettings::MODE_SHAPEUGLARM))
{
shapexy_cn=(SHAPEXY_VCNDEF*)aligned_malloc(w*h*sizeof(SHAPEXY_VCNDEF));
for (int i=0;i<w*h;i++)
{
shapexy_cn[i].up =0;
shapexy_cn[i].left =0;
shapexy_cn[i].right=w-1;
shapexy_cn[i].down =h-1;
}
calcShapeXY_VContourNeighbours(cfg);
}
}
void TimgFilterLogoaway::Tplane::done(void)
{
if (bordn) aligned_free(bordn);bordn=NULL;
if (bords) aligned_free(bords);bords=NULL;
if (borde) aligned_free(borde);borde=NULL;
if (bordw) aligned_free(bordw);bordw=NULL;
if (vd) aligned_free(vd);vd=NULL;
if (vt) aligned_free(vt);vt=NULL;
if (uwetable) aligned_free(uwetable);uwetable=NULL;
if (uweweightsum) aligned_free(uweweightsum);uweweightsum=NULL;
if (shapexy_cn) aligned_free(shapexy_cn);shapexy_cn=NULL;
}
void TimgFilterLogoaway::Tplane::calcShapeXY_VContourNeighbours(const TlogoawaySettings *cfg)
{
SHAPEXY_VCNDEF *vcn=shapexy_cn;
//****************************************************************
// CALCULATE VERTICAL CONTOUR NEIGHBOURS
for( int x=1;x<w-1;x++)
{
// find top neighbours
int lastcn=0;
for(int y=1;y<h-1;y++)
{
unsigned char b=parambitmapdata[y*parambitmapstride+x];
if (b>=SHAPEMAP_CONTOUR)
lastcn=y;
else if (b<=SHAPEMAP_NOCHANGE)
continue;
else
vcn[y*w+x].up=lastcn;
}
// find bottom neighbours
lastcn=h-1;
for (int y=h-2;y>0;y--)
{
unsigned char b=parambitmapdata[y*parambitmapstride+x];
if (b>=SHAPEMAP_CONTOUR)
lastcn=y;
else if (b<=SHAPEMAP_NOCHANGE)
continue;
else
vcn[y*w+x].down=lastcn;
}
}
//****************************************************************
// CALCULATE HORIZONTAL CONTOUR NEIGHBOURS
for(int y=1;y<h-1;y++)
{
// find left neighbours
int lastcn = 0;
for(int x=1;x<w-1; x++)
{
unsigned char b=parambitmapdata[y*parambitmapstride+x];
if (b>=SHAPEMAP_CONTOUR)
lastcn = x;
else if (b<=SHAPEMAP_NOCHANGE)
continue;
else
vcn[ y*w+x].left=lastcn;
}
// find bottom neighbours
lastcn=w-1;
for(int x=w-2;x>0;x--)
{
unsigned char b=parambitmapdata[ y*parambitmapstride+x ];
if (b>=SHAPEMAP_CONTOUR)
lastcn=x;
else if (b<=SHAPEMAP_NOCHANGE)
continue;
else
vcn[y*w+x].right=lastcn;
}
}
}
unsigned char TimgFilterLogoaway::Tplane::mix2Pixels32(unsigned char a,unsigned char b,FIX wa,FIX wb)
{
return (unsigned char)((a*wa + b*wb)>>16);
}
void TimgFilterLogoaway::Tplane::renderShapeXY(const TlogoawaySettings *cfg)
{
const unsigned char *modeparambitmap=parambitmapdata+parambitmapstride;
for (int y=1;y<h-1;y++,modeparambitmap+=parambitmapstride)
for (int x=1;x<w-1;x++)
if(modeparambitmap[x]>SHAPEMAP_NOCHANGE &&
modeparambitmap[x]<SHAPEMAP_CONTOUR)
{
// HORIZONTAL GRADIENT
int d1 = x - shapexy_cn[y*w+x].left;
int d2 = shapexy_cn[y*w+x].right - x;
unsigned char p1 = logotempdata[ y*logotempstride + shapexy_cn[y*w+x].left ];
unsigned char p2 = logotempdata[ y*logotempstride + shapexy_cn[y*w+x].right ];
unsigned char hp = mix2Pixels32( p1, p2, (d2<<16)/(d1+d2), (d1<<16)/(d1+d2) );
// VERTICAL GRADIENT
d1 = y - shapexy_cn[y*w+x].up;
d2 = shapexy_cn[y*w+x].down - y;
p1 = logotempdata[ logotempstride * shapexy_cn[y*w+x].up + x ];
p2 = logotempdata[ logotempstride * shapexy_cn[y*w+x].down + x ];
unsigned char vp = mix2Pixels32( p1, p2, (d2<<16)/(d1+d2), (d1<<16)/(d1+d2) );
// MIX HORIZONTAL & VERTICAL into DEST. PIXEL
// Mix based on XY slider value (0-10)
logotempdata[logotempstride*y+x] = mix2Pixels32( hp, vp,
6553 * (10-cfg->vhweight), // 0.1x
6553 * cfg->vhweight ); // 0.1x
//logotemp[p] = p1;
}
}
void TimgFilterLogoaway::Tplane::renderShapeUwe(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);
}
int radius=3*(cfg->vhweight+1);
const unsigned char *modeparambitmap=parambitmapdata+parambitmapstride;
for (int y=1;y<h-1;y++,modeparambitmap+=parambitmapstride)
for (int x=1;x<w-1;x++)
if(modeparambitmap[x]>SHAPEMAP_NOCHANGE &&
modeparambitmap[x]<SHAPEMAP_CONTOUR)
{
int lb=x-radius;
int rb=x+radius;
int ub=y-radius;
int db=y+radius;
if (lb<0) lb=0;
if (rb>w-1) lb=w-1;
if (ub<0) ub=0;
if (db>h-1) db=h-1;
double weightsum=0.0;
double b=0.0;
for (int sy=ub;sy<=db;sy++)
for (int sx=lb;sx<=rb;sx++)
if (parambitmapdata[sy*parambitmapstride+sx]>=SHAPEMAP_CONTOUR)
{
double weight = uwetable[abs(y-sy)*w+abs(x-sx)];
b+=logotempdata[sy*logotempstride+sx]*w;
weightsum+=weight;
}
int bi = (int) (b/weightsum);
logotempdata[y*logotempstride+x]=(unsigned char)bi;
}
}
void TimgFilterLogoaway::Tplane::process(const TlogoawaySettings *cfg)
{
createBorder(cfg,TlogoawaySettings::NORTH,cfg->bordn_mode);
createBorder(cfg,TlogoawaySettings::EAST ,cfg->borde_mode);
createBorder(cfg,TlogoawaySettings::SOUTH,cfg->bords_mode);
createBorder(cfg,TlogoawaySettings::WEST ,cfg->bordw_mode);
saveLogoBorder(TlogoawaySettings::NORTH);
saveLogoBorder(TlogoawaySettings::SOUTH);
saveLogoBorder(TlogoawaySettings::EAST );
saveLogoBorder(TlogoawaySettings::WEST );
switch (cfg->mode)
{
case TlogoawaySettings::MODE_XY:
setAverageVH(cfg);
for (int i=1;i<=cfg->blur;i++)
blurLogotemp(false);
break;
case TlogoawaySettings::MODE_UGLARM:
uwe(cfg);
break;
case TlogoawaySettings::MODE_SOLIDFILL:
setSolid(cfg);
break;
case TlogoawaySettings::MODE_SHAPEXY:
if (parambitmapdata)
{
renderShapeXY(cfg);
for (int i=1;i<=cfg->blur;i++)
blurLogotemp(true);
break;
}
else
return;
case TlogoawaySettings::MODE_SHAPEUGLARM:
if (parambitmapdata)
{
renderShapeUwe(cfg);
for (int i=1;i<=cfg->blur;i++)
blurLogotemp(true);
break;
}
else
return;
}
loadLogo(cfg,
cfg->bordn_mode==TlogoawaySettings::BM_INTERPOLATE,
cfg->borde_mode==TlogoawaySettings::BM_INTERPOLATE,
cfg->bords_mode==TlogoawaySettings::BM_INTERPOLATE,
cfg->bordw_mode==TlogoawaySettings::BM_INTERPOLATE);
}
//========================================= TimgFilterLogoaway =========================================
TimgFilterLogoaway::TimgFilterLogoaway(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
oldLumaOnly=oldBlur=oldMode=-1;oldparambitmap[0]='\0';
parambitmap=NULL;
}
void TimgFilterLogoaway::done(void)
{
logotempbuf.clear();
parambitmapbuf.clear();
if (parambitmap) delete parambitmap;parambitmap=NULL;
for (int i=0;i<3;i++)
plane[i].done();
}
void TimgFilterLogoaway::onSizeChange(void)
{
done();
}
bool TimgFilterLogoaway::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TlogoawaySettings *cfg=(const TlogoawaySettings*)cfg0;
if (super::is(pict,cfg) && cfg->dx>=4 && cfg->dy>=4)
{
Trect pictRect=pict.getRect(cfg->full,cfg->half);
return (unsigned int)cfg->x<=pictRect.dx-1 && (unsigned int)cfg->y<=pictRect.dy-1 &&
(unsigned int)cfg->x+cfg->dx<=pictRect.dx && (unsigned int)cfg->y+cfg->dy<=pictRect.dy;
}
else
return false;
}
HRESULT TimgFilterLogoaway::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
if (is(pict,cfg0))
{
const TlogoawaySettings *cfg=(const TlogoawaySettings*)cfg0;
init(pict,cfg->full,cfg->half);
bool cspChanged;
if (cfg->lumaonly)
cspChanged=getCurNext(FF_CSPS_MASK_YUV_PLANAR,pict,cfg->full,COPYMODE_DEF,&plane[0].dst,NULL,NULL,NULL);
else
cspChanged=getCurNext(FF_CSPS_MASK_YUV_PLANAR,pict,cfg->full,COPYMODE_DEF,&plane[0].dst,&plane[1].dst,&plane[2].dst,NULL);
if (cspChanged || logotemp.rectFull.dx!=(unsigned int)cfg->dx || logotemp.rectFull.dy!=(unsigned int)cfg->dy || !plane[0] || oldLumaOnly!=cfg->lumaonly || oldBlur!=cfg->blur || oldMode!=cfg->mode || stricmp(oldparambitmap,cfg->parambitmap)!=0)
{
oldLumaOnly=cfg->lumaonly;oldBlur=cfg->blur;oldMode=cfg->mode;strcpy(oldparambitmap,cfg->parambitmap);
done();
if (cfg->mode==TlogoawaySettings::MODE_SHAPEXY || cfg->mode==TlogoawaySettings::MODE_SHAPEUGLARM)
{
parambitmap=new TffPict(csp2,cfg->parambitmap,parambitmapbuf,deci);
if (parambitmap->rectFull.dx!=(unsigned int)cfg->dx || parambitmap->rectFull.dy!=(unsigned int)cfg->dy)
{
delete parambitmap;
parambitmap=NULL;
}
}
for (int i=0;i<(cfg->lumaonly?1:3);i++)
{
plane[i].shiftX=pict.cspInfo.shiftX[i];plane[i].shiftY=pict.cspInfo.shiftY[i];
plane[i].w=cfg->dx>>plane[i].shiftX;plane[i].h=cfg->dy>>plane[i].shiftY;
if (parambitmap)
{
plane[i].parambitmapdata=parambitmap->data[i];
plane[i].parambitmapstride=parambitmap->stride[i];
}
else
{
plane[i].parambitmapdata=NULL;
plane[i].parambitmapstride=0;
}
plane[i].init(cfg);
}
}
Trect tempR(cfg->x,cfg->y,cfg->dx,cfg->dy);
logotemp.copyFrom(pict,logotempbuf,&tempR);
YUVcolor yuv(cfg->solidcolor);
for (int i=0;i<(cfg->lumaonly?1:3);i++)
{
plane[i].stride2=stride2[i];
plane[i].logotempdata=logotemp.data[i];plane[i].logotempstride=logotemp.stride[i];
plane[i].solidcolor=(i==0?yuv.Y:(i==1?yuv.V+128:yuv.U+128));
plane[i].process(cfg);
}
}
return parent->deliverSample(++it,pict);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -