/src/nuke/OCIOLogConvert/OCIOLogConvert.cpp

http://github.com/imageworks/OpenColorIO · C++ · 179 lines · 133 code · 32 blank · 14 comment · 14 complexity · a469d4327bf9d02d5d4d69ccd3789e77 MD5 · raw file

  1. /**
  2. * OpenColorIO LogConvert Iop.
  3. */
  4. #include "OCIOLogConvert.h"
  5. namespace OCIO = OCIO_NAMESPACE;
  6. #include <string>
  7. #include <sstream>
  8. #include <stdexcept>
  9. #include <DDImage/Channel.h>
  10. #include <DDImage/PixelIop.h>
  11. #include <DDImage/NukeWrapper.h>
  12. #include <DDImage/Row.h>
  13. #include <DDImage/Knobs.h>
  14. const char* OCIOLogConvert::modes[] = {
  15. "log to lin", "lin to log", 0
  16. };
  17. OCIOLogConvert::OCIOLogConvert(Node *n) : DD::Image::PixelIop(n)
  18. {
  19. modeindex = 0;
  20. }
  21. OCIOLogConvert::~OCIOLogConvert()
  22. {
  23. }
  24. void OCIOLogConvert::knobs(DD::Image::Knob_Callback f)
  25. {
  26. Enumeration_knob(f, &modeindex, modes, "operation", "operation");
  27. DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
  28. }
  29. void OCIOLogConvert::_validate(bool for_real)
  30. {
  31. try
  32. {
  33. OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
  34. const char * src = 0;
  35. const char * dst = 0;
  36. if(modeindex == 0)
  37. {
  38. src = OCIO::ROLE_COMPOSITING_LOG;
  39. dst = OCIO::ROLE_SCENE_LINEAR;
  40. }
  41. else
  42. {
  43. src = OCIO::ROLE_SCENE_LINEAR;
  44. dst = OCIO::ROLE_COMPOSITING_LOG;
  45. }
  46. processor = config->getProcessor(src, dst);
  47. }
  48. catch(OCIO::Exception &e)
  49. {
  50. error(e.what());
  51. return;
  52. }
  53. if(processor->isNoOp())
  54. {
  55. set_out_channels(DD::Image::Mask_None); // prevents engine() from being called
  56. } else {
  57. set_out_channels(DD::Image::Mask_All);
  58. }
  59. DD::Image::PixelIop::_validate(for_real);
  60. }
  61. // Note that this is copied by others (OCIODisplay)
  62. void OCIOLogConvert::in_channels(int /* n unused */, DD::Image::ChannelSet& mask) const
  63. {
  64. DD::Image::ChannelSet done;
  65. foreach(c, mask)
  66. {
  67. if (DD::Image::colourIndex(c) < 3 && !(done & c))
  68. {
  69. done.addBrothers(c, 3);
  70. }
  71. }
  72. mask += done;
  73. }
  74. // See Saturation::pixel_engine for a well-commented example.
  75. // Note that this is copied by others (OCIODisplay)
  76. void OCIOLogConvert::pixel_engine(
  77. const DD::Image::Row& in,
  78. int /* rowY unused */, int rowX, int rowXBound,
  79. DD::Image::ChannelMask outputChannels,
  80. DD::Image::Row& out)
  81. {
  82. int rowWidth = rowXBound - rowX;
  83. DD::Image::ChannelSet done;
  84. foreach (requestedChannel, outputChannels)
  85. {
  86. // Skip channels which had their trios processed already,
  87. if (done & requestedChannel)
  88. {
  89. continue;
  90. }
  91. // Pass through channels which are not selected for processing
  92. // and non-rgb channels.
  93. if (colourIndex(requestedChannel) >= 3)
  94. {
  95. out.copy(in, requestedChannel, rowX, rowXBound);
  96. continue;
  97. }
  98. DD::Image::Channel rChannel = DD::Image::brother(requestedChannel, 0);
  99. DD::Image::Channel gChannel = DD::Image::brother(requestedChannel, 1);
  100. DD::Image::Channel bChannel = DD::Image::brother(requestedChannel, 2);
  101. done += rChannel;
  102. done += gChannel;
  103. done += bChannel;
  104. const float *rIn = in[rChannel] + rowX;
  105. const float *gIn = in[gChannel] + rowX;
  106. const float *bIn = in[bChannel] + rowX;
  107. float *rOut = out.writable(rChannel) + rowX;
  108. float *gOut = out.writable(gChannel) + rowX;
  109. float *bOut = out.writable(bChannel) + rowX;
  110. // OCIO modifies in-place
  111. // Note: xOut can equal xIn in some circumstances, such as when the
  112. // 'Black' (throwaway) scanline is uses. We thus must guard memcpy,
  113. // which does not allow for overlapping regions.
  114. if (rOut != rIn) memcpy(rOut, rIn, sizeof(float)*rowWidth);
  115. if (gOut != gIn) memcpy(gOut, gIn, sizeof(float)*rowWidth);
  116. if (bOut != bIn) memcpy(bOut, bIn, sizeof(float)*rowWidth);
  117. try
  118. {
  119. OCIO::PlanarImageDesc img(rOut, gOut, bOut, NULL, rowWidth, /*height*/ 1);
  120. processor->apply(img);
  121. }
  122. catch(OCIO::Exception &e)
  123. {
  124. error(e.what());
  125. }
  126. }
  127. }
  128. const DD::Image::Op::Description OCIOLogConvert::description("OCIOLogConvert", build);
  129. const char* OCIOLogConvert::Class() const
  130. {
  131. return description.name;
  132. }
  133. const char* OCIOLogConvert::displayName() const
  134. {
  135. return description.name;
  136. }
  137. const char* OCIOLogConvert::node_help() const
  138. {
  139. // TODO more detailed help text
  140. return "Use OpenColorIO to convert from SCENE_LINEAR to COMPOSITING_LOG (or back).";
  141. }
  142. DD::Image::Op* build(Node *node)
  143. {
  144. DD::Image::NukeWrapper *op = new DD::Image::NukeWrapper(new OCIOLogConvert(node));
  145. op->channels(DD::Image::Mask_RGB);
  146. return op;
  147. }