Bild per Stream übertragen

  • Themenstarter Themenstarter DrHastig
  • Beginndatum Beginndatum
D

DrHastig

Hallo,

mein Problem ist es das ich ein Bild von einem Client zu einem Server (und andersrum) übtragen soll und das mittels normaler Socketverbindung. Das Bild was ankommt ist allerdings nur ca. halb so groß wie das eigentliche und ist einfach nur schwarz bzw. wenn ich es mir im Programm anzeigen lasse wird es garnicht angezeigt (transparenz?).

Im Clienten lade ich das Bild als BufferedImage. Anschließend zerlege ich dies in ein int-Array. Dieses Array wird dann mittels DataOutputStream zum Server übertragen und dort mit DataInputStream in einen Vector gelesen. AUs dem Vektor wird dann ein int-Array gemacht aus welchem ein Image-Object erstellt wird. Aus diesem Image-Object wird nun ein BufferedImage gemacht welches in eine Datei mittels ImageIO.write() geschrieben wird.

Hier mein Ansatz bis jetzt:
Im Client
Java:
public void connect(String host, int portCmd, int portImg) throws UnknownHostException, IOException {
	try {
		socketCmd = new Socket(host, portCmd);
		socketImg = new Socket(host, portImg);
	}
	catch(ConnectException e) {
		this.lastErrors = "Server nicht erreichbar: " + e.getMessage() + "\n";
		return;
	}
	
	in = socketImg.getInputStream();
	out = socketImg.getOutputStream();
	
	outData = new DataOutputStream(out);
	
	inText = new BufferedReader(new InputStreamReader(socketCmd.getInputStream()));
	
	outText = new PrintStream(socketCmd.getOutputStream());
	
	new Thread(this).start();
}

private boolean sendImg(String path) throws IOException, InterruptedException {
	boolean res = false;
	System.out.println("anfang sendImg");
	try {
		outText.print("data\n");
		System.out.println("call raus");
		boolean foo2;
		while(!(foo2 = inText.ready())) {
			System.out.println(foo2);
		}
		foo = inText.readLine();
		System.out.println(foo);
		if(foo.equalsIgnoreCase("OK")) {
			System.out.println("bestätigung da");
			File img = new File(path);
			BufferedImage bi = ImageIO.read(img);
			//foo = path.substring(path.lastIndexOf(".") + 1, path.length());
			//System.out.println(foo);
			//res =  ImageIO.write(ImageIO.read(img), foo, out);
			System.out.println(bi.getWidth() + "\t" + bi.getHeight());
			int[] pixel = getArrayFromImage(bi, bi.getWidth(), bi.getHeight());
			for(int i : pixel) {
				outData.writeInt(i);
			}
			outData.flush();
			System.out.println("img gesendet");
		}
		else {
			System.out.println("bestätigung nicht da");
			this.lastErrors += "Keine Bestätigung erhalten\n";
		}
	}
	finally {
		state = State.listen;
	}
	return res;
}

private int[] getArrayFromImage(Image img, int width, int height) throws InterruptedException {
	int[] pixels = new int[width * height];
	PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height, pixels, 0, width);
	pg.grabPixels();
	
	return pixels;
}

