1 /* 2 */ 3 4 /* 5 6 Copyright (C) 2014 Ferrero Andrea 7 8 This program is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20 21 22 */ 23 24 /* 25 26 These files are distributed with PhotoFlow - http://aferrero2707.github.io/PhotoFlow/ 27 28 */ 29 30 #ifndef PF_WHITE_BALANCE_H 31 #define PF_WHITE_BALANCE_H 32 33 #include <string> 34 35 #include "../base/processor.hh" 36 #include "../base/rawmatrix.hh" 37 38 #include "raw_image.hh" 39 40 41 //#define RT_EMU 1 42 43 44 //#define __CLIP(a) CLIP(a) 45 #define __CLIP(a) (a) 46 47 namespace PF 48 { 49 50 extern int wb_sample_x; 51 extern int wb_sample_y; 52 53 class WhiteBalancePar: public OpParBase 54 { 55 dcraw_data_t* image_data; 56 57 PropertyBase wb_mode; 58 59 Property<float>* wb_red[WB_LAST]; 60 Property<float>* wb_green[WB_LAST]; 61 Property<float>* wb_blue[WB_LAST]; 62 63 Property<float> camwb_corr_red; 64 Property<float> camwb_corr_green; 65 Property<float> camwb_corr_blue; 66 67 Property<float> wb_target_L; 68 Property<float> wb_target_a; 69 Property<float> wb_target_b; 70 71 Property<float> saturation_level_correction; 72 Property<float> black_level_correction; 73 74 float wb_red_current, wb_green_current, wb_blue_current; 75 76 public: 77 WhiteBalancePar(); 78 79 /* Set processing hints: 80 1. the intensity parameter makes no sense for an image, 81 creation of an intensity map is not allowed 82 2. the operation can work without an input image; 83 the blending will be set in this case to "passthrough" and the image 84 data will be simply linked to the output 85 */ has_intensity()86 bool has_intensity() { return false; } has_opacity()87 bool has_opacity() { return true; } needs_input()88 bool needs_input() { return true; } 89 get_image_data()90 dcraw_data_t* get_image_data() {return image_data; } 91 92 void init_wb_coefficients( dcraw_data_t* idata, std::string camera_maker, std::string camera_model ); 93 get_wb_mode()94 wb_mode_t get_wb_mode() { return (wb_mode_t)(wb_mode.get_enum_value().first); } get_wb_red()95 float get_wb_red() { return wb_red_current; /*wb_red.get();*/ } get_wb_green()96 float get_wb_green() { return wb_green_current; /*wb_green.get();*/ } get_wb_blue()97 float get_wb_blue() { return wb_blue_current; /*wb_blue.get();*/ } 98 get_preset_wb_red(int id)99 float get_preset_wb_red(int id) { return wb_red[id]->get(); } get_preset_wb_green(int id)100 float get_preset_wb_green(int id ) { return wb_green[id]->get(); } get_preset_wb_blue(int id)101 float get_preset_wb_blue(int id) { return wb_blue[id]->get(); } 102 get_camwb_corr_red()103 float get_camwb_corr_red() { return camwb_corr_red.get(); } get_camwb_corr_green()104 float get_camwb_corr_green() { return camwb_corr_green.get(); } get_camwb_corr_blue()105 float get_camwb_corr_blue() { return camwb_corr_blue.get(); } 106 get_wb(float * mul)107 void get_wb(float* mul) { 108 mul[0] = get_wb_red(); 109 mul[1] = get_wb_green(); 110 mul[2] = get_wb_blue(); 111 } set_wb(float r,float g,float b)112 void set_wb(float r, float g, float b) { 113 wb_red_current = r; 114 wb_green_current = g; 115 wb_blue_current = b; 116 std::cout<<"WhiteBalancePar: setting WB coefficients to "<<r<<","<<g<<","<<b<<std::endl; 117 } 118 get_saturation_level_correction()119 float get_saturation_level_correction() { return saturation_level_correction.get(); } get_black_level_correction()120 float get_black_level_correction() { return black_level_correction.get(); } 121 122 VipsImage* build(std::vector<VipsImage*>& in, int first, 123 VipsImage* imap, VipsImage* omap, unsigned int& level); 124 }; 125 126 127 128 template < OP_TEMPLATE_DEF > 129 class WhiteBalance 130 { 131 public: render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)132 void render(VipsRegion** ireg, int n, int in_first, 133 VipsRegion* imap, VipsRegion* omap, 134 VipsRegion* oreg, OpParBase* par) 135 { 136 WhiteBalancePar* rdpar = dynamic_cast<WhiteBalancePar*>(par); 137 if( !rdpar ) return; 138 139 float mul[4] = {1,1,1,1}; 140 141 //std::cout<<"WhiteBalance::render(): rdpar->get_wb_mode()="<<rdpar->get_wb_mode()<<std::endl; 142 //switch( rdpar->get_wb_mode() ) { 143 //case WB_SPOT: 144 //case WB_COLOR_SPOT: 145 //render_spotwb(ireg, n, in_first, imap, omap, oreg, rdpar); 146 //std::cout<<"render_spotwb() called"<<std::endl; 147 mul[0] = rdpar->get_wb_red(); 148 mul[1] = rdpar->get_wb_green(); 149 mul[2] = rdpar->get_wb_blue(); 150 mul[3] = rdpar->get_wb_green(); 151 //break; 152 //default: 153 //render_camwb(ireg, n, in_first, imap, omap, oreg, rdpar); 154 //std::cout<<"render_camwb() called"<<std::endl; 155 //mul[0] = rdpar->get_wb_red()*rdpar->get_camwb_corr_red(); 156 //mul[1] = rdpar->get_wb_green()*rdpar->get_camwb_corr_green(); 157 //mul[2] = rdpar->get_wb_blue()*rdpar->get_camwb_corr_blue(); 158 //mul[3] = rdpar->get_wb_green()*rdpar->get_camwb_corr_green(); 159 //break; 160 //} 161 162 dcraw_data_t* image_data = rdpar->get_image_data(); 163 VipsRect *r = &oreg->valid; 164 int nbands = ireg[in_first]->im->Bands; 165 166 int x, y; 167 //float range = image_data->color.maximum - image_data->color.black; 168 float range = 1; 169 float min_mul = mul[0]; 170 float max_mul = mul[0]; 171 /* 172 for(int i = 0; i < 4; i++) { 173 std::cout<<"cam_mu["<<i<<"]="<<image_data->color.cam_mul[i]<<" "; 174 } 175 std::cout<<std::endl; 176 */ 177 for(int i = 1; i < 4; i++) { 178 if( mul[i] < min_mul ) 179 min_mul = mul[i]; 180 if( mul[i] > max_mul ) 181 max_mul = mul[i]; 182 } 183 //std::cout<<"range="<<range<<" min_mul="<<min_mul<<" new range="<<range*min_mul<<std::endl; 184 range *= min_mul; 185 186 //for(int i = 0; i < 4; i++) { 187 // mul[i] = mul[i] / range; 188 //} 189 190 float* p; 191 float* pout; 192 int line_sz = r->width*3; 193 for( y = 0; y < r->height; y++ ) { 194 p = (float*)VIPS_REGION_ADDR( ireg[in_first], r->left, r->top + y ); 195 pout = (float*)VIPS_REGION_ADDR( oreg, r->left, r->top + y ); 196 for( x=0; x < line_sz; x+=3) { 197 //pout[x] = __CLIP( (p[x]-black[0]) * sat_corr * mul[0] - black[0]); 198 //pout[x+1] = __CLIP(p[x+1] * sat_corr * mul[1] - black[1]); 199 //pout[x+2] = __CLIP(p[x+2] * sat_corr * mul[2] - black[2]); 200 pout[x] = __CLIP( p[x] * mul[0] ); 201 pout[x+1] = __CLIP( p[x+1] * mul[1] ); 202 pout[x+2] = __CLIP( p[x+2] * mul[2] ); 203 if(false && r->left==0 && r->top==0) std::cout<<" p["<<x<<"]="<<p[x]<<" pout["<<x<<"]="<<pout[x]<<std::endl; 204 } 205 } 206 } 207 }; 208 209 210 211 212 ProcessorBase* new_white_balance(); 213 } 214 215 #endif 216 217 218