viernes, 29 de febrero de 2008

Timer para ABAP

Estoy intentando programar un space invaders en ABAP -ya saben el de las navecitas- y bueno... tengo la necesidad de ejecutar eventos que se repitan en un intervalo establecido, y ya que aprendí a usar el timer, decidí poner un ejemplo super sencillo aca.

Este programa, escribe "hola" en un report y luego cada 3 segundos escribe "hola otra vez!!"

*&---------------------------------------------------------------------*
*& Autor: Carlos Agreda *
*& Fecha: Feb 29 (Es biciesto) 2008 *
*&---------------------------------------------------------------------*

REPORT ZEJ_TIMER.
data: temporizador type ref to cl_gui_timer.
* Definición del manejador de eventos ------------------------------------
class lcl_event_handler definition.
     public section.
          class-methods: on_Timer for event finished of cl_gui_timer
          importing sender.
endclass.
* Implementación del manejador de eventos ------------------------------
class lcl_event_handler implementation.
     method on_Timer.
          write: 'Hola otra vez!!'.
          sender->run( ).
     endmethod.
endclass.

start-of-selection.
     create object temporizador.
     set handler lcl_event_handler=>on_Timer for temporizador.

     temporizador->interval = 3. "el tiempo va en segundos
     temporizador->run( ).
     write: 'Hola'.

sábado, 16 de febrero de 2008

Esteganografia en Imagenes (LSB)

Este es un un trabajo que presente en la universidad el 2004 para el curso de Algebra Universal, y quiero postearlo por aqui para que no se pierda en el olvido.

Es una aplicacion de esteganografia que permite ocultar un texto ascii o inclusive un archivo binario cualquiera dentro de una imagen BMP de 24 bits.

Esteganos: Oculto, Grafia: Escrito
La esteganografía tiene como objeto de estudio las técnicas que permitan ocultar información detrás de otros datos; de tal forma que al ser "mezclados" sean visibles solo los datos de soporte y nuestra información confidencial pase desapercibida ante los ojos de cualquier observador.

Ej.
Otro ejemplo.

La iglesia mas antigua, puso el rumor ultimo.

...si extraemos la primera letra de cada palabra obtenermos:
La iglesia mas antiguaa, puso el rumor ultimo. = Lima peru.

Este es un ejemplo muy sencillo en texto, ya se les podra ocurrir miles de ideas distintas para ocultar sobre texto, pero... como ocultar sobre una imagen?

La primera alternativa para ocultar un mensaje (bits) sobre un BMP de 24 bits es aprovechar su estructura simar al siguiente grafico. solo debemos ocultar nuestros datos justo despues de los metadatos (primeros 54 bytes) y modificar el campo offset (campo que guarda la distancia entre los metadatos y los pixeles) de tal manera que podamos hacer espacio para todo lo que queremos esconder.
Esta alternativa si bien es cierto es muy sencilla de implementar tiene el defecto de que la imagen obtenida sera considerablemente grande, seria extranho tener una imagen de un icono (10x10) que nos ocupe 10 Mb no?

Otra alternativa -desde mi parecer mucho mejor- es esconder lo que queremos esconder en los LSB de cada componente de un pixel.

En espanhol:

Cada pixel, en un archivo BMP (de 24 bits), esta representado por 3 bytes conteniendo la intensidad de color para ROJO, VERDE y AZUL (RGB: red, green, blue). Entonces combinando valores en esas posiciones podemos obtener los = (16777216) colores que puede mostrar un pixel, habitualmente se dice 16 millones de colores, pero son un poquito mas.

Bueno entonces... cada byte contiene un valor entre 0 y 255 (en binario 00000000 y 11111111), estos bytes igual que en el sistema decimal conforme sus cifras esten mas a la izquierda tendran mas valor (peso) por citar un ejemplo:

5768, si cambiamos la primera cifra (la mas significativa) a 3 nos queda 3768, la diferencia es notable. Pero si cambiamos la ultima cifra (la menos significativa) por ejemplo a un 2 nos queda 5762, la diferencia es relativamente minima.

