简体   繁体   中英

Image transfer between C++ and Java via Socket

I would like to transfer an image from a Java application to a C++ application. I am using sockets as the communication method, and for now this works good with strings.

I want to be able to transmit it both way (Java <-> C++).

The image is NOT a file, this is a memory object/structure . So my main problem is how to encode the image for the transmission, so that it can be used in Java and in C++.

The transfer is on the same machine (no network, so the speed isn't critical), but still the faster/more efficient, the better.

Thank you

Note : I am using OpenCV in C++, and the main goal is to process a webcam stream. I don't / can't use JavaCV or something like that !

How about sending the RGB bytes. You can get the RGB bytes from BufferedImage and then send it to your C++ layer as a byte array. And then in the C++ layer construct back the the image using that byte array.

Using an efficient, cross-language data interchange format like Google protobuf , might be a solution. protobuf allows you to interchange image objects like this:

// Java image class

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

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

Image objects could be serialized using the following protobuf message:

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

The protobuf compiler will generate Java and C++ classes from this definition. From Java you serialize an Image as an ImageMsg object:

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

On the C++ side, read back the object from the stream:

std::istream* is;
// initialize istream

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

It is also possible to do the reverse, ie, send the image object from C++ to Java.

You should either use a common portable image format (such as .png, .gif, .jpg, .bmp), bearing in mind that some of those are lossy, or else you should send raw pixel data. If you send raw data, then you'll also have to make sure both ends know the image height and width, and the pixel format (that is, the order of channels R, G, B and possibly A, and the number of bits for each). Maybe you need to communicate that as part of the message, but maybe for your application some of those things are always the same.

You can either convert the image to a byte array or to a base64 encoded string and pass it between the two apps here is an example of how to encode a cv::Mat to a std::string using opencv in C++

std::vector<uchar> buf;
cv::imencode(".jpg", frame, buf); //you can use other extensions read more into cv::imencode to find the best one for you.
auto *enc_msg = reinterpret_cast<unsigned char*>(buf.data());
std::string encoded = base64_encode(enc_msg, buf.size());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM