Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2013-08-21 21:42:32 +0400
committerPaul B Mahol <onemda@gmail.com>2013-08-22 18:56:13 +0400
commitb1e276f8df257a7ad190419b349d0d86d104c8ae (patch)
tree39d41317b8d34cdc8e949aa50a3b591af49ce4a2 /libavfilter/vf_hue.c
parent6e643239d9956ce32888d87451706ee7c8757afa (diff)
lavfi/hue: allow changing brightness
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavfilter/vf_hue.c')
-rw-r--r--libavfilter/vf_hue.c69
1 files changed, 62 insertions, 7 deletions
diff --git a/libavfilter/vf_hue.c b/libavfilter/vf_hue.c
index d066c4075f..e5017fbb62 100644
--- a/libavfilter/vf_hue.c
+++ b/libavfilter/vf_hue.c
@@ -68,11 +68,15 @@ typedef struct {
float saturation;
char *saturation_expr;
AVExpr *saturation_pexpr;
+ float brightness;
+ char *brightness_expr;
+ AVExpr *brightness_pexpr;
int hsub;
int vsub;
int32_t hue_sin;
int32_t hue_cos;
double var_values[VAR_NB];
+ uint8_t lut_l[256];
uint8_t lut_u[256][256];
uint8_t lut_v[256][256];
} HueContext;
@@ -86,6 +90,8 @@ static const AVOption hue_options[] = {
{ .str = "1" }, .flags = FLAGS },
{ "H", "set the hue angle radians expression", OFFSET(hue_expr), AV_OPT_TYPE_STRING,
{ .str = NULL }, .flags = FLAGS },
+ { "b", "set the brightness expression", OFFSET(brightness_expr), AV_OPT_TYPE_STRING,
+ { .str = "0" }, .flags = FLAGS },
{ NULL }
};
@@ -102,6 +108,16 @@ static inline void compute_sin_and_cos(HueContext *hue)
hue->hue_cos = rint(cos(hue->hue) * (1 << 16) * hue->saturation);
}
+static inline void create_luma_lut(HueContext *h)
+{
+ const float b = h->brightness;
+ int i;
+
+ for (i = 0; i < 256; i++) {
+ h->lut_l[i] = av_clip_uint8(i + b * 25.5);
+ }
+}
+
static inline void create_chrominance_lut(HueContext *h, const int32_t c,
const int32_t s)
{
@@ -181,14 +197,15 @@ static av_cold int init(AVFilterContext *ctx)
if (ret < 0) \
return ret; \
} while (0)
+ SET_EXPR(brightness, "b");
SET_EXPR(saturation, "s");
SET_EXPR(hue_deg, "h");
SET_EXPR(hue, "H");
#undef SET_EXPR
av_log(ctx, AV_LOG_VERBOSE,
- "H_expr:%s h_deg_expr:%s s_expr:%s\n",
- hue->hue_expr, hue->hue_deg_expr, hue->saturation_expr);
+ "H_expr:%s h_deg_expr:%s s_expr:%s b_expr:%s\n",
+ hue->hue_expr, hue->hue_deg_expr, hue->saturation_expr, hue->brightness_expr);
compute_sin_and_cos(hue);
return 0;
@@ -198,6 +215,7 @@ static av_cold void uninit(AVFilterContext *ctx)
{
HueContext *hue = ctx->priv;
+ av_expr_free(hue->brightness_pexpr);
av_expr_free(hue->hue_deg_pexpr);
av_expr_free(hue->hue_pexpr);
av_expr_free(hue->saturation_pexpr);
@@ -235,6 +253,22 @@ static int config_props(AVFilterLink *inlink)
return 0;
}
+static void apply_luma_lut(HueContext *s,
+ uint8_t *ldst, const int dst_linesize,
+ uint8_t *lsrc, const int src_linesize,
+ int w, int h)
+{
+ int i;
+
+ while (h--) {
+ for (i = 0; i < w; i++)
+ ldst[i] = s->lut_l[lsrc[i]];
+
+ lsrc += src_linesize;
+ ldst += dst_linesize;
+ }
+}
+
static void apply_lut(HueContext *s,
uint8_t *udst, uint8_t *vdst, const int dst_linesize,
uint8_t *usrc, uint8_t *vsrc, const int src_linesize,
@@ -267,6 +301,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
AVFilterLink *outlink = inlink->dst->outputs[0];
AVFrame *outpic;
const int32_t old_hue_sin = hue->hue_sin, old_hue_cos = hue->hue_cos;
+ const float old_brightness = hue->brightness;
int direct = 0;
if (av_frame_is_writable(inpic)) {
@@ -296,6 +331,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
}
}
+ if (hue->brightness_expr) {
+ hue->brightness = av_expr_eval(hue->brightness_pexpr, hue->var_values, NULL);
+
+ if (hue->brightness < -10 || hue->brightness > 10) {
+ hue->brightness = av_clipf(hue->brightness, -10, 10);
+ av_log(inlink->dst, AV_LOG_WARNING,
+ "Brightness value not in range [%d,%d]: clipping value to %0.1f\n",
+ -10, 10, hue->brightness);
+ }
+ }
+
if (hue->hue_deg_expr) {
hue->hue_deg = av_expr_eval(hue->hue_deg_pexpr, hue->var_values, NULL);
hue->hue = hue->hue_deg * M_PI / 180;
@@ -305,18 +351,22 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
}
av_log(inlink->dst, AV_LOG_DEBUG,
- "H:%0.1f*PI h:%0.1f s:%0.f t:%0.1f n:%d\n",
- hue->hue/M_PI, hue->hue_deg, hue->saturation,
+ "H:%0.1f*PI h:%0.1f s:%0.f b:%0.f t:%0.1f n:%d\n",
+ hue->hue/M_PI, hue->hue_deg, hue->saturation, hue->brightness,
hue->var_values[VAR_T], (int)hue->var_values[VAR_N]);
compute_sin_and_cos(hue);
if (old_hue_sin != hue->hue_sin || old_hue_cos != hue->hue_cos)
create_chrominance_lut(hue, hue->hue_cos, hue->hue_sin);
+ if (old_brightness != hue->brightness && hue->brightness)
+ create_luma_lut(hue);
+
if (!direct) {
- av_image_copy_plane(outpic->data[0], outpic->linesize[0],
- inpic->data[0], inpic->linesize[0],
- inlink->w, inlink->h);
+ if (!hue->brightness)
+ av_image_copy_plane(outpic->data[0], outpic->linesize[0],
+ inpic->data[0], inpic->linesize[0],
+ inlink->w, inlink->h);
if (inpic->data[3])
av_image_copy_plane(outpic->data[3], outpic->linesize[3],
inpic->data[3], inpic->linesize[3],
@@ -327,6 +377,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
inpic->data[1], inpic->data[2], inpic->linesize[1],
FF_CEIL_RSHIFT(inlink->w, hue->hsub),
FF_CEIL_RSHIFT(inlink->h, hue->vsub));
+ if (hue->brightness)
+ apply_luma_lut(hue, outpic->data[0], outpic->linesize[0],
+ inpic->data[0], inpic->linesize[0], inlink->w, inlink->h);
if (!direct)
av_frame_free(&inpic);
@@ -355,6 +408,8 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar
av_freep(&hue->hue_deg_expr);
} else if (!strcmp(cmd, "s")) {
SET_EXPR(saturation, "s");
+ } else if (!strcmp(cmd, "b")) {
+ SET_EXPR(brightness, "b");
} else
return AVERROR(ENOSYS);