Java Byte Array And Image With Socket - java

My program takes a picture of the users screen, when they are using my program, to make a screenshot, then sends it to a server. The image will load about 1/4 of the way and freeze.
Sending the screenshot:
BufferedImage buffimg = robot.createScreenCapture(captureSize);
BufferedImage image = buffimg;
byte[] imageInByte;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
baos.flush();
imageInByte = baos.toByteArray();
baos.close();
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.println("!SCREENDATA!");
out.flush();
dos.writeInt(baos.toByteArray().length);
dos.write(baos.toByteArray());
dos.flush();
Getting the image:
if (input.startsWith("!SCREENDATA!")) {
System.out.println("reading");
DataInputStream dis = new DataInputStream(socket.getInputStream());
int len = dis.readInt();
System.out.println(len);
byte[] data = new byte[len];
dis.read(data);
InputStream in = new ByteArrayInputStream(data);
Image image = Toolkit.getDefaultToolkit().createImage(data);
v.repaint(image);
}
Displaying the image:
public void repaint(Image img) {
frame.getContentPane().add(new JLabel(new ImageIcon(img)));
frame.repaint();
frame.pack();
}
If anyone could help me with this, I would appreciate it a lot!

You need to keep calling dis.read(data); as this method on a TCP socket isn't designed to offer the entire buffer in one call (it's a stream socket, it keeps going). But be aware that the method call will block when the socket has no data to give. Also, it's best to send the file size in advance of the file so the other end knows how much to expect - it is less prone to protocol errors that can cause an infinite loop.
Have a look at the answers at how to achieve transfer file between client and server using java socket.
Anyway, an analogy: the socket has a bucket which fills up which is 512kb, let's say. You have a bucket that is 2048kb. You have to keep pouring the socket bucket into your own bucket.
Also, don't do stuff with Swing unless its on the Event Dispatch Thread. See How do you use the Event Dispatch Thread? for more details.

Related

extreamly slow image download speed

I have a java web application, where users can download images
The way i coded the download is using IOUtils.copy to the response stream
But downloading a 4mb image takes around 10 sec and its happening really slow.
It seems like the server is sending chunk at a time.
this is the way I am writing the image to the output stream:
OutputStream out = response.getOutputStream();
FileInputStream stream = new FileInputStream(path);
IOUtils.copy(stream, out);
out.flush();
out.close();
Is there a faster way to do this?
UPDATE
following code using 1MB buffer and copyLarge didn't make any change.
FileInputStream stream = new FileInputStream(path);
byte[] buffer = new byte[1024 * 1024];
IOUtils.copyLarge(stream, out,buffer );
Try copyLarge:
public static long copyLarge(InputStream input,
OutputStream output,
byte[] buffer) throws IOException
Use buffer size about 1Mb

Cannot send screenshots taken by a method of Robot class from the client to the server

I was able to send a picture from the client to the server using the following code but when I tried to send a screenshot taken by createScreenapture() method, I was able to take the screenshot and save it in my PC but was unable so send it to the server. Could anyone help me please?
These lines capture the screenshot and save it in my PC
Robot robot = new Robot(gdev);
this.bImage = robot.createScreenCapture(rectangle);
ImageIO.write(bImage, "jpg", new File("C:\\Users\\hp\\Desktop\\JAVA\\SocketProgrammingForReal\\Screencapture.jpg"));
These are responsible for sending the image
public void SendImage() throws IOException {
ByteOutputStream byteOutput = new ByteOutputStream();
ImageIO.write(bImage, "jpg", byteOutput);
byte[] size = ByteBuffer.allocate(4).putInt(byteOutput.size()).array();
dout.write(size);
ImageIO.write(bImage, "jpg", byteOutput);
dout.write(byteOutput.toByteArray());
dout.flush();
}
code for receiving the image and for saving it in my PC
DataInputStream din = new DataInputStream(server.getInputStream());
byte[] b = new byte[4];
din.read(b);
int size = ByteBuffer.wrap(b).asIntBuffer().get();
byte[] bImage = new byte[size];
din.readFully(bImage);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bImage));
ImageIO.write(image, "jpg", new File("C:\\Users\\hp\\Desktop\\JAVA\\screencapture2.jpg"));

Encrypted Image Format For A Java Game

