diff options
Diffstat (limited to 'bitmap/float_bm_bilateral_filter.cpp')
| -rw-r--r-- | bitmap/float_bm_bilateral_filter.cpp | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/bitmap/float_bm_bilateral_filter.cpp b/bitmap/float_bm_bilateral_filter.cpp new file mode 100644 index 0000000..4d45eb9 --- /dev/null +++ b/bitmap/float_bm_bilateral_filter.cpp @@ -0,0 +1,95 @@ +//========= 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] ); + } +} + |