From c5e843b82205c04c618a423d3bb223f1f630b7a1 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 11 Aug 2003 04:26:00 +0000 Subject: added sources from pidip-0.12.4 svn path=/trunk/externals/pidip/; revision=837 --- modules/pdp_cmap.c | 539 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 539 insertions(+) create mode 100644 modules/pdp_cmap.c (limited to 'modules/pdp_cmap.c') diff --git a/modules/pdp_cmap.c b/modules/pdp_cmap.c new file mode 100644 index 0000000..3d8524f --- /dev/null +++ b/modules/pdp_cmap.c @@ -0,0 +1,539 @@ +/* + * PiDiP module + * Copyright (c) by Yves Degoyon ( ydegoyon@free.fr ) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* This object is a color mapper that lets you change the colors within the image + */ + +#include "pdp.h" +#include "yuv.h" +#include +#include + +struct _rtext +{ + char *x_buf; + int x_bufsize; + int x_selstart; + int x_selend; + int x_active; + int x_dragfrom; + int x_height; + int x_drawnwidth; + int x_drawnheight; + t_text *x_text; + t_glist *x_glist; + char x_tag[50]; + struct _rtext *x_next; +}; + +#define t_rtext struct _rtext + +extern int rtext_width(t_rtext *x); +extern int rtext_height(t_rtext *x); +extern t_rtext *glist_findrtext(t_glist *gl, t_text *who); + +typedef struct _color +{ + t_int on; + t_int y,u,v; + t_int oy,ou,ov; + t_int tolerance; +} t_color; + +#define COLORHEIGHT 5 +#define DEFAULT_CAPACITY 10 + +static char *pdp_cmap_version = "pdp_cmap: a color mapper version 0.1 written by Yves Degoyon (ydegoyon@free.fr)"; + +typedef struct pdp_cmap_struct +{ + t_object x_obj; + t_float x_f; + + t_int x_packet0; + t_int x_dropped; + + t_int x_vwidth; + t_int x_vheight; + t_int x_vsize; + + t_int x_capacity; // number of mapped colors + t_int x_current; // current color + t_color *x_colors; // color substitution table + + t_int x_cursor; // show cursor or not + t_int x_luminosity; // use luminosity or not + + t_int x_colorR; // setable r + t_int x_colorG; // setable g + t_int x_colorB; // setable b + + t_int x_cursX; // X coordinate of cursor + t_int x_cursY; // Y coordinate of cursor + short int *x_frame; // keep a copy of current frame for picking color + + t_outlet *x_pdp_output; // output packets + + t_canvas *x_canvas; + +} t_pdp_cmap; + +static void pdp_cmap_draw_color(t_pdp_cmap *x, t_int r, t_int g, t_int b) +{ + t_int width, height; + char color[32]; + + sprintf( color, "#%.2X%.2X%.2X", r, g, b ); + width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); + height = rtext_height( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) ); + sys_vgui(".x%x.c delete rectangle %xCOLOR\n", x->x_canvas, x ); + sys_vgui(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xCOLOR\n", + x->x_canvas, x->x_obj.te_xpix+width+5, x->x_obj.te_ypix, + x->x_obj.te_xpix+width+height+5, + x->x_obj.te_ypix+height, color, x ); +} + +static void pdp_cmap_r(t_pdp_cmap *x, t_floatarg fr ) +{ + if ( ( fr >= 0 ) && ( fr < 255 ) ) + { + x->x_colorR = (int)fr; + x->x_colors[x->x_current].y = (yuv_RGBtoY( (x->x_colorR << 16) + (x->x_colorG << 8) + x->x_colorB ))<<7; + x->x_colors[x->x_current].u = (yuv_RGBtoU( (x->x_colorR << 16) + (x->x_colorG << 8) + x->x_colorB )-128)<<8; + x->x_colors[x->x_current].v = (yuv_RGBtoV( (x->x_colorR << 16) + (x->x_colorG << 8) + x->x_colorB )-128)<<8; + pdp_cmap_draw_color( x, x->x_colorR, x->x_colorG, x->x_colorB ); + } +} + +static void pdp_cmap_g(t_pdp_cmap *x, t_floatarg fg ) +{ + if ( ( fg >= 0 ) && ( fg < 255 ) ) + { + x->x_colorG = (int)fg; + x->x_colors[x->x_current].y = (yuv_RGBtoY( (x->x_colorR << 16) + (x->x_colorG << 8) + x->x_colorB ))<<7; + x->x_colors[x->x_current].u = (yuv_RGBtoU( (x->x_colorR << 16) + (x->x_colorG << 8) + x->x_colorB )-128)<<8; + x->x_colors[x->x_current].v = (yuv_RGBtoV( (x->x_colorR << 16) + (x->x_colorG << 8) + x->x_colorB )-128)<<8; + pdp_cmap_draw_color( x, x->x_colorR, x->x_colorG, x->x_colorB ); + } +} + +static void pdp_cmap_b(t_pdp_cmap *x, t_floatarg fb ) +{ + if ( ( fb >= 0 ) && ( fb < 255 ) ) + { + x->x_colorB = (int)fb; + x->x_colors[x->x_current].y = (yuv_RGBtoY( (x->x_colorR << 16) + (x->x_colorG << 8) + x->x_colorB ))<<7; + x->x_colors[x->x_current].u = (yuv_RGBtoU( (x->x_colorR << 16) + (x->x_colorG << 8) + x->x_colorB )-128)<<8; + x->x_colors[x->x_current].v = (yuv_RGBtoV( (x->x_colorR << 16) + (x->x_colorG << 8) + x->x_colorB )-128)<<8; + pdp_cmap_draw_color( x, x->x_colorR, x->x_colorG, x->x_colorB ); + } +} + +static void pdp_cmap_cursx(t_pdp_cmap *x, t_floatarg fx ) +{ + if ( ( fx >= 0 ) && ( fx < x->x_vwidth) ) + { + x->x_cursX = (int)fx; + } +} + +static void pdp_cmap_cursy(t_pdp_cmap *x, t_floatarg fy ) +{ + if ( ( fy >= 0 ) && ( fy < x->x_vheight) ) + { + x->x_cursY = (int)fy; + } +} + +static void pdp_cmap_tolerance(t_pdp_cmap *x, t_floatarg ftolerance ) +{ + if ( ftolerance >= 0 ) + { + x->x_colors[x->x_current].tolerance = (int)ftolerance; + } +} + +static void pdp_cmap_luminosity(t_pdp_cmap *x, t_floatarg fluminosity ) +{ + if ( ( fluminosity == 0 ) || ( fluminosity == 1 ) ) + { + x->x_luminosity = (int)fluminosity; + } +} + +static void pdp_cmap_delete(t_pdp_cmap *x, t_floatarg fcolor ) +{ + if ( ( fcolor >= 0 ) && ( fcolor < x->x_capacity ) ) + { + x->x_colors[(int)fcolor].on = 0; + } +} + +static void pdp_cmap_clear(t_pdp_cmap *x) +{ + t_int ci; + + for ( ci=0; cix_capacity; ci++) + { + x->x_colors[ci].on = 0; + } + x->x_current = 0; +} + +static void pdp_cmap_resize(t_pdp_cmap *x, t_floatarg fnewsize ) +{ + t_color *colors; + t_int ci, csize; + + if ( (int) fnewsize<=0 ) return; + + // allocate new structures + colors = (t_color*) getbytes( fnewsize*sizeof(t_color) ); + + for ( ci=0; cix_capacity ) + { + post( "pdp_form : new size is too small : texts lost !!" ); + csize = fnewsize; + } + else + { + csize = x->x_capacity; + } + + // copy all values + for ( ci=0; cix_colors[ci], sizeof( t_color ) ); + } + + // free old structures + if ( x->x_colors ) freebytes( x->x_colors, x->x_capacity*sizeof(t_color) ); + + // set new structures + x->x_colors = colors; + x->x_capacity = fnewsize; + x->x_current = 0; +} + +static void pdp_cmap_setcur(t_pdp_cmap *x, t_floatarg fpx, t_floatarg fpy ) +{ + if ( (fpx>=0.0) && (fpx<=1.0) && (fpy>=0.0) && (fpy<=1.0) ) + { + x->x_cursX = fpx*(t_float)x->x_vwidth; + x->x_cursY = fpy*(t_float)x->x_vheight; + } +} + +static void pdp_cmap_current(t_pdp_cmap *x, t_floatarg fcurrent ) +{ + if ( ( fcurrent >= 0 ) && ( fcurrent < x->x_capacity ) ) + { + x->x_current = (int)fcurrent; + post( "pdp_cmap : color index set to : %d", x->x_current ); + } +} + +static void pdp_cmap_cursor(t_pdp_cmap *x, t_floatarg fcursor ) +{ + if ( ( fcursor == 0 ) || ( fcursor == 1 ) ) + { + x->x_cursor = (int)fcursor; + } +} + +static void pdp_cmap_pick(t_pdp_cmap *x) +{ + t_int y,u,v; + + if ( x->x_frame && ( x->x_cursX > 0 ) && ( x->x_cursX < x->x_vwidth ) + && ( x->x_cursY > 0 ) && ( x->x_cursY < x->x_vheight ) ) + { + x->x_colors[x->x_current].oy = x->x_frame[ x->x_cursY*x->x_vwidth+x->x_cursX ]; + x->x_colors[x->x_current].ov = x->x_frame[ x->x_vsize+((x->x_cursY>>1)*(x->x_vwidth>>1)+(x->x_cursX>>1)) ]; + x->x_colors[x->x_current].ou = x->x_frame[ x->x_vsize+(x->x_vsize>>2)+((x->x_cursY>>1)*(x->x_vwidth>>1)+(x->x_cursX>>1)) ]; + y = (x->x_colors[x->x_current].oy)>>7; + v = (x->x_colors[x->x_current].ov>>8)+128; + u = (x->x_colors[x->x_current].ou>>8)+128; + x->x_colorR = yuv_YUVtoR( y, u, v ); + x->x_colorG = yuv_YUVtoG( y, u, v ); + x->x_colorB = yuv_YUVtoB( y, u, v ); + pdp_cmap_draw_color( x, x->x_colorR, x->x_colorG, x->x_colorB ); + x->x_colors[x->x_current].y = 255; + x->x_colors[x->x_current].u = 255; + x->x_colors[x->x_current].v = 255; + x->x_colors[x->x_current].on = 1; + } +} + +static void pdp_cmap_allocate(t_pdp_cmap *x) +{ + x->x_frame = (short int *) getbytes ( ( x->x_vsize + ( x->x_vsize>>1 ) ) << 1 ); + + if ( !x->x_frame ) + { + post( "pdp_mgrid : severe error : cannot allocate buffer !!! "); + return; + } +} + +static void pdp_cmap_free_ressources(t_pdp_cmap *x) +{ + if ( x->x_frame ) freebytes ( x->x_frame, ( x->x_vsize + ( x->x_vsize>>1 ) ) << 1 ); +} + +static void pdp_cmap_process_yv12(t_pdp_cmap *x) +{ + t_pdp *header = pdp_packet_header(x->x_packet0); + short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_int i, ci; + t_int px=0, py=0, ppx=0, ppy=0; + t_int y=0, u=0, v=0; + short int *pfY, *pfU, *pfV; + short int *poY, *poU, *poV; + t_int diff; + + /* allocate all ressources */ + if ( ( (int)header->info.image.width != x->x_vwidth ) || + ( (int)header->info.image.height != x->x_vheight ) ) + { + pdp_cmap_free_ressources( x ); + x->x_vwidth = header->info.image.width; + x->x_vheight = header->info.image.height; + x->x_vsize = x->x_vwidth*x->x_vheight; + pdp_cmap_allocate( x ); + post( "pdp_cmap : reallocated buffers" ); + } + + memcpy(x->x_frame, data, (x->x_vsize + (x->x_vsize>>1))<<1 ); + + // map colors + for ( ci=0; cix_capacity; ci++ ) + { + if ( x->x_colors[ci].on ) + { + pfY = data; + pfV = data+x->x_vsize; + pfU = data+x->x_vsize+(x->x_vsize>>2); + poY = x->x_frame; + poV = x->x_frame+x->x_vsize; + poU = x->x_frame+x->x_vsize+(x->x_vsize>>2); + for ( py=0; pyx_vheight; py++ ) + { + for ( px=0; pxx_vwidth; px++ ) + { + y = *poY; + v = *poV; + u = *poU; + + if ( x->x_luminosity ) + { + diff = (abs(y-x->x_colors[ci].oy)>>7)+(abs(u-x->x_colors[ci].ou)>>8)+(abs(v-x->x_colors[ci].ov)>>8); + } + else + { + diff = (abs(u-x->x_colors[ci].ou)>>8)+(abs(v-x->x_colors[ci].ov)>>8); + } + + if ( diff <= x->x_colors[ci].tolerance ) + { + // change color not luminosity + // *pfY = x->x_colors[ci].y; + *pfV = x->x_colors[ci].v; + *pfU = x->x_colors[ci].u; + } + + pfY++;poY++; + if ( (px%2==0) && (py%2==0) ) + { + pfU++;pfV++; + poU++;poV++; + } + } + } + } + } + + // draw cursor + if ( ( x->x_cursX > 0 ) && ( x->x_cursY > 0 ) && ( x->x_cursor ) ) + { + for ( px=(x->x_cursX-5); px<=(x->x_cursX+5); px++ ) + { + if ( ( px > 0 ) && ( px < x->x_vwidth ) ) + { + if ( ((*(data+x->x_cursY*x->x_vwidth+px))>>7) < 128 ) + { + *(data+x->x_cursY*x->x_vwidth+px) = 0xff<<7; + } + else + { + *(data+x->x_cursY*x->x_vwidth+px) = 0x00<<7; + } + } + } + for ( py=(x->x_cursY-5); py<=(x->x_cursY+5); py++ ) + { + if ( ( py > 0 ) && ( py < x->x_vheight ) ) + { + if ( ((*(data+py*x->x_vwidth+x->x_cursX))>>7) < 128 ) + { + *(data+py*x->x_vwidth+x->x_cursX) = 0xff<<7; + } + else + { + *(data+py*x->x_vwidth+x->x_cursX) = 0x00<<7; + } + } + } + } + + pdp_packet_pass_if_valid(x->x_pdp_output, &x->x_packet0); + + return; +} + +static void pdp_cmap_process(t_pdp_cmap *x) +{ + int encoding; + t_pdp *header = 0; + + /* check if image data packets are compatible */ + if ( (header = pdp_packet_header(x->x_packet0)) + && (PDP_IMAGE == header->type)){ + + /* pdp_cmap_process inputs and write into active inlet */ + switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ + + case PDP_IMAGE_YV12: + pdp_cmap_process_yv12(x); + break; + + case PDP_IMAGE_GREY: + // should write something to handle these one day + // but i don't use this mode + break; + + default: + /* don't know the type, so dont pdp_cmap_process */ + break; + + } + } + +} + +static void pdp_cmap_input_0(t_pdp_cmap *x, t_symbol *s, t_floatarg f) +{ + /* if this is a register_ro message or register_rw message, register with packet factory */ + + if (s== gensym("register_rw")) + x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("image/YCrCb/*") ); + + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)){ + + pdp_cmap_process(x); + + } +} + +static void pdp_cmap_free(t_pdp_cmap *x) +{ + int i; + + pdp_packet_mark_unused(x->x_packet0); + pdp_cmap_free_ressources( x ); +} + +t_class *pdp_cmap_class; + +void *pdp_cmap_new(void) +{ + t_int ci; + + t_pdp_cmap *x = (t_pdp_cmap *)pd_new(pdp_cmap_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("current")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("cursx")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("cursy")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("R")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("G")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("B")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("tolerance")); + + x->x_pdp_output = outlet_new(&x->x_obj, &s_anything); + + x->x_packet0 = -1; + + x->x_cursX = -1; + x->x_cursY = -1; + x->x_cursor = 1; + x->x_luminosity = 1; + + x->x_capacity = DEFAULT_CAPACITY; + x->x_current = 0; + x->x_colors = (t_color *) getbytes( x->x_capacity*sizeof(t_color) ); + for ( ci=0; cix_capacity; ci++) + { + x->x_colors[ci].on = 0; + x->x_colors[ci].tolerance = 10; + } + + x->x_canvas = canvas_getcurrent(); + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_cmap_setup(void) +{ + post( pdp_cmap_version ); + pdp_cmap_class = class_new(gensym("pdp_cmap"), (t_newmethod)pdp_cmap_new, + (t_method)pdp_cmap_free, sizeof(t_pdp_cmap), 0, A_NULL); + + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_r, gensym("R"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_g, gensym("G"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_b, gensym("B"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_cursx, gensym("cursx"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_cursy, gensym("cursy"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_pick, gensym("pick"), A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_tolerance, gensym("tolerance"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_cursor, gensym("cursor"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_luminosity, gensym("luminosity"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_current, gensym("current"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_clear, gensym("clear"), A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_delete, gensym("delete"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_resize, gensym("resize"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_cmap_class, (t_method)pdp_cmap_setcur, gensym("setcur"), A_DEFFLOAT, A_DEFFLOAT, A_NULL); +} + +#ifdef __cplusplus +} +#endif -- cgit v1.2.1