/* * calc.c * * * * Copyright (C) 2002 - 2002 Benninghaus, Rottweil * EMail: el@eb-themen.de * * 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. */ #ifndef _calc_c #define _calc_c #ifdef __cplusplus extern "C" { #endif calcvalues cv; int POSOFFSET( int x, int y ) { int res; res = y * WIDTH; res = res + x; return( res ); } void drawCross( unsigned char *buf, int x, int y, int len, unsigned char val ) { int off,offset,mlen; unsigned char *p; offset = POSOFFSET(x,y); p = &buf[offset]; if(len <= 0){ p[0] = val; return; } /*middle x point, and line (len) to right*/ off = 0; while( ( off <= len ) && ( ( x + off ) < WIDTH ) ){ p[off] = val; off++; } /* middle x point - 1, and line ( len - 1 ) left*/ mlen = len * -1; off = -1; while( ( off >= mlen ) && ( ( x + off ) >= 0 ) ){ p[off] = val; off--; } /*middle y point - 1, and line ( len - 1 ) up*/ mlen = len * -1; off = -1; while( ( off >= mlen ) && ( ( y + off ) >= 0 ) ){ offset = POSOFFSET( x, y + off ); p = &buf[offset]; p[0] = val; off--; } /*middle y point + 1, and line ( len - 1 ) down*/ off = 1; while( ( off <= len ) && ( ( y + off ) < HEIGHT ) ){ offset = POSOFFSET( x, y + off ); p = &buf[offset]; p[0] = val; off++; } } int testCross( unsigned char *buf, int x, int y, int len, unsigned char val ) { int off,offset,mlen; unsigned char *p; offset = POSOFFSET(x,y); p = &buf[offset]; if(len <= 0){ if(p[0] == val){ return(1); } return(0); } /*middle x point, and line (len) to right*/ off = 0; while( ( off <= len ) && ( ( x + off ) < WIDTH ) ){ if(p[off] == val){ return(1); } off++; } /* middle x point - 1, and line ( len - 1 ) left*/ mlen = len * -1; off = -1; while( ( off >= mlen ) && ( ( x + off ) >= 0 ) ){ if(p[off] == val){ return(1); } off--; } /*middle y point - 1, and line ( len - 1 ) up*/ mlen = len * -1; off = -1; while( ( off >= mlen ) && ( ( y + off ) >= 0 ) ){ offset = POSOFFSET( x, y + off ); p = &buf[offset]; if(p[0] == val){ return(1); } off--; } /*middle y point + 1, and line ( len - 1 ) down*/ off = 1; while( ( off <= len ) && ( ( y + off ) < HEIGHT ) ){ offset = POSOFFSET( x, y + off ); p = &buf[offset]; if(p[0] == val){ return(1); } off++; } return(0); } int testRect( unsigned char *buf, int x, int y, int len, unsigned char val ) { int sx,sy,ex,ey,offset,off; unsigned char *p; offset = POSOFFSET(x,y); p = &buf[offset]; /*first testing the exact koor*/ if(p[0] == val){ return(1); } if(len <= 0){ return(0); } sx = x - len; sy = y - len; ex = x + len; ey = y + len; if( sx < 0 ){ sx = 0; } if( sy < 0 ){ sy = 0; } if(ey >= HEIGHT){ ey = HEIGHT - 1; } if(ex >= WIDTH){ ex = WIDTH - 1; } if( ex <= sx ){ return(0); } if( ey <= sy ){ return(0); } while( sy <= ey ){ off = sx; while( off <= ex ){ offset = POSOFFSET( off, sy ); p = &buf[offset]; if(p[0] == val){ return(1); } off++; } sy++; } return(0); } int testKoor( unsigned char *buf, int x, int y, unsigned char val ) { if( cfg.koortype ){ return( testCross( buf, x, y, cfg.seeing , val ) ); } else { return( testRect( buf, x, y, cfg.seeing , val ) ); } return(0); } int calcfirst_spread( unsigned char *buf ) { int offset; unsigned char *p; int ct = 0; int x = 0; int y = 0; int flag = 0; cv.valid = 0; cv.nrkoorcorrect = cfg.maxcalckoor; if(count == 1){ cv.ycheckpixelrange = cfg.yraster; cv.xcheckpixelrange = cfg.xraster; } while(ct < cfg.maxcalckoor ){ cv.k[ct].x = -1; cv.k[ct].y = -1; ct++; } ct = 0; while( ( y < HEIGHT ) && ( ct < cfg.maxcalckoor ) ) { x = 0; while( x < WIDTH ) { offset = POSOFFSET( x, y ); p = &buf[offset]; if( ( p[0] == 255 ) && ( ct < cfg.maxcalckoor ) ) { cv.k[ct].x = x; cv.k[ct].y = y; ct++; } x = x + cv.xcheckpixelrange; } y = y + cv.ycheckpixelrange; } while( cv.valid < cfg.maxcalckoor ){ if( (cv.k[cv.valid].x < 0 ) || ( cv.k[cv.valid].y < 0 ) ){ break; } cv.valid++; } if( ( cv.valid < cv.nrkoorcorrect ) && ( count < cfg.calcstart ) ) { if(cv.ycheckpixelrange > 1 ){ cv.ycheckpixelrange--; } if(cv.xcheckpixelrange > 1 ){ cv.xcheckpixelrange--; } } if(cv.nrkoorcorrect > cv.valid){ cv.nrkoorcorrect = cv.valid; } if(cv.nrkoorcorrect > 0 ){ cv.nrkoorcorrect = ( cv.nrkoorcorrect * cfg.percentcorrect ) / 100; if(cv.nrkoorcorrect == 0){ cv.nrkoorcorrect = 1; } } return( cv.valid ); } /* the real comparison returns 0, if no valid stuff available for comparison, 1, if all okay, and pictue is in correct position 2, if test says, that picture not in correct position */ int calc_spread( unsigned char *buf ) { int ct,x,y,correct; if( ! cv.valid ){ return(0); } ct = 0; correct = 0; while( ( ct < cfg.maxcalckoor ) && ( cv.k[ct].x >= 0 ) && ( cv.k[ct].y >= 0 ) ) { x = cv.k[ct].x; y = cv.k[ct].y; if( testKoor( buf, x, y, 255 ) ){ correct++; if(correct >= cv.nrkoorcorrect){ return(1); } } ct++; } if(correct >= cv.nrkoorcorrect){ return(1); } return( 2 ); } /* --------------------------------------------------------------*/ int calcfirst_cover( unsigned char *buf ) { int numkoor; cv.valid = 0; cv.fbuf = buf; numkoor = ( WIDTH / cfg.xraster ) * ( HEIGHT / cfg.yraster ); numkoor = ( numkoor * cfg.percentcorrect ) / 100; cv.nrkoorcorrect = numkoor; if(cv.nrkoorcorrect > 0 ){ cv.valid = 1; } return( cv.valid ); } int calc_cover( unsigned char *buf ) { unsigned char *p; int offset; int ct = 0; int x = 0; int y = 0; if(! cv.valid){ return(0); } ct = 0; while( y < HEIGHT ) { x = 0; while( x < WIDTH ) { offset = POSOFFSET( x, y ); p = &buf[offset]; if(ct < cv.nrkoorcorrect ) { if( testKoor( cv.fbuf, x, y, p[0]) ){ ct++; } } else { return(1); } x = x + cfg.xraster; } y = y + cfg.yraster; } if( ct >= cv.nrkoorcorrect ){ return(1); } return(2); } /* --------------------------------------------------------------*/ int calcfirst_spot( unsigned char *buf ) { int x,y,sx,sy,ex,ey,offset; unsigned char *p; int ct = 0; cv.valid = 0; ct = 0; while(ct < 5){ cv.spot[ct].x = -1; cv.spot[ct].y = -1; ct++; } x = fv.max.x; y = fv.max.y; offset = POSOFFSET( 0, y); p = &buf[offset]; ex = x; sx = x; while ( ( ( ex + 1 ) < WIDTH ) && (p[ex + 1] == 255 ) ){ ex++; } while ( ( ( sx - 1 ) >= 0 ) && ( p[sx - 1] == 255 ) ){ sx--; } if(ex < sx){ return(0); } cv.spot[0].x = ex - sx; cv.spot[0].x = cv.spot[0].x / 2; cv.spot[0].x = cv.spot[0].x + sx; x = cv.spot[0].x; ey = y; sy = y; while ( ey < HEIGHT ){ offset = POSOFFSET( x , ey ); p = &buf[offset]; if(p[0] != 255){ break; } ey++; } ey--; while ( sy >= 0 ){ offset = POSOFFSET( x , sy ); p = &buf[offset]; if(p[0] != 255){ break; } sy--; } sy++; if(ey < sy){ return(0); } y = ey - sy; y = y / 2; y = y + sy; cv.spot[0].y = y; cv.spot[1].y = y; cv.spot[2].y = y; cv.spot[3].y = sy; cv.spot[3].x = x; cv.spot[4].y = ey; cv.spot[4].x = x; /*now x,y points to the center of spot*/ sx = x; ex = x; offset = POSOFFSET( 0, y); p = &buf[offset]; while ( ( ( ex + 1 ) < WIDTH ) && (p[ex + 1] == 255 ) ){ ex++; } while ( ( ( sx - 1 ) >= 0 ) && ( p[sx - 1] == 255 ) ){ sx--; } if(ex < sx){ return(0); } cv.spot[1].x = sx; cv.spot[2].x = ex; while( cv.valid < 5 ){ if( ( cv.spot[cv.valid].x < 0 ) || ( cv.spot[cv.valid].y < 0 ) ){ cv.valid = 0; return(0); } cv.valid++; } return( cv.valid ); } int calc_spot( unsigned char *buf ) { int flag; if(! cv.valid){ return(0); } cv.changed = 0; flag = 1; if( ! testKoor( buf , cv.spot[1].x , cv.spot[1].y , 255 ) ){ /*pos is moved to right*/ cv.right = 1; flag = 2; } if( ! testKoor( buf , cv.spot[2].x , cv.spot[2].y , 255 ) ){ /*pos is moved to left*/ cv.left = 1; flag = 2; } if( ! testKoor( buf , cv.spot[3].x , cv.spot[3].y , 255 ) ){ /*pos is moved down*/ cv.up = 1; flag = 2; } if( ! testKoor( buf , cv.spot[4].x , cv.spot[4].y , 255 ) ){ /*pos is moved up*/ cv.down = 1; flag = 2; } /*correctur for flicker, because if for example the moving exactly go left, the upper, and lower koordinate can also be wrong*/ if(cv.up && cv.down){ cv.up = 0; cv.down = 0; } if(cv.left && cv.right){ cv.left = 0; cv.right = 0; } if( (! cv.left ) && ( ! cv.right ) && (! cv.up ) && (! cv.down)){ flag = 1; } if( flag == 2 ){ if( (cv.prev_right != cv.right) || (cv.prev_left != cv.left) || (cv.prev_up != cv.up) || (cv.prev_down != cv.down) ){ cv.changed = 1; cv.prev_left = cv.left; cv.prev_right = cv.right; cv.prev_up = cv.up; cv.prev_down = cv.down; } } /*all okay*/ return(flag); } /* --------------------------------------------------------------*/ /* ##############################################################*/ int calcfirst( unsigned char *buf ) { cv.left = 0; cv.right = 0; cv.up = 0; cv.down = 0; cv.prev_left = cv.left; cv.prev_right = cv.right; cv.prev_up = cv.up; cv.prev_down = cv.down; switch( cfg.strategy ){ case 0: return( calcfirst_spot( buf ) ); case 1: return( calcfirst_spread( buf ) ); case 2: return( calcfirst_cover( buf ) ); default:break; } return( 0 ); } int calc( unsigned char *buf ) { cv.left = 0; cv.right = 0; cv.up = 0; cv.down = 0; switch( cfg.strategy ){ case 0: return( calc_spot( buf ) ); case 1: return( calc_spread( buf ) ); case 2: return( calc_cover( buf ) ); default:break; } return( 0 ); } #ifdef __cplusplus } #endif #endif /*_filter_c*/