Qt编程:ImagePlay中的IPLProcessProperty类

IPLProcessProperty 是 ImagePlay 框架中用于处理图像处理算法属性的基类系统。它提供了一套完整的属性管理机制,支持多种数据类型和 GUI 控件类型。

主要功能

  1. 属性管理:为图像处理算法提供可配置的参数

  2. 序列化/反序列化:支持属性的保存和加载

  3. GUI 集成:与用户界面控件绑定

  4. 事件通知:属性变化时通知相关组件

//#############################################################################
//
//  This file is part of ImagePlay.
//
//  ImagePlay 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 3 of the License, or
//  (at your option) any later version.
//
//  ImagePlay 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 ImagePlay.  If not, see <http://www.gnu.org/licenses/>.
//
//#############################################################################

#ifndef IPLPROCESSPROPERTY_H
#define IPLPROCESSPROPERTY_H

#include "IPLProcess.h"
#include "IPLColor.h"
#include "IPLPoint.h"

#include <cstring>
#include <string>
#include <map>
#include <sstream>
#include <vector>
#include <memory>

class IPLProcess;


// we need a base class in order to use the template in std::map
class IPLSHARED_EXPORT IPLProcessProperty
{
public:
    struct SerializedData
    {
        std::string type;
        std::string widget;
        std::string widgetName;
        std::string value;
    };

    struct DeserialationFailed : public std::runtime_error
    { DeserialationFailed(): std::runtime_error("") {} };

    int position() const                  { return _position; }
    const char* name() const              { return _name; }
    const char* title() const             { return _title; }
    const char* description() const       { return _description; }
    IPLProcessWidgetType widget() const   { return _widget; }
    virtual const char* type() const = 0;
    virtual SerializedData serialize() const = 0;
    virtual void deserialize(const SerializedData &data) = 0;
    virtual IPLProcessProperty *clone() const = 0;
    virtual void resetValue() = 0;

protected:
    IPLProcessProperty(int position,
                       const char *name,
                       const char *title,
                       const char *description,
                       IPLProcess *process,
                       IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT);

    int _position;                  //!< Position in GUI
    const char* _name;              //!< ID for GUI
    const char* _title;             //!< Short title for GUI
    const char* _description;       //!< Short help for GUI
    IPLProcess*  _process;
    IPLProcessWidgetType _widget;
};


// templates are not possible because of serialization issues

// INT
class IPLSHARED_EXPORT IPLProcessPropertyInt : public IPLProcessProperty
{
public:
    IPLProcessPropertyInt(IPLProcess* process, int position, const char* name, const char* title, const char* description, int value, IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT, int min=0, int max=0);

    int min() const                         { return _min; }
    int max() const                         { return _max; }
    int value() const                       { return _value; }
    void setValue(int value);
    void resetValue()                       { setValue(_default); }
    virtual const char *type() const        { return "int"; }
    virtual SerializedData serialize() const;
    virtual void deserialize(const SerializedData &data);
    IPLProcessProperty *clone() const;

private:
    int _min;                         //!< min value, may be used in GUI
    int _max;                         //!< max value, may be used in GUI
    int _value;                       //!< current value
    int _default;                     //!< default value
};

// UNSIGNED INT
class IPLSHARED_EXPORT IPLProcessPropertyUnsignedInt: public IPLProcessProperty
{
public:
    IPLProcessPropertyUnsignedInt(IPLProcess* process, int position, const char* name, const char* title, const char* description, unsigned int value, IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT, unsigned int min=0, unsigned int max=0);

    unsigned int min() const                         { return _min; }
    unsigned int max() const                         { return _max; }
    unsigned int value() const                       { return _value; }
    void setValue(unsigned int value);
    void resetValue()                                { setValue(_default); }
    virtual const char *type() const                 { return "uint"; }
    virtual SerializedData serialize() const;
    virtual void deserialize(const SerializedData &data);
    IPLProcessProperty *clone() const;

private:
    unsigned int _min;                         //!< min value, may be used in GUI
    unsigned int _max;                         //!< max value, may be used in GUI
    unsigned int _value;                       //!< current value
    unsigned int _default;                     //!< default value
};

// DOUBLE
class IPLSHARED_EXPORT IPLProcessPropertyDouble : public IPLProcessProperty
{
public:
    IPLProcessPropertyDouble(IPLProcess* process, int position, const char* name, const char* title, const char* description, double value, IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT, double min=0.0, double max=0.0);

    double min() const                         { return _min; }
    double max() const                         { return _max; }
    double value() const                       { return _value; }
    void setValue(double value);
    void resetValue()                          { setValue(_default); }
    virtual const char *type() const           { return "double"; }
    virtual SerializedData serialize() const;
    virtual void deserialize(const SerializedData &data);
    IPLProcessProperty *clone() const;

private:
    double _min;                         //!< min value, may be used in GUI
    double _max;                         //!< max value, may be used in GUI
    double _value;                       //!< current value
    double _default;                     //!< default value
};

// DOUBLE
class IPLSHARED_EXPORT IPLProcessPropertyFloat : public IPLProcessProperty
{
public:
    IPLProcessPropertyFloat(IPLProcess* process, int position, const char* name, const char* title, const char* description, float value, IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT,  float min=0.0f, float max=0.0f);

    float min() const                         { return _min; }
    float max() const                         { return _max; }
    float value() const                       { return _value; }
    void setValue(float value);
    void resetValue()                         { setValue(_default); }
    virtual const char *type() const          { return "float"; }
    virtual SerializedData serialize() const;
    virtual void deserialize(const SerializedData &data);
    IPLProcessProperty *clone() const;

private:
    float _min;                         //!< min value, may be used in GUI
    float _max;                         //!< max value, may be used in GUI
    float _value;                       //!< current value
    float _default;                     //!< default value
};



// BOOL
class IPLSHARED_EXPORT IPLProcessPropertyBool : public IPLProcessProperty
{
public:
    IPLProcessPropertyBool(IPLProcess* process, int position, const char* name, const char* title, const char* description, bool value, IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT);

    bool value() const                       { return _value; }
    void setValue(bool value);
    void resetValue()                        { setValue(_default); }
    virtual const char *type() const         { return "bool"; }
    virtual SerializedData serialize() const;
    virtual void deserialize(const SerializedData &data);
    IPLProcessProperty *clone() const;

protected:
    bool _value;                       //!< current value
    bool _default;                     //!< default value
};

// BOOL ONE SHOT
class IPLSHARED_EXPORT IPLProcessPropertyBoolOneShot : public IPLProcessPropertyBool
{
public:
    IPLProcessPropertyBoolOneShot(IPLProcess* process, int position, const char* name, const char* title, const char* description, bool value, IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT);
    bool value()                             { bool ret = _value; _value = false; return ret; }
};

// STRING
class IPLSHARED_EXPORT IPLProcessPropertyString : public IPLProcessProperty
{
public:
    IPLProcessPropertyString(IPLProcess* process, int position, const char* name, const char* title, const char* description, const std::string &value, IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT);

    std::string value() const                       { return _value; }
    void setValue(const std::string &value);
    void setValue(std::string &&value);
    void resetValue()                               { setValue(_default); }
    virtual const char *type() const                { return "string"; }
    virtual SerializedData serialize() const;
    virtual void deserialize(const SerializedData &data);
    IPLProcessProperty *clone() const;

private:
    std::string _value;                       //!< current value
    std::string _default;                     //!< default value
};


// VECTOR<INT>
class IPLSHARED_EXPORT IPLProcessPropertyVectorInt : public IPLProcessProperty
{
public:
    IPLProcessPropertyVectorInt(IPLProcess* process, int position, const char* name, const char* title, const char* description, const std::vector<int> &value, IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT);

    const std::vector<int> &value() const                       { return _value; }
    void setValue(const std::vector<int> &value);
    void setValue(std::vector<int> &&value);
    void resetValue()                                           { setValue(_default); }
    virtual const char *type() const                            { return "vector<int>"; }
    virtual SerializedData serialize() const;
    virtual void deserialize(const SerializedData &data);
    IPLProcessProperty *clone() const;

private:
    std::vector<int> _value;                       //!< current value
    std::vector<int> _default;                     //!< default value
};

// VECTOR<DOUBLE>
class IPLSHARED_EXPORT IPLProcessPropertyVectorDouble : public IPLProcessProperty
{
public:
    IPLProcessPropertyVectorDouble(IPLProcess* process, int position, const char* name, const char* title, const char* description, const std::vector<double> &value, IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT);

    const std::vector<double> &value() const                    { return _value; }
    void setValue(const std::vector<double> &value);
    void setValue(std::vector<double> &&value);
    void resetValue()                                           { setValue(_default); }
    virtual const char *type() const                            { return "vector<double>"; }
    virtual SerializedData serialize() const;
    virtual void deserialize(const SerializedData &data);
    IPLProcessProperty *clone() const;

private:
    std::vector<double> _value;                       //!< current value
    std::vector<double> _default;                     //!< default value
};

// COLOR
class IPLSHARED_EXPORT IPLProcessPropertyColor : public IPLProcessProperty
{
public:
    IPLProcessPropertyColor(IPLProcess* process, int position, const char* name, const char* title, const char* description, const IPLColor &value, IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT);

    const IPLColor &value() const                       { return _value; }
    void setValue(const IPLColor &value);
    void setValue(IPLColor &&value);
    void resetValue()                                   { setValue(_default); }
    virtual const char *type() const                    { return "color"; }
    virtual SerializedData serialize() const;
    virtual void deserialize(const SerializedData &data);
    IPLProcessProperty *clone() const;

private:
    IPLColor _value;                       //!< current value
    IPLColor _default;                     //!< default value
};


// POINT
class IPLSHARED_EXPORT IPLProcessPropertyPoint : public IPLProcessProperty
{
public:
    IPLProcessPropertyPoint(IPLProcess* process, int position, const char* name, const char* title, const char* description, const IPLPoint &value, IPLProcessWidgetType widget = IPL_WIDGET_DEFAULT);

    const IPLPoint &value() const                       { return _value; }
    void setValue(const IPLPoint &value);
    void setValue(IPLPoint &&value);
    void resetValue()                                   { setValue(_default); }
    virtual const char *type() const                    { return "point"; }
    virtual SerializedData serialize() const;
    virtual void deserialize(const SerializedData &data);
    IPLProcessProperty *clone() const;

private:
    IPLPoint _value;                       //!< current value
    IPLPoint _default;                     //!< default value
};

//! IPLProcessPropertyMap
typedef std::map<std::string, std::shared_ptr<IPLProcessProperty>> IPLProcessPropertyMap;


#endif // IPLPROCESSPROPERTY_H
//#############################################################################
//
//  This file is part of ImagePlay.
//
//  ImagePlay 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 3 of the License, or
//  (at your option) any later version.
//
//  ImagePlay 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 ImagePlay.  If not, see <http://www.gnu.org/licenses/>.
//
//#############################################################################

#include "IPLProcessProperty.h"

#include <array>
#include <cctype>
#include <regex>

template<class T>
inline std::string serializeValue(const T &value)
{
    std::ostringstream buffer;
    buffer << value;
    return buffer.str();
}

template<>
inline std::string serializeValue<bool>(const bool &value)
{
    std::ostringstream buffer;
    buffer <<  (value ? "true" : "false");
    return buffer.str();
}

template<>
inline std::string serializeValue<std::vector<int>>(const std::vector<int> &value)
{
    std::ostringstream buffer;
    buffer << "[";
    if (value.size() > 0) buffer << value[0];
    for (int i = 1; i < (int) value.size(); ++i) buffer << "," << value[i];
    buffer << "]";
    return buffer.str();
}

template<>
inline std::string serializeValue<std::vector<double>>(const std::vector<double> &value)
{
    std::ostringstream buffer;
    buffer << "[";
    if (value.size() > 0) buffer << value[0];
    for (int i = 1; i < (int) value.size(); ++i) buffer << "," << value[i];
    buffer << "]";
    return buffer.str();
}

template<>
inline std::string serializeValue<IPLColor>(const IPLColor &value)
{
    std::ostringstream buffer;
    buffer << "[" << value.red() << "," << value.green() << "," << value.blue() << "]";
    return buffer.str();
}

template<>
inline std::string serializeValue<IPLPoint>(const IPLPoint &value)
{
    std::ostringstream buffer;
    buffer << "[" << value.x() << "," << value.y() << "]";
    return buffer.str();
}

template<class T>
inline IPLProcessProperty::SerializedData serializeProperty(const char *type, IPLProcessWidgetType widget, const T &value)
{
    IPLProcessProperty::SerializedData result;
    result.type = serializeValue(type);
    result.widget = serializeValue(widget);
    result.widgetName = serializeValue(widgetName(widget));
    result.value = serializeValue(value);
    return result;
}

inline void deserializeValue(const std::string &data, bool &value)
{
    /*if (data.length() != 4)
    {
        value = false;
        return;
    }*/

    //static const unsigned char nonAsciiMap = 1<<7;
    std::string lowercase(data);
    //tolower is undefined (i.e. might crash) for non-ASCII characters. Since we don't want to parse those, just xor them out
    //std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), [](char c) { return c ^ nonAsciiMap; });
    std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), tolower); //Transform to lower case
    value = (lowercase.compare("true") == 0 || lowercase.compare("1") == 0);
}

inline void deserializeValue(const std::string &data, int &value)
{
    int result = 0;
    if (sscanf(data.c_str(),"%d",&result) < 1)
        throw IPLProcessProperty::DeserialationFailed();
    value = result;
}

inline void deserializeValue(const std::string &data, IPLProcessWidgetType &value)
{
    int tmp;
    deserializeValue(data,tmp);
    value = (IPLProcessWidgetType) tmp;
}

inline void deserializeValue(const std::string &data, unsigned int &value)
{
    unsigned int result = 0;
    if (sscanf(data.c_str(),"%u",&result) < 1)
        throw IPLProcessProperty::DeserialationFailed();
    value = result;
}

inline void deserializeValue(const std::string &data, float &value)
{
    float result = 0;
    if (sscanf(data.c_str(),"%f",&result) < 1)
        throw IPLProcessProperty::DeserialationFailed();
    value = result;
}

inline void deserializeValue(const std::string &data, double &value)
{
    double result = 0;
    if (sscanf(data.c_str(),"%lf",&result) < 1)
        throw IPLProcessProperty::DeserialationFailed();
    value = result;
}

inline void deserializeValue(const std::string &data, std::vector<int> &value)
{
    std::vector<int> result;
    std::smatch match;
    auto pos = data.begin();
    while(std::regex_search(pos,data.end(),match,std::regex("[0-9]|-")))
    {
        pos += match.position();

        int charsParsed = 0;
        int element = 0;
        if (sscanf(&(*pos),"%d%n",&element,&charsParsed) > 0)
            result.push_back(element);

        pos += charsParsed;
    }
    value.swap(result);
}

inline void deserializeValue(const std::string &data, std::vector<double> &value)
{
    std::vector<double> result;
    std::smatch match;
    auto pos = data.begin();
    while(std::regex_search(pos,data.end(),match,std::regex("[0-9]|-")))
    {
        pos += match.position();

        int charsParsed = 0;
        double element = 0;
        if (sscanf(&(*pos),"%f%n",&element,&charsParsed) > 0)
            result.push_back(element);

        pos += charsParsed;
    }
    value.swap(result);
}

inline void deserializeValue(const std::string &data, IPLColor &value)
{
    std::array<float,3> color;

    int i = 0;
    std::smatch match;
    auto pos = data.begin();
    while(i < (int) color.size() && std::regex_search(pos,data.end(),match,std::regex("[-0-9.]")))
    {
        pos += match.position();

        int charsParsed = 0;
        float element = 0;
        if (sscanf(&(*pos),"%f%n",&element,&charsParsed) > 0)
            color[i++] = element;

        pos += charsParsed;
    }
    value = IPLColor(color[0], color[1], color[2]);
}

inline void deserializeValue(const std::string &data, IPLPoint &value)
{
    std::array<double,2> point;

    int i = 0;
    std::smatch match;
    auto pos = data.begin();
    while(i < (int) point.size() && std::regex_search(pos,data.end(),match,std::regex("[-0-9.]")))
    {
        pos += match.position();

        int charsParsed = 0;
        float element = 0;
        if (sscanf(&(*pos),"%f%n",&element,&charsParsed) > 0)
            point[i++] = element;

        pos += charsParsed;
    }

    value = IPLPoint(point[0], point[1]);
}

inline void deserializeValue(const std::string &data, std::string &value)
{
    value = data;
}

template<class T>
inline void deserializeProperty(IPLProcessProperty::SerializedData data, IPLProcessWidgetType &widget, T &value)
{
    deserializeValue(data.widget,widget);
    deserializeValue(data.value,value);
}

IPLProcessProperty::IPLProcessProperty(int position, const char* name, const char *title, const char *description, IPLProcess *process, IPLProcessWidgetType widget):
    _position(position),
    _name(name),
    _title(title),
    _description(description),
    _process(process),
    _widget(widget)
{}

IPLProcessPropertyInt::IPLProcessPropertyInt(IPLProcess *process, int position, const char* name, const char* title, const char *description, int value, IPLProcessWidgetType widget, int min, int max):
    IPLProcessProperty(position,name,title,description,process,widget),
    _value(value),
    _default(value),
    _min(min),
    _max(max)
{}

void IPLProcessPropertyInt::setValue(int value)
{
    _value = value;
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

IPLProcessProperty::SerializedData IPLProcessPropertyInt::serialize() const
{
    return serializeProperty(type(),_widget,_value);
}

void IPLProcessPropertyInt::deserialize(const SerializedData &data)
{
    deserializeProperty(data,_widget,_value);
}

IPLProcessProperty *IPLProcessPropertyInt::clone() const
{
    return new IPLProcessPropertyInt(*this);
}

IPLProcessPropertyUnsignedInt::IPLProcessPropertyUnsignedInt(IPLProcess *process, int position, const char* name, const char* title, const char *description, unsigned int value, IPLProcessWidgetType widget, unsigned int min, unsigned int max):
    IPLProcessProperty(position,name,title,description,process,widget),
    _value(value),
    _default(value),
    _min(min),
    _max(max)
{}

void IPLProcessPropertyUnsignedInt::setValue(unsigned int value)
{
    _value = value;
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

IPLProcessProperty::SerializedData IPLProcessPropertyUnsignedInt::serialize() const
{
    return serializeProperty(type(),_widget,_value);
}

void IPLProcessPropertyUnsignedInt::deserialize(const SerializedData &data)
{
    deserializeProperty(data,_widget,_value);
}

IPLProcessProperty *IPLProcessPropertyUnsignedInt::clone() const
{
    return new IPLProcessPropertyUnsignedInt(*this);
}


IPLProcessPropertyDouble::IPLProcessPropertyDouble(IPLProcess *process, int position, const char* name, const char* title, const char *description, double value, IPLProcessWidgetType widget, double min, double max):
    IPLProcessProperty(position,name,title,description,process, widget),
    _value(value),
    _default(value),
    _min(min),
    _max(max)
{}

void IPLProcessPropertyDouble::setValue(double value)
{
    _value = value;
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

IPLProcessProperty::SerializedData IPLProcessPropertyDouble::serialize() const
{
    return serializeProperty(type(),_widget,_value);
}

void IPLProcessPropertyDouble::deserialize(const SerializedData &data)
{
    deserializeProperty(data,_widget,_value);
}

IPLProcessProperty *IPLProcessPropertyDouble::clone() const
{
    return new IPLProcessPropertyDouble(*this);
}


IPLProcessPropertyFloat::IPLProcessPropertyFloat(IPLProcess *process, int position, const char* name, const char* title, const char *description, float value, IPLProcessWidgetType widget, float min, float max):
    IPLProcessProperty(position,name,title,description,process,widget),
    _value(value),
    _default(value),
    _min(min),
    _max(max)
{}

void IPLProcessPropertyFloat::setValue(float value)
{
    _value = value;
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

IPLProcessProperty::SerializedData IPLProcessPropertyFloat::serialize() const
{
    return serializeProperty(type(),_widget,_value);
}

void IPLProcessPropertyFloat::deserialize(const SerializedData &data)
{
    deserializeProperty(data,_widget,_value);
}

IPLProcessProperty *IPLProcessPropertyFloat::clone() const
{
    return new IPLProcessPropertyFloat(*this);
}


IPLProcessPropertyBool::IPLProcessPropertyBool(IPLProcess *process, int position, const char* name, const char* title, const char *description, bool value, IPLProcessWidgetType widget):
    IPLProcessProperty(position,name,title,description,process,widget),
    _value(value),
    _default(value)
{}

void IPLProcessPropertyBool::setValue(bool value)
{
    _value = value;
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

IPLProcessProperty::SerializedData IPLProcessPropertyBool::serialize() const
{
    return serializeProperty(type(),_widget,_value);
}

void IPLProcessPropertyBool::deserialize(const SerializedData &data)
{
    deserializeProperty(data,_widget,_value);
}

IPLProcessProperty *IPLProcessPropertyBool::clone() const
{
    return new IPLProcessPropertyBool(*this);
}

IPLProcessPropertyBoolOneShot::IPLProcessPropertyBoolOneShot(IPLProcess *process, int position, const char* name, const char* title, const char *description, bool value, IPLProcessWidgetType widget):
    IPLProcessPropertyBool(process, position,name,title,description,process,widget)
{}


IPLProcessPropertyString::IPLProcessPropertyString(IPLProcess *process, int position, const char* name, const char* title, const char *description, const std::string &value, IPLProcessWidgetType widget):
    IPLProcessProperty(position,name,title,description,process,widget),
    _value(value),
    _default(value)
{}

void IPLProcessPropertyString::setValue(const std::string &value)
{
    _value = value;
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

void IPLProcessPropertyString::setValue(std::string &&value)
{
    _value = std::move(value);
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

IPLProcessProperty::SerializedData IPLProcessPropertyString::serialize() const
{
    return serializeProperty(type(),_widget,_value);
}

void IPLProcessPropertyString::deserialize(const SerializedData &data)
{
    deserializeProperty(data,_widget,_value);
}

IPLProcessProperty *IPLProcessPropertyString::clone() const
{
    return new IPLProcessPropertyString(*this);
}


IPLProcessPropertyVectorInt::IPLProcessPropertyVectorInt(IPLProcess *process, int position, const char* name, const char* title, const char *description, const std::vector<int> &value, IPLProcessWidgetType widget):
    IPLProcessProperty(position,name,title,description,process,widget),
    _value(value)
{
    _default = value;
}

void IPLProcessPropertyVectorInt::setValue(const std::vector<int> &value)
{
    _value = value;
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

void IPLProcessPropertyVectorInt::setValue(std::vector<int> &&value)
{
    _value = std::move(value);
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

IPLProcessProperty::SerializedData IPLProcessPropertyVectorInt::serialize() const
{
    return serializeProperty(type(),_widget,_value);
}

void IPLProcessPropertyVectorInt::deserialize(const SerializedData &data)
{
    deserializeProperty(data,_widget,_value);
}

IPLProcessProperty *IPLProcessPropertyVectorInt::clone() const
{
    return new IPLProcessPropertyVectorInt(*this);
}



IPLProcessPropertyVectorDouble::IPLProcessPropertyVectorDouble(IPLProcess *process, int position, const char* name, const char* title, const char *description, const std::vector<double> &value, IPLProcessWidgetType widget):
    IPLProcessProperty(position,name,title,description,process,widget),
    _value(value),
    _default(value)
{}

void IPLProcessPropertyVectorDouble::setValue(const std::vector<double> &value)
{
    _value = value;
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

void IPLProcessPropertyVectorDouble::setValue(std::vector<double> &&value)
{
    _value = std::move(value);
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

IPLProcessProperty::SerializedData IPLProcessPropertyVectorDouble::serialize() const
{
    return serializeProperty(type(),_widget,_value);
}

void IPLProcessPropertyVectorDouble::deserialize(const SerializedData &data)
{
    deserializeProperty(data,_widget,_value);
}

IPLProcessProperty *IPLProcessPropertyVectorDouble::clone() const
{
    return new IPLProcessPropertyVectorDouble(*this);
}


IPLProcessPropertyColor::IPLProcessPropertyColor(IPLProcess *process, int position, const char* name, const char* title, const char *description, const IPLColor &value, IPLProcessWidgetType widget):
    IPLProcessProperty(position,name,title,description,process,widget),
    _value(value),
    _default(value)
{}

void IPLProcessPropertyColor::setValue(const IPLColor &value)
{
    _value = value;
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

void IPLProcessPropertyColor::setValue(IPLColor &&value)
{
    _value = std::move(value);
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

IPLProcessProperty::SerializedData IPLProcessPropertyColor::serialize() const
{
    return serializeProperty(type(),_widget,_value);
}

void IPLProcessPropertyColor::deserialize(const SerializedData &data)
{
    deserializeProperty(data,_widget,_value);
}

IPLProcessProperty *IPLProcessPropertyColor::clone() const
{
    return new IPLProcessPropertyColor(*this);
}

IPLProcessPropertyPoint::IPLProcessPropertyPoint(IPLProcess *process, int position, const char* name, const char* title, const char *description, const IPLPoint &value, IPLProcessWidgetType widget):
    IPLProcessProperty(position,name,title,description,process,widget),
    _value(value),
    _default(value)
{}

void IPLProcessPropertyPoint::setValue(const IPLPoint &value)
{
    _value = value;
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

void IPLProcessPropertyPoint::setValue(IPLPoint &&value)
{
    _value = std::move(value);
    _process->requestUpdate();
    _process->processPropertyEvents(new IPLEvent(_name));
    _process->notifyPropertyChangedEventHandler();
}

IPLProcessProperty::SerializedData IPLProcessPropertyPoint::serialize() const
{
    return serializeProperty(type(),_widget,_value);
}

void IPLProcessPropertyPoint::deserialize(const SerializedData &data)
{
    deserializeProperty(data,_widget,_value);
}

IPLProcessProperty *IPLProcessPropertyPoint::clone() const
{
    return new IPLProcessPropertyPoint(*this);
}

类结构

基类 IPLProcessProperty

所有属性类的基类,定义了通用接口:

class IPLProcessProperty {
public:
    struct SerializedData {
        std::string type;
        std::string widget;
        std::string widgetName;
        std::string value;
    };
    
    // 基础信息访问
    int position() const;
    const char* name() const;
    const char* title() const;
    const char* description() const;
    IPLProcessWidgetType widget() const;
    
    // 必须实现的纯虚函数
    virtual const char* type() const = 0;
    virtual SerializedData serialize() const = 0;
    virtual void deserialize(const SerializedData &data) = 0;
    virtual IPLProcessProperty *clone() const = 0;
    virtual void resetValue() = 0;
};

派生属性类

框架提供了多种数据类型的属性类:

  1. IPLProcessPropertyInt - 整型属性

  2. IPLProcessPropertyUnsignedInt - 无符号整型属性

  3. IPLProcessPropertyDouble - 双精度浮点属性

  4. IPLProcessPropertyFloat - 单精度浮点属性

  5. IPLProcessPropertyBool - 布尔属性

  6. IPLProcessPropertyBoolOneShot - 一次性布尔属性(点击后自动复位)

  7. IPLProcessPropertyString - 字符串属性

  8. IPLProcessPropertyVectorInt - 整型向量属性

  9. IPLProcessPropertyVectorDouble - 双精度浮点向量属性

  10. IPLProcessPropertyColor - 颜色属性

  11. IPLProcessPropertyPoint - 点坐标属性

核心实现细节

序列化机制

每个属性类都实现了 serialize() 和 deserialize() 方法,用于将属性值转换为字符串表示和反向转换。

// 序列化模板函数
template<class T>
inline std::string serializeValue(const T &value) {
    std::ostringstream buffer;
    buffer << value;
    return buffer.str();
}

// 特化版本的序列化
template<>
inline std::string serializeValue<bool>(const bool &value) {
    return value ? "true" : "false";
}

// 向量类型的序列化
template<>
inline std::string serializeValue<std::vector<int>>(const std::vector<int> &value) {
    std::ostringstream buffer;
    buffer << "[";
    if (value.size() > 0) buffer << value[0];
    for (int i = 1; i < (int) value.size(); ++i) buffer << "," << value[i];
    buffer << "]";
    return buffer.str();
}

反序列化机制

反序列化使用正则表达式和 sscanf 来解析字符串值:

inline void deserializeValue(const std::string &data, bool &value) {
    std::string lowercase(data);
    std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), tolower);
    value = (lowercase.compare("true") == 0 || lowercase.compare("1") == 0);
}

inline void deserializeValue(const std::string &data, std::vector<int> &value) {
    std::vector<int> result;
    std::smatch match;
    auto pos = data.begin();
    while(std::regex_search(pos,data.end(),match,std::regex("[0-9]|-"))) {
        pos += match.position();
        int charsParsed = 0;
        int element = 0;
        if (sscanf(&(*pos),"%d%n",&element,&charsParsed) > 0)
            result.push_back(element);
        pos += charsParsed;
    }
    value.swap(result);
}

属性变更通知

当属性值变化时,会触发以下操作:

  1. 请求处理流程更新

  2. 发送属性变化事件

  3. 通知属性变化处理器

void IPLProcessPropertyInt::setValue(int value) {
    _value = value;
    _process->requestUpdate();  // 请求更新
    _process->processPropertyEvents(new IPLEvent(_name)); // 发送事件
    _process->notifyPropertyChangedEventHandler(); // 通知处理器
}

使用示例

创建属性

// 在图像处理算法中创建属性
class MyImageProcessor : public IPLProcessor {
public:
    MyImageProcessor() {
        // 添加整型属性,范围0-100,默认值50,使用滑块控件
        addProperty("threshold", "Threshold", "Image binarization threshold", 
                    50, IPL_WIDGET_SLIDER, 0, 100);
        
        // 添加布尔属性,默认false,使用复选框
        addProperty("invert", "Invert", "Invert output", 
                    false, IPL_WIDGET_CHECKBOX);
        
        // 添加颜色属性
        addProperty("color", "Color", "Selection color", 
                    IPLColor(255,0,0), IPL_WIDGET_COLOR);
    }
};

访问属性值

void MyImageProcessor::process() {
    // 获取阈值属性值
    int threshold = getProperty("threshold")->value();
    
    // 获取反转标志
    bool invert = getProperty("invert")->value();
    
    // 获取颜色值
    IPLColor color = getProperty("color")->value();
    
    // 处理图像...
}

设计特点

  1. 类型安全:每种数据类型有对应的属性类,避免类型混淆

  2. 可扩展性:易于添加新的属性类型

  3. GUI 集成:支持多种控件类型 (滑块、复选框、颜色选择器等)

  4. 默认值支持:所有属性都保存默认值,可随时重置

  5. 克隆支持:支持深度复制属性对象

总结

IPLProcessProperty 系统是 ImagePlay 框架中处理算法参数的核心组件,它提供了:

  • 多种数据类型的属性支持

  • 完整的序列化/反序列化能力

  • 与 GUI 控件的紧密集成

  • 属性变更通知机制

  • 类型安全和可扩展的设计

这套系统使得图像处理算法的参数可以方便地在 GUI 中配置、保存和加载,大大简化了算法开发和用户交互的实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值