domingo, 27 de diciembre de 2009

Mi tele lee multimedia

Como indica su fabricante, mi tele lee estos formatos:





























ExtensiónVídeoTamañoKilobits/sAudio
.aviMPEG-4 SP
MPEG-4 ASP
352×288
720×576
384
8000
MPEG layer 2/3
AC3
.mpg
.mpeg
.vob
MPEG-1
MPEG-2
352×288
720×576
1500
9800
MPEG layer 2
LPCM
AC3
.mp4H.264, L2-CIF
H.264, L4-HD
352×288
1920×1080
2000
20000
AAC-LC
AAC-LC

Los tamaños y tasas de bits los he mirado en MPEG-4, y H.264

Me falta hacer una chuleta con las opciones que hay que pasar a FFmpeg para generar estos formatos.

Y probarlos, claro.

viernes, 18 de diciembre de 2009

RCX

Tras profunda exploración del trastero, he re-encontrado mi Robotics Invention System 1.5.
Dentro de esta caja, está el RCX, que es un "ladrillo" amarillo que aloja un microcontrolador con sensores y salidas.

Fue mi regalo de cumpleaños del 2000 o 2001 y me he llevado la desagradable sorpresa de que Lego quitó todas la referencias de su web oficial allá por 2008.

Así que he tenido que ir escarbando:

http://brickos.sourceforge.net/index.html

http://www.mapageweb.umontreal.ca/cousined/lego/

http://www.crynwr.com/lego-robotics/

El RCX se comunica por infrarrojos, pero se habla con los PC a través de una cajita intermedia unida por el puerto serie. El puerto infrarrojo de muchos portátiles no vale, porque Lego usa un protocolo rarito.

Los que tengan un Palm, sí que pueden comunicarse por infrarrojos con el RCX.

domingo, 25 de octubre de 2009

Compilar para Windows desde Ubuntu (II)

En vez de traernos los ejecutables necesarios para la compilación cruzada, podemos traernos los fuentes, y compilarlos.
La ventaja es que podemos tener la última versión, y compilarlos para exactamente la CPU que tengamos (en mi caso, CFLAGS=-march=pentium-m).

Adaptado de la receta de Ramiro.

Nos instalamos algunas dependencias de gcc:
sudo apt-get install flex bison

Algunas dependencias de FFmpeg.
sudo apt-get install texinfo yasm subversion

Y un entorno para poder testear los ejecutables de Windows, sin salir de Linux:
sudo apt-get install wine

Nos preparamos un directorio para bajarnos y compilar el código fuente:
cd "$HOME"
mkdir src
export BASE_PATH="$HOME/src"


