00001 #include "colormodels.h"
00002 #include "filexml.h"
00003 #include "picon_png.h"
00004 #include "quark.h"
00005 #include "quarkwindow.h"
00006
00007 #include <stdio.h>
00008 #include <string.h>
00009
00010 #include <libintl.h>
00011 #define _(String) gettext(String)
00012 #define gettext_noop(String) String
00013 #define N_(String) gettext_noop (String)
00014
00015 PluginClient* new_plugin(PluginServer *server)
00016 {
00017 return new SharpenMain(server);
00018 }
00019
00020 SharpenMain::SharpenMain(PluginServer *server)
00021 : PluginVClient(server)
00022 {
00023 sharpness = 0;
00024 thread = 0;
00025 load_defaults();
00026 }
00027
00028 SharpenMain::~SharpenMain()
00029 {
00030 if(thread)
00031 {
00032
00033 thread->window->set_done(0);
00034 thread->completion.lock();
00035 delete thread;
00036 }
00037
00038 save_defaults();
00039 delete defaults;
00040 }
00041
00042 char* SharpenMain::plugin_title() { return N_("Quark"); }
00043 int SharpenMain::is_realtime() { return 1; }
00044
00045 VFrame* SharpenMain::new_picon()
00046 {
00047 return new VFrame(picon_png);
00048 }
00049
00050
00051 int SharpenMain::start_realtime()
00052 {
00053
00054 last_sharpness = sharpness;
00055
00056 total_engines = smp > 1 ? 2 : 1;
00057 engine = new SharpenEngine*[total_engines];
00058 for(int i = 0; i < total_engines; i++)
00059 {
00060 engine[i] = new SharpenEngine(this);
00061 engine[i]->start();
00062 }
00063 return 0;
00064 }
00065
00066 int SharpenMain::stop_realtime()
00067 {
00068 for(int i = 0; i < total_engines; i++)
00069 {
00070 delete engine[i];
00071 }
00072 delete engine;
00073 return 0;
00074 }
00075
00076 int SharpenMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
00077 {
00078 int i, j, k;
00079
00080 load_configuration();
00081
00082 get_luts(pos_lut, neg_lut, input_ptr->get_color_model());
00083
00084 if(sharpness != 0)
00085 {
00086
00087 row_step = (interlace || horizontal) ? 2 : 1;
00088
00089 for(j = 0; j < row_step; j += total_engines)
00090 {
00091 for(k = 0; k < total_engines && k + j < row_step; k++)
00092 {
00093 engine[k]->start_process_frame(input_ptr, input_ptr, k + j);
00094 }
00095 for(k = 0; k < total_engines && k + j < row_step; k++)
00096 {
00097 engine[k]->wait_process_frame();
00098 }
00099 }
00100 }
00101 else
00102 if(input_ptr->get_rows()[0] != output_ptr->get_rows()[0])
00103 {
00104 output_ptr->copy_from(input_ptr);
00105 }
00106 return 0;
00107 }
00108
00109 int SharpenMain::show_gui()
00110 {
00111 load_configuration();
00112 thread = new SharpenThread(this);
00113 thread->start();
00114 return 0;
00115 }
00116
00117 int SharpenMain::set_string()
00118 {
00119 if(thread) thread->window->set_title(gui_string);
00120 return 0;
00121 }
00122
00123 void SharpenMain::raise_window()
00124 {
00125 if(thread)
00126 {
00127 thread->window->raise_window();
00128 thread->window->flush();
00129 }
00130 }
00131
00132 int SharpenMain::load_defaults()
00133 {
00134 char directory[1024], string[1024];
00135
00136 sprintf(directory, "%squark.rc", BCASTDIR);
00137
00138
00139 defaults = new BC_Hash(directory);
00140 defaults->load();
00141
00142 sharpness = defaults->get("SHARPNESS", 50);
00143 interlace = defaults->get("INTERLACE", 0);
00144 horizontal = defaults->get("HORIZONTAL", 0);
00145 luminance = defaults->get("LUMINANCE", 0);
00146 return 0;
00147 }
00148
00149 int SharpenMain::save_defaults()
00150 {
00151 defaults->update("SHARPNESS", sharpness);
00152 defaults->update("INTERLACE", interlace);
00153 defaults->update("HORIZONTAL", horizontal);
00154 defaults->update("LUMINANCE", luminance);
00155 defaults->save();
00156 return 0;
00157 }
00158
00159 void SharpenMain::load_configuration()
00160 {
00161 KeyFrame *prev_keyframe, *next_keyframe;
00162
00163
00164 prev_keyframe = get_prev_keyframe(-1);
00165 next_keyframe = get_next_keyframe(-1);
00166
00167
00168 read_data(prev_keyframe);
00169 }
00170
00171
00172 int SharpenMain::get_luts(int *pos_lut, int *neg_lut, int color_model)
00173 {
00174 int i, inv_sharpness, vmax;
00175
00176 vmax = cmodel_calculate_max(color_model);
00177
00178 inv_sharpness = (int)(100 - sharpness);
00179 if(horizontal) inv_sharpness /= 2;
00180 if(inv_sharpness < 1) inv_sharpness = 1;
00181
00182 for(i = 0; i < vmax + 1; i++)
00183 {
00184 pos_lut[i] = 800 * i / inv_sharpness;
00185 neg_lut[i] = (4 + pos_lut[i] - (i << 3)) >> 3;
00186 }
00187
00188 return 0;
00189 }
00190
00191 void SharpenMain::save_data(KeyFrame *keyframe)
00192 {
00193 FileXML output;
00194
00195
00196 output.set_shared_string(keyframe->data, MESSAGESIZE);
00197 output.tag.set_title("SHARPNESS");
00198 output.tag.set_property("VALUE", sharpness);
00199 output.append_tag();
00200
00201 if(interlace)
00202 {
00203 output.tag.set_title("INTERLACE");
00204 output.append_tag();
00205 }
00206
00207 if(horizontal)
00208 {
00209 output.tag.set_title("HORIZONTAL");
00210 output.append_tag();
00211 }
00212
00213 if(luminance)
00214 {
00215 output.tag.set_title("LUMINANCE");
00216 output.append_tag();
00217 }
00218 output.tag.set_title("/SHARPNESS");
00219 output.append_tag();
00220 output.terminate_string();
00221 }
00222
00223 void SharpenMain::read_data(KeyFrame *keyframe)
00224 {
00225 FileXML input;
00226
00227 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00228
00229 int result = 0;
00230 int new_interlace = 0;
00231 int new_horizontal = 0;
00232 int new_luminance = 0;
00233
00234 while(!result)
00235 {
00236 result = input.read_tag();
00237
00238 if(!result)
00239 {
00240 if(input.tag.title_is("SHARPNESS"))
00241 {
00242 sharpness = input.tag.get_property("VALUE", sharpness);
00243 last_sharpness = sharpness;
00244 }
00245 else
00246 if(input.tag.title_is("INTERLACE"))
00247 {
00248 new_interlace = 1;
00249 }
00250 else
00251 if(input.tag.title_is("HORIZONTAL"))
00252 {
00253 new_horizontal = 1;
00254 }
00255 else
00256 if(input.tag.title_is("LUMINANCE"))
00257 {
00258 new_luminance = 1;
00259 }
00260 }
00261 }
00262
00263 interlace = new_interlace;
00264 horizontal = new_horizontal;
00265 luminance = new_luminance;
00266
00267 if(sharpness > MAXSHARPNESS)
00268 sharpness = MAXSHARPNESS;
00269 else
00270 if(sharpness < 0) sharpness = 0;
00271
00272 if(thread)
00273 {
00274 thread->window->sharpen_slider->update((int)sharpness);
00275 thread->window->sharpen_interlace->update(interlace);
00276 thread->window->sharpen_horizontal->update(horizontal);
00277 thread->window->sharpen_luminance->update(luminance);
00278 }
00279 }
00280
00281
00282
00283
00284 SharpenEngine::SharpenEngine(SharpenMain *plugin)
00285 : Thread()
00286 {
00287 this->plugin = plugin;
00288 last_frame = 0;
00289 for(int i = 0; i < 4; i++)
00290 {
00291 neg_rows[i] = new int[plugin->project_frame_w * 4];
00292 }
00293 input_lock.lock();
00294 output_lock.lock();
00295 set_synchronous(1);
00296 }
00297
00298 SharpenEngine::~SharpenEngine()
00299 {
00300 last_frame = 1;
00301 input_lock.unlock();
00302 Thread::join();
00303
00304 for(int i = 0; i < 4; i++)
00305 {
00306 delete [] neg_rows[i];
00307 }
00308 }
00309
00310 int SharpenEngine::start_process_frame(VFrame *output, VFrame *input, int field)
00311 {
00312 this->output = output;
00313 this->input = input;
00314 this->field = field;
00315 input_lock.unlock();
00316 return 0;
00317 }
00318
00319 int SharpenEngine::wait_process_frame()
00320 {
00321 output_lock.lock();
00322 return 0;
00323 }
00324
00325 #define FILTER(components, vmax, wordsize) \
00326 { \
00327 int *pos_lut = plugin->pos_lut; \
00328 \
00329 \
00330 memcpy(dst, src, components * wordsize); \
00331 dst += components; \
00332 src += components; \
00333 \
00334 w -= 2; \
00335 \
00336 while(w > 0) \
00337 { \
00338 long pixel; \
00339 pixel = pos_lut[src[0]] - \
00340 neg0[-components] - \
00341 neg0[0] - \
00342 neg0[components] - \
00343 neg1[-components] - \
00344 neg1[components] - \
00345 neg2[-components] - \
00346 neg2[0] - \
00347 neg2[components]; \
00348 pixel = (pixel + 4) >> 3; \
00349 if(pixel < 0) dst[0] = 0; \
00350 else \
00351 if(pixel > vmax) dst[0] = vmax; \
00352 else \
00353 dst[0] = pixel; \
00354 \
00355 pixel = pos_lut[src[1]] - \
00356 neg0[-components + 1] - \
00357 neg0[1] - \
00358 neg0[components + 1] - \
00359 neg1[-components + 1] - \
00360 neg1[components + 1] - \
00361 neg2[-components + 1] - \
00362 neg2[1] - \
00363 neg2[components + 1]; \
00364 pixel = (pixel + 4) >> 3; \
00365 if(pixel < 0) dst[1] = 0; \
00366 else \
00367 if(pixel > vmax) dst[1] = vmax; \
00368 else \
00369 dst[1] = pixel; \
00370 \
00371 pixel = pos_lut[src[2]] - \
00372 neg0[-components + 2] - \
00373 neg0[2] - \
00374 neg0[components + 2] - \
00375 neg1[-components + 2] - \
00376 neg1[components + 2] - \
00377 neg2[-components + 2] - \
00378 neg2[2] - \
00379 neg2[components + 2]; \
00380 pixel = (pixel + 4) >> 3; \
00381 if(pixel < 0) dst[2] = 0; \
00382 else \
00383 if(pixel > vmax) dst[2] = vmax; \
00384 else \
00385 dst[2] = pixel; \
00386 \
00387 if(components == 4) \
00388 dst[3] = src[3]; \
00389 \
00390 src += components; \
00391 dst += components; \
00392 \
00393 neg0 += components; \
00394 neg1 += components; \
00395 neg2 += components; \
00396 w--; \
00397 } \
00398 \
00399 \
00400 memcpy(dst, src, components * wordsize); \
00401 }
00402
00403 void SharpenEngine::filter(int components,
00404 int wordsize,
00405 int vmax,
00406 int w,
00407 u_int16_t *src,
00408 u_int16_t *dst,
00409 int *neg0,
00410 int *neg1,
00411 int *neg2)
00412 {
00413 FILTER(components, vmax, wordsize);
00414 }
00415
00416 void SharpenEngine::filter(int components,
00417 int wordsize,
00418 int vmax,
00419 int w,
00420 unsigned char *src,
00421 unsigned char *dst,
00422 int *neg0,
00423 int *neg1,
00424 int *neg2)
00425 {
00426 FILTER(components, vmax, wordsize);
00427 }
00428
00429
00430
00431
00432
00433
00434
00435 #define SHARPEN(components, wordsize, wordtype, vmax) \
00436 { \
00437 int count, row; \
00438 unsigned char **input_rows, **output_rows; \
00439 \
00440 input_rows = input->get_rows(); \
00441 output_rows = output->get_rows(); \
00442 src_rows[0] = input_rows[field]; \
00443 src_rows[1] = input_rows[field]; \
00444 src_rows[2] = input_rows[field]; \
00445 src_rows[3] = input_rows[field]; \
00446 \
00447 for(int j = 0; j < plugin->project_frame_w; j++) \
00448 { \
00449 for(int k = 0; k < components; k++) \
00450 neg_rows[0][j * components + k] = plugin->neg_lut[((wordtype*)src_rows[0])[j * components + k]]; \
00451 } \
00452 \
00453 row = 1; \
00454 count = 1; \
00455 \
00456 for(int i = field; i < plugin->project_frame_h; i += plugin->row_step) \
00457 { \
00458 if((i + plugin->row_step) < plugin->project_frame_h) \
00459 { \
00460 if(count >= 3) count--; \
00461 \
00462 src_rows[row] = input_rows[i + plugin->row_step]; \
00463 for(int k = 0; k < plugin->project_frame_w; k++) \
00464 { \
00465 for(int j = 0; j < components; j++) \
00466 neg_rows[row][k * components + j] = plugin->neg_lut[((wordtype*)src_rows[row])[k * components + j]]; \
00467 } \
00468 \
00469 count++; \
00470 row = (row + 1) & 3; \
00471 } \
00472 else \
00473 { \
00474 count--; \
00475 } \
00476 \
00477 dst_row = output_rows[i]; \
00478 if(count == 3) \
00479 { \
00480 \
00481 if(plugin->horizontal) \
00482 filter(components, \
00483 wordsize, \
00484 vmax, \
00485 plugin->project_frame_w, \
00486 (wordtype*)src_rows[(row + 2) & 3], \
00487 (wordtype*)dst_row, \
00488 neg_rows[(row + 2) & 3] + components, \
00489 neg_rows[(row + 2) & 3] + components, \
00490 neg_rows[(row + 2) & 3] + components); \
00491 else \
00492 filter(components, \
00493 wordsize, \
00494 vmax, \
00495 plugin->project_frame_w, \
00496 (wordtype*)src_rows[(row + 2) & 3], \
00497 (wordtype*)dst_row, \
00498 neg_rows[(row + 1) & 3] + components, \
00499 neg_rows[(row + 2) & 3] + components, \
00500 neg_rows[(row + 3) & 3] + components); \
00501 } \
00502 else \
00503 if(count == 2) \
00504 { \
00505 if(i == 0) \
00506 memcpy(dst_row, src_rows[0], plugin->project_frame_w * components * wordsize); \
00507 else \
00508 memcpy(dst_row, src_rows[2], plugin->project_frame_w * components * wordsize); \
00509 } \
00510 } \
00511 }
00512
00513 void SharpenEngine::sharpen_888()
00514 {
00515 SHARPEN(3, 1, unsigned char, 0xff);
00516 }
00517
00518 void SharpenEngine::sharpen_8888()
00519 {
00520 SHARPEN(4, 1, unsigned char, 0xff);
00521 }
00522
00523 void SharpenEngine::sharpen_161616()
00524 {
00525 SHARPEN(3, 2, u_int16_t, 0xffff);
00526 }
00527
00528 void SharpenEngine::sharpen_16161616()
00529 {
00530 SHARPEN(4, 2, u_int16_t, 0xffff);
00531 }
00532
00533
00534 void SharpenEngine::run()
00535 {
00536 while(1)
00537 {
00538 input_lock.lock();
00539 if(last_frame)
00540 {
00541 output_lock.unlock();
00542 return;
00543 }
00544
00545
00546 switch(input->get_color_model())
00547 {
00548 case BC_RGB888:
00549 case BC_YUV888:
00550 sharpen_888();
00551 break;
00552
00553 case BC_RGBA8888:
00554 case BC_YUVA8888:
00555 sharpen_8888();
00556 break;
00557
00558 case BC_RGB161616:
00559 case BC_YUV161616:
00560 sharpen_161616();
00561 break;
00562
00563 case BC_RGBA16161616:
00564 case BC_YUVA16161616:
00565 sharpen_16161616();
00566 break;
00567 }
00568
00569 output_lock.unlock();
00570 }
00571 }
00572