You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
2.7 KiB
96 lines
2.7 KiB
4 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//===========================================================================//
|
||
|
|
||
|
#include <tier0/platform.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <math.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "bitmap/float_bm.h"
|
||
|
#include <tier2/tier2.h>
|
||
|
#include "tier0/threadtools.h"
|
||
|
#include "tier0/progressbar.h"
|
||
|
|
||
|
struct TBFCalculationContext
|
||
|
{
|
||
|
int min_y,max_y; // range to calculate in this thread
|
||
|
int thread_number;
|
||
|
int radius_in_pixels;
|
||
|
float edge_threshold_value;
|
||
|
FloatBitMap_t const *orig_bm;
|
||
|
FloatBitMap_t *dest_bm;
|
||
|
};
|
||
|
|
||
|
static unsigned TBFCalculationThreadFN( void *ctx1 )
|
||
|
{
|
||
|
TBFCalculationContext *ctx = (TBFCalculationContext *) ctx1;
|
||
|
for(int y=ctx->min_y; y <= ctx->max_y; y++)
|
||
|
{
|
||
|
if ( ctx->thread_number == 0 )
|
||
|
ReportProgress("Performing bilateral filter",(1+ctx->max_y-ctx->min_y),
|
||
|
y-ctx->min_y);
|
||
|
for(int x=0; x < ctx->dest_bm->Width; x++)
|
||
|
for(int c=0;c<4;c++)
|
||
|
{
|
||
|
float sum_weights=0;
|
||
|
float filter_sum=0;
|
||
|
float centerp=ctx->orig_bm->Pixel(x,y,c);
|
||
|
for(int iy=-ctx->radius_in_pixels; iy <= ctx->radius_in_pixels; iy++)
|
||
|
for(int ix=-ctx->radius_in_pixels; ix <= ctx->radius_in_pixels; ix++)
|
||
|
{
|
||
|
float this_p=ctx->orig_bm->PixelWrapped(x+ix,y+iy,c);
|
||
|
|
||
|
// caluclate the g() term. We use a gaussian
|
||
|
float exp1=(ix*ix+iy*iy)*(1.0/(2.0*ctx->radius_in_pixels*.033));
|
||
|
float g=exp(-exp1);
|
||
|
// calculate the "similarity" term. We use a triangle filter
|
||
|
float s=1.0;
|
||
|
float cdiff=fabs(centerp-this_p);
|
||
|
s= (cdiff>ctx->edge_threshold_value)?0:
|
||
|
FLerp(1,0,0,ctx->edge_threshold_value,cdiff);
|
||
|
sum_weights += s*g;
|
||
|
filter_sum += s*g*this_p;
|
||
|
}
|
||
|
ctx->dest_bm->Pixel(x,y,c)=filter_sum/sum_weights;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void FloatBitMap_t::TileableBilateralFilter( int radius_in_pixels,
|
||
|
float edge_threshold_value )
|
||
|
{
|
||
|
FloatBitMap_t orig( this ); // need a copy for the source
|
||
|
TBFCalculationContext ctxs[32];
|
||
|
ctxs[0].radius_in_pixels = radius_in_pixels;
|
||
|
ctxs[0].edge_threshold_value = edge_threshold_value;
|
||
|
ctxs[0].orig_bm = &orig;
|
||
|
ctxs[0].dest_bm = this;
|
||
|
int nthreads = min( 32, (int)GetCPUInformation()->m_nPhysicalProcessors );
|
||
|
ThreadHandle_t waithandles[32];
|
||
|
int starty=0;
|
||
|
int ystep=Height/nthreads;
|
||
|
|
||
|
for(int t=0;t<nthreads;t++)
|
||
|
{
|
||
|
if (t)
|
||
|
ctxs[t]=ctxs[0];
|
||
|
ctxs[t].thread_number=t;
|
||
|
ctxs[t].min_y=starty;
|
||
|
if (t != nthreads-1)
|
||
|
ctxs[t].max_y=min(Height-1,starty+ystep-1);
|
||
|
else
|
||
|
ctxs[t].max_y=Height-1;
|
||
|
waithandles[t]=CreateSimpleThread(TBFCalculationThreadFN, &ctxs[t]);
|
||
|
starty+=ystep;
|
||
|
}
|
||
|
for(int t=0;t<nthreads;t++)
|
||
|
{
|
||
|
ThreadJoin( waithandles[t] );
|
||
|
}
|
||
|
}
|
||
|
|