Traemos estos ficheros, y los dejamos en el directorio $BASE_PATH:
binutils-2.20.tar.bz2
gcc-core-4.2.4.tar.bz2
mingwrt-3.16-mingw32-dev.tar.gz (from http://sourceforge.net/projects/mingw/files/ under "MinGW Runtime")
w32api-3.13-mingw32-dev.tar.gz (from same site as above under "MinGW API for MS-Windows")
zlib-1.2.3.tar.gz (from http://prdownloads.sourceforge.net/libpng/ )
bzip2-1.0.5.tar.gz (from http://bzip.org/downloads.html )

El compilador cruzado lo instalamos en /usr. Pondrá su cosillas en /usr/bin/i686-mingw32*, sin machacar las del compilador nativo de Ubuntu (que son /usr/bin/i486-linux-gnu*).

Importante:
sudo ln -s /usr/i686-mingw32 /mingw

binutils:
cd "$BASE_PATH"
tar xfvj binutils-2.20.tar.bz2
cd binutils-2.20
mkdir build
cd build
../configure --target=i686-mingw32 --disable-werror --disable-nls --prefix=/usr
make
sudo make install


"runtime" de MinGW:
cd "$BASE_PATH"
sudo tar zxfv mingwrt-3.16-mingw32-dev.tar.gz -C /mingw
sudo tar zxfv w32api-3.13-mingw32-dev.tar.gz -C /mingw


compilador de C:
cd "$BASE_PATH"
tar xfvj gcc-core-4.2.4.tar.bz2
cd gcc-4.2.4
mkdir build
cd build
CFLAGS=-march=pentium-m ../configure --target=i686-mingw32 --disable-nls --prefix=/usr
make
sudo make install


En los entornos GNU, la manera de indicar que queremos usar compilación cruzada, en vez de nativa, es a través de las variables de entorno:
RANLIB=i686-mingw32-ranlib AR=i686-mingw32-ar CC=i686-mingw32-gcc

Compilamos para MinGW algunas bibliotecas de funciones:

zlib:
cd $BASE_PATH
tar zxfv zlib-1.2.3.tar.gz
cd zlib-1.2.3
CFLAGS=-march=pentium-m RANLIB=i686-mingw32-ranlib AR="i686-mingw32-ar rc" CC=i686-mingw32-gcc ./configure --prefix=/mingw
make
sudo make install


bzip2:
cd "$BASE_PATH"
tar zxfv bzip2-1.0.5.tar.gz
cd bzip2-1.0.5
make libbz2.a CFLAGS=-march=pentium-m RANLIB=i686-mingw32-ranlib AR=i686-mingw32-ar CC=i686-mingw32-gcc
sudo cp bzlib.h /mingw/include/
sudo cp libbz2.a /mingw/lib/


Y con esto ya podemos compilar un FFmpeg para MinGW. Aquí la compilación cruzada se indica con --cross-prefix=i686-mingw32- --target-os=mingw32 y la CPU con --arch=pentium-m --cpu=pentium-m:
cd "$BASE_PATH"
mkdir ffmpeg
cd ffmpeg
svn co svn://svn.ffmpeg.org/ffmpeg/trunk svn
mkdir build-win32
cd build-win32
../svn/configure --enable-memalign-hack --cross-prefix=i686-mingw32- --target-os=mingw32 --arch=pentium-m --cpu=pentium-m


Y os preguntaréis, ¿por qué no compilar para MinGW desde MinGW?. Pues porque es más lento. Pero no un poco, sino algo exagerado: diez veces más lento.

martes, 20 de octubre de 2009

Compilar para Windows desde Ubuntu (I)

Tres pasos para crear un entorno en Ubuntu que nos permita compilar para Windows.

Nos traemos el paquete básico para compilar:
sudo apt-get install build-essential

El compilador cruzado, binutils y el "runtime":
sudo apt-get install mingw32 mingw32-binutils mingw32-runtime

Y un entorno para poder testear los ejecutables que compilemos:
sudo apt-get install wine

Podemos intentar compilar FFmpeg:
configure --enable-memalign-hack --cross-prefix=i586-mingw32msvc- --target-os=mingw32 --arch=i686 --cpu=i686

Pero nos da este error:
ERROR: MinGW runtime version must be >= 3.15.

Es que en Ubuntu 9.04 las versiones de los paquetes de compilación cruzada a MinGW son algo antiguas:
dpkg -s mingw32 mingw32-binutils mingw32-runtime |fgrep Version
Version: 4.2.1.dfsg-1ubuntu1
Version: 2.18.50-20080109-1
Version: 3.13-1


FFmpeg tiene la costumbre de exigir la última versión de sus dependencias, con otros programas estos paquetes de Ubuntu nos podrían valer perfectamente.

martes, 25 de agosto de 2009

Cacharricos

En verano, los campos y las bitácoras se agostan. Ya se sabe, las vacaciones es el periodo del año en que conviene no recalentar el cerebro.

Aún así, algo ha caído:
  • Mi querido portátil, ha vuelto a la vida tras sustituirle el disco muerto de 40GB por otro de 160GB. El proceso requirió los correspondientos improrerios a la SGAE, al ver que se llevaba un 25% de la factura. En fin, Ramoncín tiene que ir pagando su hipoteca ...
  • Me quise comprar un PCecico para el salón. Oferta agotada para cuando me acerqué a la tienda, así que me llevé lo más parecido. No tan mono (es semitorre) pero con 1TB de disco.
Como uno gusta de la diversidad, el portátil tiene su Ubuntu 9.04, y el otro tiene Vista (y un Wubi dentro que tengo que configurar).

miércoles, 1 de julio de 2009

Aligerar PDFs

Mensualmente me llega una revista digital en formato PDF.
La mitad de las páginas son anuncios, así que suelo recortarlos con pdftk

Por ejemplo, para dejar sólo las páginas 1, de la 14 a la 24, y de la 26 a la 36:

pdftk MMH20090601.pdf cat 1 14-24 26-36 output MMH20090601-mini.pdf

Con lo cual se queda en la mitad de tamaño:
ls -s1 MMH20090601*
26236 MMH20090601-mini.pdf
48332 MMH20090601.pdf


A los alérgicos a la línea de comando os tranquilizará saber que podéis usar PDFTK Builder

domingo, 21 de junio de 2009

ld09.exe y podmena

Al parar el ordenador me pregunta "¿desea matar a cmd.exe, que tarda mucho?".
¿uh? si no tengo ninguna línea de comando abierta.

Lanzo el Administrador de Tareas y veo multipleas instancias de cmd.exe y un proceso iexplore.exe
Raro, porque yo uso Firefox.

Al intentar ejecutar "regedit" desde Inicio->Ejecutar se reiniciaba el Explorador.
Uf, mala pinta.
Pruebo a ejecutar "regedit" desde el administrador de tareas y también se muere.
Uf, mal rollito seguro.

Tengo gran aprecio al Process Explorer y desde ahí ya puedo lanzar con éxito a regedit.
Nos vamos a
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Current Version\Run

Y lo que canta bastante (porque no me suena de nada) es "ld09.exe"

Google nos da una página en blanco para LD09.exe
http://www.prevx.com/filenames/X1867469537856748618-X1/LD09.EXE.html

Pero la versión en la caché sí es más interesante:
http://209.85.229.132/search?q=cache:L30I0qUVx80J:www.prevx.com/filenames/X1867469537856748618-X1/LD09.EXE.html+ld09&cd=3&hl=es&ct=clnk&gl=es&client=firefox-a

Es un informe muy exhaustivo de lo que hace el virus éste.
Pone lo que hace, pero no cómo quitarlo, ya que la misma página aprovecha para venderte su antivirus.
Me entra la duda ¿serán ellos los autores del virus? A ver si su antivirus es otro virus peor ...

Bueno, en cualquiera caso la descripción de lo que hace me permite deshacer bastante:

Borré
c:\windows\ld09.exe
c:\program files\podmena\podmena.sys
c:\program files\podmena\podmena.dll


Fuí al Panel de Control, y desde el Firewall de Windows, quité al accesso a podmena.
Borré la entrada "ld09.exe" del registro
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Current Version\Run\

Y borre las ramas del registro
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\podmena
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\drv_podmena


Cruzamos dedos (lo más fácil al tocar el registro con tanta inconsciencia es que no arranque) y reiniciamos.

Bueno, superamos el arranque. Aunque seguimos con múltiples cmd.exe e iexplore.exe

Hala, a mirar con más atención a
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Current Version\Run

Ajá: hay un "C:\Program Files\Internet Explorer\Connection Wizard\icwsetup.exe" y no tiene mucho sentido que el ayudante de conexión a internet se ejecute en cada arranque.

Pues nada, borramos a "C:\Program Files\Internet Explorer\Connection Wizard\icwsetup.exe"
y quitamos su entrada de "icwsetup.exe" del registro:
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Current Version\Run\

Y reiniciamos. Pues que si quieres arroz, Catalina.

¡El muy cuco! (usaría otra expresión, pero al crear el blog marqué la casilla de contenido apto para todos públicos).
Resulta que ha vuelto a poner a "C:\Program Files\Internet Explorer\Connection Wizard\icwsetup.exe" como estaba.

Otro intento, cogemos a "notepad.exe" y lo copiamos con otro nombre, casualmente "C:\Program Files\Internet Explorer\Connection Wizard\icwsetup.exe"

Y reiniciamos. Je, je, esta vez sale una bonita ventana de "notepad" al arrancar, y no tenemos ya a los múltiples cmd.exe.

Bueno, aunque el PC sigue malito, ya tenemos controlada la infección.
Otro día toca erradicarla.

domingo, 14 de junio de 2009

Compilar para Windows desde Cygwin (II)

Vamos a compilar a libGD para Windows.

Nos traemos el código fuente:
wget http://www.libgd.org/releases/gd-2.0.36RC1.tar.bz2

Lo desempaquetamos:
tar jxvf gd-2.0.36RC1.tar.bz2

Nos vamos a su directorio:
cd gd-2.0.36RC1

Y le ponemos el parche para aligerar libGD:
patch -p0 < ..patches/libgd.trim.1.diff

Podríamos compilar libpng, libjpeg y freetype desde su código fuente, pero vamos a bajarlos ya compilados desde Mplayer Win32.
Ojo, desempaquetamos cada cosa en su sitio (bibliotecas, includes y scripts de configuración) según la jerarquía de directorios que os comenté.

Lo configuro desactivando la creación de la la bilioteca dinámica, y sólo hará la enlazada estáticamente:

CC="gcc-3" CFLAGS="-mno-cygwin -DNONDLL=1" ./configure --disable-shared --prefix=/mingw --with-png=/mingw --with-freetype=/mingw --with-jpeg=/mingw --without-xpm --without-fontconfig

A construir:
make

Y ya está, sólo falta instalarlo:
make install

viernes, 12 de junio de 2009

Parches

Imagina que modificas el código fuente de alguna utilidad. Cada vez que se libere una nueva versión, tendrás que volver a modificarla.
Pero un virtuoso programador (por ende: vago, orgulloso e impaciente) ideó a patch

Así que primero guardas en un ficherito tus cambios:
diff -u source.c.original source.c > source.diff

Y luego puedes decir a patch que aplique esos cambios a la nueva versión:
patch < source.diff

Y por supuesto no está limitado a cambios en un solo fichero, puedes tener un directorio con la versión inicial, otro directorio con la versión modificada por tí, y luego aplicar los cambios a un tercer directorio.

Por ejemplo, aquí me entretuve en recortar cosillas que no necesitaba de la versión 2.0.36 de libGD, e hize un .diff que bautizaremos como libgd.trim.1.diff.

Cuendo esté disponible la versión 2.0.37, le aplicaré mi parche asi:

cd src/gd-2.0.37
patch -p0 < ..patches/libgd.trim.1.diff

miércoles, 10 de junio de 2009

Tamaño de imágenes

La utilidad de menor tamaño que he encontrado para conocer al ancho y alto de las imágenes (PNG, GIF, JPEG, XPM) es image_size

Trivial de compilar para Cygwin:
gcc image_size.c -s -o image_size

O para Windows:
gcc -mno-cygwin image_size.c -s -o image_size

Para usarlo, basta pasar los nombres de los ficheros, y nos devuelve el nombre y dimensiones de cada uno:
image_size *.png *.gif
demoin.png: 128 128
demoin.gif: 128 128

sábado, 6 de junio de 2009

Compilar para Windows desde Cygwin (I)

Cygwin es una excelente simulación de POSIX sobre Windows, lo que facilita compilar programs que vengan del mundillo Unix.
Aparte de programs para el propio entorno Cygwin, también permite compilar programas "puro-Windows", que no dependan de la biblioteca de funciones cygwin1.dll.

Básicamente, sólo hay que añadir el parámetro "-mno-cygwin" al compilar.

Hay unos pocos paquetes Cygwin que contienen bibliotecas puras de Windows (que procedecen del proyecto MinGW): mingw-runtime, mingw-zlib y mingw-bzip2, más sus versiones -devel para desarrollar.

Estos paquetes se instalan así:
  • /usr/include/mingw/ para los includes
  • /usr/lib/mingw/ para las bibliotecas.
Resulta conveniente que ambos directorios partan de la misma raiz, así que yo tengo un par de enlaces simbólicos:
  • /mingw/include -> /usr/include/mingw/
  • /mingw/lib -> /usr/lib/mingw/
También tengo /mingw/bin para guardar ejecutables puro-Windows o scripts de configuración de las bibliotecas puro-Windows.

Vamos, que ejecuté estos comandos:

mkdir -p /mingw/bin
ln -s /usr/include/mingw/ /mingw/include
ln -s /usr/lib/mingw/ /mingw/lib

martes, 2 de junio de 2009

Jeroglíficos


Mala fama tiene la línea de comando: inescrutable, críptica, y sólo apta para los iniciados en tan oscuro saber.

¿Qúe mejor para perpetuar esa fama que escribir jeroglíficos con comandos? ;-)

Ingredientes:
  • xgawk
  • un tipo de letra adecuado, Greywolf Glyphs
  • un sencillo script, que denominaremos jeroglífico.awk.
El sencillo script es éste, donde en lugar de comentarios he preferido poner "print" para ir mostrando los pasos:

@load gd

BEGIN {
MARGEN = 8
TAM_LETRA = 48
TIPO_LETRA = "GWGLYPTT.ttf"
if (!("GDFONTPATH" in ENVIRON)) {
print "\n¡¡Recuerda definir GDFONTPATH!!\nHaz algo parecido a ...\n"
print "GDFONTPATH=/cygdrive/c/WINDOWS/Fonts/:/usr/X11R6/lib/X11/fonts/TTF/; export GDFONTPATH\n"
print "... y vuelve a lanzarme."
exit
}

print "Averiguamos el ancho que ocupa nuestro texto"
err = gdImageStringFT("", brect, 0, TIPO_LETRA, TAM_LETRA, 0.0, 0, 0, txt)
if (err) {
print err
print "\nEl tipo de letra Greywolf Glyphs está en:"
print "http://greywolf.critter.net/fonts.htm"
exit
}
ancho = brect[2]-brect[6] + MARGEN

print "Averiguamos el trazo más alto y el más bajo del tipo de letra"
err = gdImageStringFT("", brect, 0, TIPO_LETRA, TAM_LETRA, 0.0, 0, 0, "|ÑILMgf_q")
alto = brect[3]-brect[7] + MARGEN
base = -brect[7]

print "Creamos una imagen, del tamaño de nuestro texto"
im = gdImageCreateTrueColor(ancho, alto)

print "Definimos el color marrón"
marron = gdImageColorAllocate(im, 204, 153, 51)

print "Rellenamos de marrón"
gdImageFilledRectangle(im, 0, 0, ancho, alto, marron)

print "Definimos el color lila"
lila = gdImageColorAllocate(im, 128, 0, 255)

print "Dibujamos el texto en lila"
x = MARGEN/2
y = base + MARGEN/2
err=gdImageStringFT(im, brect, lila, TIPO_LETRA, TAM_LETRA, 0.0, x, y, txt)

print "Guardamos el resultado"
gdImagePngName(im, salida)

print "Destruímos la imagen"
gdImageDestroy(im)

print "¡Eso es todo, amigos!"
}


Luego invocamos el comando:
xgawk -f jeroglifico.awk -vtxt="Maravilloso" -vsalida=texto_egipcio.png

Y ya tenemos la imagen.

Bueno, la verdad es que la he recomprimido un poquito más (un 38%), con el comando:
pngcrush.exe -brute texto_egipcio.png texto_egipcio2.png

lunes, 1 de junio de 2009

Termostatos e impaciencia

Ahora que se avecina el verano, no está de más recordar que poner al mínimo el termostato en absoluto acelera que lleguemos a la temperatura de confort.
La causa es que los aparatos de aire acondicionado o están apagados o funcionan a plena potencia (salvo que sean "inverter").

Y lo mismo pasa en invierno: poner al máximo el termostato no hace que lleguemos antes a una temperatura agradable, porque las calderas (todas) o están apagadas o funcionan a plena potencia.

Vamos, que son dispositivos digitales, y el verdadero control de su potencia promedio se hace variando la relación entre el tiempo que permanecen encendidos y el tiempo que están apagados.

martes, 19 de mayo de 2009

Más ancho para las entradas

Ya tenemos todos los GIF ensanchados, ahora hay que cambiar la plantilla de Blogger para los use.

Como he guardado la plantilla antes y después de editarla, puedo usar diff para ver los cambios:

diff -u lineadecomandos_plantilla-2009-05-16\ 1223.xml lineadecomandos_plantilla-2009-05-16\ 1616.xml

--- lineadecomandos_plantilla-2009-05-16 1223.xml 2009-05-16 12:34:06.015625000 +0200
+++ lineadecomandos_plantilla-2009-05-16 1616.xml 2009-05-16 16:53:48.312500000 +0200
@@ -102,15 +102,15 @@
these measurements, the images will also need to change.
*/
#outer-wrapper {
- width:740px;
+ width:960px;
margin:0 auto;
text-align:$startSide;
font: $bodyFont;
}
#main-wrap1 {
- width:485px;
+ width:705px;
float:$startSide;
- background:$mainBgColor url("http://www1.blogblog.com/rounders3/corners_main_bot.gif") no-repeat $startSide bottom;
+ background:$mainBgColor url("http://usuarios.arsystel.com/wzrlpy/lineadecomandos/corners_main_bot705.gif") no-repeat $startSide bottom;
margin:15px 0 0;
padding:0 0 10px;
color:$mainTextColor;
@@ -122,13 +122,13 @@
#main-wrap2 {
float:$startSide;
width:100%;
- background:url("http://www1.blogblog.com/rounders3/corners_main_top.gif") no-repeat $startSide top;
+ background:url("http://usuarios.arsystel.com/wzrlpy/lineadecomandos/corners_main_top705.gif") no-repeat $startSide top;
padding:10px 0 0;
}
#main {
- background:url("http://www.blogblog.com/rounders3/rails_main.gif") repeat-y $startSide;
+ background:url("http://usuarios.arsystel.com/wzrlpy/lineadecomandos/rails_main705.gif") repeat-y $startSide;
padding:0;
- width:485px;
+ width:705px;
}
#sidebar-wrap {
width:240px;
@@ -142,14 +142,14 @@

