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 
7 #ifndef INCLUDED_IMF_PARTHELPER_H
8 #define INCLUDED_IMF_PARTHELPER_H
9 
10 //-----------------------------------------------------------------------------
11 //
12 // Functions to help split channels into separate parts: provide a list of
13 // channels, with desired views. call SplitChannels to assign a part to each
14 // layer, or correct the name of the channel.
15 // Also can enumerate the parts in a file and list which parts channels are in
16 //
17 // This is a good way to offer a 'create Multipart file' checkbox to the user in a
18 // write dialog box: Populate a list of MultiViewChannelName objects,
19 // call SplitChannels with whether single or multipart files are required.
20 // Then write the number of parts it specifies, using internal_name for the channel
21 // names in the ChannelList and FrameBuffer objects. There should be no need
22 // for different codepaths for single part and multipart files
23 //
24 // Similarly, on reading a file as a MultiPartInputFile, use GetChannelsInMultiPartFile to
25 // enumerate all channels in the file, using internal_name in FrameBuffer objects
26 // to read the channel
27 //
28 //
29 //-----------------------------------------------------------------------------
30 
31 #include "ImfForward.h"
32 #include "ImfNamespace.h"
33 #include "ImfExport.h"
34 #include "ImfMultiPartInputFile.h"
35 #include "ImfChannelList.h"
37 #include "ImfStandardAttributes.h"
38 #include "ImfMultiView.h"
39 
40 #include <string>
41 #include <map>
42 #include <set>
43 
45 
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 internal_name;///< name used in headers: in singlepart mode, may contain viewname
54 
55  //return layer for this channel, or "" if no layer
57  {
58  std::size_t q=name.rfind('.');
59  if( q==name.npos )
60  {
61  return "";
62  }
63  return name.substr(0,q);
64 
65  }
66 
68  {
69  std::size_t q=name.rfind('.');
70  if( q==name.npos )
71  {
72  return name;
73  }
74  return name.substr(q+1);
75 
76  }
77 
78 };
79 
80 
81 
82 //
83 ///\brief assigns individual channels to different parts based on their layer and view name
84 /// input is an array, list, vector etc of MultiViewChannelName objects
85 /// on entry, each MultiViewChannelName name/view must be set (view can be empty if not multiview)
86 ///
87 /// if singlepart set, then on exit part_number will be zero, and internal_name will have view name inserted
88 /// otherwise, each channel will be assigned to a different part based on its layer name and view name
89 ///
90 /// @param begin pointer to first MultiViewChannelName item
91 /// @param end pointer to end of MultiViewChannelName item array
92 /// @return total number of parts required
93 //
94 
95 template<typename T> inline int
96 SplitChannels(const T & begin,const T & end,bool multipart=true,const std::string & heroView=std::string())
97 {
98  if(!multipart)
99  {
100  for(T i=begin;i!=end;i++)
101  {
102  i->part_number=0;
103 
104  //does this have a view name set?
105  if(i->view=="")
106  {
107  i->internal_name=i->name;
108  }else{
109 
110  std::string lname = i->getLayer();
111 
112  // no layer, only non-hero views get view name in layer name
113 
114 
115  if(lname=="")
116  {
117  if(i->view==heroView)
118  {
119  i->internal_name = i->name;
120  }else{
121  i->internal_name = i->view+"."+i->name;
122  }
123  }else{
124  i->internal_name = lname+"."+i->view+"."+i->getSuffix();
125  }
126  }
127  }
128  // single part created
129  return 1;
130  }else{
131  // step 1: extract individual layers and parts
132  // for each layer, enumerate which views are active
133 
134  std::map< std::string , std::set< std::string > > viewsInLayers;
135  for(T i=begin;i!=end;i++)
136  {
137  viewsInLayers[i->getLayer()].insert(i->view);
138  }
139 
140  // step 2: assign a part number to each layer/view
141 
142  std::map< std::pair<std::string,std::string> , int > layerToPart;
143 
144  int partCount=0;
145 
146  for(std::map< std::string , std::set< std::string > >::const_iterator layer=viewsInLayers.begin();
147  layer!=viewsInLayers.end();layer++)
148  {
149  // if this layer has a heroView, insert that first
150  bool layer_has_hero = layer->second.find(heroView)!=layer->second.end();
151  if( layer_has_hero )
152  {
153  layerToPart[ std::make_pair(layer->first,heroView) ] = partCount++;
154  }
155 
156 
157  // insert other layers which aren't the hero view
158  for(std::set< std::string >::const_iterator view=layer->second.begin();
159  view!=layer->second.end();view++)
160  {
161  if(*view!=heroView)
162  {
163  layerToPart[ std::make_pair(layer->first,*view) ] = partCount++;
164  }
165  }
166 
167  }
168 
169  // step 3: update part number of each provided channel
170 
171  for( T i=begin;i!=end;i++)
172  {
173  i->internal_name=i->name;
174  i->part_number = layerToPart[ std::make_pair(i->getLayer(),i->view) ];
175  }
176 
177 
178  // return number of parts created
179  return partCount;
180  }
181 }
182 
183 //
184 // populate the chans vector<MultiViewChannelName> with a list of channels in the file
185 // and their corresponding part number
186 //
187 template<class T> 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())
207  {
208  view=file.header(p).view();
209  }
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  }else{
221  m.view=view;
222  }
223  m.part_number=p;
224  chans.push_back(m);
225 
226  }
227  }
228 }
229 
231 
232 #endif
#define OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
Definition: ImfNamespace.h:80
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:67
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:96
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:56
std::string internal_name
name used in headers: in singlepart mode, may contain viewname
Definition: ImfPartHelper.h:53
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:79
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:483