1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 20:57:35 +00:00

PixelPaint: Make filters apply to a selection if one is present

This changes ImageProcessor to use the scratch bitmap of the layer which
will cause the changes to only be applied inside the active selection
(if there is one). This also updates the FilterPreviewWidget to show the
filter preview with active selection taken into account.
This commit is contained in:
Timothy Slater 2022-11-01 17:28:05 -05:00 committed by Ali Mohammad Pur
parent 6911c5545c
commit 75c359ef31
4 changed files with 25 additions and 3 deletions

View file

@ -65,6 +65,7 @@ FilterGallery::FilterGallery(GUI::Window* parent_window, ImageEditor* editor)
m_config_widget->add_child(*m_selected_filter_config_widget);
};
m_preview_widget->set_layer(editor->active_layer());
m_preview_widget->set_bitmap(editor->active_layer()->content_bitmap().clone().release_value());
apply_button->on_click = [this](auto) {

View file

@ -21,6 +21,11 @@ FilterPreviewWidget::~FilterPreviewWidget()
{
}
void FilterPreviewWidget::set_layer(RefPtr<PixelPaint::Layer> layer)
{
m_layer = layer;
}
void FilterPreviewWidget::set_bitmap(RefPtr<Gfx::Bitmap> const& bitmap)
{
m_bitmap = bitmap;
@ -29,10 +34,24 @@ void FilterPreviewWidget::set_bitmap(RefPtr<Gfx::Bitmap> const& bitmap)
void FilterPreviewWidget::set_filter(Filter* filter)
{
if (filter)
if (filter) {
filter->apply(*m_filtered_bitmap, *m_bitmap);
else
// If we have a layer set and the image has an active selection we only want the filter to apply to the
// selected region. This will walk the image and for every pixel that is outside the selection, restore it
// from the original bitmap.
if (m_layer && !m_layer->image().selection().is_empty()) {
for (int y = 0; y < m_filtered_bitmap->height(); ++y) {
for (int x = 0; x < m_filtered_bitmap->width(); ++x) {
if (!m_layer->image().selection().is_selected(m_layer->location().translated(x, y))) {
m_filtered_bitmap->set_pixel(x, y, m_bitmap->get_pixel(x, y));
}
}
}
}
} else {
m_filtered_bitmap = m_bitmap->clone().release_value();
}
repaint();
}

View file

@ -19,6 +19,7 @@ class FilterPreviewWidget final : public GUI::Frame {
public:
virtual ~FilterPreviewWidget() override;
void set_layer(RefPtr<Layer> layer);
void set_bitmap(RefPtr<Gfx::Bitmap> const& bitmap);
void set_filter(Filter* filter);
void clear_filter();
@ -26,6 +27,7 @@ public:
private:
explicit FilterPreviewWidget();
RefPtr<Layer> m_layer;
RefPtr<Gfx::Bitmap> m_bitmap;
RefPtr<Gfx::Bitmap> m_filtered_bitmap;

View file

@ -16,7 +16,7 @@ FilterApplicationCommand::FilterApplicationCommand(NonnullRefPtr<Filter> filter,
void FilterApplicationCommand::execute()
{
m_filter->apply(m_target_layer->content_bitmap(), m_target_layer->content_bitmap());
m_filter->apply(m_target_layer->get_scratch_edited_bitmap(), m_target_layer->get_scratch_edited_bitmap());
m_filter->m_editor->gui_event_loop().deferred_invoke([strong_this = NonnullRefPtr(*this)]() {
// HACK: we can't tell strong_this to not be const
(*const_cast<NonnullRefPtr<Layer>*>(&strong_this->m_target_layer))->did_modify_bitmap(strong_this->m_target_layer->rect());