mirror of
https://github.com/clementine-player/Clementine
synced 2024-12-16 19:31:02 +01:00
Add an option to blur background image.
Fixes issue 3266.
This commit is contained in:
parent
5825768f36
commit
c4796564ea
@ -1017,16 +1017,19 @@ void PlaylistView::ReloadSettings() {
|
||||
}
|
||||
}
|
||||
QString background_image_filename = s.value(kSettingBackgroundImageFilename).toString();
|
||||
int blur_radius = s.value("blur_radius").toInt();
|
||||
// Check if background properties have changed.
|
||||
// We change properties only if they have actually changed, to avoid to call
|
||||
// set_background_image when it is not needed, as this will cause the fading
|
||||
// animation to start again. This also avoid to do useless
|
||||
// "force_background_redraw".
|
||||
if (background_image_filename != background_image_filename_
|
||||
|| background_type != background_image_type_) {
|
||||
|| background_type != background_image_type_ ||
|
||||
blur_radius_ != blur_radius) {
|
||||
// Store background properties
|
||||
background_image_type_ = background_type;
|
||||
background_image_filename_ = background_image_filename;
|
||||
blur_radius_ = blur_radius;
|
||||
if (background_image_type_ == Custom) {
|
||||
set_background_image(QImage(background_image_filename));
|
||||
} else if (background_image_type_ == AlbumCover) {
|
||||
@ -1190,18 +1193,93 @@ void PlaylistView::set_background_image(const QImage& image) {
|
||||
else
|
||||
background_image_ = image;
|
||||
|
||||
|
||||
|
||||
// Apply opacity filter
|
||||
uchar* bits = background_image_.bits();
|
||||
for (int i = 0; i < background_image_.height() * background_image_.bytesPerLine(); i+=4) {
|
||||
bits[i+3] = kBackgroundOpacity * 255;
|
||||
}
|
||||
|
||||
if (blur_radius_ != 0)
|
||||
background_image_ = blur_background_image(background_image_, blur_radius_, false);
|
||||
|
||||
if (isVisible()) {
|
||||
previous_background_image_opacity_ = 1.0;
|
||||
fade_animation_->start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QImage PlaylistView::blur_background_image(const QImage& image, int radius, bool alphaOnly = false)
|
||||
{
|
||||
int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
|
||||
int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1];
|
||||
|
||||
QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
QRect rect = image.rect();
|
||||
int r1 = rect.top();
|
||||
int r2 = rect.bottom();
|
||||
int c1 = rect.left();
|
||||
int c2 = rect.right();
|
||||
|
||||
int bpl = result.bytesPerLine();
|
||||
int rgba[4];
|
||||
unsigned char* p;
|
||||
|
||||
int i1 = 0;
|
||||
int i2 = 3;
|
||||
|
||||
if (alphaOnly)
|
||||
i1 = i2 = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3);
|
||||
|
||||
for (int col = c1; col <= c2; col++) {
|
||||
p = result.scanLine(r1) + col * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p += bpl;
|
||||
for (int j = r1; j < r2; j++, p += bpl)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int row = r1; row <= r2; row++) {
|
||||
p = result.scanLine(row) + c1 * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p += 4;
|
||||
for (int j = c1; j < c2; j++, p += 4)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int col = c1; col <= c2; col++) {
|
||||
p = result.scanLine(r2) + col * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p -= bpl;
|
||||
for (int j = r1; j < r2; j++, p -= bpl)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int row = r1; row <= r2; row++) {
|
||||
p = result.scanLine(row) + c2 * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p -= 4;
|
||||
for (int j = c1; j < c2; j++, p -= 4)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PlaylistView::FadePreviousBackgroundImage(qreal value) {
|
||||
previous_background_image_opacity_ = value;
|
||||
if (qFuzzyCompare(previous_background_image_opacity_, qreal(0.0))) {
|
||||
|
@ -73,6 +73,7 @@ class PlaylistView : public QTreeView {
|
||||
// Constants for settings: are persistent, values should not be changed
|
||||
static const char* kSettingBackgroundImageType;
|
||||
static const char* kSettingBackgroundImageFilename;
|
||||
static const int kSettingBackgroundBlurLevel;
|
||||
|
||||
static ColumnAlignmentMap DefaultColumnAlignment();
|
||||
|
||||
@ -166,6 +167,7 @@ class PlaylistView : public QTreeView {
|
||||
// Save image as the background_image_ after applying some modifications (opacity, ...).
|
||||
// Should be used instead of modifying background_image_ directly
|
||||
void set_background_image(const QImage& image);
|
||||
QImage blur_background_image(const QImage& image, int radius, bool alphaOnly);
|
||||
|
||||
private:
|
||||
static const int kGlowIntensitySteps;
|
||||
@ -173,7 +175,7 @@ class PlaylistView : public QTreeView {
|
||||
static const int kDropIndicatorWidth;
|
||||
static const int kDropIndicatorGradientWidth;
|
||||
static const qreal kBackgroundOpacity;
|
||||
|
||||
|
||||
QList<int> GetEditableColumns();
|
||||
QModelIndex NextEditableIndex(const QModelIndex& current);
|
||||
QModelIndex PrevEditableIndex(const QModelIndex& current);
|
||||
@ -194,6 +196,7 @@ class PlaylistView : public QTreeView {
|
||||
// particular (in terms of format, opacity), you should probably use
|
||||
// set_background_image_type instead of modifying background_image_ directly
|
||||
QImage background_image_;
|
||||
int blur_radius_;
|
||||
// Used if background image is a filemane
|
||||
QString background_image_filename_;
|
||||
QImage current_song_cover_art_;
|
||||
|
@ -56,6 +56,7 @@ AppearanceSettingsPage::AppearanceSettingsPage(SettingsDialog* dialog)
|
||||
connect(ui_->select_foreground_color, SIGNAL(pressed()), SLOT(SelectForegroundColor()));
|
||||
connect(ui_->select_background_color, SIGNAL(pressed()), SLOT(SelectBackgroundColor()));
|
||||
connect(ui_->use_a_custom_color_set, SIGNAL(toggled(bool)), SLOT(UseCustomColorSetOptionChanged(bool)));
|
||||
connect(ui_->blur_slider, SIGNAL(valueChanged(int)), SLOT(BlurLevelChanged(int)));
|
||||
|
||||
connect(ui_->select_background_image_filename_button, SIGNAL(pressed()), SLOT(SelectBackgroundImage()));
|
||||
connect(ui_->use_custom_background_image, SIGNAL(toggled(bool)),
|
||||
@ -114,6 +115,7 @@ void AppearanceSettingsPage::Load() {
|
||||
ui_->use_default_background->setChecked(true);
|
||||
}
|
||||
ui_->background_image_filename->setText(playlist_view_background_image_filename_);
|
||||
|
||||
s.endGroup();
|
||||
|
||||
// Moodbar settings
|
||||
@ -154,7 +156,8 @@ void AppearanceSettingsPage::Save() {
|
||||
playlist_view_background_image_filename_);
|
||||
}
|
||||
s.setValue(PlaylistView::kSettingBackgroundImageType,
|
||||
playlist_view_background_image_type_);
|
||||
playlist_view_background_image_type_);
|
||||
s.setValue("blur_radius", ui_->blur_slider->value());
|
||||
s.endGroup();
|
||||
|
||||
// Moodbar settings
|
||||
@ -230,6 +233,12 @@ void AppearanceSettingsPage::SelectBackgroundImage() {
|
||||
ui_->background_image_filename->setText(playlist_view_background_image_filename_);
|
||||
}
|
||||
|
||||
void AppearanceSettingsPage::BlurLevelChanged(int value) {
|
||||
background_blur_radius_ = value;
|
||||
ui_->background_blur_radius_label->setText(QString("%1px").arg(value));
|
||||
|
||||
}
|
||||
|
||||
void AppearanceSettingsPage::InitMoodbarPreviews() {
|
||||
#ifdef HAVE_MOODBAR
|
||||
if (initialised_moodbar_previews_)
|
||||
|
@ -42,6 +42,7 @@ private slots:
|
||||
void SelectBackgroundColor();
|
||||
void UseCustomColorSetOptionChanged(bool);
|
||||
void SelectBackgroundImage();
|
||||
void BlurLevelChanged(int);
|
||||
|
||||
private:
|
||||
static const int kMoodbarPreviewWidth;
|
||||
@ -62,7 +63,8 @@ private:
|
||||
QColor current_background_color_;
|
||||
PlaylistView::BackgroundImageType playlist_view_background_image_type_;
|
||||
QString playlist_view_background_image_filename_;
|
||||
|
||||
int background_blur_radius_;
|
||||
|
||||
bool initialised_moodbar_previews_;
|
||||
};
|
||||
|
||||
|
@ -155,6 +155,52 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="select_background_blur_label">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select blur radius:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="background_blur_radius_label">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0px</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="blur_slider">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
Loading…
Reference in New Issue
Block a user