r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / yuv / yuv.C
blobd54414ab0e471b5935d4602041b295a0bcb89828
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "defaults.h"
4 #include "filexml.h"
5 #include "guicast.h"
6 #include "picon_png.h"
7 #include "plugincolors.h"
8 #include "pluginvclient.h"
9 #include "vframe.h"
11 #include <stdint.h>
12 #include <string.h>
14 #include <libintl.h>
15 #define _(String) gettext(String)
16 #define gettext_noop(String) String
17 #define N_(String) gettext_noop (String)
20 class YUVEffect;
23 class YUVConfig
25 public:
26         YUVConfig();
28         void copy_from(YUVConfig &src);
29         int equivalent(YUVConfig &src);
30         void interpolate(YUVConfig &prev, 
31                 YUVConfig &next, 
32                 long prev_frame, 
33                 long next_frame, 
34                 long current_frame);
36         float y, u, v;
39 class YUVLevel : public BC_FSlider
41 public:
42         YUVLevel(YUVEffect *plugin, float *output, int x, int y);
43         int handle_event();
44         YUVEffect *plugin;
45         float *output;
48 class YUVWindow : public BC_Window
50 public:
51         YUVWindow(YUVEffect *plugin, int x, int y);
52         void create_objects();
53         int close_event();
54         YUVLevel *y, *u, *v;
55         YUVEffect *plugin;
58 PLUGIN_THREAD_HEADER(YUVEffect, YUVThread, YUVWindow)
60 class YUVEffect : public PluginVClient
62 public:
63         YUVEffect(PluginServer *server);
64         ~YUVEffect();
65         int process_realtime(VFrame *input, VFrame *output);
66         int is_realtime();
67         char* plugin_title();
68         VFrame* new_picon();
69         int load_defaults();
70         int save_defaults();
71         void save_data(KeyFrame *keyframe);
72         void read_data(KeyFrame *keyframe);
73         void update_gui();
74         int show_gui();
75         void raise_window();
76         int set_string();
77         int load_configuration();
79         YUVConfig config;
80         YUVThread *thread;
81         Defaults *defaults;
88 REGISTER_PLUGIN(YUVEffect)
96 YUVConfig::YUVConfig()
98         y = 0;
99         u = 0;
100         v = 0;
103 void YUVConfig::copy_from(YUVConfig &src)
105         y = src.y;
106         u = src.u;
107         v = src.v;
110 int YUVConfig::equivalent(YUVConfig &src)
112         return EQUIV(y, src.y) && EQUIV(u, src.u) && EQUIV(v, src.v);
115 void YUVConfig::interpolate(YUVConfig &prev, 
116         YUVConfig &next, 
117         long prev_frame, 
118         long next_frame, 
119         long current_frame)
121         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
122         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
124         y = prev.y * prev_scale + next.y * next_scale;
125         u = prev.u * prev_scale + next.u * next_scale;
126         v = prev.v * prev_scale + next.v * next_scale;
134 #define MAXVALUE 100
136 YUVLevel::YUVLevel(YUVEffect *plugin, float *output, int x, int y)
137  : BC_FSlider(x, 
138                         y,
139                         0,
140                         200, 
141                         200, 
142                         -MAXVALUE, 
143                         MAXVALUE, 
144                         *output)
146         this->plugin = plugin;
147         this->output = output;
150 int YUVLevel::handle_event()
152         *output = get_value();
153         plugin->send_configure_change();
154         return 1;
158 YUVWindow::YUVWindow(YUVEffect *plugin, int x, int y)
159  : BC_Window(plugin->gui_string, 
160         x, 
161         y, 
162         260, 
163         100, 
164         260, 
165         100, 
166         0, 
167         0,
168         1)
170         this->plugin = plugin;
173 void YUVWindow::create_objects()
175         int x = 10, y = 10, x1 = 50;
176         add_subwindow(new BC_Title(x, y, _("Y:")));
177         add_subwindow(this->y = new YUVLevel(plugin, &plugin->config.y, x1, y));
178         y += 30;
179         add_subwindow(new BC_Title(x, y, _("U:")));
180         add_subwindow(u = new YUVLevel(plugin, &plugin->config.u, x1, y));
181         y += 30;
182         add_subwindow(new BC_Title(x, y, _("V:")));
183         add_subwindow(v = new YUVLevel(plugin, &plugin->config.v, x1, y));
185         show_window();
186         flush();
189 int YUVWindow::close_event()
191 // Set result to 1 to indicate a client side close
192         set_done(1);
193         return 1;
200 PLUGIN_THREAD_OBJECT(YUVEffect, YUVThread, YUVWindow)
207 YUVEffect::YUVEffect(PluginServer *server)
208  : PluginVClient(server)
210         PLUGIN_CONSTRUCTOR_MACRO
212 YUVEffect::~YUVEffect()
214         PLUGIN_DESTRUCTOR_MACRO
216 int YUVEffect::is_realtime()
218         return 1;
221 char* YUVEffect::plugin_title()
223         return _("YUV");
226 NEW_PICON_MACRO(YUVEffect)
227 SHOW_GUI_MACRO(YUVEffect, YUVThread)
228 RAISE_WINDOW_MACRO(YUVEffect)
229 SET_STRING_MACRO(YUVEffect)
230 LOAD_CONFIGURATION_MACRO(YUVEffect, YUVConfig)
232 void YUVEffect::update_gui()
234         if(thread)
235         {
236                 thread->window->lock_window();
237                 load_configuration();
238                 thread->window->y->update(config.y);
239                 thread->window->u->update(config.u);
240                 thread->window->v->update(config.v);
241                 thread->window->unlock_window();
242         }
245 int YUVEffect::load_defaults()
247         char directory[BCTEXTLEN];
248         sprintf(directory, "%syuv.rc", BCASTDIR);
249         defaults = new Defaults(directory);
250         defaults->load();
251         config.y = defaults->get("Y", config.y);
252         config.u = defaults->get("U", config.u);
253         config.v = defaults->get("V", config.v);
254         return 0;
257 int YUVEffect::save_defaults()
259         defaults->update("Y", config.y);
260         defaults->update("U", config.u);
261         defaults->update("V", config.v);
262         defaults->save();
263         return 0;
266 void YUVEffect::save_data(KeyFrame *keyframe)
268         FileXML output;
269         output.set_shared_string(keyframe->data, MESSAGESIZE);
270         output.tag.set_title("YUV");
271         output.tag.set_property("Y", config.y);
272         output.tag.set_property("U", config.u);
273         output.tag.set_property("V", config.v);
274         output.append_tag();
275         output.terminate_string();
278 void YUVEffect::read_data(KeyFrame *keyframe)
280         FileXML input;
281         input.set_shared_string(keyframe->data, strlen(keyframe->data));
282         while(!input.read_tag())
283         {
284                 if(input.tag.title_is("YUV"))
285                 {
286                         config.y = input.tag.get_property("Y", config.y);
287                         config.u = input.tag.get_property("U", config.u);
288                         config.v = input.tag.get_property("V", config.v);
289                 }
290         }
294 static YUV yuv_static;
296 #define YUV_MACRO(type, max, components, use_yuv) \
297 { \
298         for(int i = 0; i < input->get_h(); i++) \
299         { \
300                 type *in_row = (type*)input->get_rows()[i]; \
301                 type *out_row = (type*)output->get_rows()[i]; \
303                 for(int j = 0; j < w; j++) \
304                 { \
305                         if(use_yuv) \
306                         { \
307                                 int y = (int)((float)in_row[0] * y_scale + 0.5); \
308                                 int u = (int)((float)(in_row[1] - (max / 2 + 1)) * u_scale + 0.5) + (max / 2 + 1); \
309                                 int v = (int)((float)(in_row[2] - (max / 2 + 1)) * v_scale + 0.5) + (max / 2 + 1); \
310                                 out_row[0] = CLIP(y, 0, max); \
311                                 out_row[1] = CLIP(u, 0, max); \
312                                 out_row[2] = CLIP(v, 0, max); \
313                         } \
314                         else \
315                         { \
316                                 int y, u, v, r, g, b; \
317                                 if(max == 0xff) \
318                                         yuv_static.rgb_to_yuv_8(in_row[0], in_row[1], in_row[2], y, u, v); \
319                                 else \
320                                         yuv_static.rgb_to_yuv_16(in_row[0], in_row[1], in_row[2], y, u, v); \
322                                 y = (int)((float)y * y_scale + 0.5); \
323                                 u = (int)((float)(u - (max / 2 + 1)) * u_scale + 0.5) + (max / 2 + 1); \
324                                 v = (int)((float)(v - (max / 2 + 1)) * v_scale + 0.5) + (max / 2 + 1); \
326                                 CLAMP(y, 0, max); \
327                                 CLAMP(u, 0, max); \
328                                 CLAMP(v, 0, max); \
330                                 if(max == 0xff) \
331                                         yuv_static.yuv_to_rgb_8(r, g, b, y, u, v); \
332                                 else \
333                                         yuv_static.yuv_to_rgb_16(r, g, b, y, u, v); \
335                                 out_row[0] = r; \
336                                 out_row[1] = g; \
337                                 out_row[2] = b; \
338                         } \
339                  \
340                         if(components == 4) \
341                                 out_row[3] = in_row[3]; \
342                         in_row += components; \
343                         out_row += components; \
344                 } \
345         } \
348 int YUVEffect::process_realtime(VFrame *input, VFrame *output)
350         load_configuration();
351         
352         if(EQUIV(config.y, 0) && EQUIV(config.u, 0) && EQUIV(config.v, 0))
353         {
354                 if(input->get_rows()[0] != output->get_rows()[0])
355                         output->copy_from(input);
356         }
357         else
358         {
359                 int w = input->get_w();
361                 float y_scale = (float)(config.y + MAXVALUE) / MAXVALUE;
362                 float u_scale = (float)(config.u + MAXVALUE) / MAXVALUE;
363                 float v_scale = (float)(config.v + MAXVALUE) / MAXVALUE;
365                 if(u_scale > 1) u_scale = 1 + (u_scale - 1) * 4;
366                 if(v_scale > 1) v_scale = 1 + (v_scale - 1) * 4;
368                 switch(input->get_color_model())
369                 {
370                         case BC_RGB888:
371                                 YUV_MACRO(unsigned char, 0xff, 3, 0)
372                                 break;
374                         case BC_YUV888:
375                                 YUV_MACRO(unsigned char, 0xff, 3, 1)
376                                 break;
378                         case BC_RGB161616:
379                                 YUV_MACRO(uint16_t, 0xffff, 3, 0)
380                                 break;
382                         case BC_YUV161616:
383                                 YUV_MACRO(uint16_t, 0xffff, 3, 1)
384                                 break;
386                         case BC_RGBA8888:
387                                 YUV_MACRO(unsigned char, 0xff, 4, 0)
388                                 break;
390                         case BC_YUVA8888:
391                                 YUV_MACRO(unsigned char, 0xff, 4, 1)
392                                 break;
394                         case BC_RGBA16161616:
395                                 YUV_MACRO(uint16_t, 0xffff, 4, 0)
396                                 break;
398                         case BC_YUVA16161616:
399                                 YUV_MACRO(uint16_t, 0xffff, 4, 1)
400                                 break;
401                 }
405         }
406         return 0;