Con esto quiero decir que podemos modificar los LSB (less significant bits, o cifras menos significativas) sin producir mayor alteracion.

Un caso:

Si observamos estos dos pixels, tan solo se le ha cambiado una unidad a cada componente R, G, B, y la variacion de color ha sido minima. Al ojo humano son practicamente el mismo color.


Con esto hemos logrado sembrar 3 bits que originalmente eran 101 ahora hemos sembrado 010, eso significa que por cada pixel podemos almacenar 3 bit sin producir un cambio aparente en el pixel.

Si repetimos este paso, recorriendo los pixels de la imagen, podemos ir sembrando (ocultando) los bits que querramos dentro de nuetra imagen. En cada pixel podremos poner 3 bits es decir necesitaremos masomenos 8 pixels para poner 3 bytes (un byte tiene 8 bits :P).



Como se puede ver no es muy dificil


Esta es una imagen que contiene un mensaje, si logran recuperarlo lo comentan :P



La imagen de bart con el mensaje la pueden descargar aqui.
La aplicacion ejecutable la pueden descargar aqui.
El codigo fuente para vb 6, lo pueden descargar aqui.
Un instalador de la aplicacion lo pueden descargar de aqui.


y si no tienen el winrar lo pueden descargar de aqui


Saludos.


viernes, 15 de febrero de 2008

SAP Consultant Certification

Navegando por ahi me tope con los contenidos para la certificación ABAP. Me pareció util postearlo por aca.

Number of certification questions: 80
Courses for certification preparation: TAW10 (ABAP Workbench Fundamentals); TAW12 (ABAP Workbench Concepts)
Please note that you are not allowed to use any reference materials during the certification test (no access to online documentation or to any SAP system).
The certification test Development Consultant SAP NetWeaver 2004– Application Development Focus ABAP verifies the knowledge in the area of the SAP NetWeaver for the consultant profile Application Development Focus ABAP. This certificate proves that the candidate has a basic understanding within this consultant profile, and can implement this knowledge practically in projects.
The certification test consists of questions from the areas specified below:

Topic Areas

1. SAP Technologies (+)
SAP systems (mySAP Business Suite and SAP NetWeaver)
Technical structure of an SAP Web Application Server

2. ABAP Workbench Basics (++)
Data types and data objects (declaration)
Internal tables
Data retrieval (authorization check)
Subroutines
Function groups and function modules
Program calls and memory management

3. Advanced ABAP (++)
ABAP runtime
Data types and data objects (usage)
Open SQL (high-performance programming)
Dynamic programming

4. ABAP Objects (++)
Classes and objects
Inheritance
Polymorphism (casting)
Interfaces
Events
Global classes and interfaces
Exception handling
Shared objects

5. ABAP Dictionary (++)
Database tables
Performance for table accesses
Consistency by means of input check (foreign key dependency)
Dependency for ABAP Dictionary objects
Views
Search helps

6. List Creation Techniques (++)
Data output in lists
Selection screen
Logical database
Interactive lists
List creation with the ALV grid control:
- Simple lists
- Field catalog
- Layout
- Event handling

7. Dialog Programming (++)
Screen (basics)
Program interface (GUI title, GUI status)
Screen elements for output (text fields, status icons, and group boxes)
Screen elements for input/output
Subscreen and tabstrip control
Table control
Context menu
Lists in dialog programming

8. Database Changes (+)
Database updates with open SQL
LUWs and client/server architecture
SAP locking concept
Organize database changes
Complex LUW processing
Number assignment
Change document creation

9. Enhancements and Modifications (+)
Changes to the standard SAP system
Personalization
Enhancements to ABAP Dictionary elements
Enhancements via customer exits
Business Transaction Events
Business Add-Ins
Modifications

Amount of questions by topic (as percentage of test):
+ = 1 - 10%
++ = 11 - 20%
+++ = over 20%

No responsibility is taken for the correctness of this information. Copyright © SAP AG 2005.

Fuente: https://websmp108.sap-ag.de/~sapidp/011000358700006455222004E

Certificación SAP-ABAP

