From 8d84d0b1a02f3939d91d05c6b39f4eb557cf8fc1 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sat, 15 Feb 2014 01:34:17 +0100 Subject: [PATCH] debugging.. --- include/mitsuba/core/bitmap.h | 9 +- src/films/hdrfilm.cpp | 56 +++--- src/films/tiledhdrfilm.cpp | 236 +++++++++++++++----------- src/integrators/misc/multichannel.cpp | 23 +++ src/libcore/bitmap.cpp | 130 ++++++++------ 5 files changed, 272 insertions(+), 182 deletions(-) diff --git a/include/mitsuba/core/bitmap.h b/include/mitsuba/core/bitmap.h index d7c91c4e..fddc1dca 100644 --- a/include/mitsuba/core/bitmap.h +++ b/include/mitsuba/core/bitmap.h @@ -678,12 +678,17 @@ public: * specified component format. Names for each of the resulting channels should * be provided via the \c channelNames parameters. * - * This function is currently only used by the \c hdrfilm plugin but located here - * as it is tied to the internals of this class. + * This feature is currently used by the \c hdrfilm and \c tiledhdrfilm plugins. */ ref convertMultiSpectrumAlphaWeight(const std::vector &pixelFormats, EComponentFormat componentFormat, const std::vector &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 &pixelFormats, + EComponentFormat componentFormat, size_t count); + /** * \brief Apply Reinhard et al's tonemapper in chromaticity space * diff --git a/src/films/hdrfilm.cpp b/src/films/hdrfilm.cpp index 2774b379..0bc9633d 100644 --- a/src/films/hdrfilm.cpp +++ b/src/films/hdrfilm.cpp @@ -215,7 +215,7 @@ public: std::vector pixelFormats = tokenize(boost::to_lower_copy( props.getString("pixelFormat", "rgb")), " ,"); std::vector channelNames = tokenize( - props.getString("channelNames", "rgb"), ", "); + props.getString("channelNames", ""), ", "); std::string componentFormat = boost::to_lower_copy( props.getString("componentFormat", "float16")); @@ -238,47 +238,50 @@ public: for (size_t i=0; i 1) - Log(EError, "The XYZ pixel format is not supported for general multi-channel images!"); + 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); - if (m_pixelFormats.size() > 1) - Log(EError, "The XYZA pixel format is not supported for general multi-channel images!"); + 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 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") { m_pixelFormats.push_back(Bitmap::ESpectrumAlpha); for (int i=0; i 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 { Log(EError, "The \"pixelFormat\" parameter must either be equal to " "\"luminance\", \"luminanceAlpha\", \"rgb\", \"rgba\", \"xyz\", \"xyza\", " @@ -529,13 +532,14 @@ public: } bool hasAlpha() const { - Assert(m_pixelFormats.size() > 0); - return - m_pixelFormats[0] == Bitmap::ELuminanceAlpha || - m_pixelFormats[0] == Bitmap::ERGBA || - m_pixelFormats[0] == Bitmap::EXYZA || - m_pixelFormats[0] == Bitmap::ESpectrumAlpha || - m_pixelFormats.size() > 1; + for (size_t i=0; i pixelFormats = tokenize(boost::to_lower_copy( + props.getString("pixelFormat", "rgb")), " ,"); + std::vector channelNames = tokenize( + props.getString("channelNames", ""), ", "); std::string componentFormat = boost::to_lower_copy( props.getString("componentFormat", "float16")); - if (pixelFormat == "luminance") { - m_pixelFormat = Bitmap::ELuminance; - } else if (pixelFormat == "luminancealpha") { - m_pixelFormat = Bitmap::ELuminanceAlpha; - } else if (pixelFormat == "rgb") { - m_pixelFormat = Bitmap::ERGB; - } else if (pixelFormat == "rgba") { - m_pixelFormat = Bitmap::ERGBA; - } else if (pixelFormat == "xyz") { - m_pixelFormat = Bitmap::EXYZ; - } else if (pixelFormat == "xyza") { - m_pixelFormat = Bitmap::EXYZA; - } else if (pixelFormat == "spectrum") { - m_pixelFormat = Bitmap::ESpectrum; - } else if (pixelFormat == "spectrumalpha") { - m_pixelFormat = Bitmap::ESpectrumAlpha; - } else { - Log(EError, "The \"pixelFormat\" parameter must either be equal to " - "\"luminance\", \"luminanceAlpha\", \"rgb\", \"rgba\", \"xyz\", \"xyza\", " - "\"spectrum\", or \"spectrumAlpha\"!"); + if (pixelFormats.empty()) + Log(EError, "At least one pixel format must be specified!"); + + if (m_pixelFormats.size() != 1 && m_channelNames.size() != m_pixelFormats.size()) + Log(EError, "Number of channel names must match the number of specified pixel formats!"); + + for (size_t i=0; i 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 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)) - Log(EError, "You requested to render a spectral image, but Mitsuba is currently " - "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."); + for (size_t i=0; ireadUInt(); + m_pixelFormats.resize((size_t) stream->readUInt()); + for (size_t i=0; ireadUInt(); + m_channelNames.resize((size_t) stream->readUInt()); + for (size_t i=0; ireadString(); m_componentFormat = (Bitmap::EComponentFormat) stream->readUInt(); } @@ -161,7 +207,11 @@ public: void serialize(Stream *stream, InstanceManager *manager) const { Film::serialize(stream, manager); - stream->writeUInt(m_pixelFormat); + for (size_t i=0; iwriteUInt(m_pixelFormats[i]); + stream->writeUInt((uint32_t) m_channelNames.size()); + for (size_t i=0; iwriteString(m_channelNames[i]); stream->writeUInt(m_componentFormat); } @@ -169,15 +219,6 @@ public: if (m_output) 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; std::string extension = boost::to_lower_copy(filename.extension().string()); if (extension != ".exr") @@ -189,19 +230,22 @@ public: header.setTileDescription(Imf::TileDescription(blockSize, blockSize, Imf::ONE_LEVEL)); header.insert("generated-by", Imf::StringAttribute("Mitsuba version " MTS_VERSION)); - if (pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) { - Imf::addChromaticities(header, Imf::Chromaticities( - Imath::V2f(1.0f, 0.0f), - Imath::V2f(0.0f, 1.0f), - 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()); + if (m_pixelFormats.size() == 1) { + /* Write a chromaticity tag when this is possible */ + Bitmap::EPixelFormat pixelFormat = m_pixelFormats[0]; + if (pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) { + Imf::addChromaticities(header, Imf::Chromaticities( + Imath::V2f(1.0f, 0.0f), + Imath::V2f(0.0f, 1.0f), + 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; size_t compStride; - int channelCount; if (m_componentFormat == Bitmap::EFloat16) { compType = Imf::HALF; @@ -219,62 +263,34 @@ public: } Imf::ChannelList &channels = header.channels(); - if (pixelFormat == Bitmap::ELuminance || pixelFormat == Bitmap::ELuminanceAlpha) { - channels.insert("Y", 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 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++; - } + for (size_t i=0; igetUInt8Data(); - if (pixelFormat == Bitmap::ELuminance || pixelFormat == Bitmap::ELuminanceAlpha) { - m_frameBuffer->insert("Y", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride; - } else if (pixelFormat == Bitmap::ERGB || pixelFormat == Bitmap::ERGBA || - pixelFormat == Bitmap::EXYZ || pixelFormat == Bitmap::EXYZA) { - m_frameBuffer->insert("R", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride; - m_frameBuffer->insert("G", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride; - m_frameBuffer->insert("B", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); ptr += compStride; - } else if (pixelFormat == Bitmap::ESpectrum || pixelFormat == Bitmap::ESpectrumAlpha) { - for (int i=0; i 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_pixelFormats.size() == 1) { + m_tile = new Bitmap(m_pixelFormats[0], m_componentFormat, + Vector2i(m_blockSize, m_blockSize)); + } else { + m_tile = new Bitmap(Bitmap::EMultiChannel, m_componentFormat, + Vector2i(m_blockSize, m_blockSize), m_channelNames.size()); + m_tile->setChannelNames(m_channelNames); } - if (m_pixelFormat == Bitmap::ERGBA || m_pixelFormat == Bitmap::EXYZA || - m_pixelFormat == Bitmap::ELuminanceAlpha) - m_frameBuffer->insert("A", Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); + char *ptr = (char *) m_tile->getUInt8Data(); + + for (size_t i=0; iinsert(m_channelNames[i], + Imf::Slice(compType, ptr, m_pixelStride, m_rowStride)); + ptr += compStride; + } m_output->setFrameBuffer(*m_frameBuffer); m_peakUsage = 0; @@ -388,6 +404,7 @@ public: } const Bitmap *source = mergedBlock->getBitmap(); + size_t sourceBpp = source->getBytesPerPixel(); size_t targetBpp = m_tile->getBytesPerPixel(); @@ -400,11 +417,15 @@ public: ); for (int i=0; iconvert(source->getPixelFormat(), 1.0f, sourceData, - m_tile->getPixelFormat(), m_tile->getGamma(), targetData, - m_tile->getWidth()); + if (m_pixelFormats.size() == 1) + cvt->convert(source->getPixelFormat(), 1.0f, sourceData, + 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; } @@ -470,11 +491,14 @@ public: void clear() { /* Do nothing */ } bool hasAlpha() const { - return - m_pixelFormat == Bitmap::ELuminanceAlpha || - m_pixelFormat == Bitmap::ERGBA || - m_pixelFormat == Bitmap::EXYZA || - m_pixelFormat == Bitmap::ESpectrumAlpha; + for (size_t i=0; i m_pixelFormats; + std::vector m_channelNames; Bitmap::EComponentFormat m_componentFormat; std::vector m_freeBlocks; std::map m_origBlocks, m_mergedBlocks; diff --git a/src/integrators/misc/multichannel.cpp b/src/integrators/misc/multichannel.cpp index 9e45a125..dc202549 100644 --- a/src/integrators/misc/multichannel.cpp +++ b/src/integrators/misc/multichannel.cpp @@ -23,7 +23,30 @@ MTS_NAMESPACE_BEGIN /*! \plugin{direct}{Multi-channel integrator} * \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 { diff --git a/src/libcore/bitmap.cpp b/src/libcore/bitmap.cpp index c908b38b..edb16a26 100644 --- a/src/libcore/bitmap.cpp +++ b/src/libcore/bitmap.cpp @@ -1361,7 +1361,7 @@ void Bitmap::convert(Bitmap *target, Float multiplier, Spectrum::EConversionInte cvt->convert(m_pixelFormat, m_gamma, m_data, target->getPixelFormat(), target->getGamma(), target->getData(), (size_t) m_size.x * (size_t) m_size.y, multiplier, intent, - m_channelCount - (hasWeight() ? 1 : 0)); + m_channelCount); } ref Bitmap::convert(EPixelFormat pixelFormat, @@ -1392,70 +1392,96 @@ ref Bitmap::convert(EPixelFormat pixelFormat, cvt->convert(m_pixelFormat, m_gamma, m_data, pixelFormat, gamma, target->getData(), (size_t) m_size.x * (size_t) m_size.y, multiplier, intent, - m_channelCount - (hasWeight() ? 1 : 0)); + m_channelCount); return target; } ref Bitmap::convertMultiSpectrumAlphaWeight(const std::vector &pixelFormats, EComponentFormat componentFormat, const std::vector &channelNames) const { - if (m_componentFormat != EFloat && m_pixelFormat != EMultiSpectrumAlphaWeight) - Log(EError, "convertMultiSpectrumAlphaWeight(): unsupported!"); - ref bitmap = new Bitmap(Bitmap::EMultiChannel, Bitmap::EFloat, m_size, channelNames.size()); + ref bitmap = new Bitmap(Bitmap::EMultiChannel, componentFormat, m_size, channelNames.size()); 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; ygetFloatData() + bitmap->getChannelCount() * (x+y*m_size.x); - Float weight = srcData[getChannelCount()-1], - invWeight = weight == 0 ? 0 : (Float) 1 / weight; - Float alpha = srcData[getChannelCount()-2] * invWeight; +void Bitmap::convertMultiSpectrumAlphaWeight(const Bitmap *source, + const uint8_t *sourcePtr, const Bitmap *target, uint8_t *targetPtr, + const std::vector &pixelFormats, + EComponentFormat componentFormat, size_t count) { + if (source->getComponentFormat() != EFloat && source->getPixelFormat() != EMultiSpectrumAlphaWeight) + Log(EError, "convertMultiSpectrumAlphaWeight(): unsupported!"); - for (size_t i=0; igetChannelCount()], *dst = temp; + + for (size_t k = 0; kgetChannelCount(); + Float weight = srcData[source->getChannelCount()-1], + invWeight = weight == 0 ? 0 : (Float) 1 / weight; + Float alpha = srcData[source->getChannelCount()-2] * invWeight; + + for (size_t i=0; iconvert(Bitmap::EMultiChannel, componentFormat); + const FormatConverter *cvt = FormatConverter::getInstance( + 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, @@ -1481,7 +1507,7 @@ void Bitmap::convert(void *target, EPixelFormat pixelFormat, cvt->convert(m_pixelFormat, m_gamma, m_data, pixelFormat, gamma, target, (size_t) m_size.x * (size_t) m_size.y, multiplier, intent, - m_channelCount - (hasWeight() ? 1 : 0)); + m_channelCount); } template void tonemapReinhard(T *data, size_t pixels, Bitmap::EPixelFormat fmt,