summaryrefslogtreecommitdiff
path: root/v4l2-apps/libv4l/libv4lconvert/processing
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-apps/libv4l/libv4lconvert/processing')
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/processing/bayerprocessing.c244
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing-priv.h68
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c202
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/processing/rgbprocessing.c156
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/processing/whitebalance.c143
5 files changed, 259 insertions, 554 deletions
diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/bayerprocessing.c b/v4l2-apps/libv4l/libv4lconvert/processing/bayerprocessing.c
deleted file mode 100644
index f4cc9922b..000000000
--- a/v4l2-apps/libv4l/libv4lconvert/processing/bayerprocessing.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
-# (C) 2008-2009 Elmar Kleijn <elmar_kleijn@hotmail.com>
-# (C) 2008-2009 Sjoerd Piepenbrink <need4weed@gmail.com>
-# (C) 2008-2009 Hans de Goede <hdegoede@redhat.com>
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "libv4lprocessing-priv.h"
-#include "../libv4lconvert-priv.h" /* for PIX_FMT defines */
-
-void bayer_normalize_analyse(unsigned char *buf, int width, int height,
- struct v4lprocessing_data *data)
-{
- int value, max = 0, min = 255;
- unsigned char *buf_end = buf + width * height;
-
- while (buf < buf_end) {
- value = *buf++;
- if (max < value)
- max = value;
- if (min > value)
- min = value;
- }
-
- data->comp1 = ((data->norm_high_bound - data->norm_low_bound) << 16) / (max - min);
- data->offset1 = min;
- data->offset2 = data->norm_low_bound;
-}
-
-void bayer_whitebalance_analyse(unsigned char *src_buffer, int width,
- int height, unsigned int pix_fmt, struct v4lprocessing_data *data)
-{
- int i, j, x1 = 0, x2 = 0, y1 = 0, y2 = 0;
- float green_avg, x_avg, y_avg, avg_avg;
- unsigned char *buf = src_buffer;
-
- int start_with_green = pix_fmt == V4L2_PIX_FMT_SGBRG8 ||
- pix_fmt == V4L2_PIX_FMT_SGRBG8;
-
- for (i = 0; i < height; i += 2) {
- for (j = 0; j < width; j += 2) {
- x1 += *buf++;
- x2 += *buf++;
- }
- for (j = 0; j < width; j += 2) {
- y1 += *buf++;
- y2 += *buf++;
- }
- }
-
- if (start_with_green) {
- green_avg = (x1 + y2) / 2;
- x_avg = x2;
- y_avg = y1;
- } else {
- green_avg = (x2 + y1) / 2;
- x_avg = x1;
- y_avg = y2;
- }
-
- avg_avg = (green_avg + x_avg + y_avg) / 3;
-
- data->comp1 = (avg_avg / green_avg) * 65536;
- data->comp2 = (avg_avg / x_avg) * 65536;
- data->comp3 = (avg_avg / y_avg) * 65536;
-}
-
-void bayer_normalize_whitebalance_analyse(unsigned char *buf, int width,
- int height, unsigned int pix_fmt, struct v4lprocessing_data *data)
-{
- int i, j, value, max = 0, min = 255, n_fac, x1 = 0, x2 = 0, y1 = 0, y2 = 0;
- float green_avg, x_avg, y_avg, avg_avg;
-
- int start_with_green = pix_fmt == V4L2_PIX_FMT_SGBRG8 ||
- pix_fmt == V4L2_PIX_FMT_SGRBG8;
-
- for (i = 0; i < height; i += 2) {
- for (j = 0; j < width; j += 2) {
- x1 += *buf;
- value = *buf++;
- if (max < value)
- max = value;
- if (min > value)
- min = value;
- x2 += *buf;
- value = *buf++;
- if (max < value)
- max = value;
- if (min > value)
- min = value;
- }
- for (j = 0; j < width; j += 2) {
- y1 += *buf;
- value = *buf++;
- if (max < value)
- max = value;
- if (min > value)
- min = value;
- y2 += *buf;
- value = *buf++;
- if (max < value)
- max = value;
- if (min > value)
- min = value;
- }
- }
-
- if (start_with_green) {
- green_avg = (x1 + y2) / 2;
- x_avg = x2;
- y_avg = y1;
- } else {
- green_avg = (x2 + y1) / 2;
- x_avg = x1;
- y_avg = y2;
- }
-
- n_fac = ((data->norm_high_bound - data->norm_low_bound) << 16) / (max - min);
-
- avg_avg = (green_avg + x_avg + y_avg) / 3;
-
- data->comp1 = (avg_avg / green_avg) * n_fac;
- data->comp2 = (avg_avg / x_avg) * n_fac;
- data->comp3 = (avg_avg / y_avg) * n_fac;
-
- data->offset1 = min;
- data->offset2 = data->norm_low_bound;
-}
-
-#define CLIP(color) (unsigned char)(((color)>0xff)?0xff:(((color)<0)?0:(color)))
-#define TOP(color) (unsigned char)(((color)>0xff)?0xff:(color))
-
-void bayer_normalize(unsigned char *buf, int width,
- int height, struct v4lprocessing_data *data)
-{
- int value;
- unsigned char *buf_end = buf + width * height;
-
- while (buf < buf_end) {
- value = ((data->comp1 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- }
-}
-
-void bayer_whitebalance(unsigned char *src_buffer, int width,
- int height, unsigned int pix_fmt,
- struct v4lprocessing_data *data)
-{
- int i, j, value;
- int limit = width * height;
- unsigned char *buf = src_buffer;
-
- int start_with_green = pix_fmt == V4L2_PIX_FMT_SGBRG8 ||
- pix_fmt == V4L2_PIX_FMT_SGRBG8;
-
- if (start_with_green) {
- for (i = 0; i < height; i += 2) {
- for (j = 0; j < width; j += 2) {
- value = (*buf * data->comp1) >> 16;
- *buf++ = TOP(value);
- value = (*buf * data->comp2) >> 16;
- *buf++ = TOP(value);
- }
- for (j = 0; j < width; j += 2) {
- value = (*buf * data->comp3) >> 16;
- *buf++ = TOP(value);
- value = (*buf * data->comp1) >> 16;
- *buf++ = TOP(value);
- }
- }
- } else {
- for (i = 0; i < height; i += 2) {
- for (j = 0; j < width; j += 2) {
- value = (*buf * data->comp2) >> 16;
- *buf++ = TOP(value);
- value = (*buf * data->comp1) >> 16;
- *buf++ = TOP(value);
- }
- for (j = 0; j < width; j += 2) {
- value = (*buf * data->comp1) >> 16;
- *buf++ = TOP(value);
- value = (*buf * data->comp3) >> 16;
- *buf++ = TOP(value);
- }
- }
- }
-}
-
-void bayer_normalize_whitebalance(unsigned char *src_buffer, int width,
- int height, unsigned int pix_fmt,
- struct v4lprocessing_data *data)
-{
- int i, j, value;
- int limit = width * height;
- unsigned char *buf = src_buffer;
-
- int start_with_green = pix_fmt == V4L2_PIX_FMT_SGBRG8 ||
- pix_fmt == V4L2_PIX_FMT_SGRBG8;
-
- if (start_with_green) {
- for (i = 0; i < height; i += 2) {
- for (j = 0; j < width; j += 2) {
- value = ((data->comp1 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- value = ((data->comp2 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- }
- for (j = 0; j < width; j += 2) {
- value = ((data->comp3 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- value = ((data->comp1 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- }
- }
- } else {
- for (i = 0; i < height; i += 2) {
- for (j = 0; j < width; j += 2) {
- value = ((data->comp2 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- value = ((data->comp1 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- }
- for (j = 0; j < width; j += 2) {
- value = ((data->comp1 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- value = ((data->comp3 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- }
- }
- }
-}
diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing-priv.h b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing-priv.h
index f2aae373d..fb514d7f5 100644
--- a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing-priv.h
+++ b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing-priv.h
@@ -23,67 +23,31 @@
#include "../control/libv4lcontrol.h"
-#define V4L2PROCESSING_PROCESS_NONE 0x00
-#define V4L2PROCESSING_PROCESS_NORMALIZE 0x01
-#define V4L2PROCESSING_PROCESS_WHITEBALANCE 0x02
-#define V4L2PROCESSING_PROCESS_NORMALIZE_WHITEBALANCE 0x03
-#define V4L2PROCESSING_PROCESS_RGB_NORMALIZE 0x01
-#define V4L2PROCESSING_PROCESS_RGB_WHITEBALANCE 0x02
-#define V4L2PROCESSING_PROCESS_RGB_NORMALIZE_WHITEBALANCE 0x03
-#define V4L2PROCESSING_PROCESS_BAYER_NORMALIZE 0x11
-#define V4L2PROCESSING_PROCESS_BAYER_WHITEBALANCE 0x12
-#define V4L2PROCESSING_PROCESS_BAYER_NORMALIZE_WHITEBALANCE 0x13
-
#define V4L2PROCESSING_UPDATE_RATE 10
struct v4lprocessing_data {
struct v4lcontrol_data *control;
int do_process;
- /* Provides the current type of processing */
- int process;
- int norm_low_bound;
- int norm_high_bound;
+ /* True if any of the lookup tables does not contain
+ linear 0-255 */
+ int lookup_table_active;
/* Counts the number of processed frames until a
V4L2PROCESSING_UPDATE_RATE overflow happens */
- int processing_data_update;
- /* Multiplication factors and offsets from the analyse functions */
- int comp1;
- int comp2;
- int comp3;
- int comp4;
- int offset1;
- int offset2;
+ int lookup_table_update_counter;
+ /* RGB/BGR lookup tables */
+ unsigned char comp1[256];
+ unsigned char green[256];
+ unsigned char comp2[256];
};
-/* Processing Bayer */
-void bayer_normalize_analyse(unsigned char *src_buffer, int width, int height,
- struct v4lprocessing_data *data);
-void bayer_whitebalance_analyse(unsigned char *src_buffer, int width,
- int height, unsigned int pix_fmt,
- struct v4lprocessing_data *data);
-void bayer_normalize_whitebalance_analyse(unsigned char *src_buffer,
- int width, int height, unsigned int pix_fmt,
- struct v4lprocessing_data *data);
-void bayer_normalize(unsigned char *src_buffer, int width, int height,
- struct v4lprocessing_data *data);
-void bayer_whitebalance(unsigned char *src_buffer, int width, int height,
- unsigned int pix_fmt, struct v4lprocessing_data *data);
-void bayer_normalize_whitebalance(unsigned char *src_buffer, int width,
- int height, unsigned int pix_fmt,
- struct v4lprocessing_data *data);
+struct v4lprocessing_filter {
+ /* Returns 1 if the filter is active */
+ int (*active)(struct v4lprocessing_data *data);
+ /* Returns 1 if any of the lookup tables was changed */
+ int (*calculate_lookup_tables)(struct v4lprocessing_data *data,
+ unsigned char *buf, const struct v4l2_format *fmt);
+};
-/* Processing RGB */
-void rgb_normalize_analyse(unsigned char *src_buffer, int width, int height,
- struct v4lprocessing_data *data);
-void rgb_whitebalance_analyse(unsigned char *src_buffer, int width, int height,
- struct v4lprocessing_data *data);
-void rgb_normalize_whitebalance_analyse(unsigned char *src_buffer,
- int width, int height, struct v4lprocessing_data *data);
-void rgb_normalize(unsigned char *src_buffer, int width, int height,
- struct v4lprocessing_data *data);
-void rgb_whitebalance(unsigned char *src_buffer, int width, int height,
- struct v4lprocessing_data *data);
-void rgb_normalize_whitebalance(unsigned char *src_buffer, int width,
- int height, struct v4lprocessing_data *data);
+extern struct v4lprocessing_filter whitebalance_filter;
#endif
diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c
index f986da02d..3a3802aab 100644
--- a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c
+++ b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c
@@ -28,6 +28,10 @@
#include "libv4lprocessing-priv.h"
#include "../libv4lconvert-priv.h" /* for PIX_FMT defines */
+static struct v4lprocessing_filter *filters[] = {
+ &whitebalance_filter,
+};
+
struct v4lprocessing_data *v4lprocessing_create(struct v4lcontrol_data* control)
{
struct v4lprocessing_data *data =
@@ -46,136 +50,130 @@ void v4lprocessing_destroy(struct v4lprocessing_data *data)
free(data);
}
-static int v4lprocessing_get_process(struct v4lprocessing_data *data,
- unsigned int pix_fmt)
+int v4lprocessing_pre_processing(struct v4lprocessing_data *data)
{
- int process = V4L2PROCESSING_PROCESS_NONE;
+ int i;
- switch(pix_fmt) {
- case V4L2_PIX_FMT_SBGGR8:
- case V4L2_PIX_FMT_SGBRG8:
- case V4L2_PIX_FMT_SGRBG8:
- case V4L2_PIX_FMT_SRGGB8:
- if (v4lcontrol_get_ctrl(data->control, V4LCONTROL_NORMALIZE)) {
- process |= V4L2PROCESSING_PROCESS_BAYER_NORMALIZE;
- }
- if (v4lcontrol_get_ctrl(data->control, V4LCONTROL_WHITEBALANCE)) {
- process |= V4L2PROCESSING_PROCESS_BAYER_WHITEBALANCE;
- }
- break;
- case V4L2_PIX_FMT_RGB24:
- case V4L2_PIX_FMT_BGR24:
- if (v4lcontrol_get_ctrl(data->control, V4LCONTROL_NORMALIZE)) {
- process |= V4L2PROCESSING_PROCESS_RGB_NORMALIZE;
- }
- if (v4lcontrol_get_ctrl(data->control, V4LCONTROL_WHITEBALANCE)) {
- process |= V4L2PROCESSING_PROCESS_RGB_WHITEBALANCE;
- }
- break;
+ data->do_process = 0;
+ for (i = 0; i < ARRAY_SIZE(filters); i++) {
+ if (filters[i]->active(data))
+ data->do_process = 1;
}
- return process;
+ return data->do_process;
}
-static void v4lprocessing_update_processing_data(
- struct v4lprocessing_data *data,
- unsigned int pix_fmt, unsigned char *buf, unsigned int width,
- unsigned int height)
+static void v4lprocessing_update_lookup_tables(struct v4lprocessing_data *data,
+ unsigned char *buf, const struct v4l2_format *fmt)
{
- switch (data->process) {
- case V4L2PROCESSING_PROCESS_BAYER_NORMALIZE:
- bayer_normalize_analyse(buf, width, height, data);
- break;
+ int i;
- case V4L2PROCESSING_PROCESS_BAYER_WHITEBALANCE:
- bayer_whitebalance_analyse(buf, width, height, pix_fmt, data);
- break;
+ for (i = 0; i < 256; i++) {
+ data->comp1[i] = i;
+ data->green[i] = i;
+ data->comp2[i] = i;
+ }
- case V4L2PROCESSING_PROCESS_BAYER_NORMALIZE_WHITEBALANCE:
- bayer_normalize_whitebalance_analyse(buf, width, height, pix_fmt, data);
- break;
+ data->lookup_table_active = 0;
+ for (i = 0; i < ARRAY_SIZE(filters); i++) {
+ if (filters[i]->active(data)) {
+ if (filters[i]->calculate_lookup_tables(data, buf, fmt))
+ data->lookup_table_active = 1;
+ }
+ }
+}
+
+static void v4lprocessing_do_processing(struct v4lprocessing_data *data,
+ unsigned char *buf, const struct v4l2_format *fmt)
+{
+ int x, y;
- case V4L2PROCESSING_PROCESS_RGB_NORMALIZE:
- rgb_normalize_analyse(buf, width, height, data);
+ switch (fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_SGBRG8:
+ case V4L2_PIX_FMT_SGRBG8: /* Bayer patterns starting with green */
+ for (y = 0; y < fmt->fmt.pix.height / 2; y++) {
+ for (x = 0; x < fmt->fmt.pix.width / 2; x++) {
+ *buf = data->green[*buf];
+ buf++;
+ *buf = data->comp1[*buf];
+ buf++;
+ }
+ buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
+ for (x = 0; x < fmt->fmt.pix.width / 2; x++) {
+ *buf = data->comp2[*buf];
+ buf++;
+ *buf = data->green[*buf];
+ buf++;
+ }
+ buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
+ }
break;
- case V4L2PROCESSING_PROCESS_RGB_WHITEBALANCE:
- rgb_whitebalance_analyse(buf, width, height, data);
+ case V4L2_PIX_FMT_SBGGR8:
+ case V4L2_PIX_FMT_SRGGB8: /* Bayer patterns *NOT* starting with green */
+ for (y = 0; y < fmt->fmt.pix.height / 2; y++) {
+ for (x = 0; x < fmt->fmt.pix.width / 2; x++) {
+ *buf = data->comp1[*buf];
+ buf++;
+ *buf = data->green[*buf];
+ buf++;
+ }
+ buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
+ for (x = 0; x < fmt->fmt.pix.width / 2; x++) {
+ *buf = data->green[*buf];
+ buf++;
+ *buf = data->comp2[*buf];
+ buf++;
+ }
+ buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
+ }
break;
- case V4L2PROCESSING_PROCESS_RGB_NORMALIZE_WHITEBALANCE:
- rgb_normalize_whitebalance_analyse(buf, width, height, data);
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ for (y = 0; y < fmt->fmt.pix.height; y++) {
+ for (x = 0; x < fmt->fmt.pix.width; x++) {
+ *buf = data->comp1[*buf];
+ buf++;
+ *buf = data->green[*buf];
+ buf++;
+ *buf = data->comp2[*buf];
+ buf++;
+ }
+ buf += fmt->fmt.pix.bytesperline - 3 * fmt->fmt.pix.width;
+ }
break;
}
}
-int v4lprocessing_pre_processing(struct v4lprocessing_data *data)
-{
- data->do_process =
- v4lcontrol_get_ctrl(data->control, V4LCONTROL_WHITEBALANCE) ||
- v4lcontrol_get_ctrl(data->control, V4LCONTROL_NORMALIZE);
-
- if (!data->do_process)
- data->process = V4L2PROCESSING_PROCESS_NONE;
-
- return data->do_process;
-}
-
void v4lprocessing_processing(struct v4lprocessing_data *data,
unsigned char *buf, const struct v4l2_format *fmt)
{
- int low_bound, high_bound, process;
-
if (!data->do_process)
return;
- process = v4lprocessing_get_process(data, fmt->fmt.pix.pixelformat);
- if (process == V4L2PROCESSING_PROCESS_NONE) {
- return;
- }
-
- low_bound = v4lcontrol_get_ctrl(data->control, V4LCONTROL_NORM_LOW_BOUND);
- high_bound = v4lcontrol_get_ctrl(data->control, V4LCONTROL_NORM_HIGH_BOUND);
-
- if (process != data->process || low_bound != data->norm_low_bound ||
- high_bound != data->norm_high_bound) {
- data->process = process;
- data->norm_low_bound = low_bound;
- data->norm_high_bound = high_bound;
- data->processing_data_update = V4L2PROCESSING_UPDATE_RATE;
+ /* Do we support the current pixformat? */
+ switch (fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_SGBRG8:
+ case V4L2_PIX_FMT_SGRBG8:
+ case V4L2_PIX_FMT_SBGGR8:
+ case V4L2_PIX_FMT_SRGGB8:
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ break;
+ default:
+ return; /* Non supported pix format */
}
- if (data->processing_data_update == V4L2PROCESSING_UPDATE_RATE) {
- data->processing_data_update = 0;
- v4lprocessing_update_processing_data(data, fmt->fmt.pix.pixelformat, buf, fmt->fmt.pix.width, fmt->fmt.pix.height);
+ if (v4lcontrol_controls_changed(data->control) ||
+ data->lookup_table_update_counter == V4L2PROCESSING_UPDATE_RATE) {
+ v4lprocessing_update_lookup_tables(data, buf, fmt);
+ data->lookup_table_update_counter = 0;
} else
- data->processing_data_update++;
-
- switch (data->process) {
- case V4L2PROCESSING_PROCESS_BAYER_NORMALIZE:
- bayer_normalize(buf, fmt->fmt.pix.width, fmt->fmt.pix.height, data);
- break;
-
- case V4L2PROCESSING_PROCESS_BAYER_WHITEBALANCE:
- bayer_whitebalance(buf, fmt->fmt.pix.width, fmt->fmt.pix.height, fmt->fmt.pix.pixelformat, data);
- break;
-
- case V4L2PROCESSING_PROCESS_BAYER_NORMALIZE_WHITEBALANCE:
- bayer_normalize_whitebalance(buf, fmt->fmt.pix.width, fmt->fmt.pix.height, fmt->fmt.pix.pixelformat,
- data);
- break;
-
- case V4L2PROCESSING_PROCESS_RGB_NORMALIZE:
- rgb_normalize(buf, fmt->fmt.pix.width, fmt->fmt.pix.height, data);
- break;
+ data->lookup_table_update_counter++;
- case V4L2PROCESSING_PROCESS_RGB_WHITEBALANCE:
- rgb_whitebalance(buf, fmt->fmt.pix.width, fmt->fmt.pix.height, data);
- break;
+ if (data->lookup_table_active)
+ v4lprocessing_do_processing(data, buf, fmt);
- case V4L2PROCESSING_PROCESS_RGB_NORMALIZE_WHITEBALANCE:
- rgb_normalize_whitebalance(buf, fmt->fmt.pix.width, fmt->fmt.pix.height, data);
- break;
- }
data->do_process = 0;
}
diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/rgbprocessing.c b/v4l2-apps/libv4l/libv4lconvert/processing/rgbprocessing.c
deleted file mode 100644
index 4e0fc3f4a..000000000
--- a/v4l2-apps/libv4l/libv4lconvert/processing/rgbprocessing.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
-# (C) 2008-2009 Elmar Kleijn <elmar_kleijn@hotmail.com>
-# (C) 2008-2009 Sjoerd Piepenbrink <need4weed@gmail.com>
-# (C) 2008-2009 Hans de Goede <hdegoede@redhat.com>
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "libv4lprocessing-priv.h"
-
-void rgb_normalize_analyse(unsigned char *buf, int width, int height,
- struct v4lprocessing_data *data)
-{
- int value, max = 0, min = 255;
- unsigned char *buf_end = buf + width * height * 3;
-
- while (buf < buf_end) {
- value = *buf++;
- if (max < value)
- max = value;
- if (min > value)
- min = value;
- }
-
- data->comp1 = ((data->norm_high_bound - data->norm_low_bound) << 16) / (max - min);
- data->offset1 = min;
- data->offset2 = data->norm_low_bound;
-}
-
-void rgb_whitebalance_analyse(unsigned char *buf, int width, int height,
- struct v4lprocessing_data *data)
-{
- int value, x = 0, y = 0, z = 0;
- float x_avg, y_avg, z_avg, avg_avg;
- unsigned char *buf_end = buf + width * height * 3;
-
- while (buf < buf_end) {
- x += *buf++;
- y += *buf++;
- z += *buf++;
- }
-
- x_avg = x;
- y_avg = y;
- z_avg = z;
- avg_avg = (x_avg + y_avg + z_avg) / 3;
-
- data->comp1 = (avg_avg / x_avg) * 65536;
- data->comp2 = (avg_avg / y_avg) * 65536;
- data->comp3 = (avg_avg / z_avg) * 65536;
-}
-
-void rgb_normalize_whitebalance_analyse(unsigned char *buf,
- int width, int height, struct v4lprocessing_data *data)
-{
- int value, max = 0, min = 255;
- int n_fac, wb_max, x = 0, y = 0, z = 0;
- float x_avg, y_avg, z_avg, avg_avg;
- unsigned char *buf_end = buf + width * height * 3;
-
- while (buf < buf_end) {
- x += *buf;
- value = *buf++;
- if (max < value)
- max = value;
- if (min > value)
- min = value;
- y += *buf;
- value = *buf++;
- if (max < value)
- max = value;
- if (min > value)
- min = value;
- z += *buf;
- value = *buf++;
- if (max < value)
- max = value;
- if (min > value)
- min = value;
- }
-
- x_avg = x;
- y_avg = y;
- z_avg = z;
- avg_avg = (x_avg + y_avg + z_avg) / 3;
-
- n_fac = ((data->norm_high_bound - data->norm_low_bound) << 16) / (max - min);
-
- data->comp1 = (avg_avg / x_avg) * n_fac;
- data->comp2 = (avg_avg / y_avg) * n_fac;
- data->comp3 = (avg_avg / z_avg) * n_fac;
-
- data->offset1 = min;
- data->offset2 = data->norm_low_bound;
-}
-
-#define CLIP(color) (unsigned char)(((color)>0xff)?0xff:(((color)<0)?0:(color)))
-#define TOP(color) (unsigned char)(((color)>0xff)?0xff:(color))
-
-void rgb_normalize(unsigned char *buf, int width, int height,
- struct v4lprocessing_data *data)
-{
- int value;
- unsigned char *buf_end = buf + width * height * 3;
-
- while (buf < buf_end) {
- value = ((data->comp1 * (*buf - data->offset1)) >> 16) +
- data->offset2;
- *buf++ = CLIP(value);
- }
-}
-
-void rgb_whitebalance(unsigned char *buf, int width, int height,
- struct v4lprocessing_data *data)
-{
- int value;
- unsigned char *buf_end = buf + width * height * 3;
-
- while (buf < buf_end) {
- value = (*buf * data->comp1) >> 16;
- *buf++ = TOP(value);
- value = (*buf * data->comp2) >> 16;
- *buf++ = TOP(value);
- value = (*buf * data->comp3) >> 16;
- *buf++ = TOP(value);
- }
-}
-
-void rgb_normalize_whitebalance(unsigned char *buf, int width, int height,
- struct v4lprocessing_data *data)
-{
- int i, value;
- int limit = width * height * 3;
- unsigned char *buf_end = buf + width * height * 3;
-
- while (buf < buf_end) {
- value = ((data->comp1 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- value = ((data->comp2 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- value = ((data->comp3 * (*buf - data->offset1)) >> 16) + data->offset2;
- *buf++ = CLIP(value);
- }
-}
diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/whitebalance.c b/v4l2-apps/libv4l/libv4lconvert/processing/whitebalance.c
new file mode 100644
index 000000000..f5bfd961c
--- /dev/null
+++ b/v4l2-apps/libv4l/libv4lconvert/processing/whitebalance.c
@@ -0,0 +1,143 @@
+/*
+# (C) 2008-2009 Elmar Kleijn <elmar_kleijn@hotmail.com>
+# (C) 2008-2009 Sjoerd Piepenbrink <need4weed@gmail.com>
+# (C) 2008-2009 Hans de Goede <hdegoede@redhat.com>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include <unistd.h>
+#include "libv4lprocessing.h"
+#include "libv4lprocessing-priv.h"
+#include "../libv4lconvert-priv.h" /* for PIX_FMT defines */
+
+#define CLIP(color) (unsigned char)(((color)>0xff)?0xff:(((color)<0)?0:(color)))
+
+static int whitebalance_active(struct v4lprocessing_data *data) {
+ return v4lcontrol_get_ctrl(data->control, V4LCONTROL_WHITEBALANCE);
+}
+
+static int whitebalance_calculate_lookup_tables_bayer(
+ struct v4lprocessing_data *data, unsigned char *buf,
+ const struct v4l2_format *fmt, int starts_with_green)
+{
+ int x, y, a1 = 0, a2 = 0, b1 = 0, b2 = 0;
+ int green_avg, comp1_avg, comp2_avg, avg_avg;
+
+ for (y = 0; y < fmt->fmt.pix.height; y += 2) {
+ for (x = 0; x < fmt->fmt.pix.width; x += 2) {
+ a1 += *buf++;
+ a2 += *buf++;
+ }
+ buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
+ for (x = 0; x < fmt->fmt.pix.width; x += 2) {
+ b1 += *buf++;
+ b2 += *buf++;
+ }
+ buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
+ }
+
+ if (starts_with_green) {
+ green_avg = (a1 + b2) / 512;
+ comp1_avg = a2 / 256;
+ comp2_avg = b1 / 256;
+ } else {
+ green_avg = (a2 + b1) / 512;
+ comp1_avg = a1 / 256;
+ comp2_avg = b2 / 256;
+ }
+
+ x = fmt->fmt.pix.width * fmt->fmt.pix.height / 64;
+ if (abs(green_avg - comp1_avg) < x &&
+ abs(green_avg - comp2_avg) < x &&
+ abs(comp1_avg - comp2_avg) < x)
+ return 0;
+
+ avg_avg = (green_avg + comp1_avg + comp2_avg) / 3;
+
+ for (x = 0; x < 256; x++) {
+ data->comp1[x] = CLIP(data->comp1[x] * avg_avg / comp1_avg);
+ data->green[x] = CLIP(data->green[x] * avg_avg / green_avg);
+ data->comp2[x] = CLIP(data->comp2[x] * avg_avg / comp2_avg);
+ }
+
+ return 1;
+}
+
+static int whitebalance_calculate_lookup_tables_rgb(
+ struct v4lprocessing_data *data, unsigned char *buf,
+ const struct v4l2_format *fmt)
+{
+ int x, y, green_avg = 0, comp1_avg = 0, comp2_avg = 0, avg_avg;
+
+ for (y = 0; y < fmt->fmt.pix.height; y++) {
+ for (x = 0; x < fmt->fmt.pix.width; x++) {
+ comp1_avg += *buf++;
+ green_avg += *buf++;
+ comp2_avg += *buf++;
+ }
+ buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width * 3;
+ }
+
+ x = fmt->fmt.pix.width * fmt->fmt.pix.height * 4;
+ if (abs(green_avg - comp1_avg) < x &&
+ abs(green_avg - comp2_avg) < x &&
+ abs(comp1_avg - comp2_avg) < x)
+ return 0;
+
+ /* scale to avoid integer overflows */
+ green_avg /= 256;
+ comp1_avg /= 256;
+ comp2_avg /= 256;
+ avg_avg = (green_avg + comp1_avg + comp2_avg) / 3;
+
+ for (x = 0; x < 256; x++) {
+ data->comp1[x] = CLIP(data->comp1[x] * avg_avg / comp1_avg);
+ data->green[x] = CLIP(data->green[x] * avg_avg / green_avg);
+ data->comp2[x] = CLIP(data->comp2[x] * avg_avg / comp2_avg);
+ }
+
+ return 1;
+}
+
+
+static int whitebalance_calculate_lookup_tables(
+ struct v4lprocessing_data *data,
+ unsigned char *buf, const struct v4l2_format *fmt)
+{
+ switch (fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_SGBRG8:
+ case V4L2_PIX_FMT_SGRBG8: /* Bayer patterns starting with green */
+ return whitebalance_calculate_lookup_tables_bayer(data, buf, fmt, 1);
+
+ case V4L2_PIX_FMT_SBGGR8:
+ case V4L2_PIX_FMT_SRGGB8: /* Bayer patterns *NOT* starting with green */
+ return whitebalance_calculate_lookup_tables_bayer(data, buf, fmt, 0);
+
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ return whitebalance_calculate_lookup_tables_rgb(data, buf, fmt);
+ }
+
+ return 0; /* Should never happen */
+}
+
+struct v4lprocessing_filter whitebalance_filter = {
+ whitebalance_active, whitebalance_calculate_lookup_tables };