lunes, 30 de abril de 2012

Cristalab

Cristalab

Cristalab


Trackear elementos móviles en After Effects

Posted: 30 Apr 2012 09:20 AM PDT

Tal como podemos realizar la captura del movimiento del fondo en After Effects, también podemos ejecutar la misma acción en elementos que se desplazan sobre un fondo estático y trasladar esos datos a los diferentes controles de un efecto asignado a esa capa, como por ejemplo un relámpago que perseguirá a uno de los presonajes del video sobre el que trabajemos.



Saludos.

Enviar comentario

Introducción a Backbone.js : Modelos

Posted: 30 Apr 2012 06:43 AM PDT

Con el pasar del tiempo en el mundo del desarrollo web, hemos visto la aparición de cientos de Frameworks con el objetivo de agilizar el proceso de desarrollo. Javascript no ha sido ajeno a esta corriente y hoy día podemos encontrar Mootools, Dojo, Ext Core, Prototype y jQuery entre otros más.



A pesar de ser tan poderosas herramientas de desarrollo, ninguna posee algún tipo de lineamiento o estructura para crear nuestro código y con el pasar del tiempo nos vamos llenando de una cantidad de líneas y archivos en JS con un montón de selectores y funciones por todos lados (Código Spaghetti).

Hoy hablaremos sobre Backbone.js, una librería Javascript creada por Jeremy Ashkenas, el mismo señor que ha creado CoffeeScript . Esta librería nos da la posibilidad de implementar el patrón de desarrollo MVC en Javascript además de otra gran cantidad beneficios.
Backbone.js posee cuatro clases principales:
  • Model
  • View
  • Router
  • Collection

[nota:fc148f99de]El siguiente tutorial es obtenido a partir de la lectura de otros tutoriales, la documentación de Backbone.js y las experiencias durante este proceso.[/nota:fc148f99de]

Manos a la obra


Primero vamos a crear una estructura HTML desde donde llamar nuestros archivos JS.

Código :

<!DOCTYPE html>  <html lang="es">     <head>        <meta charset='utf-8'>        <title>Introduccion a Blackbone.js + Mustache.js</title>     </head>     <body>        <!-- script -->        <script type="text/javascript" src="js/jquery.min.js"></script>        <script type="text/javascript" src="js/underscore-min.js"></script>        <script type="text/javascript" src="js/backbone-min.js"></script>        <script type="text/javascript" src="js/app.js"></script>     </body>  </html>

[nota:fc148f99de]Blackbone.js requiere estrictamente la librería Underscore.js para funcionar. Esta debe ir primero que blackbone.js[/nota:fc148f99de]

Model


En Backbone.js los modelos son el corazón de nuestra aplicación, imaginémoslos como un conjunto de atributos y métodos de la forma {key:value} donde los valores pueden ser funciones, objetos o arreglos.

Código :

  (function(){     var DesarrolladorModel = Backbone.Model.extend();  })();  
De esta forma hemos extendido todos los métodos y atributos de la clase Backbone.Model en DesarrolladorModel .


Agreguemos algunos atributos a nuestra clase DesarrolladorModel:

Código :

(function(){     var DesarrolladorModel = Backbone.Model.extend({        initialize: function(){           console.info("Nuevo modelo de: DesarrolladorModel");        },        defaults:{           nombre: "Pepito Perez",           edad: 24,           lenguajes:[]        }     });  })();

La función initialize como su nombre lo indica se ejecuta automáticamente al crear una nueva instancia de nuestro modelo. Por el momento no veremos ningún cambio.

[nota:fc148f99de]El atributo "defaults" nos permite definir valores por defecto para nuestro modelo.[/nota:fc148f99de]

Ahora vamos a crear una instancia de nuestro modelo DesarrolladorModel:

Código :

