1 /*****************************************************************************
2 * anaglyph.c : Create an image compatible with anaglyph glasses from a 3D video
3 *****************************************************************************
4 * Copyright (C) 2000-2012 VLC authors and VideoLAN
7 * Authors: Antoine Cellerier <dionoea .t videolan d@t org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
28 #include <vlc_common.h>
29 #include <vlc_plugin.h>
30 #include <vlc_filter.h>
31 #include <vlc_picture.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
55 static const char *const ppsz_scheme_values
[] = {
62 static const char *const ppsz_scheme_descriptions
[] = {
63 "pure red (left) pure green (right)",
64 "pure red (left) pure blue (right)",
65 "pure red (left) pure cyan (right)",
66 "pure green (left) pure magenta (right)",
67 "magenta (left) cyan (right)",
71 set_description(N_("Convert 3D picture to anaglyph image video filter"));
72 set_shortname(N_("Anaglyph"))
73 set_category(CAT_VIDEO
)
74 set_subcategory(SUBCAT_VIDEO_VFILTER
)
75 set_capability("video filter", 0)
76 add_string(FILTER_PREFIX
"scheme", "red-cyan", SCHEME_TEXT
, SCHEME_LONGTEXT
, false)
77 change_string_list(ppsz_scheme_values
, ppsz_scheme_descriptions
)
78 set_callbacks(Create
, Destroy
)
81 static const char *const ppsz_filter_options
[] = {
91 static int Create(vlc_object_t
*p_this
)
93 filter_t
*p_filter
= (filter_t
*)p_this
;
95 switch (p_filter
->fmt_in
.video
.i_chroma
)
103 msg_Err(p_filter
, "Unsupported input chroma (%4.4s)",
104 (char*)&(p_filter
->fmt_in
.video
.i_chroma
));
108 p_filter
->p_sys
= malloc(sizeof(filter_sys_t
));
109 if (!p_filter
->p_sys
)
111 filter_sys_t
*p_sys
= p_filter
->p_sys
;
113 config_ChainParse(p_filter
, FILTER_PREFIX
, ppsz_filter_options
,
116 char *psz_scheme
= var_CreateGetStringCommand(p_filter
,
117 FILTER_PREFIX
"scheme");
118 enum scheme_e scheme
= red_cyan
;
121 if (!strcmp(psz_scheme
, "red-green"))
123 else if (!strcmp(psz_scheme
, "red-blue"))
125 else if (!strcmp(psz_scheme
, "red-cyan"))
127 else if (!strcmp(psz_scheme
, "trioscopic"))
129 else if (!strcmp(psz_scheme
, "magenta-cyan"))
130 scheme
= magenta_cyan
;
132 msg_Err(p_filter
, "Unknown anaglyph color scheme '%s'", psz_scheme
);
139 p_sys
->left
= 0xff0000;
140 p_sys
->right
= 0x00ff00;
143 p_sys
->left
= 0xff0000;
144 p_sys
->right
= 0x0000ff;
147 p_sys
->left
= 0xff0000;
148 p_sys
->right
= 0x00ffff;
151 p_sys
->left
= 0x00ff00;
152 p_sys
->right
= 0xff00ff;
155 p_sys
->left
= 0xff00ff;
156 p_sys
->right
= 0x00ffff;
160 p_filter
->pf_video_filter
= Filter
;
164 static void Destroy(vlc_object_t
*p_this
)
166 filter_t
*p_filter
= (filter_t
*)p_this
;
167 filter_sys_t
*p_sys
= p_filter
->p_sys
;
171 static picture_t
*Filter(filter_t
*p_filter
, picture_t
*p_pic
)
173 filter_sys_t
*p_sys
= p_filter
->p_sys
;
178 picture_t
*p_outpic
= filter_NewPicture(p_filter
);
181 picture_Release(p_pic
);
185 switch (p_pic
->format
.i_chroma
)
190 combine_side_by_side_yuv420(p_pic
, p_outpic
,
191 p_sys
->left
, p_sys
->right
);
195 msg_Warn(p_filter
, "Unsupported input chroma (%4.4s)",
196 (char*)&(p_pic
->format
.i_chroma
));
197 picture_Release(p_pic
);
201 return CopyInfoAndRelease(p_outpic
, p_pic
);
205 static void combine_side_by_side_yuv420(picture_t
*p_inpic
, picture_t
*p_outpic
,
208 uint8_t *y1inl
= p_inpic
->p
[Y_PLANE
].p_pixels
;
210 uint8_t *uinl
= p_inpic
->p
[U_PLANE
].p_pixels
;
211 uint8_t *vinl
= p_inpic
->p
[V_PLANE
].p_pixels
;
213 uint8_t *y1out
= p_outpic
->p
[Y_PLANE
].p_pixels
;
215 uint8_t *uout
= p_outpic
->p
[U_PLANE
].p_pixels
;
216 uint8_t *vout
= p_outpic
->p
[V_PLANE
].p_pixels
;
218 const int in_pitch
= p_inpic
->p
[Y_PLANE
].i_pitch
;
219 const int out_pitch
= p_outpic
->p
[Y_PLANE
].i_pitch
;
221 const int visible_pitch
= p_inpic
->p
[Y_PLANE
].i_visible_pitch
;
222 const int visible_lines
= p_inpic
->p
[Y_PLANE
].i_visible_lines
;
223 const int uv_visible_pitch
= p_inpic
->p
[U_PLANE
].i_visible_pitch
;
225 const uint8_t *yend
= y1inl
+ visible_lines
* in_pitch
;
229 uint8_t *y1inr
= y1inl
+ visible_pitch
/2;
231 uint8_t *uinr
= uinl
+ uv_visible_pitch
/2;
232 uint8_t *vinr
= vinl
+ uv_visible_pitch
/2;
234 const uint8_t *y1end
= y1inr
;
235 y2inl
= y1inl
+ in_pitch
;
236 y2inr
= y1inr
+ in_pitch
;
237 y2out
= y1out
+ out_pitch
;
239 while (y1inl
< y1end
)
241 int rl
, gl
, bl
, rr
, gr
, br
, r
, g
, b
;
243 int rshift
= !!((0xff0000&left
) && (0xff0000&right
));
244 int gshift
= !!((0x00ff00&left
) && (0x00ff00&right
));
245 int bshift
= !!((0x0000ff&left
) && (0x0000ff&right
));
247 yuv_to_rgb(&rl
, &gl
, &bl
, *y1inl
, *uinl
, *vinl
);
248 yuv_to_rgb(&rr
, &gr
, &br
, *y1inr
, *uinr
, *vinr
);
249 r
= ((!!(0xff0000&left
))*rl
+ (!!(0xff0000&right
))*rr
)>>rshift
;
250 g
= ((!!(0x00ff00&left
))*gl
+ (!!(0x00ff00&right
))*gr
)>>gshift
;
251 b
= ((!!(0x0000ff&left
))*bl
+ (!!(0x0000ff&right
))*br
)>>bshift
;
252 rgb_to_yuv(y1out
, uout
++, vout
++, r
, g
, b
);
258 yuv_to_rgb(&rl
, &gl
, &bl
, *y1inl
, *uinl
, *vinl
);
259 yuv_to_rgb(&rr
, &gr
, &br
, *y1inr
, *uinr
, *vinr
);
260 r
= ((!!(0xff0000&left
))*rl
+ (!!(0xff0000&right
))*rr
)>>rshift
;
261 g
= ((!!(0x00ff00&left
))*gl
+ (!!(0x00ff00&right
))*gr
)>>gshift
;
262 b
= ((!!(0x0000ff&left
))*bl
+ (!!(0x0000ff&right
))*br
)>>bshift
;
263 rgb_to_yuv(y1out
, uout
++, vout
++, r
, g
, b
);
269 yuv_to_rgb(&rl
, &gl
, &bl
, *y2inl
, *uinl
, *vinl
);
270 yuv_to_rgb(&rr
, &gr
, &br
, *y2inr
, *uinr
, *vinr
);
271 r
= ((!!(0xff0000&left
))*rl
+ (!!(0xff0000&right
))*rr
)>>rshift
;
272 g
= ((!!(0x00ff00&left
))*gl
+ (!!(0x00ff00&right
))*gr
)>>gshift
;
273 b
= ((!!(0x0000ff&left
))*bl
+ (!!(0x0000ff&right
))*br
)>>bshift
;
274 rgb_to_yuv(y2out
, uout
/*will be overwritten later, as will vout*/, vout
, r
, g
, b
);
280 yuv_to_rgb(&rl
, &gl
, &bl
, *y2inl
, *uinl
, *vinl
);
281 yuv_to_rgb(&rr
, &gr
, &br
, *y2inr
, *uinr
, *vinr
);
282 r
= ((!!(0xff0000&left
))*rl
+ (!!(0xff0000&right
))*rr
)>>rshift
;
283 g
= ((!!(0x00ff00&left
))*gl
+ (!!(0x00ff00&right
))*gr
)>>gshift
;
284 b
= ((!!(0x0000ff&left
))*bl
+ (!!(0x0000ff&right
))*br
)>>bshift
;
285 rgb_to_yuv(y2out
, uout
/*will be overwritten later, as will vout*/, vout
, r
, g
, b
);
297 y1inl
= y1inr
+ 2*in_pitch
- visible_pitch
;
298 y1out
+= 2*out_pitch
- visible_pitch
;
299 uinl
= uinr
+ p_inpic
->p
[U_PLANE
].i_pitch
- uv_visible_pitch
;
300 vinl
= vinr
+ p_inpic
->p
[V_PLANE
].i_pitch
- uv_visible_pitch
;
301 uout
+= p_outpic
->p
[U_PLANE
].i_pitch
- uv_visible_pitch
;
302 vout
+= p_outpic
->p
[V_PLANE
].i_pitch
- uv_visible_pitch
;