FotoSHOCK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
graph/example.cpp

This example shows how to insert operations into GraphManager.

/*
* Copyright 2011, 2012 Lukas Jirkovsky
*
* This file is part of FotoSHOCK.
*
* FotoSHOCK 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, version 3 of the License.
*
* FotoSHOCK 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FotoSHOCK. If not, see <http://www.gnu.org/licenses/>.
*/
#include <GraphManager.hpp>
#include <TransformImage.hpp>
#include <iostream>
using std::cout;
using std::endl;
using namespace FotoSHOCKcore;
template <typename PixelFormat>
public:
AddOneFunctor(unsigned int bands) {
m_bands = bands;
}
void operator()(PixelFormat* in, PixelFormat* out) {
for (unsigned int i = 0; i < m_bands; ++i) {
out[i] = in[i] + 1;
}
}
private:
unsigned int m_bands;
};
class AddOne : public ImageOperation {
public:
virtual void runOperation (const Inputs& sources, const Outputs& dest, vector<UpdateInfo>& ROI, const long stamp) {
switch(sources[0]->getPixelData().format()) {
#define FORMAT_DO_STH(T,U) transformImage<T>(sources[0], dest[0], \
AddOneFunctor<U>(sources[0]->getPixelData().numOfBands()), ROI, stamp);
case_ANY;
#undef FORMAT_DO_STH
}
}
};
class Average : public ImageOperation {
public:
virtual void runOperation (const Inputs& sources, const Outputs& dest, vector<UpdateInfo>& /*ROI*/, const long /*stamp*/) {
switch(sources[0]->getPixelData().format()) {
#define FORMAT_DO_STH(T,U) average_impl(static_cast<ImageBuffer<T>*>((*(sources[0]))[0]), \
static_cast<ImageBuffer<T>*>((*(sources[1]))[0]), \
static_cast<ImageBuffer<T>*>((*dest[0])[0]));
case_ANY;
#undef FORMAT_DO_STH
}
}
virtual const unsigned int getNumInputs() const {
return 2;
}
private:
template <ValueType::Enum PixelFormat>
typename ImageBuffer<PixelFormat>::Iterator srcaIt = srca->upperLeft();
typename ImageBuffer<PixelFormat>::Iterator srcbIt = srcb->upperLeft();
typename ImageBuffer<PixelFormat>::Iterator destIt = dest->upperLeft();
for (; srcaIt != srcaLr; ++srcaIt, ++srcbIt, ++destIt) {
for (int band = 0; band < srca->getPixelData().numOfBands(); ++band) {
destIt[band] = (srcaIt[band] + srcbIt[band]) / 2;
}
}
}
};
public:
virtual const char* name() {return "Add One";}
virtual const char* description() {return "Adds one to each pixel.";}
virtual ImageOperation* operation() {return new AddOne;}
};
public:
virtual const char* name() {return "Average";}
virtual const char* description() {return "Computes an average of two inputs.";}
virtual InputProto inputPrototype() {
InputProto proto;
return proto;
}
virtual ImageOperation* operation() {return new Average;}
};
template <typename ValueType::Enum PixelFormat>
static void printTileContent(ImageBuffer<PixelFormat>* buffer) {
// loop over all tiles
unsigned int tilesH = buffer->getNumOfTilesHoriz();
unsigned int tilesV = buffer->getNumOfTilesVert();
cout << "Tile content" << endl;
for (unsigned int tileVert = 0; tileVert < tilesV; ++tileVert) {
cout << "\t";
for (unsigned int tileHoriz = 0; tileHoriz < tilesH; ++tileHoriz) {
typename Tile<PixelFormat>::Iterator it = buffer->getTile(tileHoriz, tileVert)->upperLeft();
cout << "(" << tileHoriz << ", " << tileVert << "): " << (unsigned int)it[0] << " ";
}
cout << endl;
}
}
AddOneDescr addOneDescr;
AverageDescr averageDescr;
int main() {
PixelData format(ValueTypeEnum::uint8, 8, 1, ColorSpaceEnum::gray);
GraphManager graph;
GraphNode* rootBlack = graph.addRoot(format, 100, 100, "black");
GraphNode* rootWhite = graph.addRoot(format, 100, 100, "white");
cout << "Content of a black root node" << endl;
switch(format.format()) {
#define FORMAT_DO_STH(T,U) printTileContent(static_cast<ImageBuffer<T>*>(rootBlack->getBuffer()));
case_ANY;
#undef FORMAT_DO_STH
}
cout << endl;
cout << "Content of a white root node" << endl;
switch(format.format()) {
#define FORMAT_DO_STH(T,U) printTileContent(static_cast<ImageBuffer<T>*>(rootWhite->getBuffer()));
case_ANY;
#undef FORMAT_DO_STH
}
cout << endl;
GraphNode* op1 = graph.insertOperation(&addOneDescr, rootBlack, NULL, NULL);
op1->addROI(ROIinfo(0, 0, 10, 10, 0));
graph.join();
// the tile (0, 0) should contain 1, the rest is undefined
cout << "Content of a node adding one to the black root node content" << endl;
cout << "with a ROI in the tile (0, 0)" << endl;
switch(format.format()) {
#define FORMAT_DO_STH(T,U) printTileContent(static_cast<ImageBuffer<T>*>(op1->getBuffer()));
case_ANY;
#undef FORMAT_DO_STH
}
cout << endl;
GraphNode* op2 = graph.insertOperation(&averageDescr, op1, rootWhite, NULL, NULL);
op2->addROI(ROIinfo(0, 0, 100, 100, 0));
graph.join();
// the content should be 128 everywhere
cout << "Content of a node adding average of the previous node and white" << endl;
cout << "with a ROI specifying the entire buffer" << endl;
switch(format.format()) {
#define FORMAT_DO_STH(T,U) printTileContent(static_cast<ImageBuffer<T>*>(op2->getBuffer()));
case_ANY;
#undef FORMAT_DO_STH
}
cout << endl;
GraphNode* op1_1 = graph.insertOperation(&addOneDescr, op1, NULL, op2, NULL);
op1_1->confirmOperation();
GraphNode* op1_2 = graph.insertOperation(&addOneDescr, op1, NULL, op1_1, NULL);
op1_2->confirmOperation();
// it is necessary to call recalculate when the node was inserted between existing nodes.
op1_2->recalculate();
graph.join();
// the content should be 129 everywhere
cout << "Content of the previous node after inserting two new \"add one\"" << endl;
cout << "nodes after the \"add one\" node" << endl;
switch(format.format()) {
#define FORMAT_DO_STH(T,U) printTileContent(static_cast<ImageBuffer<T>*>(op2->getBuffer()));
case_ANY;
#undef FORMAT_DO_STH
}
cout << endl;
}