Пример #1
0
animation filler::fill( PNG & img, int x, int y,
        colorPicker & fillColor, int tolerance, int frameFreq ) {
    /**
     * @todo You need to implement this function!
     *
     * This is the basic description of a flood-fill algorithm: Every fill
     * algorithm requires an ordering structure, which is passed to this
     * function via its template parameter. For a breadth-first-search
     * fill, that structure is a Queue, for a depth-first-search, that
     * structure is a Stack. To begin the algorithm, you simply place the
     * given point in the ordering structure. Then, until the structure is
     * empty, you do the following: 
     *
     * 1.     Remove a point from the ordering structure. 
     *
     *        If it has not been processed before and if its color is
     *        within the tolerance distance (up to and **including**
     *        tolerance away in square-RGB-space-distance) to the original
     *        point's pixel color [that is, \f$(currentRed - OriginalRed)^2 +
              (currentGreen - OriginalGreen)^2 + (currentBlue -
              OriginalBlue)^2 \leq tolerance\f$], then: 
     *        1.    indicate somehow that it has been processed (do not mark it
     *              "processed" anywhere else in your code) 
     *        2.    change its color in the image using the appropriate
     *              colorPicker
     *        3.    add all of its neighbors to the ordering structure, and 
     *        4.    if it is the appropriate frame, send the current PNG to the
     *              animation (as described below).
     * 2.     When implementing your breadth-first-search and
     *        depth-first-search fills, you will need to explore neighboring
     *        pixels in some order.
     *
     *        While the order in which you examine neighbors does not matter
     *        for a proper fill, you must use the same order as we do for
     *        your animations to come out like ours! The order you should put
     *        neighboring pixels **ONTO** the queue or stack is as follows:
     *        **RIGHT(+x), DOWN(+y), LEFT(-x), UP(-y). IMPORTANT NOTE: *UP*
     *        here means towards the top of the image, so since an image has
     *        smaller y coordinates at the top, this is in the *negative y*
     *        direction. Similarly, *DOWN* means in the *positive y*
     *        direction.** To reiterate, when you are exploring (filling out)
     *        from a given pixel, you must first try to fill the pixel to
     *        it's RIGHT, then the one DOWN from it, then to the LEFT and
     *        finally UP. If you do them in a different order, your fill may
     *        still work correctly, but your animations will be different
     *        from the grading scripts!
     * 3.     For every k pixels filled, **starting at the kth pixel**, you
     *        must add a frame to the animation, where k = frameFreq. 
     *
     *        For example, if frameFreq is 4, then after the 4th pixel has
     *        been filled you should add a frame to the animation, then again
     *        after the 8th pixel, etc.  You must only add frames for the
     *        number of pixels that have been filled, not the number that
     *        have been checked. So if frameFreq is set to 1, a pixel should
     *        be filled every frame.
     */
    
    animation mainframe;
    
    
    
    int row = img.height();
    int col = img.width(); 
    
    int xcord = x;
    int ycord = y;
        
    int counter = 0;
    
    //Every fill algorithm requires an ordering structure
    OrderingStructure <int> tempx;
    OrderingStructure <int> tempy;
    
    //making arrays for checking if pixel is processed already
    bool ** processed = new bool* [col];
    for(int i = 0; i < col; i++){
    	processed[i] = new bool[row];
    	for(int j = 0; j < row; j++){
    		processed[i][j] = false;
    	}
    }
    
  
    // you simply place the given point in the ordering structure
    tempx.add(xcord);
    tempy.add(ycord);
    
    
    
    RGBAPixel origin = *img(x,y);
    
    
	//Then, until the structure is empty, you do the following
    while(tempx.isEmpty() == false && tempy.isEmpty() == false){
    	
       	//Remove a point from the ordering structure.
    	xcord = tempx.peek();
    	ycord = tempy.peek();
        	
        
		tempx.remove();
		tempy.remove();	
    	
    	
    	int redval = img(xcord,ycord)->red-origin.red;
    	int greenval = img(xcord,ycord)->green-origin.green;
    	int blueval = img(xcord,ycord)->blue-origin.blue;
    	
    	
    	//If it has not been processed before and if its color is within the tolerance distance
    	if(!processed[xcord][ycord] ){
    		//indicate somehow that it has been processedprocessed[xcord][ycord] = true
    		processed[xcord][ycord] = true;
     		if (redval*redval + greenval*greenval + blueval*blueval <= tolerance){
				//change its color in the image using the appropriate colorPicker
				*img(xcord,ycord) = fillColor(xcord,ycord);
				
				
				//add all of its neighbors to the ordering structure
				if(xcord+1 < row && ycord < col ) {
					tempx.add(xcord+1);
					tempy.add(ycord);
					}
				if(xcord < row  && ycord + 1 < col ) {
					tempx.add(xcord);
					tempy.add(ycord+1);
					}
				if(xcord-1 >= 0 && xcord-1 < row && ycord < col ) {
					tempx.add(xcord-1);
					tempy.add(ycord);
					}
				if(xcord < row && ycord-1 < col && ycord -1 >= 0 ) {
					tempx.add(xcord);
					tempy.add(ycord-1);
					}
				
			
			//if it is the appropriate frame, send the current PNG to the animation 
				counter++;
				if(counter % frameFreq == 0){
					counter = 0;
					mainframe.addFrame(img);
				} 
			}
			
		}
		
		
    }
       
   	for(int i = 0; i < col; i++){
    	delete [] processed[i];
    } 
    
    delete [] processed;
       
    return mainframe;

}
Пример #2
0
animation filler::fill( PNG & img, int x, int y,
        colorPicker & fillColor, int tolerance, int frameFreq ) {
    /**
     * @todo You need to implement this function!
     *
     * This is the basic description of a flood-fill algorithm: Every fill
     * algorithm requires an ordering structure, which is passed to this
     * function via its template parameter. For a breadth-first-search
     * fill, that structure is a Queue, for a depth-first-search, that
     * structure is a Stack. To begin the algorithm, you simply place the
     * given point in the ordering structure. Then, until the structure is
     * empty, you do the following:
     *
     * 1.     Remove a point from the ordering structure. 
     *
     *        If it has not been processed before and if its color is
     *        within the tolerance distance (up to and **including**
     *        tolerance away in square-RGB-space-distance) to the original
     *        point's pixel color [that is, \f$(currentRed - OriginalRed)^2 +
              (currentGreen - OriginalGreen)^2 + (currentBlue -
              OriginalBlue)^2 \leq tolerance\f$], then: 
     *        1.    indicate somehow that it has been processed (do not mark it
     *              "processed" anywhere else in your code) 
     *        2.    change its color in the image using the appropriate
     *              colorPicker
     *        3.    add all of its neighbors to the ordering structure, and 
     *        4.    if it is the appropriate frame, send the current PNG to the
     *              animation (as described below).
     * 2.     When implementing your breadth-first-search and
     *        depth-first-search fills, you will need to explore neighboring
     *        pixels in some order.
     *
     *        While the order in which you examine neighbors does not matter
     *        for a proper fill, you must use the same order as we do for
     *        your animations to come out like ours! The order you should put
     *        neighboring pixels **ONTO** the queue or stack is as follows:
     *        **RIGHT(+x), DOWN(+y), LEFT(-x), UP(-y). IMPORTANT NOTE: *UP*
     *        here means towards the top of the image, so since an image has
     *        smaller y coordinates at the top, this is in the *negative y*
     *        direction. Similarly, *DOWN* means in the *positive y*
     *        direction.** To reiterate, when you are exploring (filling out)
     *        from a given pixel, you must first try to fill the pixel to
     *        it's RIGHT, then the one DOWN from it, then to the LEFT and
     *        finally UP. If you do them in a different order, your fill may
     *        still work correctly, but your animations will be different
     *        from the grading scripts!
     * 3.     For every k pixels filled, **starting at the kth pixel**, you
     *        must add a frame to the animation, where k = frameFreq. 
     *
     *        For example, if frameFreq is 4, then after the 4th pixel has
     *        been filled you should add a frame to the animation, then again
     *        after the 8th pixel, etc.  You must only add frames for the
     *        number of pixels that have been filled, not the number that
     *        have been checked. So if frameFreq is set to 1, a pixel should
     *        be filled every frame.
     */
	OrderingStructure <int> xCoordinates;
	OrderingStructure <int> yCoordinates;
	animation myAnimation;
	int frameCount = 0;
	std::vector <bool> checkArray(img.height()*img.width());
	for (size_t i = 0; i < img.height(); i++)
	{
		for(size_t j = 0; j < img.width(); j++)
		{
			checkArray[i*img.width()+j] = false;
		}
	}
	xCoordinates.add(x);
	yCoordinates.add(y);
	int origin_r = img(x,y)->red;
 	int origin_g = img(x,y)->green;
        int origin_b = img(x,y)->blue;

	while(!xCoordinates.isEmpty())
	{
		int currX = xCoordinates.remove();
		int currY = yCoordinates.remove();
		RGBAPixel currPixel = *img(currX,currY);
		int colorDistance = pow(currPixel.red-origin_r,2) + pow(currPixel.green-origin_g,2) + pow(currPixel.blue -origin_b,2);	
		if((!checkArray[currY*img.width()+currX])&& colorDistance <= tolerance)
		{
			checkArray[currY*img.width()+currX] = true;
			RGBAPixel tempPixel = fillColor(currX,currY);
			img(currX,currY)->red = tempPixel.red;
			img(currX,currY)->green = tempPixel.green;
			img(currX,currY)->blue = tempPixel.blue;
			//right
			if(currX + 1 < int(img.height()))
			{
				xCoordinates.add(currX+1);
				yCoordinates.add(currY);
			}
			//down
			if(currY + 1 < int(img.height()))
			{
				xCoordinates.add(currX);
				yCoordinates.add(currY+1);
			}
			//left
			if(currX - 1 >= 0)
			{
				xCoordinates.add(currX-1);
				yCoordinates.add(currY);
			}
			//up
			if(currY - 1 >= 0)
			{
				xCoordinates.add(currX);
				yCoordinates.add(currY-1);
			}			
			if((++frameCount) % frameFreq == 0) 
				myAnimation.addFrame(img);

		}	
	
	}
		
    	return myAnimation;	
}
Пример #3
0
animation filler::fill( PNG & img, int x, int y,
        colorPicker & fillColor, int tolerance, int frameFreq ) 
{
	OrderingStructure<RGBAPixel> sq; //pixel structure
	OrderingStructure<int> sqX; //Xcoord structure
	OrderingStructure<int> sqY; //Ycoord structure
	int** marks = new int *[img.width()]; //array of pointers with size width 0 1 2 3
	for(int i = 0; i < img.width(); i++) //array of pointers to arrays of size height x = 0->y = 0 1
	{
		marks[i] = new int[img.height()];
		for(int j = 0; j < img.height(); j++) //set coordinates to mark values e.g 0,1 = 0
			marks[i][j] = 0;
	}

	int count = 0; //count when to add new frame
	animation fillAnimation; //animation to return

	RGBAPixel origin = (*img(x,y));
	sq.add(origin);
	sqX.add(x);
	sqY.add(y);

	while(!sq.isEmpty())
	{
		RGBAPixel pixel = sq.remove();
		int xCoord = sqX.remove();
		int yCoord = sqY.remove();

		int originRed = origin.red, pixelRed = pixel.red, 
			originBlue = origin.blue, pixelBlue = pixel.blue,
			originGreen = origin.green, pixelGreen = pixel.green; 

		int toleranceValue = pow((originRed - pixelRed), 2) + 
			pow((originBlue - pixelBlue), 2) + 
			pow((originGreen - pixelGreen), 2);

		if(marks[xCoord][yCoord] == 0 && toleranceValue <= tolerance)
		{	

			marks[xCoord][yCoord] = 1;
			count++;
			*img(xCoord,yCoord) = fillColor(xCoord,yCoord);

			if(count == frameFreq)
			{
				fillAnimation.addFrame(img);
				count = 0;
			}
		
		
			if(xCoord < img.width() - 1)
			{
				sqX.add(xCoord + 1);
				sqY.add(yCoord);
				sq.add(*img(xCoord+1,yCoord));
			}

			if(yCoord < img.height() - 1)
			{
				sqX.add(xCoord);
				sqY.add(yCoord+1);
				sq.add(*img(xCoord,yCoord+1));
			}

			if(xCoord - 1 >= 0)
			{
				sqX.add(xCoord-1);
				sqY.add(yCoord);
				sq.add(*img(xCoord-1,yCoord));
			}

			if(yCoord - 1 >= 0)	
			{
				sqX.add(xCoord);
				sqY.add(yCoord-1);
				sq.add(*img(xCoord,yCoord-1));
			}
		}
	}
    return fillAnimation;
}
Пример #4
0
animation filler::fill(PNG& img, int x, int y, colorPicker& fillColor,
                       int tolerance, int frameFreq)
{
    /**
     * @todo You need to implement this function!
     *
     * This is the basic description of a flood-fill algorithm: Every fill
     * algorithm requires an ordering structure, which is passed to this
     * function via its template parameter. For a breadth-first-search
     * fill, that structure is a Queue, for a depth-first-search, that
     * structure is a Stack. To begin the algorithm, you simply place the
     * given point in the ordering structure. Then, until the structure is
     * empty, you do the following:
     *
     * 1.     Remove a point from the ordering structure.
     *
     *        If it has not been processed before and if its color is
     *        within the tolerance distance (up to and **including**
     *        tolerance away in square-RGB-space-distance) to the original
     *        point's pixel color [that is, \f$(currentRed - OriginalRed)^2 +
              (currentGreen - OriginalGreen)^2 + (currentBlue -
              OriginalBlue)^2 \leq tolerance\f$], then:
     *        1.    indicate somehow that it has been processed (do not mark it
     *              "processed" anywhere else in your code)
     *        2.    change its color in the image using the appropriate
     *              colorPicker
     *        3.    add all of its neighbors to the ordering structure, and
     *        4.    if it is the appropriate frame, send the current PNG to the
     *              animation (as described below).
     * 2.     When implementing your breadth-first-search and
     *        depth-first-search fills, you will need to explore neighboring
     *        pixels in some order.
     *
     *        While the order in which you examine neighbors does not matter
     *        for a proper fill, you must use the same order as we do for
     *        your animations to come out like ours! The order you should put
     *        neighboring pixels **ONTO** the queue or stack is as follows:
     *        **RIGHT(+x), DOWN(+y), LEFT(-x), UP(-y). IMPORTANT NOTE: *UP*
     *        here means towards the top of the image, so since an image has
     *        smaller y coordinates at the top, this is in the *negative y*
     *        direction. Similarly, *DOWN* means in the *positive y*
     *        direction.** To reiterate, when you are exploring (filling out)
     *        from a given pixel, you must first try to fill the pixel to
     *        it's RIGHT, then the one DOWN from it, then to the LEFT and
     *        finally UP. If you do them in a different order, your fill may
     *        still work correctly, but your animations will be different
     *        from the grading scripts!
     * 3.     For every k pixels filled, **starting at the kth pixel**, you
     *        must add a frame to the animation, where k = frameFreq.
     *
     *        For example, if frameFreq is 4, then after the 4th pixel has
     *        been filled you should add a frame to the animation, then again
     *        after the 8th pixel, etc.  You must only add frames for the
     *        number of pixels that have been filled, not the number that
     *        have been checked. So if frameFreq is set to 1, a pixel should
     *        be filled every frame.
     */
    OrderingStructure<int> xcoord;
    OrderingStructure<int> ycoord;
    xcoord.add(x);
    ycoord.add(y);

    animation a;
    int counter = 0;
    
    int h = img.height();
    int w = img.width();
    bool** processed = new bool*[h];
    for (int i = 0; i < h; i++){
	processed[i] = new bool[w];
	for (int j = 0; j < w; j++){
	    processed[i][j] = false;
	}
    }

    int oriRed = img(x,y) -> red;
    int oriGreen = img(x,y) -> green;
    int oriBlue = img(x,y) -> blue;

    while (!xcoord.isEmpty() && !ycoord.isEmpty()){
	x = xcoord.remove();
	y = ycoord.remove();
	
	int curRed = img(x,y) -> red;
	int curGreen = img(x,y) -> green;
	int curBlue = img(x,y) -> blue;

	int colorDist = (curRed - oriRed)*(curRed - oriRed) + (curGreen - oriGreen)*(curGreen - oriGreen) + (curBlue - oriBlue)*(curBlue - oriBlue);
	if (!processed[y][x] && colorDist <= tolerance){
	    processed[y][x] = true;

   	    img(x,y) -> red = fillColor(x,y).red;
	    img(x,y) -> green = fillColor(x,y).green;
	    img(x,y) -> blue = fillColor(x,y).blue;	

	    if (x + 1 < w && !processed[y][x+1]){
		xcoord.add(x + 1); 
		ycoord.add(y);
	    }

	    if (y + 1 < h && !processed[y+1][x]){
		xcoord.add(x);
		ycoord.add(y + 1);
	    }

	    if (x - 1 >= 0 && !processed[y][x-1]){
		xcoord.add(x - 1);
		ycoord.add(y);
	    }
	
	    if (y - 1 >= 0 && !processed[y-1][x]){
		xcoord.add(x);
		ycoord.add(y - 1);
	    }

	    counter++;
	    if (counter % frameFreq == 0)
		a.addFrame(img);
	}
    }
 
    for (int i = 0; i < h; i++)
	delete [] processed[i];
    delete [] processed;

    return a;
}
Пример #5
0
animation filler::fill( PNG & img, int x, int y,
        colorPicker & fillColor, int tolerance, int frameFreq ) {
    /**
     * @todo You need to implement this function!
     *
     * This is the basic description of a flood-fill algorithm: Every fill
     * algorithm requires an ordering structure, which is passed to this
     * function via its template parameter. For a breadth-first-search
     * fill, that structure is a Queue, for a depth-first-search, that
     * structure is a Stack. To begin the algorithm, you simply place the
     * given point in the ordering structure. Then, until the structure is
     * empty, you do the following:
     *
     * 1.     Remove a point from the ordering structure. 
     *
     *        If it has not been processed before and if its color is
     *        within the tolerance distance (up to and **including**
     *        tolerance away in square-RGB-space-distance) to the original
     *        point's pixel color [that is, \f$(currentRed - OriginalRed)^2 +
              (currentGreen - OriginalGreen)^2 + (currentBlue -
              OriginalBlue)^2 \leq tolerance\f$], then: 
     *        1.    indicate somehow that it has been processed (do not mark it
     *              "processed" anywhere else in your code) 
     *        2.    change its color in the image using the appropriate
     *              colorPicker
     *        3.    add all of its neighbors to the ordering structure, and 
     *        4.    if it is the appropriate frame, send the current PNG to the
     *              animation (as described below).
     * 2.     When implementing your breadth-first-search and
     *        depth-first-search fills, you will need to explore neighboring
     *        pixels in some order.
     *
     *        While the order in which you examine neighbors does not matter
     *        for a proper fill, you must use the same order as we do for
     *        your animations to come out like ours! The order you should put
     *        neighboring pixels **ONTO** the queue or stack is as follows:
     *        **RIGHT(+x), DOWN(+y), LEFT(-x), UP(-y). IMPORTANT NOTE: *UP*
     *        here means towards the top of the image, so since an image has
     *        smaller y coordinates at the top, this is in the *negative y*
     *        direction. Similarly, *DOWN* means in the *positive y*
     *        direction.** To reiterate, when you are exploring (filling out)
     *        from a given pixel, you must first try to fill the pixel to
     *        it's RIGHT, then the one DOWN from it, then to the LEFT and
     *        finally UP. If you do them in a different order, your fill may
     *        still work correctly, but your animations will be different
     *        from the grading scripts!
     * 3.     For every k pixels filled, **starting at the kth pixel**, you
     *        must add a frame to the animation, where k = frameFreq. 
     *
     *        For example, if frameFreq is 4, then after the 4th pixel has
     *        been filled you should add a frame to the animation, then again
     *        after the 8th pixel, etc.  You must only add frames for the
     *        number of pixels that have been filled, not the number that
     *        have been checked. So if frameFreq is set to 1, a pixel should
     *        be filled every frame.
     */
	OrderingStructure<RGBAPixel> pixels; //structure to return
    	OrderingStructure<int> cx;		//x axis
    	OrderingStructure<int> cy;		//y axis
    	bool process[img.width()][img.height()];
    for (int i = 0; i < img.width(); i++)
    {
        for (int j = 0; j <img.height(); j++)
        {
            process[i][j] = false;
        }
    }
	 animation anim;		//output
    int frame = 0;

    RGBAPixel origPixel = *(img(x,y));	//one pix to input
    int origRed = origPixel.red;
    int origGreen = origPixel.green;
    int origBlue = origPixel.blue;
	pixels.add(*img(x,y));//put into
    	cx.add(x);
    	cy.add(y);

    while (!pixels.isEmpty())
    {
        //remove one point in the structure
        RGBAPixel currPixel = pixels.remove();

        int currRed = currPixel.red;
        int currGreen = currPixel.green;
        int currBlue = currPixel.blue;
        int currX = cx.remove();
        int currY = cy.remove();
	 int min = pow(origRed-currRed,2)+pow(origGreen-currGreen,2)+pow(origBlue-currBlue,2);
	if ((min <= tolerance) && !process[currX][currY])
        {
	process[currX][currY] = true;//mark
         frame++;
	*(img(currX,currY)) = fillColor(currX,currY);
	  if (currX+1 <img.width())
            {
            //RIGHT
            pixels.add(*(img(currX+1,currY)));
            cx.add(currX+1);
            cy.add(currY);
            }
            
            if (currY+1 <img.height())
            {
            //DOWN
            pixels.add(*(img(currX,currY+1)));
            cx.add(currX);
            cy.add(currY+1);
            }

            if (currX-1>= 0)
            {
            //LEFT
            pixels.add(*(img(currX-1,currY)));
            cx.add(currX-1);
            cy.add(currY);
            }

            if (currY-1>= 0)
            {
            //DOWN
            pixels.add(*(img(currX,currY-1)));
            cx.add(currX);
            cy.add(currY-1);
            }
		 if (frame % frameFreq == 0)
            {
                //add the current image to the animation
                anim.addFrame(img);
            }
     }
    }
    return anim;
}