jueves, 10 de noviembre de 2011

Optimizar imágenes PNG en Linux

Hola.

Resulta que necesitaba utilizar una gran cantidad imágenes PNG en una aplicación por el rollo de las transparencias y tan solo 10 de estas imágenes pesaban 37MiB, después de la compresión: 8.5MiB.

Buscando un poco te encuentras con bastantes aplicaciones que se dedican a ¿comprimir?/cuantizar/optimizar imágenes en formato PNG, pero la única aplicación que reducía el tamaño en disco así de bien y sin que se notaran grandes cambios (37MiB->8.5MiB) fue pngnq.

Primero vamos a instalarlo, si te encuentras en Debian o derivados:
$ sudo apt-get install pngnq
En la página recomiendan utilizarlo junto a pngcrush de esta forma:
pngnq -n 256 image.png && pngcrush image-nq8.png smallimage.png
he intentado utilizar la línea de arriba, pero obtengo los mismos resultados sin pngcrush, entonces yo lo utilizo así:
$ pngnq image.png -d directorioSalida
lo que genera un nueva imagen llamada image-nq8.png en el directorio especificado.

Pero si como yo necesitan realizar el mismo proceso sobre muchas imágenes y además quieren mantener los nombres de las imágenes sin el -nq8 este script medio cutre, es el primero que hago en python les podría ayudar:

#!/usr/bin/python

import sys
import os
import glob

from subprocess import Popen, PIPE

def check_execs(*progs):
    """Check if the programs are installed, if not exit and report."""
    for prog in progs:
        try:
            Popen([prog, '--help'], stdout=PIPE, stderr=PIPE)
        except OSError:
            msg = 'The {0} program is necessary to run this script'.format(prog)
            sys.exit(msg)
    return


def listDirectory(directory, fileExt):                                       

 directorioOriginal = os.getcwd()
 directorio = os.path.join(os.pardir, directory)

 if os.path.isdir(directorio):
  os.chdir(directorio)
  lista = glob.glob("*."+fileExt)
  os.chdir(directorioOriginal)
  return lista

def renameImagePngnq(image, directory):

 currentDir = os.getcwd();
 os.chdir(os.path.join(os.pardir, directory))
 (name, extension) = os.path.splitext(image)

 if extension == ".png":
  newName = name[:-4] + extension
  os.rename(image, newName)

 os.chdir(currentDir)

 
check_execs("pngnq")

# Obteniendo directorio
path = os.getcwd()
if len(sys.argv) == 2:
 path = sys.argv[1]

# Obteniendo lista de archivos
lista = listDirectory(path, "png")

# creando directorio de salida
out = path + "/optimizadas"
if not os.path.exists(out):
  os.mkdir(out)

os.chdir(path)

for imagen in lista:
 os.system("pngnq " + imagen + " -v -d " + out)
 print "\n\n"

print "Renombrando ficheros..." 
os.chdir(out)
for img_nq8 in listDirectory(out, "png"):
 renameImagePngnq(img_nq8, out)
 
print "Bye..." 
lo guardamos con un nombre creativo como optimiza_png.py, le damos permisos de ejecución y lo ejecutamos de la siguiente forma:
$ chmod +x optimiza_png.py
$ ./optimiza.png /directorio/con/imagenes/png
si omitimos el segundo parámetro el directorio que tomará por defecto para buscar imágenes png será el directorio donde estamos ejecutando el script. El script creará una carpeta llamada optimizadas con las imágenes procesadas por pngnq.

viernes, 4 de noviembre de 2011

Instalar JEE con Glassfish en Debian

Hola.

Vamos a instalar JEE (Java Enterprise Edition) con Glassfish para comenzar a ver de que van los JSP, Servficios Web...

Primero descargamos el paquete que nos convenga de la página oficial, por ejemplo elegimos Java EE 6 Development Kit Bundles without JDK/Java EE 6 SDK Update 3 ya que viene con GlassFish Open Source Edition 3.x.x y después seleccionamos java_ee_sdk-6u3-unix-ml.sh (multilenguaje).