Imagino que muchos como yo quisieran certificarse algún día en SAP ABAP -mundillo interesante en el que he venido a llegar de casualidad- y dado que estoy al inicio de esta aventura de recopilar información y empezar a estudiar, me he decidido postear cada paso que voy dando hasta llegar a lograrlo (espero :P).

Síganme los buenos!!!

Todo material es bienvenido, los comentarios y recomendaciones, también.

Saludos.

jueves, 14 de febrero de 2008

SAP CRM para iPhone

SAP está trabajando en un CRM -Customer Relationship Management- móvil para iPhone. El argumento de SAP es que sus clientes corporativos prefieren iPhone antes que otras marcas y no pueden perder el pulso del mercado. SAP, líder de software de gestión e inteligencia empresarial ha decidido desarrollar aplicaciones para iPhone comenzando con CRM 2007.

El nuevo CRM, que se empezará a comercializar a finales de mes, contará con un programa que permitirá el envío de datos de clientes a los teléfonos iPhone de Apple. SAP ha buscado en esta nueva generación de aplicaciones utilizar todas las experiencias de los servicios de la web 2.0, inspirándose en las herramientas de Google y Yahoo.
El CRM móvil será un instrumento imprescindible para que las empresas puedan brindar mayor satisfacción de los clientes, mejorar sus objetivos de rendimiento financiero e impulsar su ventaja competitiva en el mercado, comenzando por los equipos de fuerza de ventas para llegar, tarde o temprano, a las actividades de aprovisionamiento y producción.

Mujer afgana identificada por su iris

Sharbat Gula, fotografiada en 1984 a los 12 años en un refugio en Pakistán por el fotógrafo de la National Geographic Steve McCurry, y localizada 18 años después en una remota parte de Afganistán donde fue nuevamente fotografiada por McCurry, es mencionada por la National Geographic en su revista y en su website.

John Daugman todo un ícono en el procesamiento y reconocimiento del iris humano, calculó el IrisCode de ambos ojos en la fotografía de 1984. Un sección procesada de la fotografía de 1984 se muestra aquí. La circunferencia muestra la automática localización del iris y sus bordes, el descarte de ciertas reflexiones especulares del ojo y la representación del IrisCode. Luego calculó el IrisCods de ambos ojos fotografiados en 2002. La imágenes procesadas pueden ser vistas aquí, para el ojo izquierdo y derecho.

Aún lo más interesante surge a continuación. Cuando se obtuvo la distancia de Hamming de los ojos izquierdo y derecho(los cuales en todo humano son completamente diferentes), se obtuvo medidas muy similares, que como el mismo Daugman manifiesta es estadísticamente casi imposible para diferentes iris se muestren medidas tan poco distintas. La estadística matemática de que tal evento pase es de seis millones a uno para el ojo derecho y 10 elevado a 15 para el ojo izquierdo. NatGeo aceptó nuevamente publicar esta conclusión.

Como se ve el IrisCode tuvo todo un reto, y salió con algunas heridas pero victorioso al fin.

Fuente: http://www.seccperu.org/?q=node/608

Algo sobre lógica difusa.

Han podido ver sus lavadoras u otros electrodomésticos que dicen "FUZZY LOGIC?"

Habitualmente las premisas de la lógica que conocemos tienen sólo dos extremos: o son completamente ciertas o son totalmente falsas (1 v 0). En el mundo de la lógica difusa las premisas pueden tener un grado de certeza que le permite acercar la matemática al lenguaje impreciso del hombre común, ya que está repleto de términos vagos como “poco”, “mucho”, “tibio”, etc.

Entonces podemos decir que la lógica difusa analiza los métodos y principios del razonamiento a partir de proposiciones IMPRECISAS similar a como lo haría un ser humano: "Si hace algo de frio y tengo muchas cosas que hacer entonces no salgo", ¿Cuánto es algo o mucho?
De esa manera tu lavadora puede decirdir cuanto tiempo lavar, cuanto detergente pedir, y cuanta agua cargar, con reglas de inferencias del tipo:

Si la ropa esta muy sucia, y el agua es fria, y ademas hay mucha ropa -> cargar mucha agua y lavar durante mucho tiempo. :P

Para los q quieren saber mas...

Un sistema difuso convencional consta de 3 etapas que son las siguientes:

Fuzzyficación
Consiste en llevar los valores del mundo real al ambiente Fuzzy mediante el uso de funciones de membresía. Por ejemplo, si tenemos un paciente con fiebre, podemos plantear un modelo en el que la situación de fiebre no se restringe sólo a dos valores (hay fiebre o no hay fiebre), sino que tenemos todo un rango de temperaturas posible, asi un paciente que tiene 38C de tempratura puede tener fiebre como no tenerla pero en cierto grado.

Inferencia Lógica
Para poder operar con los Conjuntos Difusos es necesario definir las operaciones elementales entre ellos. Esto implica definir el modo de calcular las funciones de pertenencia a estos tres conjuntos.
Siento FP una función que nos devuelve el grado de pertenencia al un conjunto difuso, Zadeh propone:
FP(X AND Y) = mínimo de (FP (X), FP(Y))
FP (X OR Y) = máximo de (FP (X), FP (Y))
NOT FP = 1 – FP (X), considerando pertenencia total = 1

En realidad, estas expresiones son bastante arbitrarias y podrían haberse definido de muchas otras maneras. En la actualidad se considera correcto definir el operador AND mediante cualquier aplicación t-norma y el operador OR mediante cualquier aplicación s-norma.

Defuzzyficación
Después de calcular las reglas fuzzy y evaluar las variables fuzzy, necesitaremos trasladar estos valores nuevamente hacia el mundo real. El método más popular de defusificación es el cálculo del centro de gravedad ó centroide, el cual retorna el centro del área bajo la curva de la inferencia.

El término difuso aplicado a la lógica procede de la expresión fuzzy sets (conjuntos difusos) acuñada por Lofti A. Zadeh. Zadeh prefirió el término fuzzy para denominar a sus conjuntos y a la lógica en la que se apoya su análisis. Uno de los países donde más éxito han tenido los sistemas difusos ha sido en Japón. Empresas como Fuji Elec.& TIT han desarrollado aplicaciones de control fuzzy para el proceso de purificación del agua, Hitachi con una aplicación de control fuzzy para el Metro en Sendai City o Matsushita con una aplicación de control fuzzy para la unidad de suministro de agua caliente para uso doméstico. Merece una mención especial la creación de LIFE (Laboratory for International Fuzzy Engineering Research) en marzo de 1989, creado por el Ministerio de Comercio Internacional e Industria en Japón (MITI). Pero también en USA las empresas han comenzado a aplicar la lógica difusa a sus desarrollos y proyectos. Entre otras encontramos a la NASA, Boeing, Rochwell, Bell o a Ford Motor Co., que experimenta con un sistema de aparcamiento automático para camiones con remolque.

Los comentarios son bienvenidos.

jueves, 7 de febrero de 2008

Plantilla super básica para aprender ALV

Esta es una plantilla que hice hace un tiempo cuando aprendí a usar ALV, es la plantilla más básica como ejemplo para aprender, luego uno ya puede ir agregándole otras capacidades que ALV permite.

Solo cambia lo que está en rojo y para obtener un programa que muestra un ALV.


*&---------------------------------------------------------------------*
*& autor....... : Carlos Agreda*
*& Descripción..: programa plantilla basico para alv *
*&---------------------------------------------------------------------*

REPORT ZEJ_ALV.
     type-pools: slis.
     Data: gt_fieldcat TYPE slis_t_fieldcat_alv WITH HEADER LINE.
     Data: BEGIN OF it_datos OCCURS 0.
                        INCLUDE STRUCTURE
tabla_diccionario.
     Data: END OF it_datos .

     perform llenaDatos.
     perform llenaFieldcat.
     perform mostrarALV.

*llena la tabla interna con los datos que queremos mostrar  
form llenaDatos.
             SELECT * FROM
tabla_diccionario INTO TABLE it_datos.
endform.

*Llena el fieldcat para cada campo
form llenaFieldcat.
* repetir este bloque por cada campo
             CLEAR gt_fieldcat.
             gt_fieldcat-SELTEXT_L = '
caption_campo'.
             gt_fieldcat-fieldname = '
nombre_del_Campo'.
             gt_fieldcat-tabname = '
tabla_diccionario'.
             APPEND gt_fieldcat.
*fin del bloque

endform.

* muestra el alv
form mostrarALV.
             CALL FUNCTION 'REUSE_ALV_LIST_DISPLAY'
             EXPORTING
                      it_fieldcat = gt_fieldcat[]
             TABLES
                      t_outtab = it_datos
             EXCEPTIONS
                      program_error = 1
             OTHERS = 2.
endform.


Espero no haber olvidado nada.

miércoles, 6 de febrero de 2008

Tres en raya para ABAP

Ésta es una implementacion -ociosa- del juego de 3 en raya en ABAP/4, por el momento es muy torpe -juega totalmente aleatorio- y poco robusta, pero es un buen ejemplo de programas interactivos.
El código está listo para pegar poner F8 y jugar.
Prometo implementar la heurística del juego para que no le puedas ganarle, pero eso será en otro post.
Por cierto el generador de aleatorios de ABAP es muy malo, prometo implementar uno y postearlo también.

*&---------------------------------------------------------------------*
*& Autor.........: Carlos Agreda Pérez
*& Descripción...: Juego de 3 en raya
*& Fecha ........: 06/FEB/2008 *
*&---------------------------------------------------------------------*

REPORT ZTMP_3R no standard page heading.
Data: aleatorio type i, posX type i, posY type i.
Data: ganoMaquina type i value 0.
Data: ganoJugador type i value 0.
Data: Begin of estado,
     P1 VALUE '-', P2 VALUE '-', P3 VALUE '-', P4 VALUE '-', P5 VALUE '-',
     P6 VALUE '-', P7 VALUE '-', P8 VALUE '-', P9 VALUE '-',
End of estado.

perform elegirAccionMaquina.
perform mostrarEstado.
 
* CAPTURA DE LA JUGADA-----------------------
AT LINE-SELECTION.
     GET CURSOR LINE posY OFFSET posX.   
     if posX = 10 and posY = 4. estado-P1 = 'o'. endif.
     if posX = 20 and posY = 4. estado-P2 = 'o'. endif.
     if posX = 30 and posY = 4. estado-P3 = 'o'. endif.
     if posX = 10 and posY = 6. estado-P4 = 'o'. endif.
     if posX = 20 and posY = 6. estado-P5 = 'o'. endif.
     if posX = 30 and posY = 6. estado-P6 = 'o'. endif.
     if posX = 10 and posY = 8. estado-P7 = 'o'. endif.
     if posX = 20 and posY = 8. estado-P8 = 'o'. endif.
     if posX = 30 and posY = 8. estado-P9 = 'o'. endif.
     perform verificarGanador.
     if ganoJugador NE 1.
            perform elegirAccionMaquina.
     endif.
     perform mostrarEstado. 
 
* SUBPROGRAMAS ------------------------------------ 
form elegirAccionMaquina.
       perform generarAleatorioLibre.
       if aleatorio = 1. estado-P1 = 'X'. endif.
       if aleatorio = 2. estado-P2 = 'X'. endif.
       if aleatorio = 3. estado-P3 = 'X'. endif.
       if aleatorio = 4. estado-P4 = 'X'. endif.
       if aleatorio = 5. estado-P5 = 'X'. endif.
       if aleatorio = 6. estado-P6 = 'X'. endif.
       if aleatorio = 7. estado-P7 = 'X'. endif.
       if aleatorio = 8. estado-P8 = 'X'. endif.
       if aleatorio = 9. estado-P9 = 'X'. endif.
endform.

form mostrarEstado.
      write: /, /, /.
      write at 11(1): estado-P1. write at 21(1): estado-P2. write at 31(1): estado-P3. write: /.
      write at 11(1): estado-P4. write at 21(1): estado-P5. write at 31(1): estado-P6. write: /.
      write at 11(1): estado-P7. write at 21(1): estado-P8. write at 31(1): estado-P9.
endform.

form generarAleatorioLibre.
      CALL FUNCTION 'QF05_RANDOM_INTEGER'
      EXPORTING
             RAN_INT_MIN = 1
             RAN_INT_MAX = 9
      IMPORTING
             RAN_INT = aleatorio
      EXCEPTIONS
             OTHERS = 1.
      if aleatorio = 1 and estado-P1 NE '-'. perform generarAleatorioLibre. endif.
      if aleatorio = 2 and estado-P2 NE '-'. perform generarAleatorioLibre. endif.
      if aleatorio = 3 and estado-P3 NE '-'. perform generarAleatorioLibre. endif.
      if aleatorio = 4 and estado-P4 NE '-'. perform generarAleatorioLibre. endif.
      if aleatorio = 5 and estado-P5 NE '-'. perform generarAleatorioLibre. endif.
      if aleatorio = 6 and estado-P6 NE '-'. perform generarAleatorioLibre. endif.
      if aleatorio = 7 and estado-P7 NE '-'. perform generarAleatorioLibre. endif.
      if aleatorio = 8 and estado-P8 NE '-'. perform generarAleatorioLibre. endif.
      if aleatorio = 9 and estado-P9 NE '-'. perform generarAleatorioLibre. endif.
endform.

form verificarGanador.
      if estado-P1 = 'X' and estado-P2 = 'X' and estado-P3 = 'X'. ganoMaquina = 1. endif.
      if estado-P4 = 'X' and estado-P5 = 'X' and estado-P6 = 'X'. ganoMaquina = 1. endif.
      if estado-P7 = 'X' and estado-P8 = 'X' and estado-P9 = 'X'. ganoMaquina = 1. endif.
      if estado-P1 = 'X' and estado-P4 = 'X' and estado-P7 = 'X'. ganoMaquina = 1. endif.
      if estado-P2 = 'X' and estado-P5 = 'X' and estado-P8 = 'X'. ganoMaquina = 1. endif.
      if estado-P3 = 'X' and estado-P6 = 'X' and estado-P9 = 'X'. ganoMaquina = 1. endif.
      if estado-P3 = 'X' and estado-P5 = 'X' and estado-P7 = 'X'. ganoMaquina = 1. endif.
      if estado-P1 = 'X' and estado-P5 = 'X' and estado-P9 = 'X'. ganoMaquina = 1. endif.
      if estado-P1 = 'o' and estado-P2 = 'o' and estado-P3 = 'o'. ganoJugador = 1. endif.
      if estado-P4 = 'o' and estado-P5 = 'o' and estado-P6 = 'o'. ganoJugador = 1. endif.
      if estado-P7 = 'o' and estado-P8 = 'o' and estado-P9 = 'o'. ganoJugador = 1. endif.
      if estado-P1 = 'o' and estado-P4 = 'o' and estado-P7 = 'o'. ganoJugador = 1. endif.
      if estado-P2 = 'o' and estado-P5 = 'o' and estado-P8 = 'o'. ganoJugador = 1. endif.
      if estado-P3 = 'o' and estado-P6 = 'o' and estado-P9 = 'o'. ganoJugador = 1. endif.
      if estado-P3 = 'o' and estado-P5 = 'o' and estado-P7 = 'o'. ganoJugador = 1. endif.
      if estado-P1 = 'o' and estado-P5 = 'o' and estado-P9 = 'o'. ganoJugador = 1. endif.  
      if ganoMaquina = 1. Write 'Te gané'.
      elseif ganoJugador = 1. Write 'Ganaste'.
      endif.
endform.

Capturar la posición de un doble clic en un Report ABAP/4

Estuve implementando un tres en raya en ABAP -para refrescar ABAP y aprovechando que no hay proyectos- y para recibir las jugadas me fue necesario capturar la posición de un doble clic sobre el report.
Es bien fácil tan solo utilizar el evento AT LINE-SELECTION. (se invoca cuando das el doble clic) y la instrucción GET CURSOR LINE posY OFFSET posX.

