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.
95 lines
2.7 KiB
95 lines
2.7 KiB
//========= 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 uintp 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] ); |
|
} |
|
} |
|
|
|
|