CS50 Problem Set 4

CS50 Problem Set 4

King Hua Lv2

CS50 Problem Set 4

Here’s my answer for the CS50 Problem Set 4. Hope that will help you a bit.

Problem 1: Volume

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 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[44];
fread(&header, 44, 1, input);
fwrite(&header, 44, 1, output);

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

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

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

Problem 2: Filter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "helpers.h"
#include <math.h>

// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
int avg = 0;

for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
avg = (int) round((image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue) /
3.0);

image[i][j].rgbtRed = avg;
image[i][j].rgbtGreen = avg;
image[i][j].rgbtBlue = avg;
}
}
return;
}

// 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 sepiaRed = (int) round(.393 * image[i][j].rgbtRed + .769 * image[i][j].rgbtGreen +
.189 * image[i][j].rgbtBlue);
int sepiaGreen = (int) round(.349 * image[i][j].rgbtRed + .686 * image[i][j].rgbtGreen +
.168 * image[i][j].rgbtBlue);
int sepiaBlue = (int) round(.272 * image[i][j].rgbtRed + .534 * image[i][j].rgbtGreen +
.131 * image[i][j].rgbtBlue);
// sepiaRed = .393 * originalRed + .769 * originalGreen + .189 * originalBlue
// sepiaGreen = .349 * originalRed + .686 * originalGreen + .168 * originalBlue
// sepiaBlue = .272 * originalRed + .534 * originalGreen + .131 * originalBlue

// Make sure that if the value of sepiaRed, sepiaGreen and sepiaBlue exceed 255, their
// value will be capped at 255
if (sepiaRed > 255)
{
sepiaRed = 255;
}
if (sepiaGreen > 255)
{
sepiaGreen = 255;
}
if (sepiaBlue > 255)
{
sepiaBlue = 255;
}

image[i][j].rgbtRed = sepiaRed;
image[i][j].rgbtGreen = sepiaGreen;
image[i][j].rgbtBlue = sepiaBlue;
}
}
return;
}

// Reflect image horizontally
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
int temp_width = 0;
RGBTRIPLE temp[height][width];

if (width % 2 == 0)
{
temp_width = width / 2;
}
else
{
temp_width = (width + 1) / 2;
}
for (int i = 0; i < height; i++)
{
for (int j = 0; j < temp_width; j++)
{
// Swap pixels
temp[i][j] = image[i][j];
image[i][j] = image[i][width - 1 - j];
image[i][width - 1 - j] = temp[i][j];
}
}
return;
}

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
// Create a copy of image
RGBTRIPLE copy[height][width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int tempRed = 0, tempGreen = 0, tempBlue = 0;
float pixel_count = 0;
copy[i][j] = image[i][j];

// get the average of the pixel RGB values
for (int m = i - 1; m <= i + 1; m++)
{
for (int n = j - 1; n <= j + 1; n++)
{
if (m >= 0 && m < height && n >= 0 &&
n < width) // avoiding the pixels that cross the edge
{
tempRed += image[m][n].rgbtRed;
tempGreen += image[m][n].rgbtGreen;
tempBlue += image[m][n].rgbtBlue;

pixel_count += 1;
}
}
}
copy[i][j].rgbtRed = round(tempRed / pixel_count);
copy[i][j].rgbtGreen = round(tempGreen / pixel_count);
copy[i][j].rgbtBlue = round(tempBlue / pixel_count);
}
}

// give the value of copy[i][j] back to image[i][j]
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
image[i][j] = copy[i][j];
}
}
return;
}

Problem 3: Recover

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
// Accept a single command-line argument
if (argc != 2)
{
printf("Usage: ./recover FILE\n");
return 1;
}

// Open the memory card
FILE *card = fopen(argv[1], "r");

// Create a buffer for a block of data
uint8_t buffer[512];
int counter = 0;
int found_image = 1;
FILE *img;
char filename[8];
// While there's still data left to read from the memory card
while (fread(buffer, 1, 512, card) == 512)
{
// Create JPEGs from the data
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff &&
(buffer[3] & 0xf0) == 0xe0)
{
found_image = 0;
}

if (found_image == 0)
{
if (counter != 0)
{
fclose(img);
} // close the previous file and start a new file to write (except the first file)

sprintf(filename, "%03i.jpg", counter);
img = fopen(filename, "w");
fwrite(buffer, 1, 512, img);
counter += 1;
found_image = 1;
}
else if (counter != 0)
// the block does not contain the signature of jpg, so it will be continuously written into
// the previously opened file if the first block does not contain the signature, it won't be
// written to the image
{
fwrite(buffer, 1, 512, img);
}
}

// there's nothing to write, so close all the files
fclose(img);
fclose(card);
}
  • Title: CS50 Problem Set 4
  • Author: King Hua
  • Created at : 2026-02-16 20:34:03
  • Updated at : 2026-02-16 21:02:15
  • Link: https://kinghua0629.github.io/2026/02/16/CS50-Problem-Set-4/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments