To learn about JPEG compression, I downloaded a simple BMP/JPEG encoder that I have been examining. I have several questions, hopefully someone can help me with. I'm not a trained computer scientist, just a hobby programmer. Grateful for any help.
The following code reads a bitmap, I left some information out for brevity. I understand that a bitmap header is written as a struct, so the components can be read directly to variables without iterating.
BYTE is a typedef for uint8_t
int bmp_load(BMP *pb, char *file)
{
BMPFILEHEADER header = {0};
FILE *fp = NULL;
BYTE *pdata = NULL;
int i;
fp = fopen(file, "rb");
if (!fp) return -1;
fread(&header, sizeof(header), 1, fp);
pb->width = header.biWidth;
pb->height = header.biHeight;
pb->stride = ALIGN(header.biWidth * 3, 4);
pb->pdata = malloc(pb->stride * pb->height);// allocate a byte for each element of bitmap?
if (pb->pdata) {
pdata = (BYTE*)pb->pdata + pb->stride * pb->height; // Title question: Cast pdata as uint8_t buffer but what is the addition for? I think it has to do with padding a BMP file. Without addition there is a bus error: 10
for (i=0; i<pb->height; i++) {
pdata -= pb->stride; // What is the subtraction for?
fread(pdata, pb->stride, 1, fp);
}
}
fclose(fp);
return pb->pdata ? 0 : -1; // If pdata was being modified in the for loop, why is pb->pdata returned?
}
I have my questions as comments in the code and also pasted below. What is the addition for? I think it has to do with padding a BMP file. Without addition there is a bus error: 10
pdata = (BYTE*)pb->pdata + pb->stride * pb->height;
What is the subtraction for?
pdata -= pb->stride;
And finally, why is pb->pdata returned but its actually pdata that is modified in the code?
Here is a rewrite of the function that might be easier to understand.
int bmp_load(BMP *pb, char *file)
{
FILE* = fopen(file, "rb");
if (!fp) return -1;
BMPFILEHEADER header;
fread(&header, sizeof(header), 1, fp);
pb->width = header.biWidth;
pb->height = header.biHeight;
pb->stride = ALIGN(header.biWidth * 3, 4);
pb->pdata = malloc(pb->stride * pb->height);
if (!pb->pdata) return -1;
for (int i = pb->height - 1; i >= 0; i--) {
BYTE* pdata_current_row = pb->pdata + pb->stride * i;
fread(pdata_current_row, pb->stride, 1, fp);
}
fclose(fp);
return 0;
}
The for loop has i
decreasing because pixels are usually stored "bottom-up" (in BMP at least).