Адаптация кода с записи в бинарный файл в запись в буфер в памяти
У меня возникли проблемы с конвертацией кода.
imagedata - это исходный буфер где хранится изображение. Полный код который я взял за основу тут. Я этот буфер формирую через Vulkan API.
Вот есть такой код для записи в файл.
for (int32_t y = 0; y < height; y++)
{
unsigned int *row = (unsigned int *)imagedata;
for (int32_t x = 0; x < width; x++)
{
file.write((char *)row, 4);
row++;
}
imagedata += subResourceLayout.rowPitch;
}
file.close();
Далее я при помощи библиотеки stb_image_writter загружаю созданный файл и формирую изображение. Всё отлично работает.
P.S.: при этом какая-то странная проблема. Я вообще могу записывать и через исходный буфер imagedata, но есть проблема на интегрированных GPU. Если ширина фреймбуфера не кратна 2-м, то вместо изображения какая-то ересь. В общем оно поломано. Видимо, как в примере, этот цикл нужен для выравнивания памяти в буфере. И действительно так у меня всё работает.
Создавать файл бинарный мне не нужно и мне хотелось бы записывать это всё в буфер в памяти. Я попробовал сделать так, но почему-то изображение получается чёрно-белым. Видимо я что-то забыл или переписал криво.
std::vector<char> data{};
for (int32_t y = 0; y < height; y++)
{
unsigned int *row = (unsigned int *)imagedata;
for (int32_t x = 0; x < width; x++)
{
data.push_back(row[0]);
data.push_back(row[1]);
data.push_back(row[2]);
data.push_back(row[3]);
row++;
}
imagedata += subResourceLayout.rowPitch;
}
Подскажите пожалуйста что я сделал не так? Ведь если экспортировать в бинарный файл, а потом загружать из него работает. Значит проблемой скорей всего является мой переписанный код.
Насколько я понимаю file.write берет данные из row и вставляет в файл первые n элементов. Я вроде сделал также через push_back, но почему тогда не работает?
И кстати, я добавлю, если заменить код в цикле на:
data.push_back(row[0]);
data.push_back(row[0]);
data.push_back(row[0]);
data.push_back(row[0]);
то вообще ничего не изменится. Будет также чёрно-белое изображение. Может быть я не правильно обращаюсь к переменной row ?
Попробовал сделать через stringstream - работает. Но мне кажется это не лучший способ. В общем подытожив можно сказать что вопрос заключается в том как переписать код так, чтобы функционально он был таким же как это делается через stream.write
UPD: Также моя попытка через char*:
char *data = new char[width * height * 4];
for (int32_t y = 0; y < height; y++)
{
unsigned int *row = (unsigned int *)imagedata;
for (int32_t x = 0; x < width; x++)
{
data[y + x] = (char)*(row);
data[y + x + 1] = (char)*(row + 1);
data[y + x + 2] = (char)*(row + 2);
data[y + x + 3] = (char)*(row + 3);
row++;
}
imagedata += subResourceLayout.rowPitch;
}
stbi_write_jpg("testFromBuffer.jpg", width, height, 4, data, 100);
delete[] data;
Ответы (1 шт):
Я разобрался.
Мне нужно было перед добавлением сделать cast row в char т.к. как было сказано @user7860670 отправляется 16 байт вместо 4.
std::vector<char> data{};
for (int32_t y = 0; y < height; y++)
{
unsigned int *row = (unsigned int *)imagedata;
for (int32_t x = 0; x < width; x++)
{
for (int i = 0; i < 4; i++)
data.push_back(reinterpret_cast<char*>(row)[i]);
row++;
}
imagedata += subResourceLayout.rowPitch;
}
Также нашёл замечательный пример пока гуглил. Там объясняется как это делается через memcpy.