1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <xcam_std.h>
5 #include "xcam_log.h"
6 #include "rk_aiq_alsc_convert_otp.h"
7
8 // #define WRITE_OTP_TABLE 1
9
convertLscTableParameter(resolution_t * cur_res,alsc_otp_grad_t * otpGrad,RkAiqBayerPattern_t bayerPattern)10 void convertLscTableParameter(resolution_t *cur_res, alsc_otp_grad_t *otpGrad,
11 RkAiqBayerPattern_t bayerPattern)
12 {
13 XCAM_STATIC_PROFILING_START(convertLscTable);
14
15 int32_t bayer = bayerPattern;
16 int32_t srcLscWidth = otpGrad->width;
17 int32_t srcLscHeight = otpGrad->height;
18 int32_t dstWidth = cur_res->width;
19 int32_t dstHeight = cur_res->height;
20
21 LOGD_ALSC("input params: src %dx%d, dst %dx%d, bayer: %d\n",
22 srcLscWidth, srcLscHeight, dstWidth,
23 dstHeight, bayer);
24
25 if (dstWidth == srcLscWidth && dstHeight == srcLscHeight) {
26 return;
27 }
28
29 if (dstWidth > srcLscWidth && dstHeight > srcLscHeight)
30 {
31 if ((dstWidth / 2 <= srcLscWidth) && (dstHeight / 2 <= srcLscHeight))
32 {
33 dstWidth = dstWidth / 2;
34 dstHeight = dstHeight / 2;
35 } else {
36 LOGE_ALSC("Failed to handle: src %dx%d, dst %dx%x, return!\n",
37 srcLscWidth, srcLscHeight, dstWidth, dstHeight);
38 return;
39 }
40 } else if (dstWidth < srcLscWidth && dstHeight < srcLscHeight) {
41 if ((dstWidth <= srcLscWidth / 2) && (dstHeight <= srcLscHeight / 2))
42 {
43 srcLscWidth = srcLscWidth / 2;
44 srcLscHeight = srcLscHeight / 2;
45 }
46 }
47
48 uint32_t maxSize = srcLscWidth > srcLscHeight ? srcLscWidth : srcLscHeight;
49 uint32_t ratio = maxSize > 3200 ? 8 : (maxSize > 1600 ? 4 : (maxSize > 800 ? 2 : 1));
50 srcLscWidth = 2 * (int32_t)(srcLscWidth / (ratio * 2));
51 srcLscHeight = 2 * (int32_t)(srcLscHeight / (ratio * 2));
52 dstWidth = 2 * (int32_t)(dstWidth / (ratio * 2));
53 dstHeight = 2 * (int32_t)(dstHeight / (ratio * 2));
54
55 uint16_t *rTable = new uint16_t[srcLscWidth * srcLscHeight];
56 uint16_t *grTable = new uint16_t[srcLscWidth * srcLscHeight];
57 uint16_t *gbTable = new uint16_t[srcLscWidth * srcLscHeight];
58 uint16_t *bTable = new uint16_t[srcLscWidth * srcLscHeight];
59 uint16_t *corTable = new uint16_t[srcLscWidth * srcLscHeight];
60 uint16_t *corTable_crop = new uint16_t[dstWidth * dstHeight];
61
62 #if WRITE_OTP_TABLE
63 char fileName[32] = {0};
64 snprintf(fileName, sizeof(fileName) - 1, "/tmp/otp_lsc_r.bin");
65 writeFile(fileName, otpGrad->lsc_r);
66 snprintf(fileName, sizeof(fileName) - 1, "/tmp/otp_lsc_b.bin");
67 writeFile(fileName, otpGrad->lsc_b);
68 snprintf(fileName, sizeof(fileName) - 1, "/tmp/otp_lsc_gr.bin");
69 writeFile(fileName, otpGrad->lsc_gr);
70 snprintf(fileName, sizeof(fileName) - 1, "/tmp/otp_lsc_gb.bin");
71 writeFile(fileName, otpGrad->lsc_gb);
72 #endif
73
74 // Interpolate gain table back to full size
75 int sizeX[16];
76 int sizeY[16];
77 computeSamplingInterval(srcLscWidth, srcLscHeight, sizeX, sizeY);
78 calculateCorrectFactor(otpGrad->lsc_r, rTable, srcLscWidth, srcLscHeight, sizeX, sizeY);
79 calculateCorrectFactor(otpGrad->lsc_gr, grTable, srcLscWidth, srcLscHeight, sizeX, sizeY);
80 calculateCorrectFactor(otpGrad->lsc_gb, gbTable, srcLscWidth, srcLscHeight, sizeX, sizeY);
81 calculateCorrectFactor(otpGrad->lsc_b, bTable, srcLscWidth, srcLscHeight, sizeX, sizeY);
82 getLscParameter(rTable, grTable, gbTable, bTable, corTable, srcLscWidth, srcLscHeight, bayer);
83
84 // Clipping a Gain table is centered by default
85 int cropoffsetx = srcLscWidth / 2 - dstWidth / 2;
86 int cropoffsety = srcLscHeight / 2 - dstHeight / 2;
87
88 if (cropoffsetx % 2 != 0)
89 cropoffsetx = cropoffsetx - 1;
90 if (cropoffsety % 2 != 0)
91 cropoffsety = cropoffsety -1;
92
93 for (int i = 0; i < dstHeight; i++)
94 {
95
96 memcpy(corTable_crop + i * dstWidth, corTable + (cropoffsety + i)*srcLscWidth + cropoffsetx, dstWidth * 2);
97 //*(corTable_crop + i*dstWidth + j) = *(corTable + (cropoffsety + i)*srcLscWidth + j + cropoffsetx);
98 }
99
100 delete[] rTable;
101 delete[] grTable;
102 delete[] gbTable;
103 delete[] bTable;
104 delete[] corTable;
105
106
107 // down-sampling again according to crop size
108 uint16_t *plscdataR = new uint16_t[dstWidth / 2 * dstHeight / 2];
109 uint16_t *plscdataGr = new uint16_t[dstWidth / 2 * dstHeight / 2];
110 uint16_t *plscdataGb = new uint16_t[dstWidth / 2 * dstHeight / 2];
111 uint16_t *plscdataB = new uint16_t[dstWidth / 2 * dstHeight / 2];
112
113 memset(plscdataR, 0, sizeof(uint16_t)*dstWidth / 2 * dstHeight / 2);
114 memset(plscdataGr, 0, sizeof(uint16_t)*dstWidth / 2 * dstHeight / 2);
115 memset(plscdataGb, 0, sizeof(uint16_t)*dstWidth / 2 * dstHeight / 2);
116 memset(plscdataB, 0, sizeof(uint16_t)*dstWidth / 2 * dstHeight / 2);
117
118 separateBayerChannel(corTable_crop, plscdataR, plscdataGr, plscdataGb, plscdataB, dstWidth, dstHeight, bayer);
119
120
121 int cPos[17]; // col sampling
122 int rPos[17]; // row sampling
123 computeSamplingPoint(dstWidth / 2, cPos);
124 computeSamplingPoint(dstHeight / 2, rPos);
125 int r, c;
126 for (int i = 0; i < 17; i++)
127 {
128 for (int j = 0; j < 17; j++)
129 {
130 r = rPos[i];
131 c = cPos[j];
132
133 *(otpGrad->lsc_r + i * 17 + j) = plscdataR[r * dstWidth / 2 + c];
134 *(otpGrad->lsc_gr + i * 17 + j) = plscdataGr[r * dstWidth / 2 + c];
135 *(otpGrad->lsc_gb + i * 17 + j) = plscdataGb[r * dstWidth / 2 + c];
136 *(otpGrad->lsc_b + i * 17 + j) = plscdataB[r * dstWidth / 2 + c];
137 }
138 }
139
140 #if WRITE_OTP_TABLE
141 snprintf(fileName, sizeof(fileName) - 1, "/tmp/converted_otp_lsc_r.bin");
142 writeFile(fileName, otpGrad->lsc_r);
143 snprintf(fileName, sizeof(fileName) - 1, "/tmp/converted_otp_lsc_b.bin");
144 writeFile(fileName, otpGrad->lsc_b);
145 snprintf(fileName, sizeof(fileName) - 1, "/tmp/converted_otp_lsc_gr.bin");
146 writeFile(fileName, otpGrad->lsc_gr);
147 snprintf(fileName, sizeof(fileName) - 1, "/tmp/converted_otp_lsc_gb.bin");
148 writeFile(fileName, otpGrad->lsc_gb);
149 #endif
150
151 delete[] plscdataR;
152 delete[] plscdataGr;
153 delete[] plscdataGb;
154 delete[] plscdataB;
155 delete[] corTable_crop;
156
157 LOGD_ALSC("crop otp LscMatrix r[0:3]:%d,%d,%d,%d, gr[0:3]:%d,%d,%d,%d, gb[0:3]:%d,%d,%d,%d, b[0:3]:%d,%d,%d,%d\n",
158 otpGrad->lsc_r[0],
159 otpGrad->lsc_r[1],
160 otpGrad->lsc_r[2],
161 otpGrad->lsc_r[3],
162 otpGrad->lsc_gr[0],
163 otpGrad->lsc_gr[1],
164 otpGrad->lsc_gr[2],
165 otpGrad->lsc_gr[3],
166 otpGrad->lsc_gb[0],
167 otpGrad->lsc_gb[1],
168 otpGrad->lsc_gb[2],
169 otpGrad->lsc_gb[3],
170 otpGrad->lsc_b[0],
171 otpGrad->lsc_b[1],
172 otpGrad->lsc_b[2],
173 otpGrad->lsc_b[3]);
174
175 XCAM_STATIC_PROFILING_END(convertLscTable, 0);
176 }
177
computeSamplingPoint(int size,int * pos)178 void computeSamplingPoint(int size, int *pos)
179 {
180 float sampPos[17] = { 0.0, 6.25, 12.5, 18.75, 25.0, 31.25, 37.5, 43.75, 50.0,
181 56.25, 62.5, 68.75, 75.0, 81.25, 87.5, 93.75, 100.0
182 };
183 float tmpVal;
184
185 pos[0] = 0;
186 for (int i = 1; i < 17; i++)
187 {
188 tmpVal = sampPos[i] / 100;
189 pos[i] = (int)(tmpVal * size) - 1;
190 }
191
192 }
193
computeSamplingInterval(int width,int height,int * xInterval,int * yInterval)194 void computeSamplingInterval(int width, int height, int *xInterval, int *yInterval)
195 {
196 int xpos[17];
197 int ypos[17];
198
199 computeSamplingPoint(width, xpos);
200 computeSamplingPoint(height, ypos);
201
202 for (int i = 0; i < 16; i++)
203 {
204 xInterval[i] = xpos[i + 1] - xpos[i];
205 yInterval[i] = ypos[i + 1] - ypos[i];
206 }
207
208 xInterval[0] = xInterval[0] + 1;
209 yInterval[0] = yInterval[0] + 1;
210 }
211
calculateCorrectFactor(uint16_t * table,uint16_t * correctTable,int width,int height,int * xInterval,int * yInterval)212 void calculateCorrectFactor(uint16_t *table, uint16_t *correctTable, int width, int height, int *xInterval, int *yInterval)
213 {
214 int xGrad[16], yGrad[16];
215 int xblk, yblk;
216 uint16_t xbase, ybase, xoffset, yoffset;
217 uint16_t curSizeX, curSizeY, curGradX, curGradY;
218 uint16_t luCoeff, ldCoeff, ruCoeff, rdCoeff;
219 uint32_t lCoeff, rCoeff, coeff;
220 uint32_t tmp, tmp2;
221
222 computeGradient(xInterval, yInterval, xGrad, yGrad);
223
224 for (ybase = 0, yblk = 0; yblk < 16; yblk++)
225 {
226 curSizeY = yInterval[yblk];
227 curGradY = yGrad[yblk];
228 for (xbase = 0, xblk = 0; xblk < 16; xblk++)
229 {
230 curSizeX = xInterval[xblk];
231 curGradX = xGrad[xblk];
232 luCoeff = table[yblk * 17 + xblk];
233 ldCoeff = table[(yblk + 1) * 17 + xblk];
234 ruCoeff = table[yblk * 17 + xblk + 1];
235 rdCoeff = table[(yblk + 1) * 17 + xblk + 1];
236 for (yoffset = 0; yoffset < curSizeY; yoffset++)
237 {
238 tmp = abs(luCoeff - ldCoeff);
239 tmp = tmp * curGradY;
240 tmp = (tmp + c_dy_round) >> c_dy_shift;
241 tmp = tmp * yoffset;
242 tmp = (tmp + c_extend_round) >> c_lsc_corr_extend;
243 tmp = (tmp << (32 - c_lsc_corr_bw)) >> (32 - c_lsc_corr_bw);
244 lCoeff = luCoeff << c_corr_diff;
245 lCoeff = (luCoeff > ldCoeff) ? (lCoeff - tmp) : (lCoeff + tmp);
246
247 tmp = abs(ruCoeff - rdCoeff);
248 tmp = tmp * curGradY;
249 tmp = (tmp + c_dy_round) >> c_dy_shift;
250 tmp = tmp * yoffset;
251 tmp = (tmp + c_extend_round) >> c_lsc_corr_extend;
252 tmp = (tmp << (32 - c_lsc_corr_bw)) >> (32 - c_lsc_corr_bw);
253 rCoeff = ruCoeff << c_corr_diff;
254 rCoeff = (ruCoeff > rdCoeff) ? (rCoeff - tmp) : (rCoeff + tmp);
255
256 coeff = lCoeff << c_lsc_corr_extend;
257 tmp = abs((int)(rCoeff - lCoeff));
258 tmp = tmp * curGradX;
259 tmp = (tmp + c_dx_round) >> c_dx_shift;
260 for (xoffset = 0; xoffset < curSizeX; xoffset++)
261 {
262 tmp2 = (coeff + c_extend_round) >> c_lsc_corr_extend;
263 tmp2 = (tmp2 > ((1 << c_lsc_corr_bw) - 1)) ? ((1 << c_lsc_corr_bw) - 1) : tmp2;
264 *(correctTable + (ybase + yoffset) * width + (xbase + xoffset)) = (uint16_t)tmp2 >> c_corr_diff;
265 coeff = (lCoeff > rCoeff) ? (coeff - tmp) : (coeff + tmp);
266 }
267 }
268 xbase += curSizeX;
269 }
270 ybase += curSizeY;
271 }
272 }
273
getLscParameter(uint16_t * r,uint16_t * gr,uint16_t * gb,uint16_t * b,uint16_t * table,int width,int height,int bayer)274 void getLscParameter(uint16_t *r, uint16_t *gr, uint16_t *gb, uint16_t *b, uint16_t *table, int width, int height, int bayer)
275 {
276 int bayerIdx;
277 int idx;
278
279 for (int i = 0; i < height; i++)
280 {
281 for (int j = 0; j < width; j++)
282 {
283 idx = i * width + j;
284 bayerIdx = getBayerIndex(bayer, i, j);
285 switch (bayerIdx)
286 {
287 case 0:
288 table[idx] = r[idx];
289 break;
290 case 1:
291 table[idx] = gr[idx];
292 break;
293 case 2:
294 table[idx] = gb[idx];
295 break;
296 case 3:
297 table[idx] = b[idx];
298 break;
299 default:
300 break;
301 }
302 }
303 }
304 }
305
separateBayerChannel(uint16_t * src,uint16_t * disR,uint16_t * disGr,uint16_t * disGb,uint16_t * disB,int width,int height,int bayer)306 void separateBayerChannel(uint16_t* src, uint16_t* disR, uint16_t* disGr, uint16_t* disGb, uint16_t* disB, int width, int height, int bayer)
307 {
308 int index = 0;
309 int bayerIdx = 0;
310
311 for (int i = 0; i < height; i++)
312 {
313 for (int j = 0; j < width; j++)
314 {
315 index = i * width + j;
316 bayerIdx = getBayerIndex(bayer, i, j);
317 switch (bayerIdx)
318 {
319 case 0:
320 *(disR++) = *(src + index);
321 break;
322 case 1:
323 *(disGr++) = *(src + index);
324 break;
325 case 2:
326 *(disGb++) = *(src + index);
327 break;
328 case 3:
329 *(disB++) = *(src + index);
330 break;
331 default:
332 break;
333 }
334 }
335 }
336 }
computeGradient(int * xInterval,int * yInterval,int * xGradient,int * yGradient)337 void computeGradient(int *xInterval, int *yInterval, int *xGradient, int *yGradient)
338 {
339 // gradient N = INT(2^15 / SizeN + 0.5)
340 for (int i = 0; i < 16; i++)
341 {
342 xGradient[i] = (int)(32768.0 / (double)xInterval[i] + 0.5);
343 if (xGradient[i] > 8191)
344 {
345 xGradient[i] = 8191;
346 }
347
348 yGradient[i] = (int)(32768.0 / (double)yInterval[i] + 0.5);
349 if (yGradient[i] > 8191)
350 {
351 yGradient[i] = 8191;
352 }
353 }
354 }
getBayerIndex(int pattern,int row,int col)355 int getBayerIndex(int pattern, int row, int col)
356 {
357 int index = 0;
358 int x, y;
359 int tmp = 0;
360
361 x = row % 2;
362 y = col % 2;
363
364 if (x == 0 && y == 0)
365 {
366 tmp = 0;
367 }
368 else if (x == 0 && y == 1)
369 {
370 tmp = 1;
371 }
372 else if (x == 1 && y == 0)
373 {
374 tmp = 2;
375 }
376 else if (x == 1 && y == 1)
377 {
378 tmp = 3;
379 }
380
381 if (pattern == BAYER_BGGR)
382 {
383 switch (tmp)
384 {
385 case 0:
386 index = B_INDEX;
387 break;
388 case 1:
389 index = GB_INDEX;
390 break;
391 case 2:
392 index = GR_INDEX;
393 break;
394 case 3:
395 index = R_INDEX;
396 break;
397 }
398 }
399 else if (pattern == BAYER_GBRG)
400 {
401 switch (tmp)
402 {
403 case 0:
404 index = GB_INDEX;
405 break;
406 case 1:
407 index = B_INDEX;
408 break;
409 case 2:
410 index = R_INDEX;
411 break;
412 case 3:
413 index = GR_INDEX;
414 break;
415 }
416 }
417 else if (pattern == BAYER_GRBG)
418 {
419 switch (tmp)
420 {
421 case 0:
422 index = GR_INDEX;
423 break;
424 case 1:
425 index = R_INDEX;
426 break;
427 case 2:
428 index = B_INDEX;
429 break;
430 case 3:
431 index = GB_INDEX;
432 break;
433 }
434 }
435 else if (pattern == BAYER_RGGB)
436 {
437 switch (tmp)
438 {
439 case 0:
440 index = R_INDEX;
441 break;
442 case 1:
443 index = GR_INDEX;
444 break;
445 case 2:
446 index = GB_INDEX;
447 break;
448 case 3:
449 index = B_INDEX;
450 break;
451 }
452 }
453
454 return index;
455 }
456
writeFile(char * fileName,uint16_t * buf)457 void writeFile(char *fileName, uint16_t *buf)
458 {
459 FILE *fd = fopen(fileName, "wb");
460 if (fd == NULL)
461 printf("%s: open failed: %s\n", __func__, fileName);
462 else {
463 fwrite(buf, 1, LSCDATA_LEN * sizeof(uint16_t), fd);
464 fclose(fd);
465 }
466 }
467
468
lightFallOff(uint16_t * table,float * percenttable,float percent,int width,int height)469 void lightFallOff(uint16_t *table, float *percenttable, float percent, int width, int height)
470 {
471 float ratio = (float)width / (float)height;
472 float rMax = sqrt(pow((float)(16 / 2 * ratio), 2) + pow((float)(16 / 2), 2));
473 float r = 0.0, alpha = 0.0, falloff = 0.0, halfPi = 3.1415926 / 2;
474
475 percent = percent / 100.0;
476
477 uint16_t tmpTable[17 * 17];
478 memcpy(tmpTable, table, sizeof(uint16_t) * 17 * 17);
479
480 for (int i = 0; i < 17; i++)
481 {
482 for (int j = 0; j < 17; j++)
483 {
484 table[i * 17 + j] = (float)(table[i * 17 + j] - 1024) * percent + 1024.0;
485 percenttable[i * 17 + j] = (float)table[i * 17 + j] / (float)tmpTable[i * 17 + j];
486 }
487 }
488 }
489
adjustVignettingForLscOTP(uint16_t * tableB,uint16_t * tableGb,uint16_t * tableGr,uint16_t * tableR,float newVig,int width,int height)490 void adjustVignettingForLscOTP(uint16_t *tableB, uint16_t *tableGb, uint16_t *tableGr, uint16_t *tableR, float newVig, int width, int height)
491 {
492 const float falloffRevert70[17 * 17] = {
493 1.42857, 1.3392, 1.27634, 1.22754, 1.18984, 1.16169, 1.14214, 1.13063, 1.12683, 1.13063, 1.14214, 1.16169, 1.18984, 1.22754, 1.27634, 1.3392, 1.42857,
494 1.37424, 1.29764, 1.23862, 1.19214, 1.15602, 1.12897, 1.11015, 1.09905, 1.09539, 1.09905, 1.11015, 1.12897, 1.15602, 1.19214, 1.23862, 1.29764, 1.37424,
495 1.33537, 1.26382, 1.20742, 1.16268, 1.12778, 1.10158, 1.08335, 1.07259, 1.06904, 1.07259, 1.08335, 1.10158, 1.12778, 1.16268, 1.20742, 1.26382, 1.33537,
496 1.30481, 1.23644, 1.18195, 1.13853, 1.10458, 1.07908, 1.06131, 1.05082, 1.04735, 1.05082, 1.06131, 1.07908, 1.10458, 1.13853, 1.18195, 1.23644, 1.30481,
497 1.28095, 1.21477, 1.16169, 1.11927, 1.08606, 1.06109, 1.04368, 1.0334, 1.03, 1.0334, 1.04368, 1.06109, 1.08606, 1.11927, 1.16169, 1.21477, 1.28095,
498 1.26297, 1.19832, 1.14626, 1.10458, 1.07193, 1.04735, 1.03021, 1.02009, 1.01675, 1.02009, 1.03021, 1.04735, 1.07193, 1.10458, 1.14626, 1.19832, 1.26297,
499 1.25042, 1.18678, 1.13541, 1.09425, 1.06197, 1.03767, 1.02072, 1.01071, 1.0074, 1.01071, 1.02072, 1.03767, 1.06197, 1.09425, 1.13541, 1.18678, 1.25042,
500 1.24299, 1.17993, 1.12897, 1.0881, 1.05605, 1.03191, 1.01508, 1.00513, 1.00184, 1.00513, 1.01508, 1.03191, 1.05605, 1.0881, 1.12897, 1.17993, 1.24299,
501 1.24053, 1.17766, 1.12683, 1.08606, 1.05408, 1.03, 1.0132, 1.00328, 1, 1.00328, 1.0132, 1.03, 1.05408, 1.08606, 1.12683, 1.17766, 1.24053,
502 1.24299, 1.17993, 1.12897, 1.0881, 1.05605, 1.03191, 1.01508, 1.00513, 1.00184, 1.00513, 1.01508, 1.03191, 1.05605, 1.0881, 1.12897, 1.17993, 1.24299,
503 1.25042, 1.18678, 1.13541, 1.09425, 1.06197, 1.03767, 1.02072, 1.01071, 1.0074, 1.01071, 1.02072, 1.03767, 1.06197, 1.09425, 1.13541, 1.18678, 1.25042,
504 1.26297, 1.19832, 1.14626, 1.10458, 1.07193, 1.04735, 1.03021, 1.02009, 1.01675, 1.02009, 1.03021, 1.04735, 1.07193, 1.10458, 1.14626, 1.19832, 1.26297,
505 1.28095, 1.21477, 1.16169, 1.11927, 1.08606, 1.06109, 1.04368, 1.0334, 1.03, 1.0334, 1.04368, 1.06109, 1.08606, 1.11927, 1.16169, 1.21477, 1.28095,
506 1.30481, 1.23644, 1.18195, 1.13853, 1.10458, 1.07908, 1.06131, 1.05082, 1.04735, 1.05082, 1.06131, 1.07908, 1.10458, 1.13853, 1.18195, 1.23644, 1.30481,
507 1.33537, 1.26382, 1.20742, 1.16268, 1.12778, 1.10158, 1.08335, 1.07259, 1.06904, 1.07259, 1.08335, 1.10158, 1.12778, 1.16268, 1.20742, 1.26382, 1.33537,
508 1.37424, 1.29764, 1.23862, 1.19214, 1.15602, 1.12897, 1.11015, 1.09905, 1.09539, 1.09905, 1.11015, 1.12897, 1.15602, 1.19214, 1.23862, 1.29764, 1.37424,
509 1.42857, 1.3392, 1.27634, 1.22754, 1.18984, 1.16169, 1.14214, 1.13063, 1.12683, 1.13063, 1.14214, 1.16169, 1.18984, 1.22754, 1.27634, 1.3392, 1.42857 };
510
511 for (int i = 0; i < 17 * 17; i++)
512 {
513 tableB[i] = tableB[i] < 1024 ? 1024 : tableB[i];
514 tableGb[i] = tableGb[i] < 1024 ? 1024 : tableGb[i];
515 tableGr[i] = tableGr[i] < 1024 ? 1024 : tableGr[i];
516 tableR[i] = tableR[i] < 1024 ? 1024 : tableR[i];
517 }
518
519 // revert to 100 vig
520 for (int i = 0; i < 17 * 17; i++)
521 {
522 tableB[i] = (float)(tableB[i] - 1024) * falloffRevert70[i] + 1024.0 +0.5;
523 tableGb[i] = (float)(tableGb[i] - 1024) * falloffRevert70[i] + 1024.0 + 0.5;
524 tableGr[i] = (float)(tableGr[i] - 1024) * falloffRevert70[i] + 1024.0 + 0.5;
525 tableR[i] = (float)(tableR[i] - 1024) * falloffRevert70[i] + 1024.0 + 0.5;
526 }
527
528 // calculate new falloff table
529 float newFalloffTable[17 * 17];
530 lightFallOff(tableGb, newFalloffTable, newVig, width, height);
531
532 // apply to other channel
533 for (int i = 0; i < 17 * 17; i++)
534 {
535 tableB[i] = (float)tableB[i] * newFalloffTable[i] + 0.5;
536 tableGr[i] = (float)tableGr[i] * newFalloffTable[i] + 0.5;
537 tableR[i] = (float)tableR[i] * newFalloffTable[i] + 0.5;
538 }
539 }
540