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