user2138149
user2138149

Reputation: 16849

binary copy data from struct to std::vector

I am using a lib which can load BMP images from memory.

I have a class which represents a BMP.

To load from memory I have to supply a pointer to some BMP formatted data in memory and a variable for the size of that data. (void* data, size_t length)

I want to store my data in a std::vector. (Avoids manual memory management)

I've attempted to write a function to return a std::vector<unsigned char>, but I don't think what I've got is very good.

std::vector<unsigned char> BMP::BITMAP::SaveMem() const
{

    // memory storage
    std::vector<unsigned char> memory;


    BITMAPFILEHEADER f_head;
    f_head.bfType = ushort_rev(((WORD)'B' << 0x08) | ((WORD)'M' << 0x00));
    f_head.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + m_width_memory * m_height;
    f_head.bfReserved1 = 0;
    f_head.bfReserved2 = 0;
    f_head.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);


    // build standard bitmap file header
    BITMAPINFOHEADER i_head;
    i_head.biSize = sizeof(BITMAPINFOHEADER);
    i_head.biWidth = m_width;
    i_head.biHeight = m_height;
    i_head.biPlanes = 1;
    i_head.biBitCount = m_bit_count;
    i_head.biCompression = 0;
    i_head.biSizeImage = m_width_memory * m_height;
    i_head.biXPelsPerMeter = 0;
    i_head.biYPelsPerMeter = 0;
    i_head.biClrUsed = 0;
    i_head.biClrImportant = 0;


    // alloc
    memory.resize(f_head.bfSize);

    std::copy(&f_head, &f_head + sizeof(f_head), memory.at(0));
    std::copy(&i_head, &i_head + sizeof(i_head), memory.at(0) + sizeof(f_head));


    // write data
    for(unsigned int y = 0; y < m_height; ++ y)
    {
        std::copy(&m_data[y * m_width_memory], m_data[y * m_width_memory + 3 * m_size_x], memory.at(0) + sizeof(f_head) + sizeof(i_head));
    }

}

Clearly this doesn't compile. I can't think of any alternative to std::copy. Is this really the right tool for the job?

To make it compile I think I should change memory.at(x) to memory.data() + x... By doing this I would be using raw pointers - which is why I don't think std::copy is any better than memcpy.

Could I have some advice on this? It's somewhat an illogical task and had I known about this requirement earlier I would have stored my pixel data in an unsigned char with the bitmap file headers preceeding the data. Unfortunatly it will be a lot of work to change the design now, so I'd rather not touch it.

Upvotes: 0

Views: 449

Answers (1)

Some programmer dude
Some programmer dude

Reputation: 409176

Three problems:

  1. You want to copy bytes, but the std::copy function is provided a pointer to a BITMAPFILEHEADER (or BITMAPINFOHEADER) structure. You need to convert the pointers to bytes, like reinterpret_cast<uint8_t*>(&f_head).

  2. The previous leads to other problems with the end of the data, the expression &f_head + sizeof(f_head) which really is equal to (&f_head)[sizeof(f_head)], and is way beyond the end of the structure. You need to use bytes here as well, as in reinterpret_cast<uint8_t*>(&f_head) + sizeof f_head.

  3. The last problem is the destination for the std::copy call, as it needs to be a similar type as the source, i.e. a pointer to uint8_t (in the case of my casts). You can easily get that by doing e.g. &memory[0]. And for the second call &memory[sizeof f_head].

Upvotes: 1

Related Questions