Aqui  un ejemplo sencillo:


*& Autor.........: Carlos Agreda
*& Descripción...: Captura la posición del doble
*& clic y la escribe en pantalla 
*& Fecha ........: 06/FEB/2008

REPORT ZEJEMPLO.
DATA : posX type i, posY type i.
write 'hola'.

AT LINE-SELECTION.
GET CURSOR LINE posY OFFSET posX.
write: posX, posY.


La restricción es que nomás se podrán dar clics sobre la superficie escrita, en éste caso solo se podrá dar doble clic sobre "hola".

Prometo postear el fuente del tres en raya ni bien lo termine :P

Destripando un BMP (24 bits)

Existe una gran variedad de formatos de imágenes tal como BMP, TIFF, GIF, PNG, JPEG, etc. El más sencillo de todos es el formato BMP de 24 bits.

Características:
No es comprimido (Una desventaja con respecto a espacio pero ventaja por su simplicidad)
Por no ser comprimido es de alta calidad
Se puede ver en cualquier visor de imágenes por ser el mas básico.

Veamos que hay dentro...



Los Primeros 54 Bytes contienen los metadatos de nuestra imagen y su estructura es la siguiente:

2 bytes - contienen siempre 'BM', para poder identificar que es un bmp
4 bytes - tamaño del archivo (en bytes)
4 bytes - Reservados, contienen ceros (reservados para usos futuros)
4 bytes - offset, distancia entre cabecera y píxels (no lo usaremos)
4 bytes - Tamaño de Metadatos (tamaño de esta estructura = 40)
4 bytes - Ancho (numero de píxeles horizontales)
4 bytes - Alto (numero de pixeles verticales)
2 bytes - Numero de planos de color (No lo usaremos, valdrá 1)
2 bytes - Profundidad de color (debe ser 24 para nuestro caso)
4 bytes - Tipo de compresión (valdrá 0, ya que es descomprimido)
4 bytes - Tamaño de la estructura Imagen
4 bytes - Píxeles por metro horizontal (No lo usaremos)
4 bytes - Píxeles por metro vertical (No lo usaremos)
4 bytes - Cantidad de colores usados (No lo usaremos)
4 bytes - Cantidad de colores importantes (Tampoco usaremos)


Suman 54 bytes, y son los primeros 54 bytes que debemos leer de nuestro archivo.
Podemos leerlo uno a uno pero lo mejor es crear una estructura y leerlos todo de un solo paso.

Ejemplo de Estuctura para Visual Basic:


Public Type tipoMetadatosBMP
       B As Byte
       M As Byte
       tamaño As Long
       reservado As Long
       offset As Long
       tamañoMetadatosB
       ancho As Long
       alto As Long
       planos As Integer
       profundidadColor As Integer
       tipoCompresion As Long
       tamañoEstructuraImagen As Long
       pixelsPorMetroH As Long
       pixelsPorMetroV As Long
       cantidadColoresUsados As Long
       cantidadColoresImportantes As Long
End Type


Ejemplo de estructura para C++:

struct tipoMetadatosBMP
{     char bm[2];
      int tamano;
      int reservado;
      int offset;
      int tamanoMetadatos;
      int alto;
      int ancho;
      short numeroPlanos;
      short profundidadColor;
      int tipoCompresion;
      int tamanoEstructura;
      int pxmh;
      int pxmv;
      int coloresUsados;
      int coloresImportantes;

} ;

No debe variar mucho de lenguaje en lenguaje.
Inmediatamente después de Nuestra cabecera (metadatos), vienen los píxeles (si, esos cuadraditos de colores que conforman nuestra imagen)

Cada Píxel se almacena en 24 bits (3 bytes)
De los 24 bits = 3 bytes, se utilizan 1 byte por cada color básico es decir...
Un byte parta R, Un byte para G, Un byte para B

NO, no son los colores rastas :P, son los colores básicos para el BMP, cada color puede ser obtenido mediante una combinacion de R (red), G (green) y B (blue).

Considerando que un byte puede almacenar 256 valores diferentes, tenemos:
256 (R) x 256 (G) x 256 colores (B) = 16777216 Colores RGB

