package org.squidy.nodes.reactivision.remote.image; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.AsynchronousCloseException; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import org.squidy.nodes.reactivision.remote.CalibrationArea; public class ImageServer implements Runnable { /** * The port number on which the server is waiting for connection attempts. */ private int serverPort; private ServerSocketChannel serverSocketChannel; private SocketChannel socketChannel; private boolean connected; private boolean running; private BufferedImage currentImage = new BufferedImage(1024, 768, BufferedImage.TYPE_BYTE_GRAY); private CalibrationArea calibrationArea; public ImageServer(int serverPort) { this.serverPort = serverPort; connected = false; } public BufferedImage getImage() { return currentImage; } public void run() { //wait for connection attempt try { socketChannel = serverSocketChannel.accept(); connected = true; ImageMessage message; while (connected) { //get image message = ImageMessage.read(socketChannel); BufferedImage image = new BufferedImage(message.width, message.height, BufferedImage.TYPE_INT_ARGB); //Option A (better) int imageDataCounter = 0; for (int y = 0; y < message.height; ++y) { for (int x = 0; x < message.width; ++x) { int rgb = (int)(message.imageData[imageDataCounter++] & 255); rgb = (255 << 24) | (rgb << 16) | (rgb << 8) | rgb; image.setRGB(x, y, rgb); } } //Option B /* DataBuffer data = new DataBufferByte(message.imageData, message.imageData.length); int bitMasks[] = new int[]{(byte)0xf}; SampleModel sampleModel = new SinglePixelPackedSampleModel( DataBuffer.TYPE_BYTE, message.width, message.height, bitMasks); WritableRaster raster = Raster.createWritableRaster(sampleModel, data, null); image.setData(raster); */ //make image available currentImage = image; //cause repaint calibrationArea.repaint(); } } catch (AsynchronousCloseException e) { //do nothing } catch (IOException e) { e.printStackTrace(); connected = false; try { if (socketChannel != null) socketChannel.close(); } catch (IOException f) { f.printStackTrace(); } if (running) restart(); } catch (IllegalArgumentException e) { connected = false; try { socketChannel.close(); } catch (IOException f) { f.printStackTrace(); } if (running) restart(); } } public void setCalibrationArea(CalibrationArea calibrationArea) { this.calibrationArea = calibrationArea; } /** * Returns <code>true</code> if the ControlServer could be initialized and is, * now waiting for connections on the specified port. * * @return */ public boolean start() { // Create a server socket in blocking mode and check for connections try { serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(true); serverSocketChannel.socket().bind(new InetSocketAddress(serverPort)); } catch (IOException e) { e.printStackTrace(); return false; } running = true; (new Thread(this)).start(); return true; } public void stop() { running = false; try { serverSocketChannel.close(); } catch (IOException e) {} if (connected) { connected = false; try { socketChannel.close(); } catch (IOException e) {} } } private void restart() { (new Thread(this)).start(); } }