Damos permisos de ejecución e instalamos:
$ chmod +x java_ee_sdk-6u3-unix-ml.sh
$ sh java_ee_sdk-6u3-unix-ml.sh
en el asistente elegimos Instalación típica (en Instalación personalizda podemos configurar una instalación existente) y el directorio de instalación sugerido es en la carpeta personal (por ejemplo /home/oscar/glassfish3). Si todo va bien al terminar la instalación tendremos configurado Glassfish, en el puerto 4848 para administración y el 8080 para exponer aplicaciones web (si ya tienes alguno de estos puertos ocupados, entonces elige la opción de Instalación personalizada para asignar puertos).
Para parar e iniciar Glassfish debemos ejecutar los siguientes comandos:
$ /home/TU_USUARIO/glassfish3/bin/asadmin stop-domain
$ /home/TU_USUARIO/glassfish3/bin/asadmin start-domain
pero como eso no nos gusta mejor creamos un script en /etc/init.d/, entonces hacemos lo siguiente:
# nano /etc/init.d/glassfish
del siguiente script modificamos la línea asadmin="/home/oscar/glassfish3/bin/asadmin" según nuestra instalación.
#!/bin/bash

asadmin="/home/oscar/glassfish3/bin/asadmin"

case $1 in
start)
sh $asadmin start-domain
;;
stop)
sh $asadmin stop-domain
;;
restart)
sh $asadmin restart-domain
;;
*)
#Default case: restart de daemon
sh $asadmin restart-domain
;;
esac
exit 0
guardamos, damos permisos de ejecución y probamos:
# chmod +x /etc/init.d/glassfish
# service glassfish stop
# service glassfish start
# service glassfish restart
y listo.

martes, 1 de noviembre de 2011

Habilitar/deshabilitar componentes de un Panel en Java

Hola.

En ocasiones sucede que necesitamos deshabilitar todos los componentes de un JPanel o un JFrame por alguna razón. Además tenemos botones, etiquetas, sliders, cajas de texto... y tenemos que hacer por cada componente setEnable(true/false), pero como buenos programadores esa opción no nos agrada, así que buscamos y el buen Google nos da la solución rápidamente:

@Override
public void setEnabled(boolean en) {
    super.setEnabled(en);
    setComponentsEnabled(this, en);
}
private void setComponentsEnabled(java.awt.Container c, boolean en) {
    Component[] components = c.getComponents();
    for (Component comp: components) {
        if (comp instanceof java.awt.Container)
            setComponentsEnabled((java.awt.Container) comp, en);
        comp.setEnabled(en);
    }
}

esto lo que hace es sobreescribir el método setEnabled() del componente de tal forma que cuando se llame al método primero se activará/desactivará el propio componente y posteriormente habilita/deshabilita todos los componentes en él con la llamada a setComponentsEnabled.

Pero esto de pegar el par de métodos en cada componente como que no parece lo mejor, porque no mejor hacer lo siguiente:

public static void setEnableContainer(Container c, boolean band) {
        
 Component[] components = c.getComponents();
 c.setEnabled(band);
 for(int i = 0; i < components.length; i++){            
  components[i].setEnabled(band);
  
  if(components[i] instanceof Container){
   setEnableContainer((Container)components[i], band);
  }
  
 }        
} 
 así podemos dejar el método digamos en una clase SwingUtils y cuando necesitemos habilitar/deshabilitar un componente y todos sus hijos únicamente haríamos una llamada así:

SwingUtils.setEnableContainer(miComponente, true);
SwingUtils.setEnableContainer(miComponente, false); 

y listo.

SwingUtils.java

lunes, 31 de octubre de 2011

Problema de dependencias "Cannot compile against a module..." en NetBeans Platform

Hola.

En la semana me enteré de un componente curioso llamado Sticky Note vía el blog de Geertjan e intenté ejecutar el ejemplo de Geertjan:
como sea, el caso es que intenté compilar su ejemplo para probarlo y la sorpresa esta vez fue algo como esto:

Cannot compile against a module: .....\org-netbeans-modules... org-netbeans-api-visual.jar because of dependency: org-netbeans-api-visual.jar > 3.x.x

y me enviaba a alguna parte del archivo build.xml [harness]. Además de que este problema se presentaba con cada dependencia en el módulo.

Pues resulta que la solución es muy sencilla, vamos nuestro proyecto o módulo (Ctrl+1) click derecho sobre él -> Properties -> Libreries -> Modules Dependencies y eliminamos todas las dependencias y las volvemos a agregar, damos aceptar, Clean and Build All y listo, ahora si a probar la Sticky Note Sidebar.

Otra vez un problema que se soluciona fácilmente, pero lo pongo porque me tardé un buen rato para solucionarlo.

Fuente.


Instalar JDK 7 en Debian Squeeze

Hola.

