Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/WuQuantizer.cpp view on Meta::CPAN
break;
}
return 0;
}
// Compute remainder of Vol(cube, mmt), substituting pos for
// r1, g1, or b1 (depending on dir)
LONG
WuQuantizer::Top(Box *cube, BYTE dir, int pos, LONG *mmt) {
switch(dir)
{
case FI_RGBA_RED:
return( mmt[INDEX(pos, cube->g1, cube->b1)]
-mmt[INDEX(pos, cube->g1, cube->b0)]
-mmt[INDEX(pos, cube->g0, cube->b1)]
+mmt[INDEX(pos, cube->g0, cube->b0)] );
break;
case FI_RGBA_GREEN:
return( mmt[INDEX(cube->r1, pos, cube->b1)]
-mmt[INDEX(cube->r1, pos, cube->b0)]
-mmt[INDEX(cube->r0, pos, cube->b1)]
+mmt[INDEX(cube->r0, pos, cube->b0)] );
break;
case FI_RGBA_BLUE:
return( mmt[INDEX(cube->r1, cube->g1, pos)]
-mmt[INDEX(cube->r1, cube->g0, pos)]
-mmt[INDEX(cube->r0, cube->g1, pos)]
+mmt[INDEX(cube->r0, cube->g0, pos)] );
break;
}
return 0;
}
// Compute the weighted variance of a box
// NB: as with the raw statistics, this is really the variance * ImageSize
float
WuQuantizer::Var(Box *cube) {
float dr = (float) Vol(cube, mr);
float dg = (float) Vol(cube, mg);
float db = (float) Vol(cube, mb);
float xx = gm2[INDEX(cube->r1, cube->g1, cube->b1)]
-gm2[INDEX(cube->r1, cube->g1, cube->b0)]
-gm2[INDEX(cube->r1, cube->g0, cube->b1)]
+gm2[INDEX(cube->r1, cube->g0, cube->b0)]
-gm2[INDEX(cube->r0, cube->g1, cube->b1)]
+gm2[INDEX(cube->r0, cube->g1, cube->b0)]
+gm2[INDEX(cube->r0, cube->g0, cube->b1)]
-gm2[INDEX(cube->r0, cube->g0, cube->b0)];
return (xx - (dr*dr+dg*dg+db*db)/(float)Vol(cube,wt));
}
// We want to minimize the sum of the variances of two subboxes.
// The sum(c^2) terms can be ignored since their sum over both subboxes
// is the same (the sum for the whole box) no matter where we split.
// The remaining terms have a minus sign in the variance formula,
// so we drop the minus sign and MAXIMIZE the sum of the two terms.
float
WuQuantizer::Maximize(Box *cube, BYTE dir, int first, int last , int *cut, LONG whole_r, LONG whole_g, LONG whole_b, LONG whole_w) {
LONG half_r, half_g, half_b, half_w;
int i;
float temp;
LONG base_r = Bottom(cube, dir, mr);
LONG base_g = Bottom(cube, dir, mg);
LONG base_b = Bottom(cube, dir, mb);
LONG base_w = Bottom(cube, dir, wt);
float max = 0.0;
*cut = -1;
for (i = first; i < last; i++) {
half_r = base_r + Top(cube, dir, i, mr);
half_g = base_g + Top(cube, dir, i, mg);
half_b = base_b + Top(cube, dir, i, mb);
half_w = base_w + Top(cube, dir, i, wt);
// now half_x is sum over lower half of box, if split at i
if (half_w == 0) { // subbox could be empty of pixels!
continue; // never split into an empty box
} else {
temp = ((float)half_r*half_r + (float)half_g*half_g + (float)half_b*half_b)/half_w;
}
half_r = whole_r - half_r;
half_g = whole_g - half_g;
half_b = whole_b - half_b;
half_w = whole_w - half_w;
if (half_w == 0) { // subbox could be empty of pixels!
continue; // never split into an empty box
} else {
temp += ((float)half_r*half_r + (float)half_g*half_g + (float)half_b*half_b)/half_w;
}
if (temp > max) {
max=temp;
*cut=i;
}
}
return max;
}
bool
WuQuantizer::Cut(Box *set1, Box *set2) {
BYTE dir;
int cutr, cutg, cutb;
LONG whole_r = Vol(set1, mr);
LONG whole_g = Vol(set1, mg);
LONG whole_b = Vol(set1, mb);
LONG whole_w = Vol(set1, wt);
( run in 1.170 second using v1.01-cache-2.11-cpan-70e19b8f4f1 )