/* -*- mona-c++ -*-
* Copyright (c) Leipzig, Madrid 2004 - 2008
* Max-Planck-Institute for Human Cognitive and Brain Science
* Max-Planck-Institute for Evolutionary Anthropology
* BIT, ETSI Telecomunicacion, UPM
*
* This program is free software; you can redistribute it and/or modify
* it 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.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <memory>
#include <vector>
#include <numeric>
#include <libmona/filter_plugin2d.hh>
#include <libmona/2DImageWrap.hh>
#include <libmona/monaPopt.hh>
#include <libmona/monaException.hh>
#include <libmona/monaHistory.hh>
using namespace mona;
using namespace std;
struct logical_xor : public binary_function<bool, bool, bool> {
bool operator ()(bool a, bool b) const{
return (a || b) && (!(a && b));
}
};
struct set_sub : public binary_function<bool, bool, bool> {
bool operator ()(bool a, bool b) const{
return a && !b;
}
};
template <typename F>
C2DImageWrap combine_image(const C2DBitImage& image_1, const C2DBitImage& image_2, F f)
{
if (image_1.get_size() != image_2.get_size())
throw invalid_argument("input images need to be of the same size");
C2DBitImage *result = new C2DBitImage(image_1.get_size());
transform(image_1.begin(), image_1.end(), image_2.begin(), result->begin(), f);
return C2DImageWrap(result);
}
int main(int argc, const char *argv[])
{
string a_filename;
string b_filename;
string out_filename;
string out_type;
int binop;
enum EOps {op_and, op_or, op_xor, op_nand, op_nor, op_nxor, op_sub};
const popt::option::Dictionary combine_option[] = {
{"and", op_and},
{"or", op_or},
{"xor", op_xor},
{"nand", op_nand},
{"nor", op_nor},
{"nxor", op_nxor},
{"sub", op_sub},
{NULL, 0},
};
try {
C2DImageIOPluginHandler imageio;
popt::COptions options;
options.push_back(popt::option( a_filename, "file1", '1', "input image 1", NULL ));
options.push_back(popt::option( b_filename, "file2", '2', "input image 2", NULL ));
options.push_back(popt::option( out_filename, "out-file", 'o', "combined image", NULL ));
options.push_back(popt::option( binop, combine_option, "op", 'p', "combine operator", "and"));
options.push_back(popt::option( out_type, imageio.get_set(), "type", 't',"output file type" , NULL));
vector<string> unknown_opts;
popt::parse_options(argc, argv, options, unknown_opts);
if (!unknown_opts.empty())
throw mona_fatal_error("Unknown options given");
if (a_filename.empty() || b_filename.empty() ||out_filename.empty())
throw mona_fatal_error("2 input files and an output file required");
auto_ptr<C2DImageList> image_list_1(imageio.load(a_filename));
if (!image_list_1.get() || image_list_1->empty())
throw mona_fatal_error(string("No images found in ") + a_filename);
auto_ptr<C2DImageList> image_list_2(imageio.load(b_filename));
if (!image_list_2.get() || image_list_2->empty())
throw mona_fatal_error(string("No images found in ") + b_filename);
C2DBitImage *image_1 = image_list_1->begin()->getC2DBitImage();
if (!image_1)
throw invalid_argument("Input image 1 needs to be in bit representation");
C2DBitImage *image_2 = image_list_2->begin()->getC2DBitImage();
if (!image_2)
throw invalid_argument("Input image 2 needs to be in bit representation");
if (out_type.empty())
out_type = image_list_1->get_sourceformat();
C2DImageList out_list;
switch (binop) {
case op_and: out_list.push_back(combine_image(*image_1, *image_2, logical_and<bool>())); break;
case op_or: out_list.push_back(combine_image(*image_1, *image_2, logical_or<bool>())); break;
case op_xor: out_list.push_back(combine_image(*image_1, *image_2, logical_xor())); break;
case op_nand:out_list.push_back(combine_image(*image_1, *image_2, not2(logical_and<bool>()))); break;
case op_nor: out_list.push_back(combine_image(*image_1, *image_2, not2(logical_or<bool>()))); break;
case op_nxor:out_list.push_back(combine_image(*image_1, *image_2, not2(logical_xor()))); break;
case op_sub: out_list.push_back(combine_image(*image_1, *image_2, set_sub())); break;
default:
throw invalid_argument("operation not supported");
}
if ( !imageio.save(out_type, out_list, out_filename) ){
string not_save = ("unable to save result to ") + out_filename;
throw mona_runtime_error(not_save);
};
return EXIT_SUCCESS;
}
catch (const mona_runtime_error& e){
cverr() << argv[0] << " error: " << e.what() << endl;
}
catch (const mona_fatal_error& e){
cverr() << argv[0] << " fatal: " << e.what() << endl;
}
catch (const mona_exception& e){
cverr() << argv[0] << " error: " << e.what() << endl;
}
catch (const invalid_argument &e){
cverr() << argv[0] << " error: " << e.what() << endl;
}
catch (const exception& e){
cverr() << argv[0] << " error: " << e.what() << endl;
}
catch (...){
cverr() << argv[0] << " unknown exception" << endl;
}
return EXIT_FAILURE;
}