00001 #include "colormodels.h"
00002 #include "effecttv.h"
00003 #include "plugincolors.h"
00004 #include "vframe.h"
00005
00006 #include <stdint.h>
00007 #include <stdio.h>
00008
00009
00010
00011 unsigned int EffectTV::fastrand_val = 0;
00012
00013 EffectTV::EffectTV(int w, int h)
00014 {
00015 this->w = w;
00016 this->h = h;
00017 background = (unsigned char*)new uint16_t[w * h];
00018 diff = new unsigned char[w * h];
00019 diff2 = new unsigned char[w * h];
00020 yuv_init();
00021 yuv = new YUV;
00022 }
00023
00024 EffectTV::~EffectTV()
00025 {
00026 delete [] background;
00027 delete [] diff;
00028 delete [] diff2;
00029 delete yuv;
00030 }
00031
00032
00033 int EffectTV::yuv_init()
00034 {
00035 int i;
00036
00037 for(i = 0; i < 256; i++)
00038 {
00039 YtoRGB[i] = (int)( 1.164 * (i - 16));
00040 VtoR[i] = (int)( 1.596 * (i - 128));
00041 VtoG[i] = (int)(-0.813 * (i - 128));
00042 UtoG[i] = (int)(-0.391 * (i - 128));
00043 UtoB[i] = (int)( 2.018 * (i - 128));
00044 RtoY[i] = (int)( 0.257 * i);
00045 RtoU[i] = (int)(-0.148 * i);
00046 RtoV[i] = (int)( 0.439 * i);
00047 GtoY[i] = (int)( 0.504 * i);
00048 GtoU[i] = (int)(-0.291 * i);
00049 GtoV[i] = (int)(-0.368 * i);
00050 BtoY[i] = (int)( 0.098 * i);
00051 BtoV[i] = (int)(-0.071 * i);
00052
00053 }
00054 return 0;
00055 }
00056
00057
00058 #define FRAME_TO_EFFECTTV(type, components) \
00059 { \
00060 for(int i = 0; i < width; i++) \
00061 { \
00062 uint32_t *row = tmp + i * width * sizeof(uint32_t); \
00063 type *input_row = ((type**)frame->get_rows())[i]; \
00064 \
00065 for(int j = 0; j < width; j++) \
00066 { \
00067 if(sizeof(type) == 1) \
00068 { \
00069 row[j * sizeof(uint32_t)] = ((uint32_t)input_row[0]) << 16; \
00070 row[j * sizeof(uint32_t)] |= ((uint32_t)input_row[1]) << 8; \
00071 row[j * sizeof(uint32_t)] |= input_row[2]; \
00072 } \
00073 else \
00074 { \
00075 row[j * sizeof(uint32_t)] = ((uint32_t)input_row[0]) << 8; \
00076 row[j * sizeof(uint32_t)] |= ((uint32_t)input_row[1]); \
00077 row[j * sizeof(uint32_t)] |= input_row[2] >> 8; \
00078 } \
00079 input_row += components; \
00080 row++; \
00081 } \
00082 } \
00083 }
00084
00085
00086 void EffectTV::frame_to_effecttv(VFrame *frame, uint32_t *tmp)
00087 {
00088 int width = frame->get_w();
00089 int height = frame->get_h();
00090
00091 switch(frame->get_color_model())
00092 {
00093 case BC_RGB888:
00094 case BC_YUV888:
00095 FRAME_TO_EFFECTTV(uint8_t, 3);
00096 break;
00097
00098 case BC_RGBA8888:
00099 case BC_YUVA8888:
00100 FRAME_TO_EFFECTTV(uint8_t, 4);
00101 break;
00102
00103 case BC_RGB161616:
00104 case BC_YUV161616:
00105 FRAME_TO_EFFECTTV(uint16_t, 3);
00106 break;
00107
00108 case BC_RGBA16161616:
00109 case BC_YUVA16161616:
00110 FRAME_TO_EFFECTTV(uint16_t, 4);
00111 break;
00112 }
00113 }
00114
00115
00116
00117 #define EFFECTTV_TO_FRAME(type, components) \
00118 { \
00119 for(int i = 0; i < width; i++) \
00120 { \
00121 uint32_t *row = tmp + i * width * sizeof(uint32_t); \
00122 type *output_row = ((type**)frame->get_rows())[i]; \
00123 \
00124 for(int j = 0; j < width; j++) \
00125 { \
00126 if(sizeof(type) == 1) \
00127 { \
00128 output_row[0] = (row[j * sizeof(uint32_t)] & 0xff0000) >> 16; \
00129 output_row[1] = (row[j * sizeof(uint32_t)] & 0xff00) >> 8; \
00130 output_row[2] = row[j * sizeof(uint32_t)] & 0xff; \
00131 if(components == 4) output_row[3] = 0xff; \
00132 } \
00133 else \
00134 { \
00135 output_row[0] = (row[j * sizeof(uint32_t)] & 0xff0000) >> 8; \
00136 output_row[1] = row[j * sizeof(uint32_t)] & 0xff00; \
00137 output_row[2] = (row[j * sizeof(uint32_t)] & 0xff) << 8; \
00138 if(components == 4) output_row[3] = 0xffff; \
00139 } \
00140 output_row += components; \
00141 row++; \
00142 } \
00143 } \
00144 }
00145
00146
00147 void EffectTV::effecttv_to_frame(VFrame *frame, uint32_t *tmp)
00148 {
00149 int width = frame->get_w();
00150 int height = frame->get_h();
00151
00152 switch(frame->get_color_model())
00153 {
00154 case BC_RGB888:
00155 case BC_YUV888:
00156 EFFECTTV_TO_FRAME(uint8_t, 3);
00157 break;
00158
00159 case BC_RGBA8888:
00160 case BC_YUVA8888:
00161 EFFECTTV_TO_FRAME(uint8_t, 4);
00162 break;
00163
00164 case BC_RGB161616:
00165 case BC_YUV161616:
00166 EFFECTTV_TO_FRAME(uint16_t, 3);
00167 break;
00168
00169 case BC_RGBA16161616:
00170 case BC_YUVA16161616:
00171 EFFECTTV_TO_FRAME(uint16_t, 4);
00172 break;
00173 }
00174 }
00175
00176
00177
00178 void EffectTV::image_set_threshold_y(int threshold)
00179 {
00180 y_threshold = threshold * 7;
00181 }
00182
00183
00184
00185
00186 #define IMAGE_BGSUBTRACT_UPDATE_Y(result, \
00187 input_rows, \
00188 type, \
00189 components, \
00190 is_yuv) \
00191 { \
00192 int i, j; \
00193 int R, G, B; \
00194 type *p; \
00195 int16_t *q; \
00196 unsigned char *r; \
00197 int v; \
00198 \
00199 q = (int16_t *)background; \
00200 r = diff; \
00201 \
00202 for(i = 0; i < h; i++) \
00203 { \
00204 p = (type*)input_rows[j]; \
00205 \
00206 for(j = 0; j < w; j++) \
00207 { \
00208 if(is_yuv && sizeof(type) == 2) \
00209 { \
00210 R = G = B = (int)p[0] >> 8; \
00211 R <<= 1; \
00212 G <<= 2; \
00213 } \
00214 else \
00215 if(is_yuv && sizeof(type) == 1) \
00216 { \
00217 R = G = B = (int)p[0]; \
00218 R <<= 1; \
00219 G <<= 2; \
00220 } \
00221 else \
00222 if(sizeof(type) == 4) \
00223 { \
00224 R = (int)(p[0] * 0x1ff); \
00225 G = (int)(p[1] * 0x3ff); \
00226 B = (int)(p[2] * 0xff); \
00227 CLAMP(R, 0, 0x1ff); \
00228 CLAMP(G, 0, 0x3ff); \
00229 CLAMP(B, 0, 0xff); \
00230 } \
00231 else \
00232 if(sizeof(type) == 2) \
00233 { \
00234 R = (int)p[0] >> (8 - 1); \
00235 G = (int)p[1] >> (8 - 2); \
00236 B = (int)p[2] >> 8; \
00237 } \
00238 else \
00239 { \
00240 R = (int)p[0] << 1; \
00241 G = (int)p[1] << 2; \
00242 B = (int)p[2]; \
00243 } \
00244 \
00245 v = (R + G + B) - (int)(*q); \
00246 *q = (int16_t)(R + G + B); \
00247 *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
00248 \
00249 p += components; \
00250 q++; \
00251 r++; \
00252 } \
00253 } \
00254 \
00255 result = diff; \
00256 }
00257
00258
00259
00260
00261
00262
00263
00264 unsigned char* EffectTV::image_bgsubtract_update_y(unsigned char **input_rows,
00265 unsigned char **output_rows,
00266 int color_model)
00267 {
00268 unsigned char *diff;
00269
00270
00271 switch(color_model)
00272 {
00273 case BC_RGB888:
00274 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
00275 input_rows,
00276 uint8_t,
00277 3,
00278 0);
00279 break;
00280 case BC_YUV888:
00281 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
00282 input_rows,
00283 uint8_t,
00284 3,
00285 1);
00286 break;
00287 case BC_RGB_FLOAT:
00288 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
00289 input_rows,
00290 float,
00291 3,
00292 0);
00293 break;
00294 case BC_RGBA8888:
00295 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
00296 input_rows,
00297 uint8_t,
00298 4,
00299 0);
00300 break;
00301 case BC_RGBA_FLOAT:
00302 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
00303 input_rows,
00304 float,
00305 4,
00306 0);
00307 break;
00308 case BC_YUVA8888:
00309 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
00310 input_rows,
00311 uint8_t,
00312 4,
00313 1);
00314 break;
00315 case BC_RGB161616:
00316 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
00317 input_rows,
00318 uint16_t,
00319 3,
00320 0);
00321 break;
00322 case BC_YUV161616:
00323 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
00324 input_rows,
00325 uint16_t,
00326 3,
00327 1);
00328 break;
00329 case BC_RGBA16161616:
00330 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
00331 input_rows,
00332 uint16_t,
00333 4,
00334 0);
00335 break;
00336 case BC_YUVA16161616:
00337 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
00338 input_rows,
00339 uint16_t,
00340 4,
00341 1);
00342 break;
00343 }
00344
00345 return diff;
00346 }
00347
00348
00349
00350
00351
00352
00353 #define IMAGE_BGSUBTRACT_Y(type, components, is_yuv) \
00354 { \
00355 int i, j; \
00356 int R, G, B; \
00357 type *p; \
00358 \
00359 for(i = 0; i < h; i++) \
00360 { \
00361 p = (type*)input_rows[i]; \
00362 \
00363 for(j = 0; j < w; j++) \
00364 { \
00365 if(is_yuv && sizeof(type) == 2) \
00366 { \
00367 R = G = B = (int)p[0] >> 8; \
00368 R <<= 1; \
00369 G <<= 2; \
00370 } \
00371 else \
00372 if(is_yuv && sizeof(type) == 1) \
00373 { \
00374 R = G = B = (int)p[0]; \
00375 R <<= 1; \
00376 G <<= 2; \
00377 } \
00378 else \
00379 if(sizeof(type) == 4) \
00380 { \
00381 R = (int)(p[0] * 0x1ff); \
00382 G = (int)(p[1] * 0x3ff); \
00383 B = (int)(p[2] * 0xff); \
00384 CLAMP(R, 0, 0x1ff); \
00385 CLAMP(G, 0, 0x3ff); \
00386 CLAMP(B, 0, 0xff); \
00387 } \
00388 else \
00389 if(sizeof(type) == 2) \
00390 { \
00391 R = (int)p[0] >> (8 - 1); \
00392 G = (int)p[1] >> (8 - 2); \
00393 B = (int)p[2] >> 8; \
00394 } \
00395 else \
00396 { \
00397 R = (int)p[0] << 1; \
00398 G = (int)p[1] << 2; \
00399 B = (int)p[2]; \
00400 } \
00401 \
00402 v = (R + G + B) - (int)(*q); \
00403 *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
00404 \
00405 p += components; \
00406 q++; \
00407 r++; \
00408 } \
00409 } \
00410 }
00411
00412
00413 unsigned char* EffectTV::image_bgsubtract_y(unsigned char **input_rows,
00414 int color_model)
00415 {
00416 int16_t *q;
00417 unsigned char *r;
00418 int v;
00419
00420 q = (int16_t *)background;
00421 r = diff;
00422
00423
00424
00425 switch(color_model)
00426 {
00427 case BC_RGB888:
00428 IMAGE_BGSUBTRACT_Y(uint8_t, 3, 0);
00429 break;
00430 case BC_YUV888:
00431 IMAGE_BGSUBTRACT_Y(uint8_t, 3, 1);
00432 break;
00433 case BC_RGB_FLOAT:
00434 IMAGE_BGSUBTRACT_Y(float, 3, 0);
00435 break;
00436 case BC_RGBA_FLOAT:
00437 IMAGE_BGSUBTRACT_Y(float, 4, 0);
00438 break;
00439 case BC_RGBA8888:
00440 IMAGE_BGSUBTRACT_Y(uint8_t, 4, 0);
00441 break;
00442 case BC_YUVA8888:
00443 IMAGE_BGSUBTRACT_Y(uint8_t, 4, 1);
00444 break;
00445 case BC_RGB161616:
00446 IMAGE_BGSUBTRACT_Y(uint16_t, 3, 0);
00447 break;
00448 case BC_YUV161616:
00449 IMAGE_BGSUBTRACT_Y(uint16_t, 3, 1);
00450 break;
00451 case BC_RGBA16161616:
00452 IMAGE_BGSUBTRACT_Y(uint16_t, 4, 0);
00453 break;
00454 case BC_YUVA16161616:
00455 IMAGE_BGSUBTRACT_Y(uint16_t, 4, 1);
00456 break;
00457 }
00458
00459
00460
00461 return diff;
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 }
00478
00479
00480
00481
00482
00483
00484 unsigned char* EffectTV::image_diff_filter(unsigned char *diff)
00485 {
00486 int x, y;
00487 unsigned char *src, *dest;
00488 unsigned int count;
00489 unsigned int sum1, sum2, sum3;
00490 int width = w;
00491 int height = h;
00492
00493 src = diff;
00494 dest = diff2 + width + 1;
00495 for(y = 1; y < height - 1; y++)
00496 {
00497 sum1 = src[0] + src[width] + src[width * 2];
00498 sum2 = src[1] + src[width + 1] + src[width * 2 + 1];
00499 src += 2;
00500
00501 for(x = 1; x < width - 1; x++)
00502 {
00503 sum3 = src[0] + src[width] + src[width * 2];
00504 count = sum1 + sum2 + sum3;
00505 sum1 = sum2;
00506 sum2 = sum3;
00507 *dest++ = (0xff * 3 - count) >> 24;
00508 src++;
00509 }
00510
00511 dest += 2;
00512 }
00513
00514 return diff2;
00515 }
00516
00517
00518
00519
00520
00521
00522 #define IMAGE_BGSET_Y(type, components, is_yuv) \
00523 { \
00524 int i, j; \
00525 int R, G, B; \
00526 type *p; \
00527 int16_t *q; \
00528 int width = frame->get_w(); \
00529 int height = frame->get_h(); \
00530 \
00531 q = (int16_t *)background; \
00532 \
00533 \
00534 \
00535 for(i = 0; i < height; i++) \
00536 { \
00537 p = (type*)frame->get_rows()[i]; \
00538 \
00539 for(j = 0; j < width; j++) \
00540 { \
00541 if(is_yuv && sizeof(type) == 2) \
00542 { \
00543 R = G = B = (int)p[0] >> 8; \
00544 R <<= 1; \
00545 G <<= 2; \
00546 } \
00547 else \
00548 if(is_yuv && sizeof(type) == 1) \
00549 { \
00550 R = G = B = (int)p[0]; \
00551 R <<= 1; \
00552 G <<= 2; \
00553 } \
00554 else \
00555 if(sizeof(type) == 4) \
00556 { \
00557 R = (int)(p[0] * 0x1ff); \
00558 G = (int)(p[1] * 0x3ff); \
00559 B = (int)(p[2] * 0xff); \
00560 CLAMP(R, 0, 0x1ff); \
00561 CLAMP(G, 0, 0x3ff); \
00562 CLAMP(B, 0, 0xff); \
00563 } \
00564 else \
00565 if(sizeof(type) == 2) \
00566 { \
00567 R = (int)p[0] >> (8 - 1); \
00568 G = (int)p[1] >> (8 - 2); \
00569 B = (int)p[2] >> 8; \
00570 } \
00571 else \
00572 { \
00573 R = (int)p[0] << 1; \
00574 G = (int)p[1] << 2; \
00575 B = (int)p[2]; \
00576 } \
00577 \
00578 *q = (int16_t)(R + G + B); \
00579 p += components; \
00580 \
00581 \
00582 q++; \
00583 } \
00584 } \
00585 }
00586
00587
00588
00589
00590
00591 void EffectTV::image_bgset_y(VFrame *frame)
00592 {
00593 switch(frame->get_color_model())
00594 {
00595 case BC_RGB888:
00596 IMAGE_BGSET_Y(uint8_t, 3, 0);
00597 break;
00598 case BC_RGB_FLOAT:
00599 IMAGE_BGSET_Y(float, 3, 0);
00600 break;
00601 case BC_YUV888:
00602 IMAGE_BGSET_Y(uint8_t, 3, 1);
00603 break;
00604 case BC_RGBA8888:
00605 IMAGE_BGSET_Y(uint8_t, 3, 0);
00606 break;
00607 case BC_RGBA_FLOAT:
00608 IMAGE_BGSET_Y(float, 3, 0);
00609 break;
00610 case BC_YUVA8888:
00611 IMAGE_BGSET_Y(uint8_t, 3, 1);
00612 break;
00613 case BC_RGB161616:
00614 IMAGE_BGSET_Y(uint16_t, 3, 0);
00615 break;
00616 case BC_YUV161616:
00617 IMAGE_BGSET_Y(uint16_t, 3, 1);
00618 break;
00619 case BC_RGBA16161616:
00620 IMAGE_BGSET_Y(uint16_t, 4, 0);
00621 break;
00622 case BC_YUVA16161616:
00623 IMAGE_BGSET_Y(uint16_t, 4, 1);
00624 break;
00625 }
00626 }
00627
00628