.main .widget {
margin-top: 4px;
- width: 468px;
+ width: 688px;
padding: 0 13px;
}

.main .Blog {
margin: 0;
padding: 0;
- width: 484px;
+ width: 704px;
}

/* Links
@@ -171,7 +171,7 @@
/* Blog Header
----------------------------------------------- */
#header-wrapper {
- background:$titleBgColor url("http://www2.blogblog.com/rounders3/corners_cap_top.gif") no-repeat $startSide top;
+ background:$titleBgColor url("http://usuarios.arsystel.com/wzrlpy/lineadecomandos/corners_cap_top960.gif") no-repeat $startSide top;
margin-top:22px;
margin-$endSide:0;
margin-bottom:0;
@@ -183,7 +183,7 @@
color:$titleTextColor;
}
#header {
- background:url("http://www.blogblog.com/rounders3/corners_cap_bot.gif") no-repeat $startSide bottom;
+ background:url("http://usuarios.arsystel.com/wzrlpy/lineadecomandos/corners_cap_bot960.gif") no-repeat $startSide bottom;
padding:0 15px 8px;
}
#header h1 {
@@ -585,11 +585,11 @@
padding:15px 0 0;
}
#footer-wrap2 {
- background:$titleBgColor url("http://www2.blogblog.com/rounders3/corners_cap_top.gif") no-repeat $startSide top;
+ background:$titleBgColor url("http://usuarios.arsystel.com/wzrlpy/lineadecomandos/corners_cap_top960.gif") no-repeat $startSide top;
color:$titleTextColor;
}
#footer {
- background:url("http://www.blogblog.com/rounders3/corners_cap_bot.gif") no-repeat $startSide bottom;
+ background:url("http://usuarios.arsystel.com/wzrlpy/lineadecomandos/corners_cap_bot960.gif") no-repeat $startSide bottom;
padding:8px 15px;
}
#footer hr {display:none;}
@@ -614,7 +614,7 @@
}

