comparison libmpcodecs/vf_eq2.c @ 7517:9d433771b6d0

-vf eq2, LUT-based brightness/contrast/gamma correction (Y-only) by Hampa Hug <hhug@student.ethz.ch>
author arpi
date Fri, 27 Sep 2002 21:08:36 +0000
parents
children b667328dc62e
comparison
equal deleted inserted replaced
7516:657041b7236b 7517:9d433771b6d0
1 /*
2 * vf_eq2.c
3 *
4 * Extended software equalizer (brightness, contrast, gamma)
5 *
6 * Hampa Hug <hhug@student.ethz.ch>
7 *
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <math.h>
14
15 #include "../config.h"
16 #include "../mp_msg.h"
17
18 #include "img_format.h"
19 #include "mp_image.h"
20 #include "vf.h"
21
22
23 typedef struct vf_priv_s {
24 unsigned char *buf;
25 int buf_w;
26 int buf_h;
27
28 double contrast;
29 double bright;
30 double gamma;
31
32 unsigned char lut[256];
33 } vf_eq2_t;
34
35
36 static
37 void create_lut (vf_eq2_t *eq2)
38 {
39 unsigned i;
40 double c, b, g;
41 double v;
42
43 c = eq2->contrast;
44 b = eq2->bright;
45 g = eq2->gamma;
46
47 if ((g < 0.001) || (g > 1000.0)) {
48 g = 1.0;
49 }
50
51 fprintf (stderr, "vf_eq2: c=%.2f b=%.2f g=%.4f\n", c, b, g);
52
53 g = 1.0 / g;
54
55 for (i = 0; i < 256; i++) {
56 v = (double) i / 255.0;
57 v = c * (v - 0.5) + 0.5 + b;
58
59 if (v <= 0.0) {
60 eq2->lut[i] = 0;
61 }
62 else {
63 v = pow (v, g);
64
65 if (v >= 1.0) {
66 eq2->lut[i] = 255;
67 }
68 else {
69 eq2->lut[i] = (unsigned char) (256.0 * v);
70 }
71 }
72 }
73 }
74
75 /* could inline this */
76 static
77 void process (unsigned char *dst, int dstride, unsigned char *src, int sstride,
78 int w, int h, unsigned char lut[256])
79 {
80 int i, j;
81
82 for (j = 0; j < h; j++) {
83 for (i = 0; i < w; i++) {
84 *(dst++) = lut[*(src++)];
85 }
86
87 src += sstride - w;
88 dst += dstride - w;
89 }
90 }
91
92 static
93 int put_image (vf_instance_t *vf, mp_image_t *src)
94 {
95 mp_image_t *dst;
96 vf_eq2_t *eq2;
97
98 eq2 = vf->priv;
99
100 if ((eq2->buf == NULL) || (eq2->buf_w != src->stride[0]) || (eq2->buf_h != src->h)) {
101 eq2->buf = (unsigned char *) realloc (eq2->buf, src->stride[0] * src->h);
102 eq2->buf_w = src->stride[0];
103 eq2->buf_h = src->h;
104 }
105
106 dst = vf_get_image (vf->next, src->imgfmt, MP_IMGTYPE_EXPORT, 0, src->w, src->h);
107
108 dst->stride[0] = src->stride[0];
109 dst->stride[1] = src->stride[1];
110 dst->stride[2] = src->stride[2];
111 dst->planes[0] = vf->priv->buf;
112 dst->planes[1] = src->planes[1];
113 dst->planes[2] = src->planes[2];
114
115 process (
116 dst->planes[0], dst->stride[0], src->planes[0], src->stride[0],
117 src->w, src->h, eq2->lut
118 );
119
120 return vf_next_put_image (vf, dst);
121 }
122
123 static
124 int control (vf_instance_t *vf, int request, void *data)
125 {
126 vf_equalizer_t *eq;
127
128 switch (request) {
129 case VFCTRL_SET_EQUALIZER:
130 eq = (vf_equalizer_t *) data;
131
132 if (strcmp (eq->item, "gamma") == 0) {
133 vf->priv->gamma = exp (log (8.0) * eq->value / 100.0);
134 create_lut (vf->priv);
135 return CONTROL_TRUE;
136 }
137 else if (strcmp (eq->item, "contrast") == 0) {
138 vf->priv->contrast = (1.0 / 100.0) * (eq->value + 100);
139 create_lut (vf->priv);
140 return CONTROL_TRUE;
141 }
142 else if (strcmp (eq->item, "brightness") == 0) {
143 vf->priv->bright = (1.0 / 100.0) * eq->value;
144 create_lut (vf->priv);
145 return CONTROL_TRUE;
146 }
147 break;
148
149 case VFCTRL_GET_EQUALIZER:
150 eq = (vf_equalizer_t *) data;
151 if (strcmp (eq->item, "gamma") == 0) {
152 eq->value = (int) (100.0 * log (vf->priv->gamma) / log (8.0));
153 return CONTROL_TRUE;
154 }
155 else if (strcmp (eq->item, "contrast") == 0) {
156 eq->value = (int) (100.0 * vf->priv->contrast) - 100;
157 return CONTROL_TRUE;
158 }
159 else if (strcmp (eq->item, "brightness") == 0) {
160 eq->value = (int) (100.0 * vf->priv->bright);
161 return CONTROL_TRUE;
162 }
163 break;
164 }
165
166 return vf_next_control (vf, request, data);
167 }
168
169 static
170 int query_format (vf_instance_t *vf, unsigned fmt)
171 {
172 switch (fmt) {
173 case IMGFMT_YVU9:
174 case IMGFMT_IF09:
175 case IMGFMT_YV12:
176 case IMGFMT_I420:
177 case IMGFMT_IYUV:
178 case IMGFMT_CLPL:
179 case IMGFMT_Y800:
180 case IMGFMT_Y8:
181 case IMGFMT_NV12:
182 case IMGFMT_444P:
183 case IMGFMT_422P:
184 case IMGFMT_411P:
185 return vf_next_query_format (vf, fmt);
186 }
187
188 return 0;
189 }
190
191 static
192 void uninit (vf_instance_t *vf)
193 {
194 if (vf->priv != NULL) {
195 free (vf->priv->buf);
196 free (vf->priv);
197 }
198 }
199
200 static
201 int open (vf_instance_t *vf, char *args)
202 {
203 vf_eq2_t *eq2;
204
205 vf->control = control;
206 vf->query_format = query_format;
207 vf->put_image = put_image;
208 vf->uninit = uninit;
209
210 vf->priv = (vf_eq2_t *) malloc (sizeof (vf_eq2_t));
211 eq2 = vf->priv;
212
213 eq2->buf = NULL;
214 eq2->buf_w = 0;
215 eq2->buf_h = 0;
216
217 eq2->gamma = 1.0;
218 eq2->contrast = 1.0;
219 eq2->bright = 0.0;
220
221 if (args != NULL) {
222 sscanf (args, "%lf:%lf:%lf", &eq2->gamma, &eq2->contrast, &eq2->bright);
223 }
224
225 create_lut (eq2);
226
227 return 1;
228 }
229
230 vf_info_t vf_info_eq2 = {
231 "extended software equalizer",
232 "eq2",
233 "Hampa Hug",
234 "",
235 &open
236 };