r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / burn / burn.C
blobbb2d7148248c9646dc4f6377bd65b43b95562e24
1 #include "clip.h"
2 #include "colormodels.h"
3 #include "effecttv.h"
4 #include "filexml.h"
5 #include "picon_png.h"
6 #include "burn.h"
7 #include "burnwindow.h"
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <string.h>
13 #include <libintl.h>
14 #define _(String) gettext(String)
15 #define gettext_noop(String) String
16 #define N_(String) gettext_noop (String)
18 PluginClient* new_plugin(PluginServer *server)
20         return new BurnMain(server);
34 BurnConfig::BurnConfig()
36         threshold = 50;
37         decay = 15;
38         recycle = 1.0;
41 BurnMain::BurnMain(PluginServer *server)
42  : PluginVClient(server)
44         thread = 0;
45         defaults = 0;
46         input_ptr = 0;
47         output_ptr = 0;
48         burn_server = 0;
49         buffer = 0;
50         effecttv = 0;
51         load_defaults();
54 BurnMain::~BurnMain()
56         if(thread)
57         {
58 // Set result to 0 to indicate a server side close
59                 thread->window->set_done(0);
60                 thread->completion.lock();
61                 delete thread;
62         }
64         save_defaults();
65         if(defaults) delete defaults;
67         if(buffer) delete [] buffer;
68         if(burn_server) delete burn_server;
69         if(effecttv) delete effecttv;
72 char* BurnMain::plugin_title() { return _("BurningTV"); }
73 int BurnMain::is_realtime() { return 1; }
75 NEW_PICON_MACRO(BurnMain)
76 SHOW_GUI_MACRO(BurnMain, BurnThread)
77 SET_STRING_MACRO(BurnMain)
78 RAISE_WINDOW_MACRO(BurnMain)
80 int BurnMain::load_defaults()
82         return 0;
85 int BurnMain::save_defaults()
87         return 0;
90 void BurnMain::load_configuration()
92 //printf("BurnMain::load_configuration %d\n", source_position);
96 void BurnMain::save_data(KeyFrame *keyframe)
100 void BurnMain::read_data(KeyFrame *keyframe)
106 #define MAXCOLOR 120
108 static void HSItoRGB(double H, 
109         double S, 
110         double I, 
111         int *r, 
112         int *g, 
113         int *b)
115         double T, Rv, Gv, Bv;
117         T = H;
118         Rv = 1 + S * sin(T - 2 * M_PI / 3);
119         Gv = 1 + S * sin(T);
120         Bv = 1 + S * sin(T + 2  * M_PI / 3);
121         T = 255.999 * I / 2;
123         *r = (int)CLIP(Rv * T, 0, 255);
124         *g = (int)CLIP(Gv * T, 0, 255);
125         *b = (int)CLIP(Bv * T, 0, 255);
129 void BurnMain::make_palette()
131         int i, r, g, b;
133         for(i = 0; i < MAXCOLOR; i++)
134         {
135                 HSItoRGB(4.6 - 1.5 * i / MAXCOLOR, 
136                         (double)i / MAXCOLOR, 
137                         (double)i / MAXCOLOR,  
138                         &r, 
139                         &g, 
140                         &b);
141                 palette[0][i] = r;
142                 palette[1][i] = g;
143                 palette[2][i] = b;
144 //printf("BurnMain::make_palette %d\n", palette[0][i]);
145         }
148         for(i = MAXCOLOR; i < 256; i++)
149         {
150                 if(r < 255) r++;
151                 if(r < 255) r++;
152                 if(r < 255) r++;
153                 if(g < 255) g++;
154                 if(g < 255) g++;
155                 if(b < 255) b++;
156                 if(b < 255) b++;
157                 palette[0][i] = r;
158                 palette[1][i] = g;
159                 palette[2][i] = b;
160         }
166 int BurnMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
168         this->input_ptr = input_ptr;
169         this->output_ptr = output_ptr;
171         load_configuration();
173         if(!burn_server)
174         {
175                 effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
176                 buffer = (unsigned char *)new unsigned char[input_ptr->get_w() * input_ptr->get_h()];
177                 make_palette();
179                 effecttv->image_set_threshold_y(config.threshold);
180                 total = 0;
182                 burn_server = new BurnServer(this, 1, 1);
183         }
185         if(total == 0)
186         {
187                 bzero(buffer, input_ptr->get_w() * input_ptr->get_h());
188                 effecttv->image_bgset_y(input_ptr);
189         }
190         burn_server->process_packages();
192         total++;
193 //      if(total >= config.recycle * project_frame_rate) total = 0;
194         return 0;
199 BurnServer::BurnServer(BurnMain *plugin, int total_clients, int total_packages)
200  : LoadServer(total_clients, total_packages)
202         this->plugin = plugin;
206 LoadClient* BurnServer::new_client() 
208         return new BurnClient(this);
214 LoadPackage* BurnServer::new_package() 
216         return new BurnPackage; 
221 void BurnServer::init_packages()
223         for(int i = 0; i < total_packages; i++)
224         {
225                 BurnPackage *package = (BurnPackage*)packages[i];
226                 package->row1 = plugin->input_ptr->get_h() / total_packages * i;
227                 package->row2 = package->row1 + plugin->input_ptr->get_h() / total_packages;
228                 if(i >= total_packages - 1)
229                         package->row2 = plugin->input_ptr->get_h();
230         }
240 BurnClient::BurnClient(BurnServer *server)
241  : LoadClient(server)
243         this->plugin = server->plugin;
254 #define BURN(type, components) \
255 { \
256         i = 1; \
257         for(y = 0; y < height; y++)  \
258         { \
259                 for(x = 1; x < width - 1; x++)  \
260                 { \
261                         for(c = 0; c < components; c++) \
262                         { \
263                                 if(c == 3) \
264                                         output_rows[0][i * components + c] = input_rows[0][i * components + c]; \
265                                 else \
266                                 if(sizeof(type) == 2) \
267                                 { \
268                                         a = (input_rows[0][i * components + c] & 0xffff) >> 8; \
269                                         b = plugin->palette[c][plugin->buffer[i]] & 0xff; \
270                                         a += b; \
271                                         b = a & 0x10000; \
272                                         output_rows[0][i * components + c] = a | (b - (b >> 16)); \
273                                 } \
274                                 else \
275                                 { \
276                                         a = input_rows[0][i * components + c] & 0xff; \
277                                         b = plugin->palette[c][plugin->buffer[i]] & 0xff; \
278                                         a += b; \
279                                         b = a & 0x100; \
280                                         output_rows[0][i * components + c] = a | (b - (b >> 8)); \
281                                 } \
282                         } \
283                         i++; \
284                 } \
285                 i += 2; \
286         } \
292 void BurnClient::process_package(LoadPackage *package)
294         BurnPackage *local_package = (BurnPackage*)package;
295         unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
296         unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
297         int width = plugin->input_ptr->get_w();
298         int height = local_package->row2 - local_package->row1;
299         unsigned char *diff;
300         int pitch = width * plugin->input_ptr->get_bytes_per_pixel();
301         int i, x, y;
302         unsigned int v, w;
303         int a, b, c;
306         diff = plugin->effecttv->image_bgsubtract_y(input_rows, 
307                 plugin->input_ptr->get_color_model());
309         for(x = 1; x < width - 1; x++)
310         {
311                 v = 0;
312                 for(y = 0; y < height - 1; y++)
313                 {
314                         w = diff[y * width + x];
315                         plugin->buffer[y * width + x] |= v ^ w;
316                         v = w;
317                 }
318         }
320         for(x = 1; x < width - 1; x++) 
321         {
322                 w = 0;
323                 i = width + x;
325                 for(y = 1; y < height; y++) 
326                 {
327                         v = plugin->buffer[i];
329                         if(v < plugin->config.decay)
330                                 plugin->buffer[i - width] = 0;
331                         else
332                                 plugin->buffer[i - width + EffectTV::fastrand() % 3 - 1] = 
333                                         v - (EffectTV::fastrand() & plugin->config.decay);
335                         i += width;
336                 }
337         }
341         switch(plugin->input_ptr->get_color_model())
342         {
343                 case BC_RGB888:
344                 case BC_YUV888:
345                         BURN(uint8_t, 3);
346                         break;
348                 case BC_RGBA8888:
349                 case BC_YUVA8888:
350                         BURN(uint8_t, 4);
351                         break;
353                 case BC_RGB161616:
354                 case BC_YUV161616:
355                         BURN(uint16_t, 3);
356                         break;
358                 case BC_RGBA16161616:
359                 case BC_YUVA16161616:
360                         BURN(uint16_t, 4);
361                         break;
362         }
369 BurnPackage::BurnPackage()