r286: Heroine Virutal's official release 1.2.0
[cinelerra_cv/ct.git] / hvirtual / plugins / quark / quark.C
blobdf7beb394863292aab3de54be3fb70461e4654eb
1 #include "colormodels.h"
2 #include "filexml.h"
3 #include "picon_png.h"
4 #include "sharpen.h"
5 #include "sharpenwindow.h"
7 #include <stdio.h>
8 #include <string.h>
10 #include <libintl.h>
11 #define _(String) gettext(String)
12 #define gettext_noop(String) String
13 #define N_(String) gettext_noop (String)
15 PluginClient* new_plugin(PluginServer *server)
17         return new SharpenMain(server);
20 SharpenMain::SharpenMain(PluginServer *server)
21  : PluginVClient(server)
23         sharpness = 0;
24         thread = 0;
25         load_defaults();
28 SharpenMain::~SharpenMain()
30         if(thread)
31         {
32 // Set result to 0 to indicate a server side close
33                 thread->window->set_done(0);
34                 thread->completion.lock();
35                 delete thread;
36         }
38         save_defaults();
39         delete defaults;
42 char* SharpenMain::plugin_title() { return N_("Quark"); }
43 int SharpenMain::is_realtime() { return 1; }
45 VFrame* SharpenMain::new_picon()
47         return new VFrame(picon_png);
51 int SharpenMain::start_realtime()
53 // Initialize
54         last_sharpness = sharpness;
56         total_engines = smp > 1 ? 2 : 1;
57         engine = new SharpenEngine*[total_engines];
58         for(int i = 0; i < total_engines; i++)
59         {
60                 engine[i] = new SharpenEngine(this);
61                 engine[i]->start();
62         }
63         return 0;
66 int SharpenMain::stop_realtime()
68         for(int i = 0; i < total_engines; i++)
69         {
70                 delete engine[i];
71         }
72         delete engine;
73         return 0;
76 int SharpenMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
78         int i, j, k;
80         load_configuration();
82         get_luts(pos_lut, neg_lut, input_ptr->get_color_model());
84         if(sharpness != 0)
85         {
86 // Arm first row
87                 row_step = (interlace || horizontal) ? 2 : 1;
89                 for(j = 0; j < row_step; j += total_engines)
90                 {
91                         for(k = 0; k < total_engines && k + j < row_step; k++)
92                         {
93                                 engine[k]->start_process_frame(input_ptr, input_ptr, k + j);
94                         }
95                         for(k = 0; k < total_engines && k + j < row_step; k++)
96                         {
97                                 engine[k]->wait_process_frame();
98                         }
99                 }
100         }
101         else
102         if(input_ptr->get_rows()[0] != output_ptr->get_rows()[0])
103         {
104                 output_ptr->copy_from(input_ptr);
105         }
106         return 0;
109 int SharpenMain::show_gui()
111         load_configuration();
112         thread = new SharpenThread(this);
113         thread->start();
114         return 0;
117 int SharpenMain::set_string()
119         if(thread) thread->window->set_title(gui_string);
120         return 0;
123 void SharpenMain::raise_window()
125         if(thread)
126         {
127                 thread->window->raise_window();
128                 thread->window->flush();
129         }
132 int SharpenMain::load_defaults()
134         char directory[1024], string[1024];
135 // set the default directory
136         sprintf(directory, "%squark.rc", BCASTDIR);
138 // load the defaults
139         defaults = new Defaults(directory);
140         defaults->load();
142         sharpness = defaults->get("SHARPNESS", 50);
143         interlace = defaults->get("INTERLACE", 0);
144         horizontal = defaults->get("HORIZONTAL", 0);
145         luminance = defaults->get("LUMINANCE", 0);
146         return 0;
149 int SharpenMain::save_defaults()
151         defaults->update("SHARPNESS", sharpness);
152         defaults->update("INTERLACE", interlace);
153         defaults->update("HORIZONTAL", horizontal);
154         defaults->update("LUMINANCE", luminance);
155         defaults->save();
156         return 0;
159 void SharpenMain::load_configuration()
161         KeyFrame *prev_keyframe, *next_keyframe;
162 //printf("BlurMain::load_configuration 1\n");
164         prev_keyframe = get_prev_keyframe(-1);
165         next_keyframe = get_next_keyframe(-1);
166 // Must also switch between interpolation between keyframes and using first keyframe
167 //printf("BlurMain::load_configuration %s\n", prev_keyframe->data);
168         read_data(prev_keyframe);
172 int SharpenMain::get_luts(int *pos_lut, int *neg_lut, int color_model)
174         int i, inv_sharpness, vmax;
176         vmax = cmodel_calculate_max(color_model);
178         inv_sharpness = (int)(100 - sharpness);
179         if(horizontal) inv_sharpness /= 2;
180         if(inv_sharpness < 1) inv_sharpness = 1;
182         for(i = 0; i < vmax + 1; i++)
183         {
184                 pos_lut[i] = 800 * i / inv_sharpness;
185                 neg_lut[i] = (4 + pos_lut[i] - (i << 3)) >> 3;
186         }
188         return 0;
191 void SharpenMain::save_data(KeyFrame *keyframe)
193         FileXML output;
195 // cause data to be stored directly in text
196         output.set_shared_string(keyframe->data, MESSAGESIZE);
197         output.tag.set_title("SHARPNESS");
198         output.tag.set_property("VALUE", sharpness);
199         output.append_tag();
201         if(interlace)
202         {
203                 output.tag.set_title("INTERLACE");
204                 output.append_tag();
205         }
207         if(horizontal)
208         {
209                 output.tag.set_title("HORIZONTAL");
210                 output.append_tag();
211         }
213         if(luminance)
214         {
215                 output.tag.set_title("LUMINANCE");
216                 output.append_tag();
217         }
218         output.terminate_string();
221 void SharpenMain::read_data(KeyFrame *keyframe)
223         FileXML input;
225         input.set_shared_string(keyframe->data, strlen(keyframe->data));
227         int result = 0;
228         int new_interlace = 0;
229         int new_horizontal = 0;
230         int new_luminance = 0;
232         while(!result)
233         {
234                 result = input.read_tag();
236                 if(!result)
237                 {
238                         if(input.tag.title_is("SHARPNESS"))
239                         {
240                                 sharpness = input.tag.get_property("VALUE", sharpness);
241                                 last_sharpness = sharpness;
242                         }
243                         else
244                         if(input.tag.title_is("INTERLACE"))
245                         {
246                                 new_interlace = 1;
247                         }
248                         else
249                         if(input.tag.title_is("HORIZONTAL"))
250                         {
251                                 new_horizontal = 1;
252                         }
253                         else
254                         if(input.tag.title_is("LUMINANCE"))
255                         {
256                                 new_luminance = 1;
257                         }
258                 }
259         }
261         interlace = new_interlace;
262         horizontal = new_horizontal;
263         luminance = new_luminance;
265         if(sharpness > MAXSHARPNESS) 
266                 sharpness = MAXSHARPNESS;
267         else
268                 if(sharpness < 0) sharpness = 0;
270         if(thread) 
271         {
272                 thread->window->sharpen_slider->update((int)sharpness);
273                 thread->window->sharpen_interlace->update(interlace);
274                 thread->window->sharpen_horizontal->update(horizontal);
275                 thread->window->sharpen_luminance->update(luminance);
276         }
282 SharpenEngine::SharpenEngine(SharpenMain *plugin)
283  : Thread()
285         this->plugin = plugin;
286         last_frame = 0;
287         for(int i = 0; i < 4; i++)
288         {
289                 neg_rows[i] = new int[plugin->project_frame_w * 4];
290         }
291         input_lock.lock();
292         output_lock.lock();
293         set_synchronous(1);
296 SharpenEngine::~SharpenEngine()
298         last_frame = 1;
299         input_lock.unlock();
300         Thread::join();
302         for(int i = 0; i < 4; i++)
303         {
304                 delete [] neg_rows[i];
305         }
308 int SharpenEngine::start_process_frame(VFrame *output, VFrame *input, int field)
310         this->output = output;
311         this->input = input;
312         this->field = field;
313         input_lock.unlock();
314         return 0;
317 int SharpenEngine::wait_process_frame()
319         output_lock.lock();
320         return 0;
323 #define FILTER(components, vmax, wordsize) \
324 { \
325         int *pos_lut = plugin->pos_lut; \
327 /* Skip first pixel in row */ \
328         memcpy(dst, src, components * wordsize); \
329         dst += components; \
330         src += components; \
332         w -= 2; \
334         while(w > 0) \
335         { \
336                 long pixel; \
337                 pixel = pos_lut[src[0]] -  \
338                         neg0[-components] -  \
339                         neg0[0] -  \
340                         neg0[components] -  \
341                         neg1[-components] -  \
342                         neg1[components] -  \
343                         neg2[-components] -  \
344                         neg2[0] -  \
345                         neg2[components]; \
346                 pixel = (pixel + 4) >> 3; \
347                 if(pixel < 0) dst[0] = 0; \
348                 else \
349                 if(pixel > vmax) dst[0] = vmax; \
350                 else \
351                 dst[0] = pixel; \
353                 pixel = pos_lut[src[1]] -  \
354                         neg0[-components + 1] -  \
355                         neg0[1] -  \
356                         neg0[components + 1] -  \
357                         neg1[-components + 1] -  \
358                         neg1[components + 1] -  \
359                         neg2[-components + 1] -  \
360                         neg2[1] -  \
361                         neg2[components + 1]; \
362                 pixel = (pixel + 4) >> 3; \
363                 if(pixel < 0) dst[1] = 0; \
364                 else \
365                 if(pixel > vmax) dst[1] = vmax; \
366                 else \
367                 dst[1] = pixel; \
369                 pixel = pos_lut[src[2]] -  \
370                         neg0[-components + 2] -  \
371                         neg0[2] -  \
372                         neg0[components + 2] -  \
373                         neg1[-components + 2] -  \
374                         neg1[components + 2] -  \
375                         neg2[-components + 2] -  \
376                         neg2[2] -  \
377                         neg2[components + 2]; \
378                 pixel = (pixel + 4) >> 3; \
379                 if(pixel < 0) dst[2] = 0; \
380                 else \
381                 if(pixel > vmax) dst[2] = vmax; \
382                 else \
383                 dst[2] = pixel; \
385                 if(components == 4) \
386                         dst[3] = src[3]; \
388                 src += components; \
389                 dst += components; \
391                 neg0 += components; \
392                 neg1 += components; \
393                 neg2 += components; \
394                 w--; \
395         } \
397 /* Skip last pixel in row */ \
398         memcpy(dst, src, components * wordsize); \
401 void SharpenEngine::filter(int components,
402         int wordsize,
403         int vmax,
404         int w, 
405         u_int16_t *src, 
406         u_int16_t *dst,
407         int *neg0, 
408         int *neg1, 
409         int *neg2)
411         FILTER(components, vmax, wordsize);
414 void SharpenEngine::filter(int components,
415         int wordsize,
416         int vmax,
417         int w, 
418         unsigned char *src, 
419         unsigned char *dst,
420         int *neg0, 
421         int *neg1, 
422         int *neg2)
424         FILTER(components, vmax, wordsize);
433 #define SHARPEN(components, wordsize, wordtype, vmax) \
434 { \
435         int count, row; \
436         unsigned char **input_rows, **output_rows; \
438         input_rows = input->get_rows(); \
439         output_rows = output->get_rows(); \
440         src_rows[0] = input_rows[field]; \
441         src_rows[1] = input_rows[field]; \
442         src_rows[2] = input_rows[field]; \
443         src_rows[3] = input_rows[field]; \
445         for(int j = 0; j < plugin->project_frame_w; j++) \
446         { \
447                 for(int k = 0; k < components; k++) \
448                         neg_rows[0][j * components + k] = plugin->neg_lut[((wordtype*)src_rows[0])[j * components + k]]; \
449         } \
451         row = 1; \
452         count = 1; \
454         for(int i = field; i < plugin->project_frame_h; i += plugin->row_step) \
455         { \
456                 if((i + plugin->row_step) < plugin->project_frame_h) \
457                 { \
458                         if(count >= 3) count--; \
459 /* Arm next row */ \
460                         src_rows[row] = input_rows[i + plugin->row_step]; \
461                         for(int k = 0; k < plugin->project_frame_w; k++) \
462                         { \
463                                 for(int j = 0; j < components; j++) \
464                                         neg_rows[row][k * components + j] = plugin->neg_lut[((wordtype*)src_rows[row])[k * components + j]]; \
465                         } \
467                         count++; \
468                         row = (row + 1) & 3; \
469                 } \
470                 else \
471                 { \
472                         count--; \
473                 } \
475                 dst_row = output_rows[i]; \
476                 if(count == 3) \
477                 { \
478 /* Do the filter */ \
479                         if(plugin->horizontal) \
480                                 filter(components, \
481                                         wordsize, \
482                                         vmax, \
483                                         plugin->project_frame_w,  \
484                                         (wordtype*)src_rows[(row + 2) & 3],  \
485                                         (wordtype*)dst_row, \
486                                         neg_rows[(row + 2) & 3] + components, \
487                                         neg_rows[(row + 2) & 3] + components, \
488                                         neg_rows[(row + 2) & 3] + components); \
489                         else \
490                                 filter(components, \
491                                         wordsize, \
492                                         vmax, \
493                                         plugin->project_frame_w,  \
494                                         (wordtype*)src_rows[(row + 2) & 3],  \
495                                         (wordtype*)dst_row, \
496                                         neg_rows[(row + 1) & 3] + components, \
497                                         neg_rows[(row + 2) & 3] + components, \
498                                         neg_rows[(row + 3) & 3] + components); \
499                 } \
500                 else  \
501                 if(count == 2) \
502                 { \
503                         if(i == 0) \
504                                 memcpy(dst_row, src_rows[0], plugin->project_frame_w * components * wordsize); \
505                         else \
506                                 memcpy(dst_row, src_rows[2], plugin->project_frame_w * components * wordsize); \
507                 } \
508         } \
511 void SharpenEngine::sharpen_888()
513         SHARPEN(3, 1, unsigned char, 0xff);
516 void SharpenEngine::sharpen_8888()
518         SHARPEN(4, 1, unsigned char, 0xff);
521 void SharpenEngine::sharpen_161616()
523         SHARPEN(3, 2, u_int16_t, 0xffff);
526 void SharpenEngine::sharpen_16161616()
528         SHARPEN(4, 2, u_int16_t, 0xffff);
532 void SharpenEngine::run()
534         while(1)
535         {
536                 input_lock.lock();
537                 if(last_frame)
538                 {
539                         output_lock.unlock();
540                         return;
541                 }
544                 switch(input->get_color_model())
545                 {
546                         case BC_RGB888:
547                         case BC_YUV888:
548                                 sharpen_888();
549                                 break;
550                         
551                         case BC_RGBA8888:
552                         case BC_YUVA8888:
553                                 sharpen_8888();
554                                 break;
555                         
556                         case BC_RGB161616:
557                         case BC_YUV161616:
558                                 sharpen_161616();
559                                 break;
560                         
561                         case BC_RGBA16161616:
562                         case BC_YUVA16161616:
563                                 sharpen_16161616();
564                                 break;
565                 }
567                 output_lock.unlock();
568         }