I have been trying to create a program that runs a client in Java and the server in Python. My overall goal is to upload a picture from the client on Java to the server on Python and store it on a mysql server. I haven't tried yet to convert from image on Python to blob on mysql and already got stuck in the uploading to python phase. This is the following code:
Client: (java)
client.send("upload##user##pass##"); //this is how i know that upload request has been sent.
String directory = "/home/michael/Pictures/"+field.getText();// a valid directory of a picture.
BufferedImage bufferedImage = null;
try {
bufferedImage = ImageIO.read(new File(directory));
} catch (IOException err) {
err.printStackTrace();
}
try {
ImageIO.write(bufferedImage, "png", client.socket.getOutputStream());//sending the picture via socket.
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
And this is the server:(Python)
elif mar[0]=="upload":##this is how i know that the request is to upload
buf = ''
while len(buf)<4:
buf += clientsock.recv(4-len(buf))
size = struct.unpack('!i', buf)
print "receiving %s bytes" % size
with open('tst.jpg', 'wb') as img:
while True:
data = clientsock.recv(1024)
if not data:
break
img.write(data)
print 'received, yay!'
This code actually doesn't work and prints ridiculous amount of bytes that I want to send (around 2 gb for the picture) I have not been working a lot with the server/client so this code perhaps is awful.
I can't see that you sending image size before sending the image, but in Python code you're reading 4 bytes image size first.
You need to add sending of image size in your Java code:
try {
OutputStream outputStream = client.socket.getOutputStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "png", byteArrayOutputStream);
// get the size of image
byte[] size = ByteBuffer.allocate(4).putInt(byteArrayOutputStream.size()).array();
outputStream.write(size);
outputStream.write(byteArrayOutputStream.toByteArray());
outputStream.flush();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Related
I am trying to receive the video stream of my Tello drone using Processing as stated in its SDK documentation:
To receive the video stream via UDP I have tried to use a script by The Coding Train:
import java.awt.image.*;
import javax.imageio.*;
import java.net.*;
import java.io.*;
// Port we are receiving.
int port = 11111;
DatagramSocket ds;
// A byte array to read into (max size of 65536, could be smaller)
byte[] buffer = new byte[65536];
PImage video;
void setup() {
size(400,300);
try {
ds = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
video = createImage(320,240,RGB);
}
void draw() {
// checkForImage() is blocking, stay tuned for threaded example!
checkForImage();
// Draw the image
background(0);
imageMode(CENTER);
image(video,width/2,height/2);
}
void checkForImage() {
DatagramPacket p = new DatagramPacket(buffer, buffer.length);
try {
ds.receive(p);
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = p.getData();
println("Received datagram with " + data.length + " bytes." );
// Read incoming data into a ByteArrayInputStream
ByteArrayInputStream bais = new ByteArrayInputStream( data );
// We need to unpack JPG and put it in the PImage video
video.loadPixels();
try {
// Make a BufferedImage out of the incoming bytes
BufferedImage img = ImageIO.read(bais);
// Put the pixels into the video PImage
img.getRGB(0, 0, video.width, video.height, video.pixels, 0, video.width);
} catch (Exception e) {
e.printStackTrace();
}
// Update the PImage pixels
video.updatePixels();
}
The only thing I changed in the script is the variable port as the SDK documentation (see above) specifies, that it should be 11111.
When I run the script (after successfully sending command and streamon to the drone), I get the message Received datagram with 65536 bytes. and a Null Pointer Exception. I've found out, that the Null Pointer Exception is shown, because the following line of code returns null:
BufferedImage img = ImageIO.read(bais);
So in the end, my question is, why this line of code or more specifically ImageIO.read(bais) returns null. However, the script works correctly, if you use it combined with the Video Sender script of the Coding Train. So, what's the problem here?
I have found many examples in opencv of sending a mat through socket from java to java or c++, but I can't get it to work on python.
The server code:
MatOfByte bytemat = new MatOfByte();
Highgui.imencode(".jpg", out, bytemat);
byte[] bytes = bytemat.toArray();
r.write(String.valueOf(bytes.length));
Log.d(TAG, String.valueOf(bytes.length));
r.write(bytes);
The python code:
def recvall(sock, count):
buf = b''
while count:
newbuf = sock.recv(count)
if not newbuf: return None
buf += newbuf
count -= len(newbuf)
return buf
length = recvall(camera_socket, 5)
if not length:
continue
print length
data = recvall(camera_socket, int(length))
if not data:
continue
nparr = np.fromstring(data, np.uint8)
frame = cv2.imdecode(nparr, cv2.CV_LOAD_IMAGE_UNCHANGED)
window = cv2.namedWindow('frame', cv2.WINDOW_NORMAL)
cv2.imshow('frame', frame)
The weird part is that imdecode returns None always. I just can't get it to work.
PS: the java client works using ObjectInputStream
----EDIT----
Thanks all for advices, I've replaced the byte stream with predefined bytes and discovered that Java was sending some headers when sending bytes because it was using ObjectOutputStream.
Now the java code for writing to socket is:
DataOutputStream oos = null;
try {
oos = new DataOutputStream(os);
oos.write(byteImage);
} catch (Exception e) {
Log.e(TAG, "Error while writing to OutputStream", e);
cancel();
setState(STATE_NONE, this.type);
}
Try using np.uint8(nparr) for conversion as in:
frame = np.uint8(nparr)
This example works:
import numpy as np
import cv2
nparr = np.zeros((512, 512))
nparr[200:300, 400:450]=255
cv2.imshow("Result", np.uint8(nparr))
cv2.waitKey()
[EDIT] In case of a colour image please keep in mind that OpenCV2 images are BGR instaed of RGB, so you may vae to use
rgb = cv2.cvtColor(frame_in_bgr, cv2.COLOR_BGR2RGB)
Thanks all for advices, I've replaced the byte stream with predefined bytes and discovered that Java was sending some headers when sending bytes because it was using ObjectOutputStream.
Now the java code for writing to socket is:
DataOutputStream oos = null;
try {
oos = new DataOutputStream(os);
oos.write(byteImage);
} catch (Exception e) {
Log.e(TAG, "Error while writing to OutputStream", e);
cancel();
setState(STATE_NONE, this.type);
}
This now works. The only problem left is that the colors are inverted. Any tip on how to invert them again?
I want to use Gravatar but I don't want to publish users MD5 hashes of their e-mail addresses. And there is more potential problems. So I decided to download them and store them in my database.
But I have a problem with such a simple task as my profile picture (Earlybird) looks bad after downloading:
This is the code I used.
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
final URL url = new URL("http://www.gravatar.com/avatar/" + account.getGravatarHash() + "?d=identicon");
final BufferedImage image = ImageIO.read(url);
ImageIO.write(image, "jpg", baos);
pic = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
Value in pic is then directly stored to the database. Other pictures in my database are stored fine so problem must be in these lines.
EDIT:
I just partially fix the problem by changing "jpg" for a "png" even thought Gravatar tutorial is mentioning "jpg". Also I don't want to specify image format (unless all Gravatars are png). Can I avoid that? I want just save the bytes I get.
Browsers in most cases work with raw bytes. However it is highly appreciated to send "Content-Type: image/..." header for each image.
When you save bytes in DB you also have to
either save image content type, provided by Gravatar for this image or
convert image into your default format, so you can to hardcode content type for all images from your DB
To get headers, provided by Gravatar, you can use Apache HTTP Client.
To convert image into your preferred format, you can use ImageIO.
I found one similar problem with working solution:
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()){
final URL url = new URL("http://www.gravatar.com/avatar/" + account.getGravatarHash() + "?d=identicon");
InputStream inputStream = url.openStream();
byte[] buffer = new byte[1024];
int n;
while (-1 != (n = inputStream.read(buffer))) {
baos.write(buffer, 0, n);
}
inputStream.close();
pic = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
Looks like this works with png and jpg Gravatars.
I'm using cordova/phonegap to capture image with device (currently iphone), the capturing is working fine, I get the base64 encoded image as a string in a callback:
function handlePhotoSuccess(image){
document.getElementById("uploadItemForm:picture").src = "data:image/jpeg;base64," + image;
document.getElementById("uploadItemForm:imageBase64").value = image;
}
The imageBase64 element is a hidden h:inputText.
The image show correctly, but the saved value in the bean is not correct. It has like the image's 30% and the other part is gray.
The value in the backing bean is a String, I convert it to a byte array, then save it:
byte[] imageByte;
BASE64Decoder decoder = new BASE64Decoder();
try {
imageByte = decoder.decodeBuffer(imageString);
ByteArrayInputStream is = new ByteArrayInputStream(imageByte);
temp.setContent(is); //temp will be saved to database
images.put(currentAttribute.getId(), imageByte);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Maybe I do something wrong?
Thank you in advance!
I need a very simple function that allows me to read the first 1k bytes of a file through FTP. I want to use it in MATLAB to read the first lines and, according to some parameters, to download only files I really need eventually. I found some examples online that unfortunately do not work. Here I'm proposing the sample code where I'm trying to download one single file (I'm using the Apache libraries).
FTPClient client = new FTPClient();
FileOutputStream fos = null;
try {
client.connect("data.site.org");
// filename to be downloaded.
String filename = "filename.Z";
fos = new FileOutputStream(filename);
// Download file from FTP server
InputStream stream = client.retrieveFileStream("/pub/obs/2008/021/ab120210.08d.Z");
byte[] b = new byte[1024];
stream.read(b);
fos.write(b);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
the error is in stream which is returned empty. I know I'm passing the folder name in a wrong way, but I cannot understand how I have to do. I've tried in many way.
I've also tried with the URL's Java classes as:
URL url;
url = new URL("ftp://data.site.org/pub/obs/2008/021/ab120210.08d.Z");
URLConnection con = url.openConnection();
BufferedInputStream in =
new BufferedInputStream(con.getInputStream());
FileOutputStream out =
new FileOutputStream("C:\\filename.Z");
int i;
byte[] bytesIn = new byte[1024];
if ((i = in.read(bytesIn)) >= 0) {
out.write(bytesIn);
}
out.close();
in.close();
but it is giving an error when I'm closing the InputStream in!
I'm definitely stuck. Some comments about would be very useful!
Try this test
InputStream is = new URL("ftp://test:test#ftp.secureftp-test.com/bookstore.xml").openStream();
byte[] a = new byte[1000];
int n = is.read(a);
is.close();
System.out.println(new String(a, 0, n));
it definitely works
From my experience when you read bytes from a stream acquired from ftpClient.retrieveFileStream, for the first run it is not guarantied that you get your byte buffer filled up. However, either you should read the return value of stream.read(b); surrounded with a cycle based on it or use an advanced library to fill up the 1024 length byte[] buffer:
InputStream stream = null;
try {
// Download file from FTP server
stream = client.retrieveFileStream("/pub/obs/2008/021/ab120210.08d.Z");
byte[] b = new byte[1024];
IOUtils.read(stream, b); // will call periodically stream.read() until it fills up your buffer or reaches end-of-file
fos.write(b);
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(inputStream);
}
I cannot understand why it doesn't work. I found this link where they used the Apache library to read 4096 bytes each time. I read the first 1024 bytes and it works eventually, the only thing is that if completePendingCommand() is used, the program is held for ever. Thus I've removed it and everything works fine.