First... you're using bi.biHeight directly here, but you're forgetting that it is a negative value. I won't say much more... think about that.
bi.biSizeImage = ((bi.biWidth + padding) * bi.biHeight);
Second... I don't think you really understand how fseek() works, so I'll try to explain it to you in simple terms:
Workings of fread() and fseek() (simplified):
Imagine a filename.txt in which you have only one string: "CS50"
Create a buffer and file pointer named fileptr to filename.txt with fopen().
Now.. when you use fread(buffer, 1, 1, fileptr) for the first time, it will read the first byte: 'C'
When you use fread(buffer, 1, 1, fileptr) for the second time, it will read the second byte: 'S'
Now imagine that you want to go BACK and read that 'S' char/byte again, how would you go about it?
You can't use fread() again, because normally, when reading in from a file, the pointer continues in one direction, from the start of the file to the end, that is, the next byte will be read (the char/byte '5', because you've already read the byte 'C' and then the byte 'S');
So to move the pointer/arrow/cursor that is now pointing to '5' as the next byte to be read, you use fseek() and do something like this:
fseek(fileptr, -1, SEEK_CUR);
What will this do? It'll move the cursor/arrow (that was pointing to '5') one byte back (because I used negative 1 as the argument), so now the cursor/arrow that indicates what is the next byte to be read points one byte back... to 'S' again.
You use fread(buffer, 1, 1, fileptr) one more time and it will now read 'S' again.
SEEK_CUR means that you'll move the arrow/cursor away from where it is currently pointing (in my example, it was the byte '5')
SEEK_SET means that you will reset the cursor to the beginning of the file and start counting from there.
In my example, when the cursor was pointing to '5', I could've used fseek(fileptr, 1, SEEK_SET). This would've reset the cursor to the start of the file and jumped one byte forward (passing over 'C'). The cursor now would be pointing at the second byte: 'S'.
To read more about this, go here and see Kareem's great explanation: pset5 copy.c confused in fread