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
54  internal_name; ///< name used in headers: in singlepart mode, may contain viewname
55 
56  //return layer for this channel, or "" if no layer
58  {
59  std::size_t q = name.rfind ('.');
60  if (q == name.npos) { return ""; }
61  return name.substr (0, q);
62  }
63 
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
112  {
113  i->internal_name = i->view + "." + i->name;
114  }
115  }
116  else
117  {
118  i->internal_name =
119  lname + "." + i->view + "." + i->getSuffix ();
120  }
121  }
122  }
123  // single part created
124  return 1;
125  }
126  else
127  {
128  // step 1: extract individual layers and parts
129  // for each layer, enumerate which views are active
130 
131  std::map<std::string, std::set<std::string>> viewsInLayers;
132  for (T i = begin; i != end; i++)
133  {
134  viewsInLayers[i->getLayer ()].insert (i->view);
135  }
136 
137  // step 2: assign a part number to each layer/view
138 
139  std::map<std::pair<std::string, std::string>, int> layerToPart;
140 
141  int partCount = 0;
142 
143  for (std::map<std::string, std::set<std::string>>::const_iterator
144  layer = viewsInLayers.begin ();
145  layer != viewsInLayers.end ();
146  layer++)
147  {
148  // if this layer has a heroView, insert that first
149  bool layer_has_hero =
150  layer->second.find (heroView) != layer->second.end ();
151  if (layer_has_hero)
152  {
153  layerToPart[std::make_pair (layer->first, heroView)] =
154  partCount++;
155  }
156 
157  // insert other layers which aren't the hero view
158  for (std::set<std::string>::const_iterator view =
159  layer->second.begin ();
160  view != layer->second.end ();
161  view++)
162  {
163  if (*view != heroView)
164  {
165  layerToPart[std::make_pair (layer->first, *view)] =
166  partCount++;
167  }
168  }
169  }
170 
171  // step 3: update part number of each provided channel
172 
173  for (T i = begin; i != end; i++)
174  {
175  i->internal_name = i->name;
176  i->part_number =
177  layerToPart[std::make_pair (i->getLayer (), i->view)];
178  }
179 
180  // return number of parts created
181  return partCount;
182  }
183 }
184 
185 //
186 // populate the chans vector<MultiViewChannelName> with a list of channels in the file
187 // and their corresponding part number
188 //
189 template <class T>
190 inline void
192 {
193  bool has_multiview = false;
194  StringVector mview;
195  if (file.parts () == 1)
196  {
197  if (hasMultiView (file.header (0)))
198  {
199  mview = multiView (file.header (0));
200  has_multiview = true;
201  }
202  }
203 
204  for (int p = 0; p < file.parts (); p++)
205  {
206  const ChannelList& c = file.header (p).channels ();
207 
208  std::string view = "";
209  if (file.header (p).hasView ()) { view = file.header (p).view (); }
210  for (ChannelList::ConstIterator i = c.begin (); i != c.end (); i++)
211  {
213  m.name = std::string (i.name ());
214  m.internal_name = m.name;
215 
216  if (has_multiview)
217  {
218  m.view = viewFromChannelName (m.name, mview);
220  }
221  else
222  {
223  m.view = view;
224  }
225  m.part_number = p;
226  chans.push_back (m);
227  }
228  }
229 }
230 
232 
233 #endif
#define OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
Definition: ImfNamespace.h:83
IMF_EXPORT ChannelList & channels()
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
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)
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)
#define OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
Definition: ImfNamespace.h:80
IMF_EXPORT const Header & header(int n) const
Definition: core.h:982
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:558