body#layout #outer-wrapper {
- width: 730px;
+ width: 950px;
}

body#layout #footer-wrap1 {

domingo, 17 de mayo de 2009

Cortando y pegando GIFs (III)

Recordemos que queremos pasar el ancho de 960 a 740, así que el aumento de ancho es 960-740=220

Mientras que el GIF de cabecera es 740x8, el de las entradas es 485x15, por lo tanto:
  • el tamaño del trozo curvo es 15x15.
  • la posición del trozo curvo derecho 485-15=470
  • nuevo ancho de entradas 485+220=705
  • nueva posición del trozo curvo derecho 485+220-15=590

Con esto generamos los nuevos GIFs de las entradas:
for i in top bot
do
img=corners_main_$i
gifsicle --same-background --crop 0,0+15x15 $img.gif --crop 470,0+15x15 --p 590,0 $img.gif | gifsicle -U "#1" > ${img}705.gif
done


Hay otro GIF para hacer una línea vertical a ambos lados de las entradas, de 485x10.
  • el tamaño del trozo significativo es 10x10.
  • la posición del trozo significativo derecho 485-10=475
  • nuevo ancho de entradas 485+220=705
  • nueva posición del trozo curvo derecho 485+220-10=695
Con esto generamos el nuevo GIF:
img=rails_main
gifsicle --same-background --crop 0,0+10x10 $img.gif --crop 475,0+10x10 --p 695,0 $img.gif | gifsicle -U "#1" > ${img}705.gif


Y ya tenemos todos los GIFs. Falta subirlos a algún sitio de la Web. Si tienes ADSL, tu proveedor te suele dar entre 10 y 100 MB de espacio. Para subirlos, se puede usar el cliente ftp que venga con tu sistema operativo, wput, o FileZilla.

sábado, 16 de mayo de 2009

svg2swf

svg2swf convierte de SVG (el formato que gasta Inkscape) a SWF (vamos, a Flash).
Así que podemos convertir dibujitos vectoriales bastante bien.

He probado con mi avatar, y no queda tan mal:
svg2swf --cubic 20 --default-font test_sans.fdb avatar.svg avatar.swf




SVGSWF





Si usáis Internet Explorer, igual no véis el SVG: bajaos en tal caso el visor.

lunes, 11 de mayo de 2009

Cortando y pegando GIFs (II)

Vamos a probar con gifsicle.

Cortamos la esquina de la izquierda y la de la derecha (740-8=732):
gifsicle --same-background --crop 0,0+8x8 corners_cap_top.gif > corners_cap_top_left8.gif
gifsicle --same-background --crop 732,0+8x8 corners_cap_top.gif > corners_cap_top_right8.gif


Y luego las ponemos en sus nuevas posiciones (960-8=952):
gifsicle corners_cap_top_left8.gif --p 952,0 corners_cap_top_right8.gif | gifsicle -U "#1" > corners_cap_top960.gif

También podemos hacer todo en una única línea, sin ficheros intermedios:

gifsicle --same-background --crop 0,0+8x8 corners_cap_top.gif --crop 732,0+8x8 --p 952,0 corners_cap_top.gif | gifsicle -U "#1" > corners_cap_top960.gif

Y como tenemos que hacerlo con las esquinas de arriba y las de abajo:
for i in top bot
do
img=corners_cap_$i
gifsicle --same-background --crop 0,0+8x8 $img.gif --crop 732,0+8x8 --p 952,0 $img.gif | gifsicle -U "#1" > ${img}960.gif
done

domingo, 10 de mayo de 2009

BusyBox

Una multitud de programas Unix, con mínimo tamaño pero intentando que cumplan POSIX, y en un único ejecutable: eso es BusyBox.

Es interesante porque es muy modular: durante la configuración eliges que programas quieres, con lo que puedes controlar el tamaño final del binario.

Hice una prueba con el fuente de BusyBox 1.13.3, y con unos poquitos cambios, lo compilé dentro de Cygwin; lo configuré para generar sólo awk.

Hoy he encontrado una versión para Windows que tengo que probar.

La idea que llevo en mente es empezar por un binario que tenga hush y awk.

sábado, 2 de mayo de 2009

Cortando y pegando GIFs (I)

Resulta que Internet Explorer 6 no entiende los PNG con transparencias, excepto usando trucos realmente inmundos.

Así que tenemos usar GIF, un formato algo anticuado pero que entiende todo el mundo, para por ejemplo las esquinas redondeadas de esta plantilla de Blogger.

Los GIFs se pueden manipular con Irfanview, MS Paint, Paint.NET, GIMP, etc. pero aquí usamos la línea de comando.

Podemos usar ImageMagick, como explican aquí.

Pero aquí buscamos la utilidad de menor tamaño que permita realizar la tarea. Veamos giflib.

La tarea es ensanchar el GIF de cabecera, de 740x8 a 960x8.

Separamos la esquina redondeada izquierda, y la derecha:

gifclip -i 0 0 7 7 corners_cap_top.gif | gifpos -s 960 8 > corners_cap_top_left8.gif
gifclip -i 732 0 739 7 corners_cap_top.gif | gifpos -s 960 8 -i 952 0 > corners_cap_top_right8.gif


Cogemos un trocito de en medio, y lo ensanchamos hasta 960 -8 -8= 944:

gifclip -i 8 0 125 7 corners_cap_top.gif | gifrsize -x 8 | gifpos -s 960 8 -i 8 0 > corners_cap_mid944.gif


Y juntamos todo:

gifasm corners_cap_top_left8.gif corners_cap_mid944.gif corners_cap_top_right8.gif > multi.gif

GIF-LIB error: Wrong record type detected.


Vaya, hombre, giflib no entiende los GIFs que genera ella misma.
Habrá que usar otra cosa.

jueves, 30 de abril de 2009

Web Developer

Para ver la estructura de las páginas Web, resulta muy práctico navegar con Firefox y tener instalado Web Developer.
Por cierto, tiene una versión traducida.

Para entender las CSS que gasta Blogger en particular, conviene activar el menú Information-> Display class & ID details y también Outline -> Outline block level elements, e imprimir el blog.
Con esta especia de mapa, es más fácil seguir el código de las CSS.

lunes, 27 de abril de 2009

Barra lateral con tres cajitas

Hoy he creado esta bitácora, con la plantilla inicial "Rounders 3", y la he modificado un poquito para que en la barra lateral tenga tres cajitas en vez de dos.
¿Y qué he modificado?

Es muy importante salvar la plantilla antes y después de cada cambio, así tenemos la posibilidad de ver las modificaciones con el comando 'diff':


$ diff -u lineadecomandos_plantilla-2009-04-27\ 2230.xml lineadecomandos_plantilla-2009-04-27\ 2334.xml


La pena es que incrustar etiquetas XML dentro del editor de Blogger produce basura.
Así que hay protegerlas para que no las interprete.
Una manera es hacer una sustitución global de todos los > por &gt;,
y de todos los < por &lt;.


$ diff -u lineadecomandos_plantilla-2009-04-27\ 2230.xml lineadecomandos_plantilla-2009-04-27\ 2334.xml


--- lineadecomandos_plantilla-2009-04-27 2230.xml 2009-04-27 22:34:02.538687800 +0200
+++ lineadecomandos_plantilla-2009-04-27 2334.xml 2009-04-27 23:34:32.163687800 +0200
@@ -13,6 +13,7 @@
URL: www.stopdesign.com
Date: 27 Feb 2004
Updated by: Blogger Team
+Updated by Víctor Paesa, April 2009
----------------------------------------------- */

/* Variable definitions
@@ -27,20 +28,16 @@
type="color" default="#586" value="#558866"<
>Variable name="borderColor" description="Post Border Color" type="color"
default="#bbb" value="#bbbbbb"<
-
-
>Variable name="mainLinkColor" description="Link Color" type="color"
default="#456" value="#445566"<
>Variable name="mainVisitedLinkColor" description="Visited Link Color"
type="color" default="#234" value="#223344"<
-
>Variable name="titleBgColor" description="Page Header Background Color"
type="color" default="#357" value="#335577"<
>Variable name="titleTextColor" description="Blog Title Color"
type="color" default="#fff" value="#ffffff"<
-
- >Variable name="topSidebarHeaderColor"
- description="Top Sidebar Title Color"
+ >Variable name="sidebarHeaderColor"
+ description="Sidebar Title Color"
type="color" default="#fff" value="#ffffff"<
>Variable name="topSidebarBgColor"
description="Top Sidebar Background Color"
@@ -52,13 +49,21 @@
>Variable name="topSidebarVisitedLinkColor"
description="Top Sidebar Visited Link Color"
type="color" default="#fff" value="#ffffff"<
- >Variable name="bottomSidebarHeaderColor"
- description="Bottom Sidebar Title Color"
- type="color" default="#abc" value="#aabbcc"<
-
+ >Variable name="middleSidebarBgColor"
+ description="Middle Sidebar Background Color"
+ type="color" default="#586" value="#6f6f5f"<
+ >Variable name="middleSidebarLinkColor"
+ description="Middle Sidebar Link Color"
+ type="color" default="#99ddbb" value="#ffffff"<
+ >Variable name="middleSidebarVisitedLinkColor"
+ description="Middle Sidebar Visited Link Color"
+ type="color" default="#ffffff" value="#ffffff"<
+ >Variable name="bottomSidebarBgColor"
+ description="Bottom Sidebar Background Color"
+ type="color" default="#586" value="#aaccc0"<
>Variable name="bottomSidebarLinkColor"
description="Bottom Sidebar Link Color"
- type="color" default="#99ddbb" value="#99ddbb"<
+ type="color" default="#99ddbb" value="#ffffff"<
>Variable name="bottomSidebarVisitedLinkColor"
description="Bottom Sidebar Visited Link Color"
type="color" default="#ffffff" value="#ffffff"<
@@ -475,8 +480,8 @@

#sidebartop h2 {
line-height:1.5em;
- color:$topSidebarHeaderColor;
- border-bottom: 1px dotted $topSidebarHeaderColor;
+ color:$sidebarHeaderColor;
+ border-bottom: 1px dotted $sidebarHeaderColor;
font: $headerFont;
margin-bottom: 0.5em;
}
@@ -512,18 +517,6 @@
margin-top: 0.5em;
}

-#sidebarbottom-wrap1 {
- background:$titleBgColor url("http://www.blogblog.com/rounders3/corners_side_top.gif") no-repeat $startSide top;
- margin:0 0 15px;
- padding:10px 0 0;
- color: $titleTextColor;
-}
-
-#sidebarbottom-wrap2 {
- background:url("http://www1.blogblog.com/rounders3/corners_side_bot.gif") no-repeat $startSide bottom;
- padding:0 0 8px;
-}
-
.sidebar h2 {
margin-top:0;
margin-$endSide:0;
@@ -556,10 +549,34 @@
}

#sidebar h2 {
- color: $bottomSidebarHeaderColor;
- border-bottom: 1px dotted $bottomSidebarHeaderColor;
+ color: $sidebarHeaderColor;
+ border-bottom: 1px dotted $sidebarHeaderColor;
}

+#sidebarmiddle-wrap1 {
+ background:$middleSidebarBgColor url("http://www.blogblog.com/rounders3/corners_side_top.gif") no-repeat $startSide top;
+ margin:0 0 15px;
+ padding:10px 0 0;
+ color: $titleTextColor;
+}
+
+#sidebarmiddle-wrap2 {
+ background:url("http://www1.blogblog.com/rounders3/corners_side_bot.gif") no-repeat $startSide bottom;
+ padding:0 0 8px;
+}
+
+#sidebarbottom-wrap1 {
+ background:$bottomSidebarBgColor url("http://www.blogblog.com/rounders3/corners_side_top.gif") no-repeat $startSide top;
+ margin:0 0 15px;
+ padding:10px 0 0;
+ color: $titleTextColor;
+}
+
+#sidebarbottom-wrap2 {
+ background:url("http://www1.blogblog.com/rounders3/corners_side_bot.gif") no-repeat $startSide bottom;
+ padding:0 0 8px;
+}
+
/* Footer
----------------------------------------------- */
#footer-wrap1 {
@@ -1105,8 +1122,55 @@
>/b:section<
>/div<>/div<

