
MATLAB, como no podía ser de otra manera, es una herramienta muy útil para el desarrollo ágil de algoritmos, probarlos y así, cuando nos decidamos a pasarlos a un lenguaje distinto que nos permita su mejor explotación, estemos seguros de que va a funcionar, que no hemos implementado funciones que realmente no nos hacían falta y que no vamos a dar demasiados pasos en falso.
Nosotros, los que estudiamos Ingeniería de Telecomunicaciones, estamos bastante acostumbrados a trabajar con MATLAB pero, al menos en mi caso, siempre me había visto tratando señales de audio o de radiación, nunca imágenes o vídeos. Pero ayer, en un intento de hacer algo diferente (mostrar la evolución de una imagen conforme se va comprimiendo), se me ocurrió la idea de mostrar cada una de las imágenes obtenidas por mi algoritmo como un frame de vídeo en una película.
Tras investigar un poco, puedo decir que crear un vídeo *.avi usando MATLAB, es de lo más sencillo, es más, sólo tenemos que escribir cuatro líneas (aunque usa podrá repetirse tantas veces como frames tengamos en nuestro vídeo).
Paso 1
Creamos una variable en la que insertaremos los distintos frames:
movie = avifile('video.avi', 'fps', 10, 'compression', 'none');
Esta función tiene la siguiente especificación:
aviobj = avifile(filename, ParameterName, ParameterValue)
Es decir, le tenemos que pasar el nombre del fichero y tantas parejas parámetro->valor como deseemos; en nuestro caso hemos especificado que queremos mostrar 10 frames por segundo y que no queremos compresión alguna en nuestro vídeo resultante.
Paso 2
Añadimos todos los frames que deseemos, para ello antes debemos convertir la imagen que queremos que aparezca en el vídeo en un frame; en definitiva:
frame = im2frame(image, gray(256));
movie = addframe(movie, frame);
Si tienes dudas sobre lo que hacen estas funciones puedes consultar las especificaciones de im2frame y de addframe.
Paso 3
Cerramos las variables y, por consiguiente dejamos el video listo para reproducirse en programas como el videolán:
movie = close(movie);
Recientemente adquirí un MacBook Pro 13″, tras 4 meses de uso, puedo decir con tranquilidad que es una maravilla de equipo; pero como todo cambio de sistema operativo, programas, equipo,… implica una serie de cambios a los que debemos acostumbrarnos poco a poco.
En este caso voy a comentar una solución al problema (o característica, según se vea) que nos impide seleccionar la url en Google Chrome al pulsar la techa F6 (o fn+F6) y al que nos permite refrescar/actualizar la página pulsando la tecla F5 (o fn+F5).
Realmente configurarlo para añadir esta característica es muy sencillo; para ello nos vamos a las preferencias del sistema>teclado; una vez ahí nos dirigimos a la pestaña “Atajos del teclado” ya que vamos a añadir 2. Antes de seguir con la configuración vamos a apuntar dos nombres de comandos tal y como aparecen en el menú de Chrome y que vamos a necesitar a la hora de definir nuestro atajo:
En el menú File (Archivo) del Chrome vemos que el comando que se corresponde con la techa ⌘L (Seleccionar la dirección) es “Open Location…” en mi caso; esto debería hacer que al pulsar la combinación ⌘L, la URL se seleccione automáticamente (obtenga el foco); pues bien, nos apuntamos el nombre del comando “Open Location…” ya que lo necesitaremos más adelante.

Hacemos lo mismo pero con el comando ⌘R que está bajo el menú View (Ver), solo que en este caso con “Reload This Page“.
Leer más… »
Como último artículo de la serie, vamos a adentrarnos un poco más en la declaración de elementos similares a las funciones con macros , para ser más exactos, con sus argumentos y posibilidades:
Convertir a String
En ocasiones no es de un gran interés tratar de la misma manera todos los argumentos que le pasamos a este tipo de funciones de preprocesador.
En el caso concreto de que deseemos tratar el argumento como un String constante, habremos de precederlo con el símbolo ‘#‘, demnaera que estamos convirtiendo en constantes dichos parámetros, pero veamos un ejemplo que he sacado de gnu.org, ya que me parece bastante ilustrativo.
#define WARN_IF(EXP) \
do { if (EXP) \
fprintf (stderr, "Warning: " #EXP "\n"); } \
while (0)
WARN_IF (x == 0);
Este pedazo de código nos dará una salida como la siguiente:
do { if (x == 0) fprintf (stderr, “Warning: ” “x == 0″ “\n”); } while (0);
Es decir, el argumento EXP se sustituye como argumento en el primer caso y como un string en el segundo.
Una de las grandes ventajas de la conversión a String de este tipo de macros, es que no sólo añade dobles comillas, sino que escapa los caracteres necesarios para que la cadena se muestre tal y como es, a no ser que esta se encuentre dentro de una cadena de texto ya o sea un carácter como ‘\n‘.
Finalmente puede resultarnos de utilidad concatenar un par de tokens dados dentro de una macro; para ello podremos hacer uso de ‘##‘
Parámetros indefinidos
Algo que puede resultarnos muy interesante e incluso increíble cuando empezamos a utilizar C, es que, si bien nos han enseñado a que las funciones tienen un número definido de parámetros, ¿cómo es posible la existencia de funciones como printf?
Al igual que para las funciones, existe una forma de hacer que una macro acepte un número no definido de parámetros, y este método aparece en forma de __VA_ARGS__. Este token nos permitirá sustotuir en nuestro macro los ‘…‘ por los valores que se le han pasado a la función.
#define log(...) printf(__VA_ARGS__)
Si queremos ser más descriptivos con los parámetros podemos sustituir ‘…‘ por ‘<nombre>…‘, por ejemplo:
#define log(args...) printf(args)
Si queremos especificar un número mínimo de argumentos, podemos hacerlo de la siguiente manera:
#define log(formato, args...) printf(formato, args)
pero esto hace que sea obligatorio, en todo momento, si no pasar un segundo argumento, sí escribir la coma después del primero. Para solucionar este problema, de nuevo acudimos al manual de gnu.org que nos dice que echemos mano de ‘##‘, de manera que podamos omitir, si lo deseamos el segundo parámetro y la coma de después del primero al llamar a la macro:
#define log(formato, args...) printf(formato, ##args)
En el pasado y primer artículo de esta serie, describimos a grosso modo el funcionamiento de la directiva de preprocesador #define; siendo una de las características más importantes a tener en cuenta el hecho de que a la hora de compilar el programa no estamos trabajando con variables con un valor, sino con los valores directamente. De este modo estaremos ahorrando memoria y dotando de legibilidad a nuestro código en determinadas ocasiones.
Hoy vamos a ver cómo simular funciones con el sistema de Macros. Antes de nada, hay que aclarar que: si bien para constantes, por convenio, se utilizan letras mayúsculas en todo momento, para esta especie de funciones no es necesario hacer esto, de manera que podemos continuar con el sistema de nomenclaturas que hemos estado llevando hasta el momento (como recomendación, yo usaría todo en minúsculas menos la primera letra de cada palabra exceptuando la de la primera, Ex: hallarMaximo(…)).
Supongamos que contamos con dos funciones en nuestras librerías:
int rand(void);
int fastRand(void);
Ambas funciones llevan a cabo la misma tarea, sólo que utilizan diferentes métodos para realizarla, de hecho, la segunda que es mucho más eficiente que la primera (como puede entenderse por el nombre), la acabamos de implementar y, a pesar de que la entrada y la salida es la misma, la primera ha sido utilizada cientos de veces en nuestro código, y cambiarla implicaría un repaso exhaustivo del código fuente y, en caso de tener una API pública, implicaría cambiarla y notificárselo a todos nuestros usuarios.
En lugar de esto, podemos crear una macro que se encargue de realizar dicha sustitución durante el proceso de precompilado:
#define rand() fastRand()
de manera que, cada vez que llamemos a la función rand() en nuestro código, a la hora de compilarlo, es como si estuviésemos llamando a la función fastRand().
Pero el poder de esta herramienta no se para con estas características, sino que nos permite definir algo parecido a funciones de forma completa. Con esto quiero decir que podemos definir macros que a la hora de editar el código y utilizarlos, podemos asumir que son funciones. Pongamos un ejemplo:
#define max(x, y) ((x > y) ? x : y)
una vez hehcha esta definición, nosotros, desde nuestro código podremos llamar a esta “función” evitando que se gasten, entre otras cosas niveles de pila, ya que el código es sustituido durante el proceso de preprocesado, de manera que si escribimos en nuestro código:
int a = 2;
int b = 4;
int z = max(a, b);
el código que realmente se estará ejecutando una vez compilado será:
int a = 2;
int b = 4;
int z = ((a > b) ? a : b);
Uno de los grandes problemas de utilizar esta técnica para sustituir a las funciones es que, como podemos observar es que, a la hora de llamar a la macro, no tenemos comprobación del tipado de los datos que le pasamos, pudiendo obtener así, resultados inesperados o incluso errores de estabilidad del programa. Hay que ser conscientes en todo momento de que los argumentos, a la hora de llamar a una macro que se comporta por una función, estarán separados por comas.
Finalmente, a la hora de llamar a una macro, si no le pasamos el número de argumentos necesarios, obtendremos un error de preprocesador, pero en caso de que le pasemos argumentos vacíos, estos se sustiuirán por argumentos vacíos sin dar error durante el proceso de preprocesado.