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.h89
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c179
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.h48
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/processing/rgbprocessing.c156
5 files changed, 716 insertions, 0 deletions
diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/bayerprocessing.c b/v4l2-apps/libv4l/libv4lconvert/processing/bayerprocessing.c
new file mode 100644
index 000000000..f4cc9922b
--- /dev/null
+++ b/v4l2-apps/libv4l/libv4lconvert/processing/bayerprocessing.c
@@ -0,0 +1,244 @@
+/*
+# (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
new file mode 100644
index 000000000..f2aae373d
--- /dev/null
+++ b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing-priv.h
@@ -0,0 +1,89 @@
+/*
+# (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
+*/
+
+#ifndef __LIBV4LPROCESSING_PRIV_H
+#define __LIBV4LPROCESSING_PRIV_H
+
+#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;
+ /* 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;
+};
+
+/* 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);
+
+/* 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);
+
+#endif
diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c
new file mode 100644
index 000000000..d61c29275
--- /dev/null
+++ b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c
@@ -0,0 +1,179 @@
+/*
+# (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 */
+
+struct v4lprocessing_data *v4lprocessing_create(struct v4lcontrol_data* control)
+{
+ struct v4lprocessing_data *data =
+ calloc(1, sizeof(struct v4lprocessing_data));
+
+ if (!data)
+ return NULL;
+
+ data->control = control;
+
+ return data;
+}
+
+void v4lprocessing_destroy(struct v4lprocessing_data *data)
+{
+ free(data);
+}
+
+static int v4lprocessing_get_process(struct v4lprocessing_data *data,
+ unsigned int pix_fmt)
+{
+ int process = V4L2PROCESSING_PROCESS_NONE;
+
+ 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;
+ }
+
+ return process;
+}
+
+static void v4lprocessing_update_processing_data(
+ struct v4lprocessing_data *data,
+ unsigned int pix_fmt, unsigned char *buf, unsigned int width,
+ unsigned int height)
+{
+ switch (data->process) {
+ case V4L2PROCESSING_PROCESS_BAYER_NORMALIZE:
+ bayer_normalize_analyse(buf, width, height, data);
+ break;
+
+ case V4L2PROCESSING_PROCESS_BAYER_WHITEBALANCE:
+ bayer_whitebalance_analyse(buf, width, height, pix_fmt, data);
+ break;
+
+ case V4L2PROCESSING_PROCESS_BAYER_NORMALIZE_WHITEBALANCE:
+ bayer_normalize_whitebalance_analyse(buf, width, height, pix_fmt, data);
+ break;
+
+ case V4L2PROCESSING_PROCESS_RGB_NORMALIZE:
+ rgb_normalize_analyse(buf, width, height, data);
+ break;
+
+ case V4L2PROCESSING_PROCESS_RGB_WHITEBALANCE:
+ rgb_whitebalance_analyse(buf, width, height, data);
+ break;
+
+ case V4L2PROCESSING_PROCESS_RGB_NORMALIZE_WHITEBALANCE:
+ rgb_normalize_whitebalance_analyse(buf, width, height, data);
+ 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);
+
+ 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) {
+ data->process = process;
+ 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;
+ }
+
+ 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);
+ } 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;
+
+ case V4L2PROCESSING_PROCESS_RGB_WHITEBALANCE:
+ rgb_whitebalance(buf, fmt->fmt.pix.width, fmt->fmt.pix.height, data);
+ break;
+
+ 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/libv4lprocessing.h b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.h
new file mode 100644
index 000000000..3c50d9fb9
--- /dev/null
+++ b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.h
@@ -0,0 +1,48 @@
+/*
+# (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 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
+*/
+
+#ifndef __LIBV4LPROCESSING_H
+#define __LIBV4LPROCESSING_H
+
+/* These headers are not needed by us, but by linux/videodev2.h,
+ which is broken on some systems and doesn't include them itself :( */
+#include <sys/time.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+/* end broken header workaround includes */
+#include <linux/videodev2.h>
+
+struct v4lprocessing_data;
+struct v4lcontrol_data;
+
+struct v4lprocessing_data *v4lprocessing_create(struct v4lcontrol_data *data);
+void v4lprocessing_destroy(struct v4lprocessing_data *data);
+
+/* Prepare to process 1 frame, returns 1 if processing is necesary,
+ return 0 if no processing will be done */
+int v4lprocessing_pre_processing(struct v4lprocessing_data *data);
+
+/* Do the actual processing, this is a nop if v4lprocessing_pre_processing()
+ returned 0, or if called more then 1 time after a single
+ v4lprocessing_pre_processing() call. */
+void v4lprocessing_processing(struct v4lprocessing_data *data,
+ unsigned char *buf, const struct v4l2_format *fmt);
+
+#endif
diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/rgbprocessing.c b/v4l2-apps/libv4l/libv4lconvert/processing/rgbprocessing.c
new file mode 100644
index 000000000..4e0fc3f4a
--- /dev/null
+++ b/v4l2-apps/libv4l/libv4lconvert/processing/rgbprocessing.c
@@ -0,0 +1,156 @@
+/*
+# (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);
+ }
+}