summaryrefslogtreecommitdiffstats
path: root/src/libdepixelize/priv/pixelgraph.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdepixelize/priv/pixelgraph.h')
-rw-r--r--src/libdepixelize/priv/pixelgraph.h555
1 files changed, 0 insertions, 555 deletions
diff --git a/src/libdepixelize/priv/pixelgraph.h b/src/libdepixelize/priv/pixelgraph.h
deleted file mode 100644
index 112242647..000000000
--- a/src/libdepixelize/priv/pixelgraph.h
+++ /dev/null
@@ -1,555 +0,0 @@
-/* This file is part of the libdepixelize project
- Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
-
- GNU Lesser General Public License Usage
- This library is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2.1 of the License, or (at your
- option) any later version.
- You should have received a copy of the GNU Lesser General Public License
- along with this library. If not, see <http://www.gnu.org/licenses/>.
-
- GNU General Public License Usage
- Alternatively, this library may be used under the terms of the GNU General
- Public License as published by the Free Software Foundation, either version
- 2 of the License, or (at your option) any later version.
- You should have received a copy of the GNU General Public License along with
- this library. If not, see <http://www.gnu.org/licenses/>.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-*/
-
-#ifndef LIBDEPIXELIZE_TRACER_PIXELGRAPH_H
-#define LIBDEPIXELIZE_TRACER_PIXELGRAPH_H
-
-#include <gdkmm/pixbuf.h>
-#include <vector>
-#include <cassert>
-#include <utility>
-
-namespace Tracer {
-
-class PixelGraph
-{
-public:
- class Node
- {
- public:
- /*
- * Hamming weight of \p adj
- */
- unsigned adjsize() const
- {
- unsigned all[8] = {
- adj.top,
- adj.topright,
- adj.right,
- adj.bottomright,
- adj.bottom,
- adj.bottomleft,
- adj.left,
- adj.topleft
- };
- return all[0] + all[1] + all[2] + all[3]
- + all[4] + all[5] + all[6] + all[7];
- }
-
- guint8 rgba[4];
- // Nodes pointing from this
- struct Adj
- {
- unsigned top: 1;
- unsigned topright: 1;
- unsigned right: 1;
- unsigned bottomright: 1;
- unsigned bottom: 1;
- unsigned bottomleft: 1;
- unsigned left: 1;
- unsigned topleft: 1;
- } adj;
- };
-
- typedef std::vector<Node>::iterator iterator;
- typedef std::vector<Node>::const_iterator const_iterator;
- typedef std::vector<Node>::reverse_iterator reverse_iterator;
- typedef std::vector<Node>::const_reverse_iterator const_reverse_iterator;
-
- typedef std::pair<iterator, iterator> Edge;
- typedef std::pair<Edge, Edge> EdgePair;
- typedef std::vector<EdgePair> EdgePairContainer;
-
- class ColumnView
- {
- public:
- ColumnView(std::vector<Node> &nodes, int width, int column) :
- _nodes(nodes), _width(width), _column(column)
- {}
-
- Node &operator[](int line);
-
- private:
- std::vector<Node> &_nodes;
- const int _width;
- const int _column;
- };
-
- PixelGraph(Glib::RefPtr<Gdk::Pixbuf const> pixbuf);
-
- void checkConsistency();
-
- /**
- * It'll let you access the nodes using the syntax:
- *
- * graph[x][y]
- *
- * Where x is the column and y is the line.
- */
- ColumnView operator[](int column);
-
- // Iterators
- iterator begin()
- {
- return _nodes.begin();
- }
-
- const_iterator begin() const
- {
- return _nodes.begin();
- }
-
- iterator end()
- {
- return _nodes.end();
- }
-
- const_iterator end() const
- {
- return _nodes.end();
- }
-
- reverse_iterator rbegin()
- {
- return _nodes.rbegin();
- }
-
- const_reverse_iterator rbegin() const
- {
- return _nodes.rbegin();
- }
-
- reverse_iterator rend()
- {
- return _nodes.rend();
- }
-
- const_reverse_iterator rend() const
- {
- return _nodes.rend();
- }
-
- size_t size() const
- {
- return _nodes.size();
- }
-
- int width() const
- {
- return _width;
- }
-
- int height() const
- {
- return _height;
- }
-
- // Algorithms
- void connectAllNeighbors();
- EdgePairContainer crossingEdges();
-
- int toX(const_iterator n) const
- {
- return (&*n - &_nodes[0]) % _width;
- }
-
- int toY(const_iterator n) const
- {
- return (&*n - &_nodes[0]) / _width;
- }
-
- iterator nodeTop(iterator n)
- {
- return n - _width;
- }
-
- iterator nodeBottom(iterator n)
- {
- return n + _width;
- }
-
- iterator nodeLeft(iterator n)
- {
- return n - 1;
- }
-
- iterator nodeRight(iterator n)
- {
- return n + 1;
- }
-
- iterator nodeTopLeft(iterator n)
- {
- return n - _width - 1;
- }
-
- iterator nodeTopRight(iterator n)
- {
- return n - _width + 1;
- }
-
- iterator nodeBottomLeft(iterator n)
- {
- return n + _width - 1;
- }
-
- iterator nodeBottomRight(iterator n)
- {
- return n + _width + 1;
- }
-
- const_iterator nodeTop(const_iterator n) const
- {
- return n - _width;
- }
-
- const_iterator nodeBottom(const_iterator n) const
- {
- return n + _width;
- }
-
- const_iterator nodeLeft(const_iterator n) const
- {
- return n - 1;
- }
-
- const_iterator nodeRight(const_iterator n) const
- {
- return n + 1;
- }
-
- const_iterator nodeTopLeft(const_iterator n) const
- {
- return n - _width - 1;
- }
-
- const_iterator nodeTopRight(const_iterator n) const
- {
- return n - _width + 1;
- }
-
- const_iterator nodeBottomLeft(const_iterator n) const
- {
- return n + _width - 1;
- }
-
- const_iterator nodeBottomRight(const_iterator n) const
- {
- return n + _width + 1;
- }
-
-private:
- PixelGraph(const PixelGraph&);
-
- int _width;
- int _height;
-
- // The data representation follows the image data pattern from gdk-pixbuf.
- //
- // Quoting:
- // "Image data in a pixbuf is stored in memory in uncompressed, packed
- // format. Rows in the image are stored top to bottom, and in each row
- // pixels are stored from left to right. There may be padding at the end of
- // a row."
- //
- // Differently, _nodes don't put padding among rows.
- std::vector<Node> _nodes;
-};
-
-inline PixelGraph::PixelGraph(Glib::RefPtr<Gdk::Pixbuf const> pixbuf) :
- _width(pixbuf->get_width()),
- _height(pixbuf->get_height()),
- _nodes(size_t(_width) * _height)
-{
- if ( !_width || !_height )
- return;
-
- // Initialize the graph using the pixels' color data
- guint8 *pixels = pixbuf->get_pixels();
- Node *dest = &_nodes[0];
- const int n_channels = pixbuf->get_n_channels();
- const int rowpadding = pixbuf->get_rowstride() - _width * n_channels;
-
- if ( n_channels == 4 ) {
- for ( int i = 0 ; i != _height ; ++i ) {
- for ( int j = 0 ; j != _width ; ++j ) {
- for ( int k = 0 ; k != 4 ; ++k )
- dest->rgba[k] = pixels[k];
- {
- dest->adj.top = 0;
- dest->adj.topright = 0;
- dest->adj.right = 0;
- dest->adj.bottomright = 0;
- dest->adj.bottom = 0;
- dest->adj.bottomleft = 0;
- dest->adj.left = 0;
- dest->adj.topleft = 0;
- }
- pixels += n_channels;
- ++dest;
- }
- pixels += rowpadding;
- }
- } else {
- assert(n_channels == 3);
- for ( int i = 0 ; i != _height ; ++i ) {
- for ( int j = 0 ; j != _width ; ++j ) {
- for ( int k = 0 ; k != 3 ; ++k )
- dest->rgba[k] = pixels[k];
- dest->rgba[3] = '\xFF';
- {
- dest->adj.top = 0;
- dest->adj.topright = 0;
- dest->adj.right = 0;
- dest->adj.bottomright = 0;
- dest->adj.bottom = 0;
- dest->adj.bottomleft = 0;
- dest->adj.left = 0;
- dest->adj.topleft = 0;
- }
- pixels += n_channels;
- ++dest;
- }
- pixels += rowpadding;
- }
- }
-}
-
-inline void PixelGraph::checkConsistency()
-{
- PixelGraph::Node *it = &_nodes.front();
- for ( int i = 0 ; i != _height ; ++i ) {
- for ( int j = 0 ; j != _width ; ++j, ++it ) {
- if ( it->adj.top )
- assert((it - _width)->adj.bottom);
- if ( it->adj.topright )
- assert((it - _width + 1)->adj.bottomleft);
- if ( it->adj.right )
- assert((it + 1)->adj.left);
- if ( it->adj.bottomright )
- assert((it + _width + 1)->adj.topleft);
- if ( it->adj.bottom )
- assert((it + _width)->adj.top);
- if ( it->adj.bottomleft )
- assert((it + _width - 1)->adj.topright);
- if ( it->adj.left )
- assert((it - 1)->adj.right);
- if ( it->adj.topleft )
- assert((it - _width - 1)->adj.bottomright);
- }
- }
-}
-
-inline PixelGraph::ColumnView PixelGraph::operator[](int column)
-{
- return ColumnView(_nodes, _width, column);
-}
-
-inline void PixelGraph::connectAllNeighbors()
-{
- // ...the "center" nodes first...
- if ( _width > 2 && _height > 2 ) {
- iterator it = nodeBottomRight(begin()); // [1][1]
- for ( int i = 1 ; i != _height - 1 ; ++i ) {
- for ( int j = 1 ; j != _width - 1 ; ++j ) {
- it->adj.top = 1;
- it->adj.topright = 1;
- it->adj.right = 1;
- it->adj.bottomright = 1;
- it->adj.bottom = 1;
- it->adj.bottomleft = 1;
- it->adj.left = 1;
- it->adj.topleft = 1;
-
- it = nodeRight(it);
- }
- // After the previous loop, 'it' is pointing to the last node from
- // the row.
- // Go south, then first node in the row (increment 'it' by 1)
- // Go to the second node in the line (increment 'it' by 1)
- it += 2;
- }
- }
-
- // ...then the "top" nodes...
- if ( _width > 2 ) {
- Node *it = &_nodes[1];
- if ( _height > 1 ) {
- for ( int i = 1 ; i != _width - 1 ; ++i ) {
- it->adj.right = 1;
- it->adj.bottomright = 1;
- it->adj.bottom = 1;
- it->adj.bottomleft = 1;
- it->adj.left = 1;
-
- ++it;
- }
- } else {
- for ( int i = 1 ; i != _width - 1 ; ++i ) {
- it->adj.right = 1;
- it->adj.left = 1;
-
- ++it;
- }
- }
- }
-
- // ...then the "bottom" nodes...
- if ( _width > 2 && _height > 1 ) {
- Node *it = &((*this)[1][_height - 1]);
- for ( int i = 1 ; i != _width - 1 ; ++i ) {
- it->adj.left = 1;
- it->adj.topleft = 1;
- it->adj.top = 1;
- it->adj.topright = 1;
- it->adj.right = 1;
-
- ++it;
- }
- }
-
- // ...then the "left" nodes...
- if ( _height > 2 ) {
- iterator it = nodeBottom(begin()); // [0][1]
- if ( _width > 1 ) {
- for ( int i = 1 ; i != _height - 1 ; ++i ) {
- it->adj.top = 1;
- it->adj.topright = 1;
- it->adj.right = 1;
- it->adj.bottomright = 1;
- it->adj.bottom = 1;
-
- it = nodeBottom(it);
- }
- } else {
- for ( int i = 1 ; i != _height - 1 ; ++i ) {
- it->adj.top = 1;
- it->adj.bottom = 1;
-
- it = nodeBottom(it);
- }
- }
- }
-
- // ...then the "right" nodes...
- if ( _height > 2 && _width > 1 ) {
- iterator it = nodeBottom(begin() + _width - 1);// [_width - 1][1]
- for ( int i = 1 ; i != _height - 1 ; ++i ) {
- it->adj.bottom = 1;
- it->adj.bottomleft = 1;
- it->adj.left = 1;
- it->adj.topleft = 1;
- it->adj.top = 1;
-
- it = nodeBottom(it);
- }
- }
-
- // ...and the 4 corner nodes
- {
- Node *const top_left = &(*this)[0][0];
-
- if ( _width > 1 )
- top_left->adj.right = 1;
-
- if ( _width > 1 && _height > 1 )
- top_left->adj.bottomright = 1;
-
- if ( _height > 1 )
- top_left->adj.bottom = 1;
- }
- if ( _width > 1 ) {
- Node *const top_right = &(*this)[_width - 1][0];
-
- if ( _height > 1 ) {
- top_right->adj.bottom = 1;
- top_right->adj.bottomleft = 1;
- }
-
- top_right->adj.left = 1;
- }
- if ( _height > 1 ) {
- Node *const down_left = &(*this)[0][_height - 1];
- down_left->adj.top = 1;
-
- if ( _width > 1 ) {
- down_left->adj.topright = 1;
- down_left->adj.right = 1;
- }
- }
- if ( _width > 1 && _height > 1 ) {
- Node *const down_right = &(*this)[_width - 1][_height - 1];
- down_right->adj.left = 1;
- down_right->adj.topleft = 1;
- down_right->adj.top = 1;
- }
-}
-
-PixelGraph::EdgePairContainer PixelGraph::crossingEdges()
-{
- EdgePairContainer ret;
-
- if ( width() < 2 || height() < 2 )
- return ret;
-
- // Iterate over the graph, 2x2 blocks at time
- PixelGraph::iterator it = begin();
- for (int i = 0 ; i != height() - 1 ; ++i, ++it ) {
- for ( int j = 0 ; j != width() - 1 ; ++j, ++it ) {
- EdgePair diagonals(
- Edge(it, nodeBottomRight(it)),
- Edge(nodeRight(it), nodeBottom(it)));
-
- // Check if there are crossing edges
- if ( !diagonals.first.first->adj.bottomright
- || !diagonals.second.first->adj.bottomleft ) {
- continue;
- }
-
- ret.push_back(diagonals);
- }
- }
-
- return ret;
-}
-
-inline PixelGraph::Node &PixelGraph::ColumnView::operator[](int line)
-{
- return _nodes[line * _width + _column];
-}
-
-} // namespace Tracer
-
-#endif // LIBDEPIXELIZE_TRACER_PIXELGRAPH_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :