Anuncio

martes, 2 de octubre de 2012

RenderingHints, renderizados y operaciones de manipulación de imágenes

http://swing-facil.blogspot.com.es/2011/12/renderinghints-renderizados-y.html

RenderingHints



KEY_ALPHA_INTERPOLATION 
  • VALUE_ALPHA_INTERPOLATION_SPEED
  • VALUE_ALPHA_INTERPOLATION_QUALITY
  • VALUE_ALPHA_INTERPOLATION_DEFAULT

KEY_ANTIALIASING
  • VALUE_ANTIALIAS_ON
  • VALUE_ANTIALIAS_OFF
  • VALUE_ANTIALIAS_DEFAULT

KEY_COLOR_RENDERING
  • VALUE_COLOR_RENDER_SPEED
  • VALUE_COLOR_RENDER_QUALITY
  • VALUE_COLOR_RENDER_DEFAULT

KEY_DITHERING 

  • VALUE_DITHER_DISABLE
  • VALUE_DITHER_ENABLE
  • VALUE_DITHER_DEFAULT


KEY_FRACTIONALMETRICS 
  • VALUE_FRACTIONALMETRICS_OFF
  • VALUE_FRACTIONALMETRICS_ON
  • VALUE_FRACTIONALMETRICS_DEFAULT

KEY_INTERPOLATION  
  • VALUE_INTERPOLATION_NEAREST_NEIGHBOR → la muestra de color de la coordenada vecinas mas cercana en la imagen es la usada.
  • VALUE_INTERPOLATION_BILINEAR → la muestra de color se obtiene mediante interpolación lineal de las 4 coordenadas más cercanas.
  • VALUE_INTERPOLATION_BICUBIC → las muestras de color de 9 coordenadas cercanas en la imagen se interpolan usando una función cúbica en X e Y para producir la muestra de color.
 KEY_RENDERING
  • VALUE_RENDER_SPEED
  • VALUE_RENDER_QUALITY
  • VALUE_RENDER_DEFAULT
 KEY_STROKE_CONTROL 
  • VALUE_STROKE_NORMALIZE
  • VALUE_STROKE_PURE
  • VALUE_STROKE_DEFAULT
KEY_TEXT_ANTIALIASING
  • VALUE_TEXT_ANTIALIAS_ON → Antialiasing habilitado
  • VALUE_TEXT_ANTIALIAS_OFF → Antialiasing deshabilitado
  • VALUE_TEXT_ANTIALIAS_DEFAULT → El renderizado se realiza de acuerdo al valor del indicador KEY_ANTIALIASING
  • VALUE_TEXT_ANTIALIAS_GASP → El renderizado requiere usar la información en el recurso de la fuente que especifica para cada tamaño de punto si usar o no los valores VALUE_TEXT_ANTIALIAS_ON o VALUE_TEXT_ANTIALIAS_OFF.
  • VALUE_TEXT_ANTIALIAS_LCD_HRGB → El texto mostrado será optimizado para un display LCD con subpixeles para mostrar de izquierda a derecha RGB, de tal manera que la resolución horizontal subpixel es tres veces la de la resolución de un pixel horizontal completo (HRGB).
  • VALUE_TEXT_ANTIALIAS_LCD_HBGR → El texto mostrado será optimizado para un display LCD con subpixeles para mostrar de izquierda a derecha BGR, de tal manera que la resolución vertical subpixel es tres veces la de la resolución de un pixel vertical completo (HBGR).
  • VALUE_TEXT_ANTIALIAS_LCD_VRGB → El texto mostrado será optimizado para un display LCD con subpixeles para mostrar de arriba a abajo RGB, de tal manera que la resolución horizontal subpixel es tres veces la de la resolución de un pixel horizontal completo (VRGB).
  • VALUE_TEXT_ANTIALIAS_LCD_VBGR → El texto mostrado será optimizado para un display LCD con subpixeles para mostrar de arriba a abajo BGR, de tal manera que la resolución vertical subpixel es tres veces la de la resolución de un pixel vertical completo (VBGR).

KEY_TEXT_LCD_CONTRAST  
Los valores deben ser enteros positivos en el rango 100 a 250.

  • Un valor bajo (100) corresponde a texto con mayor contraste cuando se muestra texto oscuro en un fondo claro.
  • Un valor alto (200) corresponde a texto de bajo contraste cuando se muestra texto oscuro en un fondo claro.
  • Un valor típico esta en el estrecho rango 140-180.
  • Si no se especifica ningún valor, una implementación por defecto o del sistema será aplicada.

  

Hilos en Java(Threads) parte 3

http://monillo007.blogspot.com/2008/01/hilos-en-javathreads-parte-3.html



Recordemos lo visto en la segunda parte de Hilos en Java:

- Existen diversos tipos de constructores a partir de los cuales se puede crear un hilo, algunos de los más importantes son:
+ Thread()
+ Thread(objetoRunnable)
+ Thread(objetoRunnable, String nombre)
+ Thread(String nombre)


- Un hilo recién creado e instanciado se encuentra en estado nuevo (new), pasa a estado en ejecución (runnable) cuando se llama a su método start() y se considera muerto (dead) una vez que se completa lo contenido en su método run().

- Para llamar al método start() se necesita una instancia de la clase Thread.

- El método estático Thread.currentThread().getName() se utiliza para saber qué proceso se encuentra en ejecución en un momento determinado.

- Cuando se trata de hilos, muy pocas cosas está garantizadas. Una de ellas es que cada hilo se iniciará y se ejecutará hasta que se complete pero no en un orden específico ni sin interrupciones.

- Solamente se puede llamar una vez al método start() de un hilo en particular, de lo contrario se obtiene una excepción de tipo java.lang.IllegalThreadStateException.

Sigamos pues con los hilos en Java.

Más info tras el salto...




El programador de hilos::

En la máquina virtual de Java existe algo que llamamos el programador de hilos que es el encargado de decidir qué hilo es el que se va a ejecutar por el procesador en un momento determinado y cuándo es que debe de parar o pausar su ejecución. Asumiendo que se tiene un equipo de un solo procesador, solo un proceso puede estar corriendo en un momento dado, como lo hemos mencionado anteriormente, la idea de multi-proceso o multithreading es meramente aparente. Para que un hilo sea elegible para ser ejecutado, este debe de estar en estado en ejecución (runnable), si se encuentra en cualquier otro estado no podrá ser elegible por el programador de hilos. Es importante tomar en cuenta que...

"El orden en que un hilo en estado de ejecución es escogido por el programador de hilos no es garantizado".

...aunque no podemos controlar al programador de hilos, en algunas ocasiones podemos influenciarlo mandando a llamar algunos métodos contenidos en la clase java.lang.Thread.


Los métodos de la clase java.lang.Thread::

Algunos métodos de esta clase nos pueden ayudar a influenciar al programador de hilos a tomar una decisión sobre qué hilo ejecutar en qué momento. Los métodos son los siguientes:

+ public static void sleep(long milisegundos) throws InterruptedException
+ public static void yield()
+ public final void join() throws InterruptedException
+ public final void setPriority(int nuevaPrioridad)

Nota: el método sleep() y join() tienen versiones sobrecargadas que no hemos mencionado.

Algunos métodos de la clase java.lang.Object::

Recordemos que toda clase en Java hereda de la clase Object, por lo tanto, cualquier objeto de cualquier tipo tiene todos los métodos de la clase Object por defecto. En este caso analizaremos algunos de ellos que nos son útiles en el manejo de hilos:

+ public final void wait() throws InterruptedException
+ public final void notify()
+ public final void notifyAll()

El método wait() define 3 versiones sobrecargadas, incluyendo la mencionada anteriormente.

Antes de mencionar el comportamiento de los métodos anteriormente mencionados, analicemos algunos estados más en los que un hilo se puede encontrar y sus respectivas transiciones.

Estados de los hilos y transiciones::

Ya hemos visto 3 estados de los hilos - nuevo, en ejecución y muerto - pero hay algunos otros bastante importantes. Analicemos cada uno de ellos:

- Nuevo (new): Este es el estado en que un hilo se encuentra después de que un objeto de la clase Thread ha sido instanciado pero antes de que el método start() sea llamado.

