Bitmap parsing in c++ and get pixel

Started by
6 comments, last by Shaarigan 2 years, 6 months ago

Hi guys,

I am trying to write a bitmap parser, and every thing is good when my bitmap texture is of dimension of power of two, but when it is not I am not able to get correct pixel at location and not able to set it as well, I know this is an alignment issue, but I am not able to get to it…

how get the correct pixel color in a RGB struct and set it as well…

//reading bmp file

infile.seekg(m_BMPHeader.Offset, ios_base::beg);

m_PixelRowSize = (((size_t)m_DibHeader.BitsPerPixel * abs(m_DibHeader.Width) + 31) / 32) * 4;

m_PixelData.resize(m_PixelRowSize * abs(m_DibHeader.Height));

infile.read(reinterpret_cast<char*>(m_PixelData.data()), m_PixelData.size());

infile.close();

vector<uint8_t> m_PixelData;

//wrting to a pixel at location

void BMPImporter::SetPixel(int x, int y, BGR bgr)

{

int channels = m_DibHeader.BitsPerPixel / 8;

m_PixelData[channels * (y * GetWidth() + x) + 0] = bgr.Blue;

m_PixelData[channels * (y * GetWidth() + x) + 1] = bgr.Green;

m_PixelData[channels * (y * GetWidth() + x) + 2] = bgr.Red;

}

Advertisement

m_PixelRowSize = (((size_t)m_DibHeader.BitsPerPixel * abs(m_DibHeader.Width) + 31) / 32) * 4;

I'd start by testing this calculation with various sizes and test files.

Omae Wa Mou Shindeiru

@undefined it is coming straight from wikipedia ?

Looking at my code for reading a Bitmap from data looks different than yours, so you should have a look at the specs first:

        byte uint[4] = { 0 };

        if(stream.Get() != 'B' || stream.Get() != 'M') return false;

        stream.Read((byte*)&header.Size, 4);
        stream.Read(uint, 2);
        stream.Read(uint, 2);
        stream.Read((byte*)&header.OffBits, 4);

        stream.Read(uint, 4); if(*(uint32*)uint != 40)
            return false;

        stream.Read(uint, 4); header.DataHeader.Width = *(uint32*)uint;
        stream.Read(uint, 4); header.DataHeader.Height = *(uint32*)uint;
        stream.Read(uint, 2); header.DataHeader.Planes = *(uint16*)uint;
        stream.Read(uint, 2); header.DataHeader.BitCount = *(uint16*)uint;
        stream.Read(uint, 4); header.DataHeader.Compression = *(uint32*)uint;
        stream.Read(uint, 4); header.DataHeader.SizeImage = *(uint32*)uint;
        stream.Read(uint, 4); header.DataHeader.X_pels_per_meter = *(uint32*)uint;
        stream.Read(uint, 4); header.DataHeader.Y_pels_per_meter = *(uint32*)uint;
        stream.Read(uint, 4); header.DataHeader.Clr_used = *(uint32*)uint;
        stream.Read(uint, 4); header.DataHeader.Clr_important = *(uint32*)uint;

        byte BitsPerPixel; if (header.DataHeader.BitCount == 32) BitsPerPixel = 32;
        else BitsPerPixel = 24;
        
        header.Buffer = header.DataHeader.Width * (BitsPerPixel / 8) * header.DataHeader.Height;

This parses the header. Then you have to calculate the padding in order to get the correct byte indexing

        uint32 BytesPerPixel = header.DataHeader.BitCount / 8;
        uint32 BytesPerRow = BytesPerPixel * header.DataHeader.Width;
        uint32 BytePaddingPerRow = 4 - BytesPerRow % 4;

        if (BytePaddingPerRow == 4) BytePaddingPerRow = 0;

Indexing a single pixel should then be something like (untested)

uint32 PixelPerRow = BytesPerRow / BytesPerPixel;

pixelData[(y * PixelPerRow * BytesPerPixel) + (x * BytesPerPixel)];

how are you taking BytePaddingPerRow into account…???

also please test your code … because i have tried many combination by trial and error … and didn't got result …

I do tried
pixelData[(y * PixelPerRow * BytesPerPixel) + (x * BytesPerPixel) + BytePaddingPerRow ];

Note: I am able to parse headers very correctly, loading and saving as a different .bmp file is also fine ?

pixelData[(y * PixelPerRow * BytesPerPixel) + (x * BytesPerPixel) + BytePaddingPerRow ];

BytePaddingPerRow should be added to PixelPerRow * BytesPerPixel to obtain the stride between successive lines. The empty space should be at the end of the lines, not before any pixel.

So

size_t BytesPerRow=PixelPerRow * BytesPerPixel+ BytePaddingPerRow;

pixelData[(y * BytesPerRow + (x * BytesPerPixel) ];

Omae Wa Mou Shindeiru

Enzio599 said:
also please test your code

I've just given you an insight how I'm doing it in our engine code. If it doesn't work for you or is untested, then it is up to you. I'm not here to provide copy paste solutions

This topic is closed to new replies.

Advertisement