Created
March 24, 2011 02:19
-
-
Save nomadalex/884433 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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