I want to swap an image generated by a python program to another running python program by using a string.
(I have to use a string because in the real application the string is coming from a C-program and not a python program but that doesn't matter)
So with one program I have to read what the other printed in the console.
But like I did it now, it don't work, the image is not correctly transmitted when I run the two programs in parallel, the image is just gray, so the reader string is not similar to the printed string.
Where is my mistake here?
Sender Program:
import time
from PIL import Image
import sys
image = Image.open("t.png")
while True:
print(image.tobytes())
time.sleep(5)
Receiver Program:
import os
import sys
from PIL import Image
from subprocess import Popen, PIPE, STDOUT
script_path = os.path.join('lsend.py')
p = Popen([sys.executable, '-u', script_path],
stdout=PIPE, stderr=STDOUT, bufsize=1)
while True:
string = p.stdout.readline()
print("image received !!!")
print(string[0:10])
try:
image = Image.frombytes('RGBA',(90, 36),string,"raw")
image.show()
except:
print("fail")
My Image:
Thanks for your answers!
I think there are two issues with your code:
there is no message boundary - the sender just sends a continuous stream of bytes and the receiver has no idea where one image ends and the next begins, and
Image.tobytes()
seems to want to pair up with Image.frombuffer()
rather than Image.frombytes()
- no idea why!
So, I made your sender just send a single image and your receiver just receive a single image. I guess you would want to put some protocol on top that says how many bytes are coming, then the receiver would stop after receiving one image and start expecting a new byte count.
Here's lsend.py
:
#!/usr/bin/env python3
import sys
from PIL import Image
image = Image.open('lora.png').convert('RGB')
sys.stdout.buffer.write(image.tobytes())
And here is receiver.py
:
#!/usr/bin/env python3
import os
import sys
from PIL import Image
from subprocess import Popen, PIPE, STDOUT, DEVNULL
process = Popen(['./lsend.py'], stdout=PIPE, stderr=DEVNULL)
stdout, _ = process.communicate()
try:
image = Image.frombuffer('RGB',(90,36),stdout)
image.show()
except:
print("fail")
If the end result is to transmit video, I would recommend using sockets.
Python should provide everything you need in the socket
library
This should give a general idea of how sending data over a socket works:
import socket
# Host the socket on localhost for this example.
# This could send over a network too though.
host = "0.0.0.0"
port = 8000
# Initialize the socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
# The number of connections to listen for.
sock.listen(5)
print("Server listening.")
while True:
try:
# Accept an incoming connection from the client.
client, addr = sock.accept()
print("Accepted connection from client.")
# Wait until the client sends data.
data = client.recv(1024)
print(data)
# Send some data back to the client.
s = "Hello client"
client.send(s.encode())
client.close()
except KeyboardInterrupt:
break
Connecting to the socket is similar to hosting it. Instead of calling socket.bind
, just call the socket.connect
, and remove the socket.listen
.
import socket
# The host and port the socket is hosted on.
host = "0.0.0.0"
port = 8000
# Create the socket and connect to the server.
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
# Send the server some data.
s = "Hello server"
sock.send(s.encode())
# And receive some back.
data = sock.recv(1024)
print(data)
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.