AZhu
AZhu

Reputation: 38

gRPC -- Send .png image from Java client to Python server in Protobuf

I am trying to send images from a Java client to a Python server using gRPC and ProtoBuf. I encode the image as a ByteString and send it with a blockingStub. The Python server receives the ProtoBuf, but the Java ByteString is now a Python str. I'm not sure how to restore the image from the str.

When I call in the server:

request.ParseFromString(request.png_encoded)  # Throws error

it raises:

Traceback (most recent call last):

File "/usr/local/lib/python2.7/dist-packages/grpc/_server.py", line 364, in _call_behavior

return behavior(argument, context), True

File "process_server.py", line 57, in Process request.ParseFromString(request.png_encoded)

File "/usr/local/lib/python2.7/dist-packages/google/protobuf/message.py", line 185, in ParseFromString self.MergeFromString(serialized)

File "/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/python_message.py", line 1082, in MergeFromString if self._InternalParse(serialized, 0, length) != length:

File "/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/python_message.py", line 1108, in InternalParse new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)

File "/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/decoder.py", line 850, in SkipField return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, end)

File "/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/decoder.py", line 820, in _RaiseInvalidWireType

raise _DecodeError('Tag had invalid wire type.')

DecodeError: Tag had invalid wire type.

Java client:

public void run_process(String imPath) {
    logger.info("Will try to retrieve boxes with image " + imPath + " ...");
    File path = new File(imPath);
    byte[] imageInByte = null;
    ByteString byteIm = null;
    try {
        BufferedImage bufferedIm = null;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        bufferedIm = ImageIO.read(path);
        ImageIO.write(bufferedIm, "png", out);
        out.flush();
        imageInByte = out.toByteArray();
        out.close();
        ByteBuffer buf = ByteBuffer.wrap(imageInByte);
        byteIm = ByteString.copyFrom(buf);
    } catch (IOException e) {
        e.printStackTrace();
    }

    private final ManagedChannel channel;
    channel = ManagedChannelBuilder.forAddress("localhost", 50051).usePlaintext(true).build();
    private final ProcessServiceGrpc.ProcessServiceBlockingStub blockingStub;
    blockingStub = ProcessServiceGrpc.newBlockingStub(channel);

    ProcessRequest request = ProcessRequest.newBuilder().setPngEncoded(byteIm).build();
    ProcessResponse response;
    try {
        response = blockingStub.process(request);
    } catch (StatusRuntimeException e) {
        logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
        return;
    }
    logger.info("Boxes retrieved: " + response.toString());
}

Python server:

def Process(self, request, context):
    print(type(request.png_encoded))  # prints <type 'str'>
    request.ParseFromString(request.png_encoded)  # Throws error

    # Return empty response for now
    process_response = inference_pb2.ProcessResponse()
    return process_response

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    inference_pb2.add_ProcessServiceServicer_to_server(
        ProcessServiceServicer(), server)
    print "Starting Process Server"
    server.add_insecure_port('localhost:50051')
    server.start()
    try:
        while True:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        server.stop(0)

if __name__ == '__main__':
    serve()

I've tried to google "Decode Java Protobuf in Python" and "decode java protobuf Bytestring in python" but had no luck. Thanks in advance!

Upvotes: 2

Views: 3495

Answers (1)

Eric Anderson
Eric Anderson

Reputation: 26434

ByteString in Java is just an immutable byte[]. The Python 2 equivalent is str. It is a binary representation. If you wanted to save the image to disk, you would:

with open('out.png', 'wb') as file:
    file.write(request.png_encoded)

Upvotes: 2

Related Questions