Sending images with python sockets, images brocken - python

I wanted to make a client, that sends images and a list of strings to an server.
First I wanted to put eerything in one List, and make it one string with pickle, so I can send it.
But unfortunatley, the string became to big for pickle to handle, so I just used two sockets, one for the list, and one for the image.
It worked, but the Image I recived is broken.
This is the original image:
And here is the copied image:
As you can see, the bottom part is not there, but the real problem is, that I can't use the image in my kivy app, while the original image work.
How can I solve this problem?
Here is the server:
import socket
import errno
import base64
import pickle
from PIL import Image
import StringIO
def connect(c):#recursive funktion, that deals with the errorno 11
try:
strings = c.recv(8192)
return strings
except IOError as e:
if e.errno == errno.EWOULDBLOCK:
connect(c)
def Main():
host = IP
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print "Connection from: " + str(addr)
strings = connect(c)
#gets the image
c.send('give image')
#c.flush()
c.close()
c, addr = s.accept()
image = connect(c)
imgname = 'test.png'
if image == 'cusdom_image':
with open('images.png', "rb") as imageFile:
image = ''
image = base64.b64encode(imageFile.read())
print image
fh = open(imgname, "wb")
fh.write(image.decode('base64'))
fh.close()
if __name__ == '__main__':
Main()
And here is the client:
import socket
import base64
import pickle
from PIL import Image
import StringIO
import os, sys
ip = '138.106.181.133'
port = 12345
print 'Add event executed'
s = socket.socket()#makes socket for the first time
s.connect((ip, port))
image_path = '/home/gilgamesch/PTTT/icon.png'
print os.getcwd()
olddir = os.getcwd()
os.chdir('/')
print os.getcwd()
new_list = ['Some', 'random', 'string', 'list', ]
new_compact_list = pickle.dumps(new_list)
s.send(new_compact_list)
recived = s.recv(1023)
if image_path != '':
with open(image_path, "rb") as imageFile:
image_data = base64.b64encode(imageFile.read())
print 'open worked'
else:
image_data = 'cusdom_image'
os.chdir(olddir)
if recived == 'give image':
s.close()
s = socket.socket()#remakes socket to send image
s.connect((ip, port))
s.sendall(image_data)
s.close()
And By the way, the bitcode is fine, when the client reads it, I tested it, it gets broken, when it is send to the server.

Related

How to send and recieve a cv2 image in the form of numpy array

