~ubuntu-branches/debian/sid/v4l-utils/sid

« back to all changes in this revision

Viewing changes to lib/libv4lconvert/processing/whitebalance.c

  • Committer: Bazaar Package Importer
  • Author(s): Gregor Jasny
  • Date: 2010-05-07 20:48:34 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100507204834-ga01cxhz3fekk47r
Tags: 0.8.0-1
* New upstream version
* Switch to 3.0 (quilt) source format
* Re-enable pristine-tar
* Split utils package into command line and the Qt based qv4l2
  (Closes: #576422)
* Update upstream URL

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
# You should have received a copy of the GNU Lesser General Public License
17
17
# along with this program; if not, write to the Free Software
18
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
*/
 
19
 */
20
20
 
21
21
#include <errno.h>
22
22
#include <string.h>
27
27
#include "libv4lprocessing-priv.h"
28
28
#include "../libv4lconvert-priv.h" /* for PIX_FMT defines */
29
29
 
30
 
#define CLIP256(color) (((color)>0xff)?0xff:(((color)<0)?0:(color)))
31
 
#define CLIP(color, min, max) (((color)>(max))?(max):(((color)<(min))?(min):(color)))
32
 
 
33
 
static int whitebalance_active(struct v4lprocessing_data *data) {
34
 
  int wb;
35
 
 
36
 
  wb = v4lcontrol_get_ctrl(data->control, V4LCONTROL_WHITEBALANCE);
37
 
  if (!wb) {
38
 
    /* Reset cached color averages */
39
 
    data->green_avg = 0;
40
 
  }
41
 
 
42
 
  return wb;
 
30
#define CLIP256(color) (((color) > 0xff) ? 0xff : (((color) < 0) ? 0 : (color)))
 
31
#define CLIP(color, min, max) (((color) > (max)) ? (max) : (((color) < (min)) ? (min) : (color)))
 
32
 
 
33
static int whitebalance_active(struct v4lprocessing_data *data)
 
34
{
 
35
        int wb;
 
36
 
 
37
        wb = v4lcontrol_get_ctrl(data->control, V4LCONTROL_WHITEBALANCE);
 
38
        if (!wb) {
 
39
                /* Reset cached color averages */
 
40
                data->green_avg = 0;
 
41
        }
 
42
 
 
43
        return wb;
43
44
}
44
45
 
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)
47
48
{
48
 
  int i, avg_avg;
49
 
  const int max_step = 64;
50
 
 
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);
55
 
 
56
 
  /* First frame ? */
57
 
  if (data->green_avg == 0) {
58
 
    data->green_avg = green_avg;
59
 
    data->comp1_avg = comp1_avg;
60
 
    data->comp2_avg = comp2_avg;
61
 
  } else {
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;
67
 
      else
68
 
        data->green_avg -= max_step;
69
 
    }
70
 
    else
71
 
      data->green_avg = green_avg;
72
 
 
73
 
    if (abs(data->comp1_avg - comp1_avg) > max_step) {
74
 
      if (data->comp1_avg < comp1_avg)
75
 
        data->comp1_avg += max_step;
76
 
      else
77
 
        data->comp1_avg -= max_step;
78
 
    }
79
 
    else
80
 
      data->comp1_avg = comp1_avg;
81
 
 
82
 
    if (abs(data->comp2_avg - comp2_avg) > max_step) {
83
 
      if (data->comp2_avg < comp2_avg)
84
 
        data->comp2_avg += max_step;
85
 
      else
86
 
        data->comp2_avg -= max_step;
87
 
    }
88
 
    else
89
 
      data->comp2_avg = comp2_avg;
90
 
  }
91
 
 
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)
95
 
    return 0;
96
 
 
97
 
  avg_avg = (data->green_avg + data->comp1_avg + data->comp2_avg) / 3;
98
 
 
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);
103
 
  }
104
 
 
105
 
  return 1;
 
49
        int i, avg_avg;
 
50
        const int max_step = 64;
 
51
 
 
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);
 
56
 
 
57
        /* First frame ? */
 
58
        if (data->green_avg == 0) {
 
59
                data->green_avg = green_avg;
 
60
                data->comp1_avg = comp1_avg;
 
61
                data->comp2_avg = comp2_avg;
 
62
        } else {
 
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;
 
68
                        else
 
69
                                data->green_avg -= max_step;
 
70
                } else
 
71
                        data->green_avg = green_avg;
 
72
 
 
73
                if (abs(data->comp1_avg - comp1_avg) > max_step) {
 
74
                        if (data->comp1_avg < comp1_avg)
 
75
                                data->comp1_avg += max_step;
 
76
                        else
 
77
                                data->comp1_avg -= max_step;
 
78
                } else
 
79
                        data->comp1_avg = comp1_avg;
 
