fix Waveform contrast issues (cf989d84) · Commits · Multimedia / Kdenlive · GitLab
Admin message
Join us at
Akademy
to celebrate KDE's 30th anniversary!
Travel support requests
are open till May 31st.
Register now
Commit
cf989d84
authored
Jul 11, 2025
by
balooii balooii
Browse files
parent
c93d7041
Loading
Loading
Loading
Loading
Changes
Pipelines
Loading
Original line number
Diff line number
Diff line
@@ -110,10 +110,9 @@ QImage RGBParade::renderHUD(uint)
QFontMetrics
fm
davinci
fontMetrics
();
const
int
HUD_SCALE_MARGIN
const
int
hudScaleOffset
offset
HUD_SCALE_MARGIN
const
int
hudScaleOffsetTop
offset
int
scopeRect
().
width
()
hudScaleO
ffset
fm
horizontalAdvance
QStringLiteral
"255"
));
int
scopeRect
().
width
()
ffset
fm
horizontalAdvance
QStringLiteral
"255"
));
int
m_mousePos
()
scopeRect
().
();
bool
mouseWithinScope
m_mouseWithinWidget
&&
>=
RGBParadeGenerator
::
distBorder
&&
<=
scopeRect
().
height
()
RGBParadeGenerator
::
distBottom
RGBParadeGenerator
::
distBorder
);
@@ -126,7 +125,7 @@ QImage RGBParade::renderHUD(uint)
const
int
textMargin
// Scale baseline positions
const
int
scaleTopY
RGBParadeGenerator
::
distBorder
hudScaleOffset
// "255" position
const
int
scaleTopY
RGBParadeGenerator
::
distBorder
hudScaleOffset
Top
// "255" position
const
int
scaleBottomY
scopeRect
().
height
()
RGBParadeGenerator
::
distBottom
RGBParadeGenerator
::
distBorder
// "0" position
// Calculate the natural position for the current value text (centered on horizontal line)
@@ -167,7 +166,7 @@ QImage RGBParade::renderHUD(uint)
// When mouse is not within scope, always show scale values
davinci
setPen
palette
().
text
().
color
());
davinci
drawText
scopeRect
().
height
()
RGBParadeGenerator
::
distBottom
RGBParadeGenerator
::
distBorder
QStringLiteral
"0"
));
davinci
drawText
RGBParadeGenerator
::
distBorder
10
QStringLiteral
"255"
));
davinci
drawText
RGBParadeGenerator
::
distBorder
hudScaleOffsetTop
QStringLiteral
"255"
));
Q_EMIT
signalHUDRenderingFinished
);
Original line number
Diff line number
Diff line
@@ -14,7 +14,7 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#define CHOP255(a) ((255) < (a) ? (255) : int(a))
#define CHOP1255(a) ((a) < (1) ? (1) : ((a) > (255) ? (255) : (a)))
const
uchar
RGBParadeGenerator
::
distRight
40
);
const
uchar
RGBParadeGenerator
::
distRight
31
);
const
uchar
RGBParadeGenerator
::
distBottom
40
);
const
uchar
RGBParadeGenerator
::
distBorder
);
Original line number
Diff line number
Diff line
@@ -19,7 +19,6 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include
#include
const
QSize
Waveform
::
m_textWidth
35
);
const
int
Waveform
::
m_paddingBottom
20
);
Waveform
::
Waveform
QWidget
parent
@@ -28,6 +27,9 @@ Waveform::Waveform(QWidget *parent)
// overwrite custom scopes palette from AbstractScopeWidget with global app palette to respect users theme preference
setPalette
QPalette
());
QFontMetrics
fm
QFontMetrics
font
());
m_textWidth
fm
horizontalAdvance
QStringLiteral
"255"
));
m_ui
new
Ui
::
Waveform_UI
();
m_ui
->
setupUi
this
);
@@ -89,11 +91,8 @@ void Waveform::writeConfig()
QRect
Waveform
::
scopeRect
()
// Distance from top/left/right
int
border
QPoint
topleft
border
m_ui
->
verticalSpacer
->
geometry
().
()
border
);
return
QRect
topleft
this
->
size
()
QSize
border
topleft
(),
border
topleft
()));
QPoint
topleft
offset
m_ui
->
verticalSpacer
->
geometry
().
()
offset
);
return
QRect
topleft
QPoint
this
->
size
().
width
()
offset
this
->
size
().
height
()
offset
));
///// Implemented methods /////
@@ -128,56 +127,95 @@ QImage Waveform::renderHUD(uint)
qDebug
()
<<
"Could not initialise QPainter for Waveform HUD."
return
hud
davinci
setPen
palette
().
text
().
color
());
// qCDebug(KDENLIVE_LOG) << values.value("width");
if
scopeRect
().
height
()
<=
return
hud
QFontMetrics
fm
davinci
fontMetrics
();
const
int
hudScaleOffsetTop
offset
const
int
rightX
scopeRect
().
width
()
m_textWidth
width
()
const
int
rightX
scopeRect
().
width
()
offset
m_textWidth
const
int
m_mousePos
()
scopeRect
().
();
const
int
m_mousePos
()
scopeRect
().
();
if
scopeRect
().
height
()
&&
m_
mouseWithin
Widget
int
val
255
255
scopeRect
().
height
);
bool
mouseWithin
Scope
m_mouseWithinWidget
&&
>=
WaveformGenerator
::
distBorder
&&
<=
scopeRect
().
height
()
m_paddingBottom
WaveformGenerator
::
distBorder
);
if
val
>=
&&
val
<=
255
// Draw a horizontal line through the current mouse position
// and show the value of the waveform there
davinci
drawLine
scopeRect
().
size
().
width
()
m_textWidth
width
(),
);
if
mouseWithinScope
int
val
255
int
255.
scopeRect
().
height
()
m_paddingBottom
WaveformGenerator
::
distBorder
));
// Make the value stick to the line unless it is at the top/bottom of the scope
int
valY
const
int
top
30
const
int
bottom
20
if
valY
top
valY
top
else
if
valY
scopeRect
().
height
()
bottom
valY
scopeRect
().
height
()
bottom
if
val
>=
&&
val
<=
255
const
int
textHeight
fm
height
();
const
int
textMargin
// Scale baseline positions
const
int
scaleTopY
WaveformGenerator
::
distBorder
hudScaleOffsetTop
// "255" position
const
int
scaleBottomY
scopeRect
().
height
()
m_paddingBottom
WaveformGenerator
::
distBorder
// "0" position
// Calculate the natural position for the current value text (centered on horizontal line)
// drawText uses baseline positioning, so we need to adjust for centering
int
naturalValY
fm
ascent
()
textHeight
// Check if current value text would clip with scale values or widget edges
// For top scale: check if current value overlaps with the "255" text area
bool
clipsWithTop
naturalValY
textHeight
scaleTopY
fm
descent
()
textMargin
);
// For bottom scale: check if current value overlaps with the "0" text area
bool
clipsWithBottom
naturalValY
textHeight
scaleBottomY
fm
ascent
()
textMargin
);
bool
clipsWithWidgetTop
naturalValY
textHeight
textMargin
bool
clipsWithWidgetBottom
naturalValY
textHeight
scopeRect
().
height
()
textMargin
);
// Calculate final text position with edge clipping adjustments
int
finalValY
naturalValY
if
clipsWithWidgetTop
finalValY
textMargin
textHeight
else
if
clipsWithWidgetBottom
finalValY
scopeRect
().
height
()
textMargin
textHeight
// Draw scale values, only hide the ones that would clip
davinci
setPen
palette
().
text
().
color
());
if
clipsWithTop
davinci
drawText
rightX
scaleTopY
QStringLiteral
"255"
));
davinci
drawText
rightX
valY
QVariant
val
).
toString
());
if
clipsWithBottom
davinci
drawText
rightX
scaleBottomY
QStringLiteral
"0"
));
// Always draw the current value and the horizontal line
davinci
setPen
palette
().
highlight
().
color
());
davinci
drawText
rightX
finalValY
QVariant
val
).
toString
());
davinci
drawLine
WaveformGenerator
::
distBorder
scopeRect
().
size
().
width
()
m_textWidth
offset
WaveformGenerator
::
distBorder
);
if
scopeRect
().
width
()
// Draw a vertical line and the x position of the source clip
const
int
profileWidth
pCore
->
getCurrentProfile
()
->
width
();
const
int
clipX
profileWidth
))
scopeRect
().
width
()
m_textWidth
width
()
);
const
int
drawingAreaWidth
scopeRect
().
width
()
offset
m_textWidth
WaveformGenerator
::
distBorder
const
int
clipX
((
WaveformGenerator
::
distBorder
profileWidth
))
drawingAreaWidth
);
if
clipX
>=
&&
clipX
<=
profileWidth
int
valX
15
if
valX
valX
if
valX
scopeRect
().
width
()
55
m_textWidth
width
()
valX
scopeRect
().
width
()
55
m_textWidth
width
()
if
valX
drawingAreaWidth
valX
drawingAreaWidth
davinci
drawLine
scopeRect
().
height
()
m_paddingBottom
);
davinci
drawText
valX
scopeRect
().
height
()
QVariant
clipX
).
toString
()
QStringLiteral
" px"
));
davinci
drawText
valX
scopeRect
().
height
()
offset
QVariant
clipX
).
toString
()
QStringLiteral
" px"
));
else
// When mouse is not within scope, always show scale values
davinci
setPen
palette
().
text
().
color
());
davinci
drawText
rightX
scopeRect
().
height
()
m_paddingBottom
WaveformGenerator
::
distBorder
QStringLiteral
"0"
));
davinci
drawText
rightX
WaveformGenerator
::
distBorder
hudScaleOffsetTop
QStringLiteral
"255"
));
davinci
drawText
rightX
scopeRect
().
height
()
m_paddingBottom
QStringLiteral
"0"
));
davinci
drawText
rightX
10
QStringLiteral
"255"
));
Q_EMIT
signalHUDRenderingFinished
);
return
hud
@@ -191,8 +229,8 @@ QImage Waveform::renderGfxScope(uint accelFactor, const QImage &qimage)
const
int
paintmode
m_ui
->
paintMode
->
itemData
m_ui
->
paintMode
->
currentIndex
()).
toInt
();
ITURec
rec
m_aRec601
->
isChecked
()
ITURec
::
Rec_601
ITURec
::
Rec_709
qreal
scalingFactor
devicePixelRatioF
();
QImage
wave
m_waveformGenerator
->
calculateWaveform
((
scopeRect
().
size
()
m_textWidth
QSize
m_paddingBottom
)),
scalingFactor
qimage
WaveformGenerator
::
PaintMode
paintmode
),
true
rec
accelFactor
palette
()
);
QImage
wave
m_waveformGenerator
->
calculateWaveform
((
scopeRect
().
size
()
QSize
m_textWidth
offset
QSize
m_paddingBottom
)),
scalingFactor
qimage
WaveformGenerator
::
PaintMode
paintmode
),
true
rec
accelFactor
);
Q_EMIT
signalScopeRenderingFinished
uint
timer
elapsed
()),
);
return
wave
Original line number
Diff line number
Diff line
@@ -41,7 +41,7 @@ private:
QAction
m_aRec709
QActionGroup
m_agRec
static
const
QSize
m_textWidth
int
m_textWidth
static
const
int
m_paddingBottom
QImage
m_waveform
Original line number
Diff line number
Diff line
@@ -19,12 +19,14 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#define CHOP255(a) int((255) < (a) ? (255) : (a))
const
uchar
WaveformGenerator
::
distBorder
);
WaveformGenerator
::
WaveformGenerator
()
default
WaveformGenerator
::~
WaveformGenerator
()
default
QImage
WaveformGenerator
::
calculateWaveform
const
QSize
waveformSize
qreal
scalingFactor
const
QImage
image
const
WaveformGenerator
::
PaintMode
paintMode
bool
drawAxis
ITURec
rec
uint
accelFactor
const
QPalette
palette
bool
drawAxis
ITURec
rec
uint
accelFactor
Q_ASSERT
accelFactor
>=
);
@@ -39,24 +41,35 @@ QImage WaveformGenerator::calculateWaveform(const QSize &waveformSize, qreal sca
return
QImage
();
wave
fill
palette
base
().
color
());
QPainter
davinci
bool
ok
davinci
begin
wave
);
if
ok
qDebug
()
<<
"Could not initialise QPainter for Waveform."
return
wave
const
uint
ww
uint
scaledWaveformSize
width
());
const
uint
wh
uint
scaledWaveformSize
height
());
const
uint
iw
uint
image
width
());
const
auto
totalPixels
image
width
()
image
height
();
std
::
vector
std
::
vector
uint
>>
waveValues
size_t
scaledWaveformSize
width
()),
std
::
vector
uint
size_t
scaledWaveformSize
height
()),
));
// Calculate the actual scope area dimensions (excluding borders)
const
uint
scopeW
ww
distBorder
scalingFactor
);
const
uint
scopeH
wh
distBorder
scalingFactor
);
const
uint
scopeWLogicalPixels
waveformSize
width
()
distBorder
const
uint
scopeHLogicalPixels
waveformSize
height
()
distBorder
std
::
vector
std
::
vector
uint
>>
waveValues
size_t
scopeW
),
std
::
vector
uint
size_t
scopeH
),
));
// Number of input pixels that will fall on one scope pixel.
// Must be a float because the acceleration factor can be high, leading to <1 expected px per px.
const
float
pixelDepth
float
totalPixels
accelFactor
ww
wh
);
const
float
pixelDepth
float
totalPixels
accelFactor
scopeW
scopeH
);
const
float
gain
255.f
pixelDepth
);
// Subtract 1 from sizes because we start counting from 0.
// Not doing it would result in attempts to paint outside of the image.
const
float
hPrediv
wh
255.f
const
float
wPrediv
ww
float
iw
);
const
float
hPrediv
scopeH
255.f
const
float
wPrediv
scopeW
float
iw
);
for
int
totalPixels
+=
accelFactor
const
int
image
width
();
@@ -80,12 +93,21 @@ QImage WaveformGenerator::calculateWaveform(const QSize &waveformSize, qreal sca
// Fill background of the parade with "dark2" color from AbstractScopeWidget instead of themes base color as the different paint modes are optimized
// for a dark background.
QRgb
darkBackground
qRgb
25
25
23
);
QColor
darkBackground
25
25
23
255
);
// Fill color for the border around the scope
QColor
waveformBorderColor
darkBackground
lighter
120
);
// Fill the entire area with border color first
wave
fill
waveformBorderColor
);
// Fill the actual scope area with dark background
davinci
fillRect
QRect
distBorder
distBorder
scopeWLogicalPixels
scopeHLogicalPixels
),
darkBackground
);
QRgb
darkBackgroundRgb
darkBackground
rgb
();
switch
paintMode
case
PaintMode_Green
for
int
scaledWaveformSize
width
);
++
for
int
scaledWaveformSize
height
);
++
for
int
int
scopeW
);
++
for
int
int
scopeH
);
++
// Logarithmic scale. Needs fine tuning by hand, but looks great.
float
value
gain
float
waveValues
size_t
)][
size_t
)]);
float
logValue
value
0.0f
logf
value
0.0f
@@ -100,59 +122,49 @@ QImage WaveformGenerator::calculateWaveform(const QSize &waveformSize, qreal sca
int
alpha
CHOP255
64
logValue
);
int
inv_alpha
255
alpha
wave
setPixel
scaledWaveformSize
height
qRgba
CHOP255
((
qRed
darkBackground
inv_alpha
52
logR
alpha
255
),
CHOP255
((
qGreen
darkBackground
inv_alpha
52
logG
alpha
255
),
CHOP255
((
qBlue
darkBackground
inv_alpha
52
logB
alpha
255
),
255
));
wave
setPixel
distBorder
int
scopeH
distBorder
qRgba
CHOP255
((
qRed
darkBackground
Rgb
inv_alpha
52
logR
alpha
255
),
CHOP255
((
qGreen
darkBackground
Rgb
inv_alpha
52
logG
alpha
255
),
CHOP255
((
qBlue
darkBackground
Rgb
inv_alpha
52
logB
alpha
255
),
255
));
break
case
PaintMode_Yellow
for
int
scaledWaveformSize
width
);
++
for
int
scaledWaveformSize
height
);
++
for
int
int
scopeW
);
++
for
int
int
scopeH
);
++
int
alpha
CHOP255
gain
float
waveValues
size_t
)][
size_t
)]));
int
inv_alpha
255
alpha
wave
setPixel
scaledWaveformSize
height
qRgba
CHOP255
((
qRed
darkBackground
inv_alpha
255
alpha
255
),
CHOP255
((
qGreen
darkBackground
inv_alpha
242
alpha
255
),
CHOP255
((
qBlue
darkBackground
inv_alpha
alpha
255
),
255
));
wave
setPixel
distBorder
int
scopeH
distBorder
qRgba
CHOP255
((
qRed
darkBackground
Rgb
inv_alpha
255
alpha
255
),
CHOP255
((
qGreen
darkBackground
Rgb
inv_alpha
242
alpha
255
),
CHOP255
((
qBlue
darkBackground
Rgb
inv_alpha
alpha
255
),
255
));
break
default
// White mode
for
int
scaledWaveformSize
width
);
++
for
int
scaledWaveformSize
height
);
++
for
int
int
scopeW
);
++
for
int
int
scopeH
);
++
int
alpha
CHOP255
2.f
gain
float
waveValues
size_t
)][
size_t
)]));
int
inv_alpha
255
alpha
wave
setPixel
scaledWaveformSize
height
qRgba
CHOP255
((
qRed
darkBackground
inv_alpha
255
alpha
255
),
CHOP255
((
qGreen
darkBackground
inv_alpha
255
alpha
255
),
CHOP255
((
qBlue
darkBackground
inv_alpha
255
alpha
255
),
255
));
wave
setPixel
distBorder
int
scopeH
distBorder
qRgba
CHOP255
((
qRed
darkBackground
Rgb
inv_alpha
255
alpha
255
),
CHOP255
((
qGreen
darkBackground
Rgb
inv_alpha
255
alpha
255
),
CHOP255
((
qBlue
darkBackground
Rgb
inv_alpha
255
alpha
255
),
255
));
break
if
drawAxis
QPainter
davinci
bool
ok
davinci
begin
wave
);
if
ok
qDebug
()
<<
"Could not initialise QPainter for Waveform."
return
wave
if
paintMode
!=
PaintMode_Green
davinci
setPen
QPen
QColor
150
255
200
32
),
);
else
// opposite color of the greenish base color we're using above (#005200)
davinci
setPen
QPen
QColor
255
255
52
255
32
),
))
QRgb
opx
// inverted background color for good contrast
QRgb
penRgb
qRgba
255
qRed
darkBackground
),
255
qGreen
darkBackground
),
255
qBlue
darkBackground
),
32
);
davinci
setPen
penRgb
);
davinci
setCompositionMode
QPainter
::
CompositionMode_Overlay
);
for
int
<=
10
++
int
dy
int
10.f
wh
));
for
int
int
ww
);
++
opx
wave
pixel
dy
);
wave
setPixel
dy
qRgba
CHOP255
qRed
penRgb
qRed
opx
)),
255
CHOP255
penRgb
qBlue
opx
)),
CHOP255
qAlpha
penRgb
qAlpha
opx
))));
int
dy
distBorder
int
10.f
scopeHLogicalPixels
));
davinci
drawLine
distBorder
dy
scopeWLogicalPixels
dy
);
Loading
US