00001 #include "clip.h"
00002 #include "colormodels.h"
00003 #include "filexml.h"
00004 #include "picon_png.h"
00005 #include "dot.h"
00006 #include "dotwindow.h"
00007 #include "effecttv.h"
00008 #include "language.h"
00009
00010 #include <stdint.h>
00011 #include <stdio.h>
00012 #include <string.h>
00013
00014
00015
00016
00017
00018
00019 REGISTER_PLUGIN(DotMain)
00020
00021
00022
00023
00024
00025
00026
00027 DotConfig::DotConfig()
00028 {
00029 dot_depth = 5;
00030 dot_size = 8;
00031 }
00032
00033
00034
00035
00036
00037 DotMain::DotMain(PluginServer *server)
00038 : PluginVClient(server)
00039 {
00040 pattern = 0;
00041 sampx = 0;
00042 sampy = 0;
00043 effecttv = 0;
00044 need_reconfigure = 1;
00045 PLUGIN_CONSTRUCTOR_MACRO
00046 }
00047
00048 DotMain::~DotMain()
00049 {
00050 PLUGIN_DESTRUCTOR_MACRO
00051
00052 if(pattern) delete [] pattern;
00053 if(sampx) delete [] sampx;
00054 if(sampy) delete [] sampy;
00055 if(effecttv)
00056 {
00057 delete dot_server;
00058 delete effecttv;
00059 }
00060 }
00061
00062 char* DotMain::plugin_title() { return N_("DotTV"); }
00063 int DotMain::is_realtime() { return 1; }
00064
00065 NEW_PICON_MACRO(DotMain)
00066
00067 SHOW_GUI_MACRO(DotMain, DotThread)
00068
00069 SET_STRING_MACRO(DotMain)
00070
00071 RAISE_WINDOW_MACRO(DotMain)
00072
00073
00074 int DotMain::load_defaults()
00075 {
00076 return 0;
00077 }
00078
00079 int DotMain::save_defaults()
00080 {
00081 return 0;
00082 }
00083
00084 void DotMain::load_configuration()
00085 {
00086 }
00087
00088
00089 void DotMain::save_data(KeyFrame *keyframe)
00090 {
00091 }
00092
00093 void DotMain::read_data(KeyFrame *keyframe)
00094 {
00095 }
00096
00097 void DotMain::make_pattern()
00098 {
00099 int i, x, y, c;
00100 int u, v;
00101 double p, q, r;
00102 uint32_t *pat;
00103
00104 for(i = 0; i < config.dot_max(); i++)
00105 {
00106
00107 pat = pattern + (i + 1) * dot_hsize * dot_hsize - 1;
00108
00109
00110
00111 r = ((double)i / config.dot_max()) * dot_hsize;
00112 r *= 5;
00113
00114
00115 for(y = 0; y < dot_hsize; y++)
00116 {
00117 for(x = 0; x < dot_hsize; x++)
00118 {
00119 c = 0;
00120 for(u = 0; u < 4; u++)
00121 {
00122 p = (double)u / 4.0 + y;
00123 p = p * p;
00124
00125 for(v = 0; v < 4; v++)
00126 {
00127 q = (double)v / 4.0 + x;
00128
00129 if(p + q * q < r)
00130 {
00131 c++;
00132 }
00133 }
00134 }
00135
00136
00137 c = (c > 15) ? 15 : c;
00138
00139 *pat-- = (c << 20) | (c << 12) | (c << 4);
00140
00141
00142 }
00143 }
00144 }
00145 }
00146
00147 void DotMain::init_sampxy_table()
00148 {
00149 int i, j;
00150
00151
00152 j = dot_hsize;
00153 for(i = 0; i < dots_width; i++)
00154 {
00155 sampx[i] = j;
00156 j += dot_size;
00157 }
00158 j = dot_hsize;
00159 for(i = 0; i < dots_height; i++)
00160 {
00161 sampy[i] = j;
00162 j += dot_size;
00163 }
00164 }
00165
00166
00167 void DotMain::reconfigure()
00168 {
00169 if(!effecttv)
00170 {
00171 effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
00172 dot_server = new DotServer(this, 1, 1);
00173 }
00174
00175 dot_size = config.dot_size;
00176 dot_size = dot_size & 0xfe;
00177 dot_hsize = dot_size / 2;
00178 dots_width = input_ptr->get_w() / dot_size;
00179 dots_height = input_ptr->get_h() / dot_size;
00180 pattern = new uint32_t[config.dot_max() *
00181 dot_hsize *
00182 dot_hsize];
00183 sampx = new int[input_ptr->get_w()];
00184 sampy = new int[input_ptr->get_h()];
00185
00186 make_pattern();
00187
00188 init_sampxy_table();
00189
00190
00191 need_reconfigure = 0;
00192 }
00193
00194
00195
00196 int DotMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
00197 {
00198 this->input_ptr = input_ptr;
00199 this->output_ptr = output_ptr;
00200 load_configuration();
00201 if(need_reconfigure) reconfigure();
00202
00203
00204 dot_server->process_packages();
00205
00206 return 0;
00207 }
00208
00209
00210
00211 DotServer::DotServer(DotMain *plugin, int total_clients, int total_packages)
00212 : LoadServer(total_clients, total_packages)
00213 {
00214 this->plugin = plugin;
00215 }
00216
00217
00218 LoadClient* DotServer::new_client()
00219 {
00220 return new DotClient(this);
00221 }
00222
00223
00224
00225
00226 LoadPackage* DotServer::new_package()
00227 {
00228 return new DotPackage;
00229 }
00230
00231
00232
00233 void DotServer::init_packages()
00234 {
00235 for(int i = 0; i < get_total_packages(); i++)
00236 {
00237 DotPackage *package = (DotPackage*)get_package(i);
00238 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
00239 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
00240 }
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250 DotClient::DotClient(DotServer *server)
00251 : LoadClient(server)
00252 {
00253 this->plugin = server->plugin;
00254 }
00255
00256 #define COPY_PIXEL(type, components, output, pattern, chroma_offset) \
00257 { \
00258 if(chroma_offset) \
00259 { \
00260 if(sizeof(type) == 2) \
00261 { \
00262 output[0] = (pattern & 0xff0000) >> 8; \
00263 output[1] = chroma_offset; \
00264 output[2] = chroma_offset; \
00265 if(components > 3) output[3] = 0xffff; \
00266 } \
00267 else \
00268 { \
00269 output[0] = (pattern & 0xff0000) >> 16; \
00270 output[1] = chroma_offset; \
00271 output[2] = chroma_offset; \
00272 if(components > 3) output[3] = 0xff; \
00273 } \
00274 } \
00275 else \
00276 { \
00277 if(sizeof(type) == 4) \
00278 { \
00279 output[0] = (type)(pattern & 0xff0000) / 0xff0000; \
00280 output[1] = (type)(pattern & 0xff00) / 0xff00; \
00281 output[2] = (type)(pattern & 0xff) / 0xff; \
00282 if(components > 3) output[3] = 1; \
00283 } \
00284 else \
00285 if(sizeof(type) == 2) \
00286 { \
00287 output[0] = (pattern & 0xff0000) >> 8; \
00288 output[1] = (pattern & 0xff00); \
00289 output[2] = (pattern & 0xff) << 8; \
00290 if(components > 3) output[3] = 0xffff; \
00291 } \
00292 else \
00293 { \
00294 output[0] = (pattern & 0xff0000) >> 16; \
00295 output[1] = (pattern & 0xff00) >> 8; \
00296 output[2] = (pattern & 0xff); \
00297 if(components > 3) output[3] = 0xff; \
00298 } \
00299 } \
00300 }
00301
00302 #define DRAW_DOT(type, components, chroma_offset) \
00303 { \
00304 int x, y; \
00305 uint32_t *pat; \
00306 type *output; \
00307 int y_total = 0; \
00308 \
00309 c = (c >> (8 - plugin->config.dot_depth)); \
00310 pat = plugin->pattern + c * plugin->dot_hsize * plugin->dot_hsize; \
00311 output = ((type**)output_rows)[0] + \
00312 yy * \
00313 plugin->dot_size * \
00314 plugin->input_ptr->get_w() * \
00315 components + \
00316 xx * \
00317 plugin->dot_size * \
00318 components; \
00319 \
00320 for(y = 0; y < plugin->dot_hsize && y_total < plugin->input_ptr->get_h(); y++) \
00321 { \
00322 for(x = 0; x < plugin->dot_hsize; x++) \
00323 { \
00324 COPY_PIXEL(type, components, output, *pat, chroma_offset); \
00325 output += components; \
00326 pat++; \
00327 } \
00328 \
00329 pat -= 2; \
00330 \
00331 for(x = 0; x < plugin->dot_hsize - 1; x++) \
00332 { \
00333 COPY_PIXEL(type, components, output, *pat, chroma_offset); \
00334 output += components; \
00335 pat--; \
00336 } \
00337 \
00338 COPY_PIXEL(type, components, output, 0x00000000, chroma_offset); \
00339 \
00340 output += components * (plugin->input_ptr->get_w() - plugin->dot_size + 1); \
00341 pat += plugin->dot_hsize + 1; \
00342 y_total++; \
00343 } \
00344 \
00345 pat -= plugin->dot_hsize * 2; \
00346 \
00347 for(y = 0; y < plugin->dot_hsize && y_total < plugin->input_ptr->get_h(); y++) \
00348 { \
00349 if(y < plugin->dot_hsize - 1) \
00350 { \
00351 for(x = 0; x < plugin->dot_hsize; x++) \
00352 { \
00353 COPY_PIXEL(type, components, output, *pat, chroma_offset); \
00354 output += components; \
00355 pat++; \
00356 } \
00357 \
00358 pat -= 2; \
00359 \
00360 for(x = 0; x < plugin->dot_hsize - 1; x++) \
00361 { \
00362 COPY_PIXEL(type, components, output, *pat, chroma_offset); \
00363 output += components; \
00364 pat--; \
00365 } \
00366 \
00367 COPY_PIXEL(type, components, output, 0x00000000, chroma_offset); \
00368 \
00369 output += components * (plugin->input_ptr->get_w() - plugin->dot_size + 1); \
00370 pat += -plugin->dot_hsize + 1; \
00371 } \
00372 else \
00373 { \
00374 for(x = 0; x < plugin->dot_hsize * 2; x++) \
00375 { \
00376 COPY_PIXEL(type, components, output, 0x00000000, chroma_offset); \
00377 output += components; \
00378 } \
00379 } \
00380 \
00381 y_total++; \
00382 \
00383 } \
00384 }
00385
00386 void DotClient::draw_dot(int xx,
00387 int yy,
00388 unsigned char c,
00389 unsigned char **output_rows,
00390 int color_model)
00391 {
00392 switch(plugin->input_ptr->get_color_model())
00393 {
00394 case BC_RGB888:
00395 DRAW_DOT(uint8_t, 3, 0x0);
00396 break;
00397
00398 case BC_RGB_FLOAT:
00399 DRAW_DOT(float, 3, 0x0);
00400 break;
00401
00402 case BC_YUV888:
00403 DRAW_DOT(uint8_t, 3, 0x80);
00404 break;
00405
00406 case BC_RGBA_FLOAT:
00407 DRAW_DOT(float, 4, 0x0);
00408 break;
00409
00410 case BC_RGBA8888:
00411 DRAW_DOT(uint8_t, 4, 0x0);
00412 break;
00413
00414 case BC_YUVA8888:
00415 DRAW_DOT(uint8_t, 4, 0x80);
00416 break;
00417
00418 case BC_RGB161616:
00419 DRAW_DOT(uint16_t, 3, 0x0);
00420 break;
00421
00422 case BC_YUV161616:
00423 DRAW_DOT(uint16_t, 3, 0x8000);
00424 break;
00425
00426 case BC_RGBA16161616:
00427 DRAW_DOT(uint16_t, 4, 0x0);
00428 break;
00429 case BC_YUVA16161616:
00430 DRAW_DOT(uint16_t, 4, 0x8000);
00431 break;
00432 }
00433 }
00434
00435 #define RGB_TO_Y(type, is_yuv) \
00436 { \
00437 type *row_local = (type*)row; \
00438 \
00439 if(sizeof(type) == 4) \
00440 { \
00441 int r = (int)(row_local[0] * 0xff); \
00442 int g = (int)(row_local[0] * 0xff); \
00443 int b = (int)(row_local[0] * 0xff); \
00444 CLAMP(r, 0, 0xff); \
00445 CLAMP(g, 0, 0xff); \
00446 CLAMP(b, 0, 0xff); \
00447 i = plugin->effecttv->RtoY[r] + \
00448 plugin->effecttv->RtoY[g] + \
00449 plugin->effecttv->RtoY[b]; \
00450 } \
00451 else \
00452 if(sizeof(type) == 2) \
00453 { \
00454 if(is_yuv) \
00455 i = (int)row_local[0] >> 8; \
00456 else \
00457 { \
00458 i = plugin->effecttv->RtoY[(int)row_local[0] >> 8]; \
00459 i += plugin->effecttv->GtoY[(int)row_local[1] >> 8]; \
00460 i += plugin->effecttv->BtoY[(int)row_local[2] >> 8]; \
00461 } \
00462 } \
00463 else \
00464 { \
00465 if(is_yuv) \
00466 i = (int)row_local[0]; \
00467 else \
00468 { \
00469 i = plugin->effecttv->RtoY[(int)row_local[0]]; \
00470 i += plugin->effecttv->GtoY[(int)row_local[1]]; \
00471 i += plugin->effecttv->BtoY[(int)row_local[2]]; \
00472 } \
00473 } \
00474 }
00475
00476 unsigned char DotClient::RGBtoY(unsigned char *row, int color_model)
00477 {
00478 unsigned char i;
00479
00480 switch(color_model)
00481 {
00482 case BC_RGB888:
00483 case BC_RGBA8888:
00484 RGB_TO_Y(uint8_t, 0);
00485 break;
00486 case BC_RGB_FLOAT:
00487 case BC_RGBA_FLOAT:
00488 RGB_TO_Y(float, 0);
00489 break;
00490 case BC_YUV888:
00491 case BC_YUVA8888:
00492 RGB_TO_Y(uint8_t, 1);
00493 break;
00494 case BC_RGB161616:
00495 case BC_RGBA16161616:
00496 RGB_TO_Y(uint16_t, 0);
00497 break;
00498 case BC_YUV161616:
00499 case BC_YUVA16161616:
00500 RGB_TO_Y(uint16_t, 1);
00501 break;
00502 }
00503
00504 return i;
00505 }
00506
00507
00508 void DotClient::process_package(LoadPackage *package)
00509 {
00510 int x, y;
00511 int sx, sy;
00512 DotPackage *local_package = (DotPackage*)package;
00513 unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
00514 unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
00515 int width = plugin->input_ptr->get_w();
00516 int height = local_package->row2 - local_package->row1;
00517
00518
00519 for(y = 0; y < plugin->dots_height; y++)
00520 {
00521 sy = plugin->sampy[y];
00522 for(x = 0; x < plugin->dots_width; x++)
00523 {
00524 sx = plugin->sampx[x];
00525
00526
00527
00528
00529 draw_dot(x,
00530 y,
00531 RGBtoY(&input_rows[sy][sx * plugin->input_ptr->get_bytes_per_pixel()],
00532 plugin->input_ptr->get_color_model()),
00533 output_rows,
00534 plugin->input_ptr->get_color_model());
00535 }
00536 }
00537 }
00538
00539
00540
00541 DotPackage::DotPackage()
00542 {
00543 }
00544
00545
00546