CS50 Week 4 Problem Set: Filter-less

Kevin HindriksKevin Hindriks
4 min read

Hello newbie coders! My name is Kevin and this blog is my documentation of my coding journey which I started 4 weeks ago.

I am currently in Week 4: Memory of the CS50x course, and the practice problems, labs, and problem sets in this week really felt like there was quite a leap in difficulty level.

For the problem set "Filter", this one really had me stumped for two days. In the end, I figured out that my calculations for the averages were giving wrong numbers because I was not dividing by a FLOAT variable.

The function that I found particularly challenging was the blur function. So if you're stuck and don't want to look up the answer yet, here are some tips that may help you out:

  • The blur function will require 4 "for" loops. Two to iterate through all the pixels, and two to iterate through the surrounding pixels of the pixel you will blur.

  • Use FLOAT variables when making divisions.

If you still have difficulty figuring it out, I have pasted my own code below, which passes check50 100%. Just keep in mind that copy-pasting the code into this blog made some of the indentations weird. Also, keep in mind that I'm a beginner and some of my code may not be the best way to do it.

Good luck with the Week 4 problem sets, and don't give up! :)

<code>

#include "helpers.h"
#include <math.h>
#include <stdio.h>

// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    int average; // The average of red, green, and blue values

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            // Calculate average
            average = round((image[i][j].rgbtRed + image[i][j].rgbtGreen +
                             image[i][j].rgbtBlue) / 3.0);

            // Assign average to all colors
            image[i][j].rgbtRed = average;
            image[i][j].rgbtGreen = average;
            image[i][j].rgbtBlue = average;
        }
    }
    return;
}

// Convert image to sepia
void sepia(int height, int width, RGBTRIPLE image[height][width])
{
    // Temporary placeholders for colors used to facilitate calculation of sepia
    int orig_red, orig_green, orig_blue;

    // Temporary placeholders for new colors (in case they are over 255)
    int new_red, new_green, new_blue;

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            orig_red = image[i][j].rgbtRed;
            orig_green = image[i][j].rgbtGreen;
            orig_blue = image[i][j].rgbtBlue;

            new_red = round(.393 * orig_red + .769 * orig_green + .189 * orig_blue);
            new_green = round(.349 * orig_red + .686 * orig_green + .168 * orig_blue);
            new_blue = round(.272 * orig_red + .534 * orig_green + .131 * orig_blue);

            // This will cap the red to 255
            if (new_red > 255)
            {
                image[i][j].rgbtRed = 255;
            }
            else
                image[i][j].rgbtRed = new_red;

            // This will cap the green to 255
            if (new_green > 255)
            {
                image[i][j].rgbtGreen = 255;
            }
            else
                image[i][j].rgbtGreen = new_green;

            // This will cap the blue to 255
            if (new_blue > 255)
            {
                image[i][j].rgbtBlue = 255;
            }
            else
                image[i][j].rgbtBlue = new_blue;
        }
    }

    return;
}

// Reflect image horizontally
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
    // These temporary matrices will be used to store a copy of the image
    int temp_red[height][width], temp_green[height][width], temp_blue[height][width];

    // Let's the populate the temporary matrices here
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            temp_red[i][j] = image[i][j].rgbtRed;
            temp_green[i][j] = image[i][j].rgbtGreen;
            temp_blue[i][j] = image[i][j].rgbtBlue;
        }
    }

    // Now we can flip the image by assigning the color values
    // at the end of a row to the beginning of the row
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            image[i][j].rgbtRed = temp_red[i][width - 1 - j];
            image[i][j].rgbtGreen = temp_green[i][width - 1 - j];
            image[i][j].rgbtBlue = temp_blue[i][width - 1 - j];
        }
    }
    return;
}

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    // this will create a copy of image
    RGBTRIPLE temp[height][width];

    // make a copy of image[height][width]
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            temp[i][j] = image[i][j];
        }
    }

    // use "for" loop to iterate through 'i' values of 'image'
    for (int i = 0; i < height; i++)
    {
        // use "for" loop to iterate through 'j' values 'image'
        for (int j = 0; j < width; j++)
        {
            // total values of surrounding colors for every pixel, before taking average
            // total values of surrounding colors for every pixel, before taking average
            int total_red = 0, total_green = 0,
                total_blue = 0;

            // counts number of valid pixels
            float total_pixels = 0.00;

            // use 2 "for" loops again to iterate through surrounding pixels
            for (int x = -1; x < 2; x++)
            {
                for (int y = -1; y < 2; y++)
                {
                    int i_counter = i + x;
                    int j_counter = j + y;

                    // this 'if' statement will filter out any invalid pixles
                    if (i_counter < 0 || j_counter < 0 ||
                        i_counter > height - 1 || j_counter > width - 1)
                    {
                        continue;
                    }
                    // ELSE increment color RGB values
                    else
                    {
                        total_red += temp[i_counter][j_counter].rgbtRed;
                        total_green += temp[i_counter][j_counter].rgbtGreen;
                        total_blue += temp[i_counter][j_counter].rgbtBlue;

                        total_pixels++;
                    }
                }
            }
            // get averages and update image[i][j] color values
            image[i][j].rgbtRed = round(total_red / total_pixels);
            image[i][j].rgbtGreen = round(total_green / total_pixels);
            image[i][j].rgbtBlue = round(total_blue / total_pixels);
        }
    }
    return;
}

</code>

0
Subscribe to my newsletter

Read articles from Kevin Hindriks directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Kevin Hindriks
Kevin Hindriks

I am a full-time filmmaker, learning how to code to add to my skillset.