/src/FreeImage/Source/OpenEXR/IlmImf/ImfMultiView.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 396 lines · 181 code · 83 blank · 132 comment · 66 complexity · 246ec40a0df85c9f1fc2a51e443ed4cd MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2007, 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. // Functions related to accessing channels
  36. // and views in multi-view OpenEXR files.
  37. //
  38. //-----------------------------------------------------------------------------
  39. #include <ImfMultiView.h>
  40. using namespace std;
  41. namespace Imf {
  42. namespace {
  43. StringVector
  44. parseString (string name, char c = '.')
  45. {
  46. //
  47. // Turn name into a list of strings, separating
  48. // on char 'c' with whitespace stripped.
  49. //
  50. StringVector r;
  51. while (name.size() > 0)
  52. {
  53. size_t s = name.find (c);
  54. string sec = name.substr (0, s);
  55. //
  56. // Strip spaces from beginning
  57. //
  58. while (sec.size() > 0 && sec[0] == ' ')
  59. sec.erase (0, 1);
  60. //
  61. // Strip spaces from end
  62. //
  63. while (sec.size() > 0 && sec[sec.size() - 1] == ' ')
  64. sec.erase (sec.size() - 1);
  65. r.push_back (sec);
  66. //
  67. // Strip off name including ending 'c'
  68. //
  69. if (s == name.npos)
  70. name = "";
  71. else
  72. name = name.substr (s + 1);
  73. }
  74. return r;
  75. }
  76. int
  77. viewNum (const string &view, const StringVector &multiView)
  78. {
  79. //
  80. // returns which view number is called 'view'
  81. // returns -1 if no member of multiView is 'view'
  82. // (i.e. if viewNum() returns -1, 'view' isn't a view name
  83. // if viewNum() returns 0, 'view' is the default view
  84. // otherwise, it's some other (valid) view
  85. //
  86. for (int i = 0; i < multiView.size(); ++i)
  87. {
  88. if (multiView[i] == view)
  89. return i;
  90. }
  91. return -1;
  92. }
  93. } // namespace
  94. string
  95. defaultViewName (const StringVector &multiView)
  96. {
  97. if (multiView.size() > 0)
  98. return multiView[0];
  99. else
  100. return "";
  101. }
  102. string
  103. viewFromChannelName (const string &channel,
  104. const StringVector &multiView)
  105. {
  106. //
  107. // Given the name of a channel, return the name of the view to
  108. // which it belongs.
  109. //
  110. //
  111. // View name is penultimate section of name separated by periods ('.'s)
  112. //
  113. StringVector s = parseString (channel, '.');
  114. if (s.size() == 0)
  115. return ""; // nothing in, nothing out
  116. if (s.size() == 1)
  117. {
  118. //
  119. // Return default view name.
  120. // The rules say ALL channels with no periods
  121. // in the name belong to the default view.
  122. //
  123. return multiView[0];
  124. }
  125. else
  126. {
  127. //
  128. // size >= 2 - the last part is the channel name,
  129. // the next-to-last part is the view name.
  130. // Check if that part of the name really is
  131. // a valid view and, if it is, return it.
  132. //
  133. const string &viewName = s[s.size() - 2];
  134. if (viewNum (viewName, multiView) >= 0)
  135. return viewName;
  136. else
  137. return ""; // not associated with any particular view
  138. }
  139. }
  140. ChannelList
  141. channelsInView (const string & viewName,
  142. const ChannelList & channelList,
  143. const StringVector & multiView)
  144. {
  145. //
  146. // Return a list of all channels belonging to view viewName.
  147. //
  148. ChannelList q;
  149. for (ChannelList::ConstIterator i = channelList.begin();
  150. i != channelList.end();
  151. ++i)
  152. {
  153. //
  154. // Get view name for this channel
  155. //
  156. string view = viewFromChannelName (i.name(), multiView);
  157. //
  158. // Insert channel into q if it's a member of view viewName
  159. //
  160. if (view == viewName)
  161. q.insert (i.name(), i.channel());
  162. }
  163. return q;
  164. }
  165. ChannelList
  166. channelsInNoView (const ChannelList &channelList,
  167. const StringVector &multiView)
  168. {
  169. //
  170. // Return a list of channels not associated with any named view.
  171. //
  172. return channelsInView ("", channelList, multiView);
  173. }
  174. bool
  175. areCounterparts (const string &channel1,
  176. const string &channel2,
  177. const StringVector &multiView)
  178. {
  179. //
  180. // Given two channels, return true if they are the same
  181. // channel in two different views.
  182. //
  183. StringVector chan1 = parseString (channel1);
  184. unsigned int size1 = chan1.size(); // number of SECTIONS in string
  185. // name (not string length)
  186. StringVector chan2 = parseString (channel2);
  187. unsigned int size2 = chan2.size();
  188. if (size1 == 0 || size2 == 0)
  189. return false;
  190. //
  191. // channel1 and channel2 can't be counterparts
  192. // if either channel is in no view.
  193. //
  194. if (size1 > 1 && viewNum (chan1[size1 - 2], multiView) == -1)
  195. return false;
  196. if (size2 > 1 && viewNum (chan2[size2 - 2], multiView) == -1)
  197. return false;
  198. if (viewFromChannelName (channel1, multiView) ==
  199. viewFromChannelName (channel2, multiView))
  200. {
  201. //
  202. // channel1 and channel2 are not counterparts
  203. // if they are in the same view.
  204. //
  205. return false;
  206. }
  207. if (size1 == 1)
  208. {
  209. //
  210. // channel1 is a default channel - the channels will only be
  211. // counterparts if channel2 is of the form <view>.<channel1>
  212. //
  213. return size2 == 2 && chan1[0] == chan2[1];
  214. }
  215. if (size2 == 1)
  216. {
  217. //
  218. // channel2 is a default channel - the channels will only be
  219. // counterparts if channel1 is of the form <view>.<channel2>
  220. //
  221. return size1 == 2 && chan2[0] == chan1[1];
  222. }
  223. //
  224. // Neither channel is a default channel. To be counterparts both
  225. // channel names must have the same number of components, and
  226. // all components except the penultimate one must be the same.
  227. //
  228. if (size1 != size2)
  229. return false;
  230. for(int i = 0; i < size1; ++i)
  231. {
  232. if (i != size1 - 2 && chan1[i] != chan2[i])
  233. return false;
  234. }
  235. return true;
  236. }
  237. ChannelList
  238. channelInAllViews (const string &channelName,
  239. const ChannelList &channelList,
  240. const StringVector &multiView)
  241. {
  242. //
  243. // Given the name of a channel, return a
  244. // list of the same channel in all views.
  245. //
  246. ChannelList q;
  247. for (ChannelList::ConstIterator i=channelList.begin();
  248. i != channelList.end();
  249. ++i)
  250. {
  251. if (i.name() == channelName ||
  252. areCounterparts (i.name(), channelName, multiView))
  253. {
  254. q.insert (i.name(), i.channel());
  255. }
  256. }
  257. return q;
  258. }
  259. string
  260. channelInOtherView (const string &channelName,
  261. const ChannelList &channelList,
  262. const StringVector &multiView,
  263. const string &otherViewName)
  264. {
  265. //
  266. // Given the name of a channel in one view, return the
  267. // corresponding channel name for view otherViewName.
  268. //
  269. for (ChannelList::ConstIterator i=channelList.begin();
  270. i != channelList.end();
  271. ++i)
  272. {
  273. if (viewFromChannelName (i.name(), multiView) == otherViewName &&
  274. areCounterparts (i.name(), channelName, multiView))
  275. {
  276. return i.name();
  277. }
  278. }
  279. return "";
  280. }
  281. string
  282. insertViewName (const string &channel,
  283. const StringVector &multiView,
  284. int i)
  285. {
  286. //
  287. // Insert multiView[i] into the channel name if appropriate.
  288. //
  289. StringVector s = parseString (channel, '.');
  290. if (s.size() == 0)
  291. return ""; // nothing in, nothing out
  292. if (s.size() == 1 && i == 0)
  293. {
  294. //
  295. // Channel in the default view, with no periods in its name.
  296. // Do not insert view name.
  297. //
  298. return channel;
  299. }
  300. //
  301. // View name becomes penultimate section of new channel name.
  302. //
  303. string newName;
  304. for (int j = 0; j < s.size(); ++j)
  305. {
  306. if (j < s.size() - 1)
  307. newName += s[j] + ".";
  308. else
  309. newName += multiView[i] + "." + s[j];
  310. }
  311. return newName;
  312. }
  313. } // namespace Imf