public static void main(String[] args) {
	
	System.out.println("Client gestartet");
	//ServerVerbindung.instance().sendData();
	/*
	UserInterface gui = UserInterface.instance();
	
	gui.setVisible(true);
	*/
	JFrame frame = new JFrame();
	JPanel panel = new JPanel();
	ImageComponent ic = new ImageComponent();
	ic.setImage(new File("./img/tux_drink_xp.jpg"));
	panel.add(ic);
	frame.add(panel);
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	
	frame.setVisible(true);
	
	try {
		ServerVerbindung.instance().connect("127.0.0.1", 12345, 54321);
	} catch (UnknownHostException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	ServerVerbindung sv = ServerVerbindung.instance();
	sv.actionPerformed("data_./img/tux_drink_xp.jpg");
	
	try {
		Thread.sleep(5000);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	String foo = ServerVerbindung.instance().getLastErrors();
	System.out.println(foo.equals("") ? "Kein Fehler" : foo);
}

Im Server
Java:
public SessionHandler(Socket socketCmd, Socket socketImg) throws IOException {
	this.socketCmd = socketCmd;
	this.socketImg = socketImg;
	
	in = socketImg.getInputStream();
	out = socketImg.getOutputStream();
	
	inData = new DataInputStream(in);
	
	inText = new BufferedReader(new InputStreamReader(socketCmd.getInputStream()));
	outText = new PrintStream(socketCmd.getOutputStream());
	
	new Thread(this).start();
}

private boolean receiveImg() throws IOException {
	System.out.println("receiveImg gestartet");
	
	Vector<Integer> pixel = new Vector<Integer>(1);
	
	
	
	while(inData.available() > 0)
		pixel.add(new Integer(inData.readInt()));
	
	System.out.println("Array gelesen");
	int[] pixel2 = new int[pixel.size()];
	
	for(int i = 0; i < pixel2.length; i++)
		pixel2[i] = pixel.get(i);
		
	Image img = getImageFromArray(pixel2, 1024, 768);
	System.out.println("Bild wiederhergestellt");
	//BufferedImage img = ImageIO.read(in);
	
	//System.out.println(img == null ? "recImg null" : "läuft");
	
	//BufferedImage bi = createBufferedImage(img);
	BufferedImage bi = toBufferedImage(img);
	System.out.println("BufferedImage erstellt");
	
	boolean res = queue.add(bi);
	
	state = State.listen;
	
	return res;
}

private Image getImageFromArray(int[] pixels, int width, int height) {
	MemoryImageSource mis = new MemoryImageSource(width, height, pixels, 0, width);
	Toolkit tk = Toolkit.getDefaultToolkit();
	
	return tk.createImage(mis);
}

public BufferedImage createBufferedImage(Image image) {
	if(image instanceof BufferedImage)
		return (BufferedImage)image;
	
	BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
	
	Graphics2D g = bi.createGraphics();
	g.drawImage(image, 0, 0, null);
	g.dispose();
	
	return bi;
}

// This method returns a buffered image with the contents of an image
private BufferedImage toBufferedImage(Image image) {
    if (image instanceof BufferedImage) {
        return (BufferedImage)image;
    }

    // This code ensures that all the pixels in the image are loaded
    image = new ImageIcon(image).getImage();

    // Determine if the image has transparent pixels; for this method's
    // implementation, see e661 Determining If an Image Has Transparent Pixels
    boolean hasAlpha = hasAlpha(image);

    // Create a buffered image with a format that's compatible with the screen
    BufferedImage bimage = null;
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    try {
        // Determine the type of transparency of the new buffered image
        int transparency = Transparency.OPAQUE;
        if (hasAlpha) {
            transparency = Transparency.BITMASK;
        }

        // Create the buffered image
        GraphicsDevice gs = ge.getDefaultScreenDevice();
        GraphicsConfiguration gc = gs.getDefaultConfiguration();
        bimage = gc.createCompatibleImage(
            image.getWidth(null), image.getHeight(null), transparency);
    } catch (HeadlessException e) {
        // The system does not have a screen
    }

    if (bimage == null) {
        // Create a buffered image using the default color model
        int type = BufferedImage.TYPE_INT_RGB;
        if (hasAlpha) {
            type = BufferedImage.TYPE_INT_ARGB;
        }
        bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
    }

    // Copy image to buffered image
    Graphics g = bimage.createGraphics();

    // Paint the image onto the buffered image
    g.drawImage(image, 0, 0, null);
    g.dispose();

    return bimage;
}

// This method returns true if the specified image has transparent pixels
private boolean hasAlpha(Image image) {
    // If buffered image, the color model is readily available
    if (image instanceof BufferedImage) {
        BufferedImage bimage = (BufferedImage)image;
        return bimage.getColorModel().hasAlpha();
    }

    // Use a pixel grabber to retrieve the image's color model;
    // grabbing a single pixel is usually sufficient
     PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
    try {
        pg.grabPixels();
    } catch (InterruptedException e) {
    }

    // Get the image's color model
    ColorModel cm = pg.getColorModel();
    return cm.hasAlpha();
}

public static void main(String[] args) {
	System.out.println("Server gestartet");
	new Thread(ClientConnection.instance()).start();
	
	try {
		Thread.sleep(10000);
	} catch (InterruptedException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
	}
	SessionHandler sh = ClientConnection.instance().getNewestHandler();
	
	JFrame frame = new JFrame();
	JPanel panel = new JPanel();
	ImageComponent ic = new ImageComponent();
	
	try {
		Thread.sleep(10000);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	String foo = ClientConnection.instance().getLastErrors();
	System.out.println(foo.equals("") ? "kein Fehler" : foo);
	for(int i = 0; i < Integer.MAX_VALUE; i++);
	BufferedImage bi = sh.pollImage();
	System.out.println(bi == null ? "Image null" : "Image nicht null");
	if(bi != null) {
		File bild = new File("./bilg.jpg");
		try {
			ImageIO.write(bi, "jpg", bild);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		ic.setImage(bild);
	}
	panel.add(ic);
	frame.add(panel);
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	
	frame.setVisible(true);
}

Die Methoden um das BufferedImage zum int-array zu konvertieren und um aus einem Image ein BufferedImage zu machen habe ich nur per google gefunden. Ist leider das erste mal das ich wirklich mit Images arbeite und mal wieder kommt der Zeitdruck -_-

Hoffe jemand kann mir Helfen da nurnoch bis zum Wochenende (Freitag Abend) Zeit ist :(

MfG
Dr. Hastig
 
Zuletzt bearbeitet von einem Moderator:
Hallo,

ich hab mir dein Programm noch nicht angeschaut, aber warum willst du unbedingt ein int[]. Ich würde einfach ein byte[] draus machen.

Code:
private byte[] imageToArray(RenderedImage image){
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
    try
    {
      ImageIO.write(image, "jpg", baos);
      baos.close();
      
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
    return baos.toByteArray();
  }
  
  private RenderedImage arrayToImage(byte[] array){
    ByteArrayInputStream bais = new ByteArrayInputStream(array);
    
    try
    {
      return ImageIO.read(bais);
    }
    catch (IOException e)
    {
      e.printStackTrace();
      return null;
    }
  }


MFG

Sascha
 
Ich habe ein int[] genommen weil ich halt per google dieses Workaround gefunden habe.
Das bIld zu einem Bytearray zu machen scheint zu funktionieren allerdings bekomme ich dieses Array nicht über den Stream.

auf Clientseite
Java:
ByteArrayOutputStream baos = new ByteArrayOutputStream();

try
{
  ImageIO.write(bi, "jpg", baos);
  baos.close();
  
}
catch (IOException e)
{
  e.printStackTrace();
}
byte[] array = baos.toByteArray();
System.out.println(array.length);

outData.write(array, 0, array.length);

unf auf Serverseite
Java:
byte[] array = new byte[42816];
inData.readFully(array);
ByteArrayInputStream bais = new ByteArrayInputStream(array);
BufferedImage bi = null;
try
{
      bi = ImageIO.read(bais);
}
catch (IOException e)
{
      e.printStackTrace();
}

Nun funktioniert noch weniger als vorher. Also es scheint garnix anzukommen.
 
Args das Bild wird doch richtig übertragen. Ich habe mir jetzt nur irgendwie ein anderen Fehler reingehaun aber das Bild wird übertragen.

Also der Teil mit dem Bildübertragen wär damit gelöst.

CORBA, RMI oder sowas wär sicherlich auch eine Lösung nur es ist keine Zeit mehr sich irgendwas anzugucken. Wir haben uns halt gedacht einfache Socketverbidnung und alles über Streams jagen werden wir wohl hinbekommen ohne große Einarbeitung.
 
Hallo,

in dem verlinkten Thread gehts am Ende nicht um Croba oder RMI, sondern auch um das Übertragen eines Bildes (Live-Screenshots) über Sockets.

Gruß Tom
 
Zurück