Los foros de la comunidad.
No estás identificado.
Un programita sube por FTP la imágen de una webcam, mientras que un applet intenta mostrarla, claro, a veces coincide que la imágen no está completa, y me han consultado si podrÃa echarles una mano.
Asà que he hecho lo siguiente, un programa que lee un fichero (Berlin 001.jpg) y lo guarda con otro nombre (WebCam.jpg), y 5 segundos después, hace lo mismo con otro fichero (Berlin 002.jpg), y luego vuelve a empezar. Además la copia está ralentizada a propósito (porque lo pruebo en local).
package vciscarwebcam;
import java.io.*;
public class Switcher implements Runnable {
private boolean bRight = true;
private String sFile1 = "Berlin 001.jpg";
private String sFile2 = "Berlin 002.jpg";
private String sFile3 = "WebCam.jpg";
public Switcher() {
Thread th = new Thread(this);
th.start();
}
public void run() {
while(true) try {
File fSrc = null;
File fTrg = null;
if(bRight) {
fSrc = new File(sFile1);
System.out.println("Reading:"+sFile1);
} else {
fSrc = new File(sFile2);
System.out.println("Reading:"+sFile2);
}
fTrg = new File("build\\"+sFile3);
InputStream is = new FileInputStream(fSrc);
OutputStream os = new FileOutputStream(fTrg);
int readed = 0;
byte buffer[] = new byte[2048];
while((readed = is.read(buffer))!=-1) {
os.write(buffer, 0, readed);
Thread.sleep(50);
}
os.flush();
os.close();
is.close();
bRight = !bRight;
System.out.println("Waiting...");
Thread.sleep(5000);
} catch(Exception ex) {
ex.printStackTrace();
}
}
}Esto funciona, porque cargando la imagen en Firefox y refrescando manualmente, veo que a veces está una, a veces otra, a veces un cacho de alguna de las dos ... Ahora llega el momento del Applet, y resulta que imageUpdate() siempre recibe en infoflags ImageObserver.WIDTH o ImageObserver.HEIGHT pero nunca un ImageObserver.ALLBITS o similar.
public class AppletWC extends Applet implements Runnable, ImageObserver {
private boolean bAlive = true;
private BufferedImage biImagen = null;
private Graphics gImagen = null;
public AppletWC() {
biImagen = new BufferedImage(320, 240, BufferedImage.TYPE_INT_RGB);
gImagen = biImagen.getGraphics();
}
public void init() {
Thread th = new Thread(this);
th.start();
}
public void stop() {
bAlive = false;
}
public void paint(Graphics g) {
g.drawImage(biImagen, 0, 0, 320, 240, null);
}
public void run() {
Toolkit tk = Toolkit.getDefaultToolkit();
while(bAlive) try {
Image img = tk.createImage(new URL("http://localhost/vciscar/WebCam.jpg"));
gImagen.drawImage(img, 0, 0, this);
repaint();
Thread.sleep(100);
} catch(Exception ex) {
ex.printStackTrace();
}
}
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
System.out.println("---");
System.out.println(img.getSource().toString());
if((infoflags & (ImageObserver.WIDTH))!=0) System.out.print("width ");
if((infoflags & (ImageObserver.HEIGHT))!=0) System.out.print("height ");
if((infoflags & (ImageObserver.ERROR))!=0) System.out.print("error ");
if((infoflags & (ImageObserver.ABORT))!=0) System.out.print("abort ");
if((infoflags & (ImageObserver.ALLBITS))!=0) System.out.print("allbits ");
if((infoflags & (ImageObserver.SOMEBITS))!=0) System.out.print("somebits ");
if((infoflags & (ImageObserver.PROPERTIES))!=0) System.out.print("properties ");
if((infoflags & (ImageObserver.FRAMEBITS))!=0) System.out.print("framebits ");
boolean done = ((infoflags & (ImageObserver.ERROR | ImageObserver.FRAMEBITS | ImageObserver.ALLBITS)) != 0);
System.out.println(done);
if(done) repaint();
return done;
}
}¿Alguién sabe qué parte no he entendido bien de cómo funciona esto?
Desconectado
Segundo intento ... utilizar el MediaTracker, que para eso lo parieron ...
public void run() {
try {
boolean bError = false;
URL url = new URL("http://localhost/vciscar/WebCam.jpg");
MediaTracker mt = new MediaTracker(this);
Toolkit tk = Toolkit.getDefaultToolkit();
while(bAlive) {
System.out.println("run");
Image img = tk.createImage(url);
mt.addImage(img, 0);
mt.waitForID(0);
bError = mt.isErrorID(0);
mt.removeImage(img, 0);
if(bError) {
} else {
gImagen.drawImage(img, 0, 0, this);
gImagen.setColor(Color.RED);
gImagen.drawRect(0, 0, 25, 25);
repaint();
}
img.flush();
Thread.sleep(100);
}
} catch(Exception ex) {
ex.printStackTrace();
}
}En principio funciona ¿demasiado bien? porque tiene el mismo problema que tiene el applet original (y por el cual contactaron conmigo, y claro, no voy a ser más listo que el otro tio, cuando solo he hecho un applet "de manual") ...
Al tema ... cuando la imagen está a medias (por el otro proceso que sistematicamente la borra y la vuelve a generar poco a poco) pues el media tracker dice que ya ha acabado la carga, pero no avisa que haya ningun error con lo cual la imagen sale "Medio pintada" ... sin embargo, cuando acaba la ejecución, en la pantallita de salida (donde va dirigido el System.out) ahà si que salen mensajitos en rojo de "Premature end of JPG" o algo asÃn ... osea que (lógicamente) darse cuenta, se da cuenta, peeerooo ... a mi no me avisa, y yo acabo pintando la imagen cuando aún no deberÃa.
¿Ideas?
Desconectado
Al final he usado MediaTracker (como se recomienda) para saber cuando se ha cargado la imagen. Y luego he utilizado PixelGrabber para poder acceder a la información de cada pixel, si todos los pixels de la última fila son iguales (sospechoso) considero que la imágen no se ha cargado completamente (está siendo subida por FTP pero aún no se ha subido entera).
La curiosidad y problema al mismo tiempo, es que a pesar de lo que diga la documentación oficial, createImage si cachea la imagen, y -mirando los logs del Apache- se puede apreciar que la solicitas 1000 veces y la pide 1 solamente. He intentado otras opciones, como abrir un URLConnection desde el objeto URL y leer la imagen byte a byte con un InputStream, para luego pasarle el array de bytes a createImage, pero nada, incluso eso lo cachea WTF!!! ... al final la única solución que me ha funcionado bien, es pedir la URL con un parámetro al final que va cambiando de una petición a otra, asà no se le ocurre cachearla, pues piensa que pueden ser diferentes contenidos, y sà que la pide una y otra vez ... pero vamos, manda huevos.
Lo más curioso/gracioso, es que como Aplicacion funciona bien, solo lo cachea si es un Applet.
Desconectado