Я пытался следовать другой ответ но просто не могу понять это правильно. У меня есть около 8 МБ растрового изображения RBGX для преобразования в формат JPEG в памяти с помощью libjpeg-turbo. Если я использую jpeg_stdio_dest
Я могу записать все это в файл, затем прочитать файл обратно, и все в порядке. Тем не менее, пытаясь использовать jpeg_mem_dest
был загадкой Я все равно настроил как jpeg_stdio_dest
, но используя mem
кажется, только сделать одно выделение 4 КБ, а затем никогда не выделять больше места.
Я не могу найти документы с дальнейшими инструкциями по использованию jpeg_mem_dest
и действительно мог бы использовать какое-то направление.
void compress(std::vector<unsigned char>& input) {
jpeg_compress_struct cinfo{};
jpeg_error_mgr err{};
cinfo.err = jpeg_std_error(&err);
jpeg_create_compress(&cinfo);
#if 0 // using this with an open FILE* out works
jpeg_stdio_dest(&cinfo, out);
#endifcinfo.image_width = kWidth; // constants defined somewhere
cinfo.image_height = kHeight;
cinfo.input_components = 4;
cinfo.in_color_space = JCS_EXT_RGBX;
// what's wrong with this?
unsigned char* buf{};
unsigned long buf_sz{};
jpeg_mem_dest(&cinfo, &buf, &buf_sz);
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, 70, true);
jpeg_start_compress(&cinfo, true);
while (cinfo.next_scanline < cinfo.image_height) {
auto row = static_cast<JSAMPROW>(&input[cinfo.next_scanline * 4 * kWidth]);
jpeg_write_scanlines(&cinfo, &row, 1);
// Always prints 4096, and buf never changes
std::cout << "buf_sz: " << buf_sz
<< " buf: " << static_cast<void*>(buf) << '\n';
}
jpeg_finish_compress(&cinfo);
// ...
// in reality, return the compressed data
}
Да, это совсем не интуитивно понятно. Программист, предложивший твик jpeg_mem_dest (), не имел большого выбора, расширять существующий API-интерфейс не так просто, когда он изначально не предназначен для поддержки функции. Что совершенно неочевидно, так это то, что ваши переменные не обновляются до после вызов jpeg_finish_compress (). Соответствующий код в библиотеке:
METHODDEF(void)
term_mem_destination (j_compress_ptr cinfo)
{
my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest;
*dest->outbuffer = dest->buffer;
*dest->outsize = (unsigned long)(dest->bufsize - dest->pub.free_in_buffer);
}
Обратите внимание на слово «термин». Эта функция вызывается косвенно через указатель на функцию:
GLOBAL(void)
jpeg_finish_compress (j_compress_ptr cinfo)
{
//...
/* Write EOI, do final cleanup */
(*cinfo->marker->write_file_trailer) (cinfo);
(*cinfo->dest->term_destination) (cinfo);
//...
}
Вы ничего не можете с этим поделать. Просто настройте код std :: cout, переместите его после цикла, чтобы приспособить работу библиотеки.
Остерегайтесь других мелких деталей этой функции, также не очевидных. Вы должны освободить () буфер, который он создал. Видно в предоставленном примере программы cjpeg.c, конец main ().
Других решений пока нет …