white and brown mug with coffee

I was seriously stuck on pset4 for about 3 months? Well, in reality, I was stuck for a week and then gave up until strangers from the internet sent me really nice messages. I was shocked. The difficulty really put me off and I stopped doing it but getting those messages gave me motivation to continue doing the course and writing it up knowing that it helps others. You guys rule! πŸ₯°

Also… I realised I have been calling pseudocode = SUDOCODE for the past 2 years. Why did no one tell me? I’m cringing so much as I go through all my posts to update the word πŸ˜‚

So….HOLLA HOUSEMATES 🏠…..I’M BACK AGAINN!!

I had no idea where to start so I tried doing the pseudocode for the greyscale filter. Do you see me? I used the right word and not “sudo” anymore πŸ˜‚

Greyscale

According to the video; for each pixel, which is 8 bytes or 1 bit, there are 3 colours, RGB and in order to convert it to greyscale, you need all the values of R, G and B to be the same. Here is what I wrote out.

   // iterate through i to get to each row
   // iterate through j - to get into each byte per row
   // find values of R, G and B
   // find average of R, G and B
   // implemennt back into R, G, B new values.
   // the values to new average

For the filter, you want to find out what each value of R, G and B is per pixel so therefore you must iterate through the first row of the bitmap image.

 for (int i = 0; i < height; i++)
   {

}

Then you iterate again through each individual column in that row to collect the values of R, G, B per bit.

for (int j = 0; j < width; j++) { }

As provided by cs50, we know that to access the pixels in the 2D array we do:

image[i][j].rgbtRed;
image[i][j].rgbtBlue;
image[i][j].rgbtGreen;

Then you added them together divide by 3 to find the average. I decided to convert them all into a new int to use for the multiplication. I kept getting errors here so struggled a bit when I was checking the code as it wasn’t rounding up correctly. A quick google I found if I used float it would retain the decimal value of average then I could round it up after. For some reason it wouldn’t work any otherwise – so if you know a better way PLEASE do let me know!

            // get values of each colour
            int red = image[i][j].rgbtRed;
            int blue = image[i][j].rgbtBlue;
            int green = image[i][j].rgbtGreen;

            // find average
            float average = (round(red) + round(blue) + round(green)) / 3;
            average = round(average);

Then you use this same number to put back into each R,G,B value per pixel of the image. Basically finishing the conversion ^_^

            // implement average back into each colour
            image[i][j].rgbtRed = average;
            image[i][j].rgbtBlue = average;
            image[i][j].rgbtGreen = average;

Then the huge struggle came when I tried to compile. I kept compiling the helpers file and it was giving me mahusive errors like

My step by step walkthrough of pset4 filter challenge from the cs50 edx harvardx course

Another quick search on the cs50 Facebook Group (which btw is a blessing and you MUST join) and StackOverflow I found that you had to compile filter.c.

Then after all this, I used check50 to check the code. I don’t know any other way but it was a pass so HUZZAH! Now onto the next one πŸ™‚

Sepia

So this is the “sepia formula” algorithm. In the video, he explains the output will not be an integer. We need to round the number to the nearest whole number between the range of a 8 bits of memory (256) so the values must be between 0-255. It must not go over 255, therefore, we need to cap it at 255.

  sepiaRed = .393 * originalRed + .769 * originalGreen + .189 * originalBlue
  sepiaGreen = .349 * originalRed + .686 * originalGreen + .168 * originalBlue
  sepiaBlue = .272 * originalRed + .534 * originalGreen + .131 * originalBlue

Here is my pseudocode:

// iterate through i to get to each row
// iterate through j - to get into each byte per row
// find values of R, G and B
// convert each value to the sepia value
// round number sto nearest whole number 
// check whether the value is between 0 - 255
// if value > 255 then make it 255
// input back into R, G, B

So the next bit. I just did lots of guess work. It’s not exactly the most minimalistic code but hey, it worked πŸ˜‚

I basically first took the same code from the greyscale filter: the beginning for loop within for loop and then converting each value of colour to its own integer and copy & pasta’d that.

