summaryrefslogtreecommitdiff
path: root/v4l2-apps/libv4l/libv4lconvert/processing
diff options
context:
space:
mode:
authorhans@localhost.localdomain <hans@localhost.localdomain>2009-05-21 13:08:29 +0200
committerhans@localhost.localdomain <hans@localhost.localdomain>2009-05-21 13:08:29 +0200
commit62805a6b176a0bbd17ab8fa421791765186fb77d (patch)
tree049754e1bd4e985cb443ba944e9b98dd7113c3e0 /v4l2-apps/libv4l/libv4lconvert/processing
parent34a210b573f9c8ff8f07077f239be95d9d9248c5 (diff)
downloadmediapointer-dvb-s2-62805a6b176a0bbd17ab8fa421791765186fb77d.tar.gz
mediapointer-dvb-s2-62805a6b176a0bbd17ab8fa421791765186fb77d.tar.bz2
libv4l: rewrite video processing code
From: Hans de Goede <hdegoede@redhat.com> Rewrite video processing code to make it easier to add more video filters (and with little extra processing cost). As part of this the normalize filter has been removed as it wasn't functioning satisfactory anyways Priority: normal Signed-off-by: Hans de Goede <hdegoede@redhat.com>
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 };