ImfPartHelper.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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. #ifndef INCLUDED_IMF_PARTHELPER_H
  34. #define INCLUDED_IMF_PARTHELPER_H
  35. //-----------------------------------------------------------------------------
  36. //
  37. // Functions to help split channels into separate parts: provide a list of
  38. // channels, with desired views. call SplitChannels to assign a part to each
  39. // layer, or correct the name of the channel.
  40. // Also can enumerate the parts in a file and list which parts channels are in
  41. //
  42. // This is a good way to offer a 'create Multipart file' checkbox to the user in a
  43. // write dialog box: Populate a list of MultiViewChannelName objects,
  44. // call SplitChannels with whether single or multipart files are required.
  45. // Then write the number of parts it specifies, using internal_name for the channel
  46. // names in the ChannelList and FrameBuffer objects. There should be no need
  47. // for different codepaths for single part and multipart files
  48. //
  49. // Similarly, on reading a file as a MultiPartInputFile, use GetChannelsInMultiPartFile to
  50. // enumerate all channels in the file, using internal_name in FrameBuffer objects
  51. // to read the channel
  52. //
  53. //
  54. //-----------------------------------------------------------------------------
  55. #include "ImfForward.h"
  56. #include "ImfNamespace.h"
  57. #include "ImfExport.h"
  58. #include "ImfMultiPartInputFile.h"
  59. #include "ImfChannelList.h"
  60. #include "ImfStringVectorAttribute.h"
  61. #include "ImfStandardAttributes.h"
  62. #include "ImfMultiView.h"
  63. #include <string>
  64. #include <map>
  65. #include <set>
  66. OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
  67. struct MultiViewChannelName{
  68. public:
  69. std::string name; ///< name of channel
  70. std::string view; ///< view for channel
  71. int part_number; ///< part number: updated by SplitChannels
  72. std::string internal_name;///< name used in headers: in singlepart mode, may contain viewname
  73. virtual ~MultiViewChannelName() {}
  74. //return layer for this channel, or "" if no layer
  75. std::string getLayer() const
  76. {
  77. std::size_t q=name.rfind('.');
  78. if( q==name.npos )
  79. {
  80. return "";
  81. }
  82. return name.substr(0,q);
  83. }
  84. std::string getSuffix() const
  85. {
  86. std::size_t q=name.rfind('.');
  87. if( q==name.npos )
  88. {
  89. return name;
  90. }
  91. return name.substr(q+1);
  92. }
  93. };
  94. //
  95. ///\brief assigns individual channels to different parts based on their layer and view name
  96. /// input is an array, list, vector etc of MultiViewChannelName objects
  97. /// on entry, each MultiViewChannelName name/view must be set (view can be empty if not multiview)
  98. ///
  99. /// if singlepart set, then on exit part_number will be zero, and internal_name will have view name inserted
  100. /// otherwise, each channel will be assigned to a different part based on its layer name and view name
  101. ///
  102. /// @param begin pointer to first MultiViewChannelName item
  103. /// @param end pointer to end of MultiViewChannelName item array
  104. /// @return total number of parts required
  105. //
  106. template<typename T> int
  107. SplitChannels(const T & begin,const T & end,bool multipart=true,const std::string & heroView="")
  108. {
  109. if(!multipart)
  110. {
  111. for(T i=begin;i!=end;i++)
  112. {
  113. i->part_number=0;
  114. //does this have a view name set?
  115. if(i->view=="")
  116. {
  117. i->internal_name=i->name;
  118. }else{
  119. std::string lname = i->getLayer();
  120. // no layer, only non-hero views get view name in layer name
  121. if(lname=="")
  122. {
  123. if(i->view==heroView)
  124. {
  125. i->internal_name = i->name;
  126. }else{
  127. i->internal_name = i->view+"."+i->name;
  128. }
  129. }else{
  130. i->internal_name = lname+"."+i->view+"."+i->getSuffix();
  131. }
  132. }
  133. }
  134. // single part created
  135. return 1;
  136. }else{
  137. // step 1: extract individual layers and parts
  138. // for each layer, enumerate which views are active
  139. std::map< std::string , std::set< std::string > > viewsInLayers;
  140. for(T i=begin;i!=end;i++)
  141. {
  142. viewsInLayers[i->getLayer()].insert(i->view);
  143. }
  144. // step 2: assign a part number to each layer/view
  145. std::map< std::pair<std::string,std::string> , int > layerToPart;
  146. int partCount=0;
  147. for(std::map< std::string , std::set< std::string > >::const_iterator layer=viewsInLayers.begin();
  148. layer!=viewsInLayers.end();layer++)
  149. {
  150. // if this layer has a heroView, insert that first
  151. bool layer_has_hero = layer->second.find(heroView)!=layer->second.end();
  152. if( layer_has_hero )
  153. {
  154. layerToPart[ std::make_pair(layer->first,heroView) ] = partCount++;
  155. }
  156. // insert other layers which aren't the hero view
  157. for(std::set< std::string >::const_iterator view=layer->second.begin();
  158. view!=layer->second.end();view++)
  159. {
  160. if(*view!=heroView)
  161. {
  162. layerToPart[ std::make_pair(layer->first,*view) ] = partCount++;
  163. }
  164. }
  165. }
  166. // step 3: update part number of each provided channel
  167. for( T i=begin;i!=end;i++)
  168. {
  169. i->internal_name=i->name;
  170. i->part_number = layerToPart[ std::make_pair(i->getLayer(),i->view) ];
  171. }
  172. // return number of parts created
  173. return partCount;
  174. }
  175. }
  176. //
  177. // populate the chans vector<MultiViewChannelName> with a list of channels in the file
  178. // and their corresponding part number
  179. //
  180. template<class T> void
  181. GetChannelsInMultiPartFile(const MultiPartInputFile & file,T & chans)
  182. {
  183. bool has_multiview=false;
  184. StringVector mview;
  185. if(file.parts()==1)
  186. {
  187. if(hasMultiView(file.header(0)))
  188. {
  189. mview=multiView(file.header(0));
  190. has_multiview=true;
  191. }
  192. }
  193. for(int p=0;p<file.parts();p++)
  194. {
  195. const ChannelList & c=file.header(p).channels();
  196. std::string view="";
  197. if(file.header(p).hasView())
  198. {
  199. view=file.header(p).view();
  200. }
  201. for(ChannelList::ConstIterator i=c.begin();i!=c.end();i++)
  202. {
  203. MultiViewChannelName m;
  204. m.name=std::string(i.name());
  205. m.internal_name=m.name;
  206. if(has_multiview)
  207. {
  208. m.view=viewFromChannelName(m.name,mview);
  209. m.name=removeViewName(m.internal_name,m.view);
  210. }else{
  211. m.view=view;
  212. }
  213. m.part_number=p;
  214. chans.push_back(m);
  215. }
  216. }
  217. }
  218. OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
  219. #endif