Solutions to CS50 Problem Set 4 Filter & Recover Problems (2022)

Disclaimer: These answers are only for educational purposes only. Please do not use them for cheating. Cheating doesn’t do any good for you!

In this post, I’m giving you my solutions to CS50 Problem Set 4 Filter (less comfortable / more comfortable) Problems and Recover problems. Hope these solutions will help you to better understand the problems and be a guide for your solutions too.

The Solution to CS50 Psets 4 Filter Problem – Less Comfortable (2022)

For this problem, we just have to implement a program that applies filters to BMPs. And a bunch of files were provided for us. We have to implement some functions in helpers.c to apply greyscale, Sepia, reflection, and blur filters to the given images.

The greyscale function turns the input image into a black-and-white version of it

// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    // Iterate through each column of pixel
    for (int i = 0; i < height; i++)
    {
        // Iterate through each raw of pixel in each column
        for (int j = 0; j < width; j++)
        {
            // Get into the 2D array, obtain value of each color
            int red = image[i][j].rgbtRed;
            int blue = image[i][j].rgbtBlue;
            int green = image[i][j].rgbtGreen;

            // Calculate the rounded avarage of each pixel
            int average = round(((float)red + (float)blue + (float)green) / 3);

            // Set the calculated value to be the new value of each pixel
            image[i][j].rgbtRed = image[i][j].rgbtBlue = image[i][j].rgbtGreen = average;
        }
    }
}