+ >div id='sidebarmiddle-wrap1'<>div id='sidebarmiddle-wrap2'<
+ >b:section class='sidebar' id='sidebarmiddle' preferred='yes'<
+>b:widget id='Label1' locked='false' title='Etiquetas' type='Label'<
+>b:includable id='main'<
+ >b:if cond='data:title'<
+ >h2<>data:title/<>/h2<
+ >/b:if<
+ >div class='widget-content'<
+ >ul<
+ >b:loop values='data:labels' var='label'<
+ >li<
+ >b:if cond='data:blog.url == data:label.url'<
+ >span expr:dir='data:blog.languageDirection'<
+ >data:label.name/<
+ >/span<
+ >b:else/<
+ >a expr:dir='data:blog.languageDirection' expr:href='data:label.url'<
+ >data:label.name/<
+ >/a<
+ >/b:if<
+ >span dir='ltr'<(>data:label.count/<)>/span<
+ >/li<
+ >/b:loop<
+ >/ul<
+
+ >b:include name='quickedit'/<
+ >/div<
+>/b:includable<
+>/b:widget<
+>/b:section<
+ >/div<>/div<
+
>div id='sidebarbottom-wrap1'<>div id='sidebarbottom-wrap2'<
- >b:section class='sidebar' id='sidebar' preferred='yes'/<
+ >b:section class='sidebar' id='sidebarbot' preferred='yes'<
+>b:widget id='LinkList1' locked='false' title='Enlaces' type='LinkList'<
+>b:includable id='main'<
+
+>b:if cond='data:title'<>h2<>data:title/<>/h2<>/b:if<
+ >div class='widget-content'<
+ >ul<
+ >b:loop values='data:links' var='link'<
+ >li<>a expr:href='data:link.target'<>data:link.name/<>/a<>/li<
+ >/b:loop<
+ >/ul<
+ >b:include name='quickedit'/<
+ >/div<
+>/b:includable<
+>/b:widget<
+>/b:section<
>/div<>/div<

>/div<

domingo, 26 de abril de 2009

GIFs animados comprimidos