- En ejecución (runnable): Este es el estado en que un hilo puede ser elegido para ser ejecutado por el programador de hilos pero aún no está corriendo en el procesador. Se obtiene este estado inmediatamente después de hacer la llamada al método start() de una instancia de la clase Thread.

- Ejecutándose (running): Este es el estado en el que el hilo está realizando lo que debe de hacer, es decir, está realizando el trabajo para el cual fue diseñado.

- Esperando/bloqueado/dormido (waiting/blocked/sleeping): Es el estado en el cual el hilo está vivo aún pero no es elegible para ser ejecutado,es decir, no está en ejecución pero puede estarlo nuevamente si algún evento en particular sucede. Por ejemplo, un hilo puede estar durmiendo por que en el código se le ha pedido que lo haga pero pasa a estado en ejecución cuando el tiempo que se le pidió dormir ha expirado.

- Muerto (dead): Un hilo está muerto cuando se han completado todos los procesos y operaciones contenidos en el método run(). Una vez que un hilo ha muerto NO puede volver nunca a estar vivo, recordemos que no es posible llamar al método start() más de una vez para un solo hilo.

Prevenir la ejecución de un hilo::

:Hilo Durmiendo (sleeping):

El método sleep() es un método estático de la clase Thread. Generalmente lo usamos en el código para pausar un poco la ejecución de un proceso en particular forzándolo a dormir durante un tiempo determinado. Para forzar un hilo a dormir podemos usar un código parecido a lo siguiente:

try{
Thread.sleep(5*60*1000); //Duerme durante 5 minutos
}catch(InterruptedException ex){}

Normalmente cuando llamamos al método sleep() encerramos el código en un try/catch debido a que dicho método arroja una excepción.

El hecho de que un hilo deje de dormir, no significa que volverá a estar ejecutándose al momento de despertar, el tiempo especificado dentro del método sleep() es el mínimo de tiempo que un hilo debe de dormir, aunque puede ser mayor. De igual manera se debe de tomar en cuenta que el método sleep() es estático, es decir, solo hay uno para toda la clase Thread, por lo tanto, un hilo no puede poner a dormir a otro, el método sleep() siempre SIEMPRE afecta al hilo que se encuentra ejecutando al momento de hacer la llamada.

:Prioridades de hilo y el método yield():

Para entender el método yield(), debemos entender las prioridades de los hilos. Un hilo siempre corre con una prioridad, normalmente va de 1 a 10, debido a esto, el programador de hilos generalmente utiliza su programación basada en prioridades. Un hilo de menor prioridad que se encuentra ejecutando usualmente será desplazado al estado en ejecución para que un hilo de mayor prioridad pueda ejecutarse. De cualquier manera, nunca debes de basar el funcionamiento de tu aplicación basado en las prioridades de los hilos.

Para establecer la prioridad de un hilo debemos hacer algo parecido a lo siguiente:

HiloRunnable h = new HiloRunnable();
Thread t = new Thread(h);
t.setPriority(7);
t.start();

Algunas máquinas virtuales no son capaces de reconocer 10 valores diferentes de prioridad, lo que causa un problema al momento de la ejecución, debido a ello, la clase Thread tiene 3 constantes (variables estáticas y finales) que definen un rango de prioridades de hilo:

+ Thread.MIN_PRIORITY (1)
+ Thread.NORM_PRIORITY (5)
+ Thread.MAX_PRIORITY (10)

:El método yield():

El método yield() tiene la función de hacer que un hilo que se está ejecutando de regreso al estado en ejecución(runnable) para permitir que otros hilos de la misma prioridad puedan ejecutarse. Sin embargo, el funcionamiento de este método (al igual que de los hilos en general) no está garantizado, puede que después de que se establezca un hilo por medio del método yield() a su estado en ejecución(runnable), éste vuelva a ser elegido para ejecutarse. El método yield() nunca causará que un hilo pase a estado de espera/bloqueado/dormido, simplemente pasa de ejecutándose(running) a en ejecución(runnable).

:El método join():

