[CS50] 05-3 Problem Set

5 minute read

Published:

In this post, the solution for the problem set of the fifth lecture of CS50 is summarized.

Problem Set

volume

You may refer to https://cs50.harvard.edu/x/2024/psets/4/volume/.

Answer

// Modifies the volume of an audio file

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

// Number of bytes in .wav header
const int HEADER_SIZE = 44;

int main(int argc, char *argv[])
{
    // Check command-line arguments
    if (argc != 4)
    {
        printf("Usage: ./volume input.wav output.wav factor\n");
        return 1;
    }

    // Open files and determine scaling factor
    FILE *input = fopen(argv[1], "r");
    if (input == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    FILE *output = fopen(argv[2], "w");
    if (output == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    float factor = atof(argv[3]);

    // TODO: Copy header from input file to output file
    uint8_t header[HEADER_SIZE];
    fread(header, sizeof(uint8_t), HEADER_SIZE, input);
    fwrite(header, sizeof(uint8_t), HEADER_SIZE, output);

    // TODO: Read samples from input file and write updated data to output file
    int16_t sample;

    while (fread(&sample, sizeof(int16_t), 1, input)){
        sample *= factor;
        fwrite(&sample, sizeof(int16_t), 1, output);
    }

    // Close files
    fclose(input);
    fclose(output);
}

filter-more

You may refer to https://cs50.harvard.edu/x/2024/psets/4/filter/more/.

Answer

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

// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i++){
        for (int j = 0; j < width; j++){
            int mean = round((image[i][j].rgbtBlue + image[i][j].rgbtGreen + image[i][j].rgbtRed) / (float) 3);
            image[i][j].rgbtBlue = image[i][j].rgbtGreen = image[i][j].rgbtRed = mean;
        }
    }
    return;
}

// Reflect image horizontally
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
     for (int i = 0; i < height; i++){
        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])
{   int dx[3] = {0, -1, 1};
    int dy[3] = {0, -1, 1};
    RGBTRIPLE temp_image[height][width];

    for (int i = 0; i < height; i++){
        for (int j = 0; j < width; j++){
            int validCnt = 0;
            int blurRed = 0;
            int blurGreen = 0;
            int blurBlue = 0;

            for (int x = 0; x < 3; x++){
                for (int y = 0; y < 3; y++){
                    if (i + dy[y] >= 0 && i +dy[y] < height && j + dx[x] >= 0 && j + dx[x] < width){
                        blurRed += image[i + dy[y]][j + dx[x]].rgbtRed;
                        blurGreen += image[i + dy[y]][j + dx[x]].rgbtGreen;
                        blurBlue += image[i + dy[y]][j + dx[x]].rgbtBlue;
                        validCnt++;
                    }
                }
            }

            blurRed = round(blurRed / (float) validCnt);
            blurGreen = round(blurGreen / (float) validCnt);
            blurBlue = round(blurBlue / (float) validCnt);
            temp_image[i][j].rgbtRed = blurRed;
            temp_image[i][j].rgbtGreen = blurGreen;
            temp_image[i][j].rgbtBlue = blurBlue;
        }
    }

    for (int i = 0; i < height; i++){
        for (int j = 0; j < width; j++){
            image[i][j] = temp_image[i][j];
        }
    }
    return;
}

// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
    int dx[3] = {-1, 0, 1};
    int dy[3] = {-1, 0, 1};
    int gx_kernel[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1 , 0, 1}};
    int gy_kernel[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1 , 2, 1}};
    RGBTRIPLE temp_image[height][width];

    for (int i = 0; i < height; i++){
        for (int j = 0; j < width; j++){
            int gxRed, gxGreen, gxBlue;
            int gyRed, gyGreen, gyBlue;
            gxRed = gxGreen = gxBlue = gyRed = gyGreen = gyBlue = 0;


            for (int x = 0; x < 3; x++){
                for (int y = 0; y < 3; y++){
                    if (i + dy[y] >= 0 && i +dy[y] < height && j + dx[x] >= 0 && j + dx[x] < width){
                        gxRed += image[i + dy[y]][j + dx[x]].rgbtRed * gx_kernel[y][x];
                        gxGreen += image[i + dy[y]][j + dx[x]].rgbtGreen * gx_kernel[y][x];
                        gxBlue += image[i + dy[y]][j + dx[x]].rgbtBlue * gx_kernel[y][x];
                        gyRed += image[i + dy[y]][j + dx[x]].rgbtRed * gy_kernel[y][x];
                        gyGreen += image[i + dy[y]][j + dx[x]].rgbtGreen * gy_kernel[y][x];
                        gyBlue += image[i + dy[y]][j + dx[x]].rgbtBlue * gy_kernel[y][x];
                    }
                }
            }

            int edgeRed = round(sqrt(pow(gxRed, 2) + pow(gyRed, 2)));
            int edgeGreen = round(sqrt(pow(gxGreen, 2) + pow(gyGreen, 2)));
            int edgeBlue = round(sqrt(pow(gxBlue, 2) + pow(gyBlue, 2)));

            temp_image[i][j].rgbtRed = (edgeRed > 255) ? 255 : edgeRed;
            temp_image[i][j].rgbtGreen = (edgeGreen > 255) ? 255 : edgeGreen;
            temp_image[i][j].rgbtBlue = (edgeBlue > 255) ? 255 : edgeBlue;
        }
    }

    for (int i = 0; i < height; i++){
        for (int j = 0; j < width; j++){
            image[i][j] = temp_image[i][j];
        }
    }
    return;
}

recover

You may refer to https://cs50.harvard.edu/x/2024/psets/4/recover/.

Answer

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int argc, char *argv[])
{
    if (argc != 2){
        printf("usage: ./recover filename\n");
        return 1;
    }

    FILE *memCard = fopen("card.raw", "r");
    uint8_t header[512];
    int fileCnt = 0;

    if (memCard == NULL){
        printf("Could not open file.\n");
        return 1;
    }

    char filename[8];
    FILE *img = NULL;
    while (fread(header, 1, 512, memCard) == 512){
        if (header[0] == 0xff && header[1] == 0xd8 && header[2] == 0xff && (header[3] & 0xf0) == 0xe0){
            if (fileCnt == 0){
                //filename = malloc(8);
                sprintf(filename, "%03i.jpg", fileCnt);
                img = fopen(filename, "w");

                fwrite(header, 1, 512, img);

                fileCnt++;
            }
            else{
                fclose(img);
                sprintf(filename, "%03i.jpg", fileCnt);
                img = fopen(filename, "w");
                fwrite(header, 1, 512, img);

                fileCnt++;
            }
        }
        else{
            if (fileCnt == 0){
                continue;
            }
            fwrite(header, 1, 512, img);
        }

    }
    fclose(img);
    fclose(memCard);
    //free(filename);
    return 0;
}

/*pseudo
open memory card
while fread < 512:
    if jpeg start:
        if first:
            write
        else:
            close
            write
    else:
        write
close
*/

Leave a Comment