Tag: solutions for psets 4

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

    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.