www.pudn.com > reacTIVision-1.3.rar > threshold.c
/* Fiducial tracking library. Copyright (C) 2004 Ross BencinaThis library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "threshold.h" #include #include void simple_threshold( const unsigned char *source, int source_stride, unsigned char *dest, int width, int height, int threshold ) { const unsigned char *p = source; int count = width * height; int i; for( i=0; i < count; ++i ){ if( *p > threshold ) dest[i] = 255; else dest[i] = 0; p += source_stride; } } void simple_adaptive_threshold( const unsigned char *source, int source_stride, unsigned char *dest, int width, int height, int tile_size ) { int x_step = tile_size; int y_step = tile_size; int y, x; for( y = 0; y < height; y += y_step ){ for( x = 0; x < width; x += x_step ){ int xxmax, yymax, sum, count; int yy, xx; int mean; xxmax = x + x_step; if( xxmax > width ) xxmax = width; yymax = y + y_step; if( yymax > height ) yymax = height; sum = 0; count = 0; for( yy = y; yy < yymax; ++yy ){ for( xx = x; xx < xxmax; ++xx ){ sum += source[ (yy * width + xx) * source_stride ]; ++count; } } mean = sum / count; /* double fmean = (double)sum / (double)count; double sd = 0; for( int yy = y; yy < yymax; ++yy ){ for( int xx = x; xx < xxmax; ++xx ){ double z = source[ (yy * width + xx) * source_stride ] - fmean; sd += z*z; } } double fsd = (double)sd / (double)count; fsd = sqrt( fsd ); if( fsd < 10 ) //mean = 128; mean += 20; */ for( yy = y; yy < yymax; ++yy ){ for( xx = x; xx < xxmax; ++xx ){ if( source[ (yy * width + xx) * source_stride ] > mean ){ dest[(yy * width + xx)] = 255; }else{ dest[(yy * width + xx)] = 0; } } } } } } void overlapped_adaptive_threshold( const unsigned char *source, int source_stride, unsigned char *dest, int width, int height, int tile_size ) { /* this could be optimized by only summing each quadrant of each tile once and reusing these sums for every half step. eg by maintaining an array of sums for the current and previous half-tile rows. */ int x_step = tile_size; int y_step = tile_size; int x, y; for( y = 0; y < height; y += y_step / 2 ){ for( x = 0; x < width; x += x_step / 2 ){ int xxmax, yymax, sum, count, yy, xx; int mean; double fmean, sd, fsd; int ys, ymax, xs, xmax; xxmax = x + x_step; if( xxmax > width ) xxmax = width; yymax = y + y_step; if( yymax > height ) yymax = height; sum = 0; count = (yymax - y) * (xxmax - x ); for( yy = y; yy < yymax; ++yy ){ const unsigned char *p = source + (yy * width + x) * source_stride; for( xx = x; xx < xxmax; ++xx ){ sum += *p; //++count; p += source_stride; } } mean = sum / count; fmean = (double)sum / (double)count; sd = 0; for( yy = y; yy < yymax; ++yy ){ const unsigned char *p = source + (yy * width + x) * source_stride; for( xx = x; xx < xxmax; ++xx ){ double z = *p - fmean; sd += z*z; p += source_stride; } } fsd = (double)sd / (double)count; //fsd = sqrt( fsd ); if( fsd < 10 * 10 ) //mean = 128; mean -= 20; ys = y + y_step / 4; ymax = (y + y_step) - y_step / 4; if( ymax > yymax ) ymax = yymax; if( y == 0 ) ys = 0; xs = x + x_step / 4; xmax = (x + x_step) - x_step / 4; if( xmax > xxmax ) xmax = xxmax; if( x == 0 ) xs = 0; for( yy = ys; yy < ymax; ++yy ){ const unsigned char *p = source + (yy * width + xs) * source_stride; for( xx = xs; xx < xmax; ++xx ){ if( *p > mean ){ dest[(yy * width + xx)] = 255; }else{ dest[(yy * width + xx)] = 0; } p += source_stride; } } } } } #if 0 void overlapped_adaptive_threshold( const unsigned char *source, int source_stride, unsigned char *dest, int width, int height, int tile_size ) { int x, y, xstart, ystart, yend, xend; int diff; /* within each tile - get the maximum gradient if it's above a threshold - use the average of max and min as the tile threshold else - use a global threshold or zero the tile */ for( ystart = 0; ystart < height; ystart += tile_size ){ for( xstart = 0; xstart < width; xstart += tile_size ){ int maxGradient = 0; int min = 255; int max = 0; yend = ystart + tile_size; xend = xstart + tile_size; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ int hgradient, vgradient; int src = source[ ( y * width + x ) * source_stride ]; if( src > max ) max = src; if( src < min ) min = src; /* hgradient = src - source[ ( y * width + x + 1) * source_stride ]; // fixme -- reads 1 pixel past end if( hgradient > maxGradient ) maxGradient = hgradient; else if( -hgradient > maxGradient ) maxGradient = -hgradient; vgradient = src - source[ ( (y+1) * width + x) * source_stride ]; // fixme -- reads 1 pixel past end if( vgradient > maxGradient ) maxGradient = vgradient; else if( -vgradient > maxGradient ) maxGradient = -vgradient; */ } } diff = min - max; if( diff < 0 ) diff = -diff; //diff = abs( min - max ); if( diff > 30 ){ //if( maxGradient > 20 ){ int threshold = (min + max) / 2; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ if( source[ ( y * width + x ) * source_stride ] > threshold ){ dest[ y * width + x ] = 255; }else{ dest[ y * width + x ] = 0; } } } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ dest[ y * width + x ] = 255; } } } } } } #endif #if 0 void overlapped_adaptive_threshold( const unsigned char *source, int source_stride, unsigned char *dest, int width, int height, int tile_size ) { int x, y, xstart, ystart, yend, xend; int diff; /* within each tile - get the maximum gradient if it's above a threshold - use the average of max and min as the tile threshold else - use a global threshold or zero the tile */ for( ystart = 0; ystart < height; ystart += tile_size ){ for( xstart = 0; xstart < width; xstart += tile_size ){ int maxGradient = 0; int min = 255; int max = 0; yend = ystart + tile_size; xend = xstart + tile_size; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ int hgradient, vgradient; int src = source[ ( y * width + x ) * source_stride ]; if( src > max ) max = src; if( src < min ) min = src; hgradient = src - source[ ( y * width + x + 1) * source_stride ]; // fixme -- reads 1 pixel past end if( hgradient > maxGradient ) maxGradient = hgradient; //else if( -hgradient > maxGradient ) // maxGradient = -hgradient; vgradient = src - source[ ( (y+1) * width + x) * source_stride ]; // fixme -- reads 1 pixel past end if( vgradient > maxGradient ) maxGradient = vgradient; //else if( -vgradient > maxGradient ) // maxGradient = -vgradient; } } //diff = min - max; //if( diff < 0 ) // diff = -diff; //diff = abs( min - max ); //if( diff > 30 ){ if( maxGradient > 20 ){ int threshold = (min + max) / 2; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ if( source[ ( y * width + x ) * source_stride ] > threshold ){ dest[ y * width + x ] = 255; }else{ dest[ y * width + x ] = 0; } } } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ dest[ y * width + x ] = 255; } } } } } } #endif #if 1 // adaptive gradient tracking using sobel gradient approximation // http://www.cee.hw.ac.uk/hipr/html/sobel.html // hardwired dimensions for now #define TILE_ARRAY_HEIGHT (480/16) #define TILE_ARRAY_WIDTH (640/16) int sobel_tiles[ TILE_ARRAY_HEIGHT * TILE_ARRAY_WIDTH ]; unsigned char max_tiles[ TILE_ARRAY_HEIGHT * TILE_ARRAY_WIDTH ]; unsigned char min_tiles[ TILE_ARRAY_HEIGHT * TILE_ARRAY_WIDTH ]; // comment out the following line to use contrast thresholding instead #define USE_GRADIENT_THRESHOLDING void overlapped_adaptive_threshold2( const unsigned char *source, int source_stride, unsigned char *dest, int width, int height, int tile_size, int gradient_threshold ) { int x, y, xstart, ystart, yend, xend; //int a, b; int xtiles = width / tile_size; int ytiles = height / tile_size; int xt, yt; const unsigned char *pp1, *pp4, *pp7; unsigned char *pdest; int linestep, destlinestep; unsigned char max, min; int threshold; int approx_gradient_mag; int max_approx_gradient_mag; #define REQUIRED_EXTRA 1 // 2 for sobel // calculate full 3x3 sobel for all but the right hand vertical, // and bottom horizontal tile strips. for( yt = 0; yt < ytiles; ++yt ){ for( xt = 0; xt < xtiles; ++xt ){ xstart = xt * tile_size; xend = xstart + tile_size; if( xend > width - REQUIRED_EXTRA ) xend = width - REQUIRED_EXTRA; ystart = yt * tile_size; yend = ystart + tile_size; if( yend > height - REQUIRED_EXTRA ) yend = height - REQUIRED_EXTRA; linestep = (width - (xend - xstart)) * source_stride; pp1 = source + (ystart * width + xstart) * source_stride; pp4 = pp1 + width * source_stride; pp7 = pp1 + width * source_stride; max_approx_gradient_mag = 0; max = 0; min = 255; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ unsigned char p1 = pp1[0]; ///////// // this is just a simple edge detector #ifdef USE_GRADIENT_THRESHOLDING unsigned char p2 = pp1[source_stride]; unsigned char p4 = pp4[0]; approx_gradient_mag = abs( p2 - p1 ) + abs( p4 - p1 ); if( approx_gradient_mag > max_approx_gradient_mag ) max_approx_gradient_mag = approx_gradient_mag; pp4 += source_stride; #endif /* USE_GRADIENT_THRESHOLDING */ ///////// /* // this is the full sobel unsigned char p2 = pp1[source_stride]; unsigned char p3 = pp1[source_stride * 2]; unsigned char p4 = pp4[0]; //unsigned char p5 = pp4[source_stride]; unsigned char p6 = pp4[source_stride * 2]; unsigned char p7 = pp7[0]; unsigned char p8 = pp7[source_stride]; unsigned char p9 = pp7[source_stride * 2]; approx_gradient_mag = abs( (p1 + 2 * p2 + p3)-(p7 + 2 * p8 + p9) ) + abs( (p3 + 2 * p6 + p9)-(p1 + 2 * p4 + p7) ); if( approx_gradient_mag > max_approx_gradient_mag ) max_approx_gradient_mag = approx_gradient_mag; pp4 += source_stride; pp7 += source_stride; */ if( p1 > max ) max = p1; else if( p1 < min ) min = p1; /* if( approx_gradient_mag > 255 ) approx_gradient_mag = 255; dest[ y * width + x ] = approx_gradient_mag; */ pp1 += source_stride; } pp1 += linestep; #ifdef USE_GRADIENT_THRESHOLDING pp4 += linestep; pp7 += linestep; #endif /* USE_GRADIENT_THRESHOLDING */ } #ifdef USE_GRADIENT_THRESHOLDING sobel_tiles[ yt * TILE_ARRAY_WIDTH + xt ] = max_approx_gradient_mag; #endif /* USE_GRADIENT_THRESHOLDING */ max_tiles[ yt * TILE_ARRAY_WIDTH + xt ] = max; min_tiles[ yt * TILE_ARRAY_WIDTH + xt ] = min; } } // top left quater cell xstart = 0; xend = xstart + (tile_size/2); ystart = 0; yend = ystart + (tile_size/2); linestep = (width - (xend - xstart)) * source_stride; destlinestep = width - (xend - xstart); pp1 = source + (ystart * width + xstart) * source_stride; pdest = dest + (ystart * width + xstart); #ifdef USE_GRADIENT_THRESHOLDING max_approx_gradient_mag = sobel_tiles[ 0 ]; if( max_approx_gradient_mag > gradient_threshold ) #else if(1) #endif { max = max_tiles[ 0]; min = min_tiles[ 0 ]; #ifndef USE_GRADIENT_THRESHOLDING if( (max - min) > gradient_threshold ) #else if(1) #endif { threshold = (max + min) / 2; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ unsigned char p1 = pp1[0]; if( p1 > threshold ) *pdest = 255; else *pdest = 0; pp1 += source_stride; ++pdest; } pp1 += linestep; pdest += destlinestep; } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } /// top row of half tiles for( xt = 0; xt < xtiles - 1; ++xt ){ xstart = xt * tile_size + (tile_size/2); xend = xstart + tile_size; ystart = 0; yend = ystart + (tile_size/2); linestep = (width - (xend - xstart)) * source_stride; destlinestep = width - (xend - xstart); pp1 = source + (ystart * width + xstart) * source_stride; pdest = dest + (ystart * width + xstart); #ifdef USE_GRADIENT_THRESHOLDING max_approx_gradient_mag = sobel_tiles[ xt ]; if( sobel_tiles[ xt + 1 ] > max_approx_gradient_mag ) max_approx_gradient_mag = sobel_tiles[ xt + 1 ]; if( max_approx_gradient_mag > gradient_threshold ) #else if(1) #endif { max = max_tiles[ xt]; if( max_tiles[ xt + 1 ] > max ) max = max_tiles[ xt + 1 ]; min = min_tiles[ xt ]; if( min_tiles[ xt + 1 ] < min ) min = min_tiles[ xt + 1 ]; #ifndef USE_GRADIENT_THRESHOLDING if( (max - min) > gradient_threshold ) #else if(1) #endif { threshold = (max + min) / 2; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ unsigned char p1 = pp1[0]; if( p1 > threshold ) *pdest = 255; else *pdest = 0; pp1 += source_stride; ++pdest; } pp1 += linestep; pdest += destlinestep; } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } } // top right quater cell xstart = width - (tile_size/2) ; xend = xstart + (tile_size/2); ystart = 0; yend = ystart + (tile_size/2); linestep = (width - (xend - xstart)) * source_stride; destlinestep = width - (xend - xstart); pp1 = source + (ystart * width + xstart) * source_stride; pdest = dest + (ystart * width + xstart); #ifdef USE_GRADIENT_THRESHOLDING max_approx_gradient_mag = sobel_tiles[ xtiles - 1 ]; if( max_approx_gradient_mag > gradient_threshold ) #else if(1) #endif { max = max_tiles[ xtiles - 1 ]; min = min_tiles[ xtiles - 1 ]; #ifndef USE_GRADIENT_THRESHOLDING if( (max - min) > gradient_threshold ) #else if(1) #endif { threshold = (max + min) / 2; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ unsigned char p1 = pp1[0]; if( p1 > threshold ) *pdest = 255; else *pdest = 0; pp1 += source_stride; ++pdest; } pp1 += linestep; pdest += destlinestep; } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } for( yt = 0; yt < ytiles - 1; ++yt ){ // first half tile xstart = 0; xend = (tile_size/2); ystart = yt * tile_size + (tile_size / 2); yend = ystart + tile_size; linestep = (width - (xend - xstart)) * source_stride; destlinestep = width - (xend - xstart); pp1 = source + (ystart * width + xstart) * source_stride; pdest = dest + (ystart * width + xstart); #ifdef USE_GRADIENT_THRESHOLDING max_approx_gradient_mag = sobel_tiles[ yt * TILE_ARRAY_WIDTH ]; if( sobel_tiles[ (yt + 1) * TILE_ARRAY_WIDTH ] > max_approx_gradient_mag ) max_approx_gradient_mag = sobel_tiles[ (yt + 1) * TILE_ARRAY_WIDTH ]; if( max_approx_gradient_mag > gradient_threshold ) #else if(1) #endif { max = max_tiles[ yt* TILE_ARRAY_WIDTH ]; if( max_tiles[ (yt + 1)* TILE_ARRAY_WIDTH ] > max ) max = max_tiles[ (yt + 1)* TILE_ARRAY_WIDTH ]; min = min_tiles[ yt * TILE_ARRAY_WIDTH ]; if( min_tiles[ (yt + 1)* TILE_ARRAY_WIDTH ] < min ) min = min_tiles[ (yt + 1)* TILE_ARRAY_WIDTH ]; #ifndef USE_GRADIENT_THRESHOLDING if( (max - min) > gradient_threshold ) #else if(1) #endif { threshold = (max + min) / 2; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ unsigned char p1 = pp1[0]; if( p1 > threshold ) *pdest = 255; else *pdest = 0; pp1 += source_stride; ++pdest; } pp1 += linestep; pdest += destlinestep; } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } // row of full tiles for( xt = 0; xt < xtiles - 1; ++xt ){ xstart = xt * tile_size + (tile_size/2); xend = xstart + tile_size; ystart = yt * tile_size + (tile_size/2); yend = ystart + tile_size; linestep = (width - (xend - xstart)) * source_stride; destlinestep = width - (xend - xstart); pp1 = source + (ystart * width + xstart) * source_stride; pdest = dest + (ystart * width + xstart); #ifdef USE_GRADIENT_THRESHOLDING max_approx_gradient_mag = sobel_tiles[ yt * TILE_ARRAY_WIDTH + xt ]; if( sobel_tiles[ (yt + 1) * TILE_ARRAY_WIDTH + xt ] > max_approx_gradient_mag ) max_approx_gradient_mag = sobel_tiles[ (yt + 1) * TILE_ARRAY_WIDTH + xt ]; if( sobel_tiles[ (yt + 1) * TILE_ARRAY_WIDTH + xt + 1 ] > max_approx_gradient_mag ) max_approx_gradient_mag = sobel_tiles[ (yt + 1) * TILE_ARRAY_WIDTH + xt + 1 ]; if( sobel_tiles[ yt * TILE_ARRAY_WIDTH + xt + 1 ] > max_approx_gradient_mag ) max_approx_gradient_mag = sobel_tiles[ yt * TILE_ARRAY_WIDTH + xt + 1 ]; if( max_approx_gradient_mag > gradient_threshold ) #else if(1) #endif { max = max_tiles[ yt* TILE_ARRAY_WIDTH + xt ]; if( max_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + xt ] > max ) max = max_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + xt ]; if( max_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + xt + 1 ] > max ) max = max_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + xt + 1 ]; if( max_tiles[ yt * TILE_ARRAY_WIDTH + xt + 1] > max ) max = max_tiles[ yt * TILE_ARRAY_WIDTH + xt + 1 ]; min = min_tiles[ yt * TILE_ARRAY_WIDTH + xt ]; if( min_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + xt ] < min ) min = min_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + xt ]; if( min_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + xt + 1 ] < min ) min = min_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + xt + 1 ]; if( min_tiles[ yt * TILE_ARRAY_WIDTH + xt + 1] < min ) min = min_tiles[ yt * TILE_ARRAY_WIDTH + xt + 1 ]; #ifndef USE_GRADIENT_THRESHOLDING if( (max - min) > gradient_threshold ) #else if(1) #endif { threshold = (max + min) / 2; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ unsigned char p1 = pp1[0]; if( p1 > threshold ) *pdest = 255; else *pdest = 0; pp1 += source_stride; ++pdest; } pp1 += linestep; pdest += destlinestep; } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } } // last half tile xstart = width - (tile_size/2); xend = width; ystart = yt * tile_size + (tile_size / 2); yend = ystart + tile_size; linestep = (width - (xend - xstart)) * source_stride; destlinestep = width - (xend - xstart); pp1 = source + (ystart * width + xstart) * source_stride; pdest = dest + (ystart * width + xstart); #ifdef USE_GRADIENT_THRESHOLDING max_approx_gradient_mag = sobel_tiles[ yt * TILE_ARRAY_WIDTH + (xtiles - 1) ]; if( sobel_tiles[ (yt + 1) * TILE_ARRAY_WIDTH + (xtiles - 1) ] > max_approx_gradient_mag ) max_approx_gradient_mag = sobel_tiles[ (yt + 1) * TILE_ARRAY_WIDTH + (xtiles - 1) ]; if( max_approx_gradient_mag > gradient_threshold ) #else if(1) #endif { max = max_tiles[ yt* TILE_ARRAY_WIDTH + (xtiles - 1) ]; if( max_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + (xtiles - 1) ] > max ) max = max_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + (xtiles - 1) ]; min = min_tiles[ yt * TILE_ARRAY_WIDTH + (xtiles - 1) ]; if( min_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + (xtiles - 1) ] < min ) min = min_tiles[ (yt + 1)* TILE_ARRAY_WIDTH + (xtiles - 1) ]; #ifndef USE_GRADIENT_THRESHOLDING if( (max - min) > gradient_threshold ) #else if(1) #endif { threshold = (max + min) / 2; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ unsigned char p1 = pp1[0]; if( p1 > threshold ) *pdest = 255; else *pdest = 0; pp1 += source_stride; ++pdest; } pp1 += linestep; pdest += destlinestep; } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } } // bottom left quater cell xstart = 0; xend = xstart + (tile_size/2); ystart = (ytiles - 1) * tile_size + (tile_size / 2); yend = ystart + (tile_size/2); linestep = (width - (xend - xstart)) * source_stride; destlinestep = width - (xend - xstart); pp1 = source + (ystart * width + xstart) * source_stride; pdest = dest + (ystart * width + xstart); #ifdef USE_GRADIENT_THRESHOLDING max_approx_gradient_mag = sobel_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) ]; if( max_approx_gradient_mag > gradient_threshold ) #else if(1) #endif { max = max_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH)]; min = min_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) ]; #ifndef USE_GRADIENT_THRESHOLDING if( (max - min) > gradient_threshold ) #else if(1) #endif { threshold = (max + min) / 2; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ unsigned char p1 = pp1[0]; if( p1 > threshold ) *pdest = 255; else *pdest = 0; pp1 += source_stride; ++pdest; } pp1 += linestep; pdest += destlinestep; } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } /// bottom row of half tiles for( xt = 0; xt < xtiles - 1; ++xt ){ xstart = xt * tile_size + (tile_size/2); xend = xstart + tile_size; ystart = (ytiles - 1) * tile_size + (tile_size / 2); yend = ystart + (tile_size/2); linestep = (width - (xend - xstart)) * source_stride; destlinestep = width - (xend - xstart); pp1 = source + (ystart * width + xstart) * source_stride; pdest = dest + (ystart * width + xstart); #ifdef USE_GRADIENT_THRESHOLDING max_approx_gradient_mag = sobel_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xt ]; if( sobel_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xt + 1 ] > max_approx_gradient_mag ) max_approx_gradient_mag = sobel_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xt + 1 ]; if( max_approx_gradient_mag > gradient_threshold ) #else if(1) #endif { max = max_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xt]; if( max_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xt + 1 ] > max ) max = max_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xt + 1 ]; min = min_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xt ]; if( min_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xt + 1 ] < min ) min = min_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xt + 1 ]; #ifndef USE_GRADIENT_THRESHOLDING if( (max - min) > gradient_threshold ) #else if(1) #endif { threshold = (max + min) / 2; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ unsigned char p1 = pp1[0]; if( p1 > threshold ) *pdest = 255; else *pdest = 0; pp1 += source_stride; ++pdest; } pp1 += linestep; pdest += destlinestep; } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } } // bottom right quater cell xstart = width - (tile_size/2) ; xend = xstart + (tile_size/2); ystart = (ytiles - 1) * tile_size + (tile_size / 2); yend = ystart + (tile_size/2); linestep = (width - (xend - xstart)) * source_stride; destlinestep = width - (xend - xstart); pp1 = source + (ystart * width + xstart) * source_stride; pdest = dest + (ystart * width + xstart); #ifdef USE_GRADIENT_THRESHOLDING max_approx_gradient_mag = sobel_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xtiles - 1 ]; if( max_approx_gradient_mag > gradient_threshold ) #else if(1) #endif { max = max_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xtiles - 1 ]; min = min_tiles[ ((ytiles - 1) * TILE_ARRAY_WIDTH) + xtiles - 1 ]; #ifndef USE_GRADIENT_THRESHOLDING if( (max - min) > gradient_threshold ) #else if(1) #endif { threshold = (max + min) / 2; for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ unsigned char p1 = pp1[0]; if( p1 > threshold ) *pdest = 255; else *pdest = 0; pp1 += source_stride; ++pdest; } pp1 += linestep; pdest += destlinestep; } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } }else{ for( y = ystart; y < yend; ++y ){ for( x = xstart; x < xend; ++x ){ *pdest = 0; ++pdest; } pdest += destlinestep; } } } #endif