From 57974f9b8bad4a0e12d3cdcca7a5e87b73d07d40 Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Feb 19 2020 15:24:22 +0000 Subject: perspective: checks --- diff --git a/c++/perspective/src/generator.cpp b/c++/perspective/src/generator.cpp index 41b76db..83bf8aa 100644 --- a/c++/perspective/src/generator.cpp +++ b/c++/perspective/src/generator.cpp @@ -431,3 +431,48 @@ Generator::generate(Surface &target, const Pair2 &bounds) const { } } } + + +Real +Generator::checks_value(Real coord, Real inv_precision) const { + Real x = fabs(coord - floor(coord) - 0.5); + return clamp(inv_precision*(0.25 - x), -1, 1); +} + +Real +Generator::checks_value(const Vector2 &coord, const Vector2 &inv_precision) const { + Real x = checks_value(coord.x, inv_precision.x) + * checks_value(coord.y, inv_precision.y); + return (x + 1)*0.5; +} + +void +Generator::generate_checks(Surface &target, const Pair2 &bounds) const { + if (target.empty()) return; + + const int w = target.width(); + const int h = target.height(); + + const Color colors[2] = { + Color(1, 1, 1, 1), + Color(0, 0, 1, 1) }; + + Vector2 d = bounds.distance(); + d.x /= w; + d.y /= h; + + Vector2 inv_precision( + 2/std::max(fabs(d.x), real_precision), + 2/std::max(fabs(d.y), real_precision) ); + + Vector2 p = bounds.p0; + for(int r = 0; r < h; ++r, p.x = bounds.p0.x, p.y += d.y) { + Color *pixel = target[r]; + Real ay = checks_value(p.y, inv_precision.y); + for(int c = 0; c < w; ++c, ++pixel, p.x += d.x) { + Real ax = checks_value(p.x, inv_precision.x); + Real a = (ax*ay + 1)*0.5; + *pixel = colors[0]*a + colors[1]*(1 - a); + } + } +} diff --git a/c++/perspective/src/generator.h b/c++/perspective/src/generator.h index 8af0ef2..b79519a 100644 --- a/c++/perspective/src/generator.h +++ b/c++/perspective/src/generator.h @@ -109,12 +109,17 @@ public: inline Vector4 random(const ULongIntVector2 &coord) const { return Vector4(random(coord, 0), random(coord, 1), random(coord, 2), random(coord, 3)); } + Real checks_value(Real coord, Real inv_precision) const; + Real checks_value(const Vector2 &coord, const Vector2 &inv_precision) const; + Vector4 generate(const ULongIntVector2 &coord, bool shrink_cache = true) const; Vector4 generate(const Vector2 &coord, const Vector2 &precision) const; void generate(Surface &target, const Pair2 &bounds) const; - + void generate(GenSurface &target) const; void generate(GenSurface &target, const GenSurface &source) const; + + void generate_checks(Surface &target, const Pair2 &bounds) const; }; diff --git a/c++/perspective/src/mainwindow.cpp b/c++/perspective/src/mainwindow.cpp index fce4a8b..236c4f7 100644 --- a/c++/perspective/src/mainwindow.cpp +++ b/c++/perspective/src/mainwindow.cpp @@ -10,6 +10,10 @@ #include "mainwindow.h" +const bool checks = false; +const bool paint_outside_bounds = false; + + MainWindow::MainWindow(): src_rect_p0 (new View::Point( Vector2(-1, -1) )), src_rect_p1 (new View::Point( Vector2( 1, 1) )), @@ -109,7 +113,8 @@ MainWindow::update_src_surface() { src_surface.clear(); } else { DataSurface surface(w, h); - generator.generate(surface, rect); + if (checks) generator.generate_checks(surface, rect); + else generator.generate(surface, rect); src_surface = surface.to_cairo_surface(); } @@ -186,16 +191,21 @@ MainWindow::update_dst_surface() { std::cout << Log::tab() << "created layers:" << std::endl; Perspective::print_layers(layers, Log::tab(2)); std::cout << Log::tab() << "---------------" << std::endl; + + std::cout << Log::tab() << "optimal step: " + << Perspective::find_optimal_step(matrix, dst_bounds_pixels) << std::endl; // override dst_bounds - for(Perspective::LayerList::iterator i = layers.begin(); i != layers.end(); ++i) - i->dst_bounds = full_dst_bounds_pixels; + if (paint_outside_bounds) + for(Perspective::LayerList::iterator i = layers.begin(); i != layers.end(); ++i) + i->dst_bounds = full_dst_bounds_pixels; // make surface DataSurface surface(full_dst_bounds_pixels.p1.x, full_dst_bounds_pixels.p1.y); for(Perspective::LayerList::const_iterator i = layers.begin(); i != layers.end(); ++i) { DataSurface layer_surface(i->src_size.x, i->src_size.y); - generator.generate(layer_surface, i->src_bounds); + if (checks) generator.generate_checks(layer_surface, i->src_bounds); + else generator.generate(layer_surface, i->src_bounds); layer_surface.mult_alpha(); Perspective::add_premulted(*i, layer_surface, surface); } diff --git a/c++/perspective/src/perspective.cpp b/c++/perspective/src/perspective.cpp index fff728f..0d59e20 100644 --- a/c++/perspective/src/perspective.cpp +++ b/c++/perspective/src/perspective.cpp @@ -15,8 +15,8 @@ namespace { const int max_area_width = 4096 - 2*border_width; const int max_area = max_area_width * max_area_width; - const Real max_overscale = 1.0; - const Real max_overscale_sqr = max_overscale*max_overscale; + const Real max_overscale = 2.0; + Real max_overscale_sqr = max_overscale*max_overscale; } @@ -381,7 +381,7 @@ Perspective::create_layers( layer.src_bounds, layer.src_size, layer.back_matrix, - resolution * w, + resolution / w, layer_src_bounds, Vector2(layer.dst_bounds.size()) ); layer.back_matrix *= back_matrix; @@ -393,6 +393,35 @@ Perspective::create_layers( } +Real +Perspective::find_optimal_step( + const Matrix3 &matrix, + const IntPair2 &dst_bounds ) +{ + max_overscale_sqr = 1e10; + + ULongInt min_area = -1ull; + Real optimal_step = 0; + LayerList layers; + for(Real step = 2; step < 16; step *= 1.01) { + create_layers(layers, matrix, dst_bounds, step); + ULongInt area = 0; + for(LayerList::const_iterator i = layers.begin(); i != layers.end(); ++i) + area += i->src_size.square(); + if (area < min_area) { + min_area = area; + optimal_step = step; + } + layers.clear(); + } + + max_overscale_sqr = max_overscale*max_overscale; + + return optimal_step; +} + + + void Perspective::add_premulted( const Layer &layer, diff --git a/c++/perspective/src/perspective.h b/c++/perspective/src/perspective.h index 5961840..6d75a62 100644 --- a/c++/perspective/src/perspective.h +++ b/c++/perspective/src/perspective.h @@ -67,6 +67,10 @@ public: const IntPair2 &dst_bounds, const Real step = 4.0 ); + static Real find_optimal_step( + const Matrix3 &matrix, + const IntPair2 &dst_bounds ); + static void add_premulted( const Layer &layer, Surface &src_surface, diff --git a/c++/perspective/src/surface.cpp b/c++/perspective/src/surface.cpp index 90bf4cd..31766c9 100644 --- a/c++/perspective/src/surface.cpp +++ b/c++/perspective/src/surface.cpp @@ -147,9 +147,9 @@ Surface::to_pixbuf() const { pixels += stride; for(int c = 0; c < width(); ++c) { const Color &color = src_row[c]; - *(pixel++) = (guint8)(color.r*255.9); - *(pixel++) = (guint8)(color.g*255.9); *(pixel++) = (guint8)(color.b*255.9); + *(pixel++) = (guint8)(color.g*255.9); + *(pixel++) = (guint8)(color.r*255.9); *(pixel++) = (guint8)(color.a*255.9); } } @@ -172,9 +172,9 @@ Surface::to_cairo_surface(bool premulted) const { for(int c = 0; c < width(); ++c) { Color color = src_row[c]; if (!premulted) color.mult_alpha(); - *(pixel++) = (guint8)(color.r*255.9); - *(pixel++) = (guint8)(color.g*255.9); *(pixel++) = (guint8)(color.b*255.9); + *(pixel++) = (guint8)(color.g*255.9); + *(pixel++) = (guint8)(color.r*255.9); *(pixel++) = (guint8)(color.a*255.9); } }