Un poco de Google y encuentro esta utilidad para manipular GIFs.
Trivial de compilar en Cygwin:
./configure --disable-gifview
make
strip src/*.exe
make install


Sólo depende de la biblioteca estándar de C, así que también es trivial compilarlo para Windows:

make distclean
CC=gcc-3 CFLAGS=-mno-cygwin ./configure --disable-gifview
make
strip src/*.exe
make install


Y el comando mejorado para crear GIFs animados se queda en:

ffmpeg -i avión.wmv -r 10 -vframes 50 -f gif -pix_fmt rgb24 -s 80x60 - |gifsicle -O2 > avión.gif

viernes, 24 de abril de 2009

GIFs animados

Hay montones de herramientas para generar GIFs animados.
Y FFmpeg también puede crearlos.

No es el mejor en cuanto a la calidad resultante (no busca la paleta de colores óptima), ni cuanto a espacio (los GIF que produce no están comprimidos), pero sí es el que más formatos de entrada admite.

La situación puede mejorar pronto, porque en marzo se apuntó un voluntario para crear GIFs comprimidos.

Y ahora, un ejemplo de cómo convertir a GIF animado:

ffmpeg -i avión.wmv -r 10 -vframes 50 -f gif -pix_fmt rgb24 -s 80x60 avión.gif

sábado, 18 de abril de 2009

KDE sobre Windows

¡Quién lo podía pensar, si hay KDE para Windows!

El instalador es muy similiar al de Cygwin.
Tiene su entorno de desarrollo basado en MinGW (dice que también puede ser MSVC).
De momento me he bajado las dependencias (iconv, expat, libpng, libjpeg) de libGD y xgawk, para ver si compilo una versión para MinGW y lo cuelgo junto a los binarios que ya tengo para Cygwin, aquí.

Con algo más de tiempo, igual se puede compilar Kdenlive, el editor de video.

SWFTools

Hoy freshmeat anuncia versiones nuevas en un par de cosillas de mi interés: SWFTools y Mathomatic.

Con SWFTools se pueden hacer animaciones Flash realmente curiosas.

miércoles, 15 de abril de 2009

Gráficos desde awk

Por mi edad y mi ser austero, soy un fanático de awk.
Maravilloso para procesar ficheritos de texto, descubrí que había una variante que procesaba XML, bautizada con el no muy original y sí muy descriptivo nombre de XMLgawk

La variante tenía un interesante interfaz para añadir extensiones al lenguaje, así que contribuí con una extensión para usar las funciones gráficas de libGD.

Aquí tenéis una austera página con los binarios para Cygwin, y unas someras explicaciones de cómo compilarlos desde los fuentes.

martes, 14 de abril de 2009

Polinomios

Pues sí, uno de los paquetes de Cygwin es una calculadora algebraica, que permite hacer derivadas, integrales, límites, resolver sus raíces, todo sobre polinomios.

¡Ah si lo hubiera tenido en los tiempos que estudiaba! :-)

jueves, 2 de abril de 2009

Traducción de WinFF

Hace algún tiempo hice la traducción a mi lengua nativa de WinFF.

Si no lo conocéis, os lo recomiendo, creo que es el mejor de los programas que le ponen un interfaz gráfico a FFmpeg.

Matt ha sacado la versión 1.0beta, así que le he actualizado la traducción.

martes, 24 de marzo de 2009

Adornicos

Hoy ponemos un favicon
que no es sino una miniatura de mi avatar:
Sólo queda ahora poner el favicon en su sitio (que salga junto al enlace en "Favoritos") y plantar el avatar como imagen en la cabecera.

lunes, 23 de marzo de 2009

gd-2.0.36

Como parte de nuestra búsqueda de la brevedad y la bondad, vamos a aligerar un poco a libGD.

El paquete oficial de Cygwin tiene como dependencias a:
cygwin libXpm4 libfontconfig1 libjpeg62 libpng12

El problema es que libXpm4 tiene como dependencias al megapaquetón libX11_6, sólo para usar las funciones que manejan los bitmaps XPM, así que se puede sustituir por libXpm-noX.

Quitar libfontconfig1, es fácil: al compilar el fuente de libGD, tenemos una opción durante la configuración.

libiconv sólo se usa para convertir de una oscura codificación de japonés a Unicode. Así que fuera, mejor usar Unicode directamente para los (ejem, escasos) textos en japonés que yo maneje.

Otro ahorro es quitar la tipografía de tamaño fijo.

Así que vamos poco a poco editando los fuentes e intentando compilarlos, y cuando ya ya funciona, guardamos los cambios en un parche:

diff -u Makefile.am.org Makefile.am > ../patches/libgd.trim.1.diff
diff -u configure.ac.org configure.ac >> ../patches/libgd.trim.1.diff
diff -u config/gdlib-config.in.org config/gdlib-config.in >> ../patches/libgd.trim.1.diff
diff -u gdft.c.org gdft.c >> ../patches/libgd.trim.1.diff
diff -u gddemo.c.org gddemo.c >> ../patches/libgd.trim.1.diff


El parche es una chapucilla: lo elegante sería un parche por cambio, y enviarlos a libGD.

El parche es éste:

--- Makefile.am.org 2007-11-27 09:30:34.000000000 +0100
+++ Makefile.am 2009-03-19 11:30:01.260819300 +0100
@@ -13,17 +13,19 @@

EXTRA_DIST = README-JPEG.TXT README.TXT configure.pl bdftogd demoin.png err.out index.html install-item makefile.sample readme.jpn entities.html entities.tcl

-include_HEADERS = gd.h gdfx.h gd_io.h gdcache.h gdfontg.h gdfontl.h gdfontmb.h gdfonts.h gdfontt.h entities.h
+include_FIXFONTS = gdfontg.h gdfontl.h gdfontmb.h gdfonts.h gdfontt.h
+
+include_HEADERS = gd.h gdfx.h gd_io.h gdcache.h entities.h

lib_LTLIBRARIES = libgd.la

-libgd_la_SOURCES = gd.c gdfx.c gd_security.c gd_gd.c gd_gd2.c gd_io.c gd_io_dp.c gd_gif_in.c gd_gif_out.c gd_io_file.c gd_io_ss.c gd_jpeg.c gd_png.c gd_ss.c gd_topal.c gd_wbmp.c gdcache.c gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c gdft.c gdhelpers.c gdhelpers.h gdkanji.c gdtables.c gdxpm.c jisx0208.h wbmp.c wbmp.h
+libgd_la_FIXFONTSOURCES = gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c

-libgd_la_LDFLAGS = -version-info 2:0:0 $(XTRA_LDFLAGS)
+libgd_la_SOURCES = gd.c gdfx.c gd_security.c gd_gd.c gd_gd2.c gd_io.c gd_io_dp.c gd_gif_in.c gd_gif_out.c gd_io_file.c gd_io_ss.c gd_jpeg.c gd_png.c gd_ss.c gd_topal.c gd_wbmp.c gdcache.c gdft.c gdhelpers.c gdhelpers.h gdtables.c gdxpm.c jisx0208.h wbmp.c wbmp.h

-libgd_la_LIBADD = $(LTLIBICONV)
+libgd_la_LDFLAGS = -version-info 2:0:0 $(XTRA_LDFLAGS)

-LDADD = ./libgd.la $(LIBICONV)
+LDADD = ./libgd.la

dist-zip: distdir
zip -qr $(distdir).zip $(distdir)
--- configure.ac.org 2009-03-17 16:42:29.526062500 +0100
+++ configure.ac 2009-03-18 16:44:50.994075200 +0100
@@ -61,19 +61,6 @@
AC_HEADER_STDC
AC_CHECK_HEADERS([errno.h limits.h stddef.h stdlib.h string.h unistd.h])

-AM_ICONV
-# if test -n "$LIBICONV" ; then
-# LIBS="$LIBS $LIBICONV"
-# fi
-
-AC_CHECK_HEADERS(iconv.h,
- [AC_MSG_CHECKING(whether iconv.h defines iconv_t)
- AC_EGREP_HEADER([typedef.*iconv_t],iconv.h,
- [AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_ICONV_T_DEF, 1,
- [Define if defines iconv_t.])],
- AC_MSG_RESULT(no))])
-
# Checks for typedefs, structures, and compiler characteristics.
#AC_C_CONST
#AC_TYPE_SIZE_T
@@ -524,10 +511,9 @@

if test "$withval" != no; then
AC_CHECK_LIB(Xpm,XpmReadFileToXpmImage,
- [LIBS="-lXpm -lX11 $LIBS"
+ [LIBS="-lXpm $LIBS"
FEATURES="GD_XPM $FEATURES"
- AC_DEFINE(HAVE_LIBXPM, 1, [ Define if you have the Xpm library. ])],,
- [-lX11])
+ AC_DEFINE(HAVE_LIBXPM, 1, [ Define if you have the Xpm library. ])])
else
ac_cv_lib_Xpm_XpmReadFileToXpmImage=no
fi
--- config/gdlib-config.in.org 2009-03-19 16:12:36.221283200 +0100
+++ config/gdlib-config.in 2009-03-19 16:12:06.709311200 +0100
@@ -71,7 +71,7 @@
echo @LDFLAGS@
;;
--libs)
- echo @LIBS@ @LIBICONV@
+ echo @LIBS@
;;
--cflags|--includes)
echo -I@includedir@
@@ -84,7 +84,7 @@
echo "includedir: $includedir"
echo "cflags: -I@includedir@"
echo "ldflags: @LDFLAGS@"
- echo "libs: @LIBS@ @LIBICONV@"
+ echo "libs: @LIBS@"
echo "libdir: $libdir"
echo "features: @FEATURES@"
;;
--- gdft.c.org 2009-03-20 10:08:09.643623800 +0100
+++ gdft.c 2009-03-20 10:07:19.824264500 +0100
@@ -1081,26 +1081,7 @@
return "No character set found";
}

-#ifndef JISX0208
- if (encoding == gdFTEX_Shift_JIS)
- {
-#endif
- if ((tmpstr = (char *) gdMalloc (BUFSIZ)))
- {
- any2eucjp (tmpstr, string, BUFSIZ);
- next = tmpstr;
- }
- else
- {
next = string;
- }
-#ifndef JISX0208
- }
- else
- {
- next = string;
- }
-#endif

#if 0
fprintf(stderr,"dpi=%d,%d metric_res=%d ptsize=%g\n",hdpi,vdpi,METRIC_RES,ptsize);
--- gddemo.c.org 2009-03-20 10:36:35.767539000 +0100
+++ gddemo.c 2009-03-20 10:38:27.198319800 +0100
@@ -38,7 +38,9 @@
int i;

/* gd fonts for font test */
+#ifdef CONFIG_FIXFONT
gdFontPtr fonts[5];
+#endif
int y;

