fix: thread safety issues

- RGBNoise: move global vars (gaussian_lookup, TABLE_INITED, next_gaussian_index, last_in_range)
- Glitch0r: move global g0r_state
- Cartoon: fix PIXELAT macro to refer to instance

address #188 (seems not all filters on that list are unsafe)
This commit is contained in:
Jaromil
2025-11-26 23:31:35 +01:00
parent b0a990ed18
commit 3a720e4270
3 changed files with 74 additions and 67 deletions

View File

@@ -46,7 +46,7 @@ typedef struct {
uint32_t size;
} ScreenGeometry;
#define PIXELAT(x1,y1,s) ((s)+(x1)+ yprecal[y1])// (y1)*(geo->w)))
#define PIXELAT(x1,y1,s,inst) ((s)+(x1)+ inst->yprecal[y1])// (y1)*(geo->w)))
#define GMERROR(cc1,cc2) ((((RED(cc1)-RED(cc2))*(RED(cc1)-RED(cc2))) + \
((GREEN(cc1)-GREEN(cc2)) *(GREEN(cc1)-GREEN(cc2))) + \
((BLUE(cc1)-BLUE(cc2))*(BLUE(cc1)-BLUE(cc2)))))
@@ -155,26 +155,26 @@ long Cartoon::GetMaxContrast(int32_t *src,int x,int y) {
long error,max=0;
/* Assumes PrePixelModify has been run */
c1 = *PIXELAT(x-m_diffspace,y,src);
c2 = *PIXELAT(x+m_diffspace,y,src);
c1 = *PIXELAT(x-m_diffspace,y,src,this);
c2 = *PIXELAT(x+m_diffspace,y,src,this);
error = GMERROR(c1,c2);
if (error>max) max = error;
c1 = *PIXELAT(x,y-m_diffspace,src);
c2 = *PIXELAT(x,y+m_diffspace,src);
c1 = *PIXELAT(x,y-m_diffspace,src,this);
c2 = *PIXELAT(x,y+m_diffspace,src,this);
error = GMERROR(c1,c2);
if (error>max) max = error;
c1 = *PIXELAT(x-m_diffspace,y-m_diffspace,src);
c2 = *PIXELAT(x+m_diffspace,y+m_diffspace,src);
c1 = *PIXELAT(x-m_diffspace,y-m_diffspace,src,this);
c2 = *PIXELAT(x+m_diffspace,y+m_diffspace,src,this);
error = GMERROR(c1,c2);
if (error>max) max = error;
c1 = *PIXELAT(x+m_diffspace,y-m_diffspace,src);
c2 = *PIXELAT(x-m_diffspace,y+m_diffspace,src);
c1 = *PIXELAT(x+m_diffspace,y-m_diffspace,src,this);
c2 = *PIXELAT(x-m_diffspace,y+m_diffspace,src,this);
error = GMERROR(c1,c2);
if (error>max) max = error;
return(max);
}

View File