Recientemente leí en el blog de Geertjan algunas de las bondades del NetBeans 7.1 y cuando lo estaba instalando me dí cuenta que tenía funcionando el jdk 6 de sun que bruto, a qué tiempo de que lo liberaron. Y bueno, los pasos son los siguientes:

Primero descargamos los binarios del JDK 7 de la página oficial (por ejemplo Linux x64 - Compressed Binary).

después descomprimos en /usr/local:
sudo tar zxvf jdk-7-linux-x64.tar.gz -C /usr/local
agregamos los enlaces simbólicos java y javac al sistema de alternativas de Debian:
sudo update-alternatives --install /usr/bin/java java /usr/local/jdk1.7.0/bin/java 1 
sudo update-alternatives --install /usr/bin/javac javac /usr/local/jdk1.7.0/bin/javac 1 
ahora si podemos elegir con que alternativa de java y javac trabajar:
sudo update-alternatives --config java
sudo update-alternatives --config javac
veremos algo como esto:



verificamos las versiones de java y javac con:
java -version
javac -version 
ahora editamos el archivo /etc/profile para indicar al sistema la ruta a seguir para encontrar java:
# nano /etc/profile
pegamos la siguiente línea al final del archivo:
JAVA_HOME=$JAVA_HOME:/usr/local/jdk1.7.0/bin/java 
guardamos, cerramos y  probamos:
# source /etc/profile 
# echo $JAVA_HOME
:/usr/local/jdk1.7.0/bin/java
y listo.

Cambiar título de la ventana principal en NetBeans Platform

Hola.

Podría parecer una tontería eso de cambiar el título de una ventana, pero si estás comenzando a ver de que va esto de la Plataforma NetBeans te puede ser útil el siguiente tip:
// Only change the window title when all the UI components are fully loaded.
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
    @Override
    public void run() {
       WindowManager.getDefault().getMainWindow().setTitle(windowTitle);
    }
});

ese trozo de código lo puedes copiar por ejemplo en el constructurtor de tu TopComponent y listo.

Fuente.

domingo, 30 de octubre de 2011

Problema "Java heap space" en aplicación Netbeans Platform

Hola.

En estos días he estado desarrollando sobre Netbeans Platform porque hace magia  y el caso es que mientras ejecuto mi proyecto desde Netbeans IDE no existe problema alguno, entonces piensas: voy a generar mi instalador y a probar lo que llevo a ver si de verdad sirve esa opción que dice Package as -> Installers, así, ejecutas tu aplicación y se congela/traba/valequeso y no entiendes porque si todo iba tan bien. En este punto como buenos programadores que somos ¡ajá!, sícomo no recordamos las leyes de Murphy y mejor ejecutamos desde terminal para llevarnos la siguiente sorpresa:


java.lang.OutOfMemoryError: Java heap space

Googleando un poco nos enteramos que este error se produce cuando la JVM se queda sin memoria (de almacenamiento dinámico/ de intercambio) y además que por default el tamaño de la memoria es de 64MB (sobre Java 6). La forma de asignar tamaño a la memoria es con los siguientes parámetros de la JVM:
-Xms128m  // Como mínimo 128 MB
-Xmx512m  // Como máximo 512 MB
-Xmx1G    // Como máximo 1 GB

esto solo es parte de lo que necesitamos ya que el usuario no va a ejecutar la aplicación desde terminal pasándole algunos de los argumentos de arriba.
Buscando otro poco encontramos que la solución es modificar el script de creación Build Script que se encuentra en (Ctrl+1) Projects -> MiProyecto -> Important Files -> Build Script o en el directorio del proyecto MiProyecto -> build.xml, en este momento tenemos algo como esto:
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
<!-- for some information on what you could do (e.g. targets to override). -->
<!-- If you delete this file and reopen the project it will be recreated. -->
<project name="MiProyecto" basedir=".">
    <description>Builds the module suite MiProyecto.</description>
    <import file="nbproject/build-impl.xml"/>    
</project> 
y agregamos las siguientes líneas

<!-- Modifies the default settings for JVM (ANTES DEL CIERRE DE la etiqueta project)-->
<target name="build-launchers" depends="suite.build-launchers">
<replace file="build/launcher/etc/${app.name}.conf" token="--branding miproyecto -J-Xms24m -J-Xmx64m" value="--branding miproyecto -J-Xms128m -J-Xmx512m"/>
</target>
<!-- Modifies the default settings for JVM -->

