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 "bccmodels.h"
26 #include "sharpenwindow.h"
32 PluginClient* new_plugin(PluginServer *server)
34 return new SharpenMain(server);
37 SharpenMain::SharpenMain(PluginServer *server)
38 : PluginVClient(server)
44 SharpenMain::~SharpenMain()
48 // Set result to 0 to indicate a server side close
49 thread->window->set_done(0);
50 thread->completion.lock();
56 char* SharpenMain::plugin_title() { return _("Quark"); }
57 int SharpenMain::is_realtime() { return 1; }
59 int SharpenMain::start_realtime()
62 last_sharpness = sharpness;
64 total_engines = smp > 1 ? 2 : 1;
65 engine = new SharpenEngine*[total_engines];
66 for(int i = 0; i < total_engines; i++)
68 engine[i] = new SharpenEngine(this);
74 int SharpenMain::stop_realtime()
76 for(int i = 0; i < total_engines; i++)
84 int SharpenMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
90 get_luts(pos_lut, neg_lut, input_ptr->get_color_model());
95 row_step = (interlace || horizontal) ? 2 : 1;
97 for(j = 0; j < row_step; j += total_engines)
99 for(k = 0; k < total_engines && k + j < row_step; k++)
101 engine[k]->start_process_frame(input_ptr, input_ptr, k + j);
103 for(k = 0; k < total_engines && k + j < row_step; k++)
105 engine[k]->wait_process_frame();
110 if(input_ptr->get_rows()[0] != output_ptr->get_rows()[0])
112 output_ptr->copy_from(input_ptr);
117 int SharpenMain::show_gui()
119 load_configuration();
120 thread = new SharpenThread(this);
125 int SharpenMain::set_string()
127 if(thread) thread->window->set_title(gui_string);
131 void SharpenMain::raise_window()
135 thread->window->raise_window();
136 thread->window->flush();
141 void SharpenMain::load_configuration()
143 KeyFrame *prev_keyframe, *next_keyframe;
144 //printf("BlurMain::load_configuration 1\n");
146 prev_keyframe = get_prev_keyframe(-1);
147 next_keyframe = get_next_keyframe(-1);
148 // Must also switch between interpolation between keyframes and using first keyframe
149 //printf("BlurMain::load_configuration %s\n", prev_keyframe->get_data());
150 read_data(prev_keyframe);
154 int SharpenMain::get_luts(int *pos_lut, int *neg_lut, int color_model)
156 int i, inv_sharpness, vmax;
158 vmax = cmodel_calculate_max(color_model);
160 inv_sharpness = (int)(100 - sharpness);
161 if(horizontal) inv_sharpness /= 2;
162 if(inv_sharpness < 1) inv_sharpness = 1;
164 for(i = 0; i < vmax + 1; i++)
166 pos_lut[i] = 800 * i / inv_sharpness;
167 neg_lut[i] = (4 + pos_lut[i] - (i << 3)) >> 3;
173 void SharpenMain::save_data(KeyFrame *keyframe)
177 // cause data to be stored directly in text
178 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
179 output.tag.set_title("SHARPNESS");
180 output.tag.set_property("VALUE", sharpness);
185 output.tag.set_title("INTERLACE");
191 output.tag.set_title("HORIZONTAL");
197 output.tag.set_title("LUMINANCE");
200 output.terminate_string();
203 void SharpenMain::read_data(KeyFrame *keyframe)
207 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
210 int new_interlace = 0;
211 int new_horizontal = 0;
212 int new_luminance = 0;
216 result = input.read_tag();
220 if(input.tag.title_is("SHARPNESS"))
222 sharpness = input.tag.get_property("VALUE", sharpness);
223 last_sharpness = sharpness;
226 if(input.tag.title_is("INTERLACE"))
231 if(input.tag.title_is("HORIZONTAL"))
236 if(input.tag.title_is("LUMINANCE"))
243 interlace = new_interlace;
244 horizontal = new_horizontal;
245 luminance = new_luminance;
247 if(sharpness > MAXSHARPNESS)
248 sharpness = MAXSHARPNESS;
250 if(sharpness < 0) sharpness = 0;
254 thread->window->sharpen_slider->update((int)sharpness);
255 thread->window->sharpen_interlace->update(interlace);
256 thread->window->sharpen_horizontal->update(horizontal);
257 thread->window->sharpen_luminance->update(luminance);
264 SharpenEngine::SharpenEngine(SharpenMain *plugin)
267 this->plugin = plugin;
269 for(int i = 0; i < 4; i++)
271 neg_rows[i] = new int[plugin->project_frame_w * 4];
278 SharpenEngine::~SharpenEngine()
284 for(int i = 0; i < 4; i++)
286 delete [] neg_rows[i];
290 int SharpenEngine::start_process_frame(VFrame *output, VFrame *input, int field)
292 this->output = output;
299 int SharpenEngine::wait_process_frame()
305 #define FILTER(components, vmax, wordsize) \
307 int *pos_lut = plugin->pos_lut; \
309 /* Skip first pixel in row */ \
310 memcpy(dst, src, components * wordsize); \
319 pixel = pos_lut[src[0]] - \
320 neg0[-components] - \
323 neg1[-components] - \
325 neg2[-components] - \
328 pixel = (pixel + 4) >> 3; \
329 if(pixel < 0) dst[0] = 0; \
331 if(pixel > vmax) dst[0] = vmax; \
335 pixel = pos_lut[src[1]] - \
336 neg0[-components + 1] - \
338 neg0[components + 1] - \
339 neg1[-components + 1] - \
340 neg1[components + 1] - \
341 neg2[-components + 1] - \
343 neg2[components + 1]; \
344 pixel = (pixel + 4) >> 3; \
345 if(pixel < 0) dst[1] = 0; \
347 if(pixel > vmax) dst[1] = vmax; \
351 pixel = pos_lut[src[2]] - \
352 neg0[-components + 2] - \
354 neg0[components + 2] - \
355 neg1[-components + 2] - \
356 neg1[components + 2] - \
357 neg2[-components + 2] - \
359 neg2[components + 2]; \
360 pixel = (pixel + 4) >> 3; \
361 if(pixel < 0) dst[2] = 0; \
363 if(pixel > vmax) dst[2] = vmax; \
367 if(components == 4) \
373 neg0 += components; \
374 neg1 += components; \
375 neg2 += components; \
379 /* Skip last pixel in row */ \
380 memcpy(dst, src, components * wordsize); \
383 void SharpenEngine::filter(int components,
393 FILTER(components, vmax, wordsize);
396 void SharpenEngine::filter(int components,
406 FILTER(components, vmax, wordsize);
415 #define SHARPEN(components, wordsize, wordtype, vmax) \
418 unsigned char **input_rows, **output_rows; \
420 input_rows = input->get_rows(); \
421 output_rows = output->get_rows(); \
422 src_rows[0] = input_rows[field]; \
423 src_rows[1] = input_rows[field]; \
424 src_rows[2] = input_rows[field]; \
425 src_rows[3] = input_rows[field]; \
427 for(int j = 0; j < plugin->project_frame_w; j++) \
429 for(int k = 0; k < components; k++) \
430 neg_rows[0][j * components + k] = plugin->neg_lut[((wordtype*)src_rows[0])[j * components + k]]; \
436 for(int i = field; i < plugin->project_frame_h; i += plugin->row_step) \
438 if((i + plugin->row_step) < plugin->project_frame_h) \
440 if(count >= 3) count--; \
442 src_rows[row] = input_rows[i + plugin->row_step]; \
443 for(int k = 0; k < plugin->project_frame_w; k++) \
445 for(int j = 0; j < components; j++) \
446 neg_rows[row][k * components + j] = plugin->neg_lut[((wordtype*)src_rows[row])[k * components + j]]; \
450 row = (row + 1) & 3; \
457 dst_row = output_rows[i]; \
460 /* Do the filter */ \
461 if(plugin->horizontal) \
465 plugin->project_frame_w, \
466 (wordtype*)src_rows[(row + 2) & 3], \
467 (wordtype*)dst_row, \
468 neg_rows[(row + 2) & 3] + components, \
469 neg_rows[(row + 2) & 3] + components, \
470 neg_rows[(row + 2) & 3] + components); \
475 plugin->project_frame_w, \
476 (wordtype*)src_rows[(row + 2) & 3], \
477 (wordtype*)dst_row, \
478 neg_rows[(row + 1) & 3] + components, \
479 neg_rows[(row + 2) & 3] + components, \
480 neg_rows[(row + 3) & 3] + components); \
486 memcpy(dst_row, src_rows[0], plugin->project_frame_w * components * wordsize); \
488 memcpy(dst_row, src_rows[2], plugin->project_frame_w * components * wordsize); \
493 void SharpenEngine::sharpen_888()
495 SHARPEN(3, 1, unsigned char, 0xff);
498 void SharpenEngine::sharpen_8888()
500 SHARPEN(4, 1, unsigned char, 0xff);
503 void SharpenEngine::sharpen_161616()
505 SHARPEN(3, 2, u_int16_t, 0xffff);
508 void SharpenEngine::sharpen_16161616()
510 SHARPEN(4, 2, u_int16_t, 0xffff);
514 void SharpenEngine::run()
521 output_lock.unlock();
526 switch(input->get_color_model())
543 case BC_RGBA16161616:
544 case BC_YUVA16161616:
549 output_lock.unlock();