I'm an intermediate in python and new to libraries like numpy and opencv. I'm trying to make a video calling app using sockets.This code is just a try. I've tried in the following way but as it receives the array it's size becomes 0 and shape becomes null. Please help me do this. I'm sorry for anymistakes I've done
any help will be appreciated
Thank you. Have a nice day enter
Server:-
import socket
import threading
from _thread import *
import cv2
import numpy as np
srvr = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_ip = socket.gethostbyname(socket.gethostname())
port = 9999
client = []
try:
srvr.bind((server_ip, port))
except socket.error as e:
print(e)
def connected_client(conn, addr):
global client
print("[SERVER]: CONNECTED WITH ", addr)
check_msg = "Welcome Client"
conn.send(str.encode(check_msg))
while True:
try:
data = conn.recv(5000)
if not data:
print("[SERVER]: DISCONNECTED..")
break
for i in client:
i.sendall(data)
except:
break
conn.close()
srvr.listen(5)
while True:
print("[SERVER]: STARTED...\n [SERVER]: ACCEPTING CONNECTIONS....")
conn, addr = srvr.accept()
start_new_thread(connected_client, (conn, addr))
client.append(conn)
Client:-
import socket, cv2
import threading
from _thread import *
import numpy as np
import time
import base64
video = cv2.VideoCapture(0)
clt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SERVER = socket.gethostbyname(socket.gethostname())
PORT = 9999
ADDR = (SERVER, PORT)
clt.connect(ADDR)
print(clt.recv(2048).decode())
#recieving data from server
def recieve():
global clt
while True:
recv_frame = clt.recv(5000)
nparr = np.frombuffer(recv_frame, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
key = cv2.waitKey(1)
if key == ord('a'):
break
print(img)
# cv2.imshow("aman", recv_frame)
# break
# https://stackoverflow.com/questions/17967320/python-opencv-convert-image-to-byte-string
# new thread while to continuously recieve data
start_new_thread(recieve, ())
# loop for continuously sending data
while True:
check, frame = video.read()
str_frame = cv2.imencode('.jpg', frame)[1].tobytes()
clt.sendall(str_frame)
video.release()
cv2.destroyAllWindows()

sending a screenshot using python

I'm trying to take a screenshot and send it to another computer using python.
I've tried to do it in many different ways. Unfortunately, I didn't find a way to do it.
I would appreciate your help!
server:
from PIL import Image
from PIL import ImageGrab
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', 1111))
server_socket.listen(1)
print('Waiting For Connection...')
(client_socket, client_address) = server_socket.accept()
print('Connected to: ', client_address[0])
img = ImageGrab.grab(bbox=(10, 10, 500, 500))
photo_to_send= img.tobytes()
size = len(photo_to_send)
client_socket.send(bytes(str(size), 'utf-8'))
while size >= 0:
msg = photo_to_send[:4096]
client_socket.send(bytes(str(msg), 'utf-8'))
photo_to_send= photo_to_send[4096:]
client:
import socket
from PIL import Image
my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
my_socket.connect(('127.0.0.1', 1111))
print("Connected to the server")
size = int(my_socket.recv(1024).decode('utf-8'))
the_photo = ""
the_photo = the_photo.encode('utf-8')
while size > 0:
data = my_socket.recv(4096)
size -= len(data)
the_photo += data
img_to_save = Image.frombytes("RGB", (490,490), the_photo)
img_to_save .save("screenshot.png")
You can use pickle to serialize your Image objects. Pickle just converts an python object into bytes. pickle.dumps just encodes it to bytes and pickle.loads decodes it back.
Hope this helps!
The problem is that you are sending the textual value of the length immediately before the data itself. For example, if the image data started with AAABBB, you would be sending
1234AAABBB...
But if the image was bigger, you might send something like
56789AAABBB...
The client has no way of telling where the length ends and the data starts! To fix this, you need to send a fixed size length parameter. If you still want to a textual length, you could use zfill:
client_socket.send(str(size).zfill(16).encode())
...
size = int(my_socket.recv(16).decode())
(where 16 is chosen to be long enough to fit any possible image size)
This is not terribly efficient; real protocols usually use binary encoding:
client_socket.send(struct.pack('>I', size))
...
size, = struct.unpack('>I', my_socket.recv(4))
But this may be more complex than you need for your application.
The problem was that I encoded the photo twice.
Thanks for your help!
I really appreciate it!
Here is the solution:
server:
from PIL import ImageGrab
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', 1112))
server_socket.listen(1)
print('Waiting For Connection...')
(client_socket, client_address) = server_socket.accept()
print('Connected to: ', client_address[0])
img = ImageGrab.grab(bbox=(10, 10, 500, 500))
photo_to_send = img.tobytes()
size = len(photo_to_send)
print(size)
print(photo_to_send)
client_socket.send(bytes(str(size), 'utf-8'))
client_socket.send(photo_to_send)
client:
import socket
from PIL import Image
my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
my_socket.connect(('127.0.0.1', 1112))
print("Connected to the server")
size = int(my_socket.recv(10).decode('utf-8'))
print(size)
the_photo = my_socket.recv(size)
print(the_photo)
img_to_save = Image.frombytes("RGB", (490, 490), the_photo)
img_to_save.save("screenshot.png")
struct and pickle makes everything easy for you.
server.py
imageBytes = pickle.dumps(image)
sock.sendall(struct.pack("L", len(imageBytes)) + imageBytes)
client.py
data = b""
payload_size = struct.calcsize("L")
while True:
data += sock.recv(payload_size)
packedImageSize = data[:payload_size]
imageSize = struct.unpack("L", packedImageSize)[0]
data = data[payload_size:]
while len(data) < imageSize:
data += sock.recv(65000)
frameData = data[:imageSize]
data = data[imageSize:]
frame = pickle.loads(frameData)

send image from one server to another

I want to send an image from one server to another. I don't want to save the file on disk. I directly want to read the send data. I've written a script for this.
server.py
import socket
import cv2
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("", 6002))
s.listen(10)
c, addr = s.accept()
print('{} connected.'.format(addr))
img = cv2.imread("test.jpg")
img = cv2.imencode('.jpg', img)[1].tostring()
c.send( str(len(img)).ljust(16));
c.send(img)
i = 0
datas = img[i:i+1024]
i = i + 1024
while datas:
datas = img[i:i+1024]
c.send(datas)
i = i + 1024
print("Done sending...")
client.py
import socket
import numpy as np
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("", 6002))
img = ""
while True:
datas = s.recv(1024)
while datas:
img = img + str(datas)[2:-1]
datas = s.recv(1024)
break
print("Done receiving")
img_np = np.fromstring(img, np.uint8)
img_np = cv2.imdecode(img_np, cv2.IMREAD_COLOR)
I'm receiving image in img but when decoding it using opencv, I'm getting empty matrix img_np.
I suggest you to use Memory-Mapped File instead of ZeroMQ as it yields less latency.
Here is an example I wrote that you can use: https://github.com/off99555/python-mmap-ipc

audio over python tcp error

I am writing a simple python tcp code to send over a wav file however I seem to be getting stuck. can someone explain why my code is not working correctly?
Server Code
import socket, time
import scipy.io.wavfile
import numpy as np
def Main():
host = ''
port = 3333
MAX = 65535
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(1)
print "Listening on port..." + str(port)
c, addr = s.accept()
print "Connection from: " + str(addr)
wavFile = np.array([],dtype='int16')
i = 0
while True:
data = c.recvfrom(MAX)
if not data:
break
# print ++i
# wavfile = np.append(wavfile,data)
print data
timestr = time.strftime("%y%m%d-%h%m%s")
print timestr
# wavF = open(timestr + ".wav", "rw+")
scipy.io.wavfile.write(timestr + ".wav",44100, data)
c.close()
if __name__ == '__main__':
Main()
Client Code
host, port = "", 3333
import sys , socket
import scipy.io.wavfile
# create a tcp/ip socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# connect the socket to the port where the server is listening
server_address = (host, port)
print >>sys.stderr, 'connecting to %s port %s' % server_address
input_data = scipy.io.wavfile.read('Voice 005.wav',)
audio = input_data[1]
sock.connect(server_address)
print 'have connected'
try:
# send data
sock.sendall(audio)
print "sent" + str(audio)
sock.close()
except:
print('something failed sending data')
finally:
print >>sys.stderr, 'closing socket'
print "done sending"
sock.close()
Please help someone, I want to send an audio file to my embedded device with tcp since it crucial data to be processed on the embedded device.
Not sure why you go to the trouble of using scipy and numpy for this, since you can just use the array module to create binary arrays that will hold the wave file. Can you adapt and use the simple client/server example below?
(Note: I've copy/pasted a small Windows sound file called 'tada.wav' to the same folder to use with the test scripts.)
Code for the server script:
import socket
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
print('Listening...')
conn, addr = s.accept()
print('Connected by', addr)
outfile = open("newfile.wav", 'ab')
while True:
data = conn.recv(1024)
if not data: break
outfile.write(data)
conn.close()
outfile.close()
print ("Completed.")
Code for the client:
from array import array
from os import stat
import socket
arr = array('B') # create binary array to hold the wave file
result = stat("tada.wav") # sample file is in the same folder
f = open("tada.wav", 'rb')
arr.fromfile(f, result.st_size) # using file size as the array length
print("Length of data: " + str(len(arr)))
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.send(arr)
print('Finished sending...')
s.close()
print('done.')
This works for me (though only tested by running both on localhost) and I end up with a second wave file that's an exact copy of the one sent by the client through the socket.

Receive Image using socket programming in Python

I am trying to receive an image in python to use it in my program.
Here is the sever code:
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("127.0.0.1", 5005))
server_socket.listen(5)
data = ' '
client_socket, address = server_socket.accept()
print "Conencted to - ",address,"\n"
while (1):
data = client_socket.recv(1024)
print "The following data was received - ",data
print "Opening file - ",data
img = open(data,'r')
while True:
strng = img.readline(512)
if not strng:
break
client_socket.send(strng)
img.close()
print "Data sent successfully"
exit()
#data = 'viewnior '+data
#os.system(data)
And here is the client code:
import socket,os
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("127.0.0.1", 5005))
size = 1024
while(1):
print "Enter file name of the image with extentsion (example: filename.jpg,filename.png or if a video file then filename.mpg etc) - "
fname = raw_input()
client_socket.send(fname)
#fname = 'documents/'+fname
fp = open(fname,'w')
while True:
strng = client_socket.recv(512)
if not strng:
break
fp.write(strng)
fp.close()
print "Data Received successfully"
exit()
#data = 'viewnior '+fname
#os.system(data)
The received should now be read to be able to use it. I am opening it like this:
input_image = Image.open('data').convert('L').resize((100, 100))
but when I run both codes in cmd the output is:
The following data was received - + path Opening file - + path
Then nothing happens although the image should be used and the final output should be shown.
Anyone can help?
I don't know if this is your (only) problem, but when working with binary files, you should pass the b flag to the built-in function open:
img = open(data, 'rb')

Categories