Mitsuba Renderer  0.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
imageblock.h
Go to the documentation of this file.
1 /*
2  This file is part of Mitsuba, a physically based rendering system.
3 
4  Copyright (c) 2007-2014 by Wenzel Jakob and others.
5 
6  Mitsuba is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License Version 3
8  as published by the Free Software Foundation.
9 
10  Mitsuba is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #pragma once
20 #if !defined(__MITSUBA_RENDER_IMAGEBLOCK_H_)
21 #define __MITSUBA_RENDER_IMAGEBLOCK_H_
22 
23 #include <mitsuba/core/bitmap.h>
24 #include <mitsuba/core/sched.h>
25 #include <mitsuba/core/rfilter.h>
26 
28 
29 /**
30  * \brief Storage for an image sub-block (a.k.a render bucket)
31  *
32  * This class is used by image-based parallel processes and encapsulates
33  * computed rectangular regions of an image. This allows for easy and efficient
34  * distributed rendering of large images. Image blocks usually also include a
35  * border region storing contribuctions that are slightly outside of the block,
36  * which is required to support image reconstruction filters.
37  *
38  * \ingroup librender
39  */
41 public:
42  /**
43  * Construct a new image block of the requested properties
44  *
45  * \param fmt
46  * Specifies the pixel format -- see \ref Bitmap::EPixelFormat
47  * for a list of possibilities
48  * \param size
49  * Specifies the block dimensions (not accounting for additional
50  * border pixels required to support image reconstruction filters)
51  * \param channels
52  * Specifies the number of output channels. This is only necessary
53  * when \ref Bitmap::EMultiChannel is chosen as the pixel format
54  * \param warn
55  * Warn when writing bad sample values?
56  */
57  ImageBlock(Bitmap::EPixelFormat fmt, const Vector2i &size,
58  const ReconstructionFilter *filter = NULL, int channels = -1, bool warn = true);
59 
60  /// Set the current block offset
61  inline void setOffset(const Point2i &offset) { m_offset = offset; }
62 
63  /// Return the current block offset
64  inline const Point2i &getOffset() const { return m_offset; }
65 
66  /// Set the current block size
67  inline void setSize(const Vector2i &size) { m_size = size; }
68 
69  /// Return the current block size
70  inline const Vector2i &getSize() const { return m_size; }
71 
72  /// Return the bitmap's width in pixels
73  inline int getWidth() const { return m_size.x; }
74 
75  /// Return the bitmap's height in pixels
76  inline int getHeight() const { return m_size.y; }
77 
78  /// Warn when writing bad sample values?
79  inline bool getWarn() const { return m_warn; }
80 
81  /// Warn when writing bad sample values?
82  inline void setWarn(bool warn) { m_warn = warn; }
83 
84  /// Return the border region used by the reconstruction filter
85  inline int getBorderSize() const { return m_borderSize; }
86 
87  /// Return the number of channels stored by the image block
88  inline int getChannelCount() const { return m_bitmap->getChannelCount(); }
89 
90  /// Return the underlying pixel format
91  inline Bitmap::EPixelFormat getPixelFormat() const { return m_bitmap->getPixelFormat(); }
92 
93  /// Return a pointer to the underlying bitmap representation
94  inline Bitmap *getBitmap() { return m_bitmap; }
95 
96  /// Return a pointer to the underlying bitmap representation (const version)
97  inline const Bitmap *getBitmap() const { return m_bitmap.get(); }
98 
99  /// Clear everything to zero
100  inline void clear() { m_bitmap->clear(); }
101 
102  /// Accumulate another image block into this one
103  inline void put(const ImageBlock *block) {
104  m_bitmap->accumulate(block->getBitmap(),
105  Point2i(block->getOffset() - m_offset
106  - Vector2i(block->getBorderSize() - m_borderSize)));
107  }
108 
109  /**
110  * \brief Store a single sample inside the image block
111  *
112  * This variant assumes that the image block stores spectrum,
113  * alpha, and reconstruction filter weight values.
114  *
115  * \param pos
116  * Denotes the sample position in fractional pixel coordinates
117  * \param spec
118  * Spectrum value assocated with the sample
119  * \param alpha
120  * Alpha value assocated with the sample
121  * \return \c false if one of the sample values was \a invalid, e.g.
122  * NaN or negative. A warning is also printed in this case
123  */
124  FINLINE bool put(const Point2 &pos, const Spectrum &spec, Float alpha) {
125  Float temp[SPECTRUM_SAMPLES + 2];
126  for (int i=0; i<SPECTRUM_SAMPLES; ++i)
127  temp[i] = spec[i];
128  temp[SPECTRUM_SAMPLES] = alpha;
129  temp[SPECTRUM_SAMPLES + 1] = 1.0f;
130  return put(pos, temp);
131  }
132 
133  /**
134  * \brief Store a single sample inside the block
135  *
136  * \param _pos
137  * Denotes the sample position in fractional pixel coordinates
138  * \param value
139  * Pointer to an array containing each channel of the sample values.
140  * The array must match the length given by \ref getChannelCount()
141  * \return \c false if one of the sample values was \a invalid, e.g.
142  * NaN or negative. A warning is also printed in this case
143  */
144  FINLINE bool put(const Point2 &_pos, const Float *value) {
145  const int channels = m_bitmap->getChannelCount();
146 
147  /* Check if all sample values are valid */
148  for (int i=0; i<channels; ++i) {
149  if (EXPECT_NOT_TAKEN((!std::isfinite(value[i]) || value[i] < 0) && m_warn))
150  goto bad_sample;
151  }
152 
153  {
154  const Float filterRadius = m_filter->getRadius();
155  const Vector2i &size = m_bitmap->getSize();
156 
157  /* Convert to pixel coordinates within the image block */
158  const Point2 pos(
159  _pos.x - 0.5f - (m_offset.x - m_borderSize),
160  _pos.y - 0.5f - (m_offset.y - m_borderSize));
161 
162  /* Determine the affected range of pixels */
163  const Point2i min(std::max((int) std::ceil (pos.x - filterRadius), 0),
164  std::max((int) std::ceil (pos.y - filterRadius), 0)),
165  max(std::min((int) std::floor(pos.x + filterRadius), size.x - 1),
166  std::min((int) std::floor(pos.y + filterRadius), size.y - 1));
167 
168  /* Lookup values from the pre-rasterized filter */
169  for (int x=min.x, idx = 0; x<=max.x; ++x)
170  m_weightsX[idx++] = m_filter->evalDiscretized(x-pos.x);
171  for (int y=min.y, idx = 0; y<=max.y; ++y)
172  m_weightsY[idx++] = m_filter->evalDiscretized(y-pos.y);
173 
174  /* Rasterize the filtered sample into the framebuffer */
175  for (int y=min.y, yr=0; y<=max.y; ++y, ++yr) {
176  const Float weightY = m_weightsY[yr];
177  Float *dest = m_bitmap->getFloatData()
178  + (y * (size_t) size.x + min.x) * channels;
179 
180  for (int x=min.x, xr=0; x<=max.x; ++x, ++xr) {
181  const Float weight = m_weightsX[xr] * weightY;
182 
183  for (int k=0; k<channels; ++k)
184  *dest++ += weight * value[k];
185  }
186  }
187  }
188 
189  return true;
190 
191  bad_sample:
192  {
193  std::ostringstream oss;
194  oss << "Invalid sample value : [";
195  for (int i=0; i<channels; ++i) {
196  oss << value[i];
197  if (i+1 < channels)
198  oss << ", ";
199  }
200  oss << "]";
201  Log(EWarn, "%s", oss.str().c_str());
202  }
203  return false;
204  }
205 
206  /// Create a clone of the entire image block
208  ref<ImageBlock> clone = new ImageBlock(m_bitmap->getPixelFormat(),
209  m_bitmap->getSize() - Vector2i(2*m_borderSize, 2*m_borderSize), m_filter, m_bitmap->getChannelCount());
210  copyTo(clone);
211  return clone;
212  }
213 
214  /// Copy the contents of this image block to another one with the same configuration
215  void copyTo(ImageBlock *copy) const {
216  memcpy(copy->getBitmap()->getUInt8Data(), m_bitmap->getUInt8Data(), m_bitmap->getBufferSize());
217  copy->m_size = m_size;
218  copy->m_offset = m_offset;
219  copy->m_warn = m_warn;
220  }
221 
222  // ======================================================================
223  //! @{ \name Implementation of the WorkResult interface
224  // ======================================================================
225 
226  void load(Stream *stream);
227  void save(Stream *stream) const;
228  std::string toString() const;
229 
230  //! @}
231  // ======================================================================
232 
234 protected:
235  /// Virtual destructor
236  virtual ~ImageBlock();
237 protected:
238  ref<Bitmap> m_bitmap;
239  Point2i m_offset;
240  Vector2i m_size;
241  int m_borderSize;
242  const ReconstructionFilter *m_filter;
243  Float *m_weightsX, *m_weightsY;
244  bool m_warn;
245 };
246 
247 
249 
250 #endif /* __MITSUBA_RENDER_IMAGEBLOCK_H_ */
TVector2< int > Vector2i
Definition: fwd.h:108
const Bitmap * getBitmap() const
Return a pointer to the underlying bitmap representation (const version)
Definition: imageblock.h:97
General-purpose bitmap class with read and write support for several common file formats.
Definition: bitmap.h:50
virtual void save(Stream *stream) const =0
Serialize a work result to a binary data stream.
bool getWarn() const
Warn when writing bad sample values?
Definition: imageblock.h:79
void setWarn(bool warn)
Warn when writing bad sample values?
Definition: imageblock.h:82
int getChannelCount() const
Return the number of channels stored by the image block.
Definition: imageblock.h:88
EPixelFormat
Definition: bitmap.h:61
void clear()
Clear everything to zero.
Definition: imageblock.h:100
#define MTS_NAMESPACE_BEGIN
Definition: platform.h:137
Generic interface to separable image reconstruction filters.
Definition: rfilter.h:44
FINLINE bool put(const Point2 &_pos, const Float *value)
Store a single sample inside the block.
Definition: imageblock.h:144
Vector2i m_size
Definition: imageblock.h:240
void put(const ImageBlock *block)
Accumulate another image block into this one.
Definition: imageblock.h:103
Bitmap::EPixelFormat getPixelFormat() const
Return the underlying pixel format.
Definition: imageblock.h:91
Abstract work result – represents the result of a processed WorkUnit instance.
Definition: sched.h:80
void setOffset(const Point2i &offset)
Set the current block offset.
Definition: imageblock.h:61
const Point2i & getOffset() const
Return the current block offset.
Definition: imageblock.h:64
#define Log(level, fmt,...)
Write a Log message to the console (to be used within subclasses of Object)
Definition: logger.h:35
Bitmap * getBitmap()
Return a pointer to the underlying bitmap representation.
Definition: imageblock.h:94
Abstract seekable stream class.
Definition: stream.h:58
#define MTS_DECLARE_CLASS()
This macro must be used in the initial definition in classes that derive from Object.
Definition: class.h:158
Definition: fwd.h:99
Reference counting helper.
Definition: ref.h:40
Warning message.
Definition: formatter.h:32
const Vector2i & getSize() const
Return the current block size.
Definition: imageblock.h:70
void copyTo(ImageBlock *copy) const
Copy the contents of this image block to another one with the same configuration. ...
Definition: imageblock.h:215
int getWidth() const
Return the bitmap&#39;s width in pixels.
Definition: imageblock.h:73
Point2i m_offset
Definition: imageblock.h:239
uint8_t * getUInt8Data()
Access the underlying raster (for uint8 bitmaps)
Definition: bitmap.h:1192
virtual void load(Stream *stream)=0
Fill the work result with content acquired from a binary data stream.
int getBorderSize() const
Return the border region used by the reconstruction filter.
Definition: imageblock.h:85
Storage for an image sub-block (a.k.a render bucket)
Definition: imageblock.h:40
FINLINE bool put(const Point2 &pos, const Spectrum &spec, Float alpha)
Store a single sample inside the image block.
Definition: imageblock.h:124
bool m_warn
Definition: imageblock.h:244
virtual std::string toString() const =0
Return a string representation.
#define MTS_EXPORT_RENDER
Definition: platform.h:109
TPoint2< int > Point2i
Definition: fwd.h:131
Discrete spectral power distribution based on a number of wavelength bins over the 360-830 nm range...
Definition: spectrum.h:663
void setSize(const Vector2i &size)
Set the current block size.
Definition: imageblock.h:67
ref< ImageBlock > clone() const
Create a clone of the entire image block.
Definition: imageblock.h:207
Definition: fwd.h:95
#define MTS_NAMESPACE_END
Definition: platform.h:138
int getHeight() const
Return the bitmap&#39;s height in pixels.
Definition: imageblock.h:76