videolevels: Change levels ranges to always be (0.0, 1.0)

Now input and output levels always range from 0 to 1, regardless of what the input or output bit-depths are. This simplifies setting and getting these properties.
This commit is contained in:
Joshua M. Doe 2010-04-27 12:14:52 -04:00
parent 90f417f099
commit 9f2559c49a

View File

@ -247,16 +247,16 @@ gst_videolevels_class_init (GstVideoLevelsClass * object)
/* Install GObject properties */ /* Install GObject properties */
g_object_class_install_property (obj_class, PROP_LOWIN, g_object_class_install_property (obj_class, PROP_LOWIN,
g_param_spec_double ("lower-input-level", "Lower Input Level", "Lower Input Level", g_param_spec_double ("lower-input-level", "Lower Input Level", "Lower Input Level",
-G_MINDOUBLE, G_MAXDOUBLE, DEFAULT_PROP_LOWIN, G_PARAM_READWRITE)); 0.0, 1.0, DEFAULT_PROP_LOWIN, G_PARAM_READWRITE));
g_object_class_install_property (obj_class, PROP_HIGHIN, g_object_class_install_property (obj_class, PROP_HIGHIN,
g_param_spec_double ("upper-input-level", "Upper Input Level", "Upper Input Level", g_param_spec_double ("upper-input-level", "Upper Input Level", "Upper Input Level",
-G_MINDOUBLE, G_MAXDOUBLE, DEFAULT_PROP_HIGHIN, G_PARAM_READWRITE)); 0.0, 1.0, DEFAULT_PROP_HIGHIN, G_PARAM_READWRITE));
g_object_class_install_property (obj_class, PROP_LOWOUT, g_object_class_install_property (obj_class, PROP_LOWOUT,
g_param_spec_double ("lower-output-level", "Lower Output Level", "Lower Output Level", g_param_spec_double ("lower-output-level", "Lower Output Level", "Lower Output Level",
-G_MINDOUBLE, G_MAXDOUBLE, DEFAULT_PROP_LOWOUT, G_PARAM_READWRITE)); 0.0, 1.0, DEFAULT_PROP_LOWOUT, G_PARAM_READWRITE));
g_object_class_install_property (obj_class, PROP_HIGHOUT, g_object_class_install_property (obj_class, PROP_HIGHOUT,
g_param_spec_double ("upper-output-level", "Upper Output Level", "Upper Output Level", g_param_spec_double ("upper-output-level", "Upper Output Level", "Upper Output Level",
-G_MINDOUBLE, G_MAXDOUBLE, DEFAULT_PROP_HIGHOUT, G_PARAM_READWRITE)); 0.0, 1.0, DEFAULT_PROP_HIGHOUT, G_PARAM_READWRITE));
g_object_class_install_property (obj_class, PROP_AUTO, g_object_class_install_property (obj_class, PROP_AUTO,
g_param_spec_enum ("auto", "Auto Adjust", g_param_spec_enum ("auto", "Auto Adjust",
"Auto adjust contrast", GST_TYPE_VIDEOLEVELS_AUTO, "Auto adjust contrast", GST_TYPE_VIDEOLEVELS_AUTO,
@ -510,16 +510,6 @@ gst_videolevels_set_caps (GstBaseTransform * base, GstCaps * incaps,
levels->stride_in = GST_ROUND_UP_4 (levels->width * levels->depth_in/8); levels->stride_in = GST_ROUND_UP_4 (levels->width * levels->depth_in/8);
levels->stride_out = GST_ROUND_UP_4 (levels->width * levels->depth_out/8); levels->stride_out = GST_ROUND_UP_4 (levels->width * levels->depth_out/8);
levels->lower_input = 0.0;
levels->upper_input = (1 << levels->bpp_in) - 1;
levels->lower_output = 0.0;
levels->upper_output = (1 << levels->bpp_out) - 1;
g_object_notify (G_OBJECT (levels), "lower-input-level");
g_object_notify (G_OBJECT (levels), "upper-input-level");
g_object_notify (G_OBJECT (levels), "lower-output-level");
g_object_notify (G_OBJECT (levels), "upper-output-level");
//gst_videolevels_calculate_tables (levels); //gst_videolevels_calculate_tables (levels);
return res; return res;
@ -673,7 +663,7 @@ static void gst_videolevels_reset(GstVideoLevels* videolevels)
* *
* Calculate lookup tables based on input and output levels * Calculate lookup tables based on input and output levels
*/ */
static void /*static void
gst_videolevels_calculate_tables (GstVideoLevels * videolevels) gst_videolevels_calculate_tables (GstVideoLevels * videolevels)
{ {
gint i; gint i;
@ -724,7 +714,7 @@ gst_videolevels_calculate_tables (GstVideoLevels * videolevels)
for (i = 0; i < 65536; i += 128) for (i = 0; i < 65536; i += 128)
GST_DEBUG ("lut[%d / %d] = %d", i, GUINT16_SWAP_LE_BE(i), lut[i]); GST_DEBUG ("lut[%d / %d] = %d", i, GUINT16_SWAP_LE_BE(i), lut[i]);
} }*/
#define GINT_CLAMP(x, low, high) ((gint)(CLAMP((x),(low),(high)))) #define GINT_CLAMP(x, low, high) ((gint)(CLAMP((x),(low),(high))))
#define GUINT8_CLAMP(x, low, high) ((guint8)(CLAMP((x),(low),(high)))) #define GUINT8_CLAMP(x, low, high) ((guint8)(CLAMP((x),(low),(high))))
@ -737,23 +727,26 @@ gst_videolevels_convert_uint16le_to_uint8(GstVideoLevels * videolevels,
const gint size = videolevels->stride_in / 2 * videolevels->height; const gint size = videolevels->stride_in / 2 * videolevels->height;
gdouble m; gdouble m;
gdouble b; gdouble b;
const guint8 low = (guint8) videolevels->lower_output; const guint16 max_in = (1 << videolevels->bpp_in) - 1;
const guint8 high = (guint8) videolevels->upper_output; const guint16 low_in = (guint16) (videolevels->lower_input * max_in);
const guint16 high_in = (guint16) (videolevels->upper_input * max_in);
const guint8 max_out = (1 << videolevels->bpp_out) - 1;
const guint8 low_out = (guint8) (videolevels->lower_output * max_out);
const guint8 high_out = (guint8) (videolevels->upper_output * max_out);
GST_DEBUG ("Applying linear mapping (%.3f, %.3f) -> (%.3f, %.3f)", GST_DEBUG ("Applying linear mapping (%d, %d) -> (%d, %d)",
videolevels->lower_input, videolevels->upper_input, low_in, high_in, low_out, high_out);
videolevels->lower_output, videolevels->upper_output);
if (videolevels->lower_input == videolevels->upper_input) if (low_in == high_in)
m = 0; m = 0.0;
else else
m = (videolevels->upper_output - videolevels->lower_output) / m = (high_out - low_out) / (gdouble)(high_in - low_in);
(videolevels->upper_input - videolevels->lower_input);
b = videolevels->lower_output - m * videolevels->lower_input; b = low_out - m * low_in;
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
out[i] = GUINT8_CLAMP (m * GUINT16_FROM_LE (in[i]) + b, low, high); out[i] = GUINT8_CLAMP (m * GUINT16_FROM_LE (in[i]) + b, low_out, high_out);
} }
void void
@ -764,23 +757,25 @@ gst_videolevels_convert_uint16be_to_uint8(GstVideoLevels * videolevels,
const gint size = videolevels->stride_in / 2 * videolevels->height; const gint size = videolevels->stride_in / 2 * videolevels->height;
gdouble m; gdouble m;
gdouble b; gdouble b;
const guint8 low = (guint8) videolevels->lower_output; const guint16 max_in = (1 << videolevels->bpp_in) - 1;
const guint8 high = (guint8) videolevels->upper_output; const guint16 low_in = (guint16) (videolevels->lower_input * max_in);
const guint16 high_in = (guint16) (videolevels->upper_input * max_in);
const guint8 max_out = (1 << videolevels->bpp_out) - 1;
const guint8 low_out = (guint8) (videolevels->lower_output * max_out);
const guint8 high_out = (guint8) (videolevels->upper_output * max_out);
GST_DEBUG ("Applying linear mapping (%.3f, %.3f) -> (%.3f, %.3f)", GST_DEBUG ("Applying linear mapping (%d, %d) -> (%d, %d)",
videolevels->lower_input, videolevels->upper_input, low_in, high_in, low_out, high_out);
videolevels->lower_output, videolevels->upper_output);
if (low_in == high_in)
if (videolevels->lower_input == videolevels->upper_input) m = 0.0;
m = 0;
else else
m = (videolevels->upper_output - videolevels->lower_output) / m = (high_out - low_out) / (gdouble)(high_in - low_in);
(videolevels->upper_input - videolevels->lower_input);
b = videolevels->lower_output - m * videolevels->lower_input; b = low_out - m * low_in;
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
out[i] = GUINT8_CLAMP (m * GUINT16_FROM_BE (in[i]) + b, low, high); out[i] = GUINT8_CLAMP (m * GUINT16_FROM_BE (in[i]) + b, low_out, high_out);
} }
/** /**
@ -925,7 +920,7 @@ gst_videolevels_auto_adjust (GstVideoLevels * videolevels,
sum += videolevels->histogram[i]; sum += videolevels->histogram[i];
if (sum > npixsat) { if (sum > npixsat) {
videolevels->lower_input = videolevels->lower_input =
CLAMP (i / (gdouble)videolevels->nbins * max, min, max); CLAMP (i / (gdouble)videolevels->nbins, 0.0, 1.0);
break; break;
} }
} }
@ -937,12 +932,12 @@ gst_videolevels_auto_adjust (GstVideoLevels * videolevels,
sum += videolevels->histogram[i]; sum += videolevels->histogram[i];
if (sum > npixsat) { if (sum > npixsat) {
videolevels->upper_input = videolevels->upper_input =
CLAMP ((i + 1) / (gdouble)videolevels->nbins * max, min, max); CLAMP ((i + 1) / (gdouble)videolevels->nbins, 0.0, 1.0);
break; break;
} }
} }
GST_DEBUG ("Contrast stretch with npixsat=%d, (%.3f, %.3f)", npixsat, GST_DEBUG ("Contrast stretch with npixsat=%d, (%.6f, %.6f)", npixsat,
videolevels->lower_input, videolevels->upper_input); videolevels->lower_input, videolevels->upper_input);
g_object_notify (G_OBJECT (videolevels), "lower-input-level"); g_object_notify (G_OBJECT (videolevels), "lower-input-level");