Como recortar una imagen en Blackberry

Tuve que crear una función para poder “recortar” o “cropear” una imagen en una aplicación blackberry. Para ello hice empleo de los métodos Bitmap.getARGB() y Bitmap.setARGB():

    public static EncodedImage cropImage(EncodedImage image, int width, int height) {
        EncodedImage result = null;
        Bitmap bmp = new Bitmap(width, height);

        Bitmap original = image.getBitmap();

        int x = (original.getWidth() / 2) - (width / 2); // Centre el ancho de la img a recortar
        int y = (original.getHeight() / 2) - (height / 2); // Centre el alto de la img a recortar
        int[] argb = new int[width * height]; 
        original.getARGB(argb, 0, width, x, y, width, height);
        bmp.setARGB(argb, 0, width, 0, 0, width, height);
        result = JPEGEncodedImage.encode(bmp, 100);
        return result;
    }

En este caso en particular, se recorta al centro de la imagen el tamaño deseado. Considerando el código, seria bueno poner algunos controles sobre el tamaño de la imagen a recortar para que no ingresen dimensiones mayores de la imagen origninal. Tambien seria bueno checkear que el contenido sea valido y atrapar excepciones.

[RIM] Redondeo de float y double en 4.5

La clase MathUtilites disponible en el framework the Blackberry 4.5 no tiene disponible el método round() que permitiria redondear un número flotante o double. A diferencia de floor() o ceil(), round toma un valor decimal y si es mayor o igual a  .5 lo redondea al siguiente entero, en caso contrario al entero anterior. Esta “deficiencia” se discutió en los foros oficiales de blackberry: http://supportforums.blackberry.com/t5/Java-Development/Math-round-and-Math-random/m-p/206288Y una de las respuestas en muy interesante y que fue marcada como la solucion a esto. Es simplemente sumar a la variable float o double 0.5, asi:

public static int round(float f)
{
    return (int)(f + 0.5F);
}
public static long round(double d)
{
    return (long)(d + 0.5D);
}

Como verán, éste corrimiento hace que cualquier valor cuyo valor decimal sea inferior a 0.5 se mantenga en el mismo entero. Por ejemplo 3.2 se convertiria en 3.7 y al hacer casting a long o int, el valor devuelto seria 3. Pero cuando el valor decimal es superior o igual a 0.5 todo el valor se mueve al siguiente entero. Por ejemplo 3.7 seria 4.2 por lo tanto el valor “redondeado” seria 4. Esta solución me parecio interesante por su simpleza, aunque uno podria hacer su propia version con “if-else” para hacer el mismo comportamiento.

Abrir FileConnection en modo WRITE

Me parecio interesante y extraño a la vez, que en una aplicación para Blackberry, al intentar abrir un archivo, para escribir en el, utilizando el FileConnection me diera un IllegalModeException cuando hacia lo siguiente:

    FileConnection conn = (FileConnection) Connector.open(path, Connector.WRITE);

Revisando en varios foros me encontre con esta solución. http://discussion.forum.nokia.com/forum/showthread.php?t=65218Básicamente lo que dice es que hay que abrir la conexión sin ningun modo como parametro, es decir:

    FileConnection conn = (FileConnection) Connector.open(path);

Si esto es un bug o algo, viene de la parte de J2ME ya que la solución (del url) aplica para J2mE y tambien aplica para el framework  de Blackberry.

[RIM] Centrando campos en la pantalla

La necesidad de acomodar los objetos en la pantalla, a veces no es tan sencillo, si no se entiendie bien como se pintan los objetos creados con el SDK de RIM para desarrollar aplicaciones para Blackberry usando Java (J2ME). El truco aqui se basa en el anidamiento de managers (verticales y horizontales) segun ocupemos centrar vertical u horizontalmente un objeto ya sea  en relación con la pantalla o con otro objeto de la interfaz. Además, también requerimos saber que “bits” de estilo ocupamos definir durante la creación de los objetos, para poder obtener el resultado deseado.

package helloworld;

import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.container.FullScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;

public class TestScreen extends FullScreen {
	VerticalFieldManager myManager = new VerticalFieldManager(USE_ALL_WIDTH);

	public TestScreen() {
		ButtonField button1 = new ButtonField("Button 1",FIELD_HCENTER);
		ButtonField button2 = new ButtonField("Button 2",FIELD_VCENTER);
		ButtonField button3 = new ButtonField("Button 3",DrawStyle.HCENTER);
		bottomManager.add(button1);
		bottomManager.add(button2);
		bottomManager.add(button3);

		add(bottomManager);
	}

}

centering_fields

En el ejemplo anterior defini un manager vertical, pues deseo que mi botón se centre horizontalmente sobre la pantalla. Lo primero que se debe hacer es decirle al manager que “tome” todo el ancho posible de la pantalla. Luego durante la creación de la instancia del boton, debo definirle un bit de estilo, en este caso el FIELD_HCENTER, que le solicita al boton que se centre horizontalmente sobre su manager. Al botón dos, por ejemplo, se le definió el bit de estilo FIELD_VCENTER, que le pide que se centre verticalmente sobre el espacio asignado por el manager, que como verán en la imagen del simulador, es irrelevante o más bien imperceptible pues el boton no tiene espacio arriba o abajo para hacerlo. También podriamos estar tentados de usar el DrawStyle.HCENTER pero esto solo aplica para texto.

Primeros pasos desarrollando para Blackberry

Me ha tocado iniciar a caminar por el desarrollo para terminales móviles de Blackberry. Lo primero bueno que encontré es que es basado en JavaME y ya que tengo conocimientos en dicha plataforma, no debiera ser mucho problema. El primer obstaculo que me encontré, es que no hay disponible libros para desarrollar en Blackberry o RIM (por sus siglas en inglés Research in Motion, empresa que desarrolló el Blackberry). Aunque hay buena documentación en el sitio oficial para desarrolladores de BlackBerry, los PDFs muestran extractos de código, que si bien sirven, a veces uno ocupa el contexto para comprender mejor como utilizar uno u otro componente. Por ejemplo, queria hacer una pantalla que desplegara un menú. La documentación decía que hay que utilizar el objeto MenuItem y luego agregarlo… pero no decia a que. Si ponía en Google “menuitem blackberry” me encontraba entradas sobre algo llamado ApplicationMenuItem que pareciera mas para agregar algo al menú del teléfono y no al menú de mi aplicación. Ahi mas adelante me encontré mas información que me sirvió para poder hacer lo que queria. Primero hay que hacer un objeto tipo MainScreen, ya que es la única clase que permite agregarle Items y crear, ya sea como una anonymous o una inner class los menú items que se ocupen.

	import net.rim.device.api.ui.MenuItem;
	import net.rim.device.api.ui.component.RichTextField;
	import net.rim.device.api.ui.container.MainScreen;
	public class MyMainScreen extends MainScreen {
	  public MyMainScreen() {
	 add(new RichTextField("Main Screen")); // solo para mostrar algo
	 addMenuItem(new MyMenuItem());
	 }
	 private class MyMenuItem extends MenuItem {
	 public MyMenuItem() {
	 super("Menu 1", 110, 10);
	 }
	 public void run() {
	 // hacer algo
	 }
	 }
	}