Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
5f90ef66
Commit
5f90ef66
authored
Dec 06, 2014
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi: add colorlevels filter
Signed-off-by:
Paul B Mahol
<
onemda@gmail.com
>
parent
92a596f1
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
328 additions
and
2 deletions
+328
-2
Changelog
Changelog
+1
-0
filters.texi
doc/filters.texi
+69
-0
Makefile
libavfilter/Makefile
+1
-0
allfilters.c
libavfilter/allfilters.c
+1
-0
version.h
libavfilter/version.h
+2
-2
vf_colorlevels.c
libavfilter/vf_colorlevels.c
+254
-0
No files found.
Changelog
View file @
5f90ef66
...
...
@@ -4,6 +4,7 @@ releases are sorted from youngest to oldest.
version <next>:
- nvenc encoder
- 10bit spp filter
- colorlevels filter
version 2.5:
...
...
doc/filters.texi
View file @
5f90ef66
...
...
@@ -2934,6 +2934,75 @@ colorbalance=rs=.3
@end example
@end itemize
@section colorlevels
Adjust video input frames using levels.
The filter accepts the following options:
@table @option
@item rimin
@item gimin
@item bimin
@item aimin
Adjust red, green, blue and alpha input black point.
Allowed ranges for options are @code{[-1.0, 1.0]}. Defaults are @code{0}.
@item rimax
@item gimax
@item bimax
@item aimax
Adjust red, green, blue and alpha input white point.
Allowed ranges for options are @code{[-1.0, 1.0]}. Defaults are @code{1}.
Input levels are used to lighten highlights (bright tones), darken shadows
(dark tones), change the balance of bright and dark tones.
@item romin
@item gomin
@item bomin
@item aomin
Adjust red, green, blue and alpha output black point.
Allowed ranges for options are @code{[0, 1.0]}. Defaults are @code{0}.
@item romax
@item gomax
@item bomax
@item aomax
Adjust red, green, blue and alpha output white point.
Allowed ranges for options are @code{[0, 1.0]}. Defaults are @code{1}.
Output levels allows manual selection of a constrained output level range.
@end table
@subsection Examples
@itemize
@item
Make video output darker:
@example
colorlevels=rimin=0.058:gimin=0.058:bimin=0.058
@end example
@item
Increase contrast:
@example
colorlevels=rimin=0.039:gimin=0.039:bimin=0.039:rimax=0.96:gimax=0.96:bimax=0.96
@end example
@item
Make video output lighter:
@example
colorlevels=rimax=0.902:gimax=0.902:bimax=0.902
@end example
@item
Increase brightness:
@example
colorlevels=romin=0.5:gomin=0.5:bomin=0.5
@end example
@end itemize
@section colorchannelmixer
Adjust video input frames by re-mixing color channels.
...
...
libavfilter/Makefile
View file @
5f90ef66
...
...
@@ -100,6 +100,7 @@ OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o
OBJS-$(CONFIG_CODECVIEW_FILTER)
+=
vf_codecview.o
OBJS-$(CONFIG_COLORBALANCE_FILTER)
+=
vf_colorbalance.o
OBJS-$(CONFIG_COLORCHANNELMIXER_FILTER)
+=
vf_colorchannelmixer.o
OBJS-$(CONFIG_COLORLEVELS_FILTER)
+=
vf_colorlevels.o
OBJS-$(CONFIG_COLORMATRIX_FILTER)
+=
vf_colormatrix.o
OBJS-$(CONFIG_COPY_FILTER)
+=
vf_copy.o
OBJS-$(CONFIG_CROP_FILTER)
+=
vf_crop.o
...
...
libavfilter/allfilters.c
View file @
5f90ef66
...
...
@@ -116,6 +116,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
CODECVIEW
,
codecview
,
vf
);
REGISTER_FILTER
(
COLORBALANCE
,
colorbalance
,
vf
);
REGISTER_FILTER
(
COLORCHANNELMIXER
,
colorchannelmixer
,
vf
);
REGISTER_FILTER
(
COLORLEVELS
,
colorlevels
,
vf
);
REGISTER_FILTER
(
COLORMATRIX
,
colormatrix
,
vf
);
REGISTER_FILTER
(
COPY
,
copy
,
vf
);
REGISTER_FILTER
(
CROP
,
crop
,
vf
);
...
...
libavfilter/version.h
View file @
5f90ef66
...
...
@@ -30,8 +30,8 @@
#include "libavutil/version.h"
#define LIBAVFILTER_VERSION_MAJOR 5
#define LIBAVFILTER_VERSION_MINOR
3
#define LIBAVFILTER_VERSION_MICRO 10
1
#define LIBAVFILTER_VERSION_MINOR
4
#define LIBAVFILTER_VERSION_MICRO 10
0
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \
...
...
libavfilter/vf_colorlevels.c
0 → 100644
View file @
5f90ef66
/*
* Copyright (c) 2013 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "avfilter.h"
#include "drawutils.h"
#include "formats.h"
#include "internal.h"
#include "video.h"
#define R 0
#define G 1
#define B 2
#define A 3
typedef
struct
{
double
in_min
,
in_max
;
double
out_min
,
out_max
;
}
Range
;
typedef
struct
{
const
AVClass
*
class
;
Range
range
[
4
];
int
nb_comp
;
int
bpp
;
int
step
;
uint8_t
rgba_map
[
4
];
int
linesize
;
}
ColorLevelsContext
;
#define OFFSET(x) offsetof(ColorLevelsContext, x)
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
static
const
AVOption
colorlevels_options
[]
=
{
{
"rimin"
,
"set input red black point"
,
OFFSET
(
range
[
R
].
in_min
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
0
},
-
1
,
1
,
FLAGS
},
{
"gimin"
,
"set input green black point"
,
OFFSET
(
range
[
G
].
in_min
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
0
},
-
1
,
1
,
FLAGS
},
{
"bimin"
,
"set input blue black point"
,
OFFSET
(
range
[
B
].
in_min
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
0
},
-
1
,
1
,
FLAGS
},
{
"aimin"
,
"set input alpha black point"
,
OFFSET
(
range
[
A
].
in_min
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
0
},
-
1
,
1
,
FLAGS
},
{
"rimax"
,
"set input red white point"
,
OFFSET
(
range
[
R
].
in_max
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
1
},
-
1
,
1
,
FLAGS
},
{
"gimax"
,
"set input green white point"
,
OFFSET
(
range
[
G
].
in_max
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
1
},
-
1
,
1
,
FLAGS
},
{
"bimax"
,
"set input blue white point"
,
OFFSET
(
range
[
B
].
in_max
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
1
},
-
1
,
1
,
FLAGS
},
{
"aimax"
,
"set input alpha white point"
,
OFFSET
(
range
[
A
].
in_max
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
1
},
-
1
,
1
,
FLAGS
},
{
"romin"
,
"set output red black point"
,
OFFSET
(
range
[
R
].
out_min
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
0
},
0
,
1
,
FLAGS
},
{
"gomin"
,
"set output green black point"
,
OFFSET
(
range
[
G
].
out_min
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
0
},
0
,
1
,
FLAGS
},
{
"bomin"
,
"set output blue black point"
,
OFFSET
(
range
[
B
].
out_min
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
0
},
0
,
1
,
FLAGS
},
{
"aomin"
,
"set output alpha black point"
,
OFFSET
(
range
[
A
].
out_min
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
0
},
0
,
1
,
FLAGS
},
{
"romax"
,
"set output red white point"
,
OFFSET
(
range
[
R
].
out_max
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
1
},
0
,
1
,
FLAGS
},
{
"gomax"
,
"set output green white point"
,
OFFSET
(
range
[
G
].
out_max
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
1
},
0
,
1
,
FLAGS
},
{
"bomax"
,
"set output blue white point"
,
OFFSET
(
range
[
B
].
out_max
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
1
},
0
,
1
,
FLAGS
},
{
"aomax"
,
"set output alpha white point"
,
OFFSET
(
range
[
A
].
out_max
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
1
},
0
,
1
,
FLAGS
},
{
NULL
}
};
AVFILTER_DEFINE_CLASS
(
colorlevels
);
static
int
query_formats
(
AVFilterContext
*
ctx
)
{
static
const
enum
AVPixelFormat
pix_fmts
[]
=
{
AV_PIX_FMT_0RGB
,
AV_PIX_FMT_0BGR
,
AV_PIX_FMT_ARGB
,
AV_PIX_FMT_ABGR
,
AV_PIX_FMT_RGB0
,
AV_PIX_FMT_BGR0
,
AV_PIX_FMT_RGB24
,
AV_PIX_FMT_BGR24
,
AV_PIX_FMT_RGB48
,
AV_PIX_FMT_BGR48
,
AV_PIX_FMT_RGBA64
,
AV_PIX_FMT_BGRA64
,
AV_PIX_FMT_RGBA
,
AV_PIX_FMT_BGRA
,
AV_PIX_FMT_NONE
};
ff_set_common_formats
(
ctx
,
ff_make_format_list
(
pix_fmts
));
return
0
;
}
static
int
config_input
(
AVFilterLink
*
inlink
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
ColorLevelsContext
*
s
=
ctx
->
priv
;
const
AVPixFmtDescriptor
*
desc
=
av_pix_fmt_desc_get
(
inlink
->
format
);
s
->
nb_comp
=
desc
->
nb_components
;
s
->
bpp
=
(
desc
->
comp
[
0
].
depth_minus1
+
1
)
>>
3
;
s
->
step
=
(
av_get_padded_bits_per_pixel
(
desc
)
>>
3
)
/
s
->
bpp
;
s
->
linesize
=
inlink
->
w
*
s
->
step
;
ff_fill_rgba_map
(
s
->
rgba_map
,
inlink
->
format
);
return
0
;
}
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
in
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
ColorLevelsContext
*
s
=
ctx
->
priv
;
AVFilterLink
*
outlink
=
ctx
->
outputs
[
0
];
const
int
step
=
s
->
step
;
AVFrame
*
out
;
int
x
,
y
,
i
;
if
(
av_frame_is_writable
(
in
))
{
out
=
in
;
}
else
{
out
=
ff_get_video_buffer
(
outlink
,
outlink
->
w
,
outlink
->
h
);
if
(
!
out
)
{
av_frame_free
(
&
in
);
return
AVERROR
(
ENOMEM
);
}
av_frame_copy_props
(
out
,
in
);
}
switch
(
s
->
bpp
)
{
case
1
:
for
(
i
=
0
;
i
<
s
->
nb_comp
;
i
++
)
{
Range
*
r
=
&
s
->
range
[
i
];
const
uint8_t
offset
=
s
->
rgba_map
[
i
];
const
uint8_t
*
srcrow
=
in
->
data
[
0
];
uint8_t
*
dstrow
=
out
->
data
[
0
];
int
imin
=
round
(
r
->
in_min
*
UINT8_MAX
);
int
imax
=
round
(
r
->
in_max
*
UINT8_MAX
);
int
omin
=
round
(
r
->
out_min
*
UINT8_MAX
);
int
omax
=
round
(
r
->
out_max
*
UINT8_MAX
);
double
coeff
;
if
(
imin
<
0
)
{
imin
=
UINT8_MAX
;
for
(
y
=
0
;
y
<
inlink
->
h
;
y
++
)
{
const
uint8_t
*
src
=
srcrow
;
for
(
x
=
0
;
x
<
s
->
linesize
;
x
+=
step
)
imin
=
FFMIN
(
imin
,
src
[
x
+
offset
]);
srcrow
+=
in
->
linesize
[
0
];
}
}
if
(
imax
<
0
)
{
srcrow
=
in
->
data
[
0
];
imax
=
0
;
for
(
y
=
0
;
y
<
inlink
->
h
;
y
++
)
{
const
uint8_t
*
src
=
srcrow
;
for
(
x
=
0
;
x
<
s
->
linesize
;
x
+=
step
)
imax
=
FFMAX
(
imax
,
src
[
x
+
offset
]);
srcrow
+=
in
->
linesize
[
0
];
}
}
srcrow
=
in
->
data
[
0
];
coeff
=
(
omax
-
omin
)
/
(
double
)(
imax
-
imin
);
for
(
y
=
0
;
y
<
inlink
->
h
;
y
++
)
{
const
uint8_t
*
src
=
srcrow
;
uint8_t
*
dst
=
dstrow
;
for
(
x
=
0
;
x
<
s
->
linesize
;
x
+=
step
)
dst
[
x
+
offset
]
=
av_clip_uint8
((
src
[
x
+
offset
]
-
imin
)
*
coeff
+
omin
);
dstrow
+=
out
->
linesize
[
0
];
srcrow
+=
in
->
linesize
[
0
];
}
}
break
;
case
2
:
for
(
i
=
0
;
i
<
s
->
nb_comp
;
i
++
)
{
Range
*
r
=
&
s
->
range
[
i
];
const
uint8_t
offset
=
s
->
rgba_map
[
i
];
const
uint8_t
*
srcrow
=
in
->
data
[
0
];
uint8_t
*
dstrow
=
out
->
data
[
0
];
int
imin
=
round
(
r
->
in_min
*
UINT16_MAX
);
int
imax
=
round
(
r
->
in_max
*
UINT16_MAX
);
int
omin
=
round
(
r
->
out_min
*
UINT16_MAX
);
int
omax
=
round
(
r
->
out_max
*
UINT16_MAX
);
double
coeff
;
if
(
imin
<
0
)
{
imin
=
UINT16_MAX
;
for
(
y
=
0
;
y
<
inlink
->
h
;
y
++
)
{
const
uint16_t
*
src
=
(
const
uint16_t
*
)
srcrow
;
for
(
x
=
0
;
x
<
s
->
linesize
;
x
+=
step
)
imin
=
FFMIN
(
imin
,
src
[
x
+
offset
]);
srcrow
+=
in
->
linesize
[
0
];
}
}
if
(
imax
<
0
)
{
srcrow
=
in
->
data
[
0
];
imax
=
0
;
for
(
y
=
0
;
y
<
inlink
->
h
;
y
++
)
{
const
uint16_t
*
src
=
(
const
uint16_t
*
)
srcrow
;
for
(
x
=
0
;
x
<
s
->
linesize
;
x
+=
step
)
imax
=
FFMAX
(
imax
,
src
[
x
+
offset
]);
srcrow
+=
in
->
linesize
[
0
];
}
}
srcrow
=
in
->
data
[
0
];
coeff
=
(
omax
-
omin
)
/
(
double
)(
imax
-
imin
);
for
(
y
=
0
;
y
<
inlink
->
h
;
y
++
)
{
const
uint16_t
*
src
=
(
const
uint16_t
*
)
srcrow
;
uint16_t
*
dst
=
(
uint16_t
*
)
dstrow
;
for
(
x
=
0
;
x
<
s
->
linesize
;
x
+=
step
)
dst
[
x
+
offset
]
=
av_clip_uint16
((
src
[
x
+
offset
]
-
imin
)
*
coeff
+
omin
);
dstrow
+=
out
->
linesize
[
0
];
srcrow
+=
in
->
linesize
[
0
];
}
}
}
if
(
in
!=
out
)
av_frame_free
(
&
in
);
return
ff_filter_frame
(
outlink
,
out
);
}
static
const
AVFilterPad
colorlevels_inputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
filter_frame
=
filter_frame
,
.
config_props
=
config_input
,
},
{
NULL
}
};
static
const
AVFilterPad
colorlevels_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
},
{
NULL
}
};
AVFilter
ff_vf_colorlevels
=
{
.
name
=
"colorlevels"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Adjust the color levels."
),
.
priv_size
=
sizeof
(
ColorLevelsContext
),
.
priv_class
=
&
colorlevels_class
,
.
query_formats
=
query_formats
,
.
inputs
=
colorlevels_inputs
,
.
outputs
=
colorlevels_outputs
,
.
flags
=
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
,
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment