proper metadata support for the Bitmap class (mainly for OpenEXR I/O)
parent
f6399ad08c
commit
4d75c69d4a
|
@ -774,25 +774,23 @@ public:
|
|||
inline void setGamma(Float gamma) { m_gamma = gamma; }
|
||||
|
||||
/// Set a string-valued metadata field
|
||||
void setString(const std::string &key, const std::string &value);
|
||||
inline void setMetadataString(const std::string &key, const std::string &value) {
|
||||
m_metadata.setString(key, value);
|
||||
}
|
||||
|
||||
/// Return a string-valued metadata field
|
||||
std::string getString(const std::string &key) const;
|
||||
|
||||
/// Return a map of all present metadata
|
||||
inline std::map<std::string, std::string> &getMetadata() {
|
||||
return m_metadata;
|
||||
inline std::string getMetadataString(const std::string &key) const {
|
||||
return m_metadata.getAsString(key);
|
||||
}
|
||||
|
||||
/// Return a map of all present metadata (const version)
|
||||
inline const std::map<std::string, std::string> &getMetadata() const {
|
||||
return m_metadata;
|
||||
}
|
||||
/// Return a \ref Properties object containing the image metadata
|
||||
inline Properties &getMetadata() { return m_metadata; }
|
||||
|
||||
/// Set the metadata associated with the bitmap
|
||||
inline void setMetadata(const std::map<std::string, std::string> &metadata) {
|
||||
m_metadata = metadata;
|
||||
}
|
||||
/// Return a \ref Properties object containing the image metadata (const version)
|
||||
inline const Properties &getMetadata() const { return m_metadata; }
|
||||
|
||||
/// Set the a \ref Properties object containing the image metadata
|
||||
inline void setMetadata(const Properties &metadata) { m_metadata = metadata; }
|
||||
|
||||
//! @}
|
||||
// ======================================================================
|
||||
|
@ -910,9 +908,9 @@ protected:
|
|||
EComponentFormat m_componentFormat;
|
||||
Vector2i m_size;
|
||||
uint8_t *m_data;
|
||||
std::map<std::string, std::string> m_metadata;
|
||||
Float m_gamma;
|
||||
int m_channelCount;
|
||||
Properties m_metadata;
|
||||
};
|
||||
|
||||
/** \brief Bitmap format conversion helper class
|
||||
|
|
|
@ -71,6 +71,14 @@ public:
|
|||
struct Data {
|
||||
uint8_t *ptr;
|
||||
size_t size;
|
||||
|
||||
inline bool operator==(const Data &d) const {
|
||||
return ptr == d.ptr && size == d.size;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Data &d) const {
|
||||
return !operator==(d);
|
||||
}
|
||||
};
|
||||
|
||||
/// Construct an empty property container
|
||||
|
@ -172,6 +180,11 @@ public:
|
|||
/// Get a string (with default)
|
||||
std::string getString(const std::string &name, const std::string &defVal) const;
|
||||
|
||||
/// Return one of the parameters (converting it to a string if necessary)
|
||||
std::string getAsString(const std::string &name) const;
|
||||
/// Return one of the parameters (converting it to a string if necessary, with default value)
|
||||
std::string getAsString(const std::string &name, const std::string &defVal) const;
|
||||
|
||||
/// Store an array containing the names of all stored properties
|
||||
void putPropertyNames(std::vector<std::string> &results) const;
|
||||
|
||||
|
@ -206,6 +219,14 @@ public:
|
|||
/// Assignment operator
|
||||
void operator=(const Properties &props);
|
||||
|
||||
/// Equality comparison operator
|
||||
bool operator==(const Properties &props) const;
|
||||
|
||||
/// Inequality comparision operator
|
||||
inline bool operator!=(const Properties &props) const {
|
||||
return !operator==(props);
|
||||
}
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
private:
|
||||
|
|
|
@ -393,6 +393,16 @@ public:
|
|||
m_invTransform.serialize(stream);
|
||||
}
|
||||
|
||||
/// Equality comparison operator
|
||||
inline bool operator==(const Transform &trafo) const {
|
||||
return m_transform == trafo.m_transform;
|
||||
}
|
||||
|
||||
/// Inequality comparison operator
|
||||
inline bool operator!=(const Transform &trafo) const {
|
||||
return m_transform != trafo.m_transform;
|
||||
}
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
private:
|
||||
|
|
|
@ -383,7 +383,7 @@ public:
|
|||
|
||||
for (std::map<std::string, std::string>::const_iterator it = m_tags.begin();
|
||||
it != m_tags.end(); ++it)
|
||||
bitmap->getMetadata()[it->first] = it->second;
|
||||
bitmap->setMetadataString(it->first, it->second);
|
||||
|
||||
fs::path filename = m_destFile;
|
||||
std::string extension = boost::to_lower_copy(filename.extension().string());
|
||||
|
@ -400,7 +400,7 @@ public:
|
|||
if (m_attachLog && logger->readLog(log)) {
|
||||
log += "\n\n";
|
||||
log += Statistics::getInstance()->getStats();
|
||||
bitmap->setString("log", log);
|
||||
bitmap->setMetadataString("log", log);
|
||||
}
|
||||
|
||||
bitmap->write(m_fileFormat, stream);
|
||||
|
|
|
@ -353,7 +353,7 @@ public:
|
|||
|
||||
for (std::map<std::string, std::string>::const_iterator it = m_tags.begin();
|
||||
it != m_tags.end(); ++it)
|
||||
bitmap->getMetadata()[it->first] = it->second;
|
||||
bitmap->setMetadataString(it->first, it->second);
|
||||
|
||||
fs::path filename = m_destFile;
|
||||
std::string extension = boost::to_lower_copy(filename.extension().string());
|
||||
|
|
|
@ -38,6 +38,11 @@
|
|||
#include <ImfOutputFile.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfStringAttribute.h>
|
||||
#include <ImfIntAttribute.h>
|
||||
#include <ImfFloatAttribute.h>
|
||||
#include <ImfDoubleAttribute.h>
|
||||
#include <ImfVecAttribute.h>
|
||||
#include <ImfMatrixAttribute.h>
|
||||
#include <ImfVersion.h>
|
||||
#include <ImfIO.h>
|
||||
#include <ImathBox.h>
|
||||
|
@ -386,19 +391,6 @@ int Bitmap::getBytesPerComponent() const {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void Bitmap::setString(const std::string &key, const std::string &value) {
|
||||
m_metadata[key] = value;
|
||||
}
|
||||
|
||||
std::string Bitmap::getString(const std::string &key) const {
|
||||
std::map<std::string, std::string>::const_iterator it = m_metadata.find(key);
|
||||
if (it != m_metadata.end())
|
||||
return it->second;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
Bitmap::~Bitmap() {
|
||||
if (m_data)
|
||||
freeAligned(m_data);
|
||||
|
@ -1189,12 +1181,17 @@ std::string Bitmap::toString() const {
|
|||
<< " type = " << m_pixelFormat << endl
|
||||
<< " componentFormat = " << m_componentFormat << endl
|
||||
<< " size = " << m_size.toString() << endl;
|
||||
if (!m_metadata.empty()) {
|
||||
|
||||
std::vector<std::string> keys = m_metadata.getPropertyNames();
|
||||
if (!keys.empty()) {
|
||||
oss << " metadata = {" << endl;
|
||||
for (std::map<std::string, std::string>::const_iterator it = m_metadata.begin();
|
||||
it != m_metadata.end();) {
|
||||
oss << " \"" << it->first << "\" => \"" << it->second << "\"";
|
||||
if (++it != m_metadata.end())
|
||||
for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ) {
|
||||
std::string value = m_metadata.getAsString(*it);
|
||||
if (value.size() > 50)
|
||||
value = value.substr(0, 50) + ".. [truncated]";
|
||||
|
||||
oss << " \"" << *it << "\" => \"" << value << "\"";
|
||||
if (++it != keys.end())
|
||||
oss << ",";
|
||||
oss << endl;
|
||||
}
|
||||
|
@ -1281,7 +1278,7 @@ void Bitmap::readPNG(Stream *stream) {
|
|||
png_get_text(png_ptr, info_ptr, &text_ptr, &textIdx);
|
||||
|
||||
for (int i=0; i<textIdx; ++i, text_ptr++)
|
||||
m_metadata[text_ptr->key] = text_ptr->text;
|
||||
setMetadataString(text_ptr->key, text_ptr->text);
|
||||
|
||||
int intent; double gamma;
|
||||
if (png_get_sRGB(png_ptr, info_ptr, &intent)) {
|
||||
|
@ -1357,20 +1354,23 @@ void Bitmap::writePNG(Stream *stream, int compression) const {
|
|||
|
||||
png_text *text = NULL;
|
||||
|
||||
std::map<std::string, std::string> metadata = m_metadata;
|
||||
metadata["generated-by"] = "Mitsuba version " MTS_VERSION;
|
||||
Properties metadata(m_metadata);
|
||||
metadata.setString("generated-by", "Mitsuba version " MTS_VERSION);
|
||||
|
||||
text = new png_text[metadata.size()];
|
||||
memset(text, 0, sizeof(png_text) * metadata.size());
|
||||
int textIndex = 0;
|
||||
for (std::map<std::string, std::string>::iterator it = metadata.begin();
|
||||
it != metadata.end(); ++it) {
|
||||
text[textIndex].key = const_cast<char *>(it->first.c_str());
|
||||
text[textIndex].text = const_cast<char *>(it->second.c_str());
|
||||
text[textIndex++].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
std::vector<std::string> keys = metadata.getPropertyNames();
|
||||
std::vector<std::string> values(keys.size());
|
||||
|
||||
text = new png_text[keys.size()];
|
||||
memset(text, 0, sizeof(png_text) * keys.size());
|
||||
|
||||
for (size_t i = 0; i<keys.size(); ++i) {
|
||||
values[i] = metadata.getAsString(keys[i]);
|
||||
text[i].key = const_cast<char *>(keys[i].c_str());
|
||||
text[i].text = const_cast<char *>(values[i].c_str());
|
||||
text[i].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
}
|
||||
|
||||
png_set_text(png_ptr, info_ptr, text, textIndex);
|
||||
png_set_text(png_ptr, info_ptr, text, keys.size());
|
||||
|
||||
if (m_gamma == -1)
|
||||
png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, PNG_sRGB_INTENT_ABSOLUTE);
|
||||
|
@ -1665,11 +1665,37 @@ void Bitmap::readOpenEXR(Stream *stream, const std::string &_prefix) {
|
|||
/* Load metadata if present */
|
||||
for (Imf::Header::ConstIterator it = header.begin(); it != header.end(); ++it) {
|
||||
std::string name = it.name(), typeName = it.attribute().typeName();
|
||||
const Imf::StringAttribute *sattr = NULL;
|
||||
const Imf::StringAttribute *sattr;
|
||||
const Imf::IntAttribute *iattr;
|
||||
const Imf::FloatAttribute *fattr;
|
||||
const Imf::DoubleAttribute *dattr;
|
||||
const Imf::V3fAttribute *vattr;
|
||||
const Imf::M44fAttribute *mattr;
|
||||
|
||||
if (typeName == "string" &&
|
||||
(sattr = header.findTypedAttribute<Imf::StringAttribute>(name.c_str())))
|
||||
m_metadata[name] = sattr->value();
|
||||
m_metadata.setString(name, sattr->value());
|
||||
else if (typeName == "int" &&
|
||||
(iattr = header.findTypedAttribute<Imf::IntAttribute>(name.c_str())))
|
||||
m_metadata.setInteger(name, iattr->value());
|
||||
else if (typeName == "float" &&
|
||||
(fattr = header.findTypedAttribute<Imf::FloatAttribute>(name.c_str())))
|
||||
m_metadata.setFloat(name, (Float) fattr->value());
|
||||
else if (typeName == "double" &&
|
||||
(dattr = header.findTypedAttribute<Imf::DoubleAttribute>(name.c_str())))
|
||||
m_metadata.setFloat(name, (Float) dattr->value());
|
||||
else if (typeName == "v3f" &&
|
||||
(vattr = header.findTypedAttribute<Imf::V3fAttribute>(name.c_str()))) {
|
||||
Imath::V3f vec = vattr->value();
|
||||
m_metadata.setVector(name, Vector(vec.x, vec.y, vec.z));
|
||||
} else if (typeName == "m44f" &&
|
||||
(mattr = header.findTypedAttribute<Imf::M44fAttribute>(name.c_str()))) {
|
||||
Matrix4x4 M;
|
||||
for (int i=0; i<4; ++i)
|
||||
for (int j=0; j<4; ++j)
|
||||
M(i, j) = mattr->value().x[i][j];
|
||||
m_metadata.setTransform(name, Transform(M));
|
||||
}
|
||||
}
|
||||
|
||||
updateChannelCount();
|
||||
|
@ -1896,13 +1922,45 @@ void Bitmap::writeOpenEXR(Stream *stream,
|
|||
pixelFormat = ERGBA;
|
||||
#endif
|
||||
|
||||
std::map<std::string, std::string> metadata = m_metadata;
|
||||
metadata["generated-by"] = "Mitsuba version " MTS_VERSION;
|
||||
Properties metadata(m_metadata);
|
||||
metadata.setString("generated-by", "Mitsuba version " MTS_VERSION);
|
||||
|
||||
std::vector<std::string> keys = metadata.getPropertyNames();
|
||||
|
||||
Imf::Header header(m_size.x, m_size.y);
|
||||
for (std::map<std::string, std::string>::const_iterator it = metadata.begin();
|
||||
it != metadata.end(); ++it)
|
||||
header.insert(it->first.c_str(), Imf::StringAttribute(it->second.c_str()));
|
||||
for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it) {
|
||||
Properties::EPropertyType type = metadata.getType(*it);
|
||||
|
||||
switch (type) {
|
||||
case Properties::EString:
|
||||
header.insert(it->c_str(), Imf::StringAttribute(metadata.getString(*it)));
|
||||
break;
|
||||
case Properties::EInteger:
|
||||
header.insert(it->c_str(), Imf::IntAttribute(metadata.getInteger(*it)));
|
||||
break;
|
||||
case Properties::EFloat:
|
||||
header.insert(it->c_str(), Imf::FloatAttribute((float) metadata.getFloat(*it)));
|
||||
break;
|
||||
case Properties::EPoint: {
|
||||
Point val = metadata.getPoint(*it);
|
||||
header.insert(it->c_str(), Imf::V3fAttribute(
|
||||
Imath::V3f((float) val.x, (float) val.y, (float) val.z)));
|
||||
}
|
||||
break;
|
||||
case Properties::ETransform: {
|
||||
Matrix4x4 val = metadata.getTransform(*it).getMatrix();
|
||||
header.insert(it->c_str(), Imf::M44fAttribute(Imath::M44f(
|
||||
(float) val(0, 0), (float) val(0, 1), (float) val(0, 2), (float) val(0, 3),
|
||||
(float) val(1, 0), (float) val(1, 1), (float) val(1, 2), (float) val(1, 3),
|
||||
(float) val(2, 0), (float) val(2, 1), (float) val(2, 2), (float) val(2, 3),
|
||||
(float) val(3, 0), (float) val(3, 1), (float) val(3, 2), (float) val(3, 3))));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
header.insert(it->c_str(), Imf::StringAttribute(metadata.getAsString(*it)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pixelFormat == EXYZ || pixelFormat == EXYZA) {
|
||||
Imf::addChromaticities(header, Imf::Chromaticities(
|
||||
|
@ -2363,14 +2421,16 @@ void Bitmap::writeRGBE(Stream *stream) const {
|
|||
Log(EError, "writeRGBE(): pixel format must be ERGB or ERGBA!");
|
||||
|
||||
stream->writeLine("#?RGBE");
|
||||
for (std::map<std::string, std::string>::const_iterator it = m_metadata.begin();
|
||||
it != m_metadata.end(); ++it) {
|
||||
stream->writeLine(formatString("# Metadata [%s]:", it->first.c_str()));
|
||||
std::istringstream iss(it->second);
|
||||
|
||||
std::vector<std::string> keys = m_metadata.getPropertyNames();
|
||||
for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ) {
|
||||
stream->writeLine(formatString("# Metadata [%s]:", it->c_str()));
|
||||
std::istringstream iss(m_metadata.getAsString(*it));
|
||||
std::string buf;
|
||||
while (std::getline(iss, buf))
|
||||
stream->writeLine(formatString("# %s", buf.c_str()));
|
||||
}
|
||||
|
||||
stream->writeLine("FORMAT=32-bit_rle_rgbe\n");
|
||||
stream->writeLine(formatString("-Y %i +X %i", m_size.y, m_size.x));
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ struct PropertyElement {
|
|||
Type Properties::get##TypeName(const std::string &name) const { \
|
||||
std::map<std::string, PropertyElement>::const_iterator it = m_elements->find(name); \
|
||||
if (it == m_elements->end()) \
|
||||
SLog(EError, "Property \"%s\" missing", name.c_str()); \
|
||||
SLog(EError, "Property \"%s\" has not been specified!", name.c_str()); \
|
||||
const BaseType *result = boost::get<BaseType>(&it->second.data); \
|
||||
if (!result) \
|
||||
SLog(EError, "The property \"%s\" has the wrong type (expected <" #ReadableName ">). The " \
|
||||
|
@ -78,18 +78,55 @@ DEFINE_PROPERTY_ACCESSOR(Spectrum, Spectrum, Spectrum, spectrum)
|
|||
DEFINE_PROPERTY_ACCESSOR(std::string, std::string, String, string)
|
||||
DEFINE_PROPERTY_ACCESSOR(Properties::Data, Properties::Data, Data, data)
|
||||
|
||||
class type_visitor : public boost::static_visitor<Properties::EPropertyType> {
|
||||
public:
|
||||
Properties::EPropertyType operator()(const bool &) const { return Properties::EBoolean; }
|
||||
Properties::EPropertyType operator()(const int64_t &) const { return Properties::EInteger; }
|
||||
Properties::EPropertyType operator()(const Float &) const { return Properties::EFloat; }
|
||||
Properties::EPropertyType operator()(const Point &) const { return Properties::EPoint; }
|
||||
Properties::EPropertyType operator()(const Vector &) const { return Properties::EVector; }
|
||||
Properties::EPropertyType operator()(const Transform &) const { return Properties::ETransform; }
|
||||
Properties::EPropertyType operator()(const Spectrum &) const { return Properties::ESpectrum; }
|
||||
Properties::EPropertyType operator()(const std::string &) const { return Properties::EString; }
|
||||
Properties::EPropertyType operator()(const Properties::Data &) const { return Properties::EData; }
|
||||
};
|
||||
namespace {
|
||||
class TypeVisitor : public boost::static_visitor<Properties::EPropertyType> {
|
||||
public:
|
||||
Properties::EPropertyType operator()(const bool &) const { return Properties::EBoolean; }
|
||||
Properties::EPropertyType operator()(const int64_t &) const { return Properties::EInteger; }
|
||||
Properties::EPropertyType operator()(const Float &) const { return Properties::EFloat; }
|
||||
Properties::EPropertyType operator()(const Point &) const { return Properties::EPoint; }
|
||||
Properties::EPropertyType operator()(const Vector &) const { return Properties::EVector; }
|
||||
Properties::EPropertyType operator()(const Transform &) const { return Properties::ETransform; }
|
||||
Properties::EPropertyType operator()(const Spectrum &) const { return Properties::ESpectrum; }
|
||||
Properties::EPropertyType operator()(const std::string &) const { return Properties::EString; }
|
||||
Properties::EPropertyType operator()(const Properties::Data &) const { return Properties::EData; }
|
||||
};
|
||||
|
||||
class EqualityVisitor : public boost::static_visitor<bool> {
|
||||
public:
|
||||
EqualityVisitor(const ElementData *ref) : ref(ref) { }
|
||||
|
||||
bool operator()(const bool &v) const { const bool *v2 = boost::get<bool>(ref); return v2 ? (v == *v2) : false; }
|
||||
bool operator()(const int64_t &v) const { const int64_t *v2 = boost::get<int64_t>(ref); return v2 ? (v == *v2) : false; }
|
||||
bool operator()(const Float &v) const { const Float *v2 = boost::get<Float>(ref); return v2 ? (v == *v2) : false; }
|
||||
bool operator()(const Point &v) const { const Point *v2 = boost::get<Point>(ref); return v2 ? (v == *v2) : false; }
|
||||
bool operator()(const Vector &v) const { const Vector *v2 = boost::get<Vector>(ref); return v2 ? (v == *v2) : false; }
|
||||
bool operator()(const Transform &v) const { const Transform *v2 = boost::get<Transform>(ref); return v2 ? (v == *v2) : false; }
|
||||
bool operator()(const Spectrum &v) const { const Spectrum *v2 = boost::get<Spectrum>(ref); return v2 ? (v == *v2) : false; }
|
||||
bool operator()(const std::string &v) const { const std::string *v2 = boost::get<std::string>(ref); return v2 ? (v == *v2) : false; }
|
||||
bool operator()(const Properties::Data &v) const { const Properties::Data *v2 = boost::get<Properties::Data>(ref); return v2 ? (v == *v2) : false; }
|
||||
private:
|
||||
const ElementData *ref;
|
||||
};
|
||||
|
||||
class StringVisitor : public boost::static_visitor<void> {
|
||||
public:
|
||||
StringVisitor(std::ostringstream &oss, bool quote) : oss(oss), quote(quote) { }
|
||||
|
||||
void operator()(const bool &v) const { oss << (v ? "true" : "false"); }
|
||||
void operator()(const int64_t &v) const { oss << v; }
|
||||
void operator()(const Float &v) const { oss << v; }
|
||||
void operator()(const Point &v) const { oss << v.toString(); }
|
||||
void operator()(const Vector &v) const { oss << v.toString(); }
|
||||
void operator()(const Transform &v) const { oss << v.toString(); }
|
||||
void operator()(const Spectrum &v) const { oss << v.toString(); }
|
||||
void operator()(const std::string &v) const { oss << (quote ? "\"" : "") << v << (quote ? "\"" : ""); }
|
||||
void operator()(const Properties::Data &v) const { oss << v.ptr << " (size=" << v.size << ")"; }
|
||||
private:
|
||||
std::ostringstream &oss;
|
||||
bool quote;
|
||||
};
|
||||
}
|
||||
|
||||
Properties::Properties()
|
||||
: m_id("unnamed") {
|
||||
|
@ -145,13 +182,32 @@ Properties::EPropertyType Properties::getType(const std::string &name) const {
|
|||
if (it == m_elements->end())
|
||||
SLog(EError, "Property \"%s\" has not been specified!", name.c_str());
|
||||
|
||||
type_visitor myVisitor;
|
||||
return boost::apply_visitor(myVisitor, it->second.data);
|
||||
return boost::apply_visitor(TypeVisitor(), it->second.data);
|
||||
}
|
||||
|
||||
std::string Properties::getAsString(const std::string &name, const std::string &defVal) const {
|
||||
if (m_elements->find(name) == m_elements->end())
|
||||
return defVal;
|
||||
return getAsString(name);
|
||||
}
|
||||
|
||||
std::string Properties::getAsString(const std::string &name) const {
|
||||
std::map<std::string, PropertyElement>::const_iterator it = m_elements->find(name);
|
||||
if (it == m_elements->end())
|
||||
SLog(EError, "Property \"%s\" has not been specified!", name.c_str());
|
||||
|
||||
std::ostringstream oss;
|
||||
StringVisitor strVisitor(oss, false);
|
||||
boost::apply_visitor(strVisitor, it->second.data);
|
||||
it->second.queried = true;
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string Properties::toString() const {
|
||||
std::map<std::string, PropertyElement>::const_iterator it = m_elements->begin();
|
||||
std::ostringstream oss;
|
||||
StringVisitor strVisitor(oss, true);
|
||||
|
||||
oss << "Properties[" << endl
|
||||
<< " pluginName = \"" << m_pluginName << "\"," << endl
|
||||
|
@ -160,36 +216,7 @@ std::string Properties::toString() const {
|
|||
while (it != m_elements->end()) {
|
||||
oss << " \"" << (*it).first << "\" -> ";
|
||||
const ElementData &data = (*it).second.data;
|
||||
EPropertyType type = boost::apply_visitor(type_visitor(), data);
|
||||
switch (type) {
|
||||
case EBoolean:
|
||||
oss << (boost::get<bool>(data) ? "true" : "false");
|
||||
break;
|
||||
case EInteger:
|
||||
oss << boost::get<int64_t>(data);
|
||||
break;
|
||||
case EFloat:
|
||||
oss << boost::get<Float>(data);
|
||||
break;
|
||||
case EPoint:
|
||||
oss << boost::get<Point>(data).toString();
|
||||
break;
|
||||
case ETransform:
|
||||
oss << indent(boost::get<Transform>(data).toString());
|
||||
break;
|
||||
case ESpectrum:
|
||||
oss << boost::get<Spectrum>(data).toString();
|
||||
break;
|
||||
case EString:
|
||||
oss << "\"" << boost::get<std::string>(data) << "\"";
|
||||
break;
|
||||
case EData:
|
||||
oss << boost::get<Data>(data).ptr << " (size="
|
||||
<< boost::get<Data>(data).size << ")";
|
||||
break;
|
||||
default:
|
||||
oss << "<unknown>";
|
||||
}
|
||||
boost::apply_visitor(strVisitor, data);
|
||||
if (++it != m_elements->end())
|
||||
oss << ",";
|
||||
oss << endl;
|
||||
|
@ -219,6 +246,21 @@ void Properties::putPropertyNames(std::vector<std::string> &results) const {
|
|||
results.push_back((*it).first);
|
||||
}
|
||||
|
||||
bool Properties::operator==(const Properties &p) const {
|
||||
if (m_pluginName != p.m_pluginName || m_id != p.m_id || m_elements->size() != p.m_elements->size())
|
||||
return false;
|
||||
|
||||
std::map<std::string, PropertyElement>::const_iterator it = m_elements->begin();
|
||||
for (; it != m_elements->end(); ++it) {
|
||||
const PropertyElement &first = it->second;
|
||||
const PropertyElement &second = (*p.m_elements)[it->first];
|
||||
|
||||
if (!boost::apply_visitor(EqualityVisitor(&first.data), second.data))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ConfigurableObject::ConfigurableObject(Stream *stream, InstanceManager *manager)
|
||||
: SerializableObject(stream, manager) {
|
||||
|
|
|
@ -754,6 +754,7 @@ void export_core() {
|
|||
|
||||
void (Bitmap::*accumulate_1)(const Bitmap *bitmap, Point2i sourceOffset, Point2i targetOffset, Vector2i size) = &Bitmap::accumulate;
|
||||
void (Bitmap::*accumulate_2)(const Bitmap *bitmap, Point2i targetOffset) = &Bitmap::accumulate;
|
||||
const Properties &(Bitmap::*get_metadata)() const = &Bitmap::getMetadata;
|
||||
|
||||
BP_CLASS(Bitmap, Object, (bp::init<Bitmap::EPixelFormat, Bitmap::EComponentFormat, const Vector2i &>()))
|
||||
.def(bp::init<Bitmap::EPixelFormat, Bitmap::EComponentFormat, const Vector2i &, int>())
|
||||
|
@ -769,8 +770,10 @@ void export_core() {
|
|||
.def("accumulate", accumulate_1)
|
||||
.def("accumulate", accumulate_2)
|
||||
.def("write", &bitmap_write)
|
||||
.def("setString", &Bitmap::setString)
|
||||
.def("getString", &Bitmap::getString, BP_RETURN_VALUE)
|
||||
.def("setMetadataString", &Bitmap::setMetadataString)
|
||||
.def("getMetadataString", &Bitmap::getMetadataString, BP_RETURN_VALUE)
|
||||
.def("setMetadata", &Bitmap::setMetadata)
|
||||
.def("getMetadata", get_metadata, BP_RETURN_VALUE)
|
||||
.def("setGamma", &Bitmap::setGamma)
|
||||
.def("getGamma", &Bitmap::getGamma)
|
||||
.def("getWidth", &Bitmap::getWidth)
|
||||
|
|
Loading…
Reference in New Issue