Fixed initialisation of tf in file_open(). Without setting the memory to 0,
[cinelerra_cv/mob.git] / plugins / burn / burn.C
blob741d82539b8c1a660baa8dfa784349d10a564b98
1 #include "clip.h"
2 #include "colormodels.h"
3 #include "effecttv.h"
4 #include "filexml.h"
5 #include "language.h"
6 #include "picon_png.h"
7 #include "plugincolors.h"
8 #include "burn.h"
9 #include "burnwindow.h"
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <string.h>
17 REGISTER_PLUGIN(BurnMain)
30 BurnConfig::BurnConfig()
32         threshold = 50;
33         decay = 15;
34         recycle = 1.0;
37 BurnMain::BurnMain(PluginServer *server)
38  : PluginVClient(server)
40         input_ptr = 0;
41         output_ptr = 0;
42         burn_server = 0;
43         buffer = 0;
44         effecttv = 0;
45         yuv = new YUV;
46         PLUGIN_CONSTRUCTOR_MACRO
49 BurnMain::~BurnMain()
51         PLUGIN_DESTRUCTOR_MACRO
53         if(buffer) delete [] buffer;
54         if(burn_server) delete burn_server;
55         if(effecttv) delete effecttv;
56         if(yuv) delete yuv;
59 char* BurnMain::plugin_title() { return N_("BurningTV"); }
60 int BurnMain::is_realtime() { return 1; }
63 NEW_PICON_MACRO(BurnMain)
64 SHOW_GUI_MACRO(BurnMain, BurnThread)
65 SET_STRING_MACRO(BurnMain)
66 RAISE_WINDOW_MACRO(BurnMain)
68 int BurnMain::load_defaults()
70         return 0;
73 int BurnMain::save_defaults()
75         return 0;
78 void BurnMain::load_configuration()
80 //printf("BurnMain::load_configuration %d\n", source_position);
84 void BurnMain::save_data(KeyFrame *keyframe)
88 void BurnMain::read_data(KeyFrame *keyframe)
94 #define MAXCOLOR 120
96 void BurnMain::HSItoRGB(double H, 
97         double S, 
98         double I, 
99         int *r, 
100         int *g, 
101         int *b,
102         int color_model)
104         double T, Rv, Gv, Bv;
106         T = H;
107         Rv = 1 + S * sin(T - 2 * M_PI / 3);
108         Gv = 1 + S * sin(T);
109         Bv = 1 + S * sin(T + 2  * M_PI / 3);
110         T = 255.999 * I / 2;
112         *r = (int)CLIP(Rv * T, 0, 255);
113         *g = (int)CLIP(Gv * T, 0, 255);
114         *b = (int)CLIP(Bv * T, 0, 255);
118 void BurnMain::make_palette(int color_model)
120         int i, r, g, b;
122         for(i = 0; i < MAXCOLOR; i++)
123         {
124                 HSItoRGB(4.6 - 1.5 * i / MAXCOLOR, 
125                         (double)i / MAXCOLOR, 
126                         (double)i / MAXCOLOR,  
127                         &r, 
128                         &g, 
129                         &b, 
130                         color_model);
131                 palette[0][i] = r;
132                 palette[1][i] = g;
133                 palette[2][i] = b;
134 //printf("BurnMain::make_palette %d %d %d %d\n", i, palette[0][i], palette[1][i], palette[2][i]);
135         }
138         for(i = MAXCOLOR; i < 256; i++)
139         {
140                 if(r < 255) r++;
141                 if(r < 255) r++;
142                 if(r < 255) r++;
143                 if(g < 255) g++;
144                 if(g < 255) g++;
145                 if(b < 255) b++;
146                 if(b < 255) b++;
147                 palette[0][i] = r;
148                 palette[1][i] = g;
149                 palette[2][i] = b;
150 //printf("BurnMain::make_palette %d %d %d %d\n", i, palette[0][i], palette[1][i], palette[2][i]);
151         }
157 int BurnMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
159         this->input_ptr = input_ptr;
160         this->output_ptr = output_ptr;
162         load_configuration();
164         if(!burn_server)
165         {
166                 effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
167                 buffer = (unsigned char *)new unsigned char[input_ptr->get_w() * input_ptr->get_h()];
168                 make_palette(input_ptr->get_color_model());
170                 effecttv->image_set_threshold_y(config.threshold);
171                 total = 0;
173                 burn_server = new BurnServer(this, 1, 1);
174         }
176         if(total == 0)
177         {
178                 bzero(buffer, input_ptr->get_w() * input_ptr->get_h());
179                 effecttv->image_bgset_y(input_ptr);
180         }
181         burn_server->process_packages();
183         total++;
184 //      if(total >= config.recycle * project_frame_rate) total = 0;
185         return 0;
190 BurnServer::BurnServer(BurnMain *plugin, int total_clients, int total_packages)
191  : LoadServer(total_clients, total_packages)
193         this->plugin = plugin;
197 LoadClient* BurnServer::new_client() 
199         return new BurnClient(this);
205 LoadPackage* BurnServer::new_package() 
207         return new BurnPackage; 
212 void BurnServer::init_packages()
214         for(int i = 0; i < get_total_packages(); i++)
215         {
216                 BurnPackage *package = (BurnPackage*)get_package(i);
217                 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
218                 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
219         }
229 BurnClient::BurnClient(BurnServer *server)
230  : LoadClient(server)
232         this->plugin = server->plugin;
243 #define BURN(type, components, is_yuv) \
244 { \
245         i = 1; \
246         type **rows = (type**)input_rows; \
247         for(y = 0; y < height; y++)  \
248         { \
249                 for(x = 1; x < width - 1; x++)  \
250                 { \
251                         if(sizeof(type) == 4) \
252                         { \
253                                 a1 = (int)(rows[0][i * components] * 0xff); \
254                                 a2 = (int)(rows[0][i * components + 1] * 0xff); \
255                                 a3 = (int)(rows[0][i * components + 2] * 0xff); \
256                                 CLAMP(a1, 0, 0xff); \
257                                 CLAMP(a2, 0, 0xff); \
258                                 CLAMP(a3, 0, 0xff); \
259                                 b1 = plugin->palette[0][plugin->buffer[i]]; \
260                                 b2 = plugin->palette[1][plugin->buffer[i]]; \
261                                 b3 = plugin->palette[2][plugin->buffer[i]]; \
262                                 a1 += b1; \
263                                 a2 += b2; \
264                                 a3 += b3; \
265                                 b1 = a1 & 0x100; \
266                                 b2 = a2 & 0x100; \
267                                 b3 = a3 & 0x100; \
268                                 rows[0][i * components] = (type)(a1 | (b1 - (b1 >> 8))) / 0xff; \
269                                 rows[0][i * components + 1] = (type)(a2 | (b2 - (b2 >> 8))) / 0xff; \
270                                 rows[0][i * components + 2] = (type)(a3 | (b3 - (b3 >> 8))) / 0xff; \
271                         } \
272                         else \
273                         if(sizeof(type) == 2) \
274                         { \
275                                 a1 = ((int)rows[0][i * components + 0]) >> 8; \
276                                 a2 = ((int)rows[0][i * components + 1]) >> 8; \
277                                 a3 = ((int)rows[0][i * components + 2]) >> 8; \
278                                 b1 = plugin->palette[0][plugin->buffer[i]]; \
279                                 b2 = plugin->palette[1][plugin->buffer[i]]; \
280                                 b3 = plugin->palette[2][plugin->buffer[i]]; \
281                                 if(is_yuv) plugin->yuv->yuv_to_rgb_8(a1, a2, a3); \
282                                 a1 += b1; \
283                                 a2 += b2; \
284                                 a3 += b3; \
285                                 b1 = a1 & 0x100; \
286                                 b2 = a2 & 0x100; \
287                                 b3 = a3 & 0x100; \
288                                 a1 = (a1 | (b1 - (b1 >> 8))); \
289                                 a2 = (a2 | (b2 - (b2 >> 8))); \
290                                 a3 = (a3 | (b3 - (b3 >> 8))); \
291                                 if(is_yuv) \
292                                 { \
293                                         CLAMP(a1, 0, 0xff); \
294                                         CLAMP(a2, 0, 0xff); \
295                                         CLAMP(a3, 0, 0xff); \
296                                         plugin->yuv->rgb_to_yuv_8(a1, a2, a3); \
297                                 } \
298                                 rows[0][i * components + 0] = a1 | (a1 << 8); \
299                                 rows[0][i * components + 1] = a2 | (a2 << 8); \
300                                 rows[0][i * components + 2] = a3 | (a3 << 8); \
301                         } \
302                         else \
303                         { \
304                                 a1 = (int)rows[0][i * components + 0]; \
305                                 a2 = (int)rows[0][i * components + 1]; \
306                                 a3 = (int)rows[0][i * components + 2]; \
307                                 b1 = plugin->palette[0][plugin->buffer[i]]; \
308                                 b2 = plugin->palette[1][plugin->buffer[i]]; \
309                                 b3 = plugin->palette[2][plugin->buffer[i]]; \
310                                 if(is_yuv) plugin->yuv->yuv_to_rgb_8(a1, a2, a3); \
311                                 a1 += b1; \
312                                 a2 += b2; \
313                                 a3 += b3; \
314                                 b1 = a1 & 0x100; \
315                                 b2 = a2 & 0x100; \
316                                 b3 = a3 & 0x100; \
317                                 a1 = (a1 | (b1 - (b1 >> 8))); \
318                                 a2 = (a2 | (b2 - (b2 >> 8))); \
319                                 a3 = (a3 | (b3 - (b3 >> 8))); \
320                                 if(is_yuv) \
321                                 { \
322                                         CLAMP(a1, 0, 0xff); \
323                                         CLAMP(a2, 0, 0xff); \
324                                         CLAMP(a3, 0, 0xff); \
325                                         plugin->yuv->rgb_to_yuv_8(a1, a2, a3); \
326                                 } \
327                                 rows[0][i * components + 0] = a1; \
328                                 rows[0][i * components + 1] = a2; \
329                                 rows[0][i * components + 2] = a3; \
330                         } \
331                         i++; \
332                 } \
333                 i += 2; \
334         } \
340 void BurnClient::process_package(LoadPackage *package)
342         BurnPackage *local_package = (BurnPackage*)package;
343         unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
344         unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
345         int width = plugin->input_ptr->get_w();
346         int height = local_package->row2 - local_package->row1;
347         unsigned char *diff;
348         int pitch = width * plugin->input_ptr->get_bytes_per_pixel();
349         int i, x, y;
350         unsigned int v, w;
351         int a1, b1, c1;
352         int a2, b2, c2;
353         int a3, b3, c3;
356         diff = plugin->effecttv->image_bgsubtract_y(input_rows, 
357                 plugin->input_ptr->get_color_model());
359         for(x = 1; x < width - 1; x++)
360         {
361                 v = 0;
362                 for(y = 0; y < height - 1; y++)
363                 {
364                         w = diff[y * width + x];
365                         plugin->buffer[y * width + x] |= v ^ w;
366                         v = w;
367                 }
368         }
370         for(x = 1; x < width - 1; x++) 
371         {
372                 w = 0;
373                 i = width + x;
375                 for(y = 1; y < height; y++) 
376                 {
377                         v = plugin->buffer[i];
379                         if(v < plugin->config.decay)
380                                 plugin->buffer[i - width] = 0;
381                         else
382                                 plugin->buffer[i - width + EffectTV::fastrand() % 3 - 1] = 
383                                         v - (EffectTV::fastrand() & plugin->config.decay);
385                         i += width;
386                 }
387         }
391         switch(plugin->input_ptr->get_color_model())
392         {
393                 case BC_RGB888:
394                         BURN(uint8_t, 3, 0);
395                         break;
396                 case BC_YUV888:
397                         BURN(uint8_t, 3, 1);
398                         break;
400                 case BC_RGB_FLOAT:
401                         BURN(float, 3, 0);
402                         break;
404                 case BC_RGBA_FLOAT:
405                         BURN(float, 4, 0);
406                         break;
408                 case BC_RGBA8888:
409                         BURN(uint8_t, 4, 0);
410                         break;
411                 case BC_YUVA8888:
412                         BURN(uint8_t, 4, 1);
413                         break;
415                 case BC_RGB161616:
416                         BURN(uint16_t, 3, 0);
417                         break;
418                 case BC_YUV161616:
419                         BURN(uint16_t, 3, 1);
420                         break;
422                 case BC_RGBA16161616:
423                         BURN(uint16_t, 4, 0);
424                         break;
425                 case BC_YUVA16161616:
426                         BURN(uint16_t, 4, 1);
427                         break;
428         }
435 BurnPackage::BurnPackage()