Skip to content

Instantly share code, notes, and snippets.

@nomadalex
Created March 24, 2011 02:19
Show Gist options
  • Save nomadalex/884433 to your computer and use it in GitHub Desktop.
Save nomadalex/884433 to your computer and use it in GitHub Desktop.
#define FILTER_PI (3.1415926535897932384626433832795)
#define FILTER_2PI (2.0 * 3.1415926535897932384626433832795)
#define FILTER_4PI (4.0 * 3.1415926535897932384626433832795)
#define FILTER_SET_PARAM_IMP(type) int filter_##type##_set_param(void *this,double val,int flags) { \
assert(this != NULL); \
switch(flags) { \
case FILTER_SET_WIDTH: \
(Filter_##type *)this->width = val; \
return 1; \
break; \
default: \
break; \
} \
return 0; \
}
#define FILTER_GET_PARAM_IMP(type) int filter_##type##_get_param(void *this,double *pval,int flags) { \
assert((this != NULL) && (pval != NULL)); \
switch(flags) { \
case FILTER_GET_WIDTH: \
*pval = (Filter_##type *)this->width; \
return 1; \
break; \
default: \
break; \
} \
return 0; \
}
#define FILTER_CREATE_IMP(type, val) void* filter_box_create() \
{ \
Filter_##type * box = (Filter_##type *)malloc(sizeof(Filter_##type)); \
box->width = val; \
return (void*)box; \
}
//////////////////////////////////////////////////////////////////////////
//BOX FILTER BEGIN
typedef struct _filter_box {
double width;
}Filter_box;
double filter_box_func (void *this, double val)
{
return (fabs(val) <= (Filter_box*) this->width ? 1.0 : 0.0);
}
FILTER_SET_PARAM_IMP(box)
FILTER_GET_PARAM_IMP(box)
FILTER_CREATE_IMP(box, 0.5)
//BOX FILTER END
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//Bilinear FILTER BEGIN
typedef struct _filter_bilinear{
double width;
}Filter_bilinear;
double filter_bilinear_func (void *this,double val)
{
double width = (Filter_bilinear*) this->width;
val = fabs(val);
return (val < width ? width - val : 0.0);
}
FILTER_SET_PARAM_IMP(bilinear)
FILTER_GET_PARAM_IMP(bilinear)
FILTER_CREATE_IMP(bilinear, 1.0)
//Bilinear FILTER END
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//Gaussian FILTER BEGIN
typedef struct _filter_gaussian{
double width;
}Filter_gaussian;
double filter_gaussian_func (void *this,double val)
{
return (fabs(val) > (Filter_gaussian*)this->width ? 0.0 : (exp(-val * val / 2.0)) / sqrt(FILTER_2PI));
}
FILTER_SET_PARAM_IMP(gaussian)
FILTER_GET_PARAM_IMP(gaussian)
FILTER_CREATE_IMP(gaussian, 3.0)
//Gaussian FILTER END
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//Hamming FILTER BEGIN
typedef struct _filter_hamming{
double width;
}Filter_hamming;
double filter_hamming_func (void *this,double val)
{
if (fabs (val) > (Filter_hamming*)this->width)
return 0.0;
{
double window = 0.54 + 0.46 * cos (FILTER_2PI * val);
double sinc = (val == 0) ? 1.0 : sin (FILTER_PI * val) / (FILTER_PI * val);
return window * sinc;
}
}
FILTER_SET_PARAM_IMP(hamming)
FILTER_GET_PARAM_IMP(hamming)
FILTER_CREATE_IMP(hamming, 0.5)
//Hamming FILTER END
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//Blackman FILTER BEGIN
typedef struct _filter_blackman{
double width;
}Filter_blackman;
double filter_blackman_func (void *this,double val)
{
double width = (Filter_blackman*)this->width;
if (fabs (val) > width)
return 0.0;
{
dobule d = 2.0 * width + 1.0;
return (0.42 + 0.5 * cos (FILTER_2PI * val / ( d - 1.0 )) +
0.08 * cos (FILTER_4PI * val / ( d - 1.0 )));
}
}
FILTER_SET_PARAM_IMP(blackman)
FILTER_GET_PARAM_IMP(blackman)
FILTER_CREATE_IMP(blackman, 0.5)
//Blackman FILTER END
//////////////////////////////////////////////////////////////////////////
// we do not need it now
#undef FILTER_CREATE_IMP FILTER_GET_PARAM_IMP FILTER_SET_PARAM_IMP
typedef void* (*Filter_create)();
typedef double (*Filter_proc)(void *this,double val);
typedef int (*Filter_set_param)(void *this,double val,int flags);
typedef int (*Filter_get_param)(void *this,double* pval,int flags);
#define DEFINE_FILTER_FUNS(func) \
const Filter_##func filter_##func##_funs[] = { \
filter_box_##func, \
filter_bilinear_##func, \
filter_gaussian_##func, \
filter_hamming_##func, \
filter_blackman_##func, \
};
DEFINE_FILTER_FUNS(create)
DEFINE_FILTER_FUNS(proc)
DEFINE_FILTER_FUNS(get_param)
DEFINE_FILTER_FUNS(set_param)
void filter_destroy(void *this)
{
free(this);
}
// we do not need it now
#undef DEFINE_FILTER_FUNS
// c10n == contribution
typedef struct
{
double *weights; // Normalized weights of neighboring pixels
int left,right; // Bounds of source pixels window
} C10n; // Contirbution information for a single pixel
typedef struct
{
C10n *row; // Row (or column) of contribution weights
uint32 win_size, // Filter window size (of affecting source pixels)
line_len; // Length of line (no. or rows / cols)
} Line_c10n; // Contribution information for an entire line (row or column)
Line_c10n* alloc_contributions (uint32 line_length, uint32 window_size)
{
uint32 i = 0;
Line_c10n *res = (Line_c10n*)malloc(sizeof(Line_c10n));
// Init structure header
res->win_size = window_size;
res->line_len = line_length;
// Allocate list of contributions
res->row = (C10n*)malloc(sizeof(C10n)*line_length);//new ContributionType[uLineLength];
for(; i < line_length ; i++)
{
// Allocate contributions for every pixel
res->row[i].weights = (double*)malloc(sizeof(double)*window_size);//new double[uWindowSize];
memset(res->row[i].weights,0,sizeof(double)*window_size);
}
return res;
}
void free_contributions (Line_c10n *p)
{
uint32 i = 0;
for (; i < p->line_len; i++)
{
// Free contribs for every pixel
free(p->row[i].weights);
}
free(p->row); // Free list of pixels contribs
free(p); // Free contribs header
}
Line_c10n* calc_contributions (void* filter,int filter_type, uint32 line_size, uint32 src_size, double scale)
{
//FilterClass CurFilter;
uint32 u, i;
int left, right , window_size;
double width, center, total_weight;
double fscale = 1.0;
double fwidth;
Line_c10n *res;
filter_get_prama_funs[filter_type](filter, &fwidth, FILTER_GET_PRAMA);
if (scale < 1.0)
{ // Minification
width = fwidth / scale;
fscale = scale;
}
else
{ // Magnification
width= fwidth;
}
// Window size is the number of sampled pixels
window_size = 2 * (int)ceil(width) + 1;
// Allocate a new line contributions strucutre
res = alloc_contributions (line_size, window_size);
for (u = 0; u < line_size; u++)
{ // Scan through line of contributions
center = (double)u / scale; // Reverse mapping
// Find the significant edge points that affect the pixel
left = _max (0, (int)floor (center - width));
(*(res->row+u)).left = left;
right = _min ((int)ceil (center + width), (int)src_size - 1);
(*(res->row+u)).right = right;
// Cut edge points to fit in filter window in case of spill-off
if (right - left + 1 > window_size)
{
if (left < ((int)src_size - 1 / 2))
{
left++;
}
else
{
right--;
}
}
total_weight = 0.0; // Zero sum of weights
for (i = left; i <= right; i++)
{ // Calculate weights
double test = filter_proc_funs[filter_type](filter,fscale * (center - (double)i));
res->row[u].weights[i-left] =
fscale * filter_proc_funs[filter_type](filter,fscale * (center - (double)i));
total_weight += res->row[u].weights[i-left];
}
if (total_weight > 0.0)
{ // Normalize weight of neighbouring points
for (i = left; i <= right; i++)
{ // Normalize point
res->row[u].weights[i-left] /= total_weight;
}
}
}
return res;
}
#define SCALE_FUN_IMP(type, dw_or_dh, _sdata, _ddata, _src_n, _dst_n) \
void scale_##type (uint8 *sdata, uint32 sw, uint8 *ddata, uint32 dw_or_dh, uint32 u, Line_c10n *contrib,uint32 dpitch,uint32 dtype) \
{ \
uint32 ii, i; \
uint8 r,g,b,a,sr,sb,sg,sa; \
uint32 left,right; \
uint32 *src32,*dst32; \
uint16 *src16,*dst16; \
src32 = (uint32*) _sdata; \
dst32 = (uint32*) _ddata; \
src16 = (uint16*) _sdata; \
dst16 = (uint16*) _ddata; \
for (ii = 0; ii < dw_or_dh; ii++) \
{ \
left = contrib->row[y].left; \
right = contrib->row[y].right; \
r = 0,g = 0,b = 0,a = 0; \
for (i = left; i <= right; i++) \
{ \
\
if(dtype == DISPLAY_PIXEL_FORMAT_8888){ \
GET_RGBA_8888(src32[ _src_n ],sr,sg,sb,sa); \
} \
else if(dtype == DISPLAY_PIXEL_FORMAT_4444){ \
GET_RGBA_4444(src16[ _src_n ],sr,sg,sb,sa); \
} \
else if(dtype == DISPLAY_PIXEL_FORMAT_5551){ \
GET_RGBA_5551(src16[ _src_n ],sr,sg,sb,sa); \
} \
else if(dtype == DISPLAY_PIXEL_FORMAT_565){ \
GET_RGBA_565(src16[ _src_n ],sr,sg,sb,sa); \
} \
if(sa==0) \
continue; \
r += (uint8)(contrib->row[ii].weights[i-left] * (double)(sr)); \
g += (uint8)(contrib->row[ii].weights[i-left] * (double)(sg)); \
b += (uint8)(contrib->row[ii].weights[i-left] * (double)(sb)); \
a += (uint8)(contrib->row[ii].weights[i-left] * (double)(sa)); \
} \
if(dtype == DISPLAY_PIXEL_FORMAT_8888) \
dst32[ _dst_n ] = MAKE_RGBA_8888(r,g,b,a); \
else if(dtype == DISPLAY_PIXEL_FORMAT_4444) \
dst16[ _dst_n ] = MAKE_RGBA_4444(r,g,b,a); \
else if(dtype == DISPLAY_PIXEL_FORMAT_5551) \
dst16[ _dst_n ] = MAKE_RGBA_5551(r,g,b,a); \
else if(dtype == DISPLAY_PIXEL_FORMAT_565) \
dst16[ _dst_n ] = MAKE_RGBA_565(r,g,b,a); \
} \
}
SCALE_FUN_IMP(row, dw, sdata+u*spitch, ddata+u*dw, i, ii)
SCALE_FUN_IMP(col, dh, sdata, ddata, i*sw+u, ii*dpitch+u)
#define DIRE_SCALE_FUN_IMP(type, dire, dire2) \
void type##_scale (void* filter, int filter_type, uint8 *sdata, uint32 sw, uint32 sh, uint8 *ddata, uint32 dw, uint32 dh,uint32 spitch,uint32 dtype) \
{ \
uint32 u; \
Line_c10n * contrib; \
if (d##dire == s##dire) \
{ /* No scaling required, just copy */ \
if(dtype == DISPLAY_PIXEL_FORMAT_8888) \
memcpy (ddata, sdata, sizeof (uint32) * sw * sh); \
else \
memcpy (ddata, sdata, sizeof (uint16) * sw * sh); \
} \
/* Allocate and calculate the contributions */ \
contrib = calc_contributions (filter, filter_type, d##dire, s##dire, (double)d##dire / (double)s##dire); \
for (u = 0; u < d##dire2; u++) \
{ /* Step through rows */ \
scale_##stype (sdata, sw, ddata, d##dire, u, contrib, spitch, dtype); \
} \
free_contributions (contrib); /* Free contributions structure */ \
}
DIRE_SCALE_FUN_IMP(horiz, w, h)
DIRE_SCALE_FUN_IMP(vert, h, w)
//image scale
image_p image_scale(image_p src, int w, int h,int mode)
{
image_p dst;
uint8 * temp;
uint8 recover = 0;
uint32 spitch, dpitch;
void* filter = filter_create_funs[mode]();
dst = image_create(w,h,src->dtype);
dst->dontswizzle = 1;
if(src->swizzle ==1){
unswizzle_swap(src);
recover = 1;
}
temp = malloc(dst->w*src->h*src->bpb);
memset(temp,0,dst->w*src->h*src->bpb);
spitch = src->texw;
dpitch = dst->texw;
horiz_scale(filter, mode, src->data,src->w,src->h,temp,dst->w,src->h,spitch,src->dtype);
vert_scale (filter, mode, temp,dst->w,src->h,dst->data,dst->w,dst->h,dpitch,src->dtype);
free(temp);
destroy_filter(filter);
if(recover)
swizzle_swap(src);
return dst;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment