Search code examples
cbmp

Can integer operations (eg addition or subtraction) be performed on malloc buffers?


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?


Solution

  • 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).