(function(){     // Crear modelo     var DesarrolladorModel = Backbone.Model.extend({        initialize: function(){           console.info("Nuevo modelo de: DesarrolladorModel");        },        defaults:{           nombre: "Pepito Perez",           edad: 24,           lenguajes:[]        }     });       // Crear instancia     var desarrollador = new DesarrolladorModel;  })();

Si nos fijamos en nuestra consola, vamos a ver el mensaje que definimos en la función del atributo initialize.

Para ver que atributos posee nuestro nuevo modelo puedes hacer esto:

Código :

console.dir(desarrollador.attributes);


También podemos definir unos atributos durante la creación del modelo:

Código :

(function(){     // Crear modelo     var DesarrolladorModel = Backbone.Model.extend({        initialize: function(){           console.info("Nuevo modelo de: DesarrolladorModel");        },        defaults:{           nombre: "Pepito Perez",           edad: 24,           lenguajes:[]        }     });       // Crear instancia     var desarrollador = new DesarrolladorModel;       // Crear otra instancia cambiando valores     var desarrollador2 = new DesarrolladorModel({        nombre: "Mario marito",        edad: 19,        lenguajes: ["Javascript", "C"],        editor: "Sublime Text 2"     });    })();


Podemos definir atributos aun después de creado el modelo a través del método .set():

Código :

(function(){     // Crear modelo     var DesarrolladorModel = Backbone.Model.extend({        initialize: function(){           console.info("Nuevo modelo de: DesarrolladorModel");        },        defaults:{           nombre: "Pepito Perez",           edad: 24,           lenguajes:[]        }     });       // Crear instancia     var desarrollador = new DesarrolladorModel;       // Crear otra instancia cambiando valores     var desarrollador2 = new DesarrolladorModel({        nombre: "Mario marito",        edad: 19,        lenguajes: ["Javascript", "C"],        editor: "Sublime Text 2"     });       // Agregando atributos posteriormente     desarrollador.set({editor: "Notepad++"});    })();


Para obtener los atributos individuales de cada modelo podemos usar el método .get():

Código :

desarrollador2.get("editor");


Ahora vamos a crear un método para nuestro modelo que nos permita agregar lenguajes de programación a las instancias.

Código :

(function(){     // Crear modelo     var DesarrolladorModel = Backbone.Model.extend({        initialize: function(){           console.info("Nuevo modelo de: DesarrolladorModel");        },        defaults:{           nombre: "Pepito Perez",           edad: 24,           lenguajes:[]        },        addLenguaje: function(nuevoLenguaje){           //Obtenemos lenguajes del model           var array_lenguajes = this.get('lenguajes');             //Adicionamos el nuevo lenguaje           array_lenguajes.push(nuevoLenguaje);             // Redefinimos el atributo lenguajes           this.set({lenguajes:array_lenguajes});        }     });       // Crear instancia     var desarrollador = new DesarrolladorModel;       // Crear otra instancia cambiando valores     var desarrollador2 = new DesarrolladorModel({        nombre: "Mario marito",        edad: 19,        lenguajes: ["Javascript", "C"],        editor: "Sublime Text 2"     });       // Agregando atributos posteriormente     desarrollador.set({editor: "Notepad++"});       // Agregar nuevo lenguaje     desarrollador.addLenguaje("Python");    })();


Bueno, hasta ahora nada del otro mundo, un montón de objetos con funciones dentro podrían decir ustedes, por eso seguimos con lo bueno de esta librería.

En Backbone.js podemos asignar eventos de escucha, es decir, cuando un atributo del modelo cambie generamos un evento particular.

Cuando la propiedad editor de nuestro modelo cambie, dispararemos un evento que genere un mensaje en consola:
[nota:fc148f99de]En este caso pondremos en escucha el evento desde el atributo "initialize", pero también puede ser llamado desde la instancia del modelo.[/nota:fc148f99de]

Código :

(function(){     // Crear modelo     var DesarrolladorModel = Backbone.Model.extend({        initialize: function(){           console.info("Nuevo modelo de: DesarrolladorModel");             // Escuchando cambios para el modelo           this.on("change:editor", function(){              console.log("Has modificado el editor");           });        },        defaults:{           nombre: "Pepito Perez",           edad: 24,           lenguajes:[]        },        addLenguaje: function(nuevoLenguaje){           var array_lenguajes = this.get('lenguajes');           array_lenguajes.push(nuevoLenguaje);           this.set({lenguajes:array_lenguajes});        }     });       // Crear instancia     var desarrollador = new DesarrolladorModel;       // Crear otra instancia cambiando valores     var desarrollador2 = new DesarrolladorModel({        nombre: "Mario marito",        edad: 19,        lenguajes: ["Javascript", "C"],        editor: "Sublime Text 2"     });       // Agregando atributos posteriormente     desarrollador.set({editor: "Notepad++"});       // Agregar nuevo lenguaje     desarrollador.addLenguaje("Python");    })();

En la consola debemos estar visualizando el mensaje que definimos en el evento change:editor.

Si deseáramos que el evento se iniciara al modificar cualquier atributo del modelo lo haríamos retirando el valor de change para que escuche sobre cualquier atributo.

Código :

this.on("change", function(){ ... });


Como dije anteriormente también podemos llamar el evento desde la instancia de nuestro modelo.

Código :

desarrollador.on("change:editor", function(){ ... });


Otra función de las muchas que poseen los modelos de Backbone.js es validate, la cual nos permite realizar validaciones previas a los cambios que se apliquen a las instancias de nuestros modelos.

Imagina que la función validate es un policía que te chequea antes de entrar, Si cumples con los requisitos te dejará pasar y podrás realizar tus actividades. Pero si no los cumples no te dejará pasar y mandará un mensaje de error.

Realizaremos una validación en nuestro modelo que se encargará de verificar si el editor de uno de nuestros desarrolladores (instancias de modelo) es Dreamweaver. Luego tendremos un evento en escucha de este error que nos genere un log en la consola con el mensaje de error.

Código :

(function(){     // Crear modelo     var DesarrolladorModel = Backbone.Model.extend({        initialize: function(){           console.info("Nuevo modelo de: DesarrolladorModel");             this.on("change:editor", function(){              console.log("Has modificado el editor");           });             // Evento a la escuha del error           this.on("error", function(model, error){              console.log(error);           });        },        defaults:{           nombre: "Pepito Perez",           edad: 24,           lenguajes:[]        },        addLenguaje: function(nuevoLenguaje){           var array_lenguajes = this.get('lenguajes');           array_lenguajes.push(nuevoLenguaje);           this.set({lenguajes:array_lenguajes});        },          // Funcion de validacion        validate: function(attributes){           if(attributes.editor == "Dreamweaver"){              return "Dreamweaver no es un editor permitido!";           }        }     });       // Crear instancia     var desarrollador = new DesarrolladorModel;       // Crear otra instancia cambiando valores     var desarrollador2 = new DesarrolladorModel({        nombre: "Mario marito",        edad: 19,        lenguajes: ["Javascript", "C"],        editor: "Sublime Text 2"     });       // Agregando atributos posteriormente     desarrollador.set({editor: "Notepad++"});     desarrollador.set({editor: "Dreamweaver"});       // Agregar nuevo lenguaje     desarrollador.addLenguaje("Python");  })();


Según lo anterior, en nuestra consola deberíamos tener dos mensajes. El primero con el mensaje de cambio de editor realizado correctamente y el segundo avisándonos que Dreamweaver no es un editor válido.

La función validate es muy sencilla. Recibimos los atributos, los verificamos y retornamos un mensaje de error.

Código :

      // Funcion de validacion        validate: function(attributes){           if(attributes.editor == "Dreamweaver"){              return "Dreamweaver no es un editor permitido!";           }        }


El evento on.("error") ubicado en el atributo de initialize recibe el modelo donde se produjo el error y el mensaje de dicho error. Finalizando la actividad que disparó el evento sin que ésta se lleve a cabo.

Código :

// Evento a la escuha del error           this.on("error", function(model, error){              console.log(error);           });

[nota:fc148f99de]Podemos obtener valores de los atributos aplicando el método ".get()" al modelo que recibimos en el evento error.[/nota:fc148f99de]

De esta forma terminamos el primer tutorial de Blackbone.js y modelos. Los invito a que lean la documentación que es muy completa y con ejemplos para todos los métodos.

En el segundo tutorial de Blackbone.js trataremos las vistas. Espero que este haya sido de su agrado.
[nota:fc148f99de]Yo también soy novato en el mundo de Blackbone.js, cualquier duda o sugerencia trataremos de resolverla entre todos. @vlycser :P [/nota:fc148f99de]

Enviar comentario

Detección y manejo de sensores en Android

Posted: 30 Apr 2012 06:25 AM PDT

Una de las características que más llamó la atención desde el primer dispositivo Android, es la implementación de diferentes tipos sensores, los cuales no parecen tener límites en los nuevos dispositivos que salen a la luz (¿De verdad se necesita un barómetro en el móvil?) y a la par de ello, su implementación a través de código se realiza de manera sencilla y rápida.

Para el manejo de los diferentes sensores disponibles es necesario hacer uso de estas clases:
  • Sensor, que representa al sensor de turno que estamos por utilizar.
  • SensorManager, que nos permite acceder a los sensores del dispositivo y la Interfaz.
  • SensorEventListener, que registra los cambios hechos en el sensor indicado con eso podemos empezar a registrar los cambios hechos en los sensores, y ahora…
¡manos al código!

Crear la Interfaz a utilizar


Para poder ver los cambios registrados por los sensores de nuestros dispositivos, vamos a implementar en nuestra interfaz dos TextView que nos permitirá mostrar el valor de los cambios ocurridos en nuestros sensores.

Código :

<?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"       android:orientation="vertical"       android:layout_width="fill_parent"       android:layout_height="fill_parent">       <TextView android:id = "@+id/etiqSensorDeMovimiento"       android:layout_width="fill_parent"       android:layout_height="wrap_content"       android:text="@string/etiqSensorDeMovimiento">       </TextView>       <TextView       android:id = "@+id/sensorDeMovimiento"       android:layout_width="fill_parent"       android:layout_height="wrap_content"       android:text="@string/hello">       </TextView>       <TextView       android:id = "@+id/etiqSensorDeOrientacion"       android:layout_width="fill_parent"       android:layout_height="wrap_content"       android:text="@string/etiqSensorDeOrientacion">       </TextView>       <TextView       android:id="@+id/sensorDeOrientacion"       android:layout_width="fill_parent"       android:layout_height="wrap_content"       android:text="@string/hello">       </TextView>  </LinearLayout>


Crear la Actividad


La actividad que vamos a crear hereda de Activity para otorgarle las características de una actividad e implementa SensorEventListener para el registro de cambios en el sensor.

Código :

public class SensorActivity extends Activity implements SensorEventListener{


Definir las variables a utilizar


En este caso, he definido 5 variables del tipo Sensor, los cuales utilizaré para guardar una instancia de cada sensor que pueda detectar usando un objeto de SensorManager, y 2 objetos de TextView, los cuales ya definimos en la interfaz y modificaremos a través de código.

Código :

    private SensorManager sensorManager = null;      private Sensor sensorDeTemperatura = null;      private Sensor sensorDeProximidad = null;      private Sensor sensorDeLuz = null;      private Sensor sensorAcelerometro = null;      private Sensor sensorDeOrientacion = null;      private TextView textViewAcelerometro = null;      private TextView textViewOrientacion = null;  


Detección de Sensores


Para poder obtener instancias de los sensores embebidos en el dispositivo Android, se utiliza SensorManager a través de la llamada al método getSystemService() que nos retorna un servicio a nivel de sistema, dependiendo del parámetro que le pasemos, en este caso SENSOR_SERVICE, pues queremos hacer uso de los sensores.

Una vez inicializado sensorManager, podemos hacer uso de este objeto para solicitar instancias de los diferentes tipo de sensores haciendo uso del método getDefaultSensor() y añadiendo el tipo de sensor que queremos como parámetro.

Código :

public void onCreate(Bundle savedInstanceState) {      super.onCreate(savedInstanceState);      sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);      sensorDeProximidad = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);      sensorDeTemperatura = sensorManager.getDefaultSensor(Sensor.TYPE_TEMPERATURE);      sensorDeLuz = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);      sensorAcelerometro = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);      sensorDeOrientacion = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);  


Registro del manejador de Eventos de los sensores


Existe la posibilidad de que nuestro dispositivo no tenga todos estos sensores que pensamos, por ejemplo, en el dispositivo que yo estoy utilizando no hay sensor de Temperatura, por lo que siempre es buena idea hacer un filtro que nos permita identificar con cuáles sí contamos, y añadir el manejador de eventos de acuerdo a eso.

El siguiente código lo hace de una manera sencilla: si el sensor existe, registra el manejador de eventos usando el método registerListener() del objeto sensorManager, al que se le pasa como parámetros la clase que está implementando la interfaz SensorEventListener, el sensor que se quiera registrar y la velocidad de registro de cambios en el sensor.

Código :

if(sensorAcelerometro == null){          Toast.makeText(getApplicationContext(), "No hay Sensor movimiento", Toast.LENGTH_SHORT).show();  }  else{            Toast.makeText(getApplicationContext(), "Hay Sensor de movimiento", Toast.LENGTH_SHORT).show();            sensorManager.registerListener(this, sensorAcelerometro, SensorManager.SENSOR_DELAY_NORMAL);  }     if(sensorDeProximidad == null){            Toast.makeText(getApplicationContext(), "No hay Sensor de Proximidad", Toast.LENGTH_SHORT).show();  }  else{            Toast.makeText(getApplicationContext(), "Hay Sensor de Proximidad", Toast.LENGTH_SHORT).show();            sensorManager.registerListener(this, sensorDeProximidad, SensorManager.SENSOR_DELAY_NORMAL);  }     if(sensorDeLuz == null){           Toast.makeText(getApplicationContext(), "No hay Sensor de Luz", Toast.LENGTH_SHORT).show();  }  else{            Toast.makeText(getApplicationContext(), "Hay Sensor de Luz", Toast.LENGTH_SHORT).show();            sensorManager.registerListener(this, sensorDeLuz, SensorManager.SENSOR_DELAY_NORMAL);  }     if(sensorDeTemperatura == null){           Toast.makeText(getApplicationContext(), "No hay sensor de Temperatura", Toast.LENGTH_SHORT).show();  }  else{            Toast.makeText(getApplicationContext(), "Hay sensor de Temperatura", Toast.LENGTH_SHORT).show();           sensorManager.registerListener(this, sensorDeTemperatura, SensorManager.SENSOR_DELAY_NORMAL);  }     if(sensorDeOrientacion == null){            Toast.makeText(getApplicationContext(), "No hay sensor de Orientacion", Toast.LENGTH_SHORT).show();  }  else{            Toast.makeText(getApplicationContext(), "Hay sensor de Orientacion", Toast.LENGTH_SHORT).show();            sensorManager.registerListener(this, sensorDeOrientacion, SensorManager.SENSOR_DELAY_NORMAL);  }


Registro de Variables de la Interfaz



Esta parte es sencilla, es sólo inicializar los TextView definidos en la interfaz anterior

Código :

        setContentView(R.layout.main);             textViewAcelerometro = (TextView) findViewById(R.id.sensorDeMovimiento);          textViewAcelerometro.setTextSize(30);             textViewOrientacion = (TextView) findViewById(R.id.sensorDeOrientacion);          textViewOrientacion.setTextSize(30);  }  


Implementación de los métodos de la Interfaz



La Interfaz SensorEventListener nos pide implementar 2 métodos:

  • onAccuracyChanged(Sensor sensor, int accuracy), en la cual implementaremos las acciones a realizar cuando se cambia la precisión de un sensor.

  • onSensorChanged(SensorEvent event), la cual nos permite implementar las acciones a realizar cuando un sensor registre un cambio.


Código :

@Override  public void onAccuracyChanged(Sensor arg0, int arg1) {  }     @Override  public void onSensorChanged(SensorEvent arg0) {     synchronized (this){        float[] masData;        float x;        float y;        float z;        // TODO Auto-generated method stub        switch(arg0.sensor.getType()){           case Sensor.TYPE_PROXIMITY:              masData = arg0.values;              if(masData[0]==0){                 textViewAcelerometro.setTextSize(textViewAcelerometro.getTextSize()+10);              }              else{                 textViewAcelerometro.setTextSize(textViewAcelerometro.getTextSize()-10);              }              break;                          case Sensor.TYPE_ACCELEROMETER:                              masData = arg0.values;                        x = masData[0];              y = masData[1];                                  z = masData[2];                                  textViewAcelerometro.setText("x: " + x + "\ny: "+y + "\nz: "+z);              break;                       case Sensor.TYPE_ORIENTATION:              masData = arg0.values;              x = masData[0];              y = masData[1];              textViewOrientacion.setText("x: " + x + "\ny: "+y);              break;           default:              break;           }        }     }


En este caso se ha implementado de manera que muestre en un TextView las variaciones registradas por los sensores.

Recomendaciones



El uso de los sensores requiere de más energía por parte de la aplicación a diferencia de las que no lo hacen, por lo que es recomendable liberar al manejador de eventos cuando se vaya a salir de la aplicación e implementarla de nuevo cuando se vaya a hacer uso de ésta nuevamente. Esto se puede hacer de la siguiente manera:

Código :

          @Override     protected void onResume() {        super.onResume();        sensorManager.registerListener(this,sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),SensorManager.SENSOR_DELAY_NORMAL);     }        @Override     protected void onPause() {        sensorManager.unregisterListener(this);        super.onStop();     }


Espero les sea de utilidad este tutorial, dudas, preguntas, quejas o sugerencias, nos encontramos en los comentarios más abajo, si les gustó no se olviden de compartir =)

ENJOY!!!

Enviar comentario

Los modos de color en Photoshop

Posted: 10 Apr 2012 12:50 AM PDT

Para los que comienzan en el diseño web, gráfico, etc. o con Photoshop, es muy común que sólo tengan conocimientos básicos de los modos de Color en Photoshop. En este tutorial les quiero mostrar los Modos de Color que tenemos en Photoshop y en qué caso podemos aplicar un determinado Modo de Color.

Para que entiendan a qué me refiero con respecto a los modos de Color de una imagen, estos modos los podemos ver en nuestro Photoshop accediendo al menú: imagen > Modo.



Bueno ahora veamos un concepto básico y el uso básico de cada modo de color de una imagen:

Modo de mapa de bits


Para pasar una imagen a Modo de Mapa de Bits, tenemos que ponerla primero a Modo: Escala de Grises.
El modo Mapa de bits utiliza uno de los dos valores de color (blanco o negro) para representar los píxeles de una imagen.



Las imágenes en modo Mapa de bits se denominan imágenes de 1 bit en mapa de bits porque tienen una profundidad de bits de 1.

Usos:
El modo mapa de bits es muy útil para distintos tipos de trabajos:

  • Para modificar su gama de grises, aclarando u oscureciendo.
  • Para ver cuántos puntos o pixeles tiene tu imagen (mientras menos puntitos o pixeles tenga, tu imagen
  • se podría pixelar con más facilidad)
  • Podemos darle a nuestra imagen un zoom en modo mapa de bits y editar cuadrito x cuadrito o pixel por pixel.




Modo de escala de grises


El modo Escala de grises utiliza distintos tonos de gris en una imagen, sus variantes de color abarcan toda la escala de color del blanco al negro.



En imágenes de 8 bits, puede haber hasta 256 tonos de gris. Cada píxel de una imagen en escala de grises tiene un valor de brillo comprendido entre 0 (negro) y 255 (blanco). En imágenes de 16 y 32 bits, el número de tonos de una imagen es mucho mayor que en las imágenes de 8 bits.

Usos:
El modo escala de grises es muy útil para distintos tipos de trabajos:

  • Para controlar las luces o la luminosidad de una imagen. (En modo Escala de Grises es más fácil ver estos factores y poder manipularlos).
  • Para eliminar la información del color de una fotografía y convertir los píxeles en grises como son las fotografías de los diarios.
  • Para dar un efecto de imagen antigua en blanco y negro.
  • Para imágenes web en blanco y negro.
  • Para trabajos en la imprenta que requiera de imágenes en blanco y negro.


Modo Duotono


Para convertir nuestra imagen a Modo Duotono, primero debemos pasar la imagen a modo Escala de grises y después a modo Duotono.

En el modo Duotono podemos usar de 2 a 4 colores específicos:
  • Monótonos (escala de gris ).
  • Duotonos (dos colores).
  • Tritonos (tres colores).
  • Cuadritonos (cuatro colores).


Utilizamos de 2 a 4 tintas personalizadas, pueden ser Pantones personalizados para darle colores más exactos.



Este modo de color es usado para la impresión de tintas directas y reducir el número de ellas. En este modo nuestra imagen siempre va contar con un sólo canal en nuestro documento.

Usos:
El modo Duotono es muy útil para distintos tipos de trabajos:
  • Para aumentar la riqueza tonal de una imagen en escala de grises.
  • Para trabajos de impresión en dos colores en los que se utiliza una tinta plana (como PANTONE) para resaltar el trabajo.
  • Para hacer la imagen corporativa en base a esos 2 a 4 colores específicos. Acá guardamos nuestros pantones o colores específicos en Duotono ya que luego servirán para los demás productos de marketing o publicidad de la corporación (bolsas, hojas membretadas, tarjetas personales, banners, etc.)


Modo Indexado


Para convertir una imagen a Modo Color indexado primero debemos pasarla a Modo RGB.

El modo Color indexado produce archivos de imágenes de 8 bits con un máximo de 256 colores. Al convertir a color indexado, Photoshop crea una tabla de colores de consulta (CLUT) que almacena y genera el índice de los colores de la imagen. Si un color de la imagen original no aparece en la tabla, el programa selecciona el más parecido o emplea el tramado para simular el color utilizando los colores disponibles.

Este modo es muy utilizado en el diseño web, ya que se caracteriza por hacer una reducción al tamaño o peso del archivo manteniendo la calidad visual necesaria para presentaciones multimedia, páginas Web y usos similares.
Los archivos de color indexado se pueden guardar en los siguientes formatos: Photoshop, BMP, DICOM (Digital Imaging and Communications in Medicine), GIF, EPS de Photoshop, Formato de documento grande (PSB), PCX, PDF de Photoshop, RAW de Photoshop, Photoshop 2.0, PICT, PNG, Targa® o TIFF.

Es muy común encontrar estas imágenes en las plantillas de los CMSs Joomla, Wordpress, etc, ya que este modo es uno de los favoritos de los diseñadores web.

Cuando pasamos una imagen a este modo, nuestro panel de capas la renombra con el nombre Índice, como podemos ver en la imagen:



Usos:
El modo Indexado es muy útil para distintos tipos de trabajos:
  • Para diseño web por el bajo peso de las imágenes (recordemos que las imágenes para una página web no debe pesar mucho, si no la carga de nuestra web tomará mucho tiempo).


Modo RGB


Junto al modo CMYK es uno de los más importantes modos. Todo lo que es virtual o lo que vemos en internet, en tu ipod, celular, ipad, etc, etc está en modo RGB.
Las siglas RGB significan RED, GREEN y BLUE (Rojo, Verde y Azul)
Es el modo por defecto que usa nuestro monitor y las imágenes que vemos en las páginas webs.
Este modo utiliza el modelo RGB y asigna un valor de intensidad a cada píxel. En imágenes de 8 bits por canal, los valores de intensidad varían de 0 (negro) a 255 (blanco) para cada uno de los componentes RGB (rojo, verde, azul) de una imagen en color.
Por ejemplo, un color rojo fuerte podría tener un valor R de 246, un valor G de 20 y un valor B de 50(R-G-B). Si los valores de los tres componentes son idénticos, se obtiene un tono de gris neutro. Si los valores de todos los componentes dan 255, el resultado es blanco puro, y negro puro si el valor es de 0.

Además de ser el modo por defecto en las imágenes nuevas de Photoshop, el modelo RGB lo utilizan los monitores de los ordenadores para mostrar los colores. Esto significa que, si se trabaja en modos de color distintos a RGB, como CMYK, Photoshop convierte la imagen CMYK a RGB para la visualización en pantalla.



Usos:
El modo RGB es muy útil para distintos tipos de trabajos:
  • Para diseño web por su poco peso de estas imágenes.
  • Por su bajo peso: para trasladarlas en dispositivos USB, CDs, DVDs, o enviarlas por E-mail.
  • Para impresión en impresoras domésticas.


Modo CMYK


Las siglas CMYK significan: Cyan, Magenta, Yellow, Black (Cian, Magenta, Amarillo y Negro).

Junto al modo RGB es el modo más importante, pero dentro de la industria de la Gráfica Impresa. A diferencia del modo RGB esta imagen es todo lo que vemos en el mundo impreso, todos los diseños como afiches, cuadernos, revistas, libros, etc, etc. fueron trabajados en modo CMYK.

En el modo CMYK, a cada píxel se le asigna un valor de porcentaje para las tintas de cuatricromía. En las imágenes CMYK, el blanco puro se genera si los cuatro colores tienen valores del 0%.

El modo CMYK se usa mucho en la preparación de imágenes que se van a imprimir utilizando cuatricromía. También se puede utilizar el modo CMYK para trabajar directamente con imágenes CMYK escaneadas o importadas de sistemas de alta resolución.

Aunque CMYK es un modelo de color estándar, puede variar el rango exacto de los colores representados, dependiendo de la imprenta y las condiciones de impresión. El modo Color CMYK de Photoshop varía de acuerdo con el ajuste del espacio de trabajo especificado en el cuadro de diálogo Ajustes de color.



Usos:
El modo CMYK es muy útil para distintos tipos de trabajos en físico y real a diferencia del RGB que es algo abstracto o virtual y no lo podemos tocar, en cambio el trabajo en CMYK, ya que va ser impreso si lo vamos a poder tocar:
  • Impresión de bolsas, revistas, libros, etc.
  • Gigantografías, letreros y anuncios desde pequeños a grandes tamaños.

Para resumir, todo lo que vemos impreso fue trabajado en CMYK.

Modo Lab


LAB significa: Luminosidad A y B.

La Particularidad es la de ser independientemente del dispositivo de almacenamiento.
Consta de tres canales: Luminosidad, A y B y que aunque suene un poco a chino, es el modelo que más se acerca a la forma que tiene el ojo humano de percibir los colores.

Los valores numéricos de Lab describen todos los colores que ve una persona con una capacidad de visión normal. Como Lab describe la apariencia del color en lugar de la cantidad de colorante necesaria para que un dispositivo (como un monitor, una impresora de escritorio o una cámara digital) produzca el color, Lab se considera un modelo de color independiente de dispositivo. Los sistemas de gestión de color utilizan Lab como referencia de color para transformar un color de forma predecible de un espacio de color a otro.



Las imágenes Lab se pueden guardar en distintos formatos: Photoshop, EPS de Photoshop, Formato de documento grande (PSB), PDF de Photoshop, RAW de Photoshop, TIFF, DCS 1.0 de Photoshop o DCS 2.0 de Photoshop. Las imágenes Lab de 48 bits (16 bits por canal) se pueden guardar en estos formatos: Photoshop, Formato de documento grande (PSB), PDF de Photoshop, RAW de Photoshop y TIFF.

Nota: los formatos DCS 1.0 y DCS 2.0 convierten el archivo a CMYK al abrirlo.

Usos:
El modo LAB es muy útil:
  • Para editar, seleccionar y usar nuestros propios colores, con la característica que estamos viendo nosotros mismo esos colores (una persona que tiene problemas para diferencia los colores, no le es recomendable hacerla trabajar en este modo).
  • Como punto intermedio de conversión entre modos, pues se trata del modo que puede representar una mayor gama de colores y porque es independiente del dispositivo, con lo que aseguramos una mejor conversión.
  • Para conseguir efectos o retoques curiosos.


Modo Multicanal


Las imágenes de este modo contienen 256 niveles de gris en cada canal, por lo que se utilizan en impresión especializada. Las imágenes de modo Multicanal se pueden guardar en formato Photoshop, Formato de documento grande (PSB), Photoshop 2.0, RAW de Photoshop o DCS 2.0 de Photoshop.

Al pasar una imagen a modo Multicanal debemos considerar lo siguiente:
  • Las capas no se admiten y, por lo tanto, se acoplan.
  • Los canales de color de la imagen original se convierten en canales de tinta plana en la imagen convertida.
  • Convertir una imagen CMYK al modo Multicanal crea canales de tintas planas cian, magenta, amarillo y negro.
  • Convertir una imagen RGB al modo Multicanal crea canales de tintas planas cian, magenta y amarillo.
  • La eliminación de un canal de una imagen RGB, CMYK o Lab convierte automáticamente la imagen al modo Multicanal y acopla las capas.
  • Para exportar una imagen multicanal, guárdela en el formato DCS 2.0 de Photoshop.
  • El color indexado y las imágenes de 32 bits no pueden convertirse al modo Multicanal.


Usos:
El modo Multicanal es muy útil:
  • Editar cada color por canal de una imagen. Por ejemplo recordemos que cuando pasamos una imagen a Modo Duotono (duotonos, tritonos y cuadritonos), sólo nos crea un canal, por lo que no es posible tratar cada tinta de forma distinta según las zonas de la imagen. Entonces si esta imagen Duotono la pasamos a Multicanal, nos creará un canal para cada tinta y poder editarla, y entonces en este modo, cada tinta es un canal que a la hora de imprimir se superpondrá en el orden que determinemos sobre los otros.







8 bits, 16 bits o 32 bits


Estas indican la profundidad de una imagen. Las imágenes con más "bits" son "mejores". Y tiene su parte de verdad. No obstante, afirmar que las fotos con menos paleta de color (menos cantidad de "bits por canal") son peores, no es absolutamente cierto.

Mientas mas bits, tenga nuestra imagen va tener más información de color.

Yo lo tengo puesto a 8 bits. A 8 bits es perder calidad del RAW y a 32 bits los archivos serán más grandes y necesitarás más equipo para trabajarlos. Con 16 no pierdes calidad ya que hace una "interpolación" de 12 o 14 a 16 bits y no tiene que recortar tonos.

Enviar comentario

Introducción a MongoDB

Posted: 09 Apr 2012 08:09 AM PDT

MongoDB es un sistema de bases de datos NoSQL orientado a documentos, a diferencia de MySQL, este no es una base de datos relacional. Es open source, lleva entre nosotros desde el 2009. Está escrito en C++ y tiene intención de aumentar la escalabilidad de un sistema. Es compatible con Linux, OS X, Windows y Solaris.

Además de MongoDB existen otros sistemas NoSQL como por ejemplo Cassandra, CouchDB, Redis, Riak, Membase, Neo4j y HBase.



Considera que mongoDB fue diseñado para ser un motor de búsqueda sobre aplicaciones en la nube, debes de ser bien específico al momento de elegir un sistema NoSQL. Esto porque tienen diferentes funciones o están optimizados para diferentes tareas: Como Cassandra que fue diseñado para búsquedas en Facebook.



Si buscas un framework en PHP para poder utilizar MongoDB inmediatamente puedes probar alguno de los siguientes: CakePHP, Codeigniter, Doctrine, Drupal, Kohana, Lithium, Memcached, Symfony 2, Yii y Zend Framework.

Si buscas utilizarlo con Python prueba con PyMongo.

Conceptos básicos


Una base de datos en MongoDB tiene diferentes conceptos a una base de datos regular como MySQL. Cada registro o unidad básica de datos se le denomina documento. Y cada conjunto de documentos, que formarían una tabla, se le llama colección.

Un documento se podría comprar con el concepto de fila y una colección a una tabla.

Organización y sistema


La ventaja que tiene MongoDB ante las bases de datos racionales es la velocidad de consulta. Esto se logra gracias a que los documentos son almacenados en formato BSON, que es una versión modificada del ya conocido JSON.

BSON pesa un poco más que un JSON regular, pero gracias a que este guarda longitudes de campos, índices de arrays, entre otras cosas, es mucho más rápido (y menos costoso), acceder a la información que se consulta.

Al final del día no vamos a ver el formato BSON, así que no te preocupes, siempre lo leerás como un JSON regular.

Documentos


Los documentos son un conjunto de claves con valores asociados. Sin embargo, cabe destacar que en cada lenguaje es diferente el "output".

Código :

  { "pepito" : "uno" }    

Igual cabe destacar que una clave puede contener varios valores asociados como por ejemplo:

Código :

  { "pepito" : "uno", "dos" : 3 }    


Notas importantes
- Las claves de un documento son strings.
- No se deben utilizar caracteres como punto y el signo de dólar.
- No deben de comenzar con guión bajo.
- Las claves son sensibles a mayúsculas y minúsculas.
- No debe contener claves duplicadas.
- Cada documento tiene una _id única generada a partir de diversos métodos, así siempre será diferente.

Colecciones


Una colección nos ayuda a organizarnos de manera mucho más fácil y rápida.

Código :

> db.pepito.insert()  > db.pepito.find()  > db.pepito.drop()  


Notas importantes
- Mantener diferentes tipos de documentos en una misma colección es de masoquistas.
- Un string vacío no es un nombre válido, así como no se puede utilizar un string con signo de dolar.
- Es más rápido obtener una lista de documentos que mantengan la misma estructura.
- Siempre planea la estructura de tus colecciones y documentos antes de comenzar.

Manejo de datos desde la shell


Ya que este artículo es únicamente una introducción, no entraré en detalles de cómo instalarlo o utilizarlo con algún lenguaje. Únicamente desde la shell que viene por defecto o desde aquí (haciendo clic en "Try It Out")

Para hacer una inserción y guardarla escribimos lo siguiente para obtener algo parecido a pepito = tontito

Código :

  db.pepito.save( { "pepito" : "tontito" } )    

Y para imprimir el contenido

Código :

  db.pepito.find()    

El siguiente script inserta en el documento varios elementos en forma de tags, después usa una función para contar cada elemento con un foreach, separa los elementos y devuelve la cantidad de elementos en otro documento.

Código :

$ ./mongo  > db.things.insert( { _id : 1, tags : ['perro', 'gato'] } );  > db.things.insert( { _id : 2, tags : ['gato'] } );  > db.things.insert( { _id : 3, tags : ['raton', 'gato', 'perro'] } );  > db.things.insert( { _id : 4, tags : []  } );    > // función de mapeo  > m = function(){  ...    this.tags.forEach(  ...        function(z){  ...            emit( z , { count : 1 } );  ...        }  ...    );  ...};    > // función reductora  > r = function( key , values ){  ...    var total = 0;  ...    for ( var i=0; i<values.length; i++ )  ...        total += values[i].count;  ...    return { count : total };  ...};    > res = db.things.mapReduce(m, r, { out : "myoutput" } );  > res  {     "result" : "myoutput",     "timeMillis" : 12,     "counts" : {        "input" : 4,        "emit" : 6,        "output" : 3     },     "ok" : 1,  }  > db.myoutput.find()  {"_id" : "gato" , "value" : {"count" : 3}}  {"_id" : "perro" , "value" : {"count" : 2}}  {"_id" : "raton" , "value" : {"count" : 1}}    > db.myoutput.drop()  

Existen muchos más comandos, todos ellos están en la documentación, con el comando help, documentación o desde la shell de mongodb.org escribiendo tutorial para un rápido pero informativo tutorial.



¿Tienes dudas? Dejame un comentario aquí o sígueme en twitter @kinduff.

En el próximo tutorial les enseñaré como generar bases de datos, leerlas y modificarlas.

Enlaces de interés


- Página principal de mongoDB [link]
- Documentación mongoDB [link]
- Sourcecode + drivers para diferentes lenguajes y sistemas [link]
- NoSQL: If Only It Was That Easy [link]
- Cassandra vs MongoDB vs CouchDB vs Redis vs Riak vs HBase vs Membase vs Neo4j [link]
- [NSFW] Relational Database Vs NoSQL Fanbois [link]

Enviar comentario

Qué significa que Facebook compre Instagram

Posted: 09 Apr 2012 05:40 AM PDT

Wow. Mark Zuckerberg anunció que Facebook compró Instagram por mil millones de dolares (un billón gringo). Instagram nació como una aplicación para aplicar efectos especiales a las fotos tomadas con un iPhone, evolucionó a ser una red social privada de fotografía y la semana pasada anunció su llegada a los teléfonos Android. Es la app de fotos más exitosa de la historia y ahora parte de Facebook.

Y si esta compra no demuestra la burbuja tecnologica, no sé qué más pensar.


Hay 3 cosas que me quedan claras con esta compra:

La creación de contenido en dispositivos móviles es el mercado más caliente del momento


El gran problema de los smartphones y las tablets es que son vistas como dispositivos de consumo, más que plataformas para crear contenido. Apple lo sabe y por eso enfocó al iPad 3 (Pepito) como LA tablet para crear música, editar fotografías, componer videos profesionales y en general: Crear.

En el último mes hubo dos compras gigantes en el mundo móvil: OMGPOP (Draw me Something) por Zynga y ahora Instagram por Facebook. Un juego y una camarita. Dos apps increiblemente exitosas en hacer que los usuarios de móviles creen.

Eso sumado al lanzamiento de la espectacular "Paper" para iPad.

¿Quieres hacer platita? Programa apps móviles que le permitan a los usuarios crear.


¡El dinero ya no vale nada, carajo!


No, en serio, nada. Ayer leía un artículo de un emprendedor elegido por YCombinator donde, en su primera reunión con Venture Capitalists, los inversionistas le tiraban dinero a la cara, le pedían poder unirse a su idea, lo perseguían con pasión. Hay tanto dinero gringo, tantos fondos, tantas valuaciones locas, que la percepción de dinero en el mundo de las startups está en su momento más raro.

Esto es lo que se sentía a finales del 2004. Es lo que se sentía por el 2001. Es la punta de la ola en la burbuja del dinero en internet. Si lograste hacer plata en esta epoca, es hora de comprarte una casa en la playa, contratar a un mayordomo que se cambie el nombre a Alfred y darte por bien servido. Viene la explosión de la burbuja.

Y tengan en mente, esto lo hace Facebook justo antes de salir a la bolsa a levantar aun más plata. Es más rentable aprender a programar que traficar con droga en estas épocas.

Invertir tu tiempo y talento en una app sin modelo de negocio sigue sin tener sentido


Esto es lo que me preocupa de Twitter todos los días de mi vida. Afortunadamente, mi cuenta de Twitter ya amortizó el costo que tiene mantenerla.

Mucha gente publica montones de fotos diarias en Instagram, gente que no sabe si esas fotos seguirán ahí mañana o si a Facebook le da por matar todo, desactivar la conexión con Twitter o hacer la conexión con Facebook "obligatoria". Gran parte del atractivo de Instagram era crear una segunda red de amigos cercanos con quien compartir fotos privadas de los hijos o en el espejo del baño. Lo que siempre quiso y nunca pudo crear Path.

Ahora, no sé sabe qué pasará. Facebook dice que mantendrá todo igual, que Instagram será independiente y bla bla bla. Las empresas cambian de estrategia y de opinión. Palm murió, el Playbook fue un fracaso, Google Wave desapareció, Tweetdeck se estancó, Jaiku fue cerrado, etc, etc, etc. Hoy Instagram sigue viva ¿Mañana?

Esto pasa con las empresas llenas de hype y faltas de ingresos. Eso es una gran adquisición para Facebook ¿Pero le conviene a los usuarios que han invertido meses en crear algo único dentro de Instagram?


Lo que importa es que, hoy más que nunca, crear apps móviles que creen contenido es más valioso que tener una empresa que haga plata. ¡A aprender a programar y que viva la burbuja!

Enviar comentario

"10 Secretos para construir tu lista de suscriptores profesionalmente"

Fernando

Sabes… A finales del mes que viene
estamos por lanzar una nueva formula
de Negocios en Internet que va a
revolucionar completamente el mercado,
diferente a cualquier cosa que hallas
visto antes y que estamos 100% seguros
de batir todos los récord en ventas.


La verdad es que no puedo decirte
mucho mas por el momento! Si que…
vas a poder participar con nosotros
como Afiliado y hacer muy buen dinero.

Lo que si quiero hacer mientras tanto
es mostrarte como incrementar uno de
los activos más valioso de tu negocio
en Internet.

Eso es… la lista de suscriptores.

Cuanto mayor es tu lista, más dinero
que puedes hacer cada mes.

Es un hecho:

¿Sabias que ahora mismo puedes hacer un
promedio de $1 al mes por cada persona
en tu lista de correo electrónico?

Cuando tienes 100 personas en la lista:
=> Ganas $100 al mes.

Cuando tienes 1.000 personas en la lista:
=> Ganas $1.000 al mes.

Cuando tienes 10.000 personas en la lista:
=> Ganas $10.000 al mes.

Cuando tienes 100.000 personas en la lista:
=> Ganas $100.000 al mes.

En este reporte gratuito "10 Secretos
para construir tu lista de suscriptores
profesionalmente" encontrarás 10 de los
más importantes puntos a tomar en cuenta
para desarrollar con éxito esta importante
tarea.

Regístrate aquí para descubrir los secretos
de cómo aumentar tus ganancias y recibe
este increíble ebook 100% gratis.

Un abrazo!

@FernandoMuñiz

PD: Estáte pendiente pues lo que te vamos
a estar mostrando el mes que viene te va a
volar completamente la cabeza.
Te va a gustar mucho. Dalo por hecho!

33213 GIJON - Asturias. España





































-

Para cancelar la suscripcion en esta lista y no recibir mas mensajes clic aqui
http://www.gvomail.com/unsubscribe.php?k=2f9e780a4b23e2a24f2fd444f6d63f34&fk=e7c4cc03d04e9bda39baa838b3de403b099fd5ad2b79cd19d2f859d8b67f1e6ed2d4d9be6d31b83f65c40d75aff95992

domingo, 29 de abril de 2012

Cristalab

Cristalab


El MundoReal(tm)

Posted: 15 Apr 2006 05:00 PM PDT

Nuestro personajillos se preguntan que hay más allá de la tira.

Oh nuestro webmaster!

Posted: 13 Apr 2006 05:00 PM PDT

Nos prohibieron publicar este comic. Era lo mejor. Nos dijeron "Hagan algo impactante". Pero algo terriblemente malo paso. Ahora, una orden judicial nos obliga a mostrarlo. Contra nuestra voluntad.