mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:17:44 +00:00
LibGfx: Make Filter::Parameters more light-weight
By moving the Bitmap and Rect out of Filter::Parameters we can re-use the parameters more efficiently, allowing the filter to be applied to many bitmaps without having to re-create the filter every time.
This commit is contained in:
parent
6188c6e8a3
commit
da8d87c297
4 changed files with 35 additions and 51 deletions
|
@ -119,7 +119,7 @@ private:
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
struct FilterParameters<Gfx::SpatialGaussianBlurFilter<N>> {
|
struct FilterParameters<Gfx::SpatialGaussianBlurFilter<N>> {
|
||||||
static OwnPtr<typename Gfx::SpatialGaussianBlurFilter<N>::Parameters> get(Gfx::Bitmap& bitmap, const Gfx::IntRect& rect)
|
static OwnPtr<typename Gfx::SpatialGaussianBlurFilter<N>::Parameters> get()
|
||||||
{
|
{
|
||||||
Matrix<N, float> kernel;
|
Matrix<N, float> kernel;
|
||||||
auto sigma = 1.0f;
|
auto sigma = 1.0f;
|
||||||
|
@ -134,37 +134,37 @@ struct FilterParameters<Gfx::SpatialGaussianBlurFilter<N>> {
|
||||||
|
|
||||||
normalize(kernel);
|
normalize(kernel);
|
||||||
|
|
||||||
return make<typename Gfx::GenericConvolutionFilter<N>::Parameters>(bitmap, rect, kernel);
|
return make<typename Gfx::GenericConvolutionFilter<N>::Parameters>(kernel);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct FilterParameters<Gfx::SharpenFilter> {
|
struct FilterParameters<Gfx::SharpenFilter> {
|
||||||
static OwnPtr<Gfx::GenericConvolutionFilter<3>::Parameters> get(Gfx::Bitmap& bitmap, const Gfx::IntRect& rect)
|
static OwnPtr<Gfx::GenericConvolutionFilter<3>::Parameters> get()
|
||||||
{
|
{
|
||||||
return make<Gfx::GenericConvolutionFilter<3>::Parameters>(bitmap, rect, Matrix<3, float>(0, -1, 0, -1, 5, -1, 0, -1, 0));
|
return make<Gfx::GenericConvolutionFilter<3>::Parameters>(Matrix<3, float>(0, -1, 0, -1, 5, -1, 0, -1, 0));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct FilterParameters<Gfx::LaplacianFilter> {
|
struct FilterParameters<Gfx::LaplacianFilter> {
|
||||||
static OwnPtr<Gfx::GenericConvolutionFilter<3>::Parameters> get(Gfx::Bitmap& bitmap, const Gfx::IntRect& rect, bool diagonal)
|
static OwnPtr<Gfx::GenericConvolutionFilter<3>::Parameters> get(bool diagonal)
|
||||||
{
|
{
|
||||||
if (diagonal)
|
if (diagonal)
|
||||||
return make<Gfx::GenericConvolutionFilter<3>::Parameters>(bitmap, rect, Matrix<3, float>(-1, -1, -1, -1, 8, -1, -1, -1, -1));
|
return make<Gfx::GenericConvolutionFilter<3>::Parameters>(Matrix<3, float>(-1, -1, -1, -1, 8, -1, -1, -1, -1));
|
||||||
|
|
||||||
return make<Gfx::GenericConvolutionFilter<3>::Parameters>(bitmap, rect, Matrix<3, float>(0, -1, 0, -1, 4, -1, 0, -1, 0));
|
return make<Gfx::GenericConvolutionFilter<3>::Parameters>(Matrix<3, float>(0, -1, 0, -1, 4, -1, 0, -1, 0));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
struct FilterParameters<Gfx::GenericConvolutionFilter<N>> {
|
struct FilterParameters<Gfx::GenericConvolutionFilter<N>> {
|
||||||
static OwnPtr<typename Gfx::GenericConvolutionFilter<N>::Parameters> get(Gfx::Bitmap& bitmap, const Gfx::IntRect& rect, GUI::Window* parent_window)
|
static OwnPtr<typename Gfx::GenericConvolutionFilter<N>::Parameters> get(GUI::Window* parent_window)
|
||||||
{
|
{
|
||||||
auto input = GenericConvolutionFilterInputDialog<N>::construct(parent_window);
|
auto input = GenericConvolutionFilterInputDialog<N>::construct(parent_window);
|
||||||
input->exec();
|
input->exec();
|
||||||
if (input->result() == GUI::Dialog::ExecOK)
|
if (input->result() == GUI::Dialog::ExecOK)
|
||||||
return make<typename Gfx::GenericConvolutionFilter<N>::Parameters>(bitmap, rect, input->matrix(), input->should_wrap());
|
return make<typename Gfx::GenericConvolutionFilter<N>::Parameters>(input->matrix(), input->should_wrap());
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ struct FilterParameters<Gfx::GenericConvolutionFilter<N>> {
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
struct FilterParameters<Gfx::BoxBlurFilter<N>> {
|
struct FilterParameters<Gfx::BoxBlurFilter<N>> {
|
||||||
static OwnPtr<typename Gfx::GenericConvolutionFilter<N>::Parameters> get(Gfx::Bitmap& bitmap, const Gfx::IntRect& rect)
|
static OwnPtr<typename Gfx::GenericConvolutionFilter<N>::Parameters> get()
|
||||||
{
|
{
|
||||||
Matrix<N, float> kernel;
|
Matrix<N, float> kernel;
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ struct FilterParameters<Gfx::BoxBlurFilter<N>> {
|
||||||
|
|
||||||
normalize(kernel);
|
normalize(kernel);
|
||||||
|
|
||||||
return make<typename Gfx::GenericConvolutionFilter<N>::Parameters>(bitmap, rect, kernel);
|
return make<typename Gfx::GenericConvolutionFilter<N>::Parameters>(kernel);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -219,51 +219,51 @@ int main(int argc, char** argv)
|
||||||
edge_detect_submenu.add_action(GUI::Action::create("Laplacian (cardinal)", [&](auto&) {
|
edge_detect_submenu.add_action(GUI::Action::create("Laplacian (cardinal)", [&](auto&) {
|
||||||
if (auto* layer = image_editor.active_layer()) {
|
if (auto* layer = image_editor.active_layer()) {
|
||||||
Gfx::LaplacianFilter filter;
|
Gfx::LaplacianFilter filter;
|
||||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::LaplacianFilter>::get(layer->bitmap(), layer->rect(), false))
|
if (auto parameters = PixelPaint::FilterParameters<Gfx::LaplacianFilter>::get(false))
|
||||||
filter.apply(*parameters);
|
filter.apply(layer->bitmap(), layer->rect(), *parameters);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
edge_detect_submenu.add_action(GUI::Action::create("Laplacian (diagonal)", [&](auto&) {
|
edge_detect_submenu.add_action(GUI::Action::create("Laplacian (diagonal)", [&](auto&) {
|
||||||
if (auto* layer = image_editor.active_layer()) {
|
if (auto* layer = image_editor.active_layer()) {
|
||||||
Gfx::LaplacianFilter filter;
|
Gfx::LaplacianFilter filter;
|
||||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::LaplacianFilter>::get(layer->bitmap(), layer->rect(), true))
|
if (auto parameters = PixelPaint::FilterParameters<Gfx::LaplacianFilter>::get(true))
|
||||||
filter.apply(*parameters);
|
filter.apply(layer->bitmap(), layer->rect(), *parameters);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
auto& blur_submenu = spatial_filters_menu.add_submenu("Blur and Sharpen");
|
auto& blur_submenu = spatial_filters_menu.add_submenu("Blur and Sharpen");
|
||||||
blur_submenu.add_action(GUI::Action::create("Gaussian Blur (3x3)", [&](auto&) {
|
blur_submenu.add_action(GUI::Action::create("Gaussian Blur (3x3)", [&](auto&) {
|
||||||
if (auto* layer = image_editor.active_layer()) {
|
if (auto* layer = image_editor.active_layer()) {
|
||||||
Gfx::SpatialGaussianBlurFilter<3> filter;
|
Gfx::SpatialGaussianBlurFilter<3> filter;
|
||||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::SpatialGaussianBlurFilter<3>>::get(layer->bitmap(), layer->rect()))
|
if (auto parameters = PixelPaint::FilterParameters<Gfx::SpatialGaussianBlurFilter<3>>::get())
|
||||||
filter.apply(*parameters);
|
filter.apply(layer->bitmap(), layer->rect(), *parameters);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
blur_submenu.add_action(GUI::Action::create("Gaussian Blur (5x5)", [&](auto&) {
|
blur_submenu.add_action(GUI::Action::create("Gaussian Blur (5x5)", [&](auto&) {
|
||||||
if (auto* layer = image_editor.active_layer()) {
|
if (auto* layer = image_editor.active_layer()) {
|
||||||
Gfx::SpatialGaussianBlurFilter<5> filter;
|
Gfx::SpatialGaussianBlurFilter<5> filter;
|
||||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::SpatialGaussianBlurFilter<5>>::get(layer->bitmap(), layer->rect()))
|
if (auto parameters = PixelPaint::FilterParameters<Gfx::SpatialGaussianBlurFilter<5>>::get())
|
||||||
filter.apply(*parameters);
|
filter.apply(layer->bitmap(), layer->rect(), *parameters);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
blur_submenu.add_action(GUI::Action::create("Box Blur (3x3)", [&](auto&) {
|
blur_submenu.add_action(GUI::Action::create("Box Blur (3x3)", [&](auto&) {
|
||||||
if (auto* layer = image_editor.active_layer()) {
|
if (auto* layer = image_editor.active_layer()) {
|
||||||
Gfx::BoxBlurFilter<3> filter;
|
Gfx::BoxBlurFilter<3> filter;
|
||||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::BoxBlurFilter<3>>::get(layer->bitmap(), layer->rect()))
|
if (auto parameters = PixelPaint::FilterParameters<Gfx::BoxBlurFilter<3>>::get())
|
||||||
filter.apply(*parameters);
|
filter.apply(layer->bitmap(), layer->rect(), *parameters);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
blur_submenu.add_action(GUI::Action::create("Box Blur (5x5)", [&](auto&) {
|
blur_submenu.add_action(GUI::Action::create("Box Blur (5x5)", [&](auto&) {
|
||||||
if (auto* layer = image_editor.active_layer()) {
|
if (auto* layer = image_editor.active_layer()) {
|
||||||
Gfx::BoxBlurFilter<5> filter;
|
Gfx::BoxBlurFilter<5> filter;
|
||||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::BoxBlurFilter<5>>::get(layer->bitmap(), layer->rect()))
|
if (auto parameters = PixelPaint::FilterParameters<Gfx::BoxBlurFilter<5>>::get())
|
||||||
filter.apply(*parameters);
|
filter.apply(layer->bitmap(), layer->rect(), *parameters);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
blur_submenu.add_action(GUI::Action::create("Sharpen", [&](auto&) {
|
blur_submenu.add_action(GUI::Action::create("Sharpen", [&](auto&) {
|
||||||
if (auto* layer = image_editor.active_layer()) {
|
if (auto* layer = image_editor.active_layer()) {
|
||||||
Gfx::SharpenFilter filter;
|
Gfx::SharpenFilter filter;
|
||||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::SharpenFilter>::get(layer->bitmap(), layer->rect()))
|
if (auto parameters = PixelPaint::FilterParameters<Gfx::SharpenFilter>::get())
|
||||||
filter.apply(*parameters);
|
filter.apply(layer->bitmap(), layer->rect(),*parameters);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -271,8 +271,8 @@ int main(int argc, char** argv)
|
||||||
spatial_filters_menu.add_action(GUI::Action::create("Generic 5x5 Convolution", [&](auto&) {
|
spatial_filters_menu.add_action(GUI::Action::create("Generic 5x5 Convolution", [&](auto&) {
|
||||||
if (auto* layer = image_editor.active_layer()) {
|
if (auto* layer = image_editor.active_layer()) {
|
||||||
Gfx::GenericConvolutionFilter<5> filter;
|
Gfx::GenericConvolutionFilter<5> filter;
|
||||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::GenericConvolutionFilter<5>>::get(layer->bitmap(), layer->rect(), window))
|
if (auto parameters = PixelPaint::FilterParameters<Gfx::GenericConvolutionFilter<5>>::get(window))
|
||||||
filter.apply(*parameters);
|
filter.apply(layer->bitmap(), layer->rect(),*parameters);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -35,28 +35,15 @@ class Filter {
|
||||||
public:
|
public:
|
||||||
class Parameters {
|
class Parameters {
|
||||||
public:
|
public:
|
||||||
Parameters(Bitmap& bitmap, const IntRect& rect)
|
|
||||||
: m_target_bitmap(bitmap)
|
|
||||||
, m_target_rect(rect)
|
|
||||||
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Bitmap& bitmap() const { return m_target_bitmap; }
|
|
||||||
const IntRect& rect() const { return m_target_rect; }
|
|
||||||
virtual bool is_generic_convolution_filter() const { return false; }
|
virtual bool is_generic_convolution_filter() const { return false; }
|
||||||
|
|
||||||
virtual ~Parameters() { }
|
virtual ~Parameters() { }
|
||||||
|
|
||||||
private:
|
|
||||||
Bitmap& m_target_bitmap;
|
|
||||||
IntRect m_target_rect;
|
|
||||||
};
|
};
|
||||||
virtual ~Filter() { }
|
virtual ~Filter() { }
|
||||||
|
|
||||||
virtual const char* class_name() const = 0;
|
virtual const char* class_name() const = 0;
|
||||||
|
|
||||||
virtual void apply(const Parameters&) = 0;
|
virtual void apply(Bitmap&, const IntRect&, const Parameters&) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Filter() { }
|
Filter() { }
|
||||||
|
|
|
@ -53,9 +53,8 @@ class GenericConvolutionFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
class Parameters : public Filter::Parameters {
|
class Parameters : public Filter::Parameters {
|
||||||
public:
|
public:
|
||||||
Parameters(Gfx::Bitmap& bitmap, const Gfx::IntRect& rect, Gfx::Matrix<N, float> kernel, bool should_wrap = false)
|
Parameters(const Gfx::Matrix<N, float>& kernel, bool should_wrap = false)
|
||||||
: Filter::Parameters(bitmap, rect)
|
: m_kernel(kernel)
|
||||||
, m_kernel(move(kernel))
|
|
||||||
, m_should_wrap(should_wrap)
|
, m_should_wrap(should_wrap)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -83,21 +82,19 @@ public:
|
||||||
|
|
||||||
virtual const char* class_name() const override { return "GenericConvolutionFilter"; }
|
virtual const char* class_name() const override { return "GenericConvolutionFilter"; }
|
||||||
|
|
||||||
virtual void apply(const Filter::Parameters& parameters) override
|
virtual void apply(Bitmap& bitmap, const IntRect& rect, const Filter::Parameters& parameters) override
|
||||||
{
|
{
|
||||||
ASSERT(parameters.is_generic_convolution_filter());
|
ASSERT(parameters.is_generic_convolution_filter());
|
||||||
auto& gcf_params = static_cast<const GenericConvolutionFilter::Parameters&>(parameters);
|
auto& gcf_params = static_cast<const GenericConvolutionFilter::Parameters&>(parameters);
|
||||||
|
|
||||||
ApplyCache apply_cache;
|
ApplyCache apply_cache;
|
||||||
apply(gcf_params, apply_cache);
|
apply(bitmap, rect, gcf_params, apply_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply(const GenericConvolutionFilter::Parameters& parameters, ApplyCache& apply_cache)
|
void apply(Bitmap& source, const IntRect& source_rect, const GenericConvolutionFilter::Parameters& parameters, ApplyCache& apply_cache)
|
||||||
{
|
{
|
||||||
auto& source = parameters.bitmap();
|
if (!apply_cache.m_target || !apply_cache.m_target->size().contains(source_rect.size()))
|
||||||
const auto& source_rect = parameters.rect();
|
apply_cache.m_target = Gfx::Bitmap::create(source.format(), source_rect.size());
|
||||||
if (!apply_cache.m_target || apply_cache.m_target->size().contains(parameters.rect().size()))
|
|
||||||
apply_cache.m_target = Gfx::Bitmap::create(source.format(), parameters.rect().size());
|
|
||||||
|
|
||||||
// FIXME: Help! I am naive!
|
// FIXME: Help! I am naive!
|
||||||
for (auto i_ = 0; i_ < source_rect.width(); ++i_) {
|
for (auto i_ = 0; i_ < source_rect.width(); ++i_) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue