|
| 1 | +#include "DDImage/DeepFilterOp.h" |
| 2 | +#include "DDImage/Knobs.h" |
| 3 | +#include "DDImage/ChannelSet.h" |
| 4 | +#include "DDImage/Channel.h" |
| 5 | + |
| 6 | +using namespace DD::Image; |
| 7 | + |
| 8 | +class DeepCShuffle : public DeepFilterOp |
| 9 | +{ |
| 10 | + Channel _inChannel0; |
| 11 | + Channel _inChannel1; |
| 12 | + Channel _inChannel2; |
| 13 | + Channel _inChannel3; |
| 14 | + |
| 15 | + Channel _outChannel0; |
| 16 | + Channel _outChannel1; |
| 17 | + Channel _outChannel2; |
| 18 | + Channel _outChannel3; |
| 19 | + |
| 20 | + ChannelSet _inChannelSet; |
| 21 | + ChannelSet _outChannelSet; |
| 22 | +public: |
| 23 | + |
| 24 | + DeepCShuffle(Node* node) : DeepFilterOp(node) |
| 25 | + { |
| 26 | + _inChannel0 = Chan_Red; |
| 27 | + _inChannel1 = Chan_Green; |
| 28 | + _inChannel2 = Chan_Blue; |
| 29 | + _inChannel3 = Chan_Alpha; |
| 30 | + |
| 31 | + _outChannel0 = Chan_Red; |
| 32 | + _outChannel1 = Chan_Green; |
| 33 | + _outChannel2 = Chan_Blue; |
| 34 | + _outChannel3 = Chan_Alpha; |
| 35 | + |
| 36 | + _inChannelSet = Chan_Black; |
| 37 | + _outChannelSet = Chan_Black; |
| 38 | + } |
| 39 | + |
| 40 | + |
| 41 | + void _validate(bool); |
| 42 | + virtual void getDeepRequests(DD::Image::Box bbox, const DD::Image::ChannelSet& requestedChannels, int count, std::vector<RequestData>& requests); |
| 43 | + bool doDeepEngine(DD::Image::Box bbox, const DD::Image::ChannelSet& requestedChannels, DeepOutputPlane& deepOutPlane); |
| 44 | + |
| 45 | + virtual void knobs(Knob_Callback); |
| 46 | + static const Iop::Description d; |
| 47 | + const char* Class() const { return d.name; } |
| 48 | + virtual Op* op() { return this; } |
| 49 | + const char* node_help() const; |
| 50 | +}; |
| 51 | + |
| 52 | +void DeepCShuffle::_validate(bool for_real) |
| 53 | +{ |
| 54 | + DeepFilterOp::_validate(for_real); |
| 55 | + |
| 56 | + _inChannelSet = Chan_Black; |
| 57 | + _inChannelSet += _inChannel0; |
| 58 | + _inChannelSet += _inChannel1; |
| 59 | + _inChannelSet += _inChannel2; |
| 60 | + _inChannelSet += _inChannel3; |
| 61 | + |
| 62 | + _outChannelSet = Chan_Black; |
| 63 | + _outChannelSet += _outChannel0; |
| 64 | + _outChannelSet += _outChannel1; |
| 65 | + _outChannelSet += _outChannel2; |
| 66 | + _outChannelSet += _outChannel3; |
| 67 | + |
| 68 | + ChannelSet newChannelSet; |
| 69 | + newChannelSet = _deepInfo.channels(); |
| 70 | + newChannelSet += _outChannelSet; |
| 71 | + _deepInfo = DeepInfo(_deepInfo.formats(), _deepInfo.box(), newChannelSet); |
| 72 | +} |
| 73 | + |
| 74 | +void DeepCShuffle::getDeepRequests(Box bbox, const DD::Image::ChannelSet& requestedChannels, int count, std::vector<RequestData>& requests) |
| 75 | +{ |
| 76 | + ChannelSet modifiedRequestedChannels; |
| 77 | + modifiedRequestedChannels = requestedChannels; |
| 78 | + modifiedRequestedChannels += _inChannelSet; |
| 79 | + requests.push_back(RequestData(input0(), bbox, modifiedRequestedChannels, count)); |
| 80 | +} |
| 81 | + |
| 82 | +bool DeepCShuffle::doDeepEngine(DD::Image::Box bbox, const DD::Image::ChannelSet& requestedChannels, DeepOutputPlane& deepOutPlane) |
| 83 | +{ |
| 84 | + if (!input0()) |
| 85 | + return true; |
| 86 | + |
| 87 | + DeepPlane deepInPlane; |
| 88 | + if (!input0()->deepEngine(bbox, requestedChannels, deepInPlane)) |
| 89 | + return false; |
| 90 | + |
| 91 | + DeepInPlaceOutputPlane inPlaceOutPlane(requestedChannels, bbox); |
| 92 | + inPlaceOutPlane.reserveSamples(deepInPlane.getTotalSampleCount()); |
| 93 | + const DD::Image::ChannelSet inputChannels = input0()->deepInfo().channels(); |
| 94 | + |
| 95 | + for (Box::iterator it = bbox.begin(); it != bbox.end(); ++it) |
| 96 | + { |
| 97 | + if (Op::aborted()) |
| 98 | + return false; // bail fast on user-interrupt |
| 99 | + |
| 100 | + // Get the deep pixel from the input plane: |
| 101 | + DeepPixel deepInPixel = deepInPlane.getPixel(it); |
| 102 | + size_t inPixelSamples = deepInPixel.getSampleCount(); |
| 103 | + ChannelSet inPixelChannels = deepInPixel.channels(); |
| 104 | + |
| 105 | + inPlaceOutPlane.setSampleCount(it, deepInPixel.getSampleCount()); |
| 106 | + DeepOutputPixel outPixel = inPlaceOutPlane.getPixel(it); |
| 107 | + |
| 108 | + Channel inChannel; |
| 109 | + // copy samples to DeepOutputPlane |
| 110 | + for (size_t sampleNo = 0; sampleNo < inPixelSamples; sampleNo++) |
| 111 | + { |
| 112 | + foreach (z, requestedChannels) |
| 113 | + { |
| 114 | + inChannel = z; |
| 115 | + if (z == _outChannel0) |
| 116 | + inChannel = _inChannel0; |
| 117 | + if (z == _outChannel1) |
| 118 | + inChannel = _inChannel1; |
| 119 | + if (z == _outChannel2) |
| 120 | + inChannel = _inChannel2; |
| 121 | + if (z == _outChannel3) |
| 122 | + inChannel = _inChannel3; |
| 123 | + const float& inData = inPixelChannels.contains(inChannel) && inChannel != Chan_Black |
| 124 | + ? deepInPixel.getUnorderedSample(sampleNo, inChannel) |
| 125 | + : 0.0f; |
| 126 | + float& outData = outPixel.getWritableUnorderedSample(sampleNo, z); |
| 127 | + outData = inData; |
| 128 | + } |
| 129 | + } |
| 130 | + } |
| 131 | + |
| 132 | + // inPlaceOutPlane.reviseSamples(); |
| 133 | + mFnAssert(inPlaceOutPlane.isComplete()); |
| 134 | + deepOutPlane = inPlaceOutPlane; |
| 135 | + return true; |
| 136 | +} |
| 137 | + |
| 138 | +void DeepCShuffle::knobs(Knob_Callback f) |
| 139 | +{ |
| 140 | + Input_Channel_knob(f, &_inChannel0, 1, 0, "in"); |
| 141 | + Text_knob(f, ">>"); ClearFlags(f, Knob::STARTLINE); |
| 142 | + Channel_knob(f, &_outChannel0, 1, "out"); ClearFlags(f, Knob::STARTLINE); |
| 143 | + Input_Channel_knob(f, &_inChannel1, 1, 0, "in"); |
| 144 | + Text_knob(f, ">>"); ClearFlags(f, Knob::STARTLINE); |
| 145 | + Channel_knob(f, &_outChannel1, 1, "out"); ClearFlags(f, Knob::STARTLINE); |
| 146 | + Input_Channel_knob(f, &_inChannel2, 1, 0, "in"); |
| 147 | + Text_knob(f, ">>"); ClearFlags(f, Knob::STARTLINE); |
| 148 | + Channel_knob(f, &_outChannel2, 1, "out"); ClearFlags(f, Knob::STARTLINE); |
| 149 | + Input_Channel_knob(f, &_inChannel3, 1, 0, "in"); |
| 150 | + Text_knob(f, ">>"); ClearFlags(f, Knob::STARTLINE); |
| 151 | + Channel_knob(f, &_outChannel3, 1, "out"); ClearFlags(f, Knob::STARTLINE); |
| 152 | +} |
| 153 | + |
| 154 | +const char* DeepCShuffle::node_help() const |
| 155 | +{ |
| 156 | + return |
| 157 | + "Shuffle in Deep. Turning off an output channel passes it through. " |
| 158 | + "Turning off an input channel sets the output channel to black."; |
| 159 | +} |
| 160 | + |
| 161 | + |
| 162 | +static Op* build(Node* node) { return new DeepCShuffle(node); } |
| 163 | +const Op::Description DeepCShuffle::d("DeepCShuffle", 0, build); |
0 commit comments