From 571d610fb59e45477403a5b7be0988b3d452896a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sacha=20Percot-T=C3=A9tu?= <zakinster@zakinster.com>
Date: Tue, 17 Jul 2012 13:05:20 +0200
Subject: [PATCH] Improved the point op to handle double image

---
 app/Operations/PointOp.cpp | 287 +++++++++++++++++++++++++++++--------
 app/Operations/PointOp.h   |  61 ++++++--
 2 files changed, 281 insertions(+), 67 deletions(-)

diff --git a/app/Operations/PointOp.cpp b/app/Operations/PointOp.cpp
index 580e8ef..1ebd168 100644
--- a/app/Operations/PointOp.cpp
+++ b/app/Operations/PointOp.cpp
@@ -32,11 +32,14 @@
 #include "PointOp.h"
 #include "ImgWidget.h"
 #include "ImageListBox.h"
+#include "Widgets/ImageWidgets/StandardImageWindow.h"
+#include "Widgets/ImageWidgets/DoubleImageWindow.h"
 
 #include "../Tools.h"
 
 using namespace std;
 using namespace imagein;
+using namespace genericinterface;
 
 PointOp::PointOp() : Operation("Pixel operations") {
     
@@ -56,6 +59,15 @@ PointOp::PixelOp* PointOp::PixelOp::fromString(QString op, QString expr) {
     std::cout << "Unknown operator '" << op.toStdString() << "' !" << std::endl;
     return new PixIdent();
 }
+PointOp::DoublePixelOp* PointOp::DoublePixelOp::fromString(QString op, QString expr) {
+    if(op=="+") return new DoublePixAdd(expr.toDouble());
+    if(op=="-") return new DoublePixAdd(-expr.toDouble());
+    if(op=="*") return new DoublePixMul(expr.toDouble());
+    if(op=="/") return new DoublePixMul(1/expr.toDouble());
+    if(op=="") return new DoublePixIdent();
+    std::cout << "Unknown operator '" << op.toStdString() << "' !" << std::endl;
+    return new DoublePixIdent();
+}
 
 PointOp::ImageOp* PointOp::ImageOp::fromString(QString op) {
     if(op=="+") return new ImgAdd();
@@ -67,13 +79,36 @@ PointOp::ImageOp* PointOp::ImageOp::fromString(QString op) {
     std::cout << "Unknown operator '" << op.toStdString() << "' !" << std::endl;
     return new ImgIdent();
 }
+PointOp::DoubleImageOp* PointOp::DoubleImageOp::fromString(QString op) {
+    if(op=="+") return new DoubleImgAdd();
+    if(op=="-") return new DoubleImgSub();
+    if(op=="*") return new DoubleImgMul();
+    if(op=="/") return new DoubleImgDiv();
+    if(op=="") return new DoubleImgIdent();
+    std::cout << "Unknown operator '" << op.toStdString() << "' !" << std::endl;
+    return new DoubleImgIdent();
+}
 
-void PointOp::operator()(const imagein::Image* image, const std::map<const imagein::Image*, std::string>& imgList) {
+void PointOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>& wndList) {
 
     QStringList pixOperators, imgOperators;
+
     pixOperators << "" << "+" << "-" << "*" << "/" << "&" << "|" << "^" << "<<" << ">>";
-    imgOperators << "" << "+" << "-" << "&" << "|" << "^";
-    QString currentImgName = QString(imgList.find(image)->second.c_str());
+    imgOperators << "" << "+" << "-" << "*" << "/" << "&" << "|" << "^";
+    QString currentImgName = currentWnd->windowTitle();
+    map<const Image*,string> stdImgList;
+    map<const Image_t<double>*,string> dblImgList;
+    for(vector<ImageWindow*>::iterator it = wndList.begin(); it != wndList.end(); ++it) {
+        if((*it)->isStandard()) {
+            const StandardImageWindow* stdImgWnd = dynamic_cast<const StandardImageWindow*>(*it);
+            stdImgList.insert(pair<const Image*, string>(stdImgWnd->getImage(), stdImgWnd->windowTitle().toStdString()));
+        }
+        else if((*it)->isDouble()) {
+            const DoubleImageWindow* dblImgWnd = dynamic_cast<const DoubleImageWindow*>(*it);
+            dblImgList.insert(pair<const Image_t<double>*, string>(dblImgWnd->getImage(), dblImgWnd->windowTitle().toStdString()));
+        }
+    }
+
     
     QDialog* dialog = new QDialog();
     dialog->setWindowTitle(dialog->tr("Parameter"));
@@ -93,22 +128,23 @@ void PointOp::operator()(const imagein::Image* image, const std::map<const image
     QCheckBox* colorBox = new QCheckBox("Explode colors", dialog);
     layout->addWidget(colorBox);
 
-    int nChannel = image->getNbChannels();
+    int nChannel = currentWnd->getDisplayImage()->getNbChannels();
+
     QHBoxLayout** valueLayouts = new QHBoxLayout*[nChannel+1];
     QComboBox** pixOperatorBoxes = new QComboBox*[nChannel+1];
     QComboBox** imgOperatorBoxes = new QComboBox*[nChannel+1];
     QLineEdit** exprEdits = new QLineEdit*[nChannel+1];
-    ImageListBox** imageBoxes = new ImageListBox*[nChannel+1];
+    MixImageListBox** imageBoxes = new MixImageListBox*[nChannel+1];
 
     QWidget* pixelWidget = new QWidget(dialog);
     valueLayouts[0] = new QHBoxLayout();
     pixOperatorBoxes[0] = new QComboBox(pixelWidget);
     imgOperatorBoxes[0] = new QComboBox(pixelWidget);
-    pixOperatorBoxes[0]->addItems(pixOperators); 
-    imgOperatorBoxes[0]->addItems(imgOperators); 
+    pixOperatorBoxes[0]->addItems(pixOperators);
+    imgOperatorBoxes[0]->addItems(imgOperators);
     exprEdits[0] = new QLineEdit(pixelWidget);
     exprEdits[0]->setFixedWidth(64);
-    imageBoxes[0] = new ImageListBox(pixelWidget, image, imgList);
+    imageBoxes[0] = new MixImageListBox(pixelWidget, currentImgName.toStdString(), stdImgList, dblImgList);
     valueLayouts[0]->addWidget(new QLabel(currentImgName, pixelWidget));
     valueLayouts[0]->addWidget(pixOperatorBoxes[0]);
     valueLayouts[0]->addWidget(imgOperatorBoxes[0]);
@@ -125,11 +161,11 @@ void PointOp::operator()(const imagein::Image* image, const std::map<const image
         valueLayouts[i] = new QHBoxLayout();
         pixOperatorBoxes[i] = new QComboBox(colorWidget);
         imgOperatorBoxes[i] = new QComboBox(colorWidget);
-        pixOperatorBoxes[i]->addItems(pixOperators); 
-        imgOperatorBoxes[i]->addItems(imgOperators); 
+        pixOperatorBoxes[i]->addItems(pixOperators);
+        imgOperatorBoxes[i]->addItems(imgOperators);
         exprEdits[i] = new QLineEdit(colorWidget);
         exprEdits[i]->setFixedWidth(64);
-        imageBoxes[i] = new ImageListBox(colorWidget, image, imgList);
+        imageBoxes[i] = new MixImageListBox(colorWidget, currentImgName.toStdString(), stdImgList, dblImgList);
         valueLayouts[i]->addWidget(new QLabel(currentImgName+"::"+Tools::colorName(i-1, nChannel), colorWidget));
         valueLayouts[i]->addWidget(pixOperatorBoxes[i]);
         valueLayouts[i]->addWidget(imgOperatorBoxes[i]);
@@ -164,69 +200,202 @@ void PointOp::operator()(const imagein::Image* image, const std::map<const image
         return;
     }
 
-    PixelOp** pixelOps = new PixelOp*[nChannel];
-    ImageOp** imageOps = new ImageOp*[nChannel];
-    const Image**  imageImgs = new const Image*[nChannel];
-    unsigned int maxWidth = image->getWidth();
-    unsigned int maxHeight = image->getHeight();
-    
-    if(!colorBox->isChecked()) {
-        QString expr = exprEdits[0]->text();
-        PixelOp* pixelOp = PixelOp::fromString(pixOperatorBoxes[0]->currentText(), expr);
-        ImageOp* imageOp = ImageOp::fromString(imgOperatorBoxes[0]->currentText());
-        const Image* imageImg = imageBoxes[0]->currentImage();
-        maxWidth = min(maxWidth, imageImg->getWidth());
-        maxHeight = min(maxHeight, imageImg->getHeight());
-        
-        for(int i=0; i<nChannel; ++i) {
-            pixelOps[i] = pixelOp;
-            imageOps[i] = imageOp;
-            imageImgs[i] = imageImg;
+    bool dblResult = currentWnd->isDouble();
+    if(!valueButton->isChecked()) {
+        if(!colorBox->isChecked()) {
+            dblResult = dblResult || (imageBoxes[0]->currentType() == MixImageListBox::DBLIMG);
         }
-    }
-    else {
-        for(int i=0; i<nChannel; ++i) {
-            QString expr = exprEdits[i+1]->text();
-            pixelOps[i] = PixelOp::fromString(pixOperatorBoxes[i+1]->currentText(), expr);
-            imageOps[i] = ImageOp::fromString(imgOperatorBoxes[i+1]->currentText());
-            imageImgs[i] = imageBoxes[i+1]->currentImage();
-            maxWidth = min(maxWidth, imageImgs[i]->getWidth());
-            maxHeight = min(maxHeight, imageImgs[i]->getHeight());
+        else {
+            for(int i=0; i<nChannel; ++i) {
+                dblResult = dblResult || (imageBoxes[i+1]->currentType() == MixImageListBox::DBLIMG);
+            }
         }
     }
 
-    Image* resImg;
-    
-    if(valueButton->isChecked()) {
-        resImg = new Image(image->getWidth(), image->getHeight(), nChannel);
-        for(int c = 0; c < nChannel; ++c) {
-            for(unsigned int j = 0; j < image->getHeight(); ++j) {
-                for(unsigned int i = 0; i < image->getWidth(); ++i) {
-                    Image::depth_t value = image->getPixel(i, j, c);
-                    value = pixelOps[c]->operator()(value);
-                    resImg->setPixel(i, j, c, value);
+    if(dblResult) {
+        const DoubleImageWindow* currentDblWnd = dynamic_cast<const DoubleImageWindow*>(currentWnd);
+        const Image_t<double>* image = currentDblWnd ? currentDblWnd->getImage() : NULL;
+        unsigned int maxWidth = image->getWidth();
+        unsigned int maxHeight = image->getHeight();
+
+
+        Image_t<double>* resImg;
+
+        if(valueButton->isChecked()) {
+            DoublePixelOp** pixelOps = new DoublePixelOp*[nChannel];
+            if(!colorBox->isChecked()) {
+                QString expr = exprEdits[0]->text();
+                DoublePixelOp* pixelOp = DoublePixelOp::fromString(pixOperatorBoxes[0]->currentText(), expr);
+                for(int i=0; i<nChannel; ++i) pixelOps[i] = pixelOp;
+            }
+            else {
+                for(int i=0; i<nChannel; ++i) {
+                    QString expr = exprEdits[i+1]->text();
+                    pixelOps[i] = DoublePixelOp::fromString(pixOperatorBoxes[i+1]->currentText(), expr);
+                }
+            }
+
+            resImg = new Image_t<double>(image->getWidth(), image->getHeight(), nChannel);
+            for(int c = 0; c < nChannel; ++c) {
+                for(unsigned int j = 0; j < image->getHeight(); ++j) {
+                    for(unsigned int i = 0; i < image->getWidth(); ++i) {
+                        double value = image->getPixel(i, j, c);
+                        value = pixelOps[c]->operator()(value);
+                        resImg->setPixel(i, j, c, value);
+                    }
                 }
             }
         }
+        else {
+            DoubleImageOp** imageOps = new DoubleImageOp*[nChannel];
+            bool isDblImg[nChannel];
+            const Image_t<double>* dblImageImgs[nChannel];
+            const Image* stdImageImgs[nChannel];
+            if(!colorBox->isChecked()) {
+                DoubleImageOp* imageOp = DoubleImageOp::fromString(imgOperatorBoxes[0]->currentText());
+                for(int i=0; i<nChannel; ++i) imageOps[i] = imageOp;
+                if(imageBoxes[0]->currentType() == MixImageListBox::DBLIMG) {
+                    const Image_t<double>* imageImg = imageBoxes[0]->getDblImage(imageBoxes[0]->currentText().toStdString());
+                    for(int i=0; i<nChannel; ++i) {
+                        dblImageImgs[i] = imageImg;
+                        isDblImg[i] = true;
+                    }
+                    maxWidth = min(maxWidth, imageImg->getWidth());
+                    maxHeight = min(maxHeight, imageImg->getHeight());
+                }
+                else {
+                    const Image* imageImg = imageBoxes[0]->getStdImage(imageBoxes[0]->currentText().toStdString());
+                    for(int i=0; i<nChannel; ++i) {
+                        stdImageImgs[i] = imageImg;
+                        isDblImg[i] = false;
+                    }
+                    maxWidth = min(maxWidth, imageImg->getWidth());
+                    maxHeight = min(maxHeight, imageImg->getHeight());
+                }
+
+            }
+            else {
+                for(int i=0; i<nChannel; ++i) {
+                    imageOps[i] = DoubleImageOp::fromString(imgOperatorBoxes[i+1]->currentText());
+                    if(imageBoxes[i+1]->currentType() == MixImageListBox::DBLIMG) {
+                        const Image_t<double>* imageImg = imageBoxes[i+1]->getDblImage(imageBoxes[i+1]->currentText().toStdString());
+                        for(int i=0; i<nChannel; ++i) {
+                            dblImageImgs[i] = imageImg;
+                            isDblImg[i] = true;
+                        }
+                        maxWidth = min(maxWidth, imageImg->getWidth());
+                        maxHeight = min(maxHeight, imageImg->getHeight());
+                    }
+                    else {
+                        const Image* imageImg = imageBoxes[i+1]->getStdImage(imageBoxes[i+1]->currentText().toStdString());
+                        for(int i=0; i<nChannel; ++i) {
+                            stdImageImgs[i] = imageImg;
+                            isDblImg[i] = false;
+                        }
+                        maxWidth = min(maxWidth, imageImg->getWidth());
+                        maxHeight = min(maxHeight, imageImg->getHeight());
+                    }
+                }
+            }
+            resImg = new Image_t<double>(maxWidth, maxHeight, nChannel);
+            for(int c = 0; c < resImg->getNbChannels(); ++c) {
+                for(unsigned int j = 0; j < resImg->getHeight(); ++j) {
+                    for(unsigned int i = 0; i < resImg->getWidth(); ++i) {
+                        double value1 = image->getPixel(i, j, c);
+                        double value2;
+                        if(isDblImg[c]) {
+                            const unsigned int channel = (c < dblImageImgs[c]->getNbChannels() ? c : 0);
+                            value2 = dblImageImgs[c]->getPixel(i, j, channel);
+                        }
+                        else {
+                            const unsigned int channel = (c < stdImageImgs[c]->getNbChannels() ? c : 0);
+                            value2 = stdImageImgs[c]->getPixel(i, j, channel);
+                        }
+                        value1 = imageOps[c]->operator()(value1, value2);
+                        resImg->setPixel(i, j, c, value1);
+                    }
+                }
+            }
+        }
+
+        this->outDoubleImage(resImg, "", currentDblWnd->isNormalized(), currentDblWnd->isLogScaled());
     }
     else {
-        resImg = new Image(maxWidth, maxHeight, nChannel);
-        for(int c = 0; c < resImg->getNbChannels(); ++c) {
-            for(unsigned int j = 0; j < resImg->getHeight(); ++j) {
-                for(unsigned int i = 0; i < resImg->getWidth(); ++i) {
-                    Image::depth_t value1 = image->getPixel(i, j, c);
-                    const unsigned int channel = (c < imageImgs[c]->getNbChannels() ? c : 0);
-                    Image::depth_t value2 = imageImgs[c]->getPixel(i, j, channel);
-                    value1 = imageOps[c]->operator()(value1, value2);
-                    resImg->setPixel(i, j, c, value1);
+        const Image* image = dynamic_cast<const StandardImageWindow*>(currentWnd)->getImage();
+        unsigned int maxWidth = image->getWidth();
+        unsigned int maxHeight = image->getHeight();
+
+
+        Image* resImg;
+
+        if(valueButton->isChecked()) {
+            PixelOp** pixelOps = new PixelOp*[nChannel];
+            if(!colorBox->isChecked()) {
+                QString expr = exprEdits[0]->text();
+                PixelOp* pixelOp = PixelOp::fromString(pixOperatorBoxes[0]->currentText(), expr);
+                for(int i=0; i<nChannel; ++i) pixelOps[i] = pixelOp;
+            }
+            else {
+                for(int i=0; i<nChannel; ++i) {
+                    QString expr = exprEdits[i+1]->text();
+                    pixelOps[i] = PixelOp::fromString(pixOperatorBoxes[i+1]->currentText(), expr);
+                }
+            }
+
+            resImg = new Image(image->getWidth(), image->getHeight(), nChannel);
+            for(int c = 0; c < nChannel; ++c) {
+                for(unsigned int j = 0; j < image->getHeight(); ++j) {
+                    for(unsigned int i = 0; i < image->getWidth(); ++i) {
+                        Image::depth_t value = image->getPixel(i, j, c);
+                        value = pixelOps[c]->operator()(value);
+                        resImg->setPixel(i, j, c, value);
+                    }
+                }
+            }
+        }
+        else {
+            ImageOp** imageOps = new ImageOp*[nChannel];
+            const Image**  imageImgs = new const Image*[nChannel];
+            if(!colorBox->isChecked()) {
+                ImageOp* imageOp = ImageOp::fromString(imgOperatorBoxes[0]->currentText());
+                const Image* imageImg = imageBoxes[0]->getStdImage(imageBoxes[0]->currentText().toStdString());
+                maxWidth = min(maxWidth, imageImg->getWidth());
+                maxHeight = min(maxHeight, imageImg->getHeight());
+                for(int i=0; i<nChannel; ++i) {
+                    imageOps[i] = imageOp;
+                    imageImgs[i] = imageImg;
+                }
+            }
+            else {
+                for(int i=0; i<nChannel; ++i) {
+                    imageOps[i] = ImageOp::fromString(imgOperatorBoxes[i+1]->currentText());
+                    imageImgs[i] = imageBoxes[i+1]->getStdImage(imageBoxes[i+1]->currentText().toStdString());
+                    maxWidth = min(maxWidth, imageImgs[i]->getWidth());
+                    maxHeight = min(maxHeight, imageImgs[i]->getHeight());
+                }
+            }
+            resImg = new Image(maxWidth, maxHeight, nChannel);
+            for(int c = 0; c < resImg->getNbChannels(); ++c) {
+                for(unsigned int j = 0; j < resImg->getHeight(); ++j) {
+                    for(unsigned int i = 0; i < resImg->getWidth(); ++i) {
+                        Image::depth_t value1 = image->getPixel(i, j, c);
+                        const unsigned int channel = (c < imageImgs[c]->getNbChannels() ? c : 0);
+                        Image::depth_t value2 = imageImgs[c]->getPixel(i, j, channel);
+                        value1 = imageOps[c]->operator()(value1, value2);
+                        resImg->setPixel(i, j, c, value1);
+                    }
                 }
             }
         }
-    }
 
-    this->outImage(resImg);
+        this->outImage(resImg);
+    }
 }
 
 bool PointOp::needCurrentImg() const {
     return true;
 }
+
+bool PointOp::isValidImgWnd(const genericinterface::ImageWindow*) const {
+    return true;
+}
diff --git a/app/Operations/PointOp.h b/app/Operations/PointOp.h
index a40978d..ffe4a8f 100644
--- a/app/Operations/PointOp.h
+++ b/app/Operations/PointOp.h
@@ -30,15 +30,16 @@
 
 class QWidget;
 
-class PointOp : public Operation {
+class PointOp : public GenericOperation {
 
   public:
 
     PointOp();
 
-    void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&);
+    virtual void operator()(const genericinterface::ImageWindow* currentWnd, std::vector<genericinterface::ImageWindow*>&);
 
     bool needCurrentImg() const;
+    virtual bool isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const;
 
   private:
     typedef imagein::Image::depth_t depth_t;
@@ -58,11 +59,24 @@ class PointOp : public Operation {
         virtual intmax_t op(depth_t pixel) = 0;
         static PixelOp* fromString(QString op, QString expr);
     };
-    
+    struct DoublePixelOp {
+        DoublePixelOp(double value_ = 0) : value(value_) {}
+        virtual double operator()(double pixel) {
+            return this->op(pixel);
+        }
+        virtual double op(double pixel) = 0;
+        static DoublePixelOp* fromString(QString op, QString expr);
+        double value;
+    };
+
     struct PixIdent : PixelOp {
         intmax_t op(depth_t pixel) { return pixel; }
     };
 
+    struct DoublePixIdent : DoublePixelOp {
+        double op(double pixel) { return pixel; }
+    };
+
     template<typename T>
     struct PixOp_t : public PixelOp {
         PixOp_t(T value_) : value(value_) {}
@@ -73,10 +87,18 @@ class PointOp : public Operation {
         PixAdd(int value_) : PixOp_t(value_) {}
         intmax_t op(depth_t pixel) { return pixel + value; }
     };
+    struct DoublePixAdd : DoublePixelOp {
+        DoublePixAdd(double value_) : DoublePixelOp(value_) {}
+        double op(double pixel) { return pixel + value; }
+    };
 
     struct PixMul : PixOp_t<double> {
         PixMul(double value_) : PixOp_t(value_) {}
-        intmax_t op(depth_t pixel) { return pixel * value; }
+        intmax_t op(depth_t pixel) { return pixel * value + 0.5; }
+    };
+    struct DoublePixMul : DoublePixelOp {
+        DoublePixMul(double value_) : DoublePixelOp(value_) {}
+        double op(double pixel) { return pixel * value; }
     };
 
     struct PixAnd : PixOp_t<depth_t> {
@@ -111,19 +133,42 @@ class PointOp : public Operation {
         virtual intmax_t op(depth_t pixel1, depth_t pixel2) = 0;
         static ImageOp* fromString(QString op);
     };
-    
+
+    struct DoubleImageOp {
+        virtual double operator()(double pixel1, double pixel2) {
+            return this->op(pixel1, pixel2);
+        }
+        virtual double op(double pixel1, double pixel2) = 0;
+        static DoubleImageOp* fromString(QString op);
+    };
+
     struct ImgIdent : ImageOp {
         intmax_t op(depth_t pix1, depth_t pix2) { return pix1; } 
     };
-   
+    struct DoubleImgIdent : DoubleImageOp {
+        double op(double pix1, double pix2) { return pix1; }
+    };
+
     struct ImgAdd : ImageOp {
         intmax_t op(depth_t pix1, depth_t pix2) { return pix1 + pix2; } 
     };
-    
+    struct DoubleImgAdd : DoubleImageOp {
+        double op(double pix1, double pix2) { return pix1 + pix2; }
+    };
+
     struct ImgSub : ImageOp {
         intmax_t op(depth_t pix1, depth_t pix2) { return pix1 - pix2; } 
     };
-    
+    struct DoubleImgSub : DoubleImageOp {
+        double op(double pix1, double pix2) { return pix1 - pix2; }
+    };
+    struct DoubleImgMul : DoubleImageOp {
+        double op(double pix1, double pix2) { return pix1 * pix2; }
+    };
+    struct DoubleImgDiv : DoubleImageOp {
+        double op(double pix1, double pix2) { return pix1 / pix2; }
+    };
+
     struct ImgAnd : ImageOp {
         intmax_t op(depth_t pix1, depth_t pix2) { return pix1 & pix2; } 
     };
-- 
GitLab