Por alguna razón que desconozco al momento de diseñar el formato los ordenaron BGR y no RGB es decir primero el byte para azul, luego el byte para verde y luego el byte para verde.

Importante!!! :
Además despues de cada fila de pixels (barrido horizontal), si el ancho de
la imagen no es multiplo de 4, se rellena la linea con [ancho mod 4] bytes que
contienen 0.
Por ejemplo si la imagen tuviera 42 pixeles de ancho, se
rellenaria 2 bytes (el resto de 42/4) al final de cada fila de
pixeles.
Ahora ya que al leer los metadatos obtuvimos la resolución (Sí, la RESOLUCIÓN, o sea los píxeles horizontales x verticales)

Recuerdas?
...
ancho As Long
alto As Long
...

ahora podemos leer cada uno de los píxeles de la siguiente manera:

Codigo de ejemplo para leer una imagen en Visual Basic.


Dim meta As tipoMetadatosBMP
Dim i As Long, j As Long, k as Integer, resto as Integer
Dim pixelAux As tipoPixel
Dim relleno as Byte

Open nombreBMP For Binary As #1
Get #1, , meta ' Leemos los metadatos
resto = meta.ancho mod 4 'calculamos el resto

For i = 1 To meta.alto 'Recorremos las filas
    For j = 1 To meta.ancho 'Recorremos las columnas
        Get #1, , pixelAux 'leemos el pixel ...
    Next
    For k = 1 To resto 'leemos los pixels de relleno
        Get #1, , relleno
    Next
Next

Close #1

Asumimos que tenemos declarado el tipo:


Public Type tipoPixel
    b As Byte ' Azul
    g As Byte ' verde
    r As Byte ' rojo
End Type

Codigo de ejemplo para leer una imagen en C++

archivo.Open("imagen.bmp",CFile::modeCreateCFile::modeNoTruncateCFile::modeRead);

//cargamos los metadatos -----------------------------------

archivo.Read(&bm,2);
archivo.Read(&tamano,sizeof(tamano));
archivo.Read(&reservado,sizeof(reservado));
archivo.Read(&offset,sizeof(offset));
archivo.Read(&tamanoMetadatos,sizeof(tamanoMetadatos));
archivo.Read(&ancho,sizeof(ancho));
archivo.Read(&alto,sizeof(alto));
archivo.Read(&numeroPlanos,sizeof(numeroPlanos));
archivo.Read(&profundidadColor,sizeof(profundidadColor));
archivo.Read(&tipoCompresion,sizeof(tipoCompresion));
archivo.Read(&tamanoEstructura,sizeof(tamanoEstructura));
archivo.Read(&pxmh,sizeof(pxmh));
archivo.Read(&pxmv,sizeof(pxmv));
archivo.Read(&coloresUsados,sizeof(coloresUsados));
archivo.Read(&coloresImportantes,sizeof(coloresImportantes));
//----------------------------------------------------------


//Luego leemos los pixeles ---------------------------------

int resto = metadata.ancho % 4;
for (i=1;i<=metadata.alto;i++)

{    for (j=1;j<=metadata.ancho;j++)
     {    archivo.Read(&varB,1); //leemos el byte azul en la variable varB
          archivo.Read(&varG,1); //leemos el byte azul en la variable varB
          archivo.Read(&varR,1); //leemos el byte azul en la variable varB
     }
     for (k=1;k<=resto;k++)
          archivo.Read(&var,1); //leemos los pixels de relleno
}
archivo.Close(); //----------------------------------------------------------

El código es muy similar para cualquier otro lenguaje.
Espero les haya servido.
Comentarios y sugerencias a: carlosagreda-at-gmail.com


martes, 5 de febrero de 2008

Un Mecánico de Máquinas de turing!!!

Hace tiempo que necesitaba un espacio para poder publicar curiosidades, programas, bytes sueltos que uno siempre tiene en el cerebro y es necesario volcarlos antes que la muerte se los lleve conmigo :P, asi que bienvenidos al Mecánico de Máquinas de Turing.