El método no estático join() permite al hilo "formarse en la cola de espera" de otro hilo. Si tienes un hilo B que no puede comenzar a ejecutarse hasta que se complete el proceso del hilo A, entonces querrás que B se forme en la cola de espera de A. Esto significa que B nunca podrá ejecutarse si A no completa su proceso. En código se utiliza así:

Thread t = new Thread();
t.start();
t.join();

Existe una versión sobrecargada de join() que puede incluir el tiempo en milisegundos, por ejemplo si llamamos a t.join(5000), significa que el hilo que queremos ejecutar debe esperar a que el hilo que se está ejecutando en este momento termine, pero si tarda más de 5 segundos entonces debe dejar de esperar y entrar en estado de ejecución(runnable).

Hasta aquí le dejamos con la tercera parte...

Más sobre programación en Java aquí.

Creando un Space Invaders con Java

http://balusoft.wordpress.com/2010/09/26/creando-un-space-invaders-con-java/



Parte 0.- Introduccion
Parte 1.-La ventana
Parte 2.- Cierre debido
Parte 3.- Primeros pegotes en la ventana
Parte 4.- Primeras imagenes
Parte 5.- Optimizando la carga de imagenes
Parte 6.- Optimizando aun mas la carga de imagenes
Parte 7.- Bucle principal
Parte 8.- Limpiando la basura
Parte 9.- Controlando el caos
Parte 10.- Mas lento que el ojo
Parte 11.- Doble bufer automatico
Parte 12.- Medicion del rendimiento
Parte 13.- Reorganizacion de codigo  Java
Parte 14.- Fotogramas
Parte 15.- Fotogramas II
Parte 16.- El jugador
Parte 17.- Controlando el jugador
Parte 18.- Disparos
Parte 19.- Mas disparos- Bombas de fragmentacion
Parte 20.- Deteccion de colisiones
Parte 21.- Barra de estado
Parte 22.- Puntuacion
Parte 23.- Muriendo
Parte 24.- La venganza de los monstruos
Parte 25.- Fondo con Scroll
Parte 26.- Reaparicion de monstruos
Parte 27.- Sonido sencillo
Parte 28.- Corrigiendo los fallos de sonido
Parte 29.- Pequeñas optimizaciones

Java 2D game graphics Perfomance

What you want to do is to create a canvas component with a BufferStrategy and render to that, the code below should show you how that works, I've extracted the code from my self written Engine over here.
Performance solely depends on the stuff you want to draw, my games mostly use images. With around 1500 of them I'm still above 200 FPS at 480x480. And with just 100 images I'm hitting 6k FPS when disabling the frame limiting.
A small game (this one has around 120 images at once at the screen) I've created can be found here (yes the approach below also works fine as an applet.).



