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
e8497a33
Commit
e8497a33
authored
Mar 28, 2012
by
Nicolas George
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drawutils: implement uniform and mask blending.
parent
e3e89b6d
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
267 additions
and
0 deletions
+267
-0
drawutils.c
libavfilter/drawutils.c
+234
-0
drawutils.h
libavfilter/drawutils.h
+33
-0
No files found.
libavfilter/drawutils.c
View file @
e8497a33
...
@@ -132,6 +132,8 @@ int ff_draw_init(FFDrawContext *draw, enum PixelFormat format, unsigned flags)
...
@@ -132,6 +132,8 @@ int ff_draw_init(FFDrawContext *draw, enum PixelFormat format, unsigned flags)
unsigned
i
,
nb_planes
=
0
;
unsigned
i
,
nb_planes
=
0
;
int
pixelstep
[
MAX_PLANES
]
=
{
0
};
int
pixelstep
[
MAX_PLANES
]
=
{
0
};
if
(
!
desc
->
name
)
return
AVERROR
(
EINVAL
);
if
(
desc
->
flags
&
~
(
PIX_FMT_PLANAR
|
PIX_FMT_RGB
))
if
(
desc
->
flags
&
~
(
PIX_FMT_PLANAR
|
PIX_FMT_RGB
))
return
AVERROR
(
ENOSYS
);
return
AVERROR
(
ENOSYS
);
for
(
i
=
0
;
i
<
desc
->
nb_components
;
i
++
)
{
for
(
i
=
0
;
i
<
desc
->
nb_components
;
i
++
)
{
...
@@ -146,6 +148,8 @@ int ff_draw_init(FFDrawContext *draw, enum PixelFormat format, unsigned flags)
...
@@ -146,6 +148,8 @@ int ff_draw_init(FFDrawContext *draw, enum PixelFormat format, unsigned flags)
pixelstep
[
c
->
plane
]
!=
c
->
step_minus1
+
1
)
pixelstep
[
c
->
plane
]
!=
c
->
step_minus1
+
1
)
return
AVERROR
(
ENOSYS
);
return
AVERROR
(
ENOSYS
);
pixelstep
[
c
->
plane
]
=
c
->
step_minus1
+
1
;
pixelstep
[
c
->
plane
]
=
c
->
step_minus1
+
1
;
if
(
pixelstep
[
c
->
plane
]
>=
8
)
return
AVERROR
(
ENOSYS
);
nb_planes
=
FFMAX
(
nb_planes
,
c
->
plane
+
1
);
nb_planes
=
FFMAX
(
nb_planes
,
c
->
plane
+
1
);
}
}
if
((
desc
->
log2_chroma_w
||
desc
->
log2_chroma_h
)
&&
nb_planes
<
3
)
if
((
desc
->
log2_chroma_w
||
desc
->
log2_chroma_h
)
&&
nb_planes
<
3
)
...
@@ -159,6 +163,9 @@ int ff_draw_init(FFDrawContext *draw, enum PixelFormat format, unsigned flags)
...
@@ -159,6 +163,9 @@ int ff_draw_init(FFDrawContext *draw, enum PixelFormat format, unsigned flags)
draw
->
hsub
[
1
]
=
draw
->
hsub
[
2
]
=
draw
->
hsub_max
=
desc
->
log2_chroma_w
;
draw
->
hsub
[
1
]
=
draw
->
hsub
[
2
]
=
draw
->
hsub_max
=
desc
->
log2_chroma_w
;
draw
->
vsub
[
1
]
=
draw
->
vsub
[
2
]
=
draw
->
vsub_max
=
desc
->
log2_chroma_h
;
draw
->
vsub
[
1
]
=
draw
->
vsub
[
2
]
=
draw
->
vsub_max
=
desc
->
log2_chroma_h
;
}
}
for
(
i
=
0
;
i
<
((
desc
->
nb_components
-
1
)
|
1
);
i
++
)
draw
->
comp_mask
[
desc
->
comp
[
i
].
plane
]
|=
1
<<
(
desc
->
comp
[
i
].
offset_plus1
-
1
);
return
0
;
return
0
;
}
}
...
@@ -167,6 +174,8 @@ void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, uint8_t rgba[4])
...
@@ -167,6 +174,8 @@ void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, uint8_t rgba[4])
unsigned
i
;
unsigned
i
;
uint8_t
rgba_map
[
4
];
uint8_t
rgba_map
[
4
];
if
(
rgba
!=
color
->
rgba
)
memcpy
(
color
->
rgba
,
rgba
,
sizeof
(
color
->
rgba
));
if
((
draw
->
desc
->
flags
&
PIX_FMT_RGB
)
&&
draw
->
nb_planes
==
1
&&
if
((
draw
->
desc
->
flags
&
PIX_FMT_RGB
)
&&
draw
->
nb_planes
==
1
&&
ff_fill_rgba_map
(
rgba_map
,
draw
->
format
)
>=
0
)
{
ff_fill_rgba_map
(
rgba_map
,
draw
->
format
)
>=
0
)
{
for
(
i
=
0
;
i
<
4
;
i
++
)
for
(
i
=
0
;
i
<
4
;
i
++
)
...
@@ -246,6 +255,231 @@ void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color,
...
@@ -246,6 +255,231 @@ void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color,
}
}
}
}
/**
* Clip interval [x; x+w[ within [0; wmax[.
* The resulting w may be negative if the final interval is empty.
* dx, if not null, return the difference between in and out value of x.
*/
static
void
clip_interval
(
int
wmax
,
int
*
x
,
int
*
w
,
int
*
dx
)
{
if
(
dx
)
*
dx
=
0
;
if
(
*
x
<
0
)
{
if
(
dx
)
*
dx
=
-*
x
;
*
w
+=
*
x
;
*
x
=
0
;
}
if
(
*
x
+
*
w
>
wmax
)
*
w
=
wmax
-
*
x
;
}
/**
* Decompose w pixels starting at x
* into start + (w starting at x) + end
* with x and w aligned on multiples of 1<<sub.
*/
static
void
subsampling_bounds
(
int
sub
,
int
*
x
,
int
*
w
,
int
*
start
,
int
*
end
)
{
int
mask
=
(
1
<<
sub
)
-
1
;
*
start
=
(
-*
x
)
&
mask
;
*
x
+=
*
start
;
*
start
=
FFMIN
(
*
start
,
*
w
);
*
w
-=
*
start
;
*
end
=
*
w
&
mask
;
*
w
>>=
sub
;
}
static
int
component_used
(
FFDrawContext
*
draw
,
int
plane
,
int
comp
)
{
return
(
draw
->
comp_mask
[
plane
]
>>
comp
)
&
1
;
}
/* If alpha is in the [ 0 ; 0x1010101 ] range,
then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range,
and >> 24 gives a correct rounding. */
static
void
blend_line
(
uint8_t
*
dst
,
unsigned
src
,
unsigned
alpha
,
int
dx
,
int
w
,
unsigned
hsub
,
int
left
,
int
right
)
{
unsigned
asrc
=
alpha
*
src
;
unsigned
tau
=
0x1010101
-
alpha
;
int
x
;
src
*=
alpha
;
if
(
left
)
{
unsigned
suba
=
(
left
*
alpha
)
>>
hsub
;
*
dst
=
(
*
dst
*
(
0x1010101
-
suba
)
+
src
*
suba
)
>>
24
;
dst
+=
dx
;
}
for
(
x
=
0
;
x
<
w
;
x
++
)
{
*
dst
=
(
*
dst
*
tau
+
asrc
)
>>
24
;
dst
+=
dx
;
}
if
(
right
)
{
unsigned
suba
=
(
right
*
alpha
)
>>
hsub
;
*
dst
=
(
*
dst
*
(
0x1010101
-
suba
)
+
src
*
suba
)
>>
24
;
}
}
void
ff_blend_rectangle
(
FFDrawContext
*
draw
,
FFDrawColor
*
color
,
uint8_t
*
dst
[],
int
dst_linesize
[],
int
dst_w
,
int
dst_h
,
int
x0
,
int
y0
,
int
w
,
int
h
)
{
unsigned
alpha
,
nb_planes
,
nb_comp
,
plane
,
comp
;
int
w_sub
,
h_sub
,
x_sub
,
y_sub
,
left
,
right
,
top
,
bottom
,
y
;
uint8_t
*
p0
,
*
p
;
/* TODO optimize if alpha = 0xFF */
clip_interval
(
dst_w
,
&
x0
,
&
w
,
NULL
);
clip_interval
(
dst_h
,
&
y0
,
&
h
,
NULL
);
if
(
w
<=
0
||
h
<=
0
||
!
color
->
rgba
[
3
])
return
;
/* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */
alpha
=
0x10203
*
color
->
rgba
[
3
]
+
0x2
;
nb_planes
=
(
draw
->
nb_planes
-
1
)
|
1
;
/* eliminate alpha */
for
(
plane
=
0
;
plane
<
nb_planes
;
plane
++
)
{
nb_comp
=
draw
->
pixelstep
[
plane
];
p0
=
pointer_at
(
draw
,
dst
,
dst_linesize
,
plane
,
x0
,
y0
);
w_sub
=
w
;
h_sub
=
h
;
x_sub
=
x0
;
y_sub
=
y0
;
subsampling_bounds
(
draw
->
hsub
[
plane
],
&
x_sub
,
&
w_sub
,
&
left
,
&
right
);
subsampling_bounds
(
draw
->
vsub
[
plane
],
&
y_sub
,
&
h_sub
,
&
top
,
&
bottom
);
for
(
comp
=
0
;
comp
<
nb_comp
;
comp
++
)
{
if
(
!
component_used
(
draw
,
plane
,
comp
))
continue
;
p
=
p0
+
comp
;
if
(
top
)
{
blend_line
(
p
,
color
->
comp
[
plane
].
u8
[
comp
],
alpha
>>
1
,
draw
->
pixelstep
[
plane
],
w_sub
,
draw
->
hsub
[
plane
],
left
,
right
);
p
+=
dst_linesize
[
plane
];
}
for
(
y
=
0
;
y
<
h_sub
;
y
++
)
{
blend_line
(
p
,
color
->
comp
[
plane
].
u8
[
comp
],
alpha
,
draw
->
pixelstep
[
plane
],
w_sub
,
draw
->
hsub
[
plane
],
left
,
right
);
p
+=
dst_linesize
[
plane
];
}
if
(
bottom
)
blend_line
(
p
,
color
->
comp
[
plane
].
u8
[
comp
],
alpha
>>
1
,
draw
->
pixelstep
[
plane
],
w_sub
,
draw
->
hsub
[
plane
],
left
,
right
);
}
}
}
static
void
blend_pixel
(
uint8_t
*
dst
,
unsigned
src
,
unsigned
alpha
,
uint8_t
*
mask
,
int
mask_linesize
,
int
l2depth
,
unsigned
w
,
unsigned
h
,
unsigned
shift
,
unsigned
xm0
)
{
unsigned
xm
,
x
,
y
,
t
=
0
;
unsigned
xmshf
=
3
-
l2depth
;
unsigned
xmmod
=
7
>>
l2depth
;
unsigned
mbits
=
(
1
<<
(
1
<<
l2depth
))
-
1
;
unsigned
mmult
=
255
/
mbits
;
for
(
y
=
0
;
y
<
h
;
y
++
)
{
xm
=
xm0
;
for
(
x
=
0
;
x
<
w
;
x
++
)
{
t
+=
((
mask
[
xm
>>
xmshf
]
>>
((
~
xm
&
xmmod
)
<<
l2depth
))
&
mbits
)
*
mmult
;
xm
++
;
}
mask
+=
mask_linesize
;
}
alpha
=
(
t
>>
shift
)
*
alpha
;
*
dst
=
((
0x1010101
-
alpha
)
*
*
dst
+
alpha
*
src
)
>>
24
;
}
static
void
blend_line_hv
(
uint8_t
*
dst
,
int
dst_delta
,
unsigned
src
,
unsigned
alpha
,
uint8_t
*
mask
,
int
mask_linesize
,
int
l2depth
,
int
w
,
unsigned
hsub
,
unsigned
vsub
,
int
xm
,
int
left
,
int
right
,
int
hband
)
{
int
x
;
if
(
left
)
{
blend_pixel
(
dst
,
src
,
alpha
,
mask
,
mask_linesize
,
l2depth
,
left
,
hband
,
hsub
+
vsub
,
xm
);
dst
+=
dst_delta
;
xm
+=
left
;
}
for
(
x
=
0
;
x
<
w
;
x
++
)
{
blend_pixel
(
dst
,
src
,
alpha
,
mask
,
mask_linesize
,
l2depth
,
1
<<
hsub
,
hband
,
hsub
+
vsub
,
xm
);
dst
+=
dst_delta
;
xm
+=
1
<<
hsub
;
}
if
(
right
)
blend_pixel
(
dst
,
src
,
alpha
,
mask
,
mask_linesize
,
l2depth
,
right
,
hband
,
hsub
+
vsub
,
xm
);
}
void
ff_blend_mask
(
FFDrawContext
*
draw
,
FFDrawColor
*
color
,
uint8_t
*
dst
[],
int
dst_linesize
[],
int
dst_w
,
int
dst_h
,
uint8_t
*
mask
,
int
mask_linesize
,
int
mask_w
,
int
mask_h
,
int
l2depth
,
unsigned
endianness
,
int
x0
,
int
y0
)
{
unsigned
alpha
,
nb_planes
,
nb_comp
,
plane
,
comp
;
int
xm0
,
ym0
,
w_sub
,
h_sub
,
x_sub
,
y_sub
,
left
,
right
,
top
,
bottom
,
y
;
uint8_t
*
p0
,
*
p
,
*
m
;
clip_interval
(
dst_w
,
&
x0
,
&
mask_w
,
&
xm0
);
clip_interval
(
dst_h
,
&
y0
,
&
mask_h
,
&
ym0
);
mask
+=
ym0
*
mask_linesize
;
if
(
mask_w
<=
0
||
mask_h
<=
0
||
!
color
->
rgba
[
3
])
return
;
/* alpha is in the [ 0 ; 0x10203 ] range,
alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */
alpha
=
(
0x10307
*
color
->
rgba
[
3
]
+
0x3
)
>>
8
;
nb_planes
=
(
draw
->
nb_planes
-
1
)
|
1
;
/* eliminate alpha */
for
(
plane
=
0
;
plane
<
nb_planes
;
plane
++
)
{
nb_comp
=
draw
->
pixelstep
[
plane
];
p0
=
pointer_at
(
draw
,
dst
,
dst_linesize
,
plane
,
x0
,
y0
);
w_sub
=
mask_w
;
h_sub
=
mask_h
;
x_sub
=
x0
;
y_sub
=
y0
;
subsampling_bounds
(
draw
->
hsub
[
plane
],
&
x_sub
,
&
w_sub
,
&
left
,
&
right
);
subsampling_bounds
(
draw
->
vsub
[
plane
],
&
y_sub
,
&
h_sub
,
&
top
,
&
bottom
);
for
(
comp
=
0
;
comp
<
nb_comp
;
comp
++
)
{
if
(
!
component_used
(
draw
,
plane
,
comp
))
continue
;
p
=
p0
+
comp
;
m
=
mask
;
if
(
top
)
{
blend_line_hv
(
p
,
draw
->
pixelstep
[
plane
],
color
->
comp
[
plane
].
u8
[
comp
],
alpha
,
m
,
mask_linesize
,
l2depth
,
w_sub
,
draw
->
hsub
[
plane
],
draw
->
vsub
[
plane
],
xm0
,
left
,
right
,
top
);
p
+=
dst_linesize
[
plane
];
m
+=
top
*
mask_linesize
;
}
for
(
y
=
0
;
y
<
h_sub
;
y
++
)
{
blend_line_hv
(
p
,
draw
->
pixelstep
[
plane
],
color
->
comp
[
plane
].
u8
[
comp
],
alpha
,
m
,
mask_linesize
,
l2depth
,
w_sub
,
draw
->
hsub
[
plane
],
draw
->
vsub
[
plane
],
xm0
,
left
,
right
,
1
<<
draw
->
vsub
[
plane
]);
p
+=
dst_linesize
[
plane
];
m
+=
mask_linesize
<<
draw
->
vsub
[
plane
];
}
if
(
bottom
)
blend_line_hv
(
p
,
draw
->
pixelstep
[
plane
],
color
->
comp
[
plane
].
u8
[
comp
],
alpha
,
m
,
mask_linesize
,
l2depth
,
w_sub
,
draw
->
hsub
[
plane
],
draw
->
vsub
[
plane
],
xm0
,
left
,
right
,
bottom
);
}
}
}
int
ff_draw_round_to_sub
(
FFDrawContext
*
draw
,
int
sub_dir
,
int
round_dir
,
int
ff_draw_round_to_sub
(
FFDrawContext
*
draw
,
int
sub_dir
,
int
round_dir
,
int
value
)
int
value
)
{
{
...
...
libavfilter/drawutils.h
View file @
e8497a33
...
@@ -50,6 +50,7 @@ typedef struct FFDrawContext {
...
@@ -50,6 +50,7 @@ typedef struct FFDrawContext {
enum
PixelFormat
format
;
enum
PixelFormat
format
;
unsigned
nb_planes
;
unsigned
nb_planes
;
int
pixelstep
[
MAX_PLANES
];
/*< offset between pixels */
int
pixelstep
[
MAX_PLANES
];
/*< offset between pixels */
uint8_t
comp_mask
[
MAX_PLANES
];
/*< bitmask of used non-alpha components */
uint8_t
hsub
[
MAX_PLANES
];
/*< horizontal subsamling */
uint8_t
hsub
[
MAX_PLANES
];
/*< horizontal subsamling */
uint8_t
vsub
[
MAX_PLANES
];
/*< vertical subsamling */
uint8_t
vsub
[
MAX_PLANES
];
/*< vertical subsamling */
uint8_t
hsub_max
;
uint8_t
hsub_max
;
...
@@ -57,6 +58,7 @@ typedef struct FFDrawContext {
...
@@ -57,6 +58,7 @@ typedef struct FFDrawContext {
}
FFDrawContext
;
}
FFDrawContext
;
typedef
struct
FFDrawColor
{
typedef
struct
FFDrawColor
{
uint8_t
rgba
[
4
];
union
{
union
{
uint32_t
u32
;
uint32_t
u32
;
uint16_t
u16
;
uint16_t
u16
;
...
@@ -100,6 +102,37 @@ void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color,
...
@@ -100,6 +102,37 @@ void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color,
uint8_t
*
dst
[],
int
dst_linesize
[],
uint8_t
*
dst
[],
int
dst_linesize
[],
int
dst_x
,
int
dst_y
,
int
w
,
int
h
);
int
dst_x
,
int
dst_y
,
int
w
,
int
h
);
/**
* Blend a rectangle with an uniform color.
*/
void
ff_blend_rectangle
(
FFDrawContext
*
draw
,
FFDrawColor
*
color
,
uint8_t
*
dst
[],
int
dst_linesize
[],
int
dst_w
,
int
dst_h
,
int
x0
,
int
y0
,
int
w
,
int
h
);
/**
* Blend an alpha mask with an uniform color.
*
* @param draw draw context
* @param color color for the overlay;
* @param dst destination image
* @param dst_linesize line stride of the destination
* @param dst_w width of the destination image
* @param dst_h height of the destination image
* @param mask mask
* @param mask_linesize line stride of the mask
* @param mask_w width of the mask
* @param mask_h height of the mask
* @param l2depth log2 of depth of the mask (0 for 1bpp, 3 for 8bpp)
* @param endianness bit order of the mask (0: MSB to the left)
* @param x0 horizontal position of the overlay
* @param y0 vertical position of the overlay
*/
void
ff_blend_mask
(
FFDrawContext
*
draw
,
FFDrawColor
*
color
,
uint8_t
*
dst
[],
int
dst_linesize
[],
int
dst_w
,
int
dst_h
,
uint8_t
*
mask
,
int
mask_linesize
,
int
mask_w
,
int
mask_h
,
int
l2depth
,
unsigned
endianness
,
int
x0
,
int
y0
);
/**
/**
* Round a dimension according to subsampling.
* Round a dimension according to subsampling.
*
*
...
...
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