2010-09-20 4 views
1

Я хочу передать изображение из приложения Java в приложение C++. Я использую сокеты в качестве метода связи, и на данный момент это хорошо работает со строками.Передача изображения между C++ и Java через Socket

Я хочу, чтобы иметь возможность передавать его в обоих направлениях (Java < -> C++).

Изображение НЕ является файлом, это объект/структура памяти. Поэтому моя основная проблема заключается в том, как кодировать изображение для передачи, чтобы его можно было использовать в Java и на C++.

Передача осуществляется на одном компьютере (нет сети, поэтому скорость не является критичной), но тем не менее, чем быстрее/эффективнее, тем лучше.

Спасибо

Примечание: Я использую OpenCV в C++, и главная цель состоит в том, чтобы обрабатывать поток веб-камеры. Я не могу/не могу использовать JavaCV или что-то в этом роде!

ответ

3

Как насчет отправки байтов RGB. Вы можете получить байты RGB из BufferedImage, а затем отправить его на свой уровень C++ в виде байтового массива. А затем в слое C++ верните изображение, используя этот массив байтов.

+1

Да, это похоже на простой способ, но я подумал, что есть более быстрый/более эффективный способ. Потому что это означало бы пройти через каждый пиксель изображения в Java и на C++. –

+2

@Matthieu: Сколько раз в секунду это должно произойти? Вы не можете передавать изображение без какого-либо кода, где-нибудь, посещая каждый пиксель. Я предполагаю, что теоретически ваша Java-программа могла бы (возможно, с JNI) записать полный буфер изображения в разделяемую память в формате, необходимом для программы на C++, тогда программа на C++ могла передать это непосредственно в графический API, который он использует (в качестве экранного буфера, текстуры и т. д.). –

+2

Размер RGB может быть несколько уменьшен с кодировкой длины пробега.Вместо отправки 230 нулей вы можете отправить 230 & 0, а получатель знает, как восстановить значение. Базовый алгоритм может быть для каждой строки сканирования {RLE кодирует строку данных; отправляйте в зависимости от того, что меньше - RLE или необработанные данные}. Более сложным было бы накормить всю партию в zip-поток из Java и использовать zlib в C++ для распаковки. – locka

1

Вы должны либо использовать общий формат переносимого изображения (например, .png, .gif, .jpg, .bmp), имея в виду, что некоторые из них являются потерями, либо вы должны отправлять необработанные пиксельные данные. Если вы отправляете необработанные данные, вам также необходимо убедиться, что оба конца знают высоту и ширину изображения, а формат пикселей (то есть порядок каналов R, G, B и, возможно, A и количество бит для каждого). Возможно, вам нужно сообщить об этом как часть сообщения, но, возможно, для вашего приложения некоторые из этих вещей всегда одинаковы.

+0

Если я использую формат изображения (png, gif, jpg ...), мне придется кодировать, передавать и декодировать, который (я думаю) слишком длинный. Соединение находится на одной машине (так быстрая передача), поэтому я думаю, что проблема заключается в времени для кодирования/декодирования. –

+0

Возможно, вы правы, но каково время кодирования/декодирования изображений, которые вас интересуют, по сравнению со скоростью передачи данных, которую вы получаете через loopback-сокет? –

+0

Я не знаю. Я понимаю: вы предлагаете кодировать, а затем передавать через сокет или кодировать и записывать на диск? (Я абсолютно не хочу писать на диск, потому что это действительно грязный способ, и это слишком медленно) –

2

Использование эффективного межпотокового формата обмена данными, такого как Google protobuf, может быть решением. Protobuf позволяет менять местами объекты изображения, как это:

// Java image class 

class Image { 
    // ... 
    byte[] getImageData() { 
     return imageData_; 
    } 

    int getVersion() { 
     return version_; 
    } 
    // ... 
} 

объектов изображения можно сериализовать с помощью следующего Protobuf сообщения:

message ImageMsg { 
    required int32 version = 1; 
    required bytes imageData = 2; 
} 

Protobuf компилятор будет генерировать Java и C++ классов из этого определения. От Java вы сериализовать изображение как объект ImageMsg:

Image img; 
// ... 
ImageMsg.Builder msg = ImageMsg.newBuilder(); 
msg.setVersion(img.getVersion()); 
msg.setImageData(img.getImageData()); 
// The output stream could point to a file, socket, pipe or something else. 
msg.writeTo(someOutputStream); 

На стороне C++, прочитанной назад объект из потока:

std::istream* is; 
// initialize istream 

ImageMsg msg;  
msg.ParseFromIstream(istream); 
Image img(msg.getVersion(), msg.getImageData()); 

Также возможно сделать обратное, т.е. отправить объект изображения с C++ на Java.

+0

Это хорошая идея для структур, но похоже, что она не может обрабатывать изображения. –

+0

@Matthieu Конечно, он может обрабатывать изображения, если изображение содержится в байтовом буфере внутри структуры. –

+0

Да, я не вижу смысла использовать это, я могу легко передать байтовый буфер через Socket. То, что я ищу, - это то, что я помещаю в этот байтовый буфер. –

Смежные вопросы