import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class Test extends Thread {
    private boolean isRunning = true;
    private Canvas canvas;
    private BufferStrategy strategy;
    private BufferedImage background;
    private Graphics2D backgroundGraphics;
    private Graphics2D graphics;
    private JFrame frame;
    private int width = 320;
    private int height = 240;
    private int scale = 1;
    private GraphicsConfiguration config =
                GraphicsEnvironment.getLocalGraphicsEnvironment()
                        .getDefaultScreenDevice()
                        .getDefaultConfiguration();

    // create a hardware accelerated image
    public final BufferedImage create(final int width, final int height,
                final boolean alpha) {
        return config.createCompatibleImage(width, height, alpha
                        ? Transparency.TRANSLUCENT : Transparency.OPAQUE);
    }

    // Setup
    public Test() {
        // JFrame
        frame = new JFrame();
        frame.addWindowListener(new FrameClose());
        frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        frame.setSize(width * scale, height * scale);
        frame.setVisible(true);

        // Canvas
        canvas = new Canvas(config);
        canvas.setSize(width * scale, height * scale);
        frame.add(canvas, 0);

        // Background & Buffer
        background = create(width, height, false);
        canvas.createBufferStrategy(2);
        do {
                strategy = canvas.getBufferStrategy();
        } while (strategy == null);
        start();
    }

    private class FrameClose extends WindowAdapter {
        @Override
        public void windowClosing(final WindowEvent e) {
                isRunning = false;
        }
    }

    // Screen and buffer stuff
    private Graphics2D getBuffer() {
        if (graphics == null) {
                try {
                        graphics = (Graphics2D) strategy.getDrawGraphics();
                } catch (IllegalStateException e) {
                        return null;
                }
        }
        return graphics;
    }

    private boolean updateScreen() {
        graphics.dispose();
        graphics = null;
        try {
                strategy.show();
                Toolkit.getDefaultToolkit().sync();
                return (!strategy.contentsLost());

        } catch (NullPointerException e) {
                return true;

        } catch (IllegalStateException e) {
                return true;
        }
    }

    public void run() {
        backgroundGraphics = (Graphics2D) background.getGraphics();
        long fpsWait = (long) (1.0 / 30 * 1000);
        main: while (isRunning) {
                long renderStart = System.nanoTime();
                updateGame();

                // Update Graphics
                do {
                        Graphics2D bg = getBuffer();
                        if (!isRunning) {
                                break main;
                        }
                        renderGame(backgroundGraphics); // this calls your draw method
                        // thingy
                        if (scale != 1) {
                                bg.drawImage(background, 0, 0, width * scale, height
                                                * scale, 0, 0, width, height, null);
                        } else {
                                bg.drawImage(background, 0, 0, null);
                        }
                        bg.dispose();
                } while (!updateScreen());

                // Better do some FPS limiting here
                long renderTime = (System.nanoTime() - renderStart) / 1000000;
                try {
                        Thread.sleep(Math.max(0, fpsWait - renderTime));
                } catch (InterruptedException e) {
                        Thread.interrupted();
                        break;
                }
                renderTime = (System.nanoTime() - renderStart) / 1000000;

        }
        frame.dispose();
    }

    public void updateGame() {
        // update game logic here
    }

    public void renderGame(Graphics2D g) {
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, width, height);
    }

    public static void main(final String args[]) {
        new Test();
    }
}

Trail: 2D Graphics

http://docs.oracle.com/javase/tutorial/2d/index.html




Overview of the Java 2D Graphics API introduces the key Java 2D concepts and describes the Java 2D rendering model. This lesson is more conceptual than other lessons of this trail, it enables you to get deep into basic notions and classes descriptions.
Trail icon Getting started with Graphics uses a developed example to show you how to obtain a Graphics object and use it for common graphics rendering tasks.
Trail icon Working with Geometry teaches you how to use APIs to draw graphic primitives and arbitrary shapes, and how to apply fancy strokes and fill styles.
Trail icon Working with Text APIs shows you how to effectively use text APIs, including how to create a Font object with desired attributes, measure text, and determine the names of the fonts available on your system.
Trail icon Working with Images explains how to create a BufferedImage object, perform image-filtering operations, and draw on an image.
Trail icon Printing teaches you how to render 2D graphics to a printer, print complex documents, and use Print Services.
Trail icon Advanced topics in Java 2D explains how to perform transformations, clip the drawing region, composite overlapping graphics, specify rendering preferences, and control rendering quality.

Java Game Programming 2D Graphics, Java2D and Images

http://www3.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html




1.  Revisit java.awt.Graphics for Custom Drawing
1.1  Template for Custom Drawing
2.  Java 2D API & Graphics2D
2.1  java.awt.Graphics2D
2.2  Affine Transform (java.awt.geom.AffineTransform)
2.3  Geometric Primitives and Shapes
2.4  Point2D and its Subclasses Point, Point2D.Double and Point2D.Float (Advanced)
2.5  Interface java.awt.Shape
2.6  Stroke, Paint and Composite Attributes
3.  Working with Bitmap Images
3.1  Loading Images
3.2  drawImage()
3.3  Image Affine Transforms
3.4  Image Filtering Operations
3.5  Animating Image Frames
4.  High Performance Graphics
4.1  Full-Screen Display Mode (JDK 1.4)
4.2  Rendering to the Display & Double Buffering
4.3  Splash Screen

Gráficos - Tutorial de Java

http://www.fismat.umich.mx/computacion/notas/parte15/cap15-1.html

  1. El Sistema de Coordenadas
  2. Pintando con AWT
  3. Pintando con Swing
  4. La clase Graphics
  5. Animación
  6. Uso Avanzado de Imágenes