Receiving multiple byte arrays from socket - java

I'm currently working on a remote desktop app. The server part runs on Android device and the client one on PC/Raspberry PI. I've encountered a problem with receiving my bitmaps (screenshots from Android, send as byte arrays).
The Android Server code goes like this:
//os = new ObjectOutputStream(s.getOutputStream());
public void run() {
while(true){
try {
View v1 = getWindow().getDecorView().getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
int quality = 100;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream);
byte[] byteArray = stream.toByteArray();
if(byteArray.length>0) {
os.writeInt(byteArray.length);
os.write(byteArray, 0, byteArray.length);
os.flush();
}
} catch (IOException e) {
e.printStackTrace();
}}}
And the Receiver App on PC like this:
//ois = new ObjectInputStream(s.getInputStream());
public void run() {
while(true){
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int size = ois.readInt();
System.out.println(size);
byte[] data = new byte[size];
int length = 0;
while ((length = ois.read(data,0,size)) != -1) {
out.write(data, 0, size);
out.flush();
}
byte[] bytePicture = out.toByteArray();
out.close();
BufferedImage buffImage = byteArrayToImage(bytePicture);
ImageIcon imgIcon = new ImageIcon(buffImage);
l.setIcon(imgIcon);
} catch (IOException e) {
}}}
byteArrayToImage
public static BufferedImage byteArrayToImage(byte[] bytes) {
BufferedImage bufferedImage = null;
try {
InputStream inputStream = new ByteArrayInputStream(bytes);
bufferedImage = ImageIO.read(inputStream);
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
return bufferedImage;
}
The problem is that in the receiver app I get Java OutOfMemoryException because I cannot differ between incoming screenshots. I really cannot figure out how to read exactly the size of a bitmap (as byte array) then display it and read another and another one. Any help will be appreciated. Thanks in advance.

Related

App crashed when sending images through TCP

I'm creating a simple stream to send images taken from client's screen from client to server. For now I can receive the first image but then the app crashed unexpectedly. The idea is send the size and the image in byte array, the server receive that byte array and convert to image.
FromClient:
public void run() {
image = new BufferedImage(NORM_PRIORITY, MIN_PRIORITY, MAX_PRIORITY);
while(continueLoop) {
//send captured screen
image = robot.createScreenCapture(rectangle);
try {
//Initiate the stream
OutputStream out = clientSocket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", baos);
// store the size of each image
byte[] size = ByteBuffer.allocate(4).putInt(baos.size()).array();
dos.write(size);
dos.write(baos.toByteArray(), 0, baos.toByteArray().length);
dos.flush();
} catch(IOException e) {
e.printStackTrace();
e.printStackTrace();
continueLoop = false;
}
try {
Thread.sleep(30);
} catch(InterruptedException e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
ToServer:
public void run() {
boolean continueLoop = true;
try {
drawGUI();
// Initiate the stream
InputStream is = clientSocket.getInputStream();
DataInputStream configGraphicStream = new DataInputStream(is);
BufferedImage image = null;
while(continueLoop) {
//receive the size of image and convert to type int
byte[] sizeInByte = new byte[64];
configGraphicStream.read(sizeInByte);
int length = ByteBuffer.wrap(sizeInByte).asIntBuffer().get();
try {
// Get images
byte[] img = new byte[length];
configGraphicStream.readFully(img, 0, img.length);
image = ImageIO.read(new ByteArrayInputStream(img));
}
catch (Exception e) {
System.out.println(e.getMessage());
}
//draw images
if( image != null)
{
Graphics graphics = clientPanel.getGraphics();
graphics.drawImage(image, 0, 0, clientPanel.getWidth(), clientPanel.getHeight(), clientPanel);
}
System.out.println("Receiving image");
Thread.sleep(30);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Please help me solve this problem.

How to send a bitmap using serversocket

I am making a multiplayer drawing application for android and I need to send the drawings that every user made to one player. I am using a server socket for this.
First thing I do is convert the Bitmap to a byte array, so I can send it to the Host with host.write(byteArray);
Bitmap bitmapImage = drawView.getBitmap();
byte[] byteArray = getByteArray(bitmapImage);
byteArrayLength = byteArray.length;
MainWifiActivity.SendReceive host = MainWifiActivity.sendReceiveHost;
if (host != null) {
host.write(byteArray);
}
The following code is my SendReceive class, which listenes to the inputStream and then starts a Handler, that is supposed to save the Bitmap to Internal Storage
public class SendReceive extends Thread {
private Socket socket;
private InputStream inputStream;
private OutputStream outputStream;
public SendReceive(Socket s) {
socket = s;
try {
inputStream = s.getInputStream();
outputStream = s.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
byte[] buffer = new byte[1024];
int bytes;
int filesize;
while (socket != null) {
try {
filesize = DrawingActivity.byteArrayLength;
if(buffer.length != filesize && filesize > 0){
buffer = new byte[filesize];
}
bytes = inputStream.read(buffer,0 ,buffer.length);
if (bytes > 0) {
Message mesg = handler.obtainMessage(IMAGE_MSG, bytes, -1, buffer);
mesg.sendToTarget();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
And the Handler:
Handler handler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case IMAGE_MSG:
byte[] byteArray = (byte[]) msg.obj;
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
saveBitmapToInternalStorage(bitmap);
}
return false;
}
});
In the saveBitmapToInternalStorage Method I get a java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
private void saveBitmapToInternalStorage(Bitmap bmp) {
File directory = getApplicationContext().getDir("imageDir", Context.MODE_PRIVATE);
File myPath = new File(directory, UUID.randomUUID().toString() + ".png");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myPath);
bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {
Log.d("HELLO", "MY ERROR: " + e);
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I know that BitmapFactory.decodeByteArray returns the decoded bitmap, or null if the image could not be decoded.
But why could it not be decoded?
I think this piece is wrong
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myPath);
bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {
It should be
FileOutputStream fos = new FileOutputStream(myPath);
try {
bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {

Android render pdf to bitmap with itext library

I am trying to convert a pdf stored in my assets folder into bitmap using PdfViewer.jar.
This is my code:
public static Bitmap renderToBitmap(InputStream inStream) {
Bitmap bitmap = null;
try {
byte[] bArray = IOUtils.toByteArray(inStream);
ByteBuffer buf = ByteBuffer.wrap(bArray);
PDFPage mPdfPage = new PDFFile(buf).getPage(0, true);
float width = mPdfPage.getWidth();
float height = mPdfPage.getHeight();
bitmap = mPdfPage.getImage((int) (width), (int) (height), null);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inStream.close();
} catch (IOException e) {
// do nothing because the stream has already been closed
}
}
return bitmap;
}
This code is doing what I need. But the resulting bitmap quality is very poor.
How can I increase the quality of bitmap created ?

for loop doesn't receive full data

I got the problem that my program is stuck in the for loop because the dataInputSteam doesn't receive all data before the DataOutputSteam is finished.
In my program I want to send a secreenshot with the server and the client should receive it:
Server:
public sendScreen(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
Robot robot;
try {
robot = new Robot();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle screen = new Rectangle( screenSize );
BufferedImage image = robot.createScreenCapture( screen );
BufferedImage scaledImage = Scalr.resize(image, 300);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
byte[] screenBytes = baos.toByteArray();
daos = new DataOutputStream(socket.getOutputStream());
daos.writeInt(screenBytes.length);
daos.write(screenBytes);
System.out.println("Screen sent");
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And the client:
public static class GetScreenshot implements Runnable{
Socket socket;
private static DataInputStream din;
private static BufferedImage screenshot;
public GetScreenshot(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
System.out.println("start method getScreenshot");
int length;
byte[] buffer;
PrintWriter out;
try {
//sending command to send screenshot
out = new PrintWriter(socket.getOutputStream(), true);
out.println("GETSCREENSHOT");
din = new DataInputStream(socket.getInputStream());
System.out.println("DIS created");
length = din.readInt();
System.out.println("Got data from DIS");
buffer = new byte[length];
System.out.println("Filled buffer");
for(int i = 0; i < length; i++){
buffer[i] = (byte) din.read();
System.out.println("read" + i+ "while length is " + length + " read data " + buffer);
}
System.out.println("got buffer");
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
screenshot = ImageIO.read(bais);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//writing screenshot to local disk
File outputfile = new File("C:\\users\\XXXX\\documents\\image2.png");
try {
ImageIO.write(screenshot, "png", outputfile);
System.out.println("image written to local disk");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//set screenshot in the tool
Main.labelScreenshot.setIcon(new ImageIcon(screenshot));
}
}
Does anybody know how i can transfer all of the data of the screenshot?
Greetings
Max
I think your problem is because your view (canvas/label/etc) width & height is smaller than your image. Try to resize the screenshoot so the width & height is same as your view (canvas/label/etc).
buffer = new byte[length];
System.out.println("Filled buffer");
At this point this message is simply untrue. You have created the buffer, but you certainly haven't filled it.
for(int i = 0; i < length; i++){
buffer[i] = (byte) din.read();
System.out.println("read" + i+ "while length is " + length + " read data " + buffer);
}
All this is equivalent to:
din.readFully(buffer);
And then:
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
screenshot = ImageIO.read(bais);
//writing screenshot to local disk
File outputfile = new File("C:\\users\\XXXX\\documents\\image2.png");
try {
ImageIO.write(screenshot, "png", outputfile);
All this is entirely equivalent to:
try (new FileOutputStream out = new FileOutputStream("C:\\users\\XXXX\\documents\\image2.png"))
{
out.write(buffer);
}
There is no need to decode and re-encode the image.
You add this to the sender part:
socket.flush();
if not worked, then:
socket.shutdownOutput();

jpegs are corrupted when resampled with java imageIO

The JPEG Images that ImageIO generated view correctly on windows file explorer, as well as safari webbrowser, but in FireFox, the resampled images are clipped.
How do I use ImageIO without corrupting the resamples?
The code should resize image keeping aspect ratio, as well as do jpeg compression, the convert it to a byte [] array, which could be written to a socket.
some of my code. in this snippet, I tried adding Jui library, but still the same issue.
public static BufferedImage imageistream;
public void Resample(String child,double width,double height) throws Exception, InvalidFileStructureException, InvalidImageIndexException, UnsupportedTypeException, MissingParameterException, WrongParameterException
{
String imagePath = "";
if(this.is_mac_unix == true)
{
imagePath = this.path+"/"+child;
}
else
{
imagePath = this.path+"\\"+child;
}
PixelImage bmp = null;
try {
bmp = ToolkitLoader.loadViaToolkitOrCodecs(imagePath, true, null);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Resample resample = new Resample();
resample.setInputImage(bmp);
double fixedRatio = width/height;
if(((double)bmp.getWidth()/bmp.getHeight()) >= fixedRatio)
{
resample.setSize((int)width,(int)(bmp.getHeight()/(bmp.getWidth()/width)));
}
else
{
resample.setSize((int)width,(int)(bmp.getWidth()/(bmp.getHeight()/height)));
}
resample.setFilter(Resample.FILTER_TYPE_LANCZOS3);
resample.process();
PixelImage scaledImage = resample.getOutputImage();
Processor.imageistream = ImageCreator.convertToAwtBufferedImage(scaledImage);
bmp = null;
Runtime rt = Runtime.getRuntime();
rt.gc();
}
...
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ImageIO.write(Processor.imageistream, "jpg", baos);
// ImageIO.write(Processor.imageistream, "png", baos); Works!
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte bytes[] = baos.toByteArray();
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
OutputStream os = (OutputStream)obj[1];
OutputStreamWriter writer = (OutputStreamWriter)obj[0];
byte[] buf= new byte[4096];
int c;
try {
while (true) {
c= is.read(buf);
if (c<= 0) break;
os.write(buf, 0, c);
}
writer.close();
os.close();
is.close();
I've been successfully using:
BufferedImage bufferedImage = ImageIO.read(..);
Image img = bufferedImage.getScaledInstance(..);
BufferedImage result = // transform Image to BufferedImage
ImageIO.write(result, "image/jpeg", response.getOutputStream());
transformation is simply writing the contents of the image to a new BufferedImage

Categories