Nuke里的包围曝光合成节点---BracketStacker (&source!)

来源:互联网 发布:java分布式开源发框架 编辑:程序博客网 时间:2024/05/22 17:44

放假归来,下午下了个把包围曝光拍摄的多张照片合成出一张层次比较明显的一张图片的一个Nuke Op(本来想写的是Focus Bracketing的但发现效果不是很好),用的最简单的方法既亮度越接近0.5其权值越大,和专业的混合软件比差距还是比较大的……哭



输入

来自wiki,虽然是缩略图但也可以看到,因为光比太大,左边的图能看清亮出细节但看天空漆黑,与之相反的最右边的图能看清天空时整个建筑都爆掉了。



界面

右边的两个transform是为了对齐。


输出

如图,同一张图片能看清楚云彩和建筑最明亮的地方的细节。效果一般,但就这么滴了。


把源码发上来吧~ 

// by cuckon#pragma warning(disable:4312)#include "DDImage/Iop.h"#include "DDImage/Row.h"#include "DDImage/Tile.h"#include "DDImage/Knobs.h"#include <vector>using namespace DD::Image;using namespace std;#define For(i,from,to) for (int i = from;i<to;i++)#define ForI(to) For(i,0,to)static const char* const CLASS = "BracketStacker";static const char* const HELP = "Use to composite brackted images. ";typedef vector<Row*> RowList;const char *const kOperationLabel[] = {"HDRI","Defocus",NULL};enum Operation {kHDRI = 0,kDefocus};float RGB2Lum(float r,float g, float b) {return 0.2125f * r + 0.7154f * g + 0.0721f * b;}float weightCurve(float dark,float light,float input){input = MIN(1.0f,MAX(input,0.0f));return pow(input,light)  *  pow((1-input),dark);}class BracketStacker : public Iop{// These are the locations the user interface will store into:intoperation;doubledark_weight, light_weight,pre_gamma;public:BracketStacker(Node*);void _validate(bool);void _request(int, int, int, int, ChannelMask, int);void engine(int y, int x, int r, ChannelMask, Row &);virtual void knobs(Knob_Callback);const char* Class() const { return CLASS; }const char* node_help() const { return HELP; }static const Description d;int minimum_inputs()const{return 2;}int maximum_inputs()const{return 99999;}};BracketStacker::BracketStacker(Node* node) : Iop(node){operation = 0;dark_weight = 1;light_weight = 1;pre_gamma = 1;}void BracketStacker::knobs(Knob_Callback f){Float_knob(f,&dark_weight,IRange(0,100),"dark","dark");Float_knob(f,&light_weight,IRange(0,100),"light","light");Float_knob(f,&pre_gamma,IRange(0,100),"pre_gamma","pre_gamma");}static Iop* Blocky_c(Node* node) { return new BracketStacker(node); }const Iop::Description BracketStacker::d(CLASS, "Cuckon/BracketStacker", Blocky_c);void BracketStacker::_validate(bool for_real){// Get the size and other information from the input image:copy_info();Iop::validate(for_real);}void BracketStacker::_request(int x, int y, int r, int t, ChannelMask channels, int count){for(int i = 0;i<inputs();i++){input(i)->request(x, y, r, t, channels, count);}}void BracketStacker::engine(int y, int l, int r, ChannelMask channels, Row& out){if (!channels.contains(Mask_RGB))return;float*weight = new float[inputs()],*lum = new float[inputs()],current_lum_sum;Row::WritablePtrptr_r = out.writable(Chan_Red),ptr_g = out.writable(Chan_Green),ptr_b = out.writable(Chan_Blue);// prepare all rows for calc RowListinput_rows; ForI(inputs()) { input_rows.push_back(new Row(l,r)); input_rows.back()->get(*input(i),y,l,r,channels); }// adjust each pixelfor (int x = l;x<r;x++){current_lum_sum = 0;ForI(inputs()) { lum[i] = RGB2Lum((*input_rows[i])[Chan_Red][x], (*input_rows[i])[Chan_Green][x], (*input_rows[i])[Chan_Blue][x]);lum[i] = weightCurve((float)dark_weight,(float)light_weight,pow(lum[i],(float)pre_gamma));current_lum_sum += lum[i];}ForI(inputs())weight[i] = lum[i]/current_lum_sum;ptr_r[x] = ptr_g[x] = ptr_b[x] = 0;ForI(inputs()){ptr_r[x]+= weight[i]*(*input_rows[i])[Chan_Red][x];ptr_g[x]+= weight[i]*(*input_rows[i])[Chan_Green][x];ptr_b[x]+= weight[i]*(*input_rows[i])[Chan_Blue][x];}}}


原创粉丝点击