HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IMG_DeepShadow.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: IMG_DeepShadow.h ( IMG Library, C++)
7  *
8  * COMMENTS: Deep shadow API
9  */
10 
11 #pragma once
12 
13 #ifndef __IMG_DeepShadow__
14 #define __IMG_DeepShadow__
15 
16 #include "IMG_API.h"
17 #include "IMG_DeepStat.h"
18 #include "IMG_FileTypes.h"
19 
20 #include <PXL/PXL_Forward.h>
21 #include <UT/UT_NonCopyable.h>
22 #include <UT/UT_Rect.h>
23 #include <UT/UT_SharedPtr.h>
24 #include <UT/UT_StringHolder.h>
25 #include <UT/UT_UniquePtr.h>
26 #include <UT/UT_ValArray.h>
27 #include <UT/UT_VectorTypes.h>
28 
29 class PXL_DeepPixel;
30 class PXL_DeepSampleList;
31 class img_DeepShadow;
32 class IMG_DeepShadow;
34 class IMG_FileParms;
35 class IMG_Format;
36 class IMG_Stat;
37 class UT_WorkBuffer;
38 class UT_Options;
39 
40 /// @brief Thread-safe convenience class to make reading DSM pixels easy
41 ///
42 /// This is a thread-safe convenience class to wrap around reading pixels
43 /// which ensures that the pixel is closed properly.
44 ///
45 /// @warning Beware when declaring an IMG_DeepPixelReader in the same scope
46 /// as an IMG_DeepShadow. Since the pixel reader keeps a reference to the
47 /// file, the destruction order is important -- though calling close()
48 /// should avoid any problems.
49 ///
50 /// The class should be used as follows: @code
51 ///
52 /// IMG_DeepPixelReader pixel(dsm);
53 /// for (x, y) in raster {
54 /// if (pixel.open(x, y)) {
55 /// for (int i = 0; i < pixel.getDepth(); i++)
56 /// data = pixel.getData(chp, i);
57 /// }
58 /// }
59 /// @endcode
60 ///
62 {
63 public:
66 
68 
69  /// Open a pixel for reading
70  bool open(int x, int y);
71  /// Close the pixel. This is called automatically on destruction.
72  /// However, if an IMG_DeepPixelReader and IMG_DeepShadow are created in
73  /// the same scope, the IMG_DeepPixelReader may hold onto references (and
74  /// cause crashing errors). Calling close() manually is a safe thing to
75  /// do.
76  void close();
77  /// Returns the number of z-records
78  int getDepth() const;
79  /// Return the data for the channel at the given depth index.
80  const float *getData(const IMG_DeepShadowChannel &chp,
81  int depth_index);
82 
83  /// Alternately, just fill a PXL_DeepSampleList with the appropriate
84  /// data. This manages zback, coverage, flags and other special deep
85  /// channels.
86  bool readPixel(int x, int y, PXL_DeepSampleList &pixel) const;
87 
88 
89  /// After opening, you can call either of these methods to ensure that the
90  /// data is in the correct form for your application. "composited" pixels
91  /// will have the data accumulated over from front to back. "uncomposited"
92  /// pixels will have the raw data for each z-record.
93  ///
94  /// If the force flag is false, then the state of the file will be used
95  /// to determine whether the deep records need to be processed or not.
96  ///
97  /// These methods should be called after the pixel has been opened.
98  void composite(const IMG_DeepShadowChannel &pz,
99  const IMG_DeepShadowChannel &of,
100  bool force = false);
101  void uncomposite(const IMG_DeepShadowChannel &pz,
102  const IMG_DeepShadowChannel &of,
103  bool force = false);
104 
105 private:
106  class DeepShadowPixel; // Forward declaration
107  DeepShadowPixel *myHandle;
108 };
109 
110 /// @brief Thread-safe convenience class to make writing DSM pixels easy
111 ///
112 /// This is a thread-safe convenience class to wrap around writing pixels
113 /// which ensures that the pixel is closed properly.
114 ///
115 /// @warning Beware when declaring an IMG_DeepPixelReader in the same scope
116 /// as an IMG_DeepShadow. Since the pixel reader keeps a reference to the
117 /// file, the destruction order is important -- though calling close()
118 /// should avoid any problems.
119 ///
120 /// The class should be used as follows for sequential samples: @code
121 ///
122 /// IMG_DeepPixelWriter pixel(dsm);
123 /// for (x, y) in raster {
124 /// if (pixel.open(x, y)) {
125 /// for (int i = 0; i < depth; i++)
126 /// data = pixel.writeOrdered(z, data, vsize);
127 /// pixel.close();
128 /// }
129 /// }
130 /// @endcode
131 ///
133 {
134 public:
137 
139 
140  /// Ignore the desired sample compositing state in IMG_DeepShadow.
141  /// The default is to assume the incoming samples are pre-composited.
142  /// Writing raw samples will ignore compression levels, since the
143  /// compressors assume pre-composited samples.
144  void writeRawSamples(bool enable);
145 
146  /// Open a pixel for writing
147  bool open(int x, int y);
148 
149  /// Close the pixel. This is called automatically on destruction.
150  /// However, if an IMG_DeepPixelWriter and IMG_DeepShadow are created in
151  /// the same scope, the IMG_DeepPixelReader may hold onto references (and
152  /// cause crashing errors). Calling close() manually is a safe thing to
153  /// do.
154  bool close();
155 
156  /// Write data to the currently open pixel. This method inserts an
157  /// unordered data record with the given z-value and data into the
158  /// current pixel. vsize is the number of floats that are contained
159  /// in the data array.
160  ///
161  /// The first 3 floats of the data array must be the opacity (RGB). Any
162  /// extra channel data follows this according to the float_offset
163  /// associated with the channel. This data may be quantized to a single
164  /// float depending on the options.
165  ///
166  /// If @c vsize doesn't contain a full record, then this method will fail.
167  /// vsize must be greater or equal to 3 (depending on extra channels)
168  ///
169  /// Currently, mantra will always interpret the data as a rgb opacity
170  /// triple.
171  ///
172  /// The @c flags parameter is used to pass information to the
173  /// @c PXL_DeepSampleList interface. Possible values are:
174  /// - 0x00: No special meaning
175  /// - 0x01: Sample represents a volume
176  /// - 0x02: Sample is a matte surface
177  /// These values are found in the @c PXL_DeepSampleList::SampleFlag enum.
178  ///
179  /// The @c sampleid parameter specifies which pixel sample is associated
180  /// with these values (see @c sxres and @c syres on the create() method).
181  ///
182  /// The @c z value represents the "z-front" value for the depth sample.
183  /// For hard surfaces @c dz should be 0. For volumes @c dz should be set
184  /// to the extent of the volume sample so that the "z-back" data can be set
185  /// appropriately.
186  bool write(float z,
187  const float *chdata, int chsize,
188  int flags,
189  int sampleid,
190  float dz=0);
191 
192  /// Perform the same operation as write() except assume that data
193  /// is pre-sorted by increasing z-value. This method will perform
194  /// slightly better than write() as data does not need to be sorted.
195  bool writeOrdered(float z,
196  const float *chdata, int chsize,
197  int flags,
198  int sampleid,
199  float dz=0)
200  {
201  return write(z, chdata, chsize, flags, sampleid, dz);
202  }
203 
204  /// Alternatively, you can do something like: @code
205  /// PXL_DeepPixel pixel;
206  /// pixel.startPixel(x, y);
207  /// for (rec : records) pixel.store(rec);
208  /// write(pixel.closePixel(writer.compressor()));
209  /// @endcode
210  bool writePixel(int pixel_x, int pixel_y,
211  const PXL_DeepSampleListPtr &pixel);
212 
213  /// Access to the pixel compressor.
214  const PXL_DeepCompressorPtr &compressor() const { return myDeepCompressor; }
215 
216 private:
217  img_DeepShadow *myFile;
218  int myPixelX, myPixelY;
219  UT_UniquePtr<PXL_DeepPixel> myDeepPixel;
220  PXL_DeepCompressorPtr myDeepCompressor;
221  bool myWriteRaw;
222 };
223 
224 /// @brief Single channel of a Houdini DSM image
225 ///
226 /// A Houdini deep shadow/camera file can have any number of image channels
227 /// (planes). A DSM image contains a single channel for opacity. A deep
228 /// camera image has the opacity channel along with any number of extra image
229 /// channels.
231 {
232 public:
233  /// @param name The unique name of the DSM channel
234  /// @param float_offset
235  /// When data is read or written in deep shadow files, the pixel
236  /// data is interleaved. That is, the data for a single pixel can
237  /// be represented as an array of floats. Each channel has a
238  /// unique offset into the array. The user should @b not assume
239  /// that the offsets are contiguous. For example, the pixel data
240  /// might look like: @code
241  /// [ Of.r, // Opacity red
242  /// Of.g, // Opacity green
243  /// Of.b, // Opacity blue
244  /// Cf.r, // Color (red)
245  /// Cf.g, // Color (green)
246  /// Cf.b, // Color (blue)
247  /// s, // s coordinate
248  /// t, // t coordinate
249  /// N.x, // Normal x
250  /// N.y, // Normal y
251  /// N.z, // Normal z
252  /// ]
253  /// @endcode
254  /// Where the channels would be defined by: @code
255  /// IMG_DeepShadowChannel("Of", 0, 3);
256  /// IMG_DeepShadowChannel("Cf", 3, 3);
257  /// IMG_DeepShadowChannel("s", 6, 1);
258  /// IMG_DeepShadowChannel("t", 7, 1);
259  /// IMG_DeepShadowChannel("N", 8, 3);
260  /// @endcode
261  /// @param tuple_size Number of floats
262  /// @param storage
263  /// Storage type. This may be one of { "real16", "real32",
264  /// "real64" }. This value represents the storage of the channel
265  /// in the file.
266  /// @see IMG_DeepShadow::addExtraChannel()
267  IMG_DeepShadowChannel(const char *name,
268  int float_offset,
269  int tuple_size,
270  const char *storage="real32");
271 
272  bool operator==(const IMG_DeepShadowChannel &s) const;
273 
274  /// @{
275  /// Data acceess function
276  const char *getName() const { return myName.c_str(); }
277  const char *getStorage() const { return myStorage.c_str(); }
278  int getOffset() const { return myOffset; }
279  int getTupleSize() const { return myTupleSize; }
280  /// @}
281 
282 private:
283  UT_StringHolder myName;
284  UT_StringHolder myStorage;
285  int myOffset;
286  int myTupleSize;
287 };
288 
289 /// @brief Class to read or write deep shadow/camera images
290 ///
291 /// This class provides a creation interface for deep shadow maps.
292 /// The class can be used as follows: @code
293 /// setOption(...);
294 /// setOption(...);
295 /// ...
296 /// open(fname, xres, yres);
297 /// IMG_DeepPixelWriter writer;
298 /// foreach pixel loop
299 /// writer.open(pixel);
300 /// foreach record
301 /// writer.write(record);
302 /// end loop
303 /// writer.close();
304 /// end loop
305 /// close();
306 /// @endcode
307 ///
308 /// To read from an existing deep shadow map, the class can be used as
309 /// follows: @code
310 /// IMG_DeepShadow dsm;
311 /// IMG_DeepPixelReader pixel;
312 /// dsm.open(fname);
313 /// foreach (x,y) in raster:
314 /// pixel.open(x, y)
315 /// for (i = 0; i < pixel.getDepth(); i++)
316 /// pixel.getData(chp, i);
317 /// close();
318 /// @endcode
319 ///
320 /// @see
321 /// - TIL_TextureMap - for filtered evaluation of DSM/DCM's)
322 /// - IMG_DeepPixelReader - For thread-safe reading of DSM pixels
323 /// - IMG_DeepShadowChannel
325 {
326 public:
327  IMG_DeepShadow();
328  virtual ~IMG_DeepShadow();
329 
331 
332  /// Certain channel names are reserved as "special" channels. These
333  /// channels have special interpretations for deep images (i.e. "Z",
334  /// "ZBack", etc.). Each format registers their special channel names
335  static void addSpecialChannel(const UT_StringHolder &channel_name,
337  static IMG_DeepPlaneMask isSpecialChannel(const char *name);
338 
339  /// Set a file creation option. Options must be set before the
340  /// file is opened with open() below.
341  ///
342  /// Currently (and this list may be out of date), the options are:
343  /// - "ofstorage" = one of { "int8", "int16", "int32", "int64",
344  /// "uint8", "uint16", "uint32", "uint64",
345  /// "real16", "real32", "real64" }
346  /// - "pzstorage" = one of { "int8" ... "real64" }
347  /// - "ofsize" = one of { "1", "3" }
348  /// - "compression = a value between "0" and "9" (lossyness)
349  /// - "zbias" = minimum delta between z-values (float value)
350  /// - "depth_mode" = one of { "nearest", "midpoint", "farthest" }
351  /// - "depth_interp" = one of { "discrete", "continuous" }
352  /// - "compositing" = "0" will turn off pre-compositing of the z-records
353  /// This is recommended when dealing with deep camera maps (i.e. if
354  /// there are extra channels)
355  void setOption(const char *option, const UT_StringHolder &value);
356  void setOption(const char *option, fpreal value);
357  void setOption(const char *option, int64 value);
358  void setOption(const char *option, int value)
359  { setOption(option, (int64)value); }
360 
361  /// Set options based on the "texture:*" options defined in the UT_Options.
362  /// The UT_Options will be checked for options:
363  /// - @c texture:ofstorage
364  /// - @c texture:pzstorage
365  /// - @c texture:ofsize
366  /// - @c etc.
367  void setOptions(const UT_Options &options);
368 
369  /// Print the current values of the file options into the work buffer
370  void printArgs(UT_WorkBuffer &wbuf, bool json);
371 
372  /// Get a description of the available options that can be provided in
373  /// setOption()
374  const char *getDescription();
375 
376  /// Add an extra channel to be stored along with Of and Pz. Any number of
377  /// channels may be added (though the file size will increase accordingly).
378  /// - The name must be unique among (and not Of or Pz)
379  /// - The float_offset is the offset into the "data" in the
380  /// IMG_DeepPixelWriter::write() method. Note that the opacity
381  /// must occupy the first 3
382  /// floats of the data array. So, the float_offset @b must be at least 3.
383  /// - The tuple_size is the number of elements in the channel
384  /// Currently, this must be 1, 3 or 4.
385  /// - The storage specifies the storage type (and uses the same
386  /// tokens as the "ofstorage" option (i.e. int8, int16, int32, int64,
387  /// uint8, uint16, uint32, uint64, real16, real32 or real64.
388  /// The extra channels must be added @b before open() is called.
389  bool addExtraChannel(const IMG_DeepShadowChannel &def,
390  const UT_Options *options=0);
391 
392  /// Open a deep shadow map for writing. This method will return false
393  /// if there were errors opening the texture.
394  /// The resolution of the image is specified by @c xres and @c yres, while
395  /// the @c sxres and @c syres parameters specify the samples per pixel
396  /// (i.e. 3x3 sampling). The pixel_aspect is typically 1.0, while the crop
397  /// can be a NULL ptr.
398  ///
399  /// If the sample resolution is unknown, you can set @c sxres and @c syres
400  /// to 1 (the @c sampleid should be set to 0).
401  /// @{
402  bool create(const char *name, int xres, int yres,
403  int sxres, int syres,
404  float pixel_aspect = 1.0,
405  const UT_DimRect *crop = NULL);
406  bool create(
407  const char *name,
408  const IMG_Stat &stat,
409  const IMG_FileParms *options = NULL,
410  const IMG_Format *fmt = NULL);
411  ///@}
412 
413  /// Open a deep shadow map for reading.
414  bool open(const char *name);
415 
416 
417  /// These methods are now deprecated in favor of the
418  /// IMG_DeepPixelWriter class, which allows thread-safe writes to
419  /// deep images.
420  /// {
421  SYS_DEPRECATED(13.0)
422  bool pixelStart(int x, int y);
423  SYS_DEPRECATED(13.0)
424  bool pixelWrite(float z, const float *data, int vsize);
425  SYS_DEPRECATED(13.0)
426  bool pixelWriteOrdered(float z, const float *data,
427  int vsize);
428  SYS_DEPRECATED(13.0)
429  bool pixelClose();
430  /// }
431 
432  /// Close the deep shadow map and write it to disk.
433  bool close();
434 
435 public:
436 
437  /// Get the resolution of the deep shadow map.
438  void resolution(int &xres, int &yres) const;
439 
440  /// Get the number of channels in the DSM
441  int getChannelCount() const;
442 
443  /// Get a channel definition
444  const IMG_DeepShadowChannel *getChannel(int i) const;
445 
446  /// Get UT_Option structure from the file. These options are stored with
447  /// the file and may be queried in VEX using teximport().
448  UT_SharedPtr<UT_Options> getTextureOptions() const;
449 
450  /// Store the UT_Options structure in the file. These options are stored with
451  /// the file and may be queried in VEX using teximport() on load.
452  bool setTextureOptions(const UT_Options &opts);
453 
454  /// @{
455  /// Extract the worldToCamera transform from a UT_Options. Returns false
456  /// if there was no matrix available.
457  ///
458  /// This extracts the "space:world" matrix from the UT_Options.
459  static bool getWorldToCamera(const UT_Options *options,
460  UT_Matrix4F &xform);
461  static bool getWorldToCamera(const UT_Options *options,
462  UT_Matrix4D &xform);
463  template <typename T>
464  bool getWorldToCamera(UT_Matrix4T<T> &xform) const
465  { return getWorldToCamera(getTextureOptions().get(),
466  xform); }
467  /// @}
468 
469  /// @{
470  /// Get the camera's projection transform from the file options. Returns
471  /// false if there was no matrix available.
472  /// If @c fit_z is true, the projection will attempt to fit the z
473  /// coordinates to the NDC near/far to the range (0,1). If the camera:clip
474  /// option is not saved, this will not be possible (z coordinates will
475  /// remain unchanged). The method will @b not fail if there is no
476  /// camera:clip saved, but the z coordinates will have unexpected values
477  ///
478  /// The method gets the values for the projection matrix from the following
479  /// options:
480  /// - float camera:zoom
481  /// - int camera:projection (optional, defaults to 0)
482  /// - float image:pixelaspect (optional, defaults to 1)
483  /// - vector4 image:window (optional, defaults to [0, 1, 0, 1])
484  /// - vector2 camera:clip (used iff @c fit_z is true, defaults to (0,1))
485  /// - float camera:orthowidth (required iff @c projection != 0)
486  static bool getCameraToNDC(const UT_Options *options,
487  UT_Matrix4F &xform,
488  int xres, int yres,
489  bool fit_z=true);
490  static bool getCameraToNDC(const UT_Options *options,
491  UT_Matrix4D &xform,
492  int xres, int yres,
493  bool fit_z=true);
494  template <typename T>
496  bool fit_z=true) const
497  {
498  int xres, yres;
499  resolution(xres, yres);
500  return getCameraToNDC(getTextureOptions().get(),
501  xform, xres, yres, fit_z);
502  }
503  /// @}
504 
505  /// @{
506  /// Get the world to camera NDC space transform using the file options.
507  /// Returns false if there is no matrix available.
508  /// If @c fit_z is true, the projection will attempt to fit the z
509  /// coordinates to the NDC near/far to the range (0,1). If the camera:clip
510  /// option is not saved, this will not be possible (z coordinates will
511  /// remain unchanged).
512  /// @note This simply returns getWorldToCamera()*getCameraToNDC()
513  static bool getWorldToNDC(const UT_Options *options,
514  UT_Matrix4F &xform,
515  int xres, int yres, bool fit_z);
516  static bool getWorldToNDC(const UT_Options *options,
517  UT_Matrix4D &xform,
518  int xres, int yres, bool fit_z);
519  template <typename T>
521  bool fit_z) const
522  {
523  int xres, yres;
524  resolution(xres, yres);
525  return getWorldToNDC(getTextureOptions().get(),
526  xform, xres, yres, fit_z);
527  }
528  /// @}
529 
530  /// Return deep stats
531  UT_SharedPtr<IMG_DeepStat> getDeepStat() const;
532 
533  float ofBias() const;
534  float zBias() const;
535 
536  /// Return the PXL_DeepChannelList being written to the DSM
537  const PXL_DeepChannelListPtr &deepChannels() const;
538 
539  /// Return the number of samples per pixel
540  int deepSampleListsPerPixel() const;
541 
542  /// Metadata to send to deep image file
543  void setWriteTag(
544  const char *tag,
545  int datasize,
546  const char *const *data);
547 
548  bool copyImageTextureOptions(const IMG_DeepShadow &src, bool clear_existing);
549 
550 protected:
551  /// Perform all computation for creating an image, but don't actually open
552  /// the IMG_File. This can be done when you want to make sure all the deep
553  /// information is set up properly, but don't actually want to create the
554  /// image. One example of this might be when doing distributed rendering.
555  ///
556  /// This takes the same arguments as @c create().
557  bool createStat(IMG_Stat &stat,
558  const char *name, int xres, int yres,
559  int sxres, int syres,
560  float pixel_aspect,
561  const UT_DimRect *crop);
562 
563 private:
564  friend class IMG_DeepPixelReader;
565  friend class IMG_DeepPixelWriter;
566 
567  bool openPixelRead(IMG_DeepPixelReader &h, int x, int y);
568  void closePixelRead(IMG_DeepPixelReader &h);
569 
570 private:
571  friend class img_DeepShadow;
572 
573 private:
575  img_DeepShadow *myFile;
576 };
577 
578 #endif
GLbitfield flags
Definition: glcorearb.h:1596
PXL_API const char * getDescription(const ColorSpace *space)
Return the description of the color space.
#define SYS_DEPRECATED(__V__)
Thread-safe convenience class to make reading DSM pixels easy.
getFileOption("OpenEXR:storage") storage
Definition: HDK_Image.dox:276
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
Single channel of a Houdini DSM image.
const PXL_DeepCompressorPtr & compressor() const
Access to the pixel compressor.
Thread-safe convenience class to make writing DSM pixels easy.
GLdouble s
Definition: glad.h:3009
GLint y
Definition: glcorearb.h:103
Class to read or write deep shadow/camera images.
void close() override
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
void setOption(const char *option, int value)
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
#define IMG_API
Definition: IMG_API.h:10
const char * getName() const
int open(float queuesize) override
bool getCameraToNDC(UT_Matrix4T< T > &xform, bool fit_z=true) const
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:36
int getTupleSize() const
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
IMG_DeepPlaneMask
Definition: IMG_DeepStat.h:35
long long int64
Definition: SYS_Types.h:116
HUSD_API const char * resolution()
GLuint const GLchar * name
Definition: glcorearb.h:786
GLint GLenum GLint x
Definition: glcorearb.h:409
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
A map of string to various well defined value types.
Definition: UT_Options.h:84
SIM_API const UT_StringHolder force
fpreal64 fpreal
Definition: SYS_Types.h:277
bool getWorldToNDC(UT_Matrix4T< T > &xform, bool fit_z) const
File options for manipulating image data on load or save. This class allows you to modify the incomin...
Definition: IMG_FileParms.h:38
Contains the details of a specific image file, used by IMG_File. This class contains all the high-lev...
Definition: IMG_Stat.h:38
Definition: core.h:1131
UT_SharedPtr< PXL_DeepCompressor > PXL_DeepCompressorPtr
Definition: PXL_Forward.h:26
#define const
Definition: zconf.h:214
const char * getStorage() const
ImageBuf OIIO_API crop(const ImageBuf &src, ROI roi={}, int nthreads=0)
void write(T &out, bool v)
Definition: ImfXdr.h:287
type
Definition: core.h:1059
bool writeOrdered(float z, const float *chdata, int chsize, int flags, int sampleid, float dz=0)
Definition: format.h:895
GLenum src
Definition: glcorearb.h:1793