The sepia function turns the input image into sepia version of the same image

    // Convert image to sepia
    void sepia(int height, int width, RGBTRIPLE image[height][width])
    {
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                int red = image[i][j].rgbtRed;
                int blue = image[i][j].rgbtBlue;
                int green = image[i][j].rgbtGreen;
    
                // New sapia values
                int sepiaRed = round(0.393 * red + 0.769 * green + 0.189 * blue);
    
                if (sepiaRed > 255)
                {
                    image[i][j].rgbtRed = 255;
                }
                else
                {
                    image[i][j].rgbtRed = sepiaRed;
                }
    
                int sepiaBlue = round(0.272 * red + 0.534 * green + 0.131 * blue);
    
                if (sepiaBlue > 255)
                {
                    image[i][j].rgbtBlue = 255;
                }
                else
                {
                    image[i][j].rgbtBlue = sepiaBlue;
                }
    
                int sepiaGreen = round(0.349 * red + 0.686 * green + 0.168 * blue);
    
                if (sepiaGreen > 255)
                {
                    image[i][j].rgbtGreen = 255;
                }
                else
                {
                    image[i][j].rgbtGreen = sepiaGreen;
                }
            }
        }
    }

    The reflect function takes the image and reflects in horizontally

    // Reflect image horizontally
    void reflect(int height, int width, RGBTRIPLE image[height][width])
    {
        for (int i = 0; i < height; i++)
        {
            // Iterate through the array until you get the mid point
            for (int j = 0; j < (width / 2); j++)
            {
                RGBTRIPLE temp = image[i][j];
    
                image[i][j] = image[i][width - (j + 1)];
                image[i][width - (j + 1)] = temp;
            }
        }
        return;
    }

    The blur function takes an image and turns it into a box-blurred version of the image

    // 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 sumRed, sumBlue, sumGreen;
                sumRed = sumBlue = sumGreen = 0;
                float counter = 0.00;
    
                //Get the neighbouring pexels
                for (int c = -1; c < 2; c++)
                {
                    for (int r = -1; r < 2; r++)
                    {
                        int currentX = i + c;
                        int currentY = j + r;
    
                        //check for valid neighbouring pexels
                        if (currentX < 0 || currentX > (height - 1) || currentY < 0 || currentY > (width - 1))
                        {
                            continue;
                        }
    
                        //Get the image value
                        sumRed += image[currentX][currentY].rgbtRed;
                        sumGreen += image[currentX][currentY].rgbtGreen;
                        sumBlue += image[currentX][currentY].rgbtBlue;
    
                        counter++;
                    }
    
                    //do the average of neigbhouring pexels
                    temp[i][j].rgbtRed = round(sumRed / counter);
                    temp[i][j].rgbtGreen = round(sumGreen / counter);
                    temp[i][j].rgbtBlue = round(sumBlue / 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;
    }

    Full code of helpers.c file

    #include "helpers.h"
    #include <math.h>
    
    // Convert image to grayscale
    void grayscale(int height, int width, RGBTRIPLE image[height][width])
    {
        // Iterate through each column of pixel
        for (int i = 0; i < height; i++)
        {
            // Iterate through each raw of pixel in each column
            for (int j = 0; j < width; j++)
            {
                // Get into the 2D array, obtain value of each color
                int red = image[i][j].rgbtRed;
                int blue = image[i][j].rgbtBlue;
                int green = image[i][j].rgbtGreen;
    
                // Calculate the rounded avarage of each pixel
                int average = round(((float)red + (float)blue + (float)green) / 3);
    
                // Set the calculated value to be the new value of each pixel
                image[i][j].rgbtRed = image[i][j].rgbtBlue = image[i][j].rgbtGreen = average;
            }
        }
    }
    
    // Convert image to sepia
    void sepia(int height, int width, RGBTRIPLE image[height][width])
    {
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                int red = image[i][j].rgbtRed;
                int blue = image[i][j].rgbtBlue;
                int green = image[i][j].rgbtGreen;
    
                // New sapia values
                int sepiaRed = round(0.393 * red + 0.769 * green + 0.189 * blue);
    
                if (sepiaRed > 255)
                {
                    image[i][j].rgbtRed = 255;
                }
                else
                {
                    image[i][j].rgbtRed = sepiaRed;
                }
    
                int sepiaBlue = round(0.272 * red + 0.534 * green + 0.131 * blue);
    
                if (sepiaBlue > 255)
                {
                    image[i][j].rgbtBlue = 255;
                }
                else
                {
                    image[i][j].rgbtBlue = sepiaBlue;
                }
    
                int sepiaGreen = round(0.349 * red + 0.686 * green + 0.168 * blue);
    
                if (sepiaGreen > 255)
                {
                    image[i][j].rgbtGreen = 255;
                }
                else
                {
                    image[i][j].rgbtGreen = sepiaGreen;
                }
            }
        }
    }
    
    // Reflect image horizontally
    void reflect(int height, int width, RGBTRIPLE image[height][width])
    {
        for (int i = 0; i < height; i++)
        {
            // Iterate through the array until you get the mid point
            for (int j = 0; j < (width / 2); j++)
            {
                RGBTRIPLE temp = image[i][j];
    
                image[i][j] = image[i][width - (j + 1)];
                image[i][width - (j + 1)] = temp;
            }
        }
        return;
    }
    
    
    // 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 sumRed, sumBlue, sumGreen;
                sumRed = sumBlue = sumGreen = 0;
                float counter = 0.00;
    
                //Get the neighbouring pexels
                for (int c = -1; c < 2; c++)
                {
                    for (int r = -1; r < 2; r++)
                    {
                        int currentX = i + c;
                        int currentY = j + r;
    
                        //check for valid neighbouring pexels
                        if (currentX < 0 || currentX > (height - 1) || currentY < 0 || currentY > (width - 1))
                        {
                            continue;
                        }
    
                        //Get the image value
                        sumRed += image[currentX][currentY].rgbtRed;
                        sumGreen += image[currentX][currentY].rgbtGreen;
                        sumBlue += image[currentX][currentY].rgbtBlue;
    
                        counter++;
                    }
    
                    //do the average of neigbhouring pexels
                    temp[i][j].rgbtRed = round(sumRed / counter);
                    temp[i][j].rgbtGreen = round(sumGreen / counter);
                    temp[i][j].rgbtBlue = round(sumBlue / 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;
    }

    The Solution to CS50 Psets 4 Filter Problem – More Comfortable (2022)

    For this problem also, we have to implement a program that applies filters to BMPs. And a bunch of files were provided for us. We have to implement some functions in helpers.c to apply greyscale, reflection, blur, and edge filters to the given images.

    The greyscale function should take an image and turn it into a black-and-white version of the same image.

    // Convert image to grayscale
    void grayscale(int height, int width, RGBTRIPLE image[height][width])
    {
        // Iterate though each column
        for (int i = 0; i < height; i++)
        {
            // Iterate through each raw of pixel in each column
            for (int j = 0; j < width; j++)
            {
                // Get into 2D array and obtain value of each color
                int red = image[i][j].rgbtRed;
                int blue = image[i][j].rgbtBlue;
                int green = image[i][j].rgbtGreen;
    
                // Calculate the rounded avarage of each pixel
                int average = round(((float)red + (float)blue + (float)green) / 3);
    
                // Set the calculated value to be the new value of each pixel
                image[i][j].rgbtRed = image[i][j].rgbtBlue = image[i][j].rgbtGreen = average;
            }
        }
        return;
    }
    

    The reflection function should take an image and reflect it horizontally

    // Reflect image horizontally
    void reflect(int height, int width, RGBTRIPLE image[height][width])
    {
        for (int i = 0; i < height; i++)
        {
            // Iterate through the array until you get the mid point
            for (int j = 0; j < (width / 2); j++)
            {
                RGBTRIPLE temp = image[i][j];
    
                image[i][j] = image[i][width - (j + 1)];
                image[i][width - (j + 1)] = temp;
            }
        }
        return;
    }
    

    The blur function takes and image and turns it into a box-blurred version of the same image.

    // 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 sumRed, sumBlue, sumGreen;
                sumRed = sumBlue = sumGreen = 0;
                float counter = 0.00;
    
                //Get the neighbouring pexels
                for (int c = -1; c < 2; c++)
                {
                    for (int r = -1; r < 2; r++)
                    {
                        int currentX = i + c;
                        int currentY = j + r;
    
                        //check for valid neighbouring pexels
                        if (currentX < 0 || currentX > (height - 1) || currentY < 0 || currentY > (width - 1))
                        {
                            continue;
                        }
    
                        //Get the image value
                        sumRed += image[currentX][currentY].rgbtRed;
                        sumGreen += image[currentX][currentY].rgbtGreen;
                        sumBlue += image[currentX][currentY].rgbtBlue;
    
                        counter++;
                    }
    
                    //do the average of neigbhouring pexels
                    temp[i][j].rgbtRed = round(sumRed / counter);
                    temp[i][j].rgbtGreen = round(sumGreen / counter);
                    temp[i][j].rgbtBlue = round(sumBlue / 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;
    }

    The edges function takes an image and highlight the edges between objects, according to the sobel operator.

    // Detect edges
    void edges(int height, int width, RGBTRIPLE image[height][width])
    {
        RGBTRIPLE temp[height][width];
    
        int gx[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
        int gy[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
    
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                float gxRed = 0;
                float gyRed = 0;
                float gxGreen = 0;
                float gyGreen = 0;
                float gxBlue = 0;
                float gyBlue = 0;
    
                for (int col = -1; col < 2; col++)
                {
                    for (int row = -1; row < 2; row++)
                    {
                        if (i + col < 0 || i + col > height - 1)
                        {
                            continue;
                        }
                        if (j + row < 0 || j + row > width - 1)
                        {
                            continue;
                        }
    
                        gxRed += image[i + col][j + row].rgbtRed * gx[col + 1][row + 1];
                        gyRed += image[i + col][j + row].rgbtRed * gy[col + 1][row + 1];
                        gxGreen += image[i + col][j + row].rgbtGreen * gx[col + 1][row + 1];
                        gyGreen += image[i + col][j + row].rgbtGreen * gy[col + 1][row + 1];
                        gxBlue += image[i + col][j + row].rgbtBlue * gx[col + 1][row + 1];
                        gyBlue += image[i + col][j + row].rgbtBlue * gy[col + 1][row + 1];
                    }
                }
    
                int red = round(sqrt(gxRed * gxRed + gyRed * gyRed));
                int green = round(sqrt(gxGreen * gxGreen + gyGreen * gyGreen));
                int blue = round(sqrt(gxBlue * gxBlue + gyBlue * gyBlue));
    
                // Cap at 255
                if (red > 255)
                {
                    red = 255;
                }
                if (green > 255)
                {
                    green = 255;
                }
                if (blue > 255)
                {
                    blue = 255;
                }
    
                // Assign new values to pixels
                temp[i][j].rgbtRed = red;
                temp[i][j].rgbtGreen = green;
                temp[i][j].rgbtBlue = blue;
            }
        }
    
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                image[i][j] = temp[i][j];
            }
        }
    
        return;
    }

    Full solution to cs50 psets 4 filter – more comfortable problem

    #include "helpers.h"
    #include <math.h>
    
    // Convert image to grayscale
    void grayscale(int height, int width, RGBTRIPLE image[height][width])
    {
        // Iterate though each column
        for (int i = 0; i < height; i++)
        {
            // Iterate through each raw of pixel in each column
            for (int j = 0; j < width; j++)
            {
                // Get into 2D array and obtain value of each color
                int red = image[i][j].rgbtRed;
                int blue = image[i][j].rgbtBlue;
                int green = image[i][j].rgbtGreen;
    
                // Calculate the rounded avarage of each pixel
                int average = round(((float)red + (float)blue + (float)green) / 3);
    
                // Set the calculated value to be the new value of each pixel
                image[i][j].rgbtRed = image[i][j].rgbtBlue = image[i][j].rgbtGreen = average;
            }
        }
        return;
    }
    
    // Reflect image horizontally
    void reflect(int height, int width, RGBTRIPLE image[height][width])
    {
        for (int i = 0; i < height; i++)
        {
            // Iterate through the array until you get the mid point
            for (int j = 0; j < (width / 2); j++)
            {
                RGBTRIPLE temp = image[i][j];
    
                image[i][j] = image[i][width - (j + 1)];
                image[i][width - (j + 1)] = temp;
            }
        }
        return;
    }
    
    // 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 sumRed, sumBlue, sumGreen;
                sumRed = sumBlue = sumGreen = 0;
                float counter = 0.00;
    
                //Get the neighbouring pexels
                for (int c = -1; c < 2; c++)
                {
                    for (int r = -1; r < 2; r++)
                    {
                        int currentX = i + c;
                        int currentY = j + r;
    
                        //check for valid neighbouring pexels
                        if (currentX < 0 || currentX > (height - 1) || currentY < 0 || currentY > (width - 1))
                        {
                            continue;
                        }
    
                        //Get the image value
                        sumRed += image[currentX][currentY].rgbtRed;
                        sumGreen += image[currentX][currentY].rgbtGreen;
                        sumBlue += image[currentX][currentY].rgbtBlue;
    
                        counter++;
                    }
    
                    //do the average of neigbhouring pexels
                    temp[i][j].rgbtRed = round(sumRed / counter);
                    temp[i][j].rgbtGreen = round(sumGreen / counter);
                    temp[i][j].rgbtBlue = round(sumBlue / 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;
    }
    
    // Detect edges
    void edges(int height, int width, RGBTRIPLE image[height][width])
    {
        RGBTRIPLE temp[height][width];
    
        int gx[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
        int gy[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
    
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                float gxRed = 0;
                float gyRed = 0;
                float gxGreen = 0;
                float gyGreen = 0;
                float gxBlue = 0;
                float gyBlue = 0;
    
                for (int col = -1; col < 2; col++)
                {
                    for (int row = -1; row < 2; row++)
                    {
                        if (i + col < 0 || i + col > height - 1)
                        {
                            continue;
                        }
                        if (j + row < 0 || j + row > width - 1)
                        {
                            continue;
                        }
    
                        gxRed += image[i + col][j + row].rgbtRed * gx[col + 1][row + 1];
                        gyRed += image[i + col][j + row].rgbtRed * gy[col + 1][row + 1];
                        gxGreen += image[i + col][j + row].rgbtGreen * gx[col + 1][row + 1];
                        gyGreen += image[i + col][j + row].rgbtGreen * gy[col + 1][row + 1];
                        gxBlue += image[i + col][j + row].rgbtBlue * gx[col + 1][row + 1];
                        gyBlue += image[i + col][j + row].rgbtBlue * gy[col + 1][row + 1];
                    }
                }
    
                int red = round(sqrt(gxRed * gxRed + gyRed * gyRed));
                int green = round(sqrt(gxGreen * gxGreen + gyGreen * gyGreen));
                int blue = round(sqrt(gxBlue * gxBlue + gyBlue * gyBlue));
    
                // Cap at 255
                if (red > 255)
                {
                    red = 255;
                }
                if (green > 255)
                {
                    green = 255;
                }
                if (blue > 255)
                {
                    blue = 255;
                }
    
                // Assign new values to pixels
                temp[i][j].rgbtRed = red;
                temp[i][j].rgbtGreen = green;
                temp[i][j].rgbtBlue = blue;
            }
        }
    
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                image[i][j] = temp[i][j];
            }
        }
    
        return;
    }

    The Solution to CS50 Psets 4 Recover Problem (2022)

    For this problem, we have to implement a C program that will recover JPEG images from a forensic images. So we have to write our code in recover.c file. So here is my solution to this problem.

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    
    int main(int argc, char *argv[])
    {
        if (argc != 2)
        {
            printf("Usage: ./recover card.raw\n");
            return 1;
        }
        // Open file for read
        FILE *i = fopen(argv[1], "r");
        //If fail to open input file retun error message "Could not open file"
        if (i == NULL)
        {
            printf("Could not open file");
            return 2;
        }
    
        //declare a variable to unsigned char to store 512 chunks array
        unsigned char buffer[512];
    
        //declare a variable to count image later in the loop
        int c = 0;
    
        //file pointer use to output data gotten from input file
        FILE *o = NULL;
    
        char *f = malloc(8 * sizeof(char));
        // char file[8];
    
        //Read 512 bytes from input file and store on the buffer
        while (fread(buffer, sizeof(char), 512, i))
        {
            //check if bytes are from a JPEG
            if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
            {
                //write jpeg inot file name in form 001.jpg, 002.jpg and so on
                sprintf(f, "%03i.jpg", c);
    
                //open output file for writing
                o = fopen(f, "w");
    
                //count number of images found
                c++;
            }
    
            //Check if output have been used for valid input
            if (o != NULL)
            {
                fwrite(buffer, sizeof(char), 512, o);
            }
        }
    
        free(f);
        fclose(o);
        fclose(i);
    }

    Hope these code solutions help you to solve your problems little bit easier. If it helps consider sharing with your friends that will need these solutions.

    Leave a Comment

    Your email address will not be published. Required fields are marked *

    Scroll to Top