-2

I have a bmp file. My objective is to scale down the file to 70% of total file size. I have read the bmp headers and pixel array into src_buffer. Now I have a function that intakes pixel array and src_buffer, width of the bitmap(in pixels) src_width, height of the bitmap(in pixels) src_height and reduction factor ras input. This functions writes its output after scaling to dest_buffer, width of the bitmap(in pixels)dest_width and height of the bitmap(in pixels)dest_height. Now I want to write it back in bmp format. This is where I face difficulty. To write back, I find difficulty to populate the data members of struct BITMAPINFOHEADER and BITMAPFILEHEADER. What other thing should I take in account. I have read about padding between the rows of pixel array. How can I achieve it. I am coding in C. I dont want help with coding here. I want to help with the exact algorithm to write an BMP file.

tinutomson
  • 329
  • 6
  • 12
  • 2
    _Now I have a function that intakes pixel array and src_buffer, width of the bitmap(in pixels) src_width, height of the bitmap(in pixels) src_height and reduction factor ras input_ ***Show it and the other relevant code.*** It will be more likely someone can help if you provide your code. – ryyker Jun 26 '14 at 15:21
  • the function looks like `bool image_resize(WORD *src_buffer,unsigned int src_width, unsigned int src_height,WORD* dest_buffer,int *dest_width, int *dest_height, float r )`. – tinutomson Jun 26 '14 at 15:32
  • Which member(s) of `BITMAPFILEHEADER` and `BITMAPINFOHEADER` are confusing? If all you're doing is scaling the image down, then you should be able to use the original data for almost all of those structures' fields, save for those describing the size of the image. – Joe Farrell Jun 26 '14 at 15:51
  • 2
    Post it. ***[Like this question asker did](http://stackoverflow.com/q/24427076/645128)***. Or even like you did ***[HERE](http://stackoverflow.com/q/22836797/645128)***. Also consider ***[these guidlines for a good question](http://sscce.org/)*** when code is involved. In addition to the prototype, the definition would also be good. Show what you have tried so far to solve the stated problem. – ryyker Jun 26 '14 at 16:05
  • @JoeFarrell : BITMAPINFOHEADER .biHeight, BITMAPINFOHEADER .biWidth, BITMAPINFOHEADER .biSizeImage, BITMAPINFOHEADER .biSize and BITMAPFILEHEADER.bfSize are the once that are the data members I am not sure about. – tinutomson Jun 27 '14 at 05:51

1 Answers1

0

I figured out what exactly to do if you have to scale down a bmp file. I will talk only about 24 bit bmp file. A 24 bit bmp file consist of two headers followed by image pixel array. The first header in a BMP file is called BITMAPFILEHEADER with a total size of 14 bytes. It looks somewhat like this.

typedef struct 
{ 
    uint16_t bfType; //2 bytes storing "BM". This means that it is bmp
    uint32_t bfSize; //4 bytes total file size of bmp. Including both the header and pixel array
    uint16_t bfReserved1; //Always 0
    uint16_t bfReserved2; //Always 0
    uint32_t bfOffBits;   // stores 54. (40 +14)Total size of the headers.
} __attribute__((__packed__)) 
BITMAPFILEHEADER;

Followed by this is struct BITMAPINFOHEADER with a total size of 40 bytes. Following is its declaration

typedef struct
{
    uint32_t biSize; //40 bytes. Size of the header.
    int32_t biWidth; //Width of the bitmap image. How many pixel wide is the image. 
    int32_t biHeight; //Height of the bitmap image.
    uint16_t biPlanes; // Always 1.
    uint16_t biBitCount; //24 for 24 bit bitmap. Number of bit representing each pixel.
    uint32_t biCompression; 
    uint32_t biSizeImage; //Total size of bitmap pixel array including padding.
    int32_t biXPelsPerMeter; 
    int32_t biYPelsPerMeter; 
    uint32_t biClrUsed;
    uint32_t biClrImportant;
} __attribute__((__packed__))
BITMAPINFOHEADER; 

Now, these 2 structures are immediately followed by pixel array. A single pixel is represented by 3 bytes. say it is represented by

typedef struct
{
    uint8_t rgbtBlue;
    uint8_t rgbtGreen;
    BYTE  rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

We have a an array of RGBTRIPLE put in linear fashion. To be precise Number of pixel is given by following formula.

 BITMAPINFOHEADER.biWidth * BITMAPINFOHEADER.biHeight

The amount of memory required to store information of any image is given by :

 BITMAPINFOHEADER.biWidth * BITMAPINFOHEADER.biHeight * sizeof(RGBTRIPLE)

The memory required by any single row will be therefore :

BITMAPINFOHEADER.biWidth * sizeof(RGBTRIPLE)

Here is the catch, If total memory of any single row is not multiple of 4 bytes, A padding is added to that row so as to make it a multiple of 4. Say image is 41X30 in size. Number of bytes required to store a row would be 41*3 = 123bytes. So a padding of 1 byte will be added to this row in bmp format. Therefore BITMAPINFOHEADER.biSizeImage = 30 * 124 = 3720 bytes While decoding a bmp to raw pixel array, one should always keep in mind to remove these paddings. Similarly while writing back a bmp file(encoding), make sure that you add these extra paddings. Also note that,

BITMAPINFOHEADER.biSizeImage = (BITMAPINFOHEADER.biWidth * sizeof(RGBTRIPLE) +padding) * BITMAPINFOHEADER.biHeight

Or it can be calculated with a formula:

BITMAPINFOHEADER.biSizeImage = (((BITMAPINFOHEADER.biWidth * bmpiheader.biBitCount) + 31) / 32) * 4 * BITMAPINFOHEADER.biHeight

Please note that BITMAPINFOHEADER.biBitCount = sizeof(RGBTRIPLE) * 8 = 24 bits for 24 bit bitmap.

tinutomson
  • 329
  • 6
  • 12