debugging..

metadata
Wenzel Jakob 2014-02-15 01:34:17 +01:00
parent ee5b29878f
commit 8d84d0b1a0
5 changed files with 272 additions and 182 deletions

View File

@ -678,12 +678,17 @@ public:
* specified component format. Names for each of the resulting channels should * specified component format. Names for each of the resulting channels should
* be provided via the \c channelNames parameters. * be provided via the \c channelNames parameters.
* *
* This function is currently only used by the \c hdrfilm plugin but located here * This feature is currently used by the \c hdrfilm and \c tiledhdrfilm plugins.
* as it is tied to the internals of this class.
*/ */
ref<Bitmap> convertMultiSpectrumAlphaWeight(const std::vector<EPixelFormat> &pixelFormats, ref<Bitmap> convertMultiSpectrumAlphaWeight(const std::vector<EPixelFormat> &pixelFormats,
EComponentFormat componentFormat, const std::vector<std::string> &channelNames) const; EComponentFormat componentFormat, const std::vector<std::string> &channelNames) const;
/// Similar to the above, but writes to an already existing image
static void convertMultiSpectrumAlphaWeight(const Bitmap *source,
const uint8_t *sourcePtr, const Bitmap *target, uint8_t *targetPtr,
const std::vector<EPixelFormat> &pixelFormats,
EComponentFormat componentFormat, size_t count);
/** /**
* \brief Apply Reinhard et al's tonemapper in chromaticity space * \brief Apply Reinhard et al's tonemapper in chromaticity space
* *

View File

@ -215,7 +215,7 @@ public:
std::vector<std::string> pixelFormats = tokenize(boost::to_lower_copy( std::vector<std::string> pixelFormats = tokenize(boost::to_lower_copy(
props.getString("pixelFormat", "rgb")), " ,"); props.getString("pixelFormat", "rgb")), " ,");
std::vector<std::string> channelNames = tokenize( std::vector<std::string> channelNames = tokenize(
props.getString("channelNames", "rgb"), ", "); props.getString("channelNames", ""), ", ");
std::string componentFormat = boost::to_lower_copy( std::string componentFormat = boost::to_lower_copy(
props.getString("componentFormat", "float16")); props.getString("componentFormat", "float16"));
@ -238,47 +238,50 @@ public:
for (size_t i=0; i<pixelFormats.size(); ++i) { for (size_t i=0; i<pixelFormats.size(); ++i) {
std::string pixelFormat = pixelFormats[i]; std::string pixelFormat = pixelFormats[i];
std::string name = i < channelNames.size() ? channelNames[i] : ""; std::string name = i < channelNames.size() ? (channelNames[i] + std::string(".")) : "";
if (pixelFormat == "luminance") { if (pixelFormat == "luminance") {
m_pixelFormats.push_back(Bitmap::ELuminance); m_pixelFormats.push_back(Bitmap::ELuminance);
m_channelNames.push_back(name + ".Y"); m_channelNames.push_back(name + "Y");
} else if (pixelFormat == "luminancealpha") { } else if (pixelFormat == "luminancealpha") {
m_pixelFormats.push_back(Bitmap::ELuminanceAlpha); m_pixelFormats.push_back(Bitmap::ELuminanceAlpha);
m_channelNames.push_back(name + ".Y"); m_channelNames.push_back(name + "Y");
m_channelNames.push_back(name + ".A"); m_channelNames.push_back(name + "A");
} else if (pixelFormat == "rgb") { } else if (pixelFormat == "rgb") {
m_pixelFormats.push_back(Bitmap::ERGB); m_pixelFormats.push_back(Bitmap::ERGB);
m_channelNames.push_back(name + ".R"); m_channelNames.push_back(name + "R");
m_channelNames.push_back(name + ".G"); m_channelNames.push_back(name + "G");
m_channelNames.push_back(name + ".B"); m_channelNames.push_back(name + "B");
} else if (pixelFormat == "rgba") { } else if (pixelFormat == "rgba") {
m_pixelFormats.push_back(Bitmap::ERGBA); m_pixelFormats.push_back(Bitmap::ERGBA);
m_channelNames.push_back(name + ".R"); m_channelNames.push_back(name + "R");
m_channelNames.push_back(name + ".G"); m_channelNames.push_back(name + "G");
m_channelNames.push_back(name + ".B"); m_channelNames.push_back(name + "B");
m_channelNames.push_back(name + ".A"); m_channelNames.push_back(name + "A");
} else if (pixelFormat == "xyz") { } else if (pixelFormat == "xyz") {
m_pixelFormats.push_back(Bitmap::EXYZ); m_pixelFormats.push_back(Bitmap::EXYZ);
if (m_pixelFormats.size() > 1) m_channelNames.push_back(name + "X");
Log(EError, "The XYZ pixel format is not supported for general multi-channel images!"); m_channelNames.push_back(name + "Y");
m_channelNames.push_back(name + "Z");
} else if (pixelFormat == "xyza") { } else if (pixelFormat == "xyza") {
m_pixelFormats.push_back(Bitmap::EXYZA); m_pixelFormats.push_back(Bitmap::EXYZA);
if (m_pixelFormats.size() > 1) m_channelNames.push_back(name + "X");
Log(EError, "The XYZA pixel format is not supported for general multi-channel images!"); m_channelNames.push_back(name + "Y");
m_channelNames.push_back(name + "Z");
m_channelNames.push_back(name + "A");
} else if (pixelFormat == "spectrum") { } else if (pixelFormat == "spectrum") {
m_pixelFormats.push_back(Bitmap::ESpectrum); m_pixelFormats.push_back(Bitmap::ESpectrum);
for (int i=0; i<SPECTRUM_SAMPLES; ++i) { for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i); std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
m_channelNames.push_back(name + formatString(".%.2f-%.2fnm", coverage.first, coverage.second)); m_channelNames.push_back(name + formatString("%.2f-%.2fnm", coverage.first, coverage.second));
} }
} else if (pixelFormat == "spectrumalpha") { } else if (pixelFormat == "spectrumalpha") {
m_pixelFormats.push_back(Bitmap::ESpectrumAlpha); m_pixelFormats.push_back(Bitmap::ESpectrumAlpha);
for (int i=0; i<SPECTRUM_SAMPLES; ++i) { for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i); std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
m_channelNames.push_back(name + formatString(".%.2f-%.2fnm", coverage.first, coverage.second)); m_channelNames.push_back(name + formatString("%.2f-%.2fnm", coverage.first, coverage.second));
} }
m_channelNames.push_back(name + ".A"); m_channelNames.push_back(name + "A");
} else { } else {
Log(EError, "The \"pixelFormat\" parameter must either be equal to " Log(EError, "The \"pixelFormat\" parameter must either be equal to "
"\"luminance\", \"luminanceAlpha\", \"rgb\", \"rgba\", \"xyz\", \"xyza\", " "\"luminance\", \"luminanceAlpha\", \"rgb\", \"rgba\", \"xyz\", \"xyza\", "
@ -529,13 +532,14 @@ public:
} }
bool hasAlpha() const { bool hasAlpha() const {
Assert(m_pixelFormats.size() > 0); for (size_t i=0; i<m_pixelFormats.size(); ++i) {
return if (m_pixelFormats[i] == Bitmap::ELuminanceAlpha ||
m_pixelFormats[0] == Bitmap::ELuminanceAlpha || m_pixelFormats[i] == Bitmap::ERGBA ||
m_pixelFormats[0] == Bitmap::ERGBA || m_pixelFormats[i] == Bitmap::EXYZA ||
m_pixelFormats[0] == Bitmap::EXYZA || m_pixelFormats[i] == Bitmap::ESpectrumAlpha)
m_pixelFormats[0] == Bitmap::ESpectrumAlpha || return true;
m_pixelFormats.size() > 1; }
return false;
} }
bool destinationExists(const fs::path &baseName) const { bool destinationExists(const fs::path &baseName) const {

View File

@ -101,37 +101,78 @@ MTS_NAMESPACE_BEGIN
class TiledHDRFilm : public Film { class TiledHDRFilm : public Film {
public: public:
TiledHDRFilm(const Properties &props) : Film(props), m_output(NULL), m_frameBuffer(NULL) { TiledHDRFilm(const Properties &props) : Film(props), m_output(NULL), m_frameBuffer(NULL) {
std::string pixelFormat = boost::to_lower_copy( std::vector<std::string> pixelFormats = tokenize(boost::to_lower_copy(
props.getString("pixelFormat", "rgb")); props.getString("pixelFormat", "rgb")), " ,");
std::vector<std::string> channelNames = tokenize(
props.getString("channelNames", ""), ", ");
std::string componentFormat = boost::to_lower_copy( std::string componentFormat = boost::to_lower_copy(
props.getString("componentFormat", "float16")); props.getString("componentFormat", "float16"));
if (pixelFormat == "luminance") { if (pixelFormats.empty())
m_pixelFormat = Bitmap::ELuminance; Log(EError, "At least one pixel format must be specified!");
} else if (pixelFormat == "luminancealpha") {
m_pixelFormat = Bitmap::ELuminanceAlpha; if (m_pixelFormats.size() != 1 && m_channelNames.size() != m_pixelFormats.size())
} else if (pixelFormat == "rgb") { Log(EError, "Number of channel names must match the number of specified pixel formats!");
m_pixelFormat = Bitmap::ERGB;
} else if (pixelFormat == "rgba") { for (size_t i=0; i<pixelFormats.size(); ++i) {
m_pixelFormat = Bitmap::ERGBA; std::string pixelFormat = pixelFormats[i];
} else if (pixelFormat == "xyz") { std::string name = i < channelNames.size() ? (channelNames[i] + std::string(".")) : "";
m_pixelFormat = Bitmap::EXYZ;
} else if (pixelFormat == "xyza") { if (pixelFormat == "luminance") {
m_pixelFormat = Bitmap::EXYZA; m_pixelFormats.push_back(Bitmap::ELuminance);
} else if (pixelFormat == "spectrum") { m_channelNames.push_back(name + "Y");
m_pixelFormat = Bitmap::ESpectrum; } else if (pixelFormat == "luminancealpha") {
} else if (pixelFormat == "spectrumalpha") { m_pixelFormats.push_back(Bitmap::ELuminanceAlpha);
m_pixelFormat = Bitmap::ESpectrumAlpha; m_channelNames.push_back(name + "Y");
} else { m_channelNames.push_back(name + "A");
Log(EError, "The \"pixelFormat\" parameter must either be equal to " } else if (pixelFormat == "rgb") {
"\"luminance\", \"luminanceAlpha\", \"rgb\", \"rgba\", \"xyz\", \"xyza\", " m_pixelFormats.push_back(Bitmap::ERGB);
"\"spectrum\", or \"spectrumAlpha\"!"); m_channelNames.push_back(name + "R");
m_channelNames.push_back(name + "G");
m_channelNames.push_back(name + "B");
} else if (pixelFormat == "rgba") {
m_pixelFormats.push_back(Bitmap::ERGBA);
m_channelNames.push_back(name + "R");
m_channelNames.push_back(name + "G");
m_channelNames.push_back(name + "B");
m_channelNames.push_back(name + "A");
} else if (pixelFormat == "xyz") {
m_pixelFormats.push_back(Bitmap::EXYZ);
m_channelNames.push_back(name + "X");
m_channelNames.push_back(name + "Y");
m_channelNames.push_back(name + "Z");
} else if (pixelFormat == "xyza") {
m_pixelFormats.push_back(Bitmap::EXYZA);
m_channelNames.push_back(name + "X");
m_channelNames.push_back(name + "Y");
m_channelNames.push_back(name + "Z");
m_channelNames.push_back(name + "A");
} else if (pixelFormat == "spectrum") {
m_pixelFormats.push_back(Bitmap::ESpectrum);
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
m_channelNames.push_back(name + formatString("%.2f-%.2fnm", coverage.first, coverage.second));
}
} else if (pixelFormat == "spectrumalpha") {
m_pixelFormats.push_back(Bitmap::ESpectrumAlpha);
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
m_channelNames.push_back(name + formatString("%.2f-%.2fnm", coverage.first, coverage.second));
}
m_channelNames.push_back(name + "A");
} else {
Log(EError, "The \"pixelFormat\" parameter must either be equal to "
"\"luminance\", \"luminanceAlpha\", \"rgb\", \"rgba\", \"xyz\", \"xyza\", "
"\"spectrum\", or \"spectrumAlpha\"!");
}
} }
if (SPECTRUM_SAMPLES == 3 && (m_pixelFormat == Bitmap::ESpectrum || m_pixelFormat == Bitmap::ESpectrumAlpha)) for (size_t i=0; i<m_pixelFormats.size(); ++i) {
Log(EError, "You requested to render a spectral image, but Mitsuba is currently " if (SPECTRUM_SAMPLES == 3 && (m_pixelFormats[i] == Bitmap::ESpectrum || m_pixelFormats[i] == Bitmap::ESpectrumAlpha))
"configured for a RGB flow (i.e. SPECTRUM_SAMPLES = 3). You will need to recompile " Log(EError, "You requested to render a spectral image, but Mitsuba is currently "
"it with a different configuration. Please see the documentation for details."); "configured for a RGB flow (i.e. SPECTRUM_SAMPLES = 3). You will need to recompile "
"it with a different configuration. Please see the documentation for details.");
}
if (componentFormat == "float16") { if (componentFormat == "float16") {
m_componentFormat = Bitmap::EFloat16; m_componentFormat = Bitmap::EFloat16;
@ -151,7 +192,12 @@ public:
TiledHDRFilm(Stream *stream, InstanceManager *manager) TiledHDRFilm(Stream *stream, InstanceManager *manager)
: Film(stream, manager), m_output(NULL), m_frameBuffer(NULL) { : Film(stream, manager), m_output(NULL), m_frameBuffer(NULL) {
m_pixelFormat = (Bitmap::EPixelFormat) stream->readUInt(); m_pixelFormats.resize((size_t) stream->readUInt());
for (size_t i=0; i<m_pixelFormats.size(); ++i)
m_pixelFormats[i] = (Bitmap::EPixelFormat) stream->readUInt();
m_channelNames.resize((size_t) stream->readUInt());
for (size_t i=0; i<m_channelNames.size(); ++i)
m_channelNames[i] = stream->readString();
m_componentFormat = (Bitmap::EComponentFormat) stream->readUInt(); m_componentFormat = (Bitmap::EComponentFormat) stream->readUInt();
} }
@ -161,7 +207,11 @@ public:
void serialize(Stream *stream, InstanceManager *manager) const { void serialize(Stream *stream, InstanceManager *manager) const {
Film::serialize(stream, manager); Film::serialize(stream, manager);
stream->writeUInt(m_pixelFormat); for (size_t i=0; i<m_pixelFormats.size(); ++i)
stream->writeUInt(m_pixelFormats[i]);
stream->writeUInt((uint32_t) m_channelNames.size());
for (size_t i=0; i<m_channelNames.size(); ++i)
stream->writeString(m_channelNames[i]);
stream->writeUInt(m_componentFormat); stream->writeUInt(m_componentFormat);
} }
@ -169,15 +219,6 @@ public:
if (m_output) if (m_output)
develop(NULL, 0); develop(NULL, 0);
Bitmap::EPixelFormat pixelFormat = m_pixelFormat;
#if SPECTRUM_SAMPLES == 3
if (pixelFormat == Bitmap::ESpectrum)
pixelFormat = Bitmap::ERGB;
if (pixelFormat == Bitmap::ESpectrumAlpha)
pixelFormat = Bitmap::ERGBA;
#endif
fs::path filename = destFile; fs::path filename = destFile;
std::string extension = boost::to_lower_copy(filename.extension().string()); std::string extension = boost::to_lower_copy(filename.extension().string());
if (extension != ".exr") if (extension != ".exr")
@ -189,19 +230,22 @@ public:
header.setTileDescription(Imf::TileDescription(blockSize, blockSize, Imf::ONE_LEVEL)); header.setTileDescription(Imf::TileDescription(blockSize, blockSize, Imf::ONE_LEVEL));
header.insert("generated-by", Imf::StringAttribute("Mitsuba version " MTS_VERSION)); header.insert("generated-by", Imf::StringAttribute("Mitsuba version " MTS_VERSION));
if (pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) { if (m_pixelFormats.size() == 1) {
Imf::addChromaticities(header, Imf::Chromaticities( /* Write a chromaticity tag when this is possible */
Imath::V2f(1.0f, 0.0f), Bitmap::EPixelFormat pixelFormat = m_pixelFormats[0];
Imath::V2f(0.0f, 1.0f), if (pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) {
Imath::V2f(0.0f, 0.0f), Imf::addChromaticities(header, Imf::Chromaticities(
Imath::V2f(1.0f/3.0f, 1.0f/3.0f))); Imath::V2f(1.0f, 0.0f),
} else if (pixelFormat == Bitmap::ERGB || pixelFormat == Bitmap::ERGBA) { Imath::V2f(0.0f, 1.0f),
Imf::addChromaticities(header, Imf::Chromaticities()); Imath::V2f(0.0f, 0.0f),
Imath::V2f(1.0f/3.0f, 1.0f/3.0f)));
} else if (pixelFormat == Bitmap::ERGB || pixelFormat == Bitmap::ERGBA) {
Imf::addChromaticities(header, Imf::Chromaticities());
}
} }
Imf::PixelType compType; Imf::PixelType compType;
size_t compStride; size_t compStride;
int channelCount;
if (m_componentFormat == Bitmap::EFloat16) { if (m_componentFormat == Bitmap::EFloat16) {
compType = Imf::HALF; compType = Imf::HALF;
@ -219,62 +263,34 @@ public:
} }
Imf::ChannelList &channels = header.channels(); Imf::ChannelList &channels = header.channels();
if (pixelFormat == Bitmap::ELuminance || pixelFormat == Bitmap::ELuminanceAlpha) { for (size_t i=0; i<m_channelNames.size(); ++i)
channels.insert("Y", Imf::Channel(compType)); channels.insert(m_channelNames[i], Imf::Channel(compType));
channelCount = 1;
} else if (pixelFormat == Bitmap::ERGB || pixelFormat == Bitmap::ERGBA ||
pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) {
channels.insert("R", Imf::Channel(compType));
channels.insert("G", Imf::Channel(compType));
channels.insert("B", Imf::Channel(compType));
channelCount = 3;
} else if (pixelFormat == Bitmap::ESpectrum || pixelFormat == Bitmap::ESpectrumAlpha) {
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
std::string name = formatString("%.2f-%.2fnm", coverage.first, coverage.second);
channels.insert(name.c_str(), Imf::Channel(compType));
}
channelCount = SPECTRUM_SAMPLES;
} else {
Log(EError, "Invalid pixel format!");
return;
}
if (m_pixelFormat == Bitmap::ELuminanceAlpha || m_pixelFormat == Bitmap::ERGBA ||
m_pixelFormat == Bitmap::ESpectrumAlpha) {
channels.insert("A", Imf::Channel(compType));
channelCount++;
}
m_output = new Imf::TiledOutputFile(filename.string().c_str(), header); m_output = new Imf::TiledOutputFile(filename.string().c_str(), header);
m_frameBuffer = new Imf::FrameBuffer(); m_frameBuffer = new Imf::FrameBuffer();
m_blockSize = (int) blockSize; m_blockSize = (int) blockSize;
m_tile = new Bitmap(m_pixelFormat, m_componentFormat, Vector2i(m_blockSize, m_blockSize));
m_blocksH = (m_size.x + blockSize - 1) / blockSize; m_blocksH = (m_size.x + blockSize - 1) / blockSize;
m_blocksV = (m_size.y + blockSize - 1) / blockSize; m_blocksV = (m_size.y + blockSize - 1) / blockSize;
m_pixelStride = channelCount * compStride; m_pixelStride = m_channelNames.size() * compStride;
m_rowStride = m_pixelStride * m_blockSize; m_rowStride = m_pixelStride * m_blockSize;
char *ptr = (char *) m_tile->getUInt8Data();
if (pixelFormat == Bitmap::ELuminance || pixelFormat == Bitmap::ELuminanceAlpha) { if (m_pixelFormats.size() == 1) {
m_frameBuffer->insert("Y", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride; m_tile = new Bitmap(m_pixelFormats[0], m_componentFormat,
} else if (pixelFormat == Bitmap::ERGB || pixelFormat == Bitmap::ERGBA || Vector2i(m_blockSize, m_blockSize));
pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) { } else {
m_frameBuffer->insert("R", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride; m_tile = new Bitmap(Bitmap::EMultiChannel, m_componentFormat,
m_frameBuffer->insert("G", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride; Vector2i(m_blockSize, m_blockSize), m_channelNames.size());
m_frameBuffer->insert("B", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride; m_tile->setChannelNames(m_channelNames);
} else if (pixelFormat == Bitmap::ESpectrum || pixelFormat == Bitmap::ESpectrumAlpha) {
for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
std::pair<Float, Float> coverage = Spectrum::getBinCoverage(i);
std::string name = formatString("%f-%fnm", coverage.first, coverage.second);
m_frameBuffer->insert(name.c_str(), Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride;
}
} }
if (m_pixelFormat == Bitmap::ERGBA || m_pixelFormat == Bitmap::EXYZA || char *ptr = (char *) m_tile->getUInt8Data();
m_pixelFormat == Bitmap::ELuminanceAlpha)
m_frameBuffer->insert("A", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); for (size_t i=0; i<m_channelNames.size(); ++i) {
m_frameBuffer->insert(m_channelNames[i],
Imf::Slice(compType, ptr, m_pixelStride, m_rowStride));
ptr += compStride;
}
m_output->setFrameBuffer(*m_frameBuffer); m_output->setFrameBuffer(*m_frameBuffer);
m_peakUsage = 0; m_peakUsage = 0;
@ -388,6 +404,7 @@ public:
} }
const Bitmap *source = mergedBlock->getBitmap(); const Bitmap *source = mergedBlock->getBitmap();
size_t sourceBpp = source->getBytesPerPixel(); size_t sourceBpp = source->getBytesPerPixel();
size_t targetBpp = m_tile->getBytesPerPixel(); size_t targetBpp = m_tile->getBytesPerPixel();
@ -400,11 +417,15 @@ public:
); );
for (int i=0; i<m_blockSize; ++i) { for (int i=0; i<m_blockSize; ++i) {
cvt->convert(source->getPixelFormat(), 1.0f, sourceData, if (m_pixelFormats.size() == 1)
m_tile->getPixelFormat(), m_tile->getGamma(), targetData, cvt->convert(source->getPixelFormat(), 1.0f, sourceData,
m_tile->getWidth()); m_tile->getPixelFormat(), m_tile->getGamma(), targetData,
m_tile->getWidth());
else
Bitmap::convertMultiSpectrumAlphaWeight(source, sourceData,
m_tile, targetData, m_pixelFormats, m_componentFormat, m_tile->getWidth());
sourceData += source->getWidth() * sourceBpp; sourceData += source->getWidth() * sourceBpp;
targetData += m_tile->getWidth() * targetBpp; targetData += m_tile->getWidth() * targetBpp;
} }
@ -470,11 +491,14 @@ public:
void clear() { /* Do nothing */ } void clear() { /* Do nothing */ }
bool hasAlpha() const { bool hasAlpha() const {
return for (size_t i=0; i<m_pixelFormats.size(); ++i) {
m_pixelFormat == Bitmap::ELuminanceAlpha || if (m_pixelFormats[i] == Bitmap::ELuminanceAlpha ||
m_pixelFormat == Bitmap::ERGBA || m_pixelFormats[i] == Bitmap::ERGBA ||
m_pixelFormat == Bitmap::EXYZA || m_pixelFormats[i] == Bitmap::EXYZA ||
m_pixelFormat == Bitmap::ESpectrumAlpha; m_pixelFormats[i] == Bitmap::ESpectrumAlpha)
return true;
}
return false;
} }
bool destinationExists(const fs::path &baseName) const { bool destinationExists(const fs::path &baseName) const {
@ -488,7 +512,14 @@ public:
std::ostringstream oss; std::ostringstream oss;
oss << "TiledHDRFilm[" << endl oss << "TiledHDRFilm[" << endl
<< " size = " << m_size.toString() << "," << endl << " size = " << m_size.toString() << "," << endl
<< " pixelFormat = " << m_pixelFormat << "," << endl << " pixelFormat = ";
for (size_t i=0; i<m_pixelFormats.size(); ++i)
oss << m_pixelFormats[i] << ", ";
oss << endl
<< " channelNames = ";
for (size_t i=0; i<m_channelNames.size(); ++i)
oss << "\"" << m_channelNames[i] << "\"" << ", ";
oss << endl
<< " componentFormat = " << m_componentFormat << "," << endl << " componentFormat = " << m_componentFormat << "," << endl
<< " cropOffset = " << m_cropOffset.toString() << "," << endl << " cropOffset = " << m_cropOffset.toString() << "," << endl
<< " cropSize = " << m_cropSize.toString() << "," << endl << " cropSize = " << m_cropSize.toString() << "," << endl
@ -499,7 +530,8 @@ public:
MTS_DECLARE_CLASS() MTS_DECLARE_CLASS()
protected: protected:
Bitmap::EPixelFormat m_pixelFormat; std::vector<Bitmap::EPixelFormat> m_pixelFormats;
std::vector<std::string> m_channelNames;
Bitmap::EComponentFormat m_componentFormat; Bitmap::EComponentFormat m_componentFormat;
std::vector<ImageBlock *> m_freeBlocks; std::vector<ImageBlock *> m_freeBlocks;
std::map<uint32_t, ImageBlock *> m_origBlocks, m_mergedBlocks; std::map<uint32_t, ImageBlock *> m_origBlocks, m_mergedBlocks;

View File

@ -23,7 +23,30 @@ MTS_NAMESPACE_BEGIN
/*! \plugin{direct}{Multi-channel integrator} /*! \plugin{direct}{Multi-channel integrator}
* \order{16} * \order{16}
* \parameters{
* \parameter{\Unnamed}{\BSDF}{Multiple sub-integrators whose output
* should be rendered into a combined multi-channel image}
* }
* *
* The multi-channel integrator groups several sub-integrators together
* and invokes them at the same time for each pixel; the result is written
* to a general multi-channel image. The most common application of this plugin
* is to create additional image channels storing surface normals or the distance
* from the camera (via the \pluginref{field} plugin) or ambient occlusion
* (via the \pluginref{ao} plugin).
*
* This is a fairly advanced plugin that only plays well with a small
* part of Mitsuba---see the remarks in the red box for details.
*
* \remarks{
* \item Requires the \pluginref{hdrfilm} or \pluginref{tiledhdrfilm}.
* \item All nested integrators must
* conform to Mitsuba's basic \emph{SamplingIntegrator} interface.
* Currently, only a few of them satisfy this, including:
* \pluginref{field}, \pluginref{ao}, \pluginref{direct}, \pluginref{path},
* \pluginref{volpath}, \pluginref[volpathsimple]{volpath\_simple},
* and \pluginref{irrcache}.
* }
*/ */
class MultiChannelIntegrator : public SamplingIntegrator { class MultiChannelIntegrator : public SamplingIntegrator {

View File

@ -1361,7 +1361,7 @@ void Bitmap::convert(Bitmap *target, Float multiplier, Spectrum::EConversionInte
cvt->convert(m_pixelFormat, m_gamma, m_data, cvt->convert(m_pixelFormat, m_gamma, m_data,
target->getPixelFormat(), target->getGamma(), target->getData(), target->getPixelFormat(), target->getGamma(), target->getData(),
(size_t) m_size.x * (size_t) m_size.y, multiplier, intent, (size_t) m_size.x * (size_t) m_size.y, multiplier, intent,
m_channelCount - (hasWeight() ? 1 : 0)); m_channelCount);
} }
ref<Bitmap> Bitmap::convert(EPixelFormat pixelFormat, ref<Bitmap> Bitmap::convert(EPixelFormat pixelFormat,
@ -1392,70 +1392,96 @@ ref<Bitmap> Bitmap::convert(EPixelFormat pixelFormat,
cvt->convert(m_pixelFormat, m_gamma, m_data, cvt->convert(m_pixelFormat, m_gamma, m_data,
pixelFormat, gamma, target->getData(), pixelFormat, gamma, target->getData(),
(size_t) m_size.x * (size_t) m_size.y, multiplier, intent, (size_t) m_size.x * (size_t) m_size.y, multiplier, intent,
m_channelCount - (hasWeight() ? 1 : 0)); m_channelCount);
return target; return target;
} }
ref<Bitmap> Bitmap::convertMultiSpectrumAlphaWeight(const std::vector<EPixelFormat> &pixelFormats, ref<Bitmap> Bitmap::convertMultiSpectrumAlphaWeight(const std::vector<EPixelFormat> &pixelFormats,
EComponentFormat componentFormat, const std::vector<std::string> &channelNames) const { EComponentFormat componentFormat, const std::vector<std::string> &channelNames) const {
if (m_componentFormat != EFloat && m_pixelFormat != EMultiSpectrumAlphaWeight) ref<Bitmap> bitmap = new Bitmap(Bitmap::EMultiChannel, componentFormat, m_size, channelNames.size());
Log(EError, "convertMultiSpectrumAlphaWeight(): unsupported!");
ref<Bitmap> bitmap = new Bitmap(Bitmap::EMultiChannel, Bitmap::EFloat, m_size, channelNames.size());
bitmap->setChannelNames(channelNames); bitmap->setChannelNames(channelNames);
convertMultiSpectrumAlphaWeight(this, getUInt8Data(), bitmap,
bitmap->getUInt8Data(), pixelFormats, componentFormat,
(size_t) m_size.x * (size_t) m_size.y);
return bitmap;
}
for (int y = 0; y<m_size.y; ++y) { void Bitmap::convertMultiSpectrumAlphaWeight(const Bitmap *source,
for (int x = 0; x<m_size.x; ++x) { const uint8_t *sourcePtr, const Bitmap *target, uint8_t *targetPtr,
const Float *srcData = getFloatData() + getChannelCount() * (x+y*m_size.x); const std::vector<EPixelFormat> &pixelFormats,
Float *dstData = bitmap->getFloatData() + bitmap->getChannelCount() * (x+y*m_size.x); EComponentFormat componentFormat, size_t count) {
Float weight = srcData[getChannelCount()-1], if (source->getComponentFormat() != EFloat && source->getPixelFormat() != EMultiSpectrumAlphaWeight)
invWeight = weight == 0 ? 0 : (Float) 1 / weight; Log(EError, "convertMultiSpectrumAlphaWeight(): unsupported!");
Float alpha = srcData[getChannelCount()-2] * invWeight;
for (size_t i=0; i<pixelFormats.size(); ++i) { Float *temp = new Float[count * target->getChannelCount()], *dst = temp;
Spectrum value = ((Spectrum *) srcData)[i] * invWeight;
Float r, g, b; for (size_t k = 0; k<count; ++k) {
switch (pixelFormats[i]) { const Float *srcData = (const Float *) sourcePtr + k * source->getChannelCount();
case Bitmap::ELuminance: Float weight = srcData[source->getChannelCount()-1],
*dstData++ = value.getLuminance(); invWeight = weight == 0 ? 0 : (Float) 1 / weight;
break; Float alpha = srcData[source->getChannelCount()-2] * invWeight;
case Bitmap::ELuminanceAlpha:
*dstData++ = value.getLuminance(); for (size_t i=0; i<pixelFormats.size(); ++i) {
*dstData++ = alpha; Spectrum value = ((Spectrum *) srcData)[i] * invWeight;
break; Float tmp0, tmp1, tmp2;
case Bitmap::ERGB: switch (pixelFormats[i]) {
value.toLinearRGB(r, g, b); case Bitmap::ELuminance:
*dstData++ = r; *dst++ = value.getLuminance();
*dstData++ = g; break;
*dstData++ = b; case Bitmap::ELuminanceAlpha:
break; *dst++ = value.getLuminance();
case Bitmap::ERGBA: *dst++ = alpha;
value.toLinearRGB(r, g, b); break;
*dstData++ = r; case Bitmap::EXYZ:
*dstData++ = g; value.toXYZ(tmp0, tmp1, tmp2);
*dstData++ = b; *dst++ = tmp0;
*dstData++ = alpha; *dst++ = tmp1;
break; *dst++ = tmp2;
case Bitmap::ESpectrum: break;
for (int j=0; j<SPECTRUM_SAMPLES; ++j) case Bitmap::EXYZA:
*dstData++ = value[j]; value.toXYZ(tmp0, tmp1, tmp2);
break; *dst++ = tmp0;
case Bitmap::ESpectrumAlpha: *dst++ = tmp1;
for (int j=0; j<SPECTRUM_SAMPLES; ++j) *dst++ = tmp2;
*dstData++ = value[j]; *dst++ = alpha;
*dstData++ = alpha; break;
break; case Bitmap::ERGB:
default: value.toLinearRGB(tmp0, tmp1, tmp2);
Log(EError, "Unknown pixel format!"); *dst++ = tmp0;
} *dst++ = tmp1;
*dst++ = tmp2;
break;
case Bitmap::ERGBA:
value.toLinearRGB(tmp0, tmp1, tmp2);
*dst++ = tmp0;
*dst++ = tmp1;
*dst++ = tmp2;
*dst++ = alpha;
break;
case Bitmap::ESpectrum:
for (int j=0; j<SPECTRUM_SAMPLES; ++j)
*dst++ = value[j];
break;
case Bitmap::ESpectrumAlpha:
for (int j=0; j<SPECTRUM_SAMPLES; ++j)
*dst++ = value[j];
*dst++ = alpha;
break;
default:
Log(EError, "Unknown pixel format!");
} }
} }
} }
if (componentFormat != Bitmap::EFloat) const FormatConverter *cvt = FormatConverter::getInstance(
bitmap = bitmap->convert(Bitmap::EMultiChannel, componentFormat); std::make_pair(EFloat, target->getComponentFormat())
);
return bitmap; cvt->convert(Bitmap::EMultiChannel, 1.0f, temp, Bitmap::EMultiChannel, 1.0f, targetPtr,
count, 1.0f, Spectrum::EReflectance, target->getChannelCount());
delete[] temp;
} }
void Bitmap::convert(void *target, EPixelFormat pixelFormat, void Bitmap::convert(void *target, EPixelFormat pixelFormat,
@ -1481,7 +1507,7 @@ void Bitmap::convert(void *target, EPixelFormat pixelFormat,
cvt->convert(m_pixelFormat, m_gamma, m_data, cvt->convert(m_pixelFormat, m_gamma, m_data,
pixelFormat, gamma, target, pixelFormat, gamma, target,
(size_t) m_size.x * (size_t) m_size.y, multiplier, intent, (size_t) m_size.x * (size_t) m_size.y, multiplier, intent,
m_channelCount - (hasWeight() ? 1 : 0)); m_channelCount);
} }
template <typename T> void tonemapReinhard(T *data, size_t pixels, Bitmap::EPixelFormat fmt, template <typename T> void tonemapReinhard(T *data, size_t pixels, Bitmap::EPixelFormat fmt,