// Please see the README file or the LEGAL NOTES-section in the manual before modifying, compiling or using 'xmrm' // Idea: Manfred Kopp // Programming: Gerhard Waldhör, Andreas Artmann #include #include "wavemorph.h" #include "morphvec.h" #include "io.h" #include "init.h" #include "xmrm.h" #include "const.h" //extern ControlClass control; extern PictureClass *s_pic, *d_pic, *result_pic; extern MorphVecClass *s_vec,*d_vec, *i_vec; extern FL_OBJECT *obj_s, *obj_d, *obj_vs, *obj_vd, *obj_m, *obj_a; extern WindowClass *m_win,*d_win; extern FD_MRM *fd_MRM; extern FD_RESULT *fd_RESULT; extern FD_MORPH *fd_MORPH; extern FD_AREAS *fd_AREAS; extern FD_SLID_CONTR *fd_SLID_CONTR; extern FD_VEC_MENU *fd_VEC_MENU; extern MyImageClass *cinema[MAX_PIC],*MyImage; //extern double Bias(double x_bias,double b_bias); extern ControlClass control; void Interpol_Bias() { int begin,end,k; double dist,add; if (control.advanced) { begin=control.select_level-1; end=control.select_level+1; if (begin<1) begin=1; else while (!fl_get_button(fd_MRM->BT_Level[begin-1])) begin--; if (end>MAX_LEVELS) end=MAX_LEVELS; else while (!fl_get_button(fd_MRM->BT_Level[end-1])) end++; // printf("begin: %d select: %d end: %d\n",begin,control.select_level,end); dist = (control.b_bias_val[control.select_level-1] - control.b_bias_val[begin-1]) / (control.select_level-begin); add=0; for (k=begin; kw; scale_y = (double)obj->h; step_x = 1.0/(double)obj->h; if (fl_get_button(fd_MRM->CB_Use_Wavelets)) l=MAX_LEVELS; else l=1; for (i=0; iBT_Level[i])) col=FL_BLUE; else col=FL_BLACK; if (i == (control.select_level-1)) col=FL_RED; for (j=0; j<=(obj->h-1); j++) { y_old = (int)(y_val*scale_y); y_val = Bias(x_val,control.b_bias_val[i]); fl_line(x_old, obj->h-1 - y_old, (int)(x_val*scale_x), obj->h-1 - (int)(y_val*scale_y), col); x_old = (int)(x_val*scale_x); x_val += step_x; } y_old = (int)(y_val*scale_y); y_val = Bias(x_val,control.b_bias_val[i]); fl_line(x_old, obj->h-1 - y_old, (int)(x_val*scale_x), obj->h-1 - (int)(y_val*scale_y), col); } } #define M_SIZE 4 void Gauss_Eliminate(double A[M_SIZE][M_SIZE],double b[M_SIZE],int n) { int p,q,i,j; double op; /* ONLY FOR REGULAR EQUATION-SYSTEMS, NO Pivot-Strategy implemented (But that's enough for our purposes) */ // First form a triangle matrix: for (q=0; q=0; p--) { op=0; for (q=p+1; q=0; j--) { A[0][j]=op1; A[1][j]=op2; op1=op1*P[i][0]; op2=op2*P[i+1][0]; } b[0]=P[i][1]; b[1]=P[i+1][1]; // f'(x_l) = s_l ; f'(x_r) = s_r A[2][3]=0; A[3][3]=0; A[2][2]=1; A[3][2]=1; op1=P[i][0]; op2=P[i+1][0]; A[2][1]=2*op1; A[3][1]=2*op2; A[2][0]=3*op1*op1; A[3][0]=3*op2*op2; b[2]=s[i]; b[3]=s[i+1]; // Solve Equations with Gaussean Algorithm: Gauss_Eliminate(A,b,i); } } double Get_Akima(double x) { int i,j; double op,result; // correctction of right border: if (x>=0.999) x=0.999; // Search the rigth segment: j=0; while (control.akima_P[j][0] <= x) j++; j--; // Calculate y=akima_f(x)=ax^3+bx^2+cx+d; op=1; result=0; for (i=3; i>=0; i--) { result += control.akima_f[j][i]*op; op *= x; } return result; } void Draw_Akima(FL_OBJECT *obj) { int i,j,k,ox,oy,bx,by; double x,y,dx; Calc_Akima(control.akima_P); bx=obj->x; by=obj->y+obj->h; ox=0; oy=(int)(Get_Akima(0)*obj->h); x=0; y=0; dx=1 / (double)obj->w; for (k=0; kw; k++) { y=Get_Akima(x); j=(int)((double)y*obj->h); fl_line(bx+ox,by-oy,bx+k,by-j,FL_BLUE); ox=k; oy=j; x+=dx; } } void Draw_Akima_Points(FL_OBJECT *obj, int colored_point) { int i,x,y; for (i=0; i<(control.akima_nr); i++) { x=obj->x-POINT_SIZE/2 + (int)(control.akima_P[i][0]*(double)obj->w); y=obj->y+obj->h-POINT_SIZE/2 - (int)(control.akima_P[i][1]*(double)obj->h); fl_ovall(x, y, POINT_SIZE, POINT_SIZE, i==colored_point ? FL_RED : FL_BLACK); } } int obj_akima_handler(FL_OBJECT *obj, int event, FL_Coord mx, FL_Coord my, int key, void *xev) { int i,j,x,y,same_x; unsigned long dx,dy,dist; static int edit=0,found,colored_point=-1,lx,rx; #define A_SEARCH_RAD (POINT_SIZE/2)*(POINT_SIZE/2) x=mx-obj->x; y=obj->y+obj->h-my; switch(event) { case FL_ENTER: fl_set_object_label(fd_MRM->Infoline,"X-axis: morph-sequence - Y-axis: bottom:source- top:destination-image"); break; case FL_LEAVE: fl_set_object_label(fd_MRM->Infoline,NULL); colored_point = -1; fl_redraw_object(obj); break; case FL_DRAW: fl_rectf(obj->x,obj->y,obj->w,obj->h,FL_COL1); Draw_Akima(obj); Draw_Akima_Points(obj, colored_point); break; case FL_MOUSE: if (edit) { if (xrx) x=rx; if (y<0) y=0; if (y>obj->h) y=obj->h; control.akima_P[found][0] = (double)x / obj->w; control.akima_P[found][1] = (double)y / obj->h; fl_redraw_object(obj); } break; case FL_MOTION: colored_point = -1; for (i=0; iw); dy = y-(int)(control.akima_P[i][1]*(double)obj->h); if ( (dx*dx+dy*dy) <= A_SEARCH_RAD ) colored_point = i; } fl_redraw_object(obj); break; case FL_PUSH: // SET NEW POINT: found=-1; for (i=0; iw); dy=y-(int)(control.akima_P[i][1]*(double)obj->h); if ( (dx*dx+dy*dy)<=A_SEARCH_RAD ) found=i; } if (found == -1) { // test new point possible: same_x=0; for (i=0; iw); if ( ((j-POINT_SIZE) < x) && (x < (j+POINT_SIZE)) ) same_x=1; } if ( (same_x) || (control.akima_nr == AKIMA_MAX) || (key != 1) ) break; // position of new point: j=0; while ((int)(control.akima_P[j][0]*(double)obj->w) < x) j++; for (i=control.akima_nr; i>j; i--) { control.akima_P[i][0] = control.akima_P[i-1][0]; control.akima_P[i][1] = control.akima_P[i-1][1]; } // get new point data: control.akima_P[j][0] = (double)x / obj->w; control.akima_P[j][1] = (double)y / obj->h; control.akima_nr++; // redraw: fl_redraw_object(obj); } else { // EDIT MODE ON: if (key == 1) { edit=1; if (found == 0) { lx=rx=0; break; } else rx=(int)(control.akima_P[found+1][0]*(double)obj->w)-POINT_SIZE; if (found == control.akima_nr-1) { lx=rx=obj->w; break; } else lx=(int)(control.akima_P[found-1][0]*(double)obj->w)+POINT_SIZE; } // DELETE POINT: if (key == 3) { if ( (control.akima_nr==AKIMA_MIN) || (found==0) || (found==control.akima_nr-1) )break; for (i=found; iInfoline,"Press right button for detailed information..."); break; case FL_LEAVE: fl_set_object_label(fd_MRM->Infoline,NULL); break; case FL_DRAW: fl_rectf(obj->x,obj->y,obj->w,obj->h,FL_COL1); Interpol_Bias(); Plot_Wave_Func(obj); break; case FL_PUSH: if (key >= 2) { s1="When using the wavelet decomposition, use the right slider to control"; s2="the speed at which the different detail-levels are morphed !\n"; s3="The higher the value of F(x), the sooner the details will emerge !"; fl_show_message(s1,s2,s3); } break; default: break; } return 0; } /* callbacks for form MRM */ void callback_Sliders(FL_OBJECT *ob, long arg) { switch (arg) { case 1:// Distance influence control.warp_a = fl_get_slider_value(ob); break; case 2:// different lines influence control.warp_b = fl_get_slider_value(ob); break; case 3:// length influence control.warp_p = fl_get_slider_value(ob); break; case 4:// Wavelet-level control.slider_bias = fl_get_slider_value(ob); if (control.advanced) control.b_bias_val[control.select_level-1] = control.slider_bias; else control.b_bias_val[0] = control.slider_bias; fl_redraw_object(fd_MRM->Wave_Plot); break; case 5:// Delay slider control.delay=1/fl_get_slider_value(fd_MRM->SL_fps); break; case 6:// Wait-Box Slider (progress indicator) fl_set_slider_value(ob,control.wait); break; default: ; } } void callback_CheckButtons(FL_OBJECT *ob, long arg) { int i; static int mouse_x = 0; int mouse_y; unsigned int keymask; static int win_areas_x, win_areas_y; static int first_time = TRUE; switch (arg) { case 1:// Morph Radio_Butt control.Morph=MORPH_MORPH; if (fd_AREAS->AREAS->visible) { fl_get_win_origin(fd_AREAS->AREAS->window, &win_areas_x, &win_areas_y); XUnmapWindow(fl_get_display(), fd_AREAS->AREAS->window); } fl_set_menu_item_mode(fd_MRM->MN_Windows, 4, FL_PUP_BOX+FL_PUP_GREY); fl_show_object(fd_MRM->SL_Level_Adjust); fl_show_object(fd_MRM->Wave_Plot_Box); fl_show_object(fd_MRM->Wave_Plot); fl_show_object(fd_MRM->CT_Level_Select); if (control.advanced) { for (i=0; iBT_Level[i]);} break; case 2:// Warp Radio_Butt control.Morph=MORPH_WARP; if (fd_AREAS->AREAS->visible) { fl_get_win_origin(fd_AREAS->AREAS->window, &win_areas_x, &win_areas_y); XUnmapWindow(fl_get_display(), fd_AREAS->AREAS->window); } fl_set_menu_item_mode(fd_MRM->MN_Windows, 4, FL_PUP_BOX+FL_PUP_GREY); fl_hide_object(fd_MRM->SL_Level_Adjust); fl_hide_object(fd_MRM->Wave_Plot); fl_hide_object(fd_MRM->Wave_Plot_Box); fl_hide_object(fd_MRM->CT_Level_Select); if (control.advanced) { for (i=0; iBT_Level[i]);} break; case 3:// Animate Detail Radio_Butt control.Morph=MORPH_WAVE; if (fd_AREAS->AREAS->visible) { fl_get_win_origin(fd_AREAS->AREAS->window, &win_areas_x, &win_areas_y); XUnmapWindow(fl_get_display(), fd_AREAS->AREAS->window); } fl_set_menu_item_mode(fd_MRM->MN_Windows, 4, FL_PUP_BOX+FL_PUP_GREY); fl_hide_object(fd_MRM->SL_Level_Adjust); fl_hide_object(fd_MRM->Wave_Plot); fl_hide_object(fd_MRM->Wave_Plot_Box); fl_hide_object(fd_MRM->CT_Level_Select); if (control.advanced) { for (i=0; iBT_Level[i]);} break; case 4:// Border Vectors break; case 5:// Advanced User Mode if (s_pic->GetPicPointer() != NULL) { control.advanced=fl_get_button(fd_MRM->CB_Advanced_Mode); if (control.advanced) { if (control.Morph == MORPH_MORPH) { for (i=0; iBT_Level[i]); } fl_set_button(fd_MRM->BT_Level[0],1); fl_set_button(fd_MRM->BT_Level[MAX_LEVELS-1],1); } else { for (i=1; iBT_Level[i],0); for (i=0; iBT_Level[i]); } fl_call_object_callback(fd_MRM->CT_Level_Select); } break; case 6:// Select to show animation sequence if ( fl_get_button(ob) ) { fl_hide_object(fd_MRM->CT_Frame_Nr); fl_show_object(fd_MRM->CB_Anim_Cycle); fl_show_object(fd_MRM->BT_Animate); fl_show_object(fd_MRM->SL_fps); } control.AnimateOrShow=1; break; case 7:// Select to show picture number if ( fl_get_button(ob) ) { fl_hide_object(fd_MRM->CB_Anim_Cycle); fl_hide_object(fd_MRM->BT_Animate); fl_hide_object(fd_MRM->SL_fps); fl_show_object(fd_MRM->CT_Frame_Nr); } control.AnimateOrShow=0; break; case 8:// Cycle SRC->DEST->SRC->STOP control.Cycle = fl_get_button(ob); break; case 9:// Check_Save_Calc: break; case 10:// Check_Save_Cinema: break; case 11:// CB_Area_Map control.Morph = MORPH_AREA; if ( first_time ) { fl_show_form(fd_AREAS->AREAS,FL_PLACE_ASPECT,FL_FULLBORDER,"DETAIL MAP"); fl_get_win_origin(fd_AREAS->AREAS->window, &win_areas_x, &win_areas_y); first_time = FALSE; } else { XMapWindow(fl_get_display(), fd_AREAS->AREAS->window); XMoveWindow(fl_get_display(), fd_AREAS->AREAS->window, win_areas_x, win_areas_y); } fl_set_menu_item_mode(fd_MRM->MN_Windows, 4, FL_PUP_BOX + FL_PUP_CHECK); fl_redraw_object(obj_a); fl_hide_object(fd_MRM->SL_Level_Adjust); fl_hide_object(fd_MRM->Wave_Plot); fl_hide_object(fd_MRM->Wave_Plot_Box); fl_hide_object(fd_MRM->CT_Level_Select); if (control.advanced) { for (i=0; iBT_Level[i]);} break; /*AAA case 12:// Check_MPEG_Cycle break;*/ case 13:// CB_High_Quality: NOP break; case 14:// Check_Use_Wavelets: if ( fl_get_button(fd_MRM->CB_Use_Wavelets) ) fl_set_object_label(fd_MRM->Wave_Plot_Box,"Wavelet Interpolation Levels"); else fl_set_object_label(fd_MRM->Wave_Plot_Box,"Weighting-Progress"); fl_redraw_object(fd_MRM->Wave_Plot); break; default: ; } } void callback_Counters(FL_OBJECT *ob, long arg) { static int old_val=1; int val; switch (arg) { case 1:// Select Wavelet-Level if (control.advanced) { val = (int)fl_get_counter_value(ob); if (val > MAX_LEVELS) val = MAX_LEVELS; else { if (val>old_val) while (!fl_get_button(fd_MRM->BT_Level[val-1])) val++; else if (valBT_Level[val-1])) val--; } fl_set_counter_value(ob,val); old_val=val; control.select_level = (int) fl_get_counter_value(ob); } else { fl_set_counter_value(ob,1); control.select_level=1; } fl_set_slider_value(fd_MRM->SL_Level_Adjust,control.b_bias_val[control.select_level-1]); fl_redraw_object(fd_MRM->Wave_Plot); break; case 2:// Number of Pics to generate control.HowManyPics = (int) fl_get_counter_value(ob); if (control.WhatPic > control.HowManyPics) { fl_set_counter_value(fd_MRM->CT_Frame_Nr,(double) control.HowManyPics); control.WhatPic = control.HowManyPics; } break; case 3:// Picture Number to show // int im_x,im_y; control.WhatPic = (int) fl_get_counter_value(ob); if (control.WhatPic > control.HowManyPics) { fl_set_counter_value(ob,(double) control.HowManyPics); control.WhatPic = control.HowManyPics; } if (cinema[control.WhatPic]->GetImage() != NULL) cinema[control.WhatPic]->ShowImage(obj_m,m_win->GetWin()); /* { im_x=cinema[control.WhatPic]->image_x; im_y=cinema[control.WhatPic]->image_y; if ( (obj_m->w != im_x) || (obj_m->h != im_y) ) { fl_hide_form(fd_RESULT->RESULT); // fl_set_form_maxsize(fd_RESULT->RESULT,SHOW_MAX,(im_y*SHOW_MAX)/im_x); fl_set_form_size(fd_RESULT->RESULT,SHOW_SIZE,(im_y*SHOW_SIZE)/im_x); fl_show_form(fd_RESULT->RESULT,FL_PLACE_ASPECT,FL_FULLBORDER,"MORPH RESULT"); } */ break; case 4:// Start to save with number # control.save_start=(int) fl_get_counter_value(ob); break; case 5:// Save in steps of # control.save_step=(int) fl_get_counter_value(ob); break; default: ; } }