]> git.sesse.net Git - mlt/blob - src/modules/plusgpl/image.c
Start new plusgpl module from dgraft.
[mlt] / src / modules / plusgpl / image.c
1 /*
2  * EffecTV - Realtime Digital Video Effector
3  * Copyright (C) 2001-2006 FUKUCHI Kentaro
4  *
5  * image.c: utilities for image processing.
6  *
7  */
8
9 #include <string.h>
10 #include <stdlib.h>
11 #include "utils.h"
12
13
14 /*
15  * Collection of background subtraction functions
16  */
17
18 /* checks only fake-Y value */
19 /* In these function Y value is treated as R*2+G*4+B. */
20
21 int image_set_threshold_y(int threshold)
22 {
23         int y_threshold = threshold * 7; /* fake-Y value is timed by 7 */
24
25         return y_threshold;
26 }
27
28 void image_bgset_y(RGB32 *background, const RGB32 *src, int video_area, int y_threshold)
29 {
30         int i;
31         int R, G, B;
32         const RGB32 *p;
33         short *q;
34
35         p = src;
36         q = (short *)background;
37         for(i=0; i<video_area; i++) {
38                 /* FIXME: endianess */
39
40                 R = ((*p)&0xff0000)>>(16-1);
41                 G = ((*p)&0xff00)>>(8-2);
42                 B = (*p)&0xff;
43                 *q = (short)(R + G + B);
44                 p++;
45                 q++;
46         }
47 }
48
49 void image_bgsubtract_y(unsigned char *diff, const RGB32 *background, const RGB32 *src, int video_area, int y_threshold)
50 {
51         int i;
52         int R, G, B;
53         const RGB32 *p;
54         const short *q;
55         unsigned char *r;
56         int v;
57
58         p = src;
59         q = (const short *)background;
60         r = diff;
61         for(i=0; i<video_area; i++) {
62                 /* FIXME: endianess */
63
64                 R = ((*p)&0xff0000)>>(16-1);
65                 G = ((*p)&0xff00)>>(8-2);
66                 B = (*p)&0xff;
67                 v = (R + G + B) - (int)(*q);
68                 *r = ((v + y_threshold)>>24) | ((y_threshold - v)>>24);
69
70                 p++;
71                 q++;
72                 r++;
73         }
74
75 /* The origin of subtraction function is;
76  * diff(src, dest) = (abs(src - dest) > threshold) ? 0xff : 0;
77  *
78  * This functions is transformed to;
79  * (threshold > (src - dest) > -threshold) ? 0 : 0xff;
80  *
81  * (v + threshold)>>24 is 0xff when v is less than -threshold.
82  * (v - threshold)>>24 is 0xff when v is less than threshold.
83  * So, ((v + threshold)>>24) | ((threshold - v)>>24) will become 0xff when
84  * abs(src - dest) > threshold.
85  */
86 }
87
88 /* Background image is refreshed every frame */
89 void image_bgsubtract_update_y(unsigned char *diff, RGB32 *background, const RGB32 *src, int video_area, int y_threshold)
90 {
91         int i;
92         int R, G, B;
93         const RGB32 *p;
94         short *q;
95         unsigned char *r;
96         int v;
97
98         p = src;
99         q = (short *)background;
100         r = diff;
101         for(i=0; i<video_area; i++) {
102                 /* FIXME: endianess */
103
104                 R = ((*p)&0xff0000)>>(16-1);
105                 G = ((*p)&0xff00)>>(8-2);
106                 B = (*p)&0xff;
107                 v = (R + G + B) - (int)(*q);
108                 *q = (short)(R + G + B);
109                 *r = ((v + y_threshold)>>24) | ((y_threshold - v)>>24);
110
111                 p++;
112                 q++;
113                 r++;
114         }
115 }
116
117 /* checks each RGB value */
118
119 /* The range of r, g, b are [0..7] */
120 RGB32 image_set_threshold_RGB(int r, int g, int b)
121 {
122         unsigned char R, G, B;
123         RGB32 rgb_threshold;
124
125         R = G = B = 0xff;
126         R = R<<r;
127         G = G<<g;
128         B = B<<b;
129         rgb_threshold = (RGB32)(R<<16 | G<<8 | B);
130
131         return rgb_threshold;
132 }
133
134 void image_bgset_RGB(RGB32 *background, const RGB32 *src, int video_area)
135 {
136         int i;
137         RGB32 *p;
138
139         p = background;
140         for(i=0; i<video_area; i++) {
141                 *p++ = (*src++) & 0xfefefe;
142         }
143 }
144
145 void image_bgsubtract_RGB(unsigned char *diff, const RGB32 *background, const RGB32 *src, int video_area, RGB32 rgb_threshold)
146 {
147         int i;
148         const RGB32 *p, *q;
149         unsigned a, b;
150         unsigned char *r;
151
152         p = src;
153         q = background;
154         r = diff;
155         for(i=0; i<video_area; i++) {
156                 a = (*p++)|0x1010100;
157                 b = *q++;
158                 a = a - b;
159                 b = a & 0x1010100;
160                 b = b - (b>>8);
161                 b = b ^ 0xffffff;
162                 a = a ^ b;
163                 a = a & rgb_threshold;
164                 *r++ = (0 - a)>>24;
165         }
166 }
167
168 void image_bgsubtract_update_RGB(unsigned char *diff, RGB32 *background, const RGB32 *src, int video_area, RGB32 rgb_threshold)
169 {
170         int i;
171         const RGB32 *p;
172         RGB32 *q;
173         unsigned a, b;
174         unsigned char *r;
175
176         p = src;
177         q = background;
178         r = diff;
179         for(i=0; i<video_area; i++) {
180                 a = *p|0x1010100;
181                 b = *q&0xfefefe;
182                 *q++ = *p++;
183                 a = a - b;
184                 b = a & 0x1010100;
185                 b = b - (b>>8);
186                 b = b ^ 0xffffff;
187                 a = a ^ b;
188                 a = a & rgb_threshold;
189                 *r++ = (0 - a)>>24;
190         }
191 }
192
193 /* noise filter for subtracted image. */
194 void image_diff_filter(unsigned char *diff2, const unsigned char *diff, int width, int height)
195 {
196         int x, y;
197         const unsigned char *src;
198         unsigned char *dest;
199         unsigned int count;
200         unsigned int sum1, sum2, sum3;
201
202         src = diff;
203         dest = diff2 + width +1;
204         for(y=1; y<height-1; y++) {
205                 sum1 = src[0] + src[width] + src[width*2];
206                 sum2 = src[1] + src[width+1] + src[width*2+1];
207                 src += 2;
208                 for(x=1; x<width-1; x++) {
209                         sum3 = src[0] + src[width] + src[width*2];
210                         count = sum1 + sum2 + sum3;
211                         sum1 = sum2;
212                         sum2 = sum3;
213                         *dest++ = (0xff*3 - count)>>24;
214                         src++;
215                 }
216                 dest += 2;
217         }
218 }
219
220 /* Y value filters */
221 void image_y_over(unsigned char *diff, const RGB32 *src, int video_area, int y_threshold)
222 {
223         int i;
224         int R, G, B, v;
225         unsigned char *p = diff;
226
227         for(i = video_area; i>0; i--) {
228                 R = ((*src)&0xff0000)>>(16-1);
229                 G = ((*src)&0xff00)>>(8-2);
230                 B = (*src)&0xff;
231                 v = y_threshold - (R + G + B);
232                 *p = (unsigned char)(v>>24);
233                 src++;
234                 p++;
235         }
236 }
237
238 void image_y_under(unsigned char *diff, const RGB32 *src, int video_area, int y_threshold)
239 {
240         int i;
241         int R, G, B, v;
242         unsigned char *p = diff;
243
244         for(i = video_area; i>0; i--) {
245                 R = ((*src)&0xff0000)>>(16-1);
246                 G = ((*src)&0xff00)>>(8-2);
247                 B = (*src)&0xff;
248                 v = (R + G + B) - y_threshold;
249                 *p = (unsigned char)(v>>24);
250                 src++;
251                 p++;
252         }
253 }
254
255 /* tiny edge detection */
256 void image_edge(unsigned char *diff2, const RGB32 *src, int width, int height, int y_threshold)
257 {
258         int x, y;
259         const unsigned char *p;
260         unsigned char *q;
261         int r, g, b;
262         int ar, ag, ab;
263         int w;
264
265         p = (const unsigned char *)src;
266         q = diff2;
267         w = width * sizeof(RGB32);
268
269         for(y=0; y<height - 1; y++) {
270                 for(x=0; x<width - 1; x++) {
271                         b = p[0];
272                         g = p[1];
273                         r = p[2];
274                         ab = abs(b - p[4]);
275                         ag = abs(g - p[5]);
276                         ar = abs(r - p[6]);
277                         ab += abs(b - p[w]);
278                         ag += abs(g - p[w+1]);
279                         ar += abs(r - p[w+2]);
280                         b = ab+ag+ar;
281                         if(b > y_threshold) {
282                                 *q = 255;
283                         } else {
284                                 *q = 0;
285                         }
286                         q++;
287                         p += 4;
288                 }
289                 p += 4;
290                 *q++ = 0;
291         }
292         memset(q, 0, width);
293 }
294
295 /* horizontal flipping */
296 void image_hflip(const RGB32 *src, RGB32 *dest, int width, int height)
297 {
298         int x, y;
299
300         src += width - 1;
301         for(y=0; y<height; y++) {
302                 for(x=0; x<width; x++) {
303                         *dest++ = *src--;
304                 }
305                 src += width * 2;
306         }
307 }
308