OSDN Git Service

size setting bug fix
[hdrholic/HDRHolic.git] / HDRHolic.pde
1 import controlP5.*;
2
3 ControlP5 cp5;
4 ControlWindow controlWindow;
5 ControlWindow viewWindow;
6 Textlabel readmeText;
7
8 PImage img0;
9 PImage img1;
10 PImage img2;
11 PImage writeImg;
12
13 float scope_ratio = 5; // 1 to 100%
14
15 final int low_scope_speed_ratio = 20;
16 final float low_average_speed_ratio = 0.1;
17
18 final int high_scope_speed_ratio = 5;
19 final float high_average_speed_ratio = 0.1;
20
21 int scope_speed_ratio = low_scope_speed_ratio; // 1 to scope
22 float average_speed_ratio = low_average_speed_ratio; // 0 to picture width
23
24 final int max_lum_class = 30; // 1 to 256
25 int class_th = 20; // class threshold
26 float a_value = 0.27;
27 float gamma_u = 0.5;
28 float gamma_n = 1;
29 float gamma_o = 0.5;
30 float color_gain = 1;
31 final float delta = 0.01;
32 float[] lut_u = new float[256];
33 float[] lut_n = new float[256];
34 float[] lut_o = new float[256];
35
36 // hdr image
37 int[] hdr_img_r;
38 int[] hdr_img_g;
39 int[] hdr_img_b;
40
41 //Window Size
42 int size_x = 1024;
43 int size_y = 768;
44 int view_width, view_height;
45
46 void setup(){
47   size(size_x, size_y);
48
49   cp5 = new ControlP5(this);
50
51   controlWindow = cp5.addControlWindow("Tunewindow", 100, 100, 360, 600)
52     .hideCoordinates()
53     .setBackground(color(40))
54     ;
55
56   cp5.addTextlabel("guide")
57       .setText("Guide:")
58       .setPosition(40,40)
59       .setColorValue(0xffffffff)
60       .setFont(createFont("Georgia",20))
61       .moveTo(controlWindow)
62       ;
63
64   readmeText = cp5.addTextlabel("label")
65                .setText("Select an under exposed photo.")
66                .setPosition(40,80)
67                .setColorValue(0xffffffff)
68                .setFont(createFont("Georgia",18))
69                .moveTo(controlWindow)
70                 ;
71
72   cp5.addSlider("gamma_u")
73      .setRange(0, 2)
74      .setPosition(40, 140)
75      .setSize(200, 29)
76      .moveTo(controlWindow)
77      ;
78
79   cp5.addSlider("gamma_n")
80      .setRange(0, 2)
81      .setPosition(40, 180)
82      .setSize(200, 29)
83      .moveTo(controlWindow)
84      ;
85
86   cp5.addSlider("gamma_o")
87      .setRange(0, 2)
88      .setPosition(40, 220)
89      .setSize(200, 29)
90      .moveTo(controlWindow)
91      ;
92
93   cp5.addSlider("a_value")
94      .setRange(0, 0.5)
95      .setPosition(40, 300)
96      .setSize(200, 29)
97      .moveTo(controlWindow)
98      ;
99
100   cp5.addSlider("color_gain")
101      .setRange(0, 5)
102      .setPosition(40, 340)
103      .setSize(200, 29)
104      .moveTo(controlWindow)
105      ;
106
107   cp5.addSlider("scope_ratio")
108      .setRange(0, 20)
109      .setPosition(40, 380)
110      .setSize(200, 29)
111      .moveTo(controlWindow)
112      ;
113
114   cp5.addSlider("class_th")
115      .setRange(0, 40)
116      .setPosition(40, 420)
117      .setSize(200, 29)
118      .moveTo(controlWindow)
119      ;
120
121   cp5.addButton("Save Image")
122      .setPosition(40,500)
123      .setSize(100,39)
124      .moveTo(controlWindow)
125      ;
126
127   cp5.addButton("Exit")
128      .setPosition(160,500)
129      .setSize(100,39)
130      .moveTo(controlWindow)
131      ;
132
133   String imgPath = selectInput();
134   img0 = loadImage(imgPath);
135   readmeText.setText("Select a normal exposed photo.");
136
137   imgPath = selectInput();
138   img1 = loadImage(imgPath);
139
140   readmeText.setText("Select an over exposed photo.");
141
142   imgPath = selectInput();
143   img2 = loadImage(imgPath);
144
145   writeImg = createImage(img0.width, img0.height, RGB);
146
147 // long nt = System.nanoTime();
148
149   MakeHDR();
150   ToneMapping();
151
152 // long nt2 = System.nanoTime();
153
154 //  long a = nt2 -nt;
155 //  println("time=" +a );
156
157   readmeText.setText("Completed.");
158
159   if(img0.width > size_x || img0.height > size_y){
160     float k_width = (float)img0.width / (float)size_x;
161     float k_height = (float)img0.height / (float)size_y;
162     float k_max;
163     if(k_width > k_height){
164       k_max = k_width;
165     }else{
166       k_max = k_height;
167     }
168     view_width = (int)(img0.width/k_max);
169     view_height = (int)(img0.height/k_max);
170   }else{
171     view_width = img0.width;
172     view_height = img0.height;
173   }
174 }
175
176 public void controlEvent(ControlEvent theEvent) {
177   if(theEvent.isFrom("color_gain")) {
178     MakeHDR();
179   }
180
181   if(theEvent.isFrom("gamma_u")) {
182     MakeHDR();
183   }
184
185   if(theEvent.isFrom("gamma_n")) {
186     MakeHDR();
187   }
188
189   if(theEvent.isFrom("gamma_o")) {
190     MakeHDR();
191   }
192
193   if(theEvent.isFrom("Save Image")) {
194     String imgPath = selectOutput();
195     writeImg.save(imgPath);
196   }
197
198   if(theEvent.isFrom("Exit")) {
199     exit();
200   }
201 }
202
203
204 void draw(){
205   //  MakeHDR();
206   ToneMapping();
207   image(writeImg, 0, 0, view_width, view_height);
208 }
209
210 void MakeGamma(){
211   for (int i = 0; i < 256; i++){
212     lut_u[i] = 255*pow(((float)i/255),(1/gamma_u));
213   }
214
215   for (int i = 0; i < 256; i++){
216     lut_n[i] = 255*pow(((float)i/255),(1/gamma_n));
217   }
218
219   for (int i = 0; i < 256; i++){
220     lut_o[i] = 255*pow(((float)i/255),(1/gamma_o));
221   }  
222 }
223
224 void MakeHDR(){
225   MakeGamma();
226
227   hdr_img_r = new int[img0.height*img0.width];
228   hdr_img_g = new int[img0.height*img0.width];
229   hdr_img_b = new int[img0.height*img0.width];
230
231   img0.loadPixels();
232   img1.loadPixels();
233   img2.loadPixels();
234
235   for(int i = 0; i < img0.width*img0.height; i++){
236     color tmp_color0 = img0.pixels[i];
237     color tmp_color1 = img1.pixels[i];
238     color tmp_color2 = img2.pixels[i];
239
240     hdr_img_r[i] =
241       (int)((lut_u[(int)red(tmp_color0)] + lut_n[(int)red(tmp_color1)] + lut_o[(int)red(tmp_color2)])*color_gain/3);
242     hdr_img_g[i] =
243       (int)((lut_u[(int)green(tmp_color0)] + lut_n[(int)green(tmp_color1)] + lut_o[(int)green(tmp_color2)])*color_gain/3);
244     hdr_img_b[i] =
245       (int)((lut_u[(int)blue(tmp_color0)] + lut_n[(int)blue(tmp_color1)] + lut_o[(int)blue(tmp_color2)])*color_gain/3);
246
247 //    hdr_img_r[i] = hdr_img_r[i]/3*color_gain;
248 //    hdr_img_g[i] = hdr_img_g[i]/3*color_gain;
249 //    hdr_img_b[i] = hdr_img_b[i]/3*color_gain;
250   }
251
252   //debug-----
253   /*
254   for(int y = 0; y < img0.height; y++){
255     for(int x = 0; x < img0.width; x++){
256       int pos = x + y*img0.width;
257       color tmp_color = color(hdr_img_r[pos], hdr_img_g[pos], hdr_img_b[pos]);
258       set(x, y, tmp_color);
259     }
260   }
261   */
262   //----debug  
263 }
264
265 void ToneMapping(){
266  long nt = millis();
267
268   float lum_sum;
269   int sum_numb;
270
271   int scope = (int)(sqrt(img0.height*img0.width) * scope_ratio/100);
272   int scope_speed = (int)(scope * scope_speed_ratio/100)+1;
273   int average_speed = (int)(sqrt(img0.height*img0.width) * average_speed_ratio/100);
274
275   // debug
276 //  println("scope= " + scope);
277 //  println("scope_speed= " + scope_speed);
278 //  println("average_speede= " + average_speed);
279
280   //ToneMapping----
281   int tmp = average_speed;
282   float lum_sum_w = 0;
283
284   int[] lum = new int[img0.height*img0.width];
285   float[] lum_local = new float[img0.height*img0.width];
286 //  int[] lum_local = new int[img0.height*img0.width];
287   int[] lum_class = new int[img0.height*img0.width];
288   int[] u = new int[img0.height*img0.width];
289   int[] v = new int[img0.height*img0.width];
290
291   for(int y = 0; y < img0.height; y++){
292     for(int x = 0; x < img0.width; x++){
293       int pos = x + y*img0.width;
294       lum[pos] = (307*hdr_img_r[pos] + 604*hdr_img_g[pos] + 113*hdr_img_b[pos])  >> 10;
295       lum_local[pos] = log((float)(lum[pos]) / 256 + delta);
296 //      lum_local[pos] = (int)(log((float)(lum[pos]) / 256 + delta));
297
298       u[pos] = (-174*hdr_img_r[pos] - 338*hdr_img_g[pos] + 512*hdr_img_b[pos]) >> 10;
299       v[pos] = (512*hdr_img_r[pos] -430*hdr_img_g[pos] - 82*hdr_img_b[pos]) >> 10;
300     }
301   }
302   
303   int max_lum = (int)max(lum);
304   for(int y = 0; y < img0.height; y++){
305     for(int x = 0; x < img0.width; x++){
306       int pos = x + y*img0.width;
307       lum_class[pos] = (int)(float(lum[pos])/((max_lum+1)/max_lum_class));
308     }
309   }
310
311   for(int y = 0; y < img0.height; y++){
312     tmp = average_speed;
313     for(int x = 0; x < img0.width; x++){
314       int pos = x + y*img0.width;
315       lum_sum = 0;
316       sum_numb = 0;
317       tmp++;
318       if(tmp > average_speed){
319         tmp = 0;
320         for(int y_2 = y-scope; y_2 < y+scope; y_2 += scope_speed){
321           for(int x_2 = x-scope; x_2 < x+scope; x_2 += scope_speed){
322             if(y_2 >= 0 && y_2 < img0.height && x_2 >=0 && x_2 < img0.width){
323                 int pos_2 = x_2 + y_2*img0.width;
324                 if(abs(lum_class[pos] - lum_class[pos_2]) < class_th){
325                   sum_numb++;
326                   lum_sum += lum_local[pos_2];
327               }
328             }
329           }
330         }
331         lum_sum_w = exp(lum_sum/(float)sum_numb);
332       }
333
334       float lum_w = lum[pos]/lum_sum_w*a_value;
335
336       int r = (int)(1024*lum_w + 1433*v[pos]) >> 10;
337       int g = (int)(1024*lum_w -348*u[pos] -727*v[pos]) >> 10;
338       int b = (int)(1024*lum_w + 1812*u[pos]) >> 10;
339       
340       writeImg.pixels[pos] = color(r,g,b);
341     }
342   }
343   writeImg.updatePixels();
344
345   long nt2 = millis();
346
347   long a = nt2 -nt;
348   println("time=" +a );
349
350
351 }
352