made annotations more consistent

metadata
Wenzel Jakob 2013-01-28 21:45:41 -05:00
parent 568baf1c89
commit a5bbad3ace
7 changed files with 118 additions and 63 deletions

View File

@ -27,6 +27,7 @@
\usepackage{ifthen}
\usepackage{longtable}
\usepackage{wrapfig}
\usepackage{footnote} % savenotes environment
% Make sure that ligatures remain searchable in the PDF
\input glyphtounicode

View File

@ -58,7 +58,7 @@ extern MTS_EXPORT_CORE std::string formatString(const char *pFmt, ...);
extern MTS_EXPORT_CORE std::string timeString(Float time, bool precise = false);
/// Turn a memory size into a human-readable string
extern MTS_EXPORT_CORE std::string memString(size_t size);
extern MTS_EXPORT_CORE std::string memString(size_t size, bool precise = false);
/// Return a string representation of a list of objects
template<class Iterator> std::string containerToString(const Iterator &start, const Iterator &end) {

View File

@ -45,7 +45,6 @@ using std::endl;
#include <mitsuba/core/constants.h>
#include <mitsuba/core/fwd.h>
#include <mitsuba/render/fwd.h>
#include <mitsuba/core/stl.h>
#include <mitsuba/core/math.h>
#include <mitsuba/core/object.h>
#include <mitsuba/core/ref.h>

View File

@ -75,48 +75,68 @@ void annotate(const Scene *scene, const Properties &properties,
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;
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());
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());
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);
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());
const ConfigurableObject *source = NULL;
if (propSource == "scene")
source = scene;
else 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;
std::string replacement;
if (source == scene) {
if (propKey == "renderTime") {
replacement = timeString(renderTime);
} else if (propKey == "renderTimePrecise") {
replacement = timeString(renderTime, true);
} else if (propKey == "memUsage") {
replacement = memString(getPrivateMemoryUsage());
} else if (propKey == "memUsagePrecise") {
replacement = memString(getPrivateMemoryUsage(), true);
} else if (propKey == "coreCount") {
replacement = formatString("%i", Scheduler::getInstance()->getCoreCount());
} else if (propKey == "blockSize") {
replacement = formatString("%i", scene->getBlockSize());
} else if (propKey == "sourceFile") {
replacement = scene->getSourceFile().string();
} else if (propKey == "destFile") {
replacement = scene->getDestinationFile().string();
}
}
if (replacement.empty()) {
if (propKey == "type")
replacement = source->getProperties().getPluginName();
else
replacement = source->getProperties().getAsString(propKey);
value.replace(strt-value.c_str(), par2-strt+1, replacement);
}
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));

View File

