HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImfPartHelper.h
Go to the documentation of this file.
1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright (c) Weta Digital, Ltd and Contributors to the OpenEXR Project.
4 //
5 
6 #ifndef INCLUDED_IMF_PARTHELPER_H
7 #define INCLUDED_IMF_PARTHELPER_H
8 
9 //-----------------------------------------------------------------------------
10 //
11 // Functions to help split channels into separate parts: provide a list of
12 // channels, with desired views. call SplitChannels to assign a part to each
13 // layer, or correct the name of the channel.
14 // Also can enumerate the parts in a file and list which parts channels are in
15 //
16 // This is a good way to offer a 'create Multipart file' checkbox to the user in a
17 // write dialog box: Populate a list of MultiViewChannelName objects,
18 // call SplitChannels with whether single or multipart files are required.
19 // Then write the number of parts it specifies, using internal_name for the channel
20 // names in the ChannelList and FrameBuffer objects. There should be no need
21 // for different codepaths for single part and multipart files
22 //
23 // Similarly, on reading a file as a MultiPartInputFile, use GetChannelsInMultiPartFile to
24 // enumerate all channels in the file, using internal_name in FrameBuffer objects
25 // to read the channel
26 //
27 //
28 //-----------------------------------------------------------------------------
29 
30 #include "ImfChannelList.h"
31 #include "ImfExport.h"
32 #include "ImfForward.h"
33 #include "ImfMultiPartInputFile.h"
34 #include "ImfMultiView.h"
35 #include "ImfNamespace.h"
36 #include "ImfStandardAttributes.h"
38 
39 #include <map>
40 #include <set>
41 #include <string>
42 
44 
46 {
47 
48 public:
49  std::string name; ///< name of channel
50  std::string view; ///< view for channel
51 
52  int part_number; ///< part number: updated by SplitChannels
53  std::string
54  internal_name; ///< name used in headers: in singlepart mode, may contain viewname
55 
56  //return layer for this channel, or "" if no layer
57  std::string getLayer () const
58  {
59  std::size_t q = name.rfind ('.');
60  if (q == name.npos) { return ""; }
61  return name.substr (0, q);
62  }
63 
64  std::string getSuffix () const
65  {
66  std::size_t q = name.rfind ('.');
67  if (q == name.npos) { return name; }
68  return name.substr (q + 1);
69  }
70 };
71 
72 //
73 ///\brief assigns individual channels to different parts based on their layer and view name
74 /// input is an array, list, vector etc of MultiViewChannelName objects
75 /// on entry, each MultiViewChannelName name/view must be set (view can be empty if not multiview)
76 ///
77 /// if singlepart set, then on exit part_number will be zero, and internal_name will have view name inserted
78 /// otherwise, each channel will be assigned to a different part based on its layer name and view name
79 ///
80 /// @param begin pointer to first MultiViewChannelName item
81 /// @param end pointer to end of MultiViewChannelName item array
82 /// @return total number of parts required
83 //
84 
85 template <typename T>
86 inline int
88  const T& begin,
89  const T& end,
90  bool multipart = true,
91  const std::string& heroView = std::string ())
92 {
93  if (!multipart)
94  {
95  for (T i = begin; i != end; i++)
96  {
97  i->part_number = 0;
98 
99  //does this have a view name set?
100  if (i->view == "") { i->internal_name = i->name; }
101  else
102  {
103 
104  std::string lname = i->getLayer ();
105 
106  // no layer, only non-hero views get view name in layer name
107 
108  if (lname == "")
109  {
110  if (i->view == heroView) { i->internal_name = i->name; }
111  else { i->internal_name = i->view + "." + i->name; }
112  }
113  else
114  {
115  i->internal_name =
116  lname + "." + i->view + "." + i->getSuffix ();
117  }
118  }
119  }
120  // single part created
121  return 1;
122  }
123  else
124  {
125  // step 1: extract individual layers and parts
126  // for each layer, enumerate which views are active
127 
128  std::map<std::string, std::set<std::string>> viewsInLayers;
129  for (T i = begin; i != end; i++)
130  {
131  viewsInLayers[i->getLayer ()].insert (i->view);
132  }
133 
134  // step 2: assign a part number to each layer/view
135 
136  std::map<std::pair<std::string, std::string>, int> layerToPart;
137 
138  int partCount = 0;
139 
140  for (std::map<std::string, std::set<std::string>>::const_iterator
141  layer = viewsInLayers.begin ();
142  layer != viewsInLayers.end ();
143  layer++)
144  {
145  // if this layer has a heroView, insert that first
146  bool layer_has_hero =
147  layer->second.find (heroView) != layer->second.end ();
148  if (layer_has_hero)
149  {
150  layerToPart[std::make_pair (layer->first, heroView)] =
151  partCount++;
152  }
153 
154  // insert other layers which aren't the hero view
155  for (std::set<std::string>::const_iterator view =
156  layer->second.begin ();
157  view != layer->second.end ();
158  view++)
159  {
160  if (*view != heroView)
161  {
162  layerToPart[std::make_pair (layer->first, *view)] =
163  partCount++;
164  }
165  }
166  }
167 
168  // step 3: update part number of each provided channel
169 
170  for (T i = begin; i != end; i++)
171  {
172  i->internal_name = i->name;
173  i->part_number =
174  layerToPart[std::make_pair (i->getLayer (), i->view)];
175  }
176 
177  // return number of parts created
178  return partCount;
179  }
180 }
181 
182 //
183 // populate the chans vector<MultiViewChannelName> with a list of channels in the file
184 // and their corresponding part number
185 //
186 template <class T>
187 inline void
189 {
190  bool has_multiview = false;
191  StringVector mview;
192  if (file.parts () == 1)
193  {
194  if (hasMultiView (file.header (0)))
195  {
196  mview = multiView (file.header (0));
197  has_multiview = true;
198  }
199  }
200 
201  for (int p = 0; p < file.parts (); p++)
202  {
203  const ChannelList& c = file.header (p).channels ();
204 
205  std::string view = "";
206  if (file.header (p).hasView ()) { view = file.header (p).view (); }
207  for (ChannelList::ConstIterator i = c.begin (); i != c.end (); i++)
208  {
210  m.name = std::string (i.name ());
211  m.internal_name = m.name;
212 
213  if (has_multiview)
214  {
215  m.view = viewFromChannelName (m.name, mview);
217  }
218  else { m.view = view; }
219  m.part_number = p;
220  chans.push_back (m);
221  }
222  }
223 }
224 
226 
227 #endif
#define OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
Definition: ImfNamespace.h:83
IMF_EXPORT ChannelList & channels()
IMF_EXPORT Iterator begin()
IMF_EXPORT std::string removeViewName(const std::string &channel, const std::string &view)
GLdouble GLdouble GLdouble q
Definition: glad.h:2445
IMF_EXPORT Iterator end()
GLenum GLuint GLint GLint layer
Definition: glcorearb.h:1299
IMF_EXPORT bool hasView() const
IMF_EXPORT std::string viewFromChannelName(const std::string &channel, const StringVector &multiView)
TODO: Document this.
std::string name
name of channel
Definition: ImfPartHelper.h:49
GLuint GLuint end
Definition: glcorearb.h:475
std::string getSuffix() const
Definition: ImfPartHelper.h:64
IMF_EXPORT ConstIterator()
int SplitChannels(const T &begin, const T &end, bool multipart=true, const std::string &heroView=std::string())
assigns individual channels to different parts based on their layer and view name input is an array...
Definition: ImfPartHelper.h:87
GLuint const GLchar * name
Definition: glcorearb.h:786
int part_number
part number: updated by SplitChannels
Definition: ImfPartHelper.h:52
std::string getLayer() const
Definition: ImfPartHelper.h:57
std::string internal_name
name used in headers: in singlepart mode, may contain viewname
Definition: ImfPartHelper.h:54
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER typedef std::vector< std::string > StringVector
void GetChannelsInMultiPartFile(const MultiPartInputFile &file, T &chans)
IMF_EXPORT const Header & header(int partNumber) const
#define OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
Definition: ImfNamespace.h:80
IMF_EXPORT int parts() const
IMF_EXPORT string & view()
std::string view
view for channel
Definition: ImfPartHelper.h:50
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:566