Noticias Weblogs Foros Wiki Código

Planeta Codigo - Foros

Los foros de la comunidad.

No estás identificado.

#1 2007-05-06 11:07:41

Albin
Albin
Ubicación: Valencia (Spain)
Registrado: 2005-04-02
Mensajes: 521
Web

ImageObserver

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).

Código:

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.

Código:

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?


"somos lo que hacemos" Microsiervos (el libro)

Desconectado

 

#2 2007-05-08 18:58:46

Albin
Albin
Ubicación: Valencia (Spain)
Registrado: 2005-04-02
Mensajes: 521
Web

Re: ImageObserver

Segundo intento ... utilizar el MediaTracker, que para eso lo parieron ...

Código:

    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?


"somos lo que hacemos" Microsiervos (el libro)

Desconectado

 

#3 2007-05-11 07:04:20

Albin
Albin
Ubicación: Valencia (Spain)
Registrado: 2005-04-02
Mensajes: 521
Web

Re: ImageObserver

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.


"somos lo que hacemos" Microsiervos (el libro)

Desconectado

 

Pie del foro

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson