Skip to content

Instantly share code, notes, and snippets.

@teeschorle
Last active January 22, 2021 04:19
Show Gist options
  • Save teeschorle/3e01a70bd0df2c3261e70e2e061224c7 to your computer and use it in GitHub Desktop.
Save teeschorle/3e01a70bd0df2c3261e70e2e061224c7 to your computer and use it in GitHub Desktop.
CS50 Problem Set 4 (edX 2020) - Helpers (to be used in combination with Filters.c provided by CS50)
//CS50 Problem Set 4 (edx 2020): Filter (more comfortable)
//Author: teeschorle
#include "helpers.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
double average;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
average = round((image[i][j].rgbtBlue + image[i][j].rgbtGreen + image[i][j].rgbtRed) / 3.0); //3.0 instead of 3 in order to yield a float division result (instead of an int which is just cut off)
image[i][j].rgbtBlue = average;
image[i][j].rgbtGreen = average;
image[i][j].rgbtRed = average;
}
}
return;
}
// Reflect image horizontally
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE(*imagecopy)[width] = calloc(height, width * sizeof(RGBTRIPLE));
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
imagecopy[i][j].rgbtBlue = image[i][width - j - 1].rgbtBlue;
imagecopy[i][j].rgbtGreen = image[i][width - j - 1].rgbtGreen;
imagecopy[i][j].rgbtRed = image[i][width - j - 1].rgbtRed;
}
for (int j = 0; j < width; j++)
{
image[i][j].rgbtBlue = imagecopy[i][j].rgbtBlue;
image[i][j].rgbtGreen = imagecopy[i][j].rgbtGreen;
image[i][j].rgbtRed = imagecopy[i][j].rgbtRed;
}
}
free(imagecopy);
return;
}
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE(*imagecopy)[width] = calloc(height, width * sizeof(RGBTRIPLE));
for (int i = 1; i < height - 1; i++) //1 and height - 1 are due to different treatment of the edges
{
for (int j = 1; j < width - 1; j++) //1 and height - 1 are due to different treatment of the edges
{
imagecopy[i][j].rgbtBlue = round((image[i - 1][j - 1].rgbtBlue + image[i - 1][j].rgbtBlue + image[i - 1][j + 1].rgbtBlue + image[i][j - 1].rgbtBlue + image[i][j].rgbtBlue + image[i][j + 1].rgbtBlue + image[i + 1][j - 1].rgbtBlue + image[i + 1][j].rgbtBlue + image[i + 1][j + 1].rgbtBlue) / 9.0);
imagecopy[i][j].rgbtGreen = round((image[i - 1][j - 1].rgbtGreen + image[i - 1][j].rgbtGreen + image[i - 1][j + 1].rgbtGreen + image[i][j - 1].rgbtGreen + image[i][j].rgbtGreen + image[i][j + 1].rgbtGreen + image[i + 1][j - 1].rgbtGreen + image[i + 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen) / 9.0);
imagecopy[i][j].rgbtRed = round((image[i - 1][j - 1].rgbtRed + image[i - 1][j].rgbtRed + image[i - 1][j + 1].rgbtRed + image[i][j - 1].rgbtRed + image[i][j].rgbtRed + image[i][j + 1].rgbtRed + image[i + 1][j - 1].rgbtRed + image[i + 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed) / 9.0);
}
}
//first and last line
for (int j = 1; j < width - 1; j++) //corners treated separately
{
imagecopy[0][j].rgbtBlue = round((image[0][j - 1].rgbtBlue + image[0][j].rgbtBlue + image[0][j + 1].rgbtBlue + image[0 + 1][j - 1].rgbtBlue + image[0 + 1][j].rgbtBlue + image[0 + 1][j + 1].rgbtBlue) / 6.0);
imagecopy[0][j].rgbtGreen = round((image[0][j - 1].rgbtGreen + image[0][j].rgbtGreen + image[0][j + 1].rgbtGreen + image[0 + 1][j - 1].rgbtGreen + image[0 + 1][j].rgbtGreen + image[0 + 1][j + 1].rgbtGreen) / 6.0);
imagecopy[0][j].rgbtRed = round((image[0][j - 1].rgbtRed + image[0][j].rgbtRed + image[0][j + 1].rgbtRed + image[0 + 1][j - 1].rgbtRed + image[0 + 1][j].rgbtRed + image[0 + 1][j + 1].rgbtRed) / 6.0);
imagecopy[height - 1][j].rgbtBlue = round((image[height - 1 - 1][j - 1].rgbtBlue + image[height - 1 - 1][j].rgbtBlue + image[height - 1 - 1][j + 1].rgbtBlue + image[height - 1][j - 1].rgbtBlue + image[height - 1][j].rgbtBlue + image[height - 1][j + 1].rgbtBlue) / 6.0);
imagecopy[height - 1][j].rgbtGreen = round((image[height - 1 - 1][j - 1].rgbtGreen + image[height - 1 - 1][j].rgbtGreen + image[height - 1 - 1][j + 1].rgbtGreen + image[height - 1][j - 1].rgbtGreen + image[height - 1][j].rgbtGreen + image[height - 1][j + 1].rgbtGreen) / 6.0);
imagecopy[height - 1][j].rgbtRed = round((image[height - 1 - 1][j - 1].rgbtRed + image[height - 1 - 1][j].rgbtRed + image[height - 1 - 1][j + 1].rgbtRed + image[height - 1][j - 1].rgbtRed + image[height - 1][j].rgbtRed + image[height - 1][j + 1].rgbtRed) / 6.0);
}
//first and last column
for (int i = 1; i < height - 1; i++)
{
imagecopy[i][0].rgbtBlue = round((image[i - 1][0].rgbtBlue + image[i - 1][1].rgbtBlue + image[i][0].rgbtBlue + image[i][1].rgbtBlue + image[i + 1][0].rgbtBlue + image[i + 1][1].rgbtBlue) / 6.0);
imagecopy[i][0].rgbtGreen = round((image[i - 1][0].rgbtGreen + image[i - 1][1].rgbtGreen + image[i][0].rgbtGreen + image[i][1].rgbtGreen + image[i + 1][0].rgbtGreen + image[i + 1][1].rgbtGreen) / 6.0);
imagecopy[i][0].rgbtRed = round((image[i - 1][0].rgbtRed + image[i - 1][1].rgbtRed + image[i][0].rgbtRed + image[i][1].rgbtRed + image[i + 1][0].rgbtRed + image[i + 1][1].rgbtRed) / 6.0);
imagecopy[i][width - 1].rgbtBlue = round((image[i - 1][width - 2].rgbtBlue + image[i - 1][width - 1].rgbtBlue + image[i][width - 2].rgbtBlue + image[i][width - 1].rgbtBlue + image[i + 1][width - 2].rgbtBlue + image[i + 1][width - 1].rgbtBlue) / 6.0);
imagecopy[i][width - 1].rgbtGreen = round((image[i - 1][width - 2].rgbtGreen + image[i - 1][width - 1].rgbtGreen + image[i][width - 2].rgbtGreen + image[i][width - 1].rgbtGreen + image[i + 1][width - 2].rgbtGreen + image[i + 1][width - 1].rgbtGreen) / 6.0);
imagecopy[i][width - 1].rgbtRed = round((image[i - 1][width - 2].rgbtRed + image[i - 1][width - 1].rgbtRed + image[i][width - 2].rgbtRed + image[i][width - 1].rgbtRed + image[i + 1][width - 2].rgbtRed + image[i + 1][width - 1].rgbtRed) / 6.0);
}
//corners
imagecopy[0][0].rgbtBlue = round((image[0][0].rgbtBlue + image[0][1].rgbtBlue + image[1][0].rgbtBlue + image[1][1].rgbtBlue) / 4.0);
imagecopy[0][0].rgbtGreen = round((image[0][0].rgbtGreen + image[0][1].rgbtGreen + image[1][0].rgbtGreen + image[1][1].rgbtGreen) / 4.0);
imagecopy[0][0].rgbtRed = round((image[0][0].rgbtRed + image[0][1].rgbtRed + image[1][0].rgbtRed + image[1][1].rgbtRed) / 4.0);
imagecopy[0][width - 1].rgbtBlue = round((image[0][width - 2].rgbtBlue + image[0][width - 1].rgbtBlue + image[1][width - 2].rgbtBlue + image[1][width - 1].rgbtBlue) / 4.0);
imagecopy[0][width - 1].rgbtGreen = round((image[0][width - 2].rgbtGreen + image[0][width - 1].rgbtGreen + image[1][width - 2].rgbtGreen + image[1][width - 1].rgbtGreen) / 4.0);
imagecopy[0][width - 1].rgbtRed = round((image[0][width - 2].rgbtRed + image[0][width - 1].rgbtRed + image[1][width - 2].rgbtRed + image[1][width - 1].rgbtRed) / 4.0);
imagecopy[height - 1][0].rgbtBlue = round((image[height - 2][0].rgbtBlue + image[height - 2][1].rgbtBlue + image[height - 1][0].rgbtBlue + image[height - 1][1].rgbtBlue) / 4.0);
imagecopy[height - 1][0].rgbtGreen = round((image[height - 2][0].rgbtGreen + image[height - 2][1].rgbtGreen + image[height - 1][0].rgbtGreen + image[height - 1][1].rgbtGreen) / 4.0);
imagecopy[height - 1][0].rgbtRed = round((image[height - 2][0].rgbtRed + image[height - 2][1].rgbtRed + image[height - 1][0].rgbtRed + image[height - 1][1].rgbtRed) / 4.0);
imagecopy[height - 1][width - 1].rgbtBlue = round((image[height - 2][width - 2].rgbtBlue + image[height - 2][width - 1].rgbtBlue + image[height - 1][width - 2].rgbtBlue + image[height - 1][width - 1].rgbtBlue) / 4.0);
imagecopy[height - 1][width - 1].rgbtGreen = round((image[height - 2][width - 2].rgbtGreen + image[height - 2][width - 1].rgbtGreen + image[height - 1][width - 2].rgbtGreen + image[height - 1][width - 1].rgbtGreen) / 4.0);
imagecopy[height - 1][width - 1].rgbtRed = round((image[height - 2][width - 2].rgbtRed + image[height - 2][width - 1].rgbtRed + image[height - 1][width - 2].rgbtRed + image[height - 1][width - 1].rgbtRed) / 4.0);
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
image[i][j].rgbtBlue = imagecopy[i][j].rgbtBlue;
image[i][j].rgbtGreen = imagecopy[i][j].rgbtGreen;
image[i][j].rgbtRed = imagecopy[i][j].rgbtRed;
}
}
free(imagecopy);
return;
}
// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
// create framedimage with a 1-pixel black border for corner and border treatment
RGBTRIPLE(*framedimage)[width + 2] = calloc(height + 2, (width + 2) * sizeof(RGBTRIPLE));
// black horizontal borders
for (int i = 0; i < width + 2; i++)
{
framedimage[0][i].rgbtBlue = 0;
framedimage[0][i].rgbtGreen = 0;
framedimage[0][i].rgbtRed = 0;
framedimage[height + 1][i].rgbtBlue = 0;
framedimage[height + 1][i].rgbtGreen = 0;
framedimage[height + 1][i].rgbtRed = 0;
}
// black vertical borders
for (int i = 0; i < height + 2; i++)
{
framedimage[i][0].rgbtBlue = 0;
framedimage[i][0].rgbtGreen = 0;
framedimage[i][0].rgbtRed = 0;
framedimage[0][width + 1].rgbtBlue = 0;
framedimage[0][width + 1].rgbtGreen = 0;
framedimage[0][width + 1].rgbtRed = 0;
}
// copy image to rest of framedimage
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
framedimage[i + 1][j + 1].rgbtBlue = image[i][j].rgbtBlue;
framedimage[i + 1][j + 1].rgbtGreen = image[i][j].rgbtGreen;
framedimage[i + 1][j + 1].rgbtRed = image[i][j].rgbtRed;
}
}
// allocate memory space for imagecopy (same size as framedimage)
RGBTRIPLE(*imagecopy)[width + 2] = calloc(height + 2, (width + 2) * sizeof(RGBTRIPLE));
// create temp variables for pixel channel values
int blue = 0;
int green = 0;
int red = 0;
for (int i = 1; i < height + 1; i++) //index from 1 to height + 1 in order to filter the whole original image within the 1-pixel frame
{
for (int j = 1; j < width + 1; j++) //see above
{
blue = round(pow(pow(gx(i, j, "blue", height, width, framedimage),2) + pow(gy(i, j, "blue", height, width, framedimage),2), 0.5));
green = round(pow(pow(gx(i, j, "green", height, width, framedimage),2) + pow(gy(i, j, "green", height, width, framedimage),2), 0.5));
red = round(pow(pow(gx(i, j, "red", height, width, framedimage),2) + pow(gy(i, j, "red", height, width, framedimage),2), 0.5));
// cap values at 255
if (blue > 255)
{
blue = 255;
}
if (green > 255)
{
green = 255;
}
if (red > 255)
{
red = 255;
}
imagecopy[i][j].rgbtBlue = blue;
imagecopy[i][j].rgbtGreen = green;
imagecopy[i][j].rgbtRed = red;
}
}
// copy imagecopy back to target image (careful: imagecopy is larger than target image => cut off 1-pixel edge)
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
image[i][j].rgbtBlue = imagecopy[i + 1][j + 1].rgbtBlue;
image[i][j].rgbtGreen = imagecopy[i + 1][j + 1].rgbtGreen;
image[i][j].rgbtRed = imagecopy[i + 1][j + 1].rgbtRed;
}
}
free(imagecopy);
free(framedimage);
return;
}
int gx(int i, int j, char *channel, int height, int width, RGBTRIPLE image[height + 2][width + 2])
{
int g_x = 0;
if(strcmp(channel, "blue") == 0)
{
g_x = (image[i - 1][j + 1].rgbtBlue + 2 * image[i][j + 1].rgbtBlue + image[i + 1][j + 1].rgbtBlue) - (image[i - 1][j - 1].rgbtBlue + 2 * image[i][j - 1].rgbtBlue + image[i + 1][j - 1].rgbtBlue);
return g_x;
}
else if (strcmp(channel, "green") == 0)
{
g_x = (image[i - 1][j + 1].rgbtGreen + 2 * image[i][j + 1].rgbtGreen + image[i + 1][j + 1].rgbtGreen) - (image[i - 1][j - 1].rgbtGreen + 2 * image[i][j - 1].rgbtGreen + image[i + 1][j - 1].rgbtGreen);
return g_x;
}
else if (strcmp(channel, "red") == 0)
{
g_x = (image[i - 1][j + 1].rgbtRed + 2 * image[i][j + 1].rgbtRed + image[i + 1][j + 1].rgbtRed) - (image[i - 1][j - 1].rgbtRed + 2 * image[i][j - 1].rgbtRed + image[i + 1][j - 1].rgbtRed);
return g_x;
}
else
{
printf("colour not found");
return 0;
}
}
int gy(int i, int j, char *channel, int height, int width, RGBTRIPLE image[height + 2][width + 2])
{
int g_y = 0;
if(strcmp(channel, "blue") == 0)
{
g_y = (image[i + 1][j - 1].rgbtBlue + 2 * image[i + 1][j].rgbtBlue + image[i + 1][j + 1].rgbtBlue) - (image[i - 1][j - 1].rgbtBlue + 2 * image[i - 1][j].rgbtBlue + image[i - 1][j + 1].rgbtBlue);
return g_y;
}
else if (strcmp(channel, "green") == 0)
{
g_y = (image[i + 1][j - 1].rgbtGreen + 2 * image[i + 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen) - (image[i - 1][j - 1].rgbtGreen + 2 * image[i - 1][j].rgbtGreen + image[i - 1][j + 1].rgbtGreen);
return g_y;
}
else if (strcmp(channel, "red") == 0)
{
g_y = (image[i + 1][j - 1].rgbtRed + 2 * image[i + 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed) - (image[i - 1][j - 1].rgbtRed + 2 * image[i - 1][j].rgbtRed + image[i - 1][j + 1].rgbtRed);
return g_y;
}
else
{
printf("colour not found");
return 0;
}
}
@Idong2Archie
Copy link

Idong2Archie commented Jan 22, 2021

Thanks for your walk though. Please can you explain the #include "helper.h" line?
I have filter.c:1:10: fatal error: 'helpers.h' file not found
#include "helpers.h"

when i tried compiling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment