added fancy annotations to ldrfilm
parent
aaa16f129c
commit
89c1caed9b
|
@ -8,8 +8,8 @@ macro(add_film)
|
|||
endmacro()
|
||||
|
||||
add_film(mfilm mfilm.cpp)
|
||||
add_film(ldrfilm ldrfilm.cpp banner.h MTS_HW)
|
||||
add_film(hdrfilm hdrfilm.cpp banner.h MTS_HW)
|
||||
add_film(ldrfilm ldrfilm.cpp annotations.h banner.h MTS_HW)
|
||||
add_film(hdrfilm hdrfilm.cpp annotations.h banner.h MTS_HW)
|
||||
|
||||
if (OPENEXR_FOUND)
|
||||
include_directories(${ILMBASE_INCLUDE_DIRS} ${OPENEXR_INCLUDE_DIRS})
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2012 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#if !defined(__ANNOTATIONS_H)
|
||||
#define __ANNOTATIONS_H
|
||||
|
||||
#include <mitsuba/hw/font.h>
|
||||
#include <mitsuba/render/scene.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* This function implements a parser for the 'label[]' and 'metadata[]'
|
||||
* annotations supported by the ldrfilm and hdrfilm plugins
|
||||
*/
|
||||
void annotate(const Scene *scene, const Properties &properties,
|
||||
Bitmap *bitmap, Float renderTime, Float gamma) {
|
||||
/* Attach the custom annotations */
|
||||
Properties &metadata = bitmap->getMetadata();
|
||||
std::vector<std::string> keys = properties.getPropertyNames();
|
||||
ref<Font> font;
|
||||
|
||||
for (size_t i=0; i<keys.size(); ++i) {
|
||||
std::string key = keys[i];
|
||||
key.erase(std::remove_if(key.begin(), key.end(), ::isspace), key.end());
|
||||
std::string lkey = boost::to_lower_copy(key);
|
||||
Point2i offset(0, 0);
|
||||
bool labelAnnotation = false;
|
||||
|
||||
if (boost::starts_with(lkey, "metadata['") && boost::ends_with(lkey, "']")) {
|
||||
key = key.substr(10, key.length()-12);
|
||||
} else if (boost::starts_with(lkey, "label[") && boost::ends_with(lkey, "]")) {
|
||||
std::vector<std::string> args = tokenize(key.substr(6, key.length()-7), " ,");
|
||||
if (args.size() != 2)
|
||||
SLog(EError, "Label command '%s' has an invalid number of arguments!", key.c_str());
|
||||
char *end_ptr = NULL;
|
||||
offset.x = strtol(args[0].c_str(), &end_ptr, 10);
|
||||
if (*end_ptr != '\0')
|
||||
SLog(EError, "Label command '%s' has an invalid position argument!", key.c_str());
|
||||
offset.y = strtol(args[1].c_str(), &end_ptr, 10);
|
||||
if (*end_ptr != '\0')
|
||||
SLog(EError, "Label command '%s' has an invalid position argument!", key.c_str());
|
||||
labelAnnotation = true;
|
||||
|
||||
if (font == NULL) {
|
||||
font = new Font(Font::EBitstreamVeraMono14);
|
||||
font->convert(bitmap->getPixelFormat(), bitmap->getComponentFormat(), gamma);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
Properties::EPropertyType type = properties.getType(keys[i]);
|
||||
if (type == Properties::EString) {
|
||||
std::string value = properties.getString(keys[i]);
|
||||
|
||||
while (true) {
|
||||
char *strt;
|
||||
if (!(strt = strchr((char *) value.c_str(), '$')))
|
||||
break;
|
||||
|
||||
if (strncasecmp(strt, "$rendertime", 11) == 0) {
|
||||
value.replace(strt-value.c_str(), 11, timeString(renderTime));
|
||||
} else if (strncasecmp(strt, "$memusage", 11) == 0) {
|
||||
value.replace(strt-value.c_str(), 11, memString(getPrivateMemoryUsage()));
|
||||
} else {
|
||||
char *par1, *par2;
|
||||
if (!(par1 = strchr(strt, '[')))
|
||||
break;
|
||||
if (!(par2 = strchr(par1, ']')))
|
||||
break;
|
||||
|
||||
std::string propSource = value.substr(strt-value.c_str()+1, par1-strt-1);
|
||||
std::string propKey = value.substr(par1-value.c_str()+1, par2-par1-1);
|
||||
propSource.erase(std::remove_if(propSource.begin(), propSource.end(), ::isspace), propSource.end());
|
||||
propKey.erase(std::remove_if(propKey.begin(), propKey.end(), ::isspace), propKey.end());
|
||||
|
||||
if (!boost::starts_with(propKey, "'") || !boost::ends_with(propKey, "'"))
|
||||
SLog(EError, "Encountered invalid key '%s'", propKey.c_str());
|
||||
|
||||
propKey = propKey.substr(1, propKey.length()-2);
|
||||
|
||||
const ConfigurableObject *source = NULL;
|
||||
if (propSource == "film")
|
||||
source = scene->getFilm();
|
||||
else if (propSource == "sampler")
|
||||
source = scene->getSampler();
|
||||
else if (propSource == "sensor")
|
||||
source = scene->getSensor();
|
||||
else if (propSource == "integrator")
|
||||
source = scene->getIntegrator();
|
||||
else
|
||||
SLog(EError, "Unknown data source '%s' (must be film/sampler/sensor/integrator)", propSource.c_str());
|
||||
|
||||
std::string replacement;
|
||||
if (propKey == "type")
|
||||
replacement = source->getProperties().getPluginName();
|
||||
else
|
||||
replacement = source->getProperties().getAsString(propKey);
|
||||
|
||||
value.replace(strt-value.c_str(), par2-strt+1, replacement);
|
||||
}
|
||||
}
|
||||
if (labelAnnotation) {
|
||||
Vector2i size = font->getSize(value);
|
||||
bitmap->fillRect(offset-Vector2i(4, 4), size + Vector2i(8, 8), Spectrum(0.0f));
|
||||
font->drawText(bitmap, offset, value);
|
||||
} else {
|
||||
metadata.setString(key, value);
|
||||
}
|
||||
} else {
|
||||
if (labelAnnotation)
|
||||
SLog(EError, "Only string-valued label annotations are supported!");
|
||||
metadata.copyAttribute(properties, keys[i], key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __ANNOTATIONS_H */
|
|
@ -20,10 +20,9 @@
|
|||
#include <mitsuba/core/fstream.h>
|
||||
#include <mitsuba/core/bitmap.h>
|
||||
#include <mitsuba/core/statistics.h>
|
||||
#include <mitsuba/hw/font.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <mitsuba/render/scene.h>
|
||||
#include "banner.h"
|
||||
#include "annotations.h"
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -369,107 +368,7 @@ public:
|
|||
Log(EInfo, "Writing image to \"%s\" ..", filename.string().c_str());
|
||||
ref<FileStream> stream = new FileStream(filename, FileStream::ETruncWrite);
|
||||
|
||||
/* Attach the custom annotations */
|
||||
Properties &metadata = bitmap->getMetadata();
|
||||
std::vector<std::string> keys = m_properties.getPropertyNames();
|
||||
ref<Font> font;
|
||||
Float gamma = 1.0f; /// XXX
|
||||
|
||||
for (size_t i=0; i<keys.size(); ++i) {
|
||||
std::string key = keys[i];
|
||||
key.erase(std::remove_if(key.begin(), key.end(), ::isspace), key.end());
|
||||
std::string lkey = boost::to_lower_copy(key);
|
||||
Point2i offset(0, 0);
|
||||
bool labelAnnotation = false;
|
||||
|
||||
if (boost::starts_with(lkey, "metadata['") && boost::ends_with(lkey, "']")) {
|
||||
key = key.substr(10, key.length()-12);
|
||||
} else if (boost::starts_with(lkey, "label[") && boost::ends_with(lkey, "]")) {
|
||||
std::vector<std::string> args = tokenize(key.substr(6, key.length()-7), " ,");
|
||||
if (args.size() != 2)
|
||||
Log(EError, "Label command '%s' has an invalid number of arguments!", key.c_str());
|
||||
char *end_ptr = NULL;
|
||||
offset.x = strtol(args[0].c_str(), &end_ptr, 10);
|
||||
if (*end_ptr != '\0')
|
||||
Log(EError, "Label command '%s' has an invalid position argument!", key.c_str());
|
||||
offset.y = strtol(args[1].c_str(), &end_ptr, 10);
|
||||
if (*end_ptr != '\0')
|
||||
Log(EError, "Label command '%s' has an invalid position argument!", key.c_str());
|
||||
labelAnnotation = true;
|
||||
|
||||
if (font == NULL) {
|
||||
font = new Font(Font::EBitstreamVeraMono14);
|
||||
font->convert(bitmap->getPixelFormat(), bitmap->getComponentFormat(), gamma);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
Properties::EPropertyType type = m_properties.getType(keys[i]);
|
||||
if (type == Properties::EString) {
|
||||
std::string value = m_properties.getString(keys[i]);
|
||||
|
||||
while (true) {
|
||||
char *strt;
|
||||
if (!(strt = strchr((char *) value.c_str(), '$')))
|
||||
break;
|
||||
|
||||
if (strncasecmp(strt, "$rendertime", 11) == 0) {
|
||||
value.replace(strt-value.c_str(), 11, timeString(renderTime));
|
||||
} else if (strncasecmp(strt, "$memusage", 11) == 0) {
|
||||
value.replace(strt-value.c_str(), 11, memString(getPrivateMemoryUsage()));
|
||||
} else {
|
||||
char *par1, *par2;
|
||||
if (!(par1 = strchr(strt, '[')))
|
||||
break;
|
||||
if (!(par2 = strchr(par1, ']')))
|
||||
break;
|
||||
|
||||
std::string propSource = value.substr(strt-value.c_str()+1, par1-strt-1);
|
||||
std::string propKey = value.substr(par1-value.c_str()+1, par2-par1-1);
|
||||
propSource.erase(std::remove_if(propSource.begin(), propSource.end(), ::isspace), propSource.end());
|
||||
propKey.erase(std::remove_if(propKey.begin(), propKey.end(), ::isspace), propKey.end());
|
||||
|
||||
if (!boost::starts_with(propKey, "'") || !boost::ends_with(propKey, "'"))
|
||||
Log(EError, "Encountered invalid key '%s'", propKey.c_str());
|
||||
|
||||
propKey = propKey.substr(1, propKey.length()-2);
|
||||
|
||||
const ConfigurableObject *source = NULL;
|
||||
if (propSource == "film")
|
||||
source = scene->getFilm();
|
||||
else if (propSource == "sampler")
|
||||
source = scene->getSampler();
|
||||
else if (propSource == "sensor")
|
||||
source = scene->getSensor();
|
||||
else if (propSource == "integrator")
|
||||
source = scene->getIntegrator();
|
||||
else
|
||||
Log(EError, "Unknown data source '%s' (must be film/sampler/sensor/integrator)", propSource.c_str());
|
||||
|
||||
std::string replacement;
|
||||
if (propKey == "type")
|
||||
replacement = source->getProperties().getPluginName();
|
||||
else
|
||||
replacement = source->getProperties().getAsString(propKey);
|
||||
|
||||
value.replace(strt-value.c_str(), par2-strt+1, replacement);
|
||||
}
|
||||
cout << value << endl;
|
||||
}
|
||||
if (labelAnnotation) {
|
||||
Vector2i size = font->getSize(value);
|
||||
bitmap->fillRect(offset-Vector2i(4, 4), size + Vector2i(8, 8), Spectrum(0.0f));
|
||||
font->drawText(bitmap, offset, value);
|
||||
} else {
|
||||
metadata.setString(key, value);
|
||||
}
|
||||
} else {
|
||||
if (labelAnnotation)
|
||||
Log(EError, "Only string-valued label annotations are supported!");
|
||||
metadata.copyAttribute(m_properties, keys[i], key);
|
||||
}
|
||||
}
|
||||
annotate(scene, m_properties, bitmap, renderTime, 1.0f);
|
||||
|
||||
/* Attach the log file to the image if this is requested */
|
||||
Logger *logger = Thread::getThread()->getLogger();
|
||||
|
@ -477,7 +376,7 @@ public:
|
|||
if (m_attachLog && logger->readLog(log)) {
|
||||
log += "\n\n";
|
||||
log += Statistics::getInstance()->getStats();
|
||||
metadata.setString("log", log);
|
||||
bitmap->setMetadataString("log", log);
|
||||
}
|
||||
|
||||
bitmap->write(m_fileFormat, stream);
|
||||
|
@ -516,11 +415,6 @@ public:
|
|||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
struct Annotation {
|
||||
Point2i offset;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
Bitmap::EFileFormat m_fileFormat;
|
||||
Bitmap::EPixelFormat m_pixelFormat;
|
||||
Bitmap::EComponentFormat m_componentFormat;
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
#include <mitsuba/core/fstream.h>
|
||||
#include <mitsuba/core/bitmap.h>
|
||||
#include <mitsuba/core/statistics.h>
|
||||
#include <mitsuba/hw/font.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "banner.h"
|
||||
#include "annotations.h"
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -185,20 +185,11 @@ public:
|
|||
std::vector<std::string> keys = props.getPropertyNames();
|
||||
for (size_t i=0; i<keys.size(); ++i) {
|
||||
std::string key = boost::to_lower_copy(keys[i]);
|
||||
key.erase(std::remove_if(key.begin(), key.end(), ::isspace), key.end());
|
||||
|
||||
if (boost::starts_with(key, "tag('") && boost::ends_with(key, "')")) {
|
||||
m_tags[keys[i].substr(5, key.length()-7)] = props.getString(keys[i]);
|
||||
} else if (boost::starts_with(key, "text(") && boost::ends_with(key, ")")) {
|
||||
std::vector<std::string> args = tokenize(key.substr(5, key.length()-6), " ,");
|
||||
|
||||
if (args.size() != 2)
|
||||
Log(EError, "Text command '%s' has an invalid number of arguments!", key.c_str());
|
||||
|
||||
Annotation annotation;
|
||||
annotation.offset = Point2i(atoi(args[0].c_str()), atoi(args[1].c_str()));
|
||||
annotation.text = props.getString(keys[i]);
|
||||
m_annotations.push_back(annotation);
|
||||
}
|
||||
if ((boost::starts_with(key, "tag('") && boost::ends_with(key, "')")) ||
|
||||
(boost::starts_with(key, "text(") && boost::ends_with(key, ")")))
|
||||
props.markQueried(keys[i]);
|
||||
}
|
||||
|
||||
m_storage = new ImageBlock(Bitmap::ESpectrumAlphaWeight, m_cropSize);
|
||||
|
@ -338,23 +329,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
if (!m_annotations.empty()) {
|
||||
ref<Font> font = new Font(Font::EBitstreamVeraMono14);
|
||||
font->convert(bitmap->getPixelFormat(), bitmap->getComponentFormat(), m_gamma);
|
||||
|
||||
for (size_t i=0; i<m_annotations.size(); ++i) {
|
||||
const Point2i &offset = m_annotations[i].offset;
|
||||
const std::string &text = m_annotations[i].text;
|
||||
Vector2i size = font->getSize(text);
|
||||
bitmap->fillRect(offset-Vector2i(4, 4), size + Vector2i(8, 8), Spectrum(0.0f));
|
||||
font->drawText(bitmap, offset, text);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::map<std::string, std::string>::const_iterator it = m_tags.begin();
|
||||
it != m_tags.end(); ++it)
|
||||
bitmap->setMetadataString(it->first, it->second);
|
||||
|
||||
fs::path filename = m_destFile;
|
||||
std::string extension = boost::to_lower_copy(filename.extension().string());
|
||||
std::string expectedExtension;
|
||||
|
@ -370,6 +344,8 @@ public:
|
|||
Log(EInfo, "Writing image to \"%s\" ..", filename.string().c_str());
|
||||
ref<FileStream> stream = new FileStream(filename, FileStream::ETruncWrite);
|
||||
|
||||
annotate(scene, m_properties, bitmap, renderTime, m_gamma);
|
||||
|
||||
bitmap->write(m_fileFormat, stream);
|
||||
}
|
||||
|
||||
|
@ -415,11 +391,6 @@ public:
|
|||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
struct Annotation {
|
||||
Point2i offset;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
Bitmap::EFileFormat m_fileFormat;
|
||||
Bitmap::EPixelFormat m_pixelFormat;
|
||||
bool m_hasBanner;
|
||||
|
@ -428,9 +399,6 @@ protected:
|
|||
ref<ImageBlock> m_storage;
|
||||
ETonemapMethod m_tonemapMethod;
|
||||
Float m_exposure, m_reinhardKey, m_reinhardBurn;
|
||||
|
||||
std::vector<Annotation> m_annotations;
|
||||
std::map<std::string, std::string> m_tags;
|
||||
};
|
||||
|
||||
MTS_IMPLEMENT_CLASS_S(LDRFilm, false, Film)
|
||||
|
|
Loading…
Reference in New Issue