NicolasRobidoux wrote:fmw42 wrote:...What is the functional difference?...
Code: Select all
#define sigmoidal(a,b,x) (1/(1+exp((a)*((b)-(x)))))
#if 0
/* Simpilified function scaling,
* with better 'contrast=0' or 'flatline' handling (greyscale)
*/
double
u0 = sigmoidal(contrast,QuantumScale*midpoint,0.0),
u1 = sigmoidal(contrast,QuantumScale*midpoint,1.0);
sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum(
(MagickRealType)(MaxMap*(
(sigmoidal(contrast,QuantumScale*midpoint,(double)i/MaxMap)
-(u0+u1)/2.0)/(u1-u0+MagickEpsilon)+0.5) ));
#else
/* Scaled sigmoidal formula...
(1/(1+exp(a*(b-u))) - 1/(1+exp(a))) /
(1/(1+exp(a*(b-1)))/(1+exp(a)))) */
sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum((MagickRealType)
(MaxMap*((1.0/(1.0+exp(contrast*(midpoint/(double) QuantumRange-
(double) i/MaxMap))))-(1.0/(1.0+exp(contrast*(midpoint/
(double) QuantumRange)))))/((1.0/(1.0+exp(contrast*(midpoint/
(double) QuantumRange-1.0))))-(1.0/(1.0+exp(contrast*(midpoint/
(double) QuantumRange)))))+0.5));
#endif
continue;
}
#if 0
{
/* Inverse -- See
http://osdir.com/ml/video.image-magick.devel/2005-04/msg00006.html
*/
double
min = sigmoidal(contrast,1.0,0.0),
max = sigmoidal(contrast,QuantumScale*midpoint,1.0),
xi = min+(double)i/MaxMap*(max-min);
sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum(
(MagickRealType)(MaxMap*(
QuantumScale*midpoint-log((1-xi)/xi)/contrast) ));
}
#else
/* expanded form of the above */
sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum((MagickRealType)
(MaxMap*(QuantumScale*midpoint-log((1.0-(1.0/(1.0+exp(midpoint/
(double) QuantumRange*contrast))+((double) i/MaxMap)*((1.0/
(1.0+exp(contrast*(midpoint/(double) QuantumRange-1.0))))-(1.0/
(1.0+exp(midpoint/(double) QuantumRange*contrast))))))/
(1.0/(1.0+exp(midpoint/(double) QuantumRange*contrast))+
((double) i/MaxMap)*((1.0/(1.0+exp(contrast*(midpoint/
(double) QuantumRange-1.0))))-(1.0/(1.0+exp(midpoint/
(double) QuantumRange*contrast))))))/contrast)));
#endif
The "#if 0"s above were "#if 1"s until today, so what you are using right now are actually the first version of each of the two functions, which appear to have been put together so that things don't break down when contrast = 0, in which case u0=u1. The bad news for me is that the sigmoidal map which is supposed to be an inverse is then fairly far from being an inverse even when far from contrast=0.
The two functions should be the same. If they aren't then something went wrong.
The reason the change was made was because Fred insisted that a '0' (and non-sensical, default is 1) contrast handling produces a flat pure gray image, rather than pure black.
In both cases (except the flatline case) the function should be scaled so that black maps to black and white to white. The difference is the 'center' for scaling is a mid-point rather than zero. That mid-point scaling complication, ment the introduction of macros, which simplified the otherwise very complex calculation,
BOTH versions should produce the same results (within quantum rounding) except when near the degenerate '0' or flat line case.
If the two versions are not the same then there is an error.
I do not believe the + version was modified. (scale around 0 rather than mid-point). The only inverse difference should be again near the degenerate 'flatline' case, as information loss takes effect.
NOTE; I was against this change as I considered the degenerate flatline case to be something that should never be used. However Fred insisted that it be handled.
I now remove my objection to reverting back. OR better still --
Why are the two not equivalent? At least for non-degenerate cases.