80
 
 
81
                if (abs(data->comp2_avg - comp2_avg) > max_step) {
 
82
                        if (data->comp2_avg < comp2_avg)
 
83
                                data->comp2_avg += max_step;
 
84
                        else
 
85
                                data->comp2_avg -= max_step;
 
86
                } else
 
87
                        data->comp2_avg = comp2_avg;
 
88
        }
 
89
 
 
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)
 
93
                return 0;
 
94
 
 
95
        avg_avg = (data->green_avg + data->comp1_avg + data->comp2_avg) / 3;
 
96
 
 
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);
 
101
        }
 
102
 
 
103
        return 1;
106
104
}
107
105
 
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)
111
109
{
112
 
  int x, y, a1 = 0, a2 = 0, b1 = 0, b2 = 0;
113
 
  int green_avg, comp1_avg, comp2_avg;
114
 
 
115
 
  for (y = 0; y < fmt->fmt.pix.height; y += 2) {
116
 
    for (x = 0; x < fmt->fmt.pix.width; x += 2) {
117
 
      a1 += *buf++;
118
 
      a2 += *buf++;
119
 
    }
120
 
    buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
121
 
    for (x = 0; x < fmt->fmt.pix.width; x += 2) {
122
 
      b1 += *buf++;
123
 
      b2 += *buf++;
124
 
    }
125
 
    buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
126
 
  }
127
 
 
128
 
  if (starts_with_green) {
129
 
    green_avg = a1 / 2 + b2 / 2;
130
 
    comp1_avg = a2;
131
 
    comp2_avg = b1;
132
 
  } else {
133
 
    green_avg = a2 / 2 + b1 / 2;
134
 
    comp1_avg = a1;
135
 
    comp2_avg = b2;
136
 
  }
137
 
 
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;
142
 
 
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;
 
112
 
 
113
        for (y = 0; y < fmt->fmt.pix.height; y += 2) {
 
114
                for (x = 0; x < fmt->fmt.pix.width; x += 2) {
 
115
                        a1 += *buf++;
 
116
                        a2 += *buf++;
 
117
                }
 
118
                buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
 
119
                for (x = 0; x < fmt->fmt.pix.width; x += 2) {
 
120
                        b1 += *buf++;
 
121
                        b2 += *buf++;
 
122
                }
 
123
                buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width;
 
124
        }
 
125
 
 
126
        if (starts_with_green) {
 
127
                green_avg = a1 / 2 + b2 / 2;
 
128
                comp1_avg = a2;
 
129
                comp2_avg = b1;
 
130
        } else {
 
131
                green_avg = a2 / 2 + b1 / 2;
 
132
                comp1_avg = a1;
 
133
                comp2_avg = b2;
 
134
        }
 
135
 
 
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;
 
140
 
 
141
        return whitebalance_calculate_lookup_tables_generic(data, green_avg,
 
142
                        comp1_avg, comp2_avg);
145
143
}
146
144
 
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)
150
148
{
151
 
  int x, y, green_avg = 0, comp1_avg = 0, comp2_avg = 0;
152
 
 
153
 
  for (y = 0; y < fmt->fmt.pix.height; y++) {
154
 
    for (x = 0; x < fmt->fmt.pix.width; x++) {
155
 
      comp1_avg += *buf++;
156
 
      green_avg += *buf++;
157
 
      comp2_avg += *buf++;
158
 
    }
159
 
    buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width * 3;
160
 
  }
161
 
 
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;
166
 
 
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;
 
150
 
 
151
        for (y = 0; y < fmt->fmt.pix.height; y++) {
 
152
                for (x = 0; x < fmt->fmt.pix.width; x++) {
 
153
                        comp1_avg += *buf++;
 
154
                        green_avg += *buf++;
 
155
                        comp2_avg += *buf++;
 
156
                }
 
157
                buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width * 3;
 
158
        }
 
159
 
 
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;
 
164
 
 
165
        return whitebalance_calculate_lookup_tables_generic(data, green_avg,
 
166
                        comp1_avg, comp2_avg);
169
167
}
170
168
 
171
169
 
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)
175
173
{
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);
180
 
 
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);
184
 
 
185
 
    case V4L2_PIX_FMT_RGB24:
186
 
    case V4L2_PIX_FMT_BGR24:
187
 
      return whitebalance_calculate_lookup_tables_rgb(data, buf, fmt);
188
 
  }
189
 
 
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);
 
178
 
 
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);
 
182
 
 
183
        case V4L2_PIX_FMT_RGB24:
 
184
        case V4L2_PIX_FMT_BGR24:
 
185
                return whitebalance_calculate_lookup_tables_rgb(data, buf, fmt);
 
186
        }
 
187
 
 
188
        return 0; /* Should never happen */
191
189
}
192
190
 
193
191
struct v4lprocessing_filter whitebalance_filter = {
194
 
  whitebalance_active, whitebalance_calculate_lookup_tables };
 
192
        whitebalance_active, whitebalance_calculate_lookup_tables
 
193
};