what is the purpose of even using Fseek() in pset 4 anyhow? I must be missing something
Say we're looking at the original copy.c function.
Basically, this is what I understand what's happening:
What I understand so far:
CONCEPTS
- A bitmap file (.bmp file). A .png is just a compressed version of a bmp that is also lossless. https://i.sstatic.net/od4E4.png
- This .bmp file has 54 bytes allocated in the bitmapheader. 14 bytes towards bitmapfileheader BF + 40 bytes for bitmapinfoheader BI.
- We can see these values in bmp.h . https://i.sstatic.net/gk4Yy.png. Each of those items, bfType, biSize, etc have different byte sizes allocated to them (DWORD, LONG) etc. Wikipedia has a table for these values https://i.sstatic.net/OkAUJ.png
- We're using a typedef and struct
BITMAPDATA
- We can see the bitmap header data using
XXD
. https://i.sstatic.net/4jbJV.png. - The left most value is the address of the SCANLINE in hex, which corresponds to decimal values of 0 to 50 depending on whether the variable (such as biWidth) is 2 or 4 bytes (defined by DWORD, LONG, etc in bmp.h) and its offset starting point
- The top highlighted area is the header file (some of it is pixel files)
COLOR AND HEX
- Computer pixels on the screen are represented by RGB values, but bitmap represents them backwards as BGR
- https://i.sstatic.net/oi1Xr.png. Colors are represented as #BGR, or by 2 hex values. Denoting those values in this Copy.c program is through 0x000000, or 0x00 for B for instance
- White is #FFFFFF because it takes blue, green ,and red values to make white on a computer screen
STUFF IN COPY.C
FILE* outptr = fopen(outfile, "w");
// write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
We're keeping the output file open so we can add stuff into it and close the file later, its similar to open a word doc, adding stuff, and saving/closing. This is through FILE* outptr which is using the argv[2] we put in originally
STUFF IN COPY.C
// determine padding for scanlines int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
// iterate over pixels in scanline
for (int j = 0; j < bi.biWidth; j++)
{
// temporary storage
RGBTRIPLE triple;
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
// write RGB triple to outfile
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
// skip over padding, if any
fseek(inptr, padding, SEEK_CUR);
// then add it back (to demonstrate how)
for (int k = 0; k < padding; k++)
{
fputc(0x00, outptr);
}
}
this is the area that I don't really grasp all the way.
- We create a value called padding. This value always ends up being 0,1,2,3 based on its formula, because the scanline needs to be a multiple of 4, due to optimization of CPU usage /architecture defined by intel historically
- FORLOOP1 iterating through each row(scanline)
- FORLOOP2 iterating through each column within that row
- Within FORLOOP1, we are reading BGR values (0x00, 0xFF, etc)
- Within FORLOOP1, we look at the padding that might exist in the .bmp file
- Within FORLOOP1, we have another forloop designated for outputting padding. Because we're copying the file
I don't get what happens in 5 and 6 that well
I understand that all bmp files need to have a pixel width of a multiple of 4, and there might be padding in that file already. We calculated the amount of padding needed originally. We can count which things have BGR values through RGBtriple, and the rest is padding
TL;DR
Why do we need Fseek() at all?
Couldn't we just go straight to fputc, output the padding, and then go straight to the next scanline?
What am I missing here?