HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ImfPartHelper.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012, Weta Digital Ltd
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are
9 // met:
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 // * Neither the name of Weta Digital nor the names of
17 // its contributors may be used to endorse or promote products derived
18 // from this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 //
32 ///////////////////////////////////////////////////////////////////////////
33 
34 
35 #ifndef INCLUDED_IMF_PARTHELPER_H
36 #define INCLUDED_IMF_PARTHELPER_H
37 
38 //-----------------------------------------------------------------------------
39 //
40 // Functions to help split channels into separate parts: provide a list of
41 // channels, with desired views. call SplitChannels to assign a part to each
42 // layer, or correct the name of the channel.
43 // Also can enumerate the parts in a file and list which parts channels are in
44 //
45 // This is a good way to offer a 'create Multipart file' checkbox to the user in a
46 // write dialog box: Populate a list of MultiViewChannelName objects,
47 // call SplitChannels with whether single or multipart files are required.
48 // Then write the number of parts it specifies, using internal_name for the channel
49 // names in the ChannelList and FrameBuffer objects. There should be no need
50 // for different codepaths for single part and multipart files
51 //
52 // Similarly, on reading a file as a MultiPartInputFile, use GetChannelsInMultiPartFile to
53 // enumerate all channels in the file, using internal_name in FrameBuffer objects
54 // to read the channel
55 //
56 //
57 //-----------------------------------------------------------------------------
58 
59 #include "ImfForward.h"
60 #include "ImfNamespace.h"
61 #include "ImfExport.h"
62 #include "ImfMultiPartInputFile.h"
63 #include "ImfChannelList.h"
65 #include "ImfStandardAttributes.h"
66 #include "ImfMultiView.h"
67 
68 #include <string>
69 #include <map>
70 #include <set>
71 
73 
75 
76 public:
77  std::string name; ///< name of channel
78  std::string view; ///< view for channel
79 
80  int part_number; ///< part number: updated by SplitChannels
81  std::string internal_name;///< name used in headers: in singlepart mode, may contain viewname
82 
83  virtual ~MultiViewChannelName() {}
84 
85  //return layer for this channel, or "" if no layer
87  {
88  std::size_t q=name.rfind('.');
89  if( q==name.npos )
90  {
91  return "";
92  }
93  return name.substr(0,q);
94 
95  }
96 
98  {
99  std::size_t q=name.rfind('.');
100  if( q==name.npos )
101  {
102  return name;
103  }
104  return name.substr(q+1);
105 
106  }
107 
108 };
109 
110 
111 
112 //
113 ///\brief assigns individual channels to different parts based on their layer and view name
114 /// input is an array, list, vector etc of MultiViewChannelName objects
115 /// on entry, each MultiViewChannelName name/view must be set (view can be empty if not multiview)
116 ///
117 /// if singlepart set, then on exit part_number will be zero, and internal_name will have view name inserted
118 /// otherwise, each channel will be assigned to a different part based on its layer name and view name
119 ///
120 /// @param begin pointer to first MultiViewChannelName item
121 /// @param end pointer to end of MultiViewChannelName item array
122 /// @return total number of parts required
123 //
124 
125 template<typename T> int
126 SplitChannels(const T & begin,const T & end,bool multipart=true,const std::string & heroView="")
127 {
128  if(!multipart)
129  {
130  for(T i=begin;i!=end;i++)
131  {
132  i->part_number=0;
133 
134  //does this have a view name set?
135  if(i->view=="")
136  {
137  i->internal_name=i->name;
138  }else{
139 
140  std::string lname = i->getLayer();
141 
142  // no layer, only non-hero views get view name in layer name
143 
144 
145  if(lname=="")
146  {
147  if(i->view==heroView)
148  {
149  i->internal_name = i->name;
150  }else{
151  i->internal_name = i->view+"."+i->name;
152  }
153  }else{
154  i->internal_name = lname+"."+i->view+"."+i->getSuffix();
155  }
156  }
157  }
158  // single part created
159  return 1;
160  }else{
161  // step 1: extract individual layers and parts
162  // for each layer, enumerate which views are active
163 
164  std::map< std::string , std::set< std::string > > viewsInLayers;
165  for(T i=begin;i!=end;i++)
166  {
167  viewsInLayers[i->getLayer()].insert(i->view);
168  }
169 
170  // step 2: assign a part number to each layer/view
171 
172  std::map< std::pair<std::string,std::string> , int > layerToPart;
173 
174  int partCount=0;
175 
176  for(std::map< std::string , std::set< std::string > >::const_iterator layer=viewsInLayers.begin();
177  layer!=viewsInLayers.end();layer++)
178  {
179  // if this layer has a heroView, insert that first
180  bool layer_has_hero = layer->second.find(heroView)!=layer->second.end();
181  if( layer_has_hero )
182  {
183  layerToPart[ std::make_pair(layer->first,heroView) ] = partCount++;
184  }
185 
186 
187  // insert other layers which aren't the hero view
188  for(std::set< std::string >::const_iterator view=layer->second.begin();
189  view!=layer->second.end();view++)
190  {
191  if(*view!=heroView)
192  {
193  layerToPart[ std::make_pair(layer->first,*view) ] = partCount++;
194  }
195  }
196 
197  }
198 
199  // step 3: update part number of each provided channel
200 
201  for( T i=begin;i!=end;i++)
202  {
203  i->internal_name=i->name;
204  i->part_number = layerToPart[ std::make_pair(i->getLayer(),i->view) ];
205  }
206 
207 
208  // return number of parts created
209  return partCount;
210  }
211 }
212 
213 //
214 // populate the chans vector<MultiViewChannelName> with a list of channels in the file
215 // and their corresponding part number
216 //
217 template<class T> void
219 {
220  bool has_multiview=false;
221  StringVector mview;
222  if(file.parts()==1)
223  {
224  if(hasMultiView(file.header(0)))
225  {
226  mview=multiView(file.header(0));
227  has_multiview=true;
228  }
229  }
230 
231  for(int p=0;p<file.parts();p++)
232  {
233  const ChannelList & c=file.header(p).channels();
234 
235  std::string view="";
236  if(file.header(p).hasView())
237  {
238  view=file.header(p).view();
239  }
240  for(ChannelList::ConstIterator i=c.begin();i!=c.end();i++)
241  {
243  m.name=std::string(i.name());
244  m.internal_name=m.name;
245 
246  if(has_multiview)
247  {
248  m.view=viewFromChannelName(m.name,mview);
250  }else{
251  m.view=view;
252  }
253  m.part_number=p;
254  chans.push_back(m);
255 
256  }
257  }
258 }
259 
261 
262 #endif
virtual ~MultiViewChannelName()
Definition: ImfPartHelper.h:83
#define OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
Definition: ImfNamespace.h:109
GLenum GLuint GLint GLint layer
Definition: glcorearb.h:1298
GLsizei const GLchar *const * string
Definition: glcorearb.h:813
int parts() const
IMF_EXPORT std::string removeViewName(const std::string &channel, const std::string &view)
png_uint_32 i
Definition: png.h:2877
IMF_EXPORT std::string viewFromChannelName(const std::string &channel, const StringVector &multiView)
std::string name
name of channel
Definition: ImfPartHelper.h:77
GLuint GLuint end
Definition: glcorearb.h:474
std::string getSuffix() const
Definition: ImfPartHelper.h:97
Iterator begin()
int SplitChannels(const T &begin, const T &end, bool multipart=true, const std::string &heroView="")
assigns individual channels to different parts based on their layer and view name input is an array...
GLuint const GLchar * name
Definition: glcorearb.h:785
ChannelList & channels()
int part_number
part number: updated by SplitChannels
Definition: ImfPartHelper.h:80
bool hasView() const
std::string getLayer() const
Definition: ImfPartHelper.h:86
string & view()
std::string internal_name
name used in headers: in singlepart mode, may contain viewname
Definition: ImfPartHelper.h:81
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:108
const Header & header(int n) const
std::string view
view for channel
Definition: ImfPartHelper.h:78
Iterator end()