The main bit I changed was adding the sepia code and trying to round up the number. I don’t know how this worked but I copied I what I did before which was round up the equation total.

int  sepiaRed = round(.393 * red + .769 * green + .189 * blue);
int sepiaGreen = round(.349 * red + .686 * green + .168 * blue);
int  sepiaBlue = round(.272 * red + .534 * green + .131 * blue);

Then I just did simple if and else statements to check through if the values are more than 255. If they were I would equate the corresponding colour = 255.

if (sepiaRed < 256)

{
image[i][j].rgbtRed = sepiaRed;

}
else {

image[i][j].rgbtRed = 255;

}

If it wasn’t more than 255 then I would input that value back into that pixel. And then do that for each colour and then a voila! A quick check50 and it works. Great news and all ready to go to the next step πŸ™‚

It’s now nearly 11pm and the latest I’ve slept ALL WEEK! I’ve literally spent about 8 hours on this lol. I will return tomorrow morning to finish it off.

Reflected

For this task, we are trying to flip the bitmap image horizontally. In order to do so, the video dude explains that we have to take each pixel in each row and reflect it so if it was numbered like 1, 2, 3, 4, 5, 6 the algorithm would reverse it to become 6, 5, 4, 3, 2, 1.

If there are an odd number of pixels the middle pixel stays in it’s place but if there are an even number of pixels every single pixel will switch sides and be on the opposite sides to their original position.

So I guess it’s time for psedocode.

// iterate through row
// iterate through columns
// half width
// swap left hand with direct right-hand values (middle is static if odd number)
// re-insert back into location

Something like this should work. After a quick Google I found how to reverse an array on StackOverflow.

// do not use - copied from StackOverflow as reference.

void ReverseArray(int arr[], int size)
{
    for (int i = 0; i < size/2; ++i)
    {
        int temp = arr[i];
        arr[i] = arr[size - 1 - i];
        arr[size - 1 - i] = temp;
    }
}

So I ended up writing pseudocode from the above to help convert into my own.

First I wanted to iterate through only half of the full width of the image because as mentioned earlier we are only swapping the left hand side of pixels with the right. If we iterate through the full width it would mean swapping them all…back to the same position.

Therefor we do width / 2 to half the length. In the video he mentions if it’s an even number we can directly halve with no remainders but if it’s an odd it would become a decimal.

Even number
6 / 2 = 3

Odd number
7 / 2 = 3.5 

Good thing with integars is that if the decimal is .5 or below it rounds DOWN. So 7 / 2 would become 3. Which ignores the middle value in an array. You don’t need to swap that anyways.

After you interate through each pixel you need to create a temporary value where you put the image[i][j] in. Then you would make the new image[i][j] equate the same array that picks j away from the full width. For example…

      arr[j] = arr[width - 1 - j];
This means fullwidth would be - j as you are you trying to swap the j value with same value j away from width. 

array location: 0 1 2 3 4 5
value in array: 7 2 5 7 3 1

As you can see if j was array[1] then you would want to swap it with array[4] which is 5 – j = 5 – 1. 5 being “max width”

You do width – 1 – j as in an array it starts from 0 so you end up with having a length of 6 even though the last value in the array is array[5]

Which ended up with this error.

 error: assigning to 'int' from incompatible type

I realised as I was calling int instead of the RGBTRIPLE struct. It wouldn’t let me do int = RGBTRIPLE. So your new value needs to be called as an RGBTRIPLE struct.

Wow, it’s 7am on Sunday I honestly spend all day yesterday confused on just this section and now it looks so simple after you complete it FML.

Blur

Just a word of note. I was stuck on Blur for almost 5 months. I gave up but you guys proper steered me on. Thank you. I love you all πŸ’–

blur pset4 = #ihatemylife

I’m going to re-do the code in another method. Let’s get down to pseudocode.

As we all learn in the short videos that in order to blur an image we have to iterate through each individual pixel (which each have R,G and B values) and then check the surrounding pixels. Then we add them all up and divide by total pixels; 3×3 being the max size.

If the pixel is in any of the corners we do an average of 2×2 surrounding that pixel. If it’s attached to the top/bottom we do an average of 6×2

1. Duplicate entire image so you can blur the new values
(if you don't do this you will re-use the blurred pixels surrounding new unblurred pixels so it messes up the image.
2. Iterate through the 2D array 
3. We need to check whether there are pixels surrounding your pixel. Let's pretend it's a middle pixel in a 3x3 format
4. Check rows
5. check corners
6. check columns
7. add individual r,g and b values and divide by total pixels = average values
8. spit out new image that's blurred. 

Okay, first. duplicate entire image so you can blur the new values. You want to iterate through both the row and columns to recreate the image so that when you convert it you’re not replacing original pixels. (if you do that then it will blur the already blurred pixels).

 for (i = 0; i < height; i++)

    {

        for (j = 0; j < width; j++)

        {


            // duplicate image to a new image. as when you blur 1 original pixel it messses with next one


            newImage[i][j] = image[i][j];
        }

    }

So, I tried many methods and they just wouldn’t work and finally after months of scratching my eye out, I reached out to someone on twitter who told me his pseudocode. It helped IMMENSELY. I was going check 1 above, to the sides, below and then corners and then if they exist tally it up and divide it by total to get the average.

Check top right corner

    if (i - 1 >= 0 && j + 1 < width)

            {
                // top right

                totalRed += image[i - 1][j + 1].rgbtRed;
                totalBlue += image[i - 1][j + 1].rgbtBlue;
                totalGreen += image[i - 1][j + 1].rgbtGreen;
                totalCounter++;
            }

Check right

     if (j + 1 < width)

            {

                // right

                totalRed += image[i][j + 1].rgbtRed;
                totalBlue += image[i][j + 1].rgbtBlue;
                totalGreen += image[i][j + 1].rgbtGreen;
                totalCounter++;
            }

Check bottom

    if (i + 1 < height)

            {

                // bottom

                totalRed += image[i + 1][j].rgbtRed;
                totalBlue += image[i + 1][j].rgbtBlue;
                totalGreen += image[i + 1][j].rgbtGreen;
                totalCounter++;
            }

etc etc. You check each side, then the corners and then you add the middle pixel too

            // middle pixel
            totalRed += image[i][j].rgbtRed;
            totalBlue += image[i][j].rgbtBlue;
            totalGreen += image[i][j].rgbtGreen;
            totalCounter++;

After that you should be tallying up each colour and averaging them (to get the blur)

         // calculate average and repace r,g,b values

            newImage[i][j].rgbtRed = round(totalRed / totalCounter);
            newImage[i][j].rgbtBlue = round(totalBlue / totalCounter);
            newImage[i][j].rgbtGreen = round(totalGreen / totalCounter);

Then I started getting compilation errors saying it was too large or over the 255 max value RGB can be. So I added this if statement to say if it does go over 255 value it will equate to it.

 if (newImage[i][j].rgbtRed > 255)

            {
                newImage[i][j].rgbtRed = 255;
            }
            if (newImage[i][j].rgbtBlue > 255)

            {
                newImage[i][j].rgbtBlue = 255;
            }
            if (newImage[i][j].rgbtGreen > 255)
            {
                newImage[i][j].rgbtGreen = 255;
            }

        }

As the blur was done to a completely new image. Now the new image has been created you have to iterate it back and replace the original image. with the new one! A VOILA!!!

  for (int a = 0; a < height; a++)
    {
        for (int b = 0; b < width; b++)
        {
            image[a][b].rgbtBlue = newImage[a][b].rgbtBlue;
            image[a][b].rgbtRed = newImage[a][b].rgbtRed;
            image[a][b].rgbtGreen = newImage[a][b].rgbtGreen;
        }
    }

Oh my gosh. I can’t believe it’s finally done. *pats back*

Now, onto pset5. It’s only taking me 2 YEARS to get through cs50… to those who completed it in months I salute you!

Thanks for your patience everyone πŸ™‚

If you found this post useful please support House Ninety Two and
Buy Me a Coffee at ko-fi.com