obviamente deben cambiar miproyecto por el nombre de su proyecto (en minúculas), además pueden cambiar -J-Xms128m -J-Xmx512m según sus necesidades. Ahora sí, generamos instaladores, ejecutamos nuestra aplicación y problema resuelto.

También podría interesarnos asignar tamaño a la memoria cuando ejecutamos nuestra aplicación desde NetBeans IDE:

How to pass command line arguments to a NetBeans Platform application when run inside the IDE

 

domingo, 11 de septiembre de 2011

Trabajando lo básico de SVN con NetBeans


Hola.

En esta ocasión vamos a trabajar con SVN desde NetBeans.

Primero necesitamos tener instalado y configurado SVN en el servidor, esto es, haber creado un repositorio. Además requerimos NetBeans y SVN en el cliente. Los despistados usuarios de windows necesitan especificarle al NB donde está el svn.exe.

Creamos un repositorio (en el servidor) para alojar nuestro proyecto:
$ svnadmin create /home/USUARIO/repositorioNBPrueba/
$ mkdir proyectoNBPrueba
$ mkdir proyectoNBPrueba/branches
$ mkdir proyectoNBPrueba/tags
$ mkdir proyectoNBPrueba/trunk
# svn import /home/USUARIO/proyectoNBPrueba/ file://localhost/home/USUARIO/repositorioNBPrueba  -m "Mi primer import"
# chmod -R g+w /home/USUARIO/repositorioNBPrueba/*
ahora creamos un proyecto en NetBeans, así que vamos a New Project -> Java -> Java Application y le damos algún nombre creativo como JavaApplicationSVN.

Lo siguiente que vamos a realizar es un import del proyecto que acabamos de crear, así que sobre la ventana de proyectos del NetBeans (Ctrl+1) ubicamos Java Application, damos click derecho -> Versioning -> Import into Subversion Repository, NB nos muestra un asistente para el import donde nos pide información acerca de la ubicación del repositorio, podemos utilizar por ejemplo el protocolo svn+ssh de tal manera que en Repository URL escribimos algo como esto:
svn+ssh://DOMINIO.ALGO/home/USUARIO/repositorioNBPrueba/trunk 
¿por qué trunk, quizás debean echarle un ojo a las Buenas Prácticas de Gestión de Versiones con Subversion, lo siguiente es llenar los campos User y Password, click en Next, escribimos un pequeño comentario en Specify the Message, Next y observamos los archivos a compromoter que se ven de color verde. que indica que esos archivos han sido localmente agregados, damos click en Finish y ya tenemos nuestro proyecto en el repositorio de Subversion.

Ahora modificamos el main agregando alguna línea:
System.out.println("Modificando una clase..."); 
guardamos y notamos que la clase se pone de color azul que indica que el archivo ha sido localmente modificado, entonces hacemos click derecho sobre la clase (en la ventana de proyectos de NB) -> Subversion -> Show Changes y vemos algo como lo siguiente:


así que damos doble click sobre JavaApplicationSVN.java para ver algo como esto:



vemos del lado izquierdo el código que corresponde al repositorio (inisisto, en el servidor) y del lado derecho el código local. Además notamos que la línea que añadimos está en verde, existen tres tipos de cambios que muestra este editor:

   Azul  Indica líneas que han sido cambiadas desde la versión anterior.
   Verde  Indica líneas que han sido agregadas desde la versión anterior.
   Rojo  Indica líneas que han sido eliminadas desde la versión anterior.

y por otra parte tenemos dos operaciones importantes:

update all icon Update All Actualiza todos los archivos seleccionados desde el repositorio.
Commit all icon Commit All Permite compremeter cambios locales al repositorio.


en este caso vamos a realizar la operación de Commit para subir nuestros cambios al repositorio. Damos click en Commit all icon y escribimos un comentario sobre la operación, listo, ya hemos subido nuestros cambios al repositorio. Aunque antes de realizar operaciones de commit es recomendable realizar un update, o sea bajar primero los cambios que probablemente haya subido un integrante de nuestro equipo de desarrollo y posteriormente subir los nuestros, esto para evitar conflictos cuando dos integrantes están modificando la misma clase.

Todo lo anterior ha sido para subir nuestro proyecto nuevo al repositorio, pero suponiendo que estamos trabajando en equipo y que nosotros hacemos el primer import ¿qué pasa para el resto del equipo?, ¿cómo bajan lo que subimos?. Pues esto es realmente sencillo:

Team -> Subversion -> Checkout, en Repository URL escribimos algo como esto:
svn+ssh://DOMINIO.ALGO/home/USUARIO/repositorioNBPrueba/trunk
llenamos los campos User y Password, click en Next, en Local Folder seleccionamos la ubicación donde se guardará el proyecto, click en Finish y veremos algo como esto:

elegimos Open Project y listo, ya tenemos una copia del proyecto.

Hasta aquí lo básico de SVN con NB, pero nada mejor que Guided Tour of Subversion para profundizar en el tema.


viernes, 9 de septiembre de 2011

Lo básico de Subversion en Debian Squeeze

Hola. Subversion (SVN) es un sistema de control de versiones que a los programadores nos hace el desarrollo de una aplicación un poco más sencillo ya que cuentas con un respaldo de tu proyecto, tienes versiones de tu proyecto, ya no hay pretextos para el trabajo en equipo.

Este post sirve de recordatorio rápido sobre lo básico de SVN, hasta abajo dejo los enlaces en los que me basé por si alguien quiere profundizar en el tema.

Primero vamos a instalar SVN en nuestro servidor con Debian Squeeze:

# apt-get install subversion
ahora creamos el repositorio:
$ mkdir /home/USUARIO/repositorio
$ svnadmin create /home/USUARIO/repositorio/
asignamos permisos al repositorio:
# addgroup desarrollo
# adduser USUARIO desarrollo
# chown -R www-data:desarrollo /home/USUARIO/repositorio/*
# chmod -R g+w /home/USUARIO/repositorio/*
preparamos la carpeta del proyecto para nuestro primer import:
$ mkdir /home/USUARIO/proyecto
$ mkdir /home/USUARIO/proyecto/branches
$ mkdir /home/USUARIO/proyecto/tags
$ mkdir /home/USUARIO/proyecto/trunk
creamos Hola Mundo SVN:
$ nano /home/USUARIO/proyecto/trunk/HolaMundoSVN.java
le ponemos cualquier cosa y guardamos:
public class HolaMundoSVN{
 
 public static void main(String ... args){
  System.out.println("Hola mundo de SVN"); 
 }
  
}
hacemos nuestro primer import:
svn import /home/USUARIO/proyecto/ file://localhost/home/USUARIO/repositorio  -m "Mi primer import"
y debemos ver algo como esto:
Añadiendo      /home/USUARIO/proyecto/trunk
Añadiendo      /home/USUARIO/proyecto/trunk/HolaMundoSVN.java
Añadiendo      /home/USUARIO/proyecto/branches
Añadiendo      /home/USUARIO/proyecto/tags

Commit de la revisión 1.

Hasta aquí todo se hizo en el servidor, ahora vamos a realizar un checkout en nuestra máquina local, osea bajarnos el proyecto:
$ mkdir /home/USUARIO_LOCAL/CopiaProyecto
$ svn co svn+ssh://USUARIO@DOMINIO.ALGO/home/USUARIO/repositorio/ /home/USUARIO_LOCAL/CopiaProyecto/
introducimos el password y el servidor debería responder algo como esto:
A     /home/USUARIO_LOCAL/CopiaProyecto/trunk
A     /home/USUARIO_LOCAL/CopiaProyecto/trunk/HolaMundoSVN.java
A     /home/USUARIO_LOCAL/CopiaProyecto/branches
A     /home/USUARIO_LOCAL/CopiaProyecto/tags
Revisión obtenida: 1

Hace falta realizar la operación de commit (comprometer cambios, subir cambios hechos de manera local al servidor):
$ svn commit -m "Comentario sobre lo añadido/modificado"
Si llegamos a tener un problema como este:
Enviando       trunk/HolaMundoSVN.java
Transmitiendo contenido de archivos .svn: Falló el commit (detalles a continuación):
svn: attempt to write a readonly database
svn: attempt to write a readonly database
ejecutamos lo siguiente en el servidor:
# chown www-data:desarrollo repositorio/db/rep-cache.db
Y por último vamos a hacer un update (actualizar nuestra copia local, bajarnos los cambios del servidor):
$ svn update
Hasta aquí lo básico, para otro post dejamos conectarnos desde el netbeans, montar una interfaz web para svn, https.

Enlaces relacionados:

Buenas Prácticas de Gestión de Versiones con Subversion
Crear un repositorio Subversion
Instalando un repositorio de Subversion