/* Create output image, in true color. */
@@ -136,6 +138,7 @@
/* Draw the styled, brushed line */
gdImageLine (im_out, 0, 255, 255, 0, gdStyledBrushed);
}
+#ifdef CONFIG_FIXFONT
/* Text (non-truetype; see gdtestft for a freetype demo) */
fonts[0] = gdFontGetTiny ();
fonts[1] = gdFontGetSmall ();
@@ -156,6 +159,7 @@
(unsigned char *) "hi", red);
y += fonts[i]->h;
}
+#endif
/* Random antialiased lines; coordinates all over the image,
but the output will respect a small clipping rectangle */
gdImageSetClip (im_out, 0, gdImageSY (im_out) - 100,


Los comandos para configurar y compilar quedan así:
LC_ALL=C autoreconf -i
CC=gcc-4 TMPDIR=/tmp CFLAGS="-march=core2 -DXPM_NO_X" ./configure --x-includes=/usr/include/noX --x-libraries=/usr/lib/noX --with-xpm --without-x --without-fontconfig
LC_ALL=C TMPDIR=/tmp make

martes, 17 de marzo de 2009

x264-20090315

Toca compilar x264 para Cygwin.

Cogemos el x264 de hoy, y, como cuando detecta a Cygwin lo que hace es una compilación cruzada para MinGW, le aplicamos un parche:

patch < x264.cygwin.diff

El contenido de x264.cygwin.diff es:

diff --git a/configure b/configure
index eb51091..31da92e 100755
--- a/configure
+++ b/configure
@@ -212,11 +212,8 @@ case $host_os in
LDFLAGS="$LDFLAGS -lm"
;;
cygwin*)
- SYS="MINGW"
- CFLAGS="$CFLAGS -mno-cygwin"
- LDFLAGS="$LDFLAGS -mno-cygwin"
+ SYS="CYGWIN"
EXE=".exe"
- DEVNULL="NUL"
;;
mingw*)
SYS="MINGW"
@@ -241,6 +238,8 @@ case $host_cpu in
ASFLAGS="-O2"
if [ "$SYS" = MACOSX ]; then
ASFLAGS="$ASFLAGS -f macho -DPREFIX"
+ elif [ "$SYS" = CYGWIN ]; then
+ ASFLAGS="$ASFLAGS -f win32 -DPREFIX"
elif [ "$SYS" = MINGW ]; then
ASFLAGS="$ASFLAGS -f win32 -DPREFIX"
else
@@ -368,6 +367,8 @@ fi
if [ "$avis_input" = "auto" ] ; then
if [ $SYS = MINGW ]; then
avis_input="yes"
+ elif [ "$SYS" = CYGWIN ]; then
+ avis_input="yes"
else
avis_input="no";
fi
@@ -440,6 +441,10 @@ if [ "$shared" = "yes" ]; then
echo "SONAME=libx264-$API.dll" >> config.mak
echo 'IMPLIBNAME=libx264.dll.a' >> config.mak
echo 'SOFLAGS=-Wl,--out-implib,$(IMPLIBNAME) -Wl,--enable-auto-image-base' >> config.mak
+ elif [ "$SYS" = CYGWIN ]; then
+ echo "SONAME=libx264-$API.dll" >> config.mak
+ echo 'IMPLIBNAME=libx264.dll.a' >> config.mak
+ echo 'SOFLAGS=-Wl,--out-implib,$(IMPLIBNAME) -Wl,--enable-auto-image-base' >> config.mak
elif [ "$SYS" = "MACOSX" ]; then
echo "SOSUFFIX=dylib" >> config.mak
echo "SONAME=libx264.$API.dylib" >> config.mak


Esta es mi configuración:
CC=gcc-4 ./configure --disable-mp4-output --extra-cflags=-march=core2

Le damos caña y casca:

Found no assembler
Minimum version is yasm-0.6.1
If you really want to compile without asm, configure with --disable-asm.

Vaya, requiere yasm y no lo tengo instalado en mi Cygwin 1.7. Bueno pero lo tengo para Cygwin 1.5, bajado de Cygwin Ports, y se supone que hay compatibilidad hacia delante.

En mi Cygwin 1.5, cygcheck -l yasm me dice lo que tengo que copiar, y cygcheck /usr/bin/yasm.exe me dice las dependencias (las DLLs que también habrá que copiar si no existen ya).

Así que ejecuto en mi Cygwin 1.7:

cd /bin && cp -p /cygdrive/c/cygwin/bin/yasm.exe .
cd /usr/include && cp -pri /cygdrive/c/cygwin/usr/include/libyasm .


Y ahora ya funciona:

$ CC=gcc-4 ./configure --disable-mp4-output --extra-cflags=-march=core2
./version.sh: line 2: git: command not found
Platform: X86
System: CYGWIN
asm: yes
avis input: yes
mp4 output: no
pthread: yes
debug: no
gprof: no
PIC: no
shared: no
visualize: no
You can run 'make' or 'make fprofiled' now.


Bueno hay un errorcillo, pero git sólo se usa para poner la versión.

Así que make && make install y ya tenemos libx264 disponible.

lunes, 16 de marzo de 2009

ffmpeg-17998

Los chicos de Cygwin han sacado la versión 4.3.2-2 de gcc. Vamos a probarla con el ffmpeg de hoy.

Aprovechando que gcc 4.3.x permite optimizar para Core2, uso esta configuración:

./configure --cc=gcc-4 --enable-shared --disable-static --cpu=core2 --enable-gpl --enable-avfilter --enable-avfilter-lavf --enable-pthreads --enable-avisynth --enable-bzlib --enable-zlib --build-suffix=-SVN

Decimos make y, vaya, hombre, salen errores:

libavformat/rtsp.o: In function `__ntohl':
/usr/include/asm/byteorder.h:40: multiple definition of `___ntohl'
libavformat/os_support.o:/usr/include/asm/byteorder.h:40: first defined here


¿De dónde viene esto? Pues hay tres motivos encadenados:

  1. FFmpeg le pasa -std=c99 al compilador
  2. La versión 4.3.x de gcc cambia la semántica del comando inline en modo C99
  3. Los "includes" de las funciones C de Cygwin no cumplen la norma C99.


¿Qué soluciones hay?

  1. La fácil, quitamos el trozo que casca, o sea añadimos --disable-network a nuestra configuración.
  2. La complicada, avisar en la lista de correo de Cygwin que habría que soportar C99 en los "includes".


Es lunes, así que vamos a usar la opción 1.

Ahora funciona la cosa, pero otra tarea pendiente es enviar un parche a ffmpeg-devel para no tener que hacer esta chapucilla con las compilaciones que crean bibliotecas compartidas.

miércoles, 4 de marzo de 2009

El mejor conversor de multimedia

Claro, es FFmpeg, y casi todo lo demás está basado en él.

El resto no son tan versátiles, sino que se limitan a manejar un formato o dos como mucho: