двоичное копирование данных из структуры в std :: vector - PullRequest
0 голосов
/ 26 декабря 2018

Я использую библиотеку, которая может загружать изображения BMP из памяти.

У меня есть класс, который представляет BMP.

Для загрузки из памяти я должен предоставить указатель на некоторый BMPотформатированные данные в памяти и переменная для размера этих данных.(void* data, size_t length)

Я хочу сохранить свои данные в std::vector.(Избегает ручного управления памятью)

Я пытался написать функцию, возвращающую std::vector<unsigned char>, но я не думаю, что у меня это очень хорошо.

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));
    }

}

Очевидно, что это не компилируется.Я не могу придумать альтернативы std::copy.Действительно ли это правильный инструмент для работы?

Чтобы сделать его компилируемым, я думаю, что я должен изменить memory.at(x) на memory.data() + x ... Делая это, я буду использовать необработанные указатели - вот почему я не надеваюНе думаю, что std::copy лучше memcpy.

Могу я дать совет по этому поводу?Это несколько нелогичная задача, и если бы я знал об этом требовании раньше, я бы сохранил свои данные пикселей в unsigned char с заголовками растрового файла, предшествующими данным.К сожалению, сейчас будет очень сложно изменить дизайн, поэтому я бы не стал его трогать.

1 Ответ

0 голосов
/ 26 декабря 2018

Три проблемы:

  1. Вы хотите скопировать байт , но функция std::copy предоставляет указатель на BITMAPFILEHEADER (или BITMAPINFOHEADER) структура.Вам необходимо преобразовать указатели в байты , например reinterpret_cast<uint8_t*>(&f_head).

  2. Предыдущее приводит к другим проблемам с концом данных, выражением &f_head + sizeof(f_head)который действительно равен (&f_head)[sizeof(f_head)], и находится далеко за пределами структуры.Здесь также необходимо использовать байты, как в reinterpret_cast<uint8_t*>(&f_head) + sizeof f_head.

  3. Последняя проблема - место назначения для вызова std::copy, так как это необходимо длябыть подобным типу как источник, то есть указатель на uint8_t (в случае моих приведений).Вы можете легко получить это, например, &memory[0].А для второго звонка &memory[sizeof f_head].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...