@@ -45,7 +45,7 @@ struct glitch0r_state // helps to save time when allocating in a loop
short int howToDistort1;
short int howToDistort2;
short int passThisLine;
} g0r_state;
};
typedef struct glitch0r_instance
{
@@ -58,6 +58,8 @@ typedef struct glitch0r_instance
short int colorGlitchIntensity;
short int doColorDistortion;
short int glitchChance;
struct glitch0r_state state; // Instance-specific state
} glitch0r_instance_t;
@@ -68,17 +70,17 @@ inline static unsigned int rnd (unsigned int min, unsigned int max)
inline static void glitch0r_state_reset(glitch0r_instance_t *inst)
{
g0r_state.currentPos = 0;
g0r_state.currentBlock = rnd(1, inst->maxBlockSize);
g0r_state.blkShift = rnd(1, inst->maxBlockShift);
g0r_state.passThisLine = (inst->glitchChance < rnd(1, 101)) ? 1 : 0;
inst->state.currentPos = 0;
inst->state.currentBlock = rnd(1, inst->maxBlockSize);
inst->state.blkShift = rnd(1, inst->maxBlockShift);
inst->state.passThisLine = (inst->glitchChance < rnd(1, 101)) ? 1 : 0;
if (inst->doColorDistortion)
{
g0r_state.distortionSeed1 = rnd(0x00000000, 0xfffffffe);
g0r_state.distortionSeed2 = rnd(0x00000000, 0xfffffffe);
g0r_state.howToDistort1 = rnd (0, inst->colorGlitchIntensity);
g0r_state.howToDistort2 = rnd (0, inst->colorGlitchIntensity);
inst->state.distortionSeed1 = rnd(0x00000000, 0xfffffffe);
inst->state.distortionSeed2 = rnd(0x00000000, 0xfffffffe);
inst->state.howToDistort1 = rnd (0, inst->colorGlitchIntensity);
inst->state.howToDistort2 = rnd (0, inst->colorGlitchIntensity);
}
}
@@ -311,42 +313,42 @@ void f0r_update(f0r_instance_t instance, double time,
for (y = 0; y < inst->height; y++)
{
if (g0r_state.currentPos > g0r_state.currentBlock)
if (inst->state.currentPos > inst->state.currentBlock)
{
glitch0r_state_reset(inst);
}
else
g0r_state.currentPos++;
inst->state.currentPos++;
g0r_state.currentY = y*inst->width;
pixel = dst + g0r_state.currentY;
inst->state.currentY = y*inst->width;
pixel = dst + inst->state.currentY;
if (g0r_state.passThisLine)
if (inst->state.passThisLine)
{
memcpy((uint32_t *)(dst + g0r_state.currentY),
(uint32_t *)(src + g0r_state.currentY),
memcpy((uint32_t *)(dst + inst->state.currentY),
(uint32_t *)(src + inst->state.currentY),
(inst->width) * sizeof(uint32_t));
continue;
}
for (x = g0r_state.blkShift; x < (inst->width); x++)
for (x = inst->state.blkShift; x < (inst->width); x++)
{
*(pixel) = *(src + g0r_state.currentY + x);
*(pixel) = *(src + inst->state.currentY + x);
if (inst->doColorDistortion)
glitch0r_pixel_dist0rt(pixel,
g0r_state.distortionSeed1, g0r_state.howToDistort1);
inst->state.distortionSeed1, inst->state.howToDistort1);
pixel++;
}
for (x = 0; x < g0r_state.blkShift; x++)
for (x = 0; x < inst->state.blkShift; x++)
{
*(pixel) = *(src + g0r_state.currentY + x);
*(pixel) = *(src + inst->state.currentY + x);
if (inst->doColorDistortion)
glitch0r_pixel_dist0rt(pixel,
g0r_state.distortionSeed2, g0r_state.howToDistort2);
inst->state.distortionSeed2, inst->state.howToDistort2);
pixel++;
}

View File

@@ -29,17 +29,15 @@
#include "frei0r.h"
#include "frei0r/math.h"
static int MY_MAX_RAND = 32767;// I assume RAND_MAX to be at least this big.
static double gaussian_lookup[32767];
static int TABLE_INITED = 0;
static int next_gaussian_index = 0;
static int last_in_range = 32766;
typedef struct rgbnoise_instance
{
unsigned int width;
unsigned int height;
double noise;
double gaussian_lookup[32767];
int table_inited;
int next_gaussian_index;
int last_in_range;
} rgbnoise_instance_t;
@@ -74,9 +72,12 @@ void f0r_get_param_info(f0r_param_info_t* info, int param_index)
f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
{
rgbnoise_instance_t* inst = (rgbnoise_instance_t*)calloc(1, sizeof(*inst));
inst->width = width;
inst->width = width;
inst->height = height;
inst->noise = 0.2;
inst->table_inited = 0;
inst->next_gaussian_index = 0;
inst->last_in_range = 32766;
return (f0r_instance_t)inst;
}
@@ -133,53 +134,44 @@ static inline double gauss()
return x;
}
static void create_new_lookup_range()
static void create_new_lookup_range(rgbnoise_instance_t* inst)
{
int first, last, tmp;
first = rand() % (MY_MAX_RAND - 1);
last = rand() % (MY_MAX_RAND - 1);
first = rand() % (32767 - 1);
last = rand() % (32767 - 1);
if (first > last)
{
tmp = last;
last = first;
first = tmp;
}
next_gaussian_index = first;
last_in_range = last;
inst->next_gaussian_index = first;
inst->last_in_range = last;
}
static inline double next_gauss()
static inline double next_gauss(rgbnoise_instance_t* inst)
{
next_gaussian_index++;
if (next_gaussian_index >= last_in_range)
inst->next_gaussian_index++;
if (inst->next_gaussian_index >= inst->last_in_range)
{
create_new_lookup_range();
create_new_lookup_range(inst);
}
return gaussian_lookup[next_gaussian_index];
return inst->gaussian_lookup[inst->next_gaussian_index];
}
static inline int addNoise(int sample, double noise)
static inline int addNoise(rgbnoise_instance_t* inst, int sample, double noise)
{
int byteNoise = 0;
int noiseSample = 0;
byteNoise = (int) (noise * next_gauss());
byteNoise = (int) (noise * next_gauss(inst));
noiseSample = sample + byteNoise;
noiseSample = CLAMP(noiseSample, 0, 255);
return noiseSample;
}
}
int f0r_init()
{
if (TABLE_INITED == 0)
{
int i;
for( i = 0; i < MY_MAX_RAND; i++)
{
gaussian_lookup[i] = gauss() * 127.0;
}
TABLE_INITED = 1;
}
return 1;
}
@@ -189,6 +181,19 @@ void rgb_noise(f0r_instance_t instance, double time,
rgbnoise_instance_t* inst = (rgbnoise_instance_t*)instance;
unsigned int len = inst->width * inst->height;
// Initialize the gaussian lookup table if not already done
if (inst->table_inited == 0)
{
int i;
for( i = 0; i < 32767; i++)
{
inst->gaussian_lookup[i] = gauss() * 127.0;
}
inst->table_inited = 1;
inst->next_gaussian_index = 0;
inst->last_in_range = 32766;
}
unsigned char* dst = (unsigned char*)outframe;
const unsigned char* src = (unsigned char*)inframe;
@@ -197,11 +202,11 @@ void rgb_noise(f0r_instance_t instance, double time,
while (len--)
{
sample = *src++;
*dst++ = addNoise(sample, noise);
*dst++ = addNoise(inst, sample, noise);
sample = *src++;
*dst++ = addNoise(sample, noise);
*dst++ = addNoise(inst, sample, noise);
sample = *src++;
*dst++ = addNoise(sample, noise);
*dst++ = addNoise(inst, sample, noise);
*dst++ = *src++;
}
}