Cs50 Problem set 4 Filter less Solution: my step by step explanation

Oh, it’s a new Problem set 4 Filter, where we are required to edit a Bitmap picture and apply different filters such as Grayscale, Sepia, Reflect and Blur to it through code traditionally.

This Pset took me days before I could sit down and write something, thanks to Reddit and Stackoverflow for helping me out.

Here is it, let me explain each step I’ve taken to complete the problem.

Filter Less Solution

Firstly we are told to download the problem distribution code with wget command to get stuff ready.

while this Pset has many file like bmp.h, filter.c, helpers.h, Makefile, and helpers.c, that are working together in the background, we are only required to write the function in helpers.c file.

Grayscale/filter

What we are to do in this function is to write a code that will take an image and convert it to a black-and-white effect.

for us to implement this code, we need to make sure that in each pixel, the Red, Green, and blue values are all the same. To do this, the amount of red, green, and blue must be known so that we can average it, and set each pixel back to the average value of the RGB.

pseudocode

  • iterate through each pixel i.e the image height and width.
  • Calculate the average pixel value
  • Round the new average
  • Set each color value to the average value
int average;
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            int Red = image[i][j].rgbtRed;
            int Green = image[i][j].rgbtGreen;
            int Blue = image[i][j].rgbtBlue;
            average = round(((float)Red + (float)Green + (float)Blue)/3);
            image[i][j].rgbtRed = average;
            image[i][j].rgbtGreen = average;
            image[i][j].rgbtBlue = average;
        }
    }

Filter / Sepia function

What we are to do in this function is to write a code that takes a bitmap image and converts it to Sepia like, giving everything a reddish-brown, old-time filter.

this function seems to be the easiest of all, as we are given the formula, the only problem we are having is to make sure values are between the range of 0 to 255 and must be round up, since we are using a formula, there’s a very big chance that we could get value of float.

pseudocode

  • Iterate through each pixel. i.e the image height and width
  • Calculate each new color value using the Sepia formula
  • check if the new color is greater than 255,
    • if so, the new color value should be set to 255
    • else, the new color value should not be changed
 int originalRed, originalGreen, originalBlue;
    int sepiaRed, sepiaBlue, sepiaGreen;

    //iterate through the height
    for ( int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            //assign each value to variable created
            originalRed = image[i][j].rgbtRed;
            originalGreen = image[i][j].rgbtGreen;
            originalBlue = image[i][j].rgbtBlue;

            //calculate for sepiaColor and assign new value
            sepiaRed = round(0.393 * originalRed + 0.769 * originalGreen + 0.189 * originalBlue);


            if (sepiaRed > 255)
            {
                image[i][j].rgbtRed = 255;
            }
            else
            {
                image[i][j].rgbtRed = sepiaRed;
            }

            //calculate for sepiaGreen and assign new value
            sepiaGreen = round(0.349 * originalRed + 0.686 * originalGreen + 0.168 * originalBlue);
            if (sepiaGreen > 255)
            {
                image[i][j].rgbtGreen = 255;
            }
            else
            {
                image[i][j].rgbtGreen = sepiaGreen;
            }
            //Calculate for sepiaBlue and assign new value
            sepiaBlue = round(0.272 * originalRed + 0.534 * originalGreen + 0.131 * originalBlue);
            if (sepiaBlue > 255)
            {
                image[i][j].rgbtBlue = 255;
            }
            else
            {
                image[i][j].rgbtBlue = sepiaBlue;
            }
        }

    }
    return;

Filter / Reflect

This function’s main purpose is to convert an image to a mirror-like image. so to do this, we need to swap the pixel of the left of an image to the right of the image, but leaving the row unchanged.

pseudocode

  • iterate through the height of the image
  • iterate through half of the image width
  • create a temporary variable and store the original image in the variable
  • store right image into the original image
  • store the temporary variable into the right image
 for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < (width/2); j++)
        {
            int temPred = image[i][j].rgbtRed;
            int temPgreen = image[i][j].rgbtGreen;
            int temPblue = image[i][j].rgbtBlue;

            image[i][j].rgbtRed = image[i][width - j - 1].rgbtRed;
            image[i][j].rgbtGreen = image[i][width - j - 1].rgbtGreen;
            image[i][j].rgbtBlue = image[i][width - j - 1].rgbtBlue;

            image[i][width - j - 1].rgbtRed = temPred;
            image[i][width - j - 1].rgbtGreen = temPgreen;
            image[i][width - j - 1].rgbtBlue = temPblue;
        }


    }
    return;

Filter / Blur function

For this problem, we’ll use the “box blur,” which works by taking each pixel and, for each color value, giving it a new value by averaging the color values of neighboring pixels.

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    //create a temporary image to implement blurred algorithm on it.
    RGBTRIPLE temp[height][width];

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            int total_Red, total_Blue, total_Green;
            total_Red = total_Blue = total_Green = 0;
            float counter = 0.00;

            //Get the neighbouring pexels
            for (int x = -1; x < 2; x++)
            {
                for (int y = -1; y < 2; y++)
                {
                    int currentX = i + x;
                    int currentY = j + y;

                    //check for valid neighbouring pexels
                    if (currentX < 0 || currentX > (height - 1) || currentY < 0 || currentY > (width - 1))
                    {
                        continue;
                    }

                    //Get the image value
                    total_Red += image[currentX][currentY].rgbtRed;
                    total_Green += image[currentX][currentY].rgbtGreen;
                    total_Blue += image[currentX][currentY].rgbtBlue;

                    counter++;
                }

                //do the average of neigbhouring pexels
                temp[i][j].rgbtRed = round(total_Red / counter);
                temp[i][j].rgbtGreen = round(total_Green / counter);
                temp[i][j].rgbtBlue = round(total_Blue / counter);
            }
        }

    }

    //copy the blurr image to the original image
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            image[i][j].rgbtRed = temp[i][j].rgbtRed;
            image[i][j].rgbtGreen = temp[i][j].rgbtGreen;
            image[i][j].rgbtBlue = temp[i][j].rgbtBlue;
        }
    }
    return;
}

I hope you are able to get it done, Honestly this Pset is one of the toughest in Cs50, especially the Blur function.

Thanks for reading.

7 comments

  1. im sorry but WHY ON THE EARTH wud u post this without finishing the problem???????? And its been 9 f*cking months and u havent “got back” smh

    1. oh thanks for bringing my attention to this.
      I forgot to update it, you can check it now, it’s been updated and it’s working perfectly.
      check50 returns green…..thanks again

    2. Whoa, Bob. Whoa.

  2. Thanks for your help Collins, really appreciate you taking the time to put these up for us.

    1. I’m so glad you found it helpful.
      Thanks also

  3. Thank you for this. It was very hard for me and I got stuck many times. This helped me alot so thank you again

  4. You are a life saver!

Leave a Reply