added fancy annotations to ldrfilm

metadata
Wenzel Jakob 2013-01-28 17:04:12 -05:00
parent aaa16f129c
commit 89c1caed9b
4 changed files with 149 additions and 150 deletions

View File

@ -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})

137
src/films/annotations.h Normal file
View File

@ -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 */

View File

@ -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;

View File

@ -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)