25 #include <Utils/Param.hh>
26 #include <Base/Image/ImageBase.hh>
27 #include <Base/Image/ImageIO.hh>
28 #include <Base/Image/ImageConvert.hh>
30 #include <Base/ImageUtils/ImageCalc.hh>
46 #define OP_ADD_SCALAR 9
47 #define OP_SUBTRACT_SCALAR 10
48 #define OP_MULTIPLY_SCALAR 11
49 #define OP_DIVIDE_SCALAR 12
73 bool LoadImage(
const string &filename,
ImageBase &image,
74 const bool *floatOutput) {
75 if (filename.empty()) {
76 cerr <<
"ERROR: please specify an input image. try '-h' for help"
85 if (ImageIO::Load(filename, tempIm)!= 0) {
86 cerr <<
"ERROR: image (" << filename <<
") could not be loaded"
91 ImageConvert::ConvertST(tempIm, image, ImageBase::ST_float);
94 if (ImageIO::Load(filename, image)!= 0) {
95 cerr <<
"ERROR: image (" << filename <<
") could not be loaded"
124 bool CalculateOnTwoImages(
string *imagesInPath[2],
const string *output,
125 const int *operation,
126 const bool *floatOutput) {
131 if (!LoadImage(*imagesInPath[0], imagesIn[0], floatOutput)) {
135 if (!LoadImage(*imagesInPath[1], imagesIn[1], floatOutput)) {
140 BIASASSERT( imagesIn[0].GetWidth() == imagesIn[1].GetWidth()
141 && imagesIn[0].GetHeight() == imagesIn[1].GetHeight()
142 && imagesIn[0].GetChannelCount() == imagesIn[1].GetChannelCount())
145 if (imagesIn[0].GetStorageType() != imagesIn[1].GetStorageType()) {
146 cout <<
"ERROR: input images must have same storage type" << endl;
151 imageOut.
Init(imagesIn[0].GetWidth(), imagesIn[0].GetHeight(),
152 imagesIn[0].GetChannelCount(), imagesIn[0].GetStorageType());
155 switch (*operation) {
157 switch (imagesIn[0].GetStorageType()) {
158 case ImageBase::ST_unsignedchar:
163 case ImageBase::ST_float:
169 cout <<
"ERROR: operation not implemented for this storage type" << endl;
174 switch (imagesIn[0].GetStorageType()) {
175 case ImageBase::ST_unsignedchar:
180 case ImageBase::ST_float:
186 cout <<
"ERROR: operation not implemented for this storage type" << endl;
191 switch (imagesIn[0].GetStorageType()) {
192 case ImageBase::ST_unsignedchar:
197 case ImageBase::ST_float:
203 cout <<
"ERROR: operation not implemented for this storage type" << endl;
208 switch (imagesIn[0].GetStorageType()) {
209 case ImageBase::ST_unsignedchar:
214 case ImageBase::ST_float:
220 cout <<
"ERROR: operation not implemented for this storage type" << endl;
225 switch (imagesIn[0].GetStorageType()) {
226 case ImageBase::ST_unsignedchar:
231 case ImageBase::ST_float:
237 cout <<
"ERROR: operation not implemented for this storage type" << endl;
242 switch (imagesIn[0].GetStorageType()) {
243 case ImageBase::ST_unsignedchar:
248 case ImageBase::ST_float:
254 cout <<
"ERROR: operation not implemented for this storage type" << endl;
259 switch (imagesIn[0].GetStorageType()) {
260 case ImageBase::ST_unsignedchar:
265 case ImageBase::ST_float:
271 cout <<
"ERROR: operation not implemented for this storage type" << endl;
276 switch (imagesIn[0].GetStorageType()) {
277 case ImageBase::ST_unsignedchar:
282 case ImageBase::ST_float:
288 cout <<
"ERROR: operation not implemented for this storage type" << endl;
293 switch (imagesIn[0].GetStorageType()) {
294 case ImageBase::ST_unsignedchar:
299 case ImageBase::ST_float:
305 cout <<
"ERROR: operation not implemented for this storage type" << endl;
312 ImageIO::Save(*output, imageOut);
340 bool CalculateOnOneImageAndScalar(
const string *imageInPath,
341 const double *scalar,
342 const string *output,
343 const int *operation,
344 const bool *floatOutput) {
349 if (!LoadImage(*imageInPath, imageIn, floatOutput)) {
358 switch (*operation) {
361 case ImageBase::ST_unsignedchar:
363 (
unsigned char)*scalar,
366 case ImageBase::ST_float:
372 cout <<
"ERROR: operation not implemented for this storage type" << endl;
376 case OP_SUBTRACT_SCALAR:
378 case ImageBase::ST_unsignedchar:
380 (
unsigned char)*scalar,
383 case ImageBase::ST_float:
389 cout <<
"ERROR: operation not implemented for this storage type" << endl;
393 case OP_MULTIPLY_SCALAR:
395 case ImageBase::ST_unsignedchar:
397 (
unsigned char)*scalar,
400 case ImageBase::ST_float:
406 cout <<
"ERROR: operation not implemented for this storage type" << endl;
410 case OP_DIVIDE_SCALAR:
414 cout <<
"ERROR: the scalar must not be 0" << endl;
418 case ImageBase::ST_unsignedchar:
420 (
unsigned char)*scalar,
423 case ImageBase::ST_float:
429 cout <<
"ERROR: operation not implemented for this storage type" << endl;
436 ImageIO::Save(*output, imageOut);
461 bool CalculateOnOneImage(
const string *imageInPath,
462 const string *output,
463 const int *operation,
464 const bool *floatOutput) {
469 if (!LoadImage(*imageInPath, imageIn, floatOutput)) {
478 switch (*operation) {
481 case ImageBase::ST_unsignedchar:
485 case ImageBase::ST_float:
490 cout <<
"ERROR: operation not implemented for this storage type" << endl;
496 case ImageBase::ST_unsignedchar:
500 case ImageBase::ST_float:
505 cout <<
"ERROR: operation not implemented for this storage type" << endl;
512 ImageIO::Save(*output, imageOut);
526 int main(
int argc,
char *argv[]) {
531 "print help information and exit",
536 string *imagesInPath[2];
538 "path to the first output image (mandatory for all operations)",
543 "path to the second output image (must have same size and storage type as first input image)",
548 "the scalar value (will be cast to the storage type of the input image)",
555 "path to the output image (default: out.mip)"
556 " will be initialised with same storage type and size as first input image"
557 " (except if param '--float' is set)",
563 "convert input images to float and perform the operations on these float images. output image will be of type float as well.",
569 vector<string> operations(NUM_OPS);
572 operations[OP_ADD] =
"add";
573 operations[OP_SUBTRACT] =
"subtract";
574 operations[OP_MULTIPLY] =
"multiply";
575 operations[OP_DIVIDE] =
"divide";
576 operations[OP_AND] =
"and";
577 operations[OP_NAND] =
"nand";
578 operations[OP_OR] =
"or";
579 operations[OP_NOR] =
"nor";
580 operations[OP_XOR] =
"xor";
582 operations[OP_ADD_SCALAR] =
"addScalar";
583 operations[OP_SUBTRACT_SCALAR] =
"subtractScalar";
584 operations[OP_MULTIPLY_SCALAR] =
"multiplyScalar";
585 operations[OP_DIVIDE_SCALAR] =
"divideScalar";
587 operations[OP_LOG] =
"log";
588 operations[OP_LOG10] =
"log10";
592 "the arithmetic operation to perform.\n"
593 "\toperations that require TWO IMAGES:\n"
594 "\t- add: computes the pixelwise sum\n"
595 "\t- subtract: computes the pixelwise difference\n"
596 "\t- multiply: computes the pixelwise product\n"
597 "\t- divide: computes the pixelwise quotient\n"
598 "\t- and: computes the pixelwise AND\n"
599 "\t- nand: computes the pixelwise NAND\n"
600 "\t- or: computes the pixelwise OR\n"
601 "\t- nor: computes the pixelwise NOR\n"
602 "\t- xor: computes the pixelwise XOR\n"
603 "\toperations that require ONE IMAGE AND A SCALAR:\n"
604 "\t- addScalar: adds the scalar to each pixel\n"
605 "\t- subtractScalar: subtracts the scalar from each pixel\n"
606 "\t- multiplyScalar: multiplies the scalar with each pixel\n"
607 "\t- divideScalar: divides each pixel by the scalar\n"
608 "\toperations that require ONE IMAGE:\n"
609 "\t- log: computes the natural logarithm (base e) for each pixel\n"
610 "\t- log10: computes the common logarithm (base 10) for each pixel",
624 <<
"This tool performs pixelwise calculations on images."
627 cout <<
"Examples:" << endl
628 <<
"\tbiasimagecalc -i im1.jpg -j im2.jpg -p add -o sum.jpg" << endl
629 <<
"\tbiasimagecalc -i im.mip -s 2 -p multiply -o product.mip" << endl
630 <<
"\tbiasimagecalc -i im.mip -p log -o logarithm.mip" << endl
636 switch (*operation) {
646 CalculateOnTwoImages(imagesInPath, output, operation, floatOutput);
649 case OP_SUBTRACT_SCALAR:
650 case OP_MULTIPLY_SCALAR:
651 case OP_DIVIDE_SCALAR:
652 CalculateOnOneImageAndScalar(imagesInPath[0], scalar,
654 operation, floatOutput);
658 CalculateOnOneImage(imagesInPath[0], output, operation, floatOutput);
661 cout <<
"ERROR: operation not specified or unknown. try '-h' for help" << endl;
bool * AddParamBool(const std::string &name, const std::string &help, bool deflt=false, char cmdshort=0, int Group=GRP_NOSHOW)
double * AddParamDouble(const std::string &name, const std::string &help, double deflt=0.0, double min=-DBL_MAX, double max=DBL_MAX, char cmdshort=0, int Group=GRP_NOSHOW)
int * AddParamEnum(const std::string &name, const std::string &help, const std::vector< std::string > &enums, const int deflt=0, const std::vector< int > *IDs=NULL, const char cmdshort=0, const int Group=GRP_NOSHOW)
unsigned int GetWidth() const
int ParseCommandLine(int &argc, char *argv[])
scan command line arguments for valid parameters
void Usage(std::ostream &os=std::cout)
print Help-Information to stdout
Performs pixelwise arithmetic and boolean operations on images.
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
unsigned int GetHeight() const
This class Param provides generic support for parameters.
int SetGroupName(const int group_id, const std::string &name)
sets the name for a group
void Init(unsigned int width, unsigned int height, unsigned int nChannels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
Initialize image size and channels.
enum EStorageType GetStorageType() const
This is the base class for images in BIAS.
std::string * AddParamString(const std::string &name, const std::string &help, std::string deflt="", char cmdshort=0, int Group=GRP_NOSHOW)