27
27
#include "libv4lprocessing-priv.h"
28
28
#include "../libv4lconvert-priv.h" /* for PIX_FMT defines */
30
#define CLIP256(color) (((color)>0xff)?0xff:(((color)<0)?0:(color)))
31
#define CLIP(color, min, max) (((color)>(max))?(max):(((color)<(min))?(min):(color)))
33
static int whitebalance_active(struct v4lprocessing_data *data) {
36
wb = v4lcontrol_get_ctrl(data->control, V4LCONTROL_WHITEBALANCE);
38
/* Reset cached color averages */
30
#define CLIP256(color) (((color) > 0xff) ? 0xff : (((color) < 0) ? 0 : (color)))
31
#define CLIP(color, min, max) (((color) > (max)) ? (max) : (((color) < (min)) ? (min) : (color)))
33
static int whitebalance_active(struct v4lprocessing_data *data)
37
wb = v4lcontrol_get_ctrl(data->control, V4LCONTROL_WHITEBALANCE);
39
/* Reset cached color averages */
45
46
static int whitebalance_calculate_lookup_tables_generic(
46
struct v4lprocessing_data *data, int green_avg, int comp1_avg, int comp2_avg)
47
struct v4lprocessing_data *data, int green_avg, int comp1_avg, int comp2_avg)
49
const int max_step = 64;
51
/* Clip averages (restricts maximum white balance correction) */
52
green_avg = CLIP(green_avg, 512, 3072);
53
comp1_avg = CLIP(comp1_avg, 512, 3072);
54
comp2_avg = CLIP(comp2_avg, 512, 3072);
57
if (data->green_avg == 0) {
58
data->green_avg = green_avg;
59
data->comp1_avg = comp1_avg;
60
data->comp2_avg = comp2_avg;
62
/* Slowly adjust the averages used for the correction, so that we
63
do not get a sudden change in colors */
64
if (abs(data->green_avg - green_avg) > max_step) {
65
if (data->green_avg < green_avg)
66
data->green_avg += max_step;
68
data->green_avg -= max_step;
71
data->green_avg = green_avg;
73
if (abs(data->comp1_avg - comp1_avg) > max_step) {
74
if (data->comp1_avg < comp1_avg)
75
data->comp1_avg += max_step;
77
data->comp1_avg -= max_step;
80
data->comp1_avg = comp1_avg;
82
if (abs(data->comp2_avg - comp2_avg) > max_step) {
83
if (data->comp2_avg < comp2_avg)
84
data->comp2_avg += max_step;
86
data->comp2_avg -= max_step;
89
data->comp2_avg = comp2_avg;
92
if (abs(data->green_avg - data->comp1_avg) < max_step &&
93
abs(data->green_avg - data->comp2_avg) < max_step &&
94
abs(data->comp1_avg - data->comp2_avg) < max_step)
97
avg_avg = (data->green_avg + data->comp1_avg + data->comp2_avg) / 3;
99
for (i = 0; i < 256; i++) {
100
data->comp1[i] = CLIP256(data->comp1[i] * avg_avg / data->comp1_avg);
101
data->green[i] = CLIP256(data->green[i] * avg_avg / data->green_avg);
102
data->comp2[i] = CLIP256(data->comp2[i] * avg_avg / data->comp2_avg);
50
const int max_step = 64;
52
/* Clip averages (restricts maximum white balance correction) */
53
green_avg = CLIP(green_avg, 512, 3072);
54
comp1_avg = CLIP(comp1_avg, 512, 3072);
55
comp2_avg = CLIP(comp2_avg, 512, 3072);
58
if (data->green_avg == 0) {
59
data->green_avg = green_avg;
60
data->comp1_avg = comp1_avg;
61
data->comp2_avg = comp2_avg;
63
/* Slowly adjust the averages used for the correction, so that we
64
do not get a sudden change in colors */
65
if (abs(data->green_avg - green_avg) > max_step) {
66
if (data->green_avg < green_avg)
67
data->green_avg += max_step;
69
data->green_avg -= max_step;
71
data->green_avg = green_avg;
73
if (abs(data->comp1_avg - comp1_avg) > max_step) {
74
if (data->comp1_avg < comp1_avg)
75
data->comp1_avg += max_step;
77
data->comp1_avg -= max_step;
79
data->comp1_avg = comp1_avg;
81
if (abs(data->comp2_avg - comp2_avg) > max_step) {
82
if (data->comp2_avg < comp2_avg)
83
data->comp2_avg += max_step;
85
data->comp2_avg -= max_step;
87
data->comp2_avg = comp2_avg;
90
if (abs(data->green_avg - data->comp1_avg) < max_step &&
91
abs(data->green_avg - data->comp2_avg) < max_step &&
92
abs(data->comp1_avg - data->comp2_avg) < max_step)
95
avg_avg = (data->green_avg + data->comp1_avg + data->comp2_avg) / 3;
97
for (i = 0; i < 256; i++) {
98
data->comp1[i] = CLIP256(data->comp1[i] * avg_avg / data->comp1_avg);
99
data->green[i] = CLIP256(data->green[i] * avg_avg / data->green_avg);
100
data->comp2[i] = CLIP256(data->comp2[i] * avg_avg / data->comp2_avg);
108
106
static int whitebalance_calculate_lookup_tables_bayer(
109
struct v4lprocessing_data *data, unsigned char *buf,
110
const struct v4l2_format *fmt, int starts_with_green)
107
struct v4lprocessing_data *data, unsigned char *buf,
108
const struct v4l2_format *fmt, int starts_with_green)
112
int x, y, a1 = 0, a2 = 0, b1 = 0, b2 = 0;
113
int green_avg, comp1_avg, comp2_avg;
115
for (y = 0; y < fmt->fmt.pix.height; y += 2) {
116
for (x = 0; x < fmt->fmt.pix.width; x += 2) {
120
buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
121
for (x = 0; x < fmt->fmt.pix.width; x += 2) {
125
buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
128
if (starts_with_green) {
129
green_avg = a1 / 2 + b2 / 2;
133
green_avg = a2 / 2 + b1 / 2;
138
/* Norm avg to ~ 0 - 4095 */
139
green_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 64;
140
comp1_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 64;
141
comp2_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 64;
143
return whitebalance_calculate_lookup_tables_generic(data, green_avg,
144
comp1_avg, comp2_avg);
110
int x, y, a1 = 0, a2 = 0, b1 = 0, b2 = 0;
111
int green_avg, comp1_avg, comp2_avg;
113
for (y = 0; y < fmt->fmt.pix.height; y += 2) {
114
for (x = 0; x < fmt->fmt.pix.width; x += 2) {
118
buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
119
for (x = 0; x < fmt->fmt.pix.width; x += 2) {
123
buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
126
if (starts_with_green) {
127
green_avg = a1 / 2 + b2 / 2;
131
green_avg = a2 / 2 + b1 / 2;
136
/* Norm avg to ~ 0 - 4095 */
137
green_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 64;
138
comp1_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 64;
139
comp2_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 64;
141
return whitebalance_calculate_lookup_tables_generic(data, green_avg,
142
comp1_avg, comp2_avg);
147
145
static int whitebalance_calculate_lookup_tables_rgb(
148
struct v4lprocessing_data *data, unsigned char *buf,
149
const struct v4l2_format *fmt)
146
struct v4lprocessing_data *data, unsigned char *buf,
147
const struct v4l2_format *fmt)
151
int x, y, green_avg = 0, comp1_avg = 0, comp2_avg = 0;
153
for (y = 0; y < fmt->fmt.pix.height; y++) {
154
for (x = 0; x < fmt->fmt.pix.width; x++) {
159
buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width * 3;
162
/* Norm avg to ~ 0 - 4095 */
163
green_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 16;
164
comp1_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 16;
165
comp2_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 16;
167
return whitebalance_calculate_lookup_tables_generic(data, green_avg,
168
comp1_avg, comp2_avg);
149
int x, y, green_avg = 0, comp1_avg = 0, comp2_avg = 0;
151
for (y = 0; y < fmt->fmt.pix.height; y++) {
152
for (x = 0; x < fmt->fmt.pix.width; x++) {
157
buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width * 3;
160
/* Norm avg to ~ 0 - 4095 */
161
green_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 16;
162
comp1_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 16;
163
comp2_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 16;
165
return whitebalance_calculate_lookup_tables_generic(data, green_avg,
166
comp1_avg, comp2_avg);
172
170
static int whitebalance_calculate_lookup_tables(
173
struct v4lprocessing_data *data,
174
unsigned char *buf, const struct v4l2_format *fmt)
171
struct v4lprocessing_data *data,
172
unsigned char *buf, const struct v4l2_format *fmt)
176
switch (fmt->fmt.pix.pixelformat) {
177
case V4L2_PIX_FMT_SGBRG8:
178
case V4L2_PIX_FMT_SGRBG8: /* Bayer patterns starting with green */
179
return whitebalance_calculate_lookup_tables_bayer(data, buf, fmt, 1);
181
case V4L2_PIX_FMT_SBGGR8:
182
case V4L2_PIX_FMT_SRGGB8: /* Bayer patterns *NOT* starting with green */
183
return whitebalance_calculate_lookup_tables_bayer(data, buf, fmt, 0);
185
case V4L2_PIX_FMT_RGB24:
186
case V4L2_PIX_FMT_BGR24:
187
return whitebalance_calculate_lookup_tables_rgb(data, buf, fmt);
190
return 0; /* Should never happen */
174
switch (fmt->fmt.pix.pixelformat) {
175
case V4L2_PIX_FMT_SGBRG8:
176
case V4L2_PIX_FMT_SGRBG8: /* Bayer patterns starting with green */
177
return whitebalance_calculate_lookup_tables_bayer(data, buf, fmt, 1);
179
case V4L2_PIX_FMT_SBGGR8:
180
case V4L2_PIX_FMT_SRGGB8: /* Bayer patterns *NOT* starting with green */
181
return whitebalance_calculate_lookup_tables_bayer(data, buf, fmt, 0);
183
case V4L2_PIX_FMT_RGB24:
184
case V4L2_PIX_FMT_BGR24:
185
return whitebalance_calculate_lookup_tables_rgb(data, buf, fmt);
188
return 0; /* Should never happen */
193
191
struct v4lprocessing_filter whitebalance_filter = {
194
whitebalance_active, whitebalance_calculate_lookup_tables };
192
whitebalance_active, whitebalance_calculate_lookup_tables