4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "colormodels.h"
25 #include "sharpenwindow.h"
31 #define _(String) gettext(String)
32 #define gettext_noop(String) String
33 #define N_(String) gettext_noop (String)
35 PluginClient* new_plugin(PluginServer *server)
37 return new SharpenMain(server);
40 SharpenMain::SharpenMain(PluginServer *server)
41 : PluginVClient(server)
47 SharpenMain::~SharpenMain()
51 // Set result to 0 to indicate a server side close
52 thread->window->set_done(0);
53 thread->completion.lock();
59 char* SharpenMain::plugin_title() { return N_("Quark"); }
60 int SharpenMain::is_realtime() { return 1; }
62 int SharpenMain::start_realtime()
65 last_sharpness = sharpness;
67 total_engines = smp > 1 ? 2 : 1;
68 engine = new SharpenEngine*[total_engines];
69 for(int i = 0; i < total_engines; i++)
71 engine[i] = new SharpenEngine(this);
77 int SharpenMain::stop_realtime()
79 for(int i = 0; i < total_engines; i++)
87 int SharpenMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
93 get_luts(pos_lut, neg_lut, input_ptr->get_color_model());
98 row_step = (interlace || horizontal) ? 2 : 1;
100 for(j = 0; j < row_step; j += total_engines)
102 for(k = 0; k < total_engines && k + j < row_step; k++)
104 engine[k]->start_process_frame(input_ptr, input_ptr, k + j);
106 for(k = 0; k < total_engines && k + j < row_step; k++)
108 engine[k]->wait_process_frame();
113 if(input_ptr->get_rows()[0] != output_ptr->get_rows()[0])
115 output_ptr->copy_from(input_ptr);
120 int SharpenMain::show_gui()
122 load_configuration();
123 thread = new SharpenThread(this);
128 int SharpenMain::set_string()
130 if(thread) thread->window->set_title(gui_string);
134 void SharpenMain::raise_window()
138 thread->window->raise_window();
139 thread->window->flush();
144 void SharpenMain::load_configuration()
146 KeyFrame *prev_keyframe, *next_keyframe;
147 //printf("BlurMain::load_configuration 1\n");
149 prev_keyframe = get_prev_keyframe(-1);
150 next_keyframe = get_next_keyframe(-1);
151 // Must also switch between interpolation between keyframes and using first keyframe
152 //printf("BlurMain::load_configuration %s\n", prev_keyframe->get_data());
153 read_data(prev_keyframe);
157 int SharpenMain::get_luts(int *pos_lut, int *neg_lut, int color_model)
159 int i, inv_sharpness, vmax;
161 vmax = cmodel_calculate_max(color_model);
163 inv_sharpness = (int)(100 - sharpness);
164 if(horizontal) inv_sharpness /= 2;
165 if(inv_sharpness < 1) inv_sharpness = 1;
167 for(i = 0; i < vmax + 1; i++)
169 pos_lut[i] = 800 * i / inv_sharpness;
170 neg_lut[i] = (4 + pos_lut[i] - (i << 3)) >> 3;
176 void SharpenMain::save_data(KeyFrame *keyframe)
180 // cause data to be stored directly in text
181 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
182 output.tag.set_title("SHARPNESS");
183 output.tag.set_property("VALUE", sharpness);
188 output.tag.set_title("INTERLACE");
194 output.tag.set_title("HORIZONTAL");
200 output.tag.set_title("LUMINANCE");
203 output.terminate_string();
206 void SharpenMain::read_data(KeyFrame *keyframe)
210 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
213 int new_interlace = 0;
214 int new_horizontal = 0;
215 int new_luminance = 0;
219 result = input.read_tag();
223 if(input.tag.title_is("SHARPNESS"))
225 sharpness = input.tag.get_property("VALUE", sharpness);
226 last_sharpness = sharpness;
229 if(input.tag.title_is("INTERLACE"))
234 if(input.tag.title_is("HORIZONTAL"))
239 if(input.tag.title_is("LUMINANCE"))
246 interlace = new_interlace;
247 horizontal = new_horizontal;
248 luminance = new_luminance;
250 if(sharpness > MAXSHARPNESS)
251 sharpness = MAXSHARPNESS;
253 if(sharpness < 0) sharpness = 0;
257 thread->window->sharpen_slider->update((int)sharpness);
258 thread->window->sharpen_interlace->update(interlace);
259 thread->window->sharpen_horizontal->update(horizontal);
260 thread->window->sharpen_luminance->update(luminance);
267 SharpenEngine::SharpenEngine(SharpenMain *plugin)
270 this->plugin = plugin;
272 for(int i = 0; i < 4; i++)
274 neg_rows[i] = new int[plugin->project_frame_w * 4];
281 SharpenEngine::~SharpenEngine()
287 for(int i = 0; i < 4; i++)
289 delete [] neg_rows[i];
293 int SharpenEngine::start_process_frame(VFrame *output, VFrame *input, int field)
295 this->output = output;
302 int SharpenEngine::wait_process_frame()
308 #define FILTER(components, vmax, wordsize) \
310 int *pos_lut = plugin->pos_lut; \
312 /* Skip first pixel in row */ \
313 memcpy(dst, src, components * wordsize); \
322 pixel = pos_lut[src[0]] - \
323 neg0[-components] - \
326 neg1[-components] - \
328 neg2[-components] - \
331 pixel = (pixel + 4) >> 3; \
332 if(pixel < 0) dst[0] = 0; \
334 if(pixel > vmax) dst[0] = vmax; \
338 pixel = pos_lut[src[1]] - \
339 neg0[-components + 1] - \
341 neg0[components + 1] - \
342 neg1[-components + 1] - \
343 neg1[components + 1] - \
344 neg2[-components + 1] - \
346 neg2[components + 1]; \
347 pixel = (pixel + 4) >> 3; \
348 if(pixel < 0) dst[1] = 0; \
350 if(pixel > vmax) dst[1] = vmax; \
354 pixel = pos_lut[src[2]] - \
355 neg0[-components + 2] - \
357 neg0[components + 2] - \
358 neg1[-components + 2] - \
359 neg1[components + 2] - \
360 neg2[-components + 2] - \
362 neg2[components + 2]; \
363 pixel = (pixel + 4) >> 3; \
364 if(pixel < 0) dst[2] = 0; \
366 if(pixel > vmax) dst[2] = vmax; \
370 if(components == 4) \
376 neg0 += components; \
377 neg1 += components; \
378 neg2 += components; \
382 /* Skip last pixel in row */ \
383 memcpy(dst, src, components * wordsize); \
386 void SharpenEngine::filter(int components,
396 FILTER(components, vmax, wordsize);
399 void SharpenEngine::filter(int components,
409 FILTER(components, vmax, wordsize);
418 #define SHARPEN(components, wordsize, wordtype, vmax) \
421 unsigned char **input_rows, **output_rows; \
423 input_rows = input->get_rows(); \
424 output_rows = output->get_rows(); \
425 src_rows[0] = input_rows[field]; \
426 src_rows[1] = input_rows[field]; \
427 src_rows[2] = input_rows[field]; \
428 src_rows[3] = input_rows[field]; \
430 for(int j = 0; j < plugin->project_frame_w; j++) \
432 for(int k = 0; k < components; k++) \
433 neg_rows[0][j * components + k] = plugin->neg_lut[((wordtype*)src_rows[0])[j * components + k]]; \
439 for(int i = field; i < plugin->project_frame_h; i += plugin->row_step) \
441 if((i + plugin->row_step) < plugin->project_frame_h) \
443 if(count >= 3) count--; \
445 src_rows[row] = input_rows[i + plugin->row_step]; \
446 for(int k = 0; k < plugin->project_frame_w; k++) \
448 for(int j = 0; j < components; j++) \
449 neg_rows[row][k * components + j] = plugin->neg_lut[((wordtype*)src_rows[row])[k * components + j]]; \
453 row = (row + 1) & 3; \
460 dst_row = output_rows[i]; \
463 /* Do the filter */ \
464 if(plugin->horizontal) \
468 plugin->project_frame_w, \
469 (wordtype*)src_rows[(row + 2) & 3], \
470 (wordtype*)dst_row, \
471 neg_rows[(row + 2) & 3] + components, \
472 neg_rows[(row + 2) & 3] + components, \
473 neg_rows[(row + 2) & 3] + components); \
478 plugin->project_frame_w, \
479 (wordtype*)src_rows[(row + 2) & 3], \
480 (wordtype*)dst_row, \
481 neg_rows[(row + 1) & 3] + components, \
482 neg_rows[(row + 2) & 3] + components, \
483 neg_rows[(row + 3) & 3] + components); \
489 memcpy(dst_row, src_rows[0], plugin->project_frame_w * components * wordsize); \
491 memcpy(dst_row, src_rows[2], plugin->project_frame_w * components * wordsize); \
496 void SharpenEngine::sharpen_888()
498 SHARPEN(3, 1, unsigned char, 0xff);
501 void SharpenEngine::sharpen_8888()
503 SHARPEN(4, 1, unsigned char, 0xff);
506 void SharpenEngine::sharpen_161616()
508 SHARPEN(3, 2, u_int16_t, 0xffff);
511 void SharpenEngine::sharpen_16161616()
513 SHARPEN(4, 2, u_int16_t, 0xffff);
517 void SharpenEngine::run()
524 output_lock.unlock();
529 switch(input->get_color_model())
546 case BC_RGBA16161616:
547 case BC_YUVA16161616:
552 output_lock.unlock();