2 #include "colormodels.h"
6 #include "sharpenwindow.h"
12 #define _(String) gettext(String)
13 #define gettext_noop(String) String
14 #define N_(String) gettext_noop (String)
16 REGISTER_PLUGIN(SharpenMain)
24 SharpenConfig::SharpenConfig()
32 void SharpenConfig::copy_from(SharpenConfig &that)
34 horizontal = that.horizontal;
35 interlace = that.interlace;
36 sharpness = that.sharpness;
37 luminance = that.luminance;
40 int SharpenConfig::equivalent(SharpenConfig &that)
42 return horizontal == that.horizontal &&
43 interlace == that.interlace &&
44 EQUIV(sharpness, that.sharpness) &&
45 luminance == that.luminance;
48 void SharpenConfig::interpolate(SharpenConfig &prev,
54 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
55 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
56 this->sharpness = prev.sharpness * prev_scale + next.sharpness * next_scale;
57 this->interlace = prev.interlace;
58 this->horizontal = prev.horizontal;
59 this->luminance = prev.luminance;
72 SharpenMain::SharpenMain(PluginServer *server)
73 : PluginVClient(server)
80 SharpenMain::~SharpenMain()
84 // Set result to 0 to indicate a server side close
85 thread->window->set_done(0);
86 thread->completion.lock();
95 for(int i = 0; i < total_engines; i++)
103 SHOW_GUI_MACRO(SharpenMain, SharpenThread)
105 SET_STRING_MACRO(SharpenMain)
107 RAISE_WINDOW_MACRO(SharpenMain)
109 NEW_PICON_MACRO(SharpenMain)
111 LOAD_CONFIGURATION_MACRO(SharpenMain, SharpenConfig)
113 char* SharpenMain::plugin_title() { return _("Sharpen"); }
114 int SharpenMain::is_realtime() { return 1; }
118 int SharpenMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
124 load_configuration();
128 total_engines = smp > 1 ? 2 : 1;
129 engine = new SharpenEngine*[total_engines];
130 for(int i = 0; i < total_engines; i++)
132 engine[i] = new SharpenEngine(this);
137 get_luts(pos_lut, neg_lut, input_ptr->get_color_model());
139 if(config.sharpness != 0)
142 row_step = (config.interlace || config.horizontal) ? 2 : 1;
144 for(j = 0; j < row_step; j += total_engines)
146 for(k = 0; k < total_engines && k + j < row_step; k++)
148 engine[k]->start_process_frame(input_ptr, input_ptr, k + j);
150 for(k = 0; k < total_engines && k + j < row_step; k++)
152 engine[k]->wait_process_frame();
157 if(input_ptr->get_rows()[0] != output_ptr->get_rows()[0])
159 output_ptr->copy_from(input_ptr);
164 void SharpenMain::update_gui()
168 load_configuration();
169 thread->window->lock_window();
170 thread->window->sharpen_slider->update((int)config.sharpness);
171 thread->window->sharpen_interlace->update(config.interlace);
172 thread->window->sharpen_horizontal->update(config.horizontal);
173 thread->window->sharpen_luminance->update(config.luminance);
174 thread->window->unlock_window();
178 int SharpenMain::load_defaults()
180 char directory[1024], string[1024];
181 // set the default directory
182 sprintf(directory, "%ssharpen.rc", BCASTDIR);
185 defaults = new Defaults(directory);
188 config.sharpness = defaults->get("SHARPNESS", config.sharpness);
189 config.interlace = defaults->get("INTERLACE", config.interlace);
190 config.horizontal = defaults->get("HORIZONTAL", config.horizontal);
191 config.luminance = defaults->get("LUMINANCE", config.luminance);
192 //printf("SharpenMain::load_defaults 1 %f %d %d %d\n", sharpness, interlace, horizontal, luminance);
196 int SharpenMain::save_defaults()
198 //printf("SharpenMain::save_defaults 1 %f %d %d %d\n", sharpness, interlace, horizontal, luminance);
199 defaults->update("SHARPNESS", config.sharpness);
200 defaults->update("INTERLACE", config.interlace);
201 defaults->update("HORIZONTAL", config.horizontal);
202 defaults->update("LUMINANCE", config.luminance);
210 int SharpenMain::get_luts(int *pos_lut, int *neg_lut, int color_model)
212 int i, inv_sharpness, vmax;
214 vmax = cmodel_calculate_max(color_model);
216 inv_sharpness = (int)(100 - config.sharpness);
217 if(config.horizontal) inv_sharpness /= 2;
218 if(inv_sharpness < 1) inv_sharpness = 1;
220 for(i = 0; i < vmax + 1; i++)
222 pos_lut[i] = 800 * i / inv_sharpness;
223 neg_lut[i] = (4 + pos_lut[i] - (i << 3)) >> 3;
229 void SharpenMain::save_data(KeyFrame *keyframe)
233 // cause data to be stored directly in text
234 output.set_shared_string(keyframe->data, MESSAGESIZE);
235 output.tag.set_title("SHARPNESS");
236 output.tag.set_property("VALUE", config.sharpness);
241 output.tag.set_title("INTERLACE");
245 if(config.horizontal)
247 output.tag.set_title("HORIZONTAL");
253 output.tag.set_title("LUMINANCE");
256 output.terminate_string();
259 void SharpenMain::read_data(KeyFrame *keyframe)
263 input.set_shared_string(keyframe->data, strlen(keyframe->data));
266 int new_interlace = 0;
267 int new_horizontal = 0;
268 int new_luminance = 0;
272 result = input.read_tag();
276 if(input.tag.title_is("SHARPNESS"))
278 config.sharpness = input.tag.get_property("VALUE", config.sharpness);
279 //printf("SharpenMain::read_data %f\n", sharpness);
282 if(input.tag.title_is("INTERLACE"))
287 if(input.tag.title_is("HORIZONTAL"))
292 if(input.tag.title_is("LUMINANCE"))
299 config.interlace = new_interlace;
300 config.horizontal = new_horizontal;
301 config.luminance = new_luminance;
303 if(config.sharpness > MAXSHARPNESS)
304 config.sharpness = MAXSHARPNESS;
306 if(config.sharpness < 0) config.sharpness = 0;
312 SharpenEngine::SharpenEngine(SharpenMain *plugin)
315 this->plugin = plugin;
317 for(int i = 0; i < 4; i++)
319 neg_rows[i] = new int[plugin->input->get_w() * 4];
326 SharpenEngine::~SharpenEngine()
332 for(int i = 0; i < 4; i++)
334 delete [] neg_rows[i];
338 int SharpenEngine::start_process_frame(VFrame *output, VFrame *input, int field)
340 this->output = output;
347 int SharpenEngine::wait_process_frame()
353 #define FILTER(components, vmax, wordsize) \
355 int *pos_lut = plugin->pos_lut; \
357 /* Skip first pixel in row */ \
358 memcpy(dst, src, components * wordsize); \
367 pixel = (long)pos_lut[src[0]] - \
368 (long)neg0[-components] - \
370 (long)neg0[components] - \
371 (long)neg1[-components] - \
372 (long)neg1[components] - \
373 (long)neg2[-components] - \
375 (long)neg2[components]; \
376 pixel = (pixel + 4) >> 3; \
377 if(pixel < 0) dst[0] = 0; \
379 if(pixel > vmax) dst[0] = vmax; \
383 pixel = (long)pos_lut[src[1]] - \
384 (long)neg0[-components + 1] - \
386 (long)neg0[components + 1] - \
387 (long)neg1[-components + 1] - \
388 (long)neg1[components + 1] - \
389 (long)neg2[-components + 1] - \
391 (long)neg2[components + 1]; \
392 pixel = (pixel + 4) >> 3; \
393 if(pixel < 0) dst[1] = 0; \
395 if(pixel > vmax) dst[1] = vmax; \
399 pixel = (long)pos_lut[src[2]] - \
400 (long)neg0[-components + 2] - \
402 (long)neg0[components + 2] - \
403 (long)neg1[-components + 2] - \
404 (long)neg1[components + 2] - \
405 (long)neg2[-components + 2] - \
407 (long)neg2[components + 2]; \
408 pixel = (pixel + 4) >> 3; \
409 if(pixel < 0) dst[2] = 0; \
411 if(pixel > vmax) dst[2] = vmax; \
415 if(components == 4) \
421 neg0 += components; \
422 neg1 += components; \
423 neg2 += components; \
427 /* Skip last pixel in row */ \
428 memcpy(dst, src, components * wordsize); \
431 void SharpenEngine::filter(int components,
441 FILTER(components, vmax, wordsize);
444 void SharpenEngine::filter(int components,
454 FILTER(components, vmax, wordsize);
463 #define SHARPEN(components, wordsize, wordtype, vmax) \
466 unsigned char **input_rows, **output_rows; \
467 int w = plugin->input->get_w(); \
468 int h = plugin->input->get_h(); \
470 input_rows = input->get_rows(); \
471 output_rows = output->get_rows(); \
472 src_rows[0] = input_rows[field]; \
473 src_rows[1] = input_rows[field]; \
474 src_rows[2] = input_rows[field]; \
475 src_rows[3] = input_rows[field]; \
477 for(int j = 0; j < w; j++) \
479 for(int k = 0; k < components; k++) \
480 neg_rows[0][j * components + k] = plugin->neg_lut[((wordtype*)src_rows[0])[j * components + k]]; \
486 for(int i = field; i < h; i += plugin->row_step) \
488 if((i + plugin->row_step) < h) \
490 if(count >= 3) count--; \
492 src_rows[row] = input_rows[i + plugin->row_step]; \
493 for(int k = 0; k < w; k++) \
495 for(int j = 0; j < components; j++) \
496 neg_rows[row][k * components + j] = plugin->neg_lut[((wordtype*)src_rows[row])[k * components + j]]; \
500 row = (row + 1) & 3; \
507 dst_row = output_rows[i]; \
510 /* Do the filter */ \
511 if(plugin->config.horizontal) \
516 (wordtype*)src_rows[(row + 2) & 3], \
517 (wordtype*)dst_row, \
518 neg_rows[(row + 2) & 3] + components, \
519 neg_rows[(row + 2) & 3] + components, \
520 neg_rows[(row + 2) & 3] + components); \
526 (wordtype*)src_rows[(row + 2) & 3], \
527 (wordtype*)dst_row, \
528 neg_rows[(row + 1) & 3] + components, \
529 neg_rows[(row + 2) & 3] + components, \
530 neg_rows[(row + 3) & 3] + components); \
536 memcpy(dst_row, src_rows[0], w * components * wordsize); \
538 memcpy(dst_row, src_rows[2], w * components * wordsize); \
543 void SharpenEngine::sharpen_888()
545 SHARPEN(3, 1, unsigned char, 0xff);
548 void SharpenEngine::sharpen_8888()
550 SHARPEN(4, 1, unsigned char, 0xff);
553 void SharpenEngine::sharpen_161616()
555 SHARPEN(3, 2, u_int16_t, 0xffff);
558 void SharpenEngine::sharpen_16161616()
560 SHARPEN(4, 2, u_int16_t, 0xffff);
564 void SharpenEngine::run()
571 output_lock.unlock();
576 switch(input->get_color_model())
593 case BC_RGBA16161616:
594 case BC_YUVA16161616:
599 output_lock.unlock();