Key Points
- Hexadecimal
- Pointer:
*
operator,&
operator - Dynamic memory allocation:
malloc()
,free()
- string: null terminating character
\0
- Compare & copy string
valgrind
: check memory leakswap
function- Memory layout: heap, stack
- Call stacks
- File pointer: open, read, write, and close
- JPEG & BMP
Assignment 1: Filter (less)
Spec:
Complete functions
grayscale
,sepia
,reflect
, andblur
that apply filters to BMPs.
Functions grayscale
and sepia
simply iterate through each pixel and recalculate its RBG values. Function reflect
swaps the RGB values of each pixel with the pixel on the mirror side of it. These 3 functions are quite easy, so I don’t show them here.
Function blur
is more complicated. It computes the new value for a pixel by taking the average RGB values of the old colour values of all 9 pixels (4 or 6 pixels if the original pixel is on the edge) that form a grid around the original pixel.
To compute the new value, firstly, I need to know where the original pixel is, how many pixels to be averaged and what pixels to be averaged.
I use nested for-loops to iterate through each pixel in the 2-dimensional array. rowS, rowE, colS, colE
represent the starting and ending row index and column index that form a grid centring on the current pixel. Then I pass those values alongside the original image, the height and width of the original image, and the index of the current pixel to a function get_blur_pixel
to compute the new value.
Assignment 2: Recover
Background:
JPEGs have “signatures” patterns of bytes that can distinguish them from other file formats. The first three bytes of JPEGs are 0xff 0xd8 0xff
, and the fourth byte starts with 0xe
. Digital cameras tend to store photographs contiguously on memory cards, whereby each photo is stored immediately after the previously taken photo. Those photos stored on memory cards in units of 512 Bytes.
Spec:
Implement a program called
recover
that recovers JPEGs from a forensic image.
It took me a while to figure out how to read the next block. It turns out fread()
can do that for me.
fread
always reads from the file's current read pointer and advances that same pointer, so you can read a file in sequential chunks without having to explicitly seek.
References:
fread()
unit8_t