I am making a 2D game in Java for the PC and this game has data like sprites, sound effects, music, and text.
The problem is that I need to store it somehow.
For now I need to store my sprites in an encrypted format and I need my Java game To decrypt and load the encrypted images To bufferedimages to display them on my game.
I don't want to encapsulate everything into a single executable .jar or .exe file.
I need to make my images(Resources,Spritesheets) encrypted and secure because I don't want to the player to interfere with them or use them.
I can't use ZIP files even encrypted or protected ones by using some
sort of a Java library because Java have to export them first on the disc
before it uses it
I have searched many forums and I can't find a clear answer.
Depending upon what sort of encryption you had in mind - you can use ImageIO to write/read the image to Output and Input Streams, taking the resulting bytes and decrypt/encrypt.
To save the image, use ImageIO to write the Image to an OutputStream (for example a ByteArrayOutputStream ). From the bytes written, you can encrypt, and then save
ByteArrayOutputStream os = null;
OutputStream fos = null;
try{
os = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", os);
byte[] bytes = os.toByteArray();
encrypt(bytes);
fos = new FileOutputStream(outputfile);
fos.write(bytes);
}catch(IOException e){
e.printStackTrace();
}finally{
if ( fos != null ){try{fos.close();}catch(Exception e){}}
if ( os != null ){try{os.close();}catch(Exception e){}}//no effect, but hear for sanity's sake
}
To read the and decrypt, just read the file as bytes, decrypt the bytes, then send the byte stream to ImageIO
InputStream is = null;
ByteArrayOutputStream os = null;
ByteArrayInputStream input = null;
try{
is = new FileInputStream(inputFile);
os = new ByteArrayOutputStream ();
byte[] buffer = new byte[500];
int len = -1;
while ( ( len = is.read(buffer) ) != -1 ){
os.write(buffer, 0, len);
}
byte[] fileBytes = os.toByteArray();
decrypt(fileBytes);
input = new ByteArrayInputStream(fileBytes);
Image image = ImageIO.read(input);
}catch(IOException io){
io.printStackTrace();
}finally{
if ( is != null ){try{is.close();}catch(Exception e){}}
if ( os != null ){try{os.close();}catch(Exception e){}}
if ( input != null ){try{input.close();}catch(Exception e){}}
}
The type of encryption you use is your choice. You can use a simple Cipher to encrypt the byte array using a bitwise exclusive or (^)
for ( int i = 0; i < bytes.length; i++ ){
bytes[i] = (byte)(bytes[i] ^ 123);
}
Or more fancy encryption using a Cipher
Note that for animated gif's, you may need to search for a way to save the frames of the gif (for instance see this)

How to load streamed data directly into a BufferedImage

I am using the code provided by this accepted answer to send a list of files over a socket in Java. My goal is to be receiving a list of images. What I would like to do is read these images directly into memory as BufferedImages before writing them to disk. However, my first attempts, which was to use ImageIO.read(bis) (again, see the attached question) failed, as it attempted to continue reading beyond the end of the first image file.
My current idea is to write the data from the socket to a new output stream, then read that stream from an intput stream that is passed to ImageIO.read(). This way, I can write it byte by byte as the program is currently doing, but send it to the BufferedImage rather than the file. however I'm not sure how to link the output stream to an input stream.
Can anyone recommend simple edits to the code above, or provide another method of doing this?
In order to read the image before writing it to disk, you'll need to use a ByteArrayInputStream. http://docs.oracle.com/javase/6/docs/api/java/io/ByteArrayInputStream.html
Basically, it creates a inputstream that reads from a specified byte array. So, you'd read the image length, then it's name, then the length-amount of bytes, create the ByteArrayInputStream, and pass it to ImageIO.read
Example snippet:
long fileLength = dis.readLong();
String fileName = dis.readUTF();
byte[] bytes = new byte[fileLength];
dis.readFully(bytes);
BufferedImage bimage = ImageIO.read(new ByteArrayInputStream(bytes));
Or using the code from the other answer you cited:
String dirPath = ...;
ServerSocket serverSocket = ...;
Socket socket = serverSocket.accept();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
DataInputStream dis = new DataInputStream(bis);
int filesCount = dis.readInt();
File[] files = new File[filesCount];
for(int i = 0; i < filesCount; i++)
{
long fileLength = dis.readLong();
String fileName = dis.readUTF();
byte[] bytes = new byte[fileLength];
dis.readFully(bytes);
BufferedImage bimage = ImageIO.read(new ByteArrayInputStream(bytes));
//do some shit with your bufferedimage or whatever
files[i] = new File(dirPath + "/" + fileName);
FileOutputStream fos = new FileOutputStream(files[i]);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write(bytes, 0, fileLength);
bos.close();
}
dis.close();

streaming a jpeg using com.sun.image.codec.jpeg.JPEGImageEncoder vs javax.imageio.ImageIO

I have a BufferedImage object of a jpeg which needs to be streamed as servlet response.
The existing code streams the jpeg using JPEGImageEncoder which looks like this :
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(resp.getOutputStream());
resp.reset();
resp.setContentType("image/jpg");
resp.setHeader("Content-disposition", "inline;filename=xyz.jpg");
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(image);
param.setQuality(jpegQuality, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(image);
I have noticed that this is resulting in the file size of the streamed jpeg to be tripled , unable to figure why.So I have tried using ImageIO to stream the jpeg
ImageIO.write(image, "jpg", out);
This works just fine, I am unable to decide why my predecessor has gone with the choice of JPEGImageEncoder and was wondering what issues would arise if I change to using ImageIO, I have compared both jpegs and couldn't really spot differences. Any thoughts?
To be clear, you've already a concrete JPEG image somewhere on disk or in database and you just need to send it unmodified to the client? There's then indeed absolutely no reason to use JPEGImageEncoder (and ImageIO).
Just stream it unmodified to the response body.
E.g.
File file = new File("/path/to/image.jpg");
response.setContentType("image/jpeg");
response.setHeader("Content-Length", String.valueOf(file.length()));
InputStream input = new FileInputStream(file);
OutputStream output = response.getOutputStream();
byte[] buffer = new byte[8192];
try {
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
}
finally {
try { input.close(); } catch (IOException ignore) {}
try { output.close(); } catch (IOException ignore) {}
}
You see the mistake of unnecessarily using JPEGImageEncoder (and ImageIO) to stream image files often back in code of starters who are ignorant about the nature of bits and bytes. Those tools are only useful if you want to convert between JPEG and a different image format, or want to manipulate (crop, skew, rotate, resize, etc) it.

Categories