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
23 #include "bccmodels.h"
26 #include "dotwindow.h"
39 REGISTER_PLUGIN(DotMain)
47 DotConfig::DotConfig()
57 DotMain::DotMain(PluginServer *server)
58 : PluginVClient(server)
72 if(pattern) delete [] pattern;
73 if(sampx) delete [] sampx;
74 if(sampy) delete [] sampy;
82 const char* DotMain::plugin_title() { return N_("DotTV"); }
83 int DotMain::is_realtime() { return 1; }
85 NEW_WINDOW_MACRO(DotMain, DotWindow)
89 int DotMain::load_configuration()
95 void DotMain::save_data(KeyFrame *keyframe)
99 void DotMain::read_data(KeyFrame *keyframe)
103 void DotMain::make_pattern()
110 for(i = 0; i < config.dot_max(); i++)
112 /* Generated pattern is a quadrant of a disk. */
113 pat = pattern + (i + 1) * dot_hsize * dot_hsize - 1;
115 // r = (0.2 * i / config.dot_max() + 0.8) * dot_hsize;
117 r = ((double)i / config.dot_max()) * dot_hsize;
119 //printf("make_pattern %f\n", r);
121 for(y = 0; y < dot_hsize; y++)
123 for(x = 0; x < dot_hsize; x++)
126 for(u = 0; u < 4; u++)
128 p = (double)u / 4.0 + y;
131 for(v = 0; v < 4; v++)
133 q = (double)v / 4.0 + x;
143 c = (c > 15) ? 15 : c;
144 //printf("DotMain::make_pattern %d\n", c);
145 *pat-- = (c << 20) | (c << 12) | (c << 4);
146 /* The upper left part of a disk is needed, but generated pattern is a bottom
147 * right part. So I spin the pattern. */
153 void DotMain::init_sampxy_table()
159 for(i = 0; i < dots_width; i++)
165 for(i = 0; i < dots_height; i++)
173 void DotMain::reconfigure()
177 effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
178 dot_server = new DotServer(this, 1, 1);
181 dot_size = config.dot_size;
182 dot_size = dot_size & 0xfe;
183 dot_hsize = dot_size / 2;
184 dots_width = input_ptr->get_w() / dot_size;
185 dots_height = input_ptr->get_h() / dot_size;
186 pattern = new uint32_t[config.dot_max() *
189 sampx = new int[input_ptr->get_w()];
190 sampy = new int[input_ptr->get_h()];
197 need_reconfigure = 0;
202 int DotMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
204 this->input_ptr = input_ptr;
205 this->output_ptr = output_ptr;
206 load_configuration();
207 if(need_reconfigure) reconfigure();
210 dot_server->process_packages();
217 DotServer::DotServer(DotMain *plugin, int total_clients, int total_packages)
218 : LoadServer(total_clients, total_packages)
220 this->plugin = plugin;
224 LoadClient* DotServer::new_client()
226 return new DotClient(this);
232 LoadPackage* DotServer::new_package()
234 return new DotPackage;
239 void DotServer::init_packages()
241 for(int i = 0; i < get_total_packages(); i++)
243 DotPackage *package = (DotPackage*)get_package(i);
244 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
245 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
256 DotClient::DotClient(DotServer *server)
259 this->plugin = server->plugin;
262 #define COPY_uint16_t_0x8000_PIXEL(components, output, pattern) \
264 output[0] = (pattern & 0xff0000) >> 8; \
265 output[1] = output[2] = 0x8000; \
266 if(components > 3) output[3] = 0xffff; \
268 #define COPY_uint8_t_0x80_PIXEL(components, output, pattern) \
270 output[0] = (pattern & 0xff0000) >> 16; \
271 output[1] = output[2] = 0x80; \
272 if(components > 3) output[3] = 0xff; \
275 #define COPY_float_0x0_PIXEL(components, output, pattern) \
277 output[0] = (float)(pattern & 0xff0000) / 0xff0000; \
278 output[1] = (float)(pattern & 0xff00) / 0xff00; \
279 output[2] = (float)(pattern & 0xff) / 0xff; \
280 if(components > 3) output[3] = 1; \
282 #define COPY_uint16_t_0x0_PIXEL(components, output, pattern) \
284 output[0] = (pattern & 0xff0000) >> 8; \
285 output[1] = (pattern & 0xff00); \
286 output[2] = (pattern & 0xff) << 8; \
287 if(components > 3) output[3] = 0xffff; \
289 #define COPY_uint8_t_0x0_PIXEL(components, output, pattern) \
291 output[0] = (pattern & 0xff0000) >> 16; \
292 output[1] = (pattern & 0xff00) >> 8; \
293 output[2] = (pattern & 0xff); \
294 if(components > 3) output[3] = 0xff; \
297 #define DRAW_DOT(type, components, chroma) \
304 c = (c >> (8 - plugin->config.dot_depth)); \
305 pat = plugin->pattern + c * plugin->dot_hsize * plugin->dot_hsize; \
306 output = ((type**)output_rows)[0] + \
307 yy * plugin->dot_size * plugin->input_ptr->get_w() * components + \
308 xx * plugin->dot_size * components; \
310 for(y = 0; y < plugin->dot_hsize && y_total < plugin->input_ptr->get_h(); y++) \
312 for(x = 0; x < plugin->dot_hsize; x++) { \
313 COPY_##type##_##chroma##_PIXEL(components, output, *pat); \
314 output += components; \
318 for(x = 0; x < plugin->dot_hsize - 1; x++) { \
319 COPY_##type##_##chroma##_PIXEL(components, output, *pat); \
320 output += components; \
323 COPY_##type##_##chroma##_PIXEL(components, output, 0x00000000); \
324 output += components * (plugin->input_ptr->get_w() - plugin->dot_size + 1); \
325 pat += plugin->dot_hsize + 1; \
329 pat -= plugin->dot_hsize * 2; \
331 for(y = 0; y < plugin->dot_hsize && y_total < plugin->input_ptr->get_h(); y++) \
333 if(y < plugin->dot_hsize - 1) { \
334 for(x = 0; x < plugin->dot_hsize; x++) { \
335 COPY_##type##_##chroma##_PIXEL(components, output, *pat); \
336 output += components; \
340 for(x = 0; x < plugin->dot_hsize - 1; x++) { \
341 COPY_##type##_##chroma##_PIXEL(components, output, *pat); \
342 output += components; \
345 COPY_##type##_##chroma##_PIXEL(components, output, 0x00000000); \
346 output += components * (plugin->input_ptr->get_w() - plugin->dot_size + 1); \
347 pat += -plugin->dot_hsize + 1; \
350 for(x = 0; x < plugin->dot_hsize * 2; x++) { \
351 COPY_##type##_##chroma##_PIXEL(components, output, 0x00000000); \
352 output += components; \
360 void DotClient::draw_dot(int xx,
363 unsigned char **output_rows,
366 switch(plugin->input_ptr->get_color_model())
369 DRAW_DOT(uint8_t, 3, 0x0);
373 DRAW_DOT(float, 3, 0x0);
377 DRAW_DOT(uint8_t, 3, 0x80);
381 DRAW_DOT(float, 4, 0x0);
385 DRAW_DOT(uint8_t, 4, 0x0);
389 DRAW_DOT(uint8_t, 4, 0x80);
393 DRAW_DOT(uint16_t, 3, 0x0);
397 DRAW_DOT(uint16_t, 3, 0x8000);
400 case BC_RGBA16161616:
401 DRAW_DOT(uint16_t, 4, 0x0);
403 case BC_YUVA16161616:
404 DRAW_DOT(uint16_t, 4, 0x8000);
409 #define RGB_TO_Y(type, is_yuv) \
411 type *row_local = (type*)row; \
413 if(sizeof(type) == 4) \
415 int r = (int)(row_local[0] * 0xff); \
416 int g = (int)(row_local[0] * 0xff); \
417 int b = (int)(row_local[0] * 0xff); \
421 result = plugin->effecttv->RtoY[r] + \
422 plugin->effecttv->RtoY[g] + \
423 plugin->effecttv->RtoY[b]; \
426 if(sizeof(type) == 2) \
429 result = (int)row_local[0] >> 8; \
432 result = plugin->effecttv->RtoY[(int)row_local[0] >> 8]; \
433 result += plugin->effecttv->GtoY[(int)row_local[1] >> 8]; \
434 result += plugin->effecttv->BtoY[(int)row_local[2] >> 8]; \
440 result = (int)row_local[0]; \
443 result = plugin->effecttv->RtoY[(int)row_local[0]]; \
444 result += plugin->effecttv->GtoY[(int)row_local[1]]; \
445 result += plugin->effecttv->BtoY[(int)row_local[2]]; \
450 unsigned char DotClient::RGBtoY(unsigned char *row, int color_model)
452 unsigned char result = 0;
458 RGB_TO_Y(uint8_t, 0);
466 RGB_TO_Y(uint8_t, 1);
469 case BC_RGBA16161616:
470 RGB_TO_Y(uint16_t, 0);
473 case BC_YUVA16161616:
474 RGB_TO_Y(uint16_t, 1);
482 void DotClient::process_package(LoadPackage *package)
486 DotPackage *local_package = (DotPackage*)package;
487 unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
488 unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
489 //int width = plugin->input_ptr->get_w();
490 //int height = local_package->row2 - local_package->row1;
493 for(y = 0; y < plugin->dots_height; y++)
495 sy = plugin->sampy[y];
496 for(x = 0; x < plugin->dots_width; x++)
498 sx = plugin->sampx[x];
500 //printf("DotClient::process_package %d\n",
501 // RGBtoY(&input_rows[sy][sx * plugin->input_ptr->get_bytes_per_pixel()],
502 // plugin->input_ptr->get_color_model()));
505 RGBtoY(&input_rows[sy][sx * plugin->input_ptr->get_bytes_per_pixel()],
506 plugin->input_ptr->get_color_model()),
508 plugin->input_ptr->get_color_model());
515 DotPackage::DotPackage()