1 /*****************************************************************************
2 * anaglyph.c : Create an image compatible with anaglyph glasses from a 3D video
3 *****************************************************************************
4 * Copyright (C) 2000-2012 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea .t videolan d@t org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
28 #include <vlc_common.h>
29 #include <vlc_plugin.h>
31 #include <vlc_filter.h>
32 #include "filter_picture.h"
34 static int Create(vlc_object_t *);
35 static void Destroy(vlc_object_t *);
36 static picture_t *Filter(filter_t *, picture_t *);
37 static void combine_side_by_side_yuv420(picture_t *, picture_t *, int, int);
39 #define SCHEME_TEXT N_("Color scheme")
40 #define SCHEME_LONGTEXT N_("Define the glasses' color scheme")
42 #define FILTER_PREFIX "anaglyph-"
44 /* See http://en.wikipedia.org/wiki/Anaglyph_image for a list of known
56 static const char *const ppsz_scheme_values[] = {
63 static const char *const ppsz_scheme_descriptions[] = {
64 "pure red (left) pure green (right)",
65 "pure red (left) pure blue (right)",
66 "pure red (left) pure cyan (right)",
67 "pure green (left) pure magenta (right)",
68 "magenta (left) cyan (right)",
72 set_description(N_("Convert 3D picture to anaglyph image video filter"));
73 set_shortname(N_("Anaglyph"))
74 set_category(CAT_VIDEO)
75 set_subcategory(SUBCAT_VIDEO_VFILTER)
76 set_capability("video filter2", 0)
77 add_string(FILTER_PREFIX "scheme", "red-cyan", SCHEME_TEXT, SCHEME_LONGTEXT, false)
78 change_string_list(ppsz_scheme_values, ppsz_scheme_descriptions)
79 set_callbacks(Create, Destroy)
82 static const char *const ppsz_filter_options[] = {
92 static int Create(vlc_object_t *p_this)
95 filter_t *p_filter = (filter_t *)p_this;
97 switch (p_filter->fmt_in.video.i_chroma)
105 msg_Err(p_filter, "Unsupported input chroma (%4.4s)",
106 (char*)&(p_filter->fmt_in.video.i_chroma));
110 p_filter->p_sys = malloc(sizeof(filter_sys_t));
111 if (!p_filter->p_sys)
113 filter_sys_t *p_sys = p_filter->p_sys;
115 config_ChainParse(p_filter, FILTER_PREFIX, ppsz_filter_options,
118 char *psz_scheme = var_CreateGetStringCommand(p_filter,
119 FILTER_PREFIX "scheme");
120 enum scheme_e scheme = red_cyan;
123 if (!strcmp(psz_scheme, "red-green"))
125 else if (!strcmp(psz_scheme, "red-blue"))
127 else if (!strcmp(psz_scheme, "red-cyan"))
129 else if (!strcmp(psz_scheme, "trioscopic"))
131 else if (!strcmp(psz_scheme, "magenta-cyan"))
132 scheme = magenta_cyan;
134 msg_Err(p_filter, "Unknown anaglyph color scheme '%s'", psz_scheme);
141 p_sys->left = 0xff0000;
142 p_sys->right = 0x00ff00;
145 p_sys->left = 0xff0000;
146 p_sys->right = 0x0000ff;
149 p_sys->left = 0xff0000;
150 p_sys->right = 0x00ffff;
153 p_sys->left = 0x00ff00;
154 p_sys->right = 0xff00ff;
157 p_sys->left = 0xff00ff;
158 p_sys->right = 0x00ffff;
161 msg_Err(p_filter, "Oops");
165 p_filter->pf_video_filter = Filter;
169 static void Destroy(vlc_object_t *p_this)
171 filter_t *p_filter = (filter_t *)p_this;
172 filter_sys_t *p_sys = p_filter->p_sys;
176 static picture_t *Filter(filter_t *p_filter, picture_t *p_pic)
178 filter_sys_t *p_sys = p_filter->p_sys;
183 picture_t *p_outpic = filter_NewPicture(p_filter);
186 picture_Release(p_pic);
190 switch (p_pic->format.i_chroma)
195 combine_side_by_side_yuv420(p_pic, p_outpic,
196 p_sys->left, p_sys->right);
200 msg_Warn(p_filter, "Unsupported input chroma (%4.4s)",
201 (char*)&(p_pic->format.i_chroma));
202 picture_Release(p_pic);
206 return CopyInfoAndRelease(p_outpic, p_pic);
210 static void combine_side_by_side_yuv420(picture_t *p_inpic, picture_t *p_outpic,
213 uint8_t *y1inl = p_inpic->p[Y_PLANE].p_pixels;
215 uint8_t *uinl = p_inpic->p[U_PLANE].p_pixels;
216 uint8_t *vinl = p_inpic->p[V_PLANE].p_pixels;
218 uint8_t *y1out = p_outpic->p[Y_PLANE].p_pixels;
220 uint8_t *uout = p_outpic->p[U_PLANE].p_pixels;
221 uint8_t *vout = p_outpic->p[V_PLANE].p_pixels;
223 const int in_pitch = p_inpic->p[Y_PLANE].i_pitch;
224 const int out_pitch = p_outpic->p[Y_PLANE].i_pitch;
226 const int visible_pitch = p_inpic->p[Y_PLANE].i_visible_pitch;
227 const int visible_lines = p_inpic->p[Y_PLANE].i_visible_lines;
228 const int uv_visible_pitch = p_inpic->p[U_PLANE].i_visible_pitch;
230 const uint8_t *yend = y1inl + visible_lines * in_pitch;
234 uint8_t *y1inr = y1inl + visible_pitch/2;
236 uint8_t *uinr = uinl + uv_visible_pitch/2;
237 uint8_t *vinr = vinl + uv_visible_pitch/2;
239 const uint8_t *y1end = y1inr;
240 y2inl = y1inl + in_pitch;
241 y2inr = y1inr + in_pitch;
242 y2out = y1out + out_pitch;
244 while (y1inl < y1end)
246 int rl, gl, bl, rr, gr, br, r, g, b;
248 int rshift = !!((0xff0000&left) && (0xff0000&right));
249 int gshift = !!((0x00ff00&left) && (0x00ff00&right));
250 int bshift = !!((0x0000ff&left) && (0x0000ff&right));
252 yuv_to_rgb(&rl, &gl, &bl, *y1inl, *uinl, *vinl);
253 yuv_to_rgb(&rr, &gr, &br, *y1inr, *uinr, *vinr);
254 r = ((!!(0xff0000&left))*rl + (!!(0xff0000&right))*rr)>>rshift;
255 g = ((!!(0x00ff00&left))*gl + (!!(0x00ff00&right))*gr)>>gshift;
256 b = ((!!(0x0000ff&left))*bl + (!!(0x0000ff&right))*br)>>bshift;
257 rgb_to_yuv(y1out, uout++, vout++, r, g, b);
263 yuv_to_rgb(&rl, &gl, &bl, *y1inl, *uinl, *vinl);
264 yuv_to_rgb(&rr, &gr, &br, *y1inr, *uinr, *vinr);
265 r = ((!!(0xff0000&left))*rl + (!!(0xff0000&right))*rr)>>rshift;
266 g = ((!!(0x00ff00&left))*gl + (!!(0x00ff00&right))*gr)>>gshift;
267 b = ((!!(0x0000ff&left))*bl + (!!(0x0000ff&right))*br)>>bshift;
268 rgb_to_yuv(y1out, uout++, vout++, r, g, b);
274 yuv_to_rgb(&rl, &gl, &bl, *y2inl, *uinl, *vinl);
275 yuv_to_rgb(&rr, &gr, &br, *y2inr, *uinr, *vinr);
276 r = ((!!(0xff0000&left))*rl + (!!(0xff0000&right))*rr)>>rshift;
277 g = ((!!(0x00ff00&left))*gl + (!!(0x00ff00&right))*gr)>>gshift;
278 b = ((!!(0x0000ff&left))*bl + (!!(0x0000ff&right))*br)>>bshift;
279 rgb_to_yuv(y2out, uout/*will be overwritten later, as will vout*/, vout, r, g, b);
285 yuv_to_rgb(&rl, &gl, &bl, *y2inl, *uinl, *vinl);
286 yuv_to_rgb(&rr, &gr, &br, *y2inr, *uinr, *vinr);
287 r = ((!!(0xff0000&left))*rl + (!!(0xff0000&right))*rr)>>rshift;
288 g = ((!!(0x00ff00&left))*gl + (!!(0x00ff00&right))*gr)>>gshift;
289 b = ((!!(0x0000ff&left))*bl + (!!(0x0000ff&right))*br)>>bshift;
290 rgb_to_yuv(y2out, uout/*will be overwritten later, as will vout*/, vout, r, g, b);
302 y1inl = y1inr + 2*in_pitch - visible_pitch;
303 y1out += 2*out_pitch - visible_pitch;
304 uinl = uinr + p_inpic->p[U_PLANE].i_pitch - uv_visible_pitch;
305 vinl = vinr + p_inpic->p[V_PLANE].i_pitch - uv_visible_pitch;
306 uout += p_outpic->p[U_PLANE].i_pitch - uv_visible_pitch;
307 vout += p_outpic->p[V_PLANE].i_pitch - uv_visible_pitch;