@ -117,33 +117,64 @@ MTS_NAMESPACE_BEGIN
* </film>
* \end{xml}
*
* \subsubsection*{Annotations:}
* \subsubsection*{Render-time annotations:}
* \label{sec:film-annotations}
* The \pluginref{ldrfilm} and \pluginref{hdrfilm} plugins support an additional
* feature referred to as \emph{annotations}, which can be quite useful under
* certain circumstances.
*
* The \pluginref{ldrfilm} and \pluginref{hdrfilm} plugins support a
* feature referred to as \emph{render-time annotations} to facilitate
* record keeping.
* Annotations are used to embed useful information inside a rendered image so
* that this information is later available to anyone viewing the image.
* Exemplary uses of this feature might be to store the frame or take number,
* camera parameters, or other relevant scene information.
*
* Annotations can either be created by means of a \emph{tag}, which is an entry
* in the metadata table of the image file (does not modify the actual image data),
* or a \emph{text} label which is ``burned'' into the image.
* rendering time, memory usage, camera parameters, or other relevant scene
* information.
*
* Currently, two different types are supported: a \code{metadata} annotation
* creates an entry in the metadata table of the image, which is preferable
* when the image contents should not be touched. Alternatively, a \code{label}
* annotation creates a line of text that is overlaid on top of the image. Note
* that this is only visible when opening the output file (i.e. the line is not
* shown in the interactive viewer).
* The syntax of this looks as follows:
*
* \begin{xml}
* <film type="ldrfilm">
* <!-- Create a new metadata entry 'my_tag_name' and set it to the value 'my_tag_value' -->
* <string name="tag('my_tag_name')" value="my_tag_value"/>
* <film type="hdrfilm">
* <!-- Create a new metadata entry 'my_tag_name' and set it to the
* value 'my_tag_value' -->
* <string name="metadata['key_name']" value="Hello!"/>
*
* <!-- Add the label 'Hello' at the image position X=50, Y=80 -->
* <string name="text(50,80)" value="Hello!"/>
* <string name="label[50, 80]" value="Hello!"/>
* </film>
* \end{xml}
*
* The \code{value="..."} argument may also include certain identifiers that will be
* evaluated and substituted when the rendered image is written to disk. These include
* \begin{center}
* \begin{savenotes}
* \begin{tabular}{ll}
* \toprule
* \code{\$scene['renderTime']}& Render time of the image, \code{renderTimePrecise} for more digits.\\
* \code{\$scene['memUsage']}& Mitsuba memory usage\footnote{The definition of this quantity unfortunately
* varies a bit from platform to platform. On Linux and Windows, it denotes the total
* amount of allocated RAM and disk-based memory that is private to the process (i.e. not
* shared or shareable), which most intuitively captures the amount of memory required for
* rendering. On OSX, it denotes the working set size---roughly speaking, this is the
* amount of RAM apportioned to the process (i.e. excluding disk-based memory).}.
* Use \code{memUsagePrecise} for more digits.\\
* \code{\$scene['coreCount']}& Number of local and remote cores working on the rendering job\\
* \code{\$scene['blockSize']}& Block size used to parallelize up the rendering workload\\
* \code{\$scene['sourceFile']}& Source file name\\
* \code{\$scene['destFile']}& Destination file name\\
* \code{\$integrator['..']}& Copy a named integrator parameter\\
* \code{\$sensor['..']}& Copy a named sensor parameter\\
* \code{\$sampler['..']}& Copy a named sampler parameter\\
* \code{\$film['..']}& Copy a named film parameter\\
* \bottomrule
* \end{tabular}
* \end{savenotes}
* \end{center}
*/
class HDRFilm : public Film {
public:
HDRFilm(const Properties &props) : Film(props) {

View File

@ -123,19 +123,6 @@ std::string indent(const std::string &string, int amount) {
return oss.str();
}
std::string memString(size_t size) {
Float value = (Float) size;
const char *prefixes[] = {
"B", "KiB", "MiB", "GiB", "TiB", "PiB"
};
int prefix = 0;
while (prefix < 5 && value > 1024.0f) {
value /= 1024.0f; ++prefix;
}
return formatString(prefix == 0 ?
"%.0f %s" : "%.2f %s", value, prefixes[prefix]);
}
void * __restrict allocAligned(size_t size) {
#if defined(__WINDOWS__)
return _aligned_malloc(size, L1_CACHE_LINE_SIZE);
@ -809,8 +796,6 @@ Float fresnelDiffuseReflectance(Float eta, bool fast) {
}
std::string timeString(Float time, bool precise) {
std::ostringstream os;
if (std::isnan(time) || std::isinf(time))
return "inf";
@ -825,12 +810,31 @@ std::string timeString(Float time, bool precise) {
}
}
std::ostringstream os;
os << std::setprecision(precise ? 4 : 1)
<< std::fixed << time << suffix;
return os.str();
}
std::string memString(size_t size, bool precise) {
Float value = (Float) size;
const char *suffixes[] = {
"B", "KiB", "MiB", "GiB", "TiB", "PiB"
};
int suffix = 0;
while (suffix < 5 && value > 1024.0f) {
value /= 1024.0f; ++suffix;
}
std::ostringstream os;
os << std::setprecision(suffix == 0 ? 0 : (precise ? 4 : 1))
<< std::fixed << value << suffixes[suffix];
return os.str();
}
Float hypot2(Float a, Float b) {
Float r;
if (std::abs(a) > std::abs(b)) {

View File

@ -37,7 +37,7 @@ MTS_NAMESPACE_BEGIN
* A visualization of a fractal surface by Irving and Segerman.
* (a 2D Gospel curve developed up to level 5 along the third
* dimension). This scene makes use of instancing to replicate
* similar structures to cheaply render a structure that effectively
* similar structures to cheaply render a shape that effectively
* consists of several hundred millions of triangles.
* }
* }