HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PXL_DeepSampleList.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: PXL_DeepSampleList.h (PXL Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #pragma once
12 
13 #ifndef __PXL_DeepSampleList__
14 #define __PXL_DeepSampleList__
15 
16 #include "PXL_API.h"
17 #include "PXL_Forward.h"
18 #include "PXL_DeepChannelList.h"
19 #include <UT/UT_IntrusivePtr.h>
20 #include <UT/UT_NonCopyable.h>
21 #include <SYS/SYS_Types.h>
22 
23 class UT_JSONParser;
24 class UT_JSONWriter;
25 
26 /// Class to represent a list of deep pixel samples.
27 ///
28 /// The class stores multiple samples for multiple image channels. The image
29 /// channels Each pixel list has:
30 /// - <tt>int sampleCount</tt> @n The number of samples in the list
31 /// Each sample has:
32 /// - <tt>float z</tt>: @n Z-Depth of the sample
33 /// - <tt>uint8 flags</tt>: @n Flags associated with the sample
34 /// - <tt>uint64 coverage</tt>: @n The sample coverage mask
35 /// - <tt>float *channel_data</tt>: @n Image channel values
36 ///
37 /// The coverage mask will either be 0 (indicating full coverage) or a bit-mask
38 /// representing the coverage. If there are more than 64 samples, the sample
39 /// id's rotate (i.e. mask |= 1 << (sample_id % 64)).
40 ///
42  : public UT_IntrusiveRefCounter<PXL_DeepSampleList>
43 {
44 public:
46  int nsamples,
47  bool precomposited);
50 
51  // TODO:
52  PXL_DeepSampleList &operator=(const PXL_DeepSampleList &src) = delete;
53 
54  /// Merge two lists sorted into a single list. If the definition of the
55  /// pixel lists (i.e. the channels) don't match, then the method will
56  /// return @c a. The method properly handles @c nullptr values.
57  static PXL_DeepSampleListPtr combine(const PXL_DeepSampleListPtr &a,
58  const PXL_DeepSampleListPtr &b);
59 
60  /// Split any volume segments into multiple segements based on the z values
61  /// of the other sample list.
62  PXL_DeepSampleListPtr splitSegments(const PXL_DeepSampleList &l) const;
63 
64  /// Clear buffers etc. This keeps a reference to the channels and the
65  /// precompositing state.
66  void clear();
67 
69  {
70  VOLUME_SAMPLE = 0x01,
71  MATTE_SURFACE = 0x02,
72  };
73 
74  /// @{
75  /// Return number of samples in the deep pixel list
76  int sampleCount() const { return mySampleCount; }
77  int size() const { return mySampleCount; }
78  /// @}
79 
80  /// Return the maximum number of samples
81  int sampleCapacity() const { return mySampleCapacity; }
82 
83  /// Return whether the samples in the list are pre-composited or
84  /// un-composited
85  bool preComposited() const { return myPreComposited; }
86 
87  /// Initialize data structures, possibly enlarging buffers for the sample
88  /// count.
89  void setSampleCount(int nsamples);
90 
91  /// Set the pre-composited state
92  void setPreComposited(bool c) { myPreComposited = c; }
93 
94  /// Accessors
95  const PXL_DeepChannelListPtr &channels() const { return myChannels; }
96 
97 #define GET_SCALAR(TYPE, VMETHOD) \
98  { \
99  TYPE value; \
100  return *VMETHOD(&value, sample, sample+1); \
101  }
102 #define GET_VECTOR(TYPE, VMETHOD) \
103  { \
104  if (end == -1) end = sampleCount(); \
105  return VMETHOD(storage, start, end); \
106  }
107 
108  /// Return z-back for given sample.
109  float zfront(int sample) const
110  { GET_SCALAR(float, fillZfront); }
111 
112  /// Return a buffer with all z-front values for all samples.
113  ///
114  /// If the sample list doesn't store the z-front values in a flat array,
115  /// the values will be copied to the @c storage array and that value will
116  /// be returned. If the sample list is able to return a pointer to
117  /// internal data, the @c storage array will be left unchanged.
118  const float *zfront(float *storage, int start=0, int end=-1) const
119  { GET_VECTOR(float, fillZfront); }
120 
121  /// Return z-back for a given sample.
122  float zback(int sample) const
123  { GET_SCALAR(float, fillZback); }
124  /// Return a buffer with all z-back values for all samples.
125  /// See @c zfront() for an explanation of the @c storage array.
126  const float *zback(float *storage, int start=0, int end=-1) const
127  { GET_VECTOR(float, fillZback); }
128 
129  /// Return the z midpoint for a given sample
130  float zmid(int sample) const
131  { return 0.5f*(zfront(sample) + zback(sample)); }
132 
133  /// Return flags for a given sample (see SampleFlag enum)
134  uint8 flags(int sample) const
135  { GET_SCALAR(uint8, fillSampleFlags); }
136  /// Check to see whether a sample is a volume
137  bool isVolume(int sample) const
138  { return (flags(sample) & VOLUME_SAMPLE)
139  && (zfront(sample) < zback(sample)); }
140  /// Check to see whether a sample is a matte sample
141  bool isMatte(int sample) const
142  { return flags(sample) & MATTE_SURFACE; }
143  /// Fill buffer with flags for the samples (see SampleFlag enum).
144  /// See @c zfront() for an explanation of the @c storage array.
145  const uint8 *flags(uint8 *storage, int start=0, int end=-1) const
146  { GET_VECTOR(uint8, fillSampleFlags); }
147 
148  /// Return the sub-sample pixel location for a given sample
149  uint64 coverage(int sample) const
150  { GET_SCALAR(uint64, fillCoverage) }
151  /// Return an array of the sub-pixel locations for all samples.
152  /// See @c zfront() for an explanation of the @c storage array.
154  int start=0, int end=-1) const
155  { GET_VECTOR(uint64, fillCoverage) }
156 
157  /// Return the channel data for a given sample. The @c storage array must
158  /// contain at least @c channelSize(channel) floats.
159  const float *channelData(int channel, int sample, float *storage) const
160  { return fillChannel(channel, storage, sample, sample+1); }
161  /// Return all the data for a given channel. The @c storage array must be
162  /// at least @c sampleCount()*channelSize(channel) floats.
163  const float *channelData(int channel, float *storage,
164  int start=0, int end=-1) const
165  {
166  if (end == -1)
167  end = sampleCount();
168  return fillChannel(channel, storage, start, end);
169  }
170 
171 #undef GET_SCALAR
172 #undef GET_VECTOR
173 
174  /// Encode the sample list into a JSON stream.
175  bool save(UT_JSONWriter &j,
176  const PXL_DeepChannelListPtr &channels) const;
177 
178  /// Save, handling null pointers properly
179  static bool save(UT_JSONWriter &j, const PXL_DeepSampleListPtr &list,
180  const PXL_DeepChannelListPtr &channels);
181 
182  /// See PXL_DeepSampleList::save(). This method will create a sample list
183  /// from an encoded sample.
184  static PXL_DeepSampleListPtr load(
185  UT_JSONParser &j,
186  const PXL_DeepChannelListPtr &c);
187 
188  /// Dump sample list for debugging
189  void dump(const PXL_DeepChannelListPtr &channels,
190  const char *msg="",
191  int start = 0,
192  int end = -1) const;
193  /// Dump sample list (without channel data) for debugging
194  void dump(const char *msg="",
195  int start = 0,
196  int end = -1) const;
197 
198  /// Return a pointer to an array of the sample z-front values. If the data
199  /// isn't laid out properly for the user, the data can be copied to the @c
200  /// storage buffer. @code
201  /// for (int i = start; i != end; ++i) storage[i-start] = getZ(i);
202  /// return storage;
203  /// @endcode
204  const float *fillZfront(float *storage, int start, int end) const
205  { return myZfront + start; }
206  /// Return a pointer to an array of the z-back flags.
207  /// See @c fillZfront() for explanation of @c storage.
208  const float *fillZback(float *storage, int start, int end) const
209  { return myZback + start; }
210  /// Return a pointer to an array of the sample flags.
211  /// See @c fillZfront() for explanation of @c storage.
212  const uint8 *fillSampleFlags(uint8 *storage, int start, int end) const
213  { return myFlags + start; }
214  /// Return a pointer to an array of the sub-pixel locations.
215  /// See @c fillZfront() for explanation of @c storage.
216  const uint64 *fillCoverage(uint64 *storage, int start, int end) const
217  { return myCoverage + start; }
218  /// Return a pointer to an array of the channel data.
219  /// See @c fillZfront() for explanation of @c storage.
220  const float *fillChannel(int ch, float *storage, int start, int end) const
221  { return myChannelData[ch] + start*myChannels->tupleSize(ch); }
222 
223  /// @{
224  /// Get write-able array of z values.
225  float *zfrontBuffer() { return myZfront; }
226  float *zbackBuffer() { return myZback; }
227  /// @}
228  /// Get write-able array of flags
229  uint8 *flagBuffer() { return myFlags; }
230  /// Get write-able array of coverage
231  uint64 *coverageBuffer() { return myCoverage; }
232  /// Get write-able array of data for a given channel
233  float *channelBuffer(int i) { return myChannelData[i]; }
234 
235  /// @{
236  /// Get read-only array of z values.
237  const float *zfrontBuffer() const { return myZfront; }
238  const float *zbackBuffer() const { return myZback; }
239  /// @}
240  /// Get read-only array of flags
241  const uint8 *flagBuffer() const { return myFlags; }
242  /// Get read-only array of coverages
243  const uint64 *coverageBuffer() const { return myCoverage; }
244  /// Get read-only array of data for a given channel
245  const float *channelBuffer(int i) const { return myChannelData[i]; }
246 
247  /// The returns the number of records in the list before full opacity is
248  /// reached.
249  int findFullOpacity(int of_channel, float opacity_thresh=1.0) const;
250 
251  /// Trim the list to the number of records specified.
252  void trimLength(int nrecords) { mySampleCount = nrecords; }
253 
254  /// @{
255  /// Copy over data from a source sample list
256  void copyZfront(const PXL_DeepSampleList &s);
257  void copyZback(const PXL_DeepSampleList &s);
259  {
260  copyZfront(s);
261  copyZback(s);
262  }
263  void copyFlags(const PXL_DeepSampleList &s);
264  void copySampleId(const PXL_DeepSampleList &s);
265  void copyChannel(int ch, const PXL_DeepSampleList &s);
266  void copyAllChannels(const PXL_DeepSampleList &s);
267  /// @}
268 
269  /// Class to help with weighted sums of pixels
270  class Sum
271  {
272  public:
273  Sum(PXL_DeepSampleList &list, int idx, float scale)
274  : myList(list)
275  , myIndex(idx)
276  , myScale(scale)
277  , mySum(0)
278  , myMax(0)
279  , myFirst(true)
280  {
281  }
283  {
284  UT_ASSERT_P(!myFirst);
285  finishSum();
286  }
288 
289  void finishSum()
290  {
291  if (myFirst)
292  {
293  myList.zeroData(myIndex);
294  myFirst = false;
295  }
296  }
297  void add(const PXL_DeepSampleList &s, int sidx, float weight=1)
298  {
299  mySum += weight;
300  if (myFirst)
301  {
302  myFirst = false;
303  myMax = weight;
304  myList.copySample(myIndex, s, sidx, weight*myScale);
305  }
306  else
307  {
308  myList.addSample(myIndex, s, sidx, weight*myScale);
309  if (weight > myMax)
310  {
311  myMax = weight;
312  myList.setConditional(myIndex, s, sidx);
313  }
314  }
315  }
316  /// Add a volume sample. The @c zinterp value is a 0 to 1 value
317  /// representing <tt>(zback - zsample) / (zback - zfront)</tt>
318  void addVolume(const PXL_DeepSampleList &s, int sidx,
319  float zinterp, bool beerlambert=false)
320  {
321  if (sidx > 0 && zinterp < 1)
322  add(s, sidx, SYSmin(1-zinterp, 1.0f));
323  if (zinterp > 0)
324  add(s, sidx, SYSmin(zinterp, 1.0f));
325  }
326  int index() const { return myIndex; }
327  float totalWeight() const { return mySum * myScale; }
328  float maxWeight() const { return myMax; }
329  private:
330  PXL_DeepSampleList &myList; // Sample list
331  int myIndex; // Sample index
332  float myScale; // Scale by 1/myCount
333  float mySum; // Total weight (not always 1)
334  float myMax; // Current maximum weight
335  bool myFirst;
336  };
337 
338 
339  /// Copy the source sample into the destination index. If a @c scale is
340  /// specified, the channel data will be scaled by that amount.
341  void copySample(int didx, const PXL_DeepSampleList &s, int sidx,
342  float scale=1);
343 
344  /// Split the source sample into the destination index at the given z value
345  void extractSegment(int didx, const PXL_DeepSampleList &s, int sidx,
346  float zf, float zb, float scale=1);
347 
348  /// Set conditinal assignment based on weight. This only adjusts ordinal
349  /// channels.
350  void setConditional(int didx, const PXL_DeepSampleList &s, int sidx);
351 
352  /// Add the source sample to this sample (with an optional scale). This
353  /// only adjusts non-ordinal channels.
354  void addSample(int didx, const PXL_DeepSampleList &s, int sidx,
355  float scale=1);
356 
357  /// Initialize all records to zero
358  void zeroData();
359 
360  /// Clear a single sample
361  void zeroData(int sample);
362 
363  /// Perform compositing on the sample array using the given opacity channel
364  void composite(int of_channel, bool force = false);
365 
366  /// Perform uncompositing of sampels using the opacity channel
367  void uncomposite(int of_channel, bool force = false);
368 
369 private:
370  PXL_DeepChannelListPtr myChannels;
371  int mySampleCount;
372  int mySampleCapacity;
373  float *myZfront;
374  float *myZback;
375  uint8 *myFlags;
376  uint64 *myCoverage;
377  float **myChannelData;
378  bool myPreComposited;
379 };
380 
381 #endif
uint64 * coverageBuffer()
Get write-able array of coverage.
GLbitfield flags
Definition: glcorearb.h:1596
const uint8 * fillSampleFlags(uint8 *storage, int start, int end) const
const float * fillZfront(float *storage, int start, int end) const
void
Definition: png.h:1083
getFileOption("OpenEXR:storage") storage
Definition: HDK_Image.dox:276
GLuint start
Definition: glcorearb.h:475
uint8 flags(int sample) const
Return flags for a given sample (see SampleFlag enum)
float zback(int sample) const
Return z-back for a given sample.
#define GET_VECTOR(TYPE, VMETHOD)
int sampleCount() const
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
bool isVolume(int sample) const
Check to see whether a sample is a volume.
void add(const PXL_DeepSampleList &s, int sidx, float weight=1)
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:87
const PXL_DeepChannelListPtr & channels() const
Accessors.
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:37
const float * zback(float *storage, int start=0, int end=-1) const
unsigned long long uint64
Definition: SYS_Types.h:117
A reference counter base class for use with UT_IntrusivePtr.
#define PXL_API
Definition: PXL_API.h:10
const float * fillZback(float *storage, int start, int end) const
unsigned char uint8
Definition: SYS_Types.h:36
float * channelBuffer(int i)
Get write-able array of data for a given channel.
UT_IntrusiveRefCounter & operator=(const UT_IntrusiveRefCounter &) noexcept
Assignment operator: Does not modify counter.
GA_API const UT_StringHolder scale
GLfloat f
Definition: glcorearb.h:1926
void copyZ(const PXL_DeepSampleList &s)
int sampleCapacity() const
Return the maximum number of samples.
float zmid(int sample) const
Return the z midpoint for a given sample.
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
GLuint GLuint end
Definition: glcorearb.h:475
int & sampleCount(char *base, int xStride, int yStride, int x, int y)
Definition: ImfMisc.h:62
void trimLength(int nrecords)
Trim the list to the number of records specified.
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
const uint8 * flags(uint8 *storage, int start=0, int end=-1) const
const uint64 * fillCoverage(uint64 *storage, int start, int end) const
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
const uint64 * coverage(uint64 *storage, int start=0, int end=-1) const
GLint j
Definition: glad.h:2733
const float * channelData(int channel, float *storage, int start=0, int end=-1) const
SIM_API const UT_StringHolder force
const float * channelData(int channel, int sample, float *storage) const
const uint64 * coverageBuffer() const
Get read-only array of coverages.
void addVolume(const PXL_DeepSampleList &s, int sidx, float zinterp, bool beerlambert=false)
const float * zfront(float *storage, int start=0, int end=-1) const
float zfront(int sample) const
Return z-back for given sample.
const float * fillChannel(int ch, float *storage, int start, int end) const
const uint8 * flagBuffer() const
const float * zfrontBuffer() const
Sum(PXL_DeepSampleList &list, int idx, float scale)
void setPreComposited(bool c)
Set the pre-composited state.
ImageBuf OIIO_API add(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
const float * channelBuffer(int i) const
Get read-only array of data for a given channel.
bool preComposited() const
Class to help with weighted sums of pixels.
#define SYSmin(a, b)
Definition: SYS_Math.h:1571
#define GET_SCALAR(TYPE, VMETHOD)
const float * zbackBuffer() const
uint64 coverage(int sample) const
Return the sub-sample pixel location for a given sample.
ImageBuf OIIO_API channels(const ImageBuf &src, int nchannels, cspan< int > channelorder, cspan< float > channelvalues={}, cspan< std::string > newchannelnames={}, bool shuffle_channel_names=false, int nthreads=0)
bool isMatte(int sample) const
Check to see whether a sample is a matte sample.
GLenum src
Definition: glcorearb.h:1793