示例#1
0
int main(int argn, char** argv) {
	
	int xsize, ysize;
	char c, c2;
	int i, i2;
	int x, y;

	WINDOW* wnd;
	char buf[50];
	tile* temp_tile; 

	/* Inicjalizacja generatora liczb losowych */
	srand(time(0));

	wnd = initscr();
	start_color();
	
	if(has_colors()) {

		enable_tile_colors();
		use_default_colors();

		/* Przyporządkuj każdej płytce kolor */
		init_pair(1, COLOR_YELLOW, -1);
		init_pair(2, COLOR_GREEN, -1);
		init_pair(3, COLOR_RED, -1);
		init_pair(4, COLOR_YELLOW, -1);
		init_pair(5, COLOR_WHITE, -1);
		init_pair(6, COLOR_RED, -1);
		init_pair(7, COLOR_GREEN, -1);
		init_pair(8, COLOR_BLUE, -1);
		init_pair(9, COLOR_CYAN, -1);
		init_pair(10, COLOR_MAGENTA, -1);

	}
	else {

		disable_tile_colors();

	}

	cbreak();
	echo();
	nonl();
	intrflush(stdscr, FALSE);
	keypad(stdscr, TRUE);

	getmaxyx(wnd, ysize, xsize);

	/* Pobierz docelowy rozmiar */
	while(1) {

		werase(wnd);

		draw_frame(wnd);

		wmove(wnd, ysize/2-(MAX_SIZE-MIN_SIZE+2), 20);	

		wprintw(wnd, "Available pool size:");

		for(i=MIN_SIZE;i<=MAX_SIZE;i++) {

			wmove(wnd, ysize/2-(MAX_SIZE-MIN_SIZE+2)+(i-MIN_SIZE+1), 20);
			attron(COLOR_PAIR(5) | A_BOLD);
			wprintw(wnd, "%d", i);
			attroff(COLOR_PAIR(5) | A_BOLD);
			wprintw(wnd, " for %dx%d", i, i);
			
		}

		wmove(wnd, ysize-2, 2);
		wprintw(wnd, "Saephir (c), 2010");

		wmove(wnd, ysize/2+1, 20);
		wprintw(wnd, "Type the desired number: ");

		c = getch();

		buf[0] = c;
		buf[1] = 0;

		i2 = atoi(buf);

		if(i2 >= MIN_SIZE && i2 <= MAX_SIZE) {
			TILES_COUNT = i2;
			init();
			break;
		}

	}

	while(1) {

		werase(wnd);

		draw_frame(wnd);

		/* Wygrana gra */
		if(verify()) {

			print_game(wnd);

			wmove(wnd, ysize/2, 40);
			wprintw(wnd, "Well done!");
			wmove(wnd, ysize/2+1, 40);
			wprintw(wnd, "Press ENTER to exit...");
			getch();
			break;

		}

		print_game(wnd);
		print_pool(wnd);

		wmove(wnd, ysize-2, 1);

		wgetnstr(wnd, buf, 49);
		buf[49] = 0;

		if(strcmp(buf, "exit") == 0 || strcmp(buf, "quit") == 0 || strcmp(buf, "q") == 0) {

			break;

		}
		else if(strcmp(buf, "help") == 0 || strcmp(buf, "?") == 0) {

			wmove(wnd, ysize-2, 1);
			wclrtoeol(wnd);
			draw_frame(wnd);
			wmove(wnd, ysize-2, 1);
			wprintw(wnd, HELP_LINE);
			getch();
			wmove(wnd, ysize-2, 1);
			wclrtoeol(wnd);
			draw_frame(wnd);
			wmove(wnd, ysize-2, 1);
			wprintw(wnd, HELP_LINE2);
			getch();

		}

		else if(strcmp(buf, "<<") == 0) {

			push_left();

		}

		else if(strcmp(buf, ">>") == 0) {

			push_right();

		}

		else if(strcmp(buf, "^^") == 0) {

			push_top();

		}

		else if(strcmp(buf, "vv") == 0) {

			push_bottom();

		}
		else if(sscanf(buf, "%c%d<%c%d", &c, &i, &c2, &i2) == 4) {

			i--;
			i2--;

			if(c == c2 && i == i2)
				continue;

			if(c-'a' < 0 || c-'a' >= 2*TILES_COUNT)
				continue;

			if(c2-'a' < 0 || c2-'a' >= 2*TILES_COUNT)
				continue;

			if(i < 0 || i >= TILES_COUNT)
				continue;

			if(i2 < 0 || i2 >= TILES_COUNT)
				continue;

			/* Przesuwamy na pole gry */
			if(c-'a' < TILES_COUNT) {

				temp_tile = &game[i][c-'a'];

				/* Miejsce musi być puste */
				if(!is_empty(temp_tile))
					continue;

				/* przesuwamy z puli do gry */
				if(c2-'a' >= TILES_COUNT)
					temp_tile = &pool[i2][c2-'a'-TILES_COUNT];
				/* przesuwamy z gry do gry */
				else
					temp_tile = &game[i2][c2-'a'];

				/* Żródło nie może być puste */
				if(is_empty(temp_tile))
					continue;

				move_tile(&game[i][c-'a'], temp_tile);

			}
			/* Przesuwamy do puli */
			else {

				temp_tile = &pool[i][c-'a'-TILES_COUNT];

				/* Miejsce musi być puste */
				if(!is_empty(temp_tile))
					continue;

				/* Przesuwamy z pola gry do puli */
				if(c2-'a' < TILES_COUNT)
					temp_tile = &game[i2][c2-'a'];
				/* Przesuwamy z puli do puli */
				else
					temp_tile = &pool[i2][c2-'a'-TILES_COUNT];
				
				/* Żródło nie może być puste */
				if(is_empty(temp_tile))
					continue;

				move_tile(&pool[i][c-'a'-TILES_COUNT], temp_tile);

			}
			


		}
		else if(sscanf(buf, "%c%d>%c%d", &c, &i, &c2, &i2) == 4) {

			i--;
			i2--;

			if(c == c2 && i == i2)
				continue;

			if(c-'a' < 0 || c-'a' >= 2*TILES_COUNT)
				continue;

			if(c2-'a' < 0 || c2-'a' >= 2*TILES_COUNT)
				continue;

			if(i < 0 || i >= TILES_COUNT)
				continue;

			if(i2 < 0 || i2 >= TILES_COUNT)
				continue;

			/* Przesuwamy do puli */
			if(c2-'a' >= TILES_COUNT) {

				temp_tile = &pool[i2][c2-'a'-TILES_COUNT];

				/* Miejsce musi być puste */
				if(!is_empty(temp_tile))
					continue;

				/* Przesuwamy z pola gry */
				if(c-'a' < TILES_COUNT)
					temp_tile = &game[i][c-'a'];
				/* Przesuwamy z puli */
				else
					temp_tile = &pool[i][c-'a'-TILES_COUNT];
				
				/* Żródło nie może być puste */
				if(is_empty(temp_tile))
					continue;

				move_tile(&pool[i2][c2-'a'-TILES_COUNT], temp_tile);

			}
			/* Przesuwamy na pole gry */
			else {

				temp_tile = &game[i2][c2-'a'];

				/* Miejsce musi być puste */
				if(!is_empty(temp_tile))
					continue;

				/* Przesuwamy z puli na pole gry */
				if(c-'a' >= TILES_COUNT)
					temp_tile = &pool[i][c-'a'-TILES_COUNT];
				/* Przesuwamy z pola gry na pole gry */
				else
					temp_tile = &game[i][c-'a'];
				
				/* Żródło nie może być puste */
				if(is_empty(temp_tile))
					continue;

				move_tile(&game[i2][c2-'a'], temp_tile);

			}

		}
		else if(sscanf(buf, "%c%d>pool", &c, &i) == 2 || sscanf(buf, "pool<%c%d", &c, &i) == 2) {

			i--;

			if(strcmp(&buf[2], ">pool") != 0) {
				buf[5] = 0;
				if(strcmp(buf, "pool<") != 0)
					continue;
			}

			if(c-'a' < 0 || c-'a' >= TILES_COUNT)
				continue;

			if(i < 0 || i >= TILES_COUNT)
				continue;

			/* Żródło nie może być puste */
			if(is_empty(&game[i][c-'a']))
				continue;

			/* Jeżeli źródło nie jest puste, to istnieją wolne miejsca w puli */
			/* znajdujemy więc pierwsze wolne miejsce */
			for(y=0;y<TILES_COUNT;y++) {
				for(x=0;x<TILES_COUNT;x++) {
					
					if(is_empty(&pool[x][y])) {
						
						move_tile(&pool[x][y], &game[i][c-'a']);
						break;
					}

				}
			}
			

		}

	}

	endwin();

	return 0;
}
示例#2
0
linked_list* connComponents(const image_t *imgGy,int32_t minNumPixels){

	int32_t i,j;
	struct pixel seed;
	uint8_t T;
	uint8_t **dummy;
	int32_t Nset, ClassLabel;
	int32_t dummyClass;
	symbol_t *symbol, *symbol_tmp;
	linked_list *symbols_list;
	int32_t height, width;

	height = imgGy->height;
	width = imgGy->width;

	/* Set up segmented image structure */
	dummy=(uint8_t **) multialloc (sizeof (uint8_t), 2, (int)height, (int)width);
	symbols_list = create_linked_list();
	symbol_tmp = malloc(sizeof(symbol_t));

	/********************** Segment Image ******************/

	/* set threshold  */
	T=1;

	/* Initialize segmentation image */
	for ( i = 0; i < height; i++ ){
		for ( j = 0; j < width; j++ )
		{
			dummy[i][j] = 0;
		}
	}

	dummyClass = -1;

	/* Start class labeling at 1 */
	ClassLabel = 1;

	for ( i = 0; i < height; i++ )
		for ( j = 0; j < width; j++ )
		{
			/* If not yet classified */
			if (dummy[i][j] == 0 && getPixel(imgGy,i,j) == 1)
			{
				seed.row=i;
				seed.col=j;
				/* using this only to find Nset; will also indicate tested regions */
				ConnectedSet(seed, T, imgGy, width, height,
				             &dummyClass, dummy, &Nset, symbol_tmp);
				/* If more than 100 pixels, classify set*/
				if (Nset > minNumPixels)
				{
					symbol = malloc(sizeof(symbol_t));
					symbol->top=(uint16_t)height; symbol->bottom=0; 
					symbol->left=(uint16_t)width; symbol->right=0;

					ConnectedSet(seed, T, imgGy, width,
					             height, &ClassLabel, dummy, &Nset, symbol);

					symbol->height = (uint16_t)(symbol->bottom - symbol->top + 1);
					symbol->width = (uint16_t)(symbol->right - symbol->left + 1);
					symbol->HtW = (uint16_t)(symbol->height/symbol->width);
					symbol->NumBlack = (uint16_t)(Nset);
		
					symbol->class_label = -1;

					push_bottom(symbols_list, symbol);
	
					ClassLabel = ClassLabel + 1;
					if (ClassLabel > 255)
					{
						printf("Error: More than 256 classes.\n");
						printf("Need to increase minimum pixels per class.\n");
						exit(1);
					}
				}
			}
		}

	ClassLabel = ClassLabel - 1;

	
	multifree(dummy, 2);
	free(symbol_tmp);

	return symbols_list;
}
示例#3
0
void fix_lines_and_remove(image_t* img,params* parameters, uint32_t** last_STAFFLINES, uint32_t *previous_start, uint32_t cutNum){
/*function [result,new_start,STAFFLINES] = fix_lines_and_remove(img,params,last_STAFFLINES,previous_start,cutNum)*/
/*remvoe lines from small portion of staff. also straightens staff.*/
	flex_array_t *stafflines_tmp;	
	uint32_t *yprojection, line_thickness, line_spacing, line_w, *last_STAFFLINES_avg, max_project, sum, h, w,
		i, j, ii, count, **STAFFLINES, dummy, loc, shift, findLine, match, lineBegin,
		lineEnd, found_thickness, middle, tooThick, tooHigh, any_stafflines_zero, now_avg, last_avg, goodLine,
		tooLow, curr, extend, lastDelete, cW, cH, topStop, botStop, thickness, paramThickness, thickness_th,
		topLine, shift_loop,k;
	int16_t *tempData,*temp_array;
	int32_t lineY;
	uint8_t pixelData;
	linked_list *staffLines, *allLINES, *temp;
		
	STAFFLINES=multialloc(sizeof(uint32_t),2,5,2);

	h = img->height;
	w = img->width;
	line_thickness = (uint32_t)(parameters->thickness);
	line_spacing = (uint32_t)(parameters->spacing);
	line_w = (uint32_t)(parameters->thickness + parameters->spacing);
	
	last_STAFFLINES_avg = (uint32_t *)malloc(sizeof(uint32_t)*5);/*mget_spc((uint32_t)5, sizeof(uint32_t));*/
	for(i=0; i<5; i++){
		last_STAFFLINES_avg[i] = (uint32_t)((last_STAFFLINES[i][0] + last_STAFFLINES[i][1] + 1)/2);
	}
	yprojection= (uint32_t *)mget_spc((uint32_t)h, sizeof(uint32_t));
	max_project = 0;
	for(i=0;i<h;i++){
		sum = 0;
		for(j=0;j<w;j++){
			sum += getPixel(img,i,j);
		}
		yprojection[i] = sum;
		if(yprojection[i] > max_project){
			max_project = yprojection[i];		
		}
	}
	count = 0;
	for(i=0;i<h;i++){
    		if (yprojection[i] >= (9*max_project)/10){    /*delete staff line, twiddle with the 80% later (90%)*/
       			count++;
    		}
	}
	stafflines_tmp=make_flex_array(count);
	count = 0;
	for(i=0;i<h;i++){
    		if (yprojection[i] >= (9*max_project)/10){    /*delete staff line, twiddle with the 80% later (90%)*/
			stafflines_tmp->data[count] = i;       			
			count++;
    		}
	}
	free(yprojection);
	staffLines = group(stafflines_tmp, 3);
/*CHANGE: CUTNUM = 1 TO 0*/
	if (cutNum == 0 && staffLines->length == 5 ){
/*END CHANGE*/
		i=0;
	    	while(is_list_empty(staffLines)==0){
			tempData=(int16_t*)pop_top(staffLines);
			STAFFLINES[i][0] = tempData[0];
			STAFFLINES[i][1] = tempData[1];
			i++;
			free(tempData);
		}
	}
	else if ((staffLines->length) == 0){		
		for(i=0;i<5;i++){
			STAFFLINES[i][0] = last_STAFFLINES[i][0];
			STAFFLINES[i][1] = last_STAFFLINES[i][1];
		}
	}
/*CHANGE: CUTNUM = 1 TO 0*/
	else if (cutNum == 0 && (staffLines->length) < 5){
/*END CHANGE*/
	    	/*choose one line, then find closest line in last_STAFFLINES*/
		tempData = (int16_t*)(getIndexData(staffLines, 0));
	    	goodLine = (uint32_t)((tempData[0]+tempData[1]+1)/2);
		
		dummy = abs(last_STAFFLINES_avg[0] - goodLine);
		loc = 0;		
		for(i=1;i<5;i++){
			curr = abs(last_STAFFLINES_avg[i] - goodLine);
			if(curr<dummy){
				dummy = curr;				
				loc = i;
			}
		}
	    	shift = goodLine - last_STAFFLINES_avg[loc];
	    
	    	for(i=0;i<5;i++){
			STAFFLINES[i][0] = last_STAFFLINES[i][0]+shift;
			STAFFLINES[i][1] = last_STAFFLINES[i][1]+shift;
		}
	}
	

	else{
		count = 0;
		for(findLine=0;findLine<5;findLine++){

			match = 0;
			for(i=0;i<(staffLines->length);i++){
				tempData = (int16_t*)(getIndexData(staffLines, i));
			    	lineBegin = (uint32_t)tempData[0];
			    	lineEnd = (uint32_t)tempData[1];
				/*lineBegin is top of line, lineEnd is bottom*/

			    	found_thickness = lineEnd-lineBegin+1;
/*CHANGED: 0.5 TO 1/2*/
			    	middle = (uint32_t)((lineBegin + lineEnd+1)/2);
/*END CHANGED*/

			    	/*determine if the line is of expected location/size*/
				tooThick = 0;
				tooHigh = 0;
				tooLow = 0;
			    	if(found_thickness > (line_thickness+2)) tooThick=1;
				if(middle < (last_STAFFLINES_avg[findLine] - 3)) tooHigh=1;
				if(middle > (last_STAFFLINES_avg[findLine] + 3)) tooLow=1;
/*CHANGED: 1 TO 0*/
			    	if (cutNum == 0){
/*END CHANGED*/
					tooHigh = 0;
					tooLow = 0;
					if(middle < (last_STAFFLINES_avg[0] - 2*line_spacing)){tooHigh=1;}
/*CHANGED + TO - ALSO, avg[5] -> avg[4] */
					if(middle > (last_STAFFLINES_avg[4] + 2*line_spacing)){tooLow=1;}
/*END CHANGED*/
			    	}

			    	if (tooThick || tooHigh || tooLow){
					continue;
			    	}
			    	else{ /*we found good match for staffline*/
					match = 1;
					/*SAVE STAFF LINE LOCATIONS*/
					STAFFLINES[count][0] = lineBegin;
					STAFFLINES[count][1] = lineEnd;
					count++;
					deleteIndexData(staffLines,i);
					break;
			    	}        



			} /*end looping thru found lines*/

			if(!match){ /*CHANGED*/
		    		/*flag that no match was found*/
		    		STAFFLINES[count][0] = 0;
				STAFFLINES[count][1] = 0;
				count++;
			} 

	    	} /*end looping through matching staff lines*/
	    
	    	/*CHANGED BELOW*/
	    
	    	/*check for lines that did not get match*/
		any_stafflines_zero = 0;
		for(i=0;i<5;i++){
			if(STAFFLINES[i][0] == 0){
				any_stafflines_zero = 1;
				break;
			}
		}
	    	if (any_stafflines_zero){
			/*find shift value first*/
			shift = 100; /*big value*/
			for (findLine = 0; findLine<5;findLine++){
			/*loop to find nonzero entry in STAFFLINES, then calculate shift*/
			    if (STAFFLINES[findLine][0]){ /*if nonzero*/
				now_avg = (uint32_t)((STAFFLINES[findLine][0]+STAFFLINES[findLine][1]+1)/2);
				last_avg = last_STAFFLINES_avg[findLine];
				shift = now_avg - last_avg;
				break;
			    }
			}
			if (shift==100){ shift = 0;}
			/*replace any flagged (with 0) entries in STAFFLINES*/
			for(findLine=0;findLine<5;findLine++){
			    	if (STAFFLINES[findLine][0] == 0){
					STAFFLINES[findLine][0] = last_STAFFLINES[findLine][0]+shift;
					STAFFLINES[findLine][1] = last_STAFFLINES[findLine][1]+shift;
			    	}
			}
		}
	}

	extend = (uint32_t)((line_w+2)/4)+1;
	/*create stafflines above*/
	allLINES=create_linked_list();
	lineY = (int32_t)(((STAFFLINES[0][0] + STAFFLINES[0][1]+1)/2) - line_w); /*first above line*/
	while (1){
   		if (lineY < (int32_t)(extend + 2)){
       			break;
		}   		
		else{
			temp_array=malloc(sizeof(int16_t)*2);
			temp_array[0]=(int16_t)lineY;
			temp_array[1]=(int16_t)lineY;
			push_top(allLINES,temp_array);
       			lineY = (int32_t)(lineY - (int32_t)line_w );
   		}
	}
	for(i=0;i<5;i++){
		temp_array=malloc(sizeof(uint32_t)*2);
		temp_array[0]=(int16_t)STAFFLINES[i][0];
		temp_array[1]=(int16_t)STAFFLINES[i][1];
		push_bottom(allLINES,temp_array);
	}
	/*create stafflines below*/
	lineY = (uint32_t)(((STAFFLINES[4][0] + STAFFLINES[4][1]+1)/2) + line_w); /*first above line*/
	while (1){
   		if (lineY > (h - extend - 3)){
       			break;
		}   		
		else{
			temp_array=malloc(sizeof(int16_t)*2);
			temp_array[0]=(int16_t)lineY;
			temp_array[1]=(int16_t)lineY;
			push_bottom(allLINES,temp_array);
			lineY = (uint32_t)(lineY + (int32_t)line_w);
   		}
	}
	/*REMOVE STAFF LINES*/

	while( is_list_empty(allLINES)==0){
		tempData = (int16_t*)pop_top(allLINES);
		lineBegin = tempData[0];
		lineEnd = tempData[1];
		middle = (lineBegin + lineEnd + 1)/2;
		lastDelete = 0;
		free(tempData);
    
    
    		for(j=0;j<w;j++){
        
        		/*top of staff line*/
        		topStop = 0;
/*CHANGED*/
        		for(ii = (lineBegin-1); ii>=(lineBegin-extend); ii--){
/*END CHANGED*/
            			if (ii < 0){
                			break;
            			}
            			if (getPixel(img,ii,j)==0){ /*then erase*/
                			topStop = ii+1;
                			break;
            			}
        		}
    
			/*bottom of staff line*/
			botStop = h-1;
/*CHANGED*/
			for(ii = lineEnd+1; ii<=(lineEnd+extend); ii++){
/*END CHANGED*/
	     	      	 	if (ii > h-1){
	      	          		break;
		    		}
		    		if(getPixel(img,ii,j)==0){
		        		botStop = ii-1;              
		        		break;
		    		}
			}
	    
		
			/*check thickness of line, delete if skinny*/
	       	 	thickness = botStop - topStop + 1;
	       	 	if (parameters->thickness < 3){
		    		paramThickness = parameters->thickness + 1;
			}
			else{
		    		paramThickness = parameters->thickness;
			}
			if (lastDelete){ /*there was a line deletion last iteration*/
		    		thickness_th = paramThickness*2; /*higher threshold*/
			}
			else{
		    		thickness_th = paramThickness*2-2;
			}
			if (thickness <= thickness_th){
				for(ii=topStop; ii<=botStop; ii++){ 
		    			setPixel(img,ii,j,0);
				}
		    		lastDelete = 1;
			}
			else{
		    		lastDelete = 0;
			}
    
    		}
        
	} /*end staff line*/
	topLine = STAFFLINES[0][0];
	if(*previous_start){
    		if(*previous_start<topLine){
        		shift=topLine-(*previous_start);
/*CHANGED H-SHIFT-1 TO H-SHIFT*/
			for(shift_loop=0; shift_loop<(h-shift); shift_loop++){
/*END CHANGED*/
				for(cW=0; cW<w; cW++){
					pixelData=getPixel(img,shift_loop+shift,cW);
		    			setPixel(img,shift_loop,cW,pixelData);
				}
			}
			for(cH=h-shift-1; cH<h; cH++){
				for(cW=0; cW<w; cW++){
		    			setPixel(img,cH,cW,0);
				}
			}      	
		}
    		else if(*previous_start>topLine){
        		shift=*previous_start-topLine;
		
			for(shift_loop=h-1; shift_loop>=shift; shift_loop--){
				for(cW=0; cW<w; cW++){
					pixelData=getPixel(img,shift_loop-shift,cW);
		    			setPixel(img,shift_loop,cW, pixelData);
				}
			}
/*CHANGED: SHIFT-1 TO SHIFT*/
			for(cH=0; cH<shift; cH++){
/*END CHANGED*/
				for(cW=0; cW<w; cW++){
		    			setPixel(img,cH,cW,0);
				}
			}
		}	
	}
	else{
	    	*previous_start=topLine;
	}

	for(i=0; i<5;i++){
		last_STAFFLINES[i][0] = STAFFLINES[i][0];
		last_STAFFLINES[i][1] = STAFFLINES[i][1];
	}
	delete_list(staffLines);
	delete_list(allLINES);
	multifree(STAFFLINES,2);
}
示例#4
0
linked_list* find_top_bottom(const image_t* img,uint16_t height_min,uint16_t leftCutoff,linked_list* groupings){
    /* finds all vertical lines (stems, measure markers)
     Returns:
    groupings - indices within goodLines array of start and end of each vertical line
       ex: [40 42
            55 58
            100 110]
    
     goodLines - array of structs for each vertical found
       .top
       .bottom
       .left
       .right*/
    
    /*Var Declarations*/
    uint16_t height,width,col,row,test_length,i,real_length;
    linked_list *goodlines_first;/*since unsure of size, trim down later*/
    flex_array_t *starts;
    uint8_t inLine,shift,step;
    uint16_t cursor1,cursor2;
    good_lines_t *lines;
    /*End Var Declarations*/
    
    height=img->height;
    width=img->width;

    goodlines_first=create_linked_list();                                   
   
    real_length=0;
    for (col=0;col<width;col++){
        test_length=0;
        i=0;
        for (row=1;row<height;row++){
            if(!getPixel(img,row-1,col) && getPixel(img,row,col)) test_length++;
        }
        starts=make_flex_array(test_length);
        for (row=1;row<height;row++){
            if(!getPixel(img,row-1,col) && getPixel(img,row,col)) starts->data[i++]=row;;
        }
        
        for (i=0;i<test_length;i++) {/*start = starts;*/
            inLine = 1;
            cursor1=starts->data[i];
            cursor2=col;
            shift = 0;
            
            while(inLine){
                step = 0;
                if ( getPixel(img,cursor1+1,cursor2)==1 ){ /*right below*/
                    cursor1++;
                    step = 1;
                }
    
                if ( cursor2+1 < width && !step ){ /*to the bottom right*/
                    if (getPixel(img,cursor1+1,cursor2+1) ){
                        cursor1++;
                        cursor2++;
                        step = 1;
                        shift++;
                    }
                }
                    
                if ( cursor2-1 >= 0 && !step){ /*to the bottom left*/
                    if (getPixel(img,cursor1+1,cursor2-1) ){
                        cursor1++;
                        cursor2--;
                        step = 1;
                        shift ++;
                    }
                }
                    
                if (!step || shift > 3){ /*can't continue black run*/
                   if (cursor1-(starts->data[i])>=height_min){
                        real_length++;
                        lines=(good_lines_t *)malloc(sizeof(good_lines_t));
                        lines->bottom=cursor1;
                        lines->index=col;
                        lines->left= col<cursor2 ? col : cursor2;
                        lines->top=starts->data[i];
                        lines->right=col>cursor2 ? col: cursor2;
                        lines->left +=leftCutoff-1;
                        lines->right+= leftCutoff-1;
                        push_bottom(goodlines_first,lines);
                   }
                   inLine = 0;
                }
                
            } /*end while in line*/
        
        } /*end for thru each starting location*/
        delete_flex_array(starts);   
        
    } /*end for thru each column*/
    starts=make_flex_array(real_length);
    for (i=0;i<real_length;i++){
        starts->data[i]=((good_lines_t*)getIndexData(goodlines_first,i))->left;
    }
    /*GROUP LINES TOGETHER*/
    fill_group_indices(groupings,starts,5); /*2nd arg chosen to group close lines together*/
    
    delete_flex_array(starts);
    return goodlines_first;

}