Graficos, Planos en OpenGL

download Graficos, Planos en OpenGL

of 37

Transcript of Graficos, Planos en OpenGL

  • 7/22/2019 Graficos, Planos en OpenGL

    1/37

    INFORMTICA GRFICA

    Tema 10: Grficos Planos en OpenGL

    Gonzalo Cascn Barbero

    Elena Jorge Rico

  • 7/22/2019 Graficos, Planos en OpenGL

    2/37

    ndice

    ndice _______________________________________________________________ 2

    Tabla de figuras_______________________________________________________ 3

    1 Introduccin________________________________________________________ 4

    2 Mapas de bits _______________________________________________________ 5

    Concepto _________________________________________________________________ 5

    Ejemplo de bitmap con OpenGL _____________________________________________ 5

    Aplicaciones: Generacin de caracteres y fuentes _______________________________ 9Generacin de caracteres __________________________________________________________9Generacin de fuentes ___________________________________________________________11

    3 Imgenes__________________________________________________________ 14

    Lectura de pxeles de framebuffer a memoria _________________________________ 14

    Escritura de pxeles de memoria a framebuffer ________________________________ 17

    Copia de pxeles dentro del framebuffer ______________________________________ 18

    5 El Pipeline de renderizado de OpenGL _________________________________ 22

    6 Lectura y Dibujo de rectngulos de pxeles _____________________________ 25

    Proceso de dibujo de rectngulos de pxeles ___________________________________ 25

    Proceso de lectura de rectngulos de pxeles___________________________________ 26

    7 Formatos de imagen _______________________________________________ 28

    El formato BMP__________________________________________________________28

    8 Manejo de ficheros BMP en OpenGL __________________________________ 31

  • 7/22/2019 Graficos, Planos en OpenGL

    3/37

    Tabla de figuras

    Ilustracin 1.-Bitmap de ejemplo. ________________________________________________________6

    Ilustracin 2.-Bitmap como matriz de 0s y 1s _______________________________________________6Ilustracin 3.-Estructura GLubyte _______________________________________________________7Ilustracin 4.-Cdigo para dibujar un bitmap ______________________________________________7Ilustracin 5.- Resultado de la ejecucin del cdigo del bitmap_________________________________9Ilustracin 6.- Carcter A como bitmap ___________________________________________________9Ilustracin 7.- Carcter A como estructura GLubyte ________________________________________10Ilustracin 8.- Dos bitmaps del carcter A superpuestos _____________________________________10Ilustracin 9.- Dos bitmaps del carcter A superpuestos en cdigo_____________________________ 11Ilustracin 10.- Creacin de una fuente mediante DLs_______________________________________ 12Ilustracin 11.- Mtodo para imprimir una cadena con la fuente creada ________________________12Ilustracin 12.- Ejemplo de uso de la fuente creada _________________________________________13Ilustracin 13.- Resultado de ejecutar el cdigo del ejemplo de la fuente ________________________13Ilustracin 14.- Tipos de datos para glReadPixels() o glDrawPixels() __________________________15

    Ilustracin 15.- Formatos de Pixels para glReadPixels() o glDrawPixels()_______________________16Ilustracin 16.- Fragmento de cdigo para hacer capturas de pantalla__________________________17Ilustracin 17.- Fragmento de cdigo para dibujar un tablero de ajedrez________________________18Ilustracin 18.- Cdigo de un programa para copiar pxeles y hacer zoom_______________________ 21Ilustracin 19 Pipeline de renderizado de OpenGL _________________________________________23Ilustracin 20 Dibujo de pxeles con glDrawPixeles() _______________________________________25Ilustracin 21 Lectura de pxeles con glReadPixeles() _______________________________________27

  • 7/22/2019 Graficos, Planos en OpenGL

    4/37

    1 Introduccin

    La pantalla de un ordenador slo es capaz de visualizar grficos en dosdimensiones (2D). Para conseguir que los objetos que en ella aparecen tenganvolumen es necesario el uso de tcnicas que nos hagan creer que stos tienen3D. Estas tcnicas sern el uso de focos de luz, sombreado de colores,sombras, etc.

    Los grficos planos son tiles en OpenGL para combinarlos con los de3D para la aplicacin de texturas a los objetos. Pero no solo esto, tambin seutilizan para la visualizacin y creacin de mapas de bits, mapas de pxeles yfuentes de texto. En ocasiones, la creacin de estas imgenes desde OpenGLsupone una tarea demasiado compleja, por eso tambin existen libreras que

    nos permiten importar imgenes ya creadas para incorporarlas a la escena.

  • 7/22/2019 Graficos, Planos en OpenGL

    5/37

    2 Mapas de bits

    Concepto

    Los mapas de bits, tambin conocidos como bitmaps, son imgenesbicolor usadas para dibujar de forma rpida caracteres o smbolos (iconos,cursores, fuentes de texto, etc.). Emplean un nico bit de informacin por cadapxel, constituyendo as un array rectangular de 0s y 1s. En la posicin delarray en que aparezca un 0 se estar indicando transparencia, esto es, no semodifica el contenido del pxel que le corresponda. En la posicin del array enque aparezca un 1 se estar indicando que habr que dibujar usando el color yatributos de iluminacin del material actual.

    A los mapas de pxelestambin se les suele llamar mapas de bits. Losdos pueden ser vistos de una manera abstracta como un array rectangular depxeles. Sin embargo los mapas de pxeles suelen tener ms de dos colores yse emplean como imgenes de fondo o texturas. En este documentoconsideraremos los mapas de pxeles como imgenes y hablaremos de ellosen el apartado 3.

    Ejemplo de bitmap con OpenGL

    En este apartado vamos a ver como se creara un bitmap directamente

    desde una aplicacin con OpenGL.Imaginemos que queremos dibujar un smiley de 16x16 bits como el

    que se muestra en la siguiente figura.

  • 7/22/2019 Graficos, Planos en OpenGL

    6/37

    Ilustracin 1.-Bitmap de ejemplo.

    Como hemos dicho el bitmap es una matriz de 0s y 1s donde los bitsque estn a 0 indican ausencia de color y los bits que estan a 1 indica que serepresenten los pxeles correspondientes. Por lo tanto tendramos una matrizcomo la que se muestra a continuacin:

    B y t e 1 B y t e 2

    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 71 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0x03, 0xc02 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0x0f, 0xf03 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0x1f, 0xf84 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0x3f, 0xfc5 0 1 1 1 0 0 1 1 1 1 0 0 1 1 1 0 0x73,0xce6 0 1 1 1 0 0 1 1 1 1 0 0 1 1 1 0 0x73, 0xcc7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0xff, 0xff8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0xff, 0xff9 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0xff, 0xff

    10 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0xff, 0xff11 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 0 0x6f, 0xf612 0 1 1 1 0 1 1 1 1 1 1 0 1 1 1 0 0x77, 0xee13 0 0 1 1 1 0 0 1 1 0 0 1 1 1 0 0 0x39,0x9c14 0 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0x1e,0x7816 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0x0f,0xf016 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0x03,0xc0

    Ilustracin 2.-Bitmap como matriz de 0s y 1s

    El primer paso para crear el bitmap ser definir una estructura de tipoGLubyte. El mapa ser una matriz bytes sin signo. En OpenGL los mapas debits se definen invertidos, esto es, se almacenan desde la parte inferior hasta lasuperior. Es decir, el bit ms significativo del primer byte del array GLubyte

  • 7/22/2019 Graficos, Planos en OpenGL

    7/37

    corresponde a la parte esquina inferior izquierda del bitmap. Veamos unejemplo de cmo se definira este bitmap.

    Ilustracin 3.-Estructura GLubyte

    Como vemos es una matriz de 32 bytes sin signo, del tipo Glubyte.Una vez que tenemos la matriz GLubyte creada ya podemos dibujar

    nuestro bitmap.

    static GLubyte smiley[] = /* Cara sonriente de 16x16 */

    { 0x03, 0xc0, /* **** */

    0x0f, 0xf0, /* ******** */

    0x1e, 0x78, /* **** **** */

    0x39, 0x9c, /* *** ** *** */

    0x77, 0xee, /* *** ****** *** */

    0x6f, 0xf6, /* ** ******** ** */

    0xff, 0xff, /* **************** */

    0xff, 0xff, /* **************** */

    0xff, 0xff, /* **************** */

    0xff, 0xff, /* **************** */

    0x73, 0xce, /* *** **** *** */

    0x73, 0xce, /* *** **** *** */

    0x3f, 0xfc, /* ************ */

    0x1f, 0xf8, /* ********** */

    0x0f, 0xf0, /* ******** */

    0x03, 0xc0, /* **** */

    };

    void display(void){glClear(GL_COLOR_BUFFER_BIT);//Color de fondo blancoglClearColor(1.0,1.0,1.0,1.0);

    //Smiley verdeglColor3f (0.0, 1.0, 0.0); //Establecemos color de dibujoglRasterPos2i (50, 100); //Fijamos posicin y color de dibujoglBitmap(16,16,0,0,0,0,smiley); //Dibujamos el bitmap

    //Smiley rojoglColor3f (1.0, 0.0, 0.0);glRasterPos2i (100, 100);glBitmap(16,16,0,0,0,0,smiley);

    //Smiley azulglColor3f (0.0, 0.0, 1.0);glRasterPos2i (150, 100);glBitmap(16,16,0,0,0,0,smiley);glFlush();

    }

    Ilustracin 4.-Cdigo para dibujar un bitmap

  • 7/22/2019 Graficos, Planos en OpenGL

    8/37

    La llamada glClearColor nos permite establecer el color del fondo. Lospxeles que tengan el valor 0 en nuestro bitmap se pintarn de este color. Suprototipo es el siguiente:Void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampfalpha) Como se puede apreciar sus parmetros son los valores RGBA.

    La llamada glColor3f nos permite establecer el color de dibujo. Lospxeles que tengan el valor 1 en nuestro bitmap se pintarn de este color. Suprototipo es el siguiente:Void glColor{3/4}{b/d/f/i/s/ub/ui/us }(GL red, GL green, GL blue, GLalpha)Este mtodo cambia el valor de la variable GL_CURRENT_RASTER_COLORque es la que establece el color actual de dibujo.Dependiendo de la funcin los parmetros sern de tipo GLbyte (b), GLdouble(d), GLfloat (f), GLint (i)

    La llamada glRasterPos2i nos permite establecer la posicin en pantalladonde se va a dibujar. Adems de lo anterior, tambin sirve para fijar el colorestablecido previamente por glColor. Por lo tanto deberemos hacer siempreantes la llamada a glColor y despus a glRasterPos. El prototipo de estafuncin es el siguiente:Void glRasterPos{2/3/4}{s/i/f/d}(GL x, GL y, GL z, GL w)La posicin viene dada por las coordenadas anchura, altura y profundidad(x,y,z) del punto dentro de la ventana de dibujo, la cuarta coordenada es unacoordenada asociada al color y a las caractersticas de las texturas y no es unacoordenada del espacio. La funcin glRasterPos cambia el valor de la variableGL_CURRENT_RASTER_POSITION_VALID establecindola a False si laposicin nueva esta fuera del rea de dibujo y a True en caso contrario.

    Por ltimo, una vez que hemos establecido los colores de fondo, dedibujo y la posicin sobre la que dibujar, solo queda dibujar el mapa de bits.Esto se hace con la funcin Void glBitmap (Glsizei ancho, Glsizei alto, Glfloatxorig, Glfloat yorig, Glfloat xmov, Glfloat ymov, const Glubyte *bitmap). Los dosprimeros parmetros indican la anchura y altura del bitmap (en nuestro ejemplo16 x 16). Los dos siguientes la coordenadas (en pxeles) de la posicin de iniciode dibujo del bitmap. Los parmetros quinto y sexto el desplazamiento (enpxeles) desde la posicin de inicio del bitmap actual hasta la posicin de inicio

    del siguiente bitmap (teniendo en cuenta siempre que la posicin de inicio deun bitmap es la esquina inferior izquierda). Si la variableGL_CURRENT_RASTER_POSITION_VALID tiene el valor False se ignorar lallamada a la funcin glBitmap.

    Veamos cual sera el resultado de la ejecucin del cdigo mostrado msarriba.

  • 7/22/2019 Graficos, Planos en OpenGL

    9/37

    Ilustracin 5.- Resultado de la ejecucin del cdigo del bitmap

    Aplicaciones: Generacin de caracteres y fuentes

    Generacin de caracteres

    En el punto anterior hemos visto como se puede crear un bitmap sencilloy mostrarlo por pantalla. Para dibujar bitmaps de mayor tamao y complejidadevidentemente no se utiliza este mtodo porque la tarea sera tediosa. Por elloOpenGL contiene bibliotecas de funciones que permiten importar imgenesBMP ya creadas. La creacin de bitmaps es una tarea que ha quedado

    relegada a la creacin de caracteres.Visto el punto anterior sera fcil crear un carcter con un bitmap,

    veamos un ejemplo.

    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 70x0C, 0x000x1E, 0x000x3F, 0x000x73, 0x800xE1, 0xC00xC0, 0xC00xC0, 0xC00xC0, 0xC00xFF, 0xC00xFF, 0xC00xC0, 0xC00xC0, 0xC00xC0, 0xC00xC0, 0xC00x00, 0x000x00, 0x00

    Ilustracin 6.- Carcter A como bitmap

  • 7/22/2019 Graficos, Planos en OpenGL

    10/37

    Esta imagen representa un bitmap de 16x16 que contiene un carcter Ade 10 pxeles de ancho y 14 pxeles de alto. Para crear un bitmap con OpenGLque represente este carcter hay que tener en cuenta que se empieza a dibujarpor la esquina inferior izquierda, por tanto hay que invertir el orden en el queintroducimos los datos en el array de tipo GLubyte. Podemos ver lo que

    acabamos de decir en el siguiente recuadro:

    static GLubyte LetraA[] ={

    0x00, 0x00,0x00, 0x00,0xC0, 0xC0,0xC0, 0xC0,0xC0, 0xC0,0xC0, 0xC0,0xFF, 0xC0,

    0xFF, 0xC0,0xC0, 0xC0,0xC0, 0xC0,0xC0, 0xC0,0xE1, 0xC0,0x73, 0x80,0x3F, 0x00,0x1E, 0x00,0x0C, 0x00

    Ilustracin 7.- Carcter A como estructura GLubyte

    Debemos tener en cuenta que todo bitmap debe tener un ancho que sea

    mltiplo de 8 porque los elementos de la matriz de tipo GLubyte son conjuntosde 8 bits. Esto no quiere decir que nuestro carcter tenga que tenerforzosamente un ancho que sea mltiplo de 8 bits; podemos asignarle el anchoque queramos y dejar en blanco el espacio que sobre en la parte derecha.Despus, a la hora de utilizar los caracteres, podemos superponer sus bitmapsdejando el espacio que nos interese entre caracteres.

    Ilustracin 8.- Dos bi tmaps del carcter A superpuestos

  • 7/22/2019 Graficos, Planos en OpenGL

    11/37

    En el ejemplo vemos como superponer 2 bitmaps de la letra A dejandoun espacio entre caracteres de 2 pxeles. Esto traducido a cdigo sera lomismo que esto otro:

    glBitmap (16, 16, 0.0, 0.0, 12.0, 0.0, LetraA);

    glBitmap (16, 16, 0.0, 0.0, 0.0, 0.0, LetraA);

    Ilustracin 9.- Dos bi tmaps del carcter A superpuestos en cdigo

    En el quinto parmetro de la funcin glBitmap indicamos eldesplazamiento desde el inicio del bitmap que vamos a dibujar hasta el iniciodel siguiente (en el eje x). Por tanto si ponemos un desplazamiento de 12pxeles, como nuestro carcter tiene un ancho de 10 estamos dejando unaseparacin de 2 pxeles entre caracteres.

    Generacin de fuentes

    Una fuente consiste en un conjunto de caracteres, donde cada carctertiene un nmero identificativo (usualmente el cdigo ASCII) y un mtodo dedibujo.

    Para un conjunto de caracteres ASCII estndar, la letra mayscula A esel nmero 65, B es el 66, y as sucesivamente. La cadena DAB se podrarepresentar por tres nmeros 68, 65, 66.

    Para la definicin de fuentes completas resulta de gran utilidad el uso delas Listas de Pantalla o Display List (de ahora en adelante DL). Mediante el usode las DL podemos definir un procedimiento de dibujo para cada letra, de modo

    que cuando queramos escribir una frase nicamente con saber el cdigo decada carcter podamos acceder al procedimiento que lo dibuja.

    Podemos definir un DL como un procedimiento que se define una solavez con un nombre o identificador nico y que incluye una secuencia decomandos. Este procedimiento puede ser usado las veces que se quiera.Cuando es creado sus comandos son precompilados y, si es posible, llevadosa memoria, aumentando la velocidad de ejecucin de nuestro programa. Si lasecuencia que incluye es utilizada muchas veces nuestra aplicacin aumentarel rendimiento considerablemente.

    La funcin GLuint glGenLists(GLsizei range) genera el numero de DLvacas indicado por su parmetro (siempre un nmero positivo), devolviendo un

    entero que representa al ndice de la primera DL dentro del conjunto de DL. Assi range es 5 se crea un conjunto de 5 DL y se recibe un entero con valor, porejemplo, 3. Las listas se identificarn del 3 al 7, ambos inclusive. Con esteidentificador se crearn cada uno de los DL. Este identificador debe conocersefuera de la funcin donde se obtiene, por tanto es obligatorio que se guarde enuna variable global. Un DL solo puede ser creado dentro de la funcin deiniciacin.

    La funcin void glNewList(GLuint list, GLenum mode) crea un NuevoDL. El parmetro list contiene el identificador del DL que se va a crear, y elparmetro mode puede tomar dos posibles valores: GL_COMPILE yGL_COMPILE_AND_EXECUTE. Si toma el primer valor los comandos dentrodel DL son nicamente compilados. Si toma el segundo valor los comandosson compilados y ejecutados al crear el DL. A continuacin de esta funcin se

  • 7/22/2019 Graficos, Planos en OpenGL

    12/37

    escribe la secuencia de comandos que debe ejecutar el DL (incluso se puedellamar a un DL dentro de otro DL). Al finalizar dicha consecucin de ordenes sedebe llamar a la funcin void glEndList(void void).

    La funcin void glCallList(GLuint list) ejecuta el DL identificado por list.Por ltimo la funcin void glDeleteLists(GLuint list, GLsizei range) borra el

    nmero de listas especificado por range comenzando por el que tiene elidentificador dado por list.

    Veamos un ejemplo de cmo se creara una fuente haciendo uso de lasDisplay List:

    Ilustracin 10.- Creacin de una fuente mediante DLs

    La variable alfabeto[] es un array de tipo GLubyte que cotiene todos loscaracteres del alfabeto. Cada carcter es de 8 pixels de ancho por 13 de alto.Creamos un DL para cada una de las letras del alfabeto con un desplazamientoigual a su cdigo ASCII sobre la base. Como se puede ver, lo que hacemosdentro de la DL es definir el procedimiento para dibujar cada una de las letrasllamando a la funcin glBitmpap. Dejamos una separacin horizontal entrecaracteres de 2 pxeles y una separacin vertical tambin de 2 pxeles.

    Una vez que tenemos definida la fuente ya slo necesitamos un mtodopara imprimir cadenas:

    GLuint desplazamiento;void fuenteDeEjemplo(void){

    GLuint i, j;glPixelStorei(GL_UNPACK_ALIGNMENT, 1);desplazamiento = glGenLists (128);/*El desplazamiento es el valor ASCII de la letra*/for (i = 0,j = 'A'; i < 26; i++,j++) {

    glNewList(desplazamiento + j, GL_COMPILE);glBitmap(8, 13, 0.0, 2.0, 10.0, 0.0, alfabeto[i]);glEndList();

    }glNewList(desplazamiento + ' ', GL_COMPILE);glBitmap(8, 13, 0.0, 2.0, 10.0, 0.0, espacio);glEndList();

    }

    void imprimirCadena(char *s){glPushAttrib (GL_LIST_BIT);glListBase(desplazamiento);glCallLists(strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s);glPopAttrib ();

    }

    Ilustracin 11.- Mtodo para impr imir una cadena con la fuente creada

  • 7/22/2019 Graficos, Planos en OpenGL

    13/37

    Mediante la llamada glCallList podemos invocar las DL que hemosdefinido anteriormente. El procedimiento obtiene el cdigo ASCCII de cadacarcter de la cadena y se lo suma a la variable desplazamiento, que contieneel ndice de la primera DL del conjunto de DLs que habamos definido en elejemplo anterior. De esta forma podemos acceder a la DL de cada una de las

    letras del alfabeto.

    Por ltimo veamos como se utilizara esta fuente:

    void display(void){GLfloat black[3] = { 0.0, 0.0, 0.0 };GLfloat red[3] = { 1.0, 0.0, 0.0 };glClear(GL_COLOR_BUFFER_BIT);glColor3fv(red);glRasterPos2i(20, 60);imprimirCadena("ESTO ES UN EJEMPLO DE FUENTE");glColor3fv(black);glRasterPos2i(20, 40);imprimirCadena("ABCDEFGHIJKLMNOPQRSTUVWXYZ");glFlush ();

    }

    Ilustracin 12.- Ejemplo de uso de la fuente creada

    El resultado de la ejecucin de este cdigo sera el siguiente:

    Ilustracin 13.- Resultado de ejecutar el cdigo del ejemplo de la fuente

  • 7/22/2019 Graficos, Planos en OpenGL

    14/37

    3 Imgenes

    Una imagen es un archivo de caractersticas similares a las de unarchivo bitmap. Una imagen no se limita a un bit por pxel, sino que es capazde almacenar mayor informacin por pxel. As por ejemplo, una imagen puedecontener un color entero (R, G, B, A) en un nico pxel.

    Tienen diversas fuentes. Una imagen puede proceder de: Fotografas digitalizadas con escner. Imgenes generadas en pantalla por un programa grfico utilizandohardware grfico y recuperada pxel a pxel. Un programa software que gener la imagen en memoria pxel a pxel.

    Las imgenes tipo fotos se generan a partir de buffers de color. Sin

    embargo, se pueden leer o escribir reas rectangulares de datos de pxeles deo hacia buffers de profundidad (depth buffers) o buffers de paletas (stencilbuffers). Adems, para simplificar su presentacin en pantalla, se puedenutilizar las imgenes para hacer mapas de texturas, en cuyo caso se colocanen polgonos que son renderizados en la pantalla de la forma habitual.

    Lectura de pxeles de framebuffer a memoria

    Para leer un array rectangular de pxeles de un framebuffer y guardarlo

    en memoria utilizamos la siguiente funcin:

    void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenumformat, GLenum type, GLvoid *pixels);

    Lee datos del rectngulo del framebuffer cuya esquina inferior izquierdaest en (x, y) y cuyas dimensiones son width y height y los guarda en el arrayapuntado por pixels. format indica la clase de elementos de datos del pxel queson ledos (un ndice o un valor de componente R, G, B, o A), y type indica eltipo de dato de cada elemento.

  • 7/22/2019 Graficos, Planos en OpenGL

    15/37

    Ilustracin 14.- Tipos de datos para glReadPixels() o glDrawPixels()

  • 7/22/2019 Graficos, Planos en OpenGL

    16/37

    Ilustracin 15.- Formatos de Pixels para glReadPixels() o glDrawPixels()

    Si se est usando glReadPixels() para obtener RGBA o informacin dendice de color, se necesitara aclarar a qu buffer se est intentando acceder.Por ejemplo, si se tiene una ventana de doble buffer, se necesita especificar sise estn leyendo datos del buffer superior o del buffer inferior. Para controlar elbuffer de lectura actual, se llama a glReadBuffer().

    En la siguiente figura podemos ver un ejemplo de una funcin querealiza una captura de la pantalla de la aplicacin haciendo uso de lasfunciones explicadas anteriormente.

    En primer lugar obtenemos las coordenadas de la ventana actual y susdimensiones. Despus obtenemos el buffer de la pantalla con glReadBuffer().Por ltimo con glReadPixels podemos obtener el rectngulo de pxeles que nosinteresa, a partir de las coordenadas que habamos obtenido previamente de laventana de la aplicacin.

    Con la informacin obtenida podramos implementar una funcin comopor ejemplo WriteTga que nos permitiera guardar esos datos que tenemos en

    memoria en un archivo TGA.

  • 7/22/2019 Graficos, Planos en OpenGL

    17/37

    bool SaveScreenGrab(const char* filename) {

    //Obtenemos los parametros de la ventanaunsigned sw = glutGet(GLUT_WINDOW_WIDTH);

    unsigned sh = glutGet(GLUT_WINDOW_HEIGHT);unsigned bpp = glutGet(GLUT_WINDOW_RGBA) ? 4 : 3;GLenum format = (bpp==4) ? GL_RGBA : GL_RGB;

    // Reservamos memoria para almacenar los datos de la imagenunsigned char* pdata = new unsigned char[sw*sh*bpp];

    //Leemos del buffer de la pantallaglReadBuffer(GL_FRONT);

    //Leemos los pixeles que nos interesanglReadPixels(0,0,sw,sh,format,GL_UNSIGNED_BYTE,pdata);

    //Guardamos los datos como un archivo tgabool ret = WriteTga(filename,sw,sh,bpp,pdata);

    //Liberamos memoriadelete [] pdata;

    return ret;

    Ilustracin 16.- Fragmento de cdigo para hacer capturas de pantalla

    Escritura de pxeles de memoria a framebuffer

    Para dibujar un rectangulo de pxeles desde memoria a un framebufferutilizamos la siguiente funcin:

    void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenumtype, const GLvoid *pixels);

    Dibuja un rectngulo de datos de pxel de dimensiones width y height. Elrectngulo de pxeles se dibuja con la esquina inferior izquierda en la posicinde raster actual. format y type tienen el mismo significado que conglReadPixels() (ver tablas anteriores). El array apuntado por pxeles contienelos datos de pxel que se quiere dibujar. Si la posicin del raster actual esinvlida, no se dibuja nada, y la posicin del raster permanece invlida.

    El siguiente ejemplo, utiliza glDrawPixels() para dibujar un rectngulo

    de pxeles en la esquina inferior izquierda de una ventana. makeCheckImage()

  • 7/22/2019 Graficos, Planos en OpenGL

    18/37

    crea un array RGB de 6464 de una imagen de tablero de ajedrez en blanco ynegro. glRasterPos2i(0, 0) coloca la esquina inferior izquierda de la imagen.

    #define checkImageWidth 64

    #define checkImageHeight 64GLubyte checkImage[checkImageHeight][checkImageWidth][3];void makeCheckImage(void){

    int i, j, c;for (i = 0; i < checkImageHeight; i++){

    for (j = 0; j < checkImageWidth; j++){c = ((((i&0x8)==0)^((j&0x8))==0))*255;checkImage[i][j][0] = (GLubyte) c;checkImage[i][j][1] = (GLubyte) c;checkImage[i][j][2] = (GLubyte) c;

    }}

    }

    void init(void){glClearColor (0.0, 0.0, 0.0, 0.0);glShadeModel(GL_FLAT);makeCheckImage();glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    }

    void display(void){glClear(GL_COLOR_BUFFER_BIT);glRasterPos2i(0, 0);glDrawPixels(checkImageWidth, checkImageHeight, GL_RGB,GL_UNSIGNED_BYTE, checkImage);glFlush();

    }

    Ilustracin 17.- Fragmento de cdigo para dibujar un tablero de ajedrez

    Existe una funcin llamada glDrawBuffer(), que se utiliza para controlarel buffer de escritura actual. Hay ocasiones en que cuando se utilizaglDrawPixels() para escribir RGBA o informacin de ndices de color, se puedetener que controlar este buffer.

    Copia de pxeles dentro del framebuffer

    Para copiar un array rectangular de pxeles de una parte del framebuffera otra tenemos la siguiente funcin:

  • 7/22/2019 Graficos, Planos en OpenGL

    19/37

    void glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenumbuffer);

    Copia datos de pxeles del rectngulo del framebuffer cuya esquina

    inferior izquierda es (x, y) y cuyas dimensiones son width y height. Los datosson copiados a una nueva posicin cuya esquina inferior izquierda est dadapor la posicin actual del raster. buffer es GL_COLOR, GL_STENCIL, oGL_DEPTH, especificando el framebuffer que se utiliza. glCopyPixels() secomporta de manera similar a glReadPixels() seguido de glDrawPixels(), conla siguiente interpretacin del buffer al parmetro format:

    Si buffer es GL_DEPTH o GL_STENCIL, entonces se utilizaGL_DEPTH_COMPONENT o GL_STENCIL_INDEX , respectivamentecomo parmetros en format.

    Si buffer es GL_COLOR, format es GL_RGBA o GL_COLOR_INDEX,dependiendo si el sistema est en modo RGBA o ndice de color.

    Hay que sealar que no es necesario un parmetro format o data englCopyPixels(), ya que el dato nunca es copiado en la memoria delprocesador. El buffer de lectura (fuente) y el buffer de destino deglCopyPixels() son especificados con glReadBuffer() y glDrawBuffer()respectivamente.

    Para las tres funciones, las conversiones exactas de los datos que seenvan o se reciben del framebuffer dependen de los modos que estn activos

    en ese momento.

    A continuacin mostramos el cdigo de un programa que copia unrectngulo de pxeles de una zona de la pantalla a otra y le aplica un zoom.Consiste en un ejemplo simple en el cual se hace una copia en el lugar dondeest sealando el cursor al picar con el botn izquierdo del ratn. Para hacer elzoom se utiliza la funcin void glPixelZoom(GLfloat xfactor, GLfloat yfactor)cuyos parmetros especifican los factores de zoom en los ejes x e yrespectivamente.

    Con las teclas + y - podemos configurar el factor de aumento para elzoom y con la tecla R reseteamos el factor de zoom a 1.

    #i ncl ude "gl ut . h"#i ncl ude #i ncl ude

    #def i ne checkI mageWi dt h 64#def i ne checkI mageHei ght 64GLubyt e checkI mage[ checkI mageHei ght ] [ checkI mageWi dth] [ 3] ;

    st at i c GLdoubl e zoomFact or = 1. 0;stati c GLi nt hei ght ;st at i c bool hayCopi a=f al se;

    st at i c i nt xCoor d=- 1, yCoor d=- 1;

  • 7/22/2019 Graficos, Planos en OpenGL

    20/37

    voi d makeCheckI mage( voi d){

    i nt i , j , c ;

    f or ( i = 0; i < checkI mageHei ght ; i ++) {f or ( j = 0; j < checkI mageWi dt h; j ++) {

    c = ( ( ( ( i &0x8) ==0) ( ( j &0x8) ) ==0)) *255;checkI mage[ i ] [ j ] [ 0] = ( GLubyte) c;checkI mage[ i ] [ j ] [ 1] = ( GLubyte) c;checkI mage[ i ] [ j ] [ 2] = ( GLubyte) c;

    }}

    }

    void copia (int x,int y)

    {

    GLint screeny;

    if(hayCopia){

    screeny = height - (GLint) y;

    glRasterPos2i (x, y);

    glPixelZoom (zoomFactor, zoomFactor);

    glCopyPixels (0, 0, checkImageWidth, checkImageHeight,

    GL_COLOR);

    glPixelZoom (1.0, 1.0);

    glFlush ();

    }

    }

    voi d i ni t (voi d)

    {gl Cl earCol or ( 0. 0, 0. 0, 0. 0, 0. 0) ;gl ShadeModel ( GL_FLAT) ;makeCheckI mage( ) ;gl Pi xel St orei ( GL_UNPACK_ALI GNMENT, 1) ;

    }

    voi d di spl ay( voi d){

    gl Cl ear ( GL_COLOR_BUFFER_BI T) ;gl Rast er Pos2i ( 0, 0) ;gl Dr awPi xel s( checkI mageWi dth, checkI mageHei ght , GL_RGB,

    GL_UNSI GNED_BYTE, checkI mage) ;

    copia (xCoord,yCoord);gl Fl ush( ) ;

    }

    voi d r eshape( i nt w, i nt h){

    gl Vi ewpor t ( 0, 0, ( GLsi zei ) w, ( GLsi zei ) h) ;hei ght = ( GLi nt ) h;gl Mat r i xMode( GL_PROJ ECTI ON) ;gl LoadI dent i t y( ) ;gl uOr t ho2D( 0. 0, ( GLdoubl e) w, 0. 0, ( GLdoubl e) h) ;gl Mat r i xMode( GL_MODELVI EW) ;gl LoadI dent i t y( ) ;

    }

  • 7/22/2019 Graficos, Planos en OpenGL

    21/37

    voi d mouse( i nt but t on, i nt state, i nt x, i nt y){

    swi t ch ( but t on) {case GLUT_LEFT_BUTTON:

    hayCopia=true;xCoord=x;

    yCoord=y;

    br eak;def aul t :

    br eak;}gl ut Post Redi spl ay( ) ;

    }

    voi d keyboar d( unsi gned char key, i nt x, i nt y){

    swi t ch ( key) {

    case 'r':case 'R':

    zoomFactor = 1.0;

    gl ut Post Redi spl ay( ) ;pr i nt f ( "ZoomFact or r eset eado a 1. 0\ n") ;br eak;

    case '+':

    zoomFactor += 0.5;

    pr i nt f ( "ZoomFact or es ahora %4. 1f \ n" , zoomFact or) ;br eak;

    case '-':

    zoomFactor -= 0.5;

    i f ( zoomFact or

  • 7/22/2019 Graficos, Planos en OpenGL

    22/37

    5 El Pipeline de renderizado de OpenGL

    La mayor parte de las implementaciones de OpenGL siguen un mismo

    orden en sus operaciones, una serie de plataformas de proceso, que en suconjunto crean lo que se suele llamar el OpenGL Rendering Pipeline.

    La palabra renderizacindefine un proceso de clculocomplejodesarrollado por un ordenador destinado a generar una imagen 2D a partir deuna escena 3D. As podra decirse que en el proceso de renderizacin, lacomputadora "interpreta" la escena 3D y la plasma en una imagen 2D

    Este proceso se desarrolla con el fin de imitar un espacio 3Dformadopor estructuras poligonales, comportamiento de luces, texturas, materiales,animacin, simulando ambientes y estructuras fsicas verosmiles, etc

    Cuando se trabaja en un programade diseo 3Dpor computadora, noes posible visualizar en tiempo real el acabado final deseado de una escena 3Dcompleja ya que esto requiere una potencia de clculo demasiado elevada. Porlo que se opta por crear el entorno 3D con una forma de visualizacin mssimple y tcnica y luego generar el lento proceso de renderizacinparaconseguir los resultados finales deseados.

    El siguiente diagrama describe el funcionamiento del pipeline:

    http://es.wikipedia.org/wiki/C%C3%A1lculohttp://es.wikipedia.org/w/index.php?title=Espacio_3D&action=edithttp://es.wikipedia.org/wiki/Animaci%C3%B3nhttp://es.wikipedia.org/wiki/Softwarehttp://es.wikipedia.org/wiki/3Dhttp://es.wikipedia.org/wiki/Computadorahttp://es.wikipedia.org/wiki/Computadorahttp://es.wikipedia.org/wiki/3Dhttp://es.wikipedia.org/wiki/Softwarehttp://es.wikipedia.org/wiki/Animaci%C3%B3nhttp://es.wikipedia.org/w/index.php?title=Espacio_3D&action=edithttp://es.wikipedia.org/wiki/C%C3%A1lculo
  • 7/22/2019 Graficos, Planos en OpenGL

    23/37

    Ilustracin 19 Pipeline de renderizado de OpenGL

    En este diagrama se puede apreciar el orden de operaciones que sigueel pipeline para renderizar. Por un lado tenemos el vertex data, que describelos objetos de nuestra escena, y por el otro, el pxel data, que describe laspropiedades de la escena que se aplican sobre la imagen tal y como serepresenta en el buffer. Ambas se pueden guardar en una display list, que esun conjunto de operaciones que se guardan para ser ejecutadas en cualquiermomento.

    Sobre el vertex data se pueden aplicar evaluators. Los evaluators deOpenGL nos permiten especificar una superficie solo usando sus puntos decontrol, podemos crear superficies compuestas por puntos, modelos dealambre (wireframe) o dibujar modelos sombreados (shaded) ya que losvectores normales a la superficie son calculados en forma automtica, y hastasuperficies con la aplicacin de Texturas.

    Luego se aplicaran las per-vertex operations, que convierten losvrtices en primitivas. Aqu es donde se aplican las transformacionesgeomtricas como rotaciones, translaciones, etc., por cada vrtice. En la

    seccin de primittive assembly, se hace clipping de lo que queda fuera delplano de proyeccin, entre otros. El clipping consiste en recortar (ocultar) todo

  • 7/22/2019 Graficos, Planos en OpenGL

    24/37

    aquello que esta pero no se ve. Es decir, todo aquello que la cmara nopuede ver, porque no entra en su ngulo de visin, se elimina.

    Por la parte de pxel data, tenemos las pxel operations. Aqu lospxeles son desempaquetados desde algn array del sistema (como el

    framebuffer) y tratados (escalados, etc.). Luego, si estamos tratando contexturas, se preparan en la seccin texture assembly.

    Ambos caminos convergen en la Rasterization, donde son convertidosen fragmentos. Cada fragmento ser un pxel del framebuffer. Aqu es dondese tiene en cuenta el modelo de sombreado, la anchura de las lneas, o elantialiassing.

    En la ltima etapa, las per-fragmet operations, es donde se preparanlos texels (elementos de texturas) para ser aplicados a cada pxel, la fog(niebla), el z-buffering, el blending, etc. Todas estas operaciones desembocan

    en el framebuffer, donde obtenemos el render final.

  • 7/22/2019 Graficos, Planos en OpenGL

    25/37

    6 Lectura y Dibujo de rectngulos de pxeles

    Existen dos procesos parecidos, pero distintos a la vez en el tratamiento deimgenes. La transferencia de datos del framebuffera memoria y viceversa noes idntica y provoca diferentes operaciones.

    Proceso de dibujo de rectngulos de pxeles

    En esta figura se describe el proceso de dibujo de pxeles en el frambuffer.

    Ilustracin 20 Dibujo de pxeles con glDrawPixeles()

  • 7/22/2019 Graficos, Planos en OpenGL

    26/37

  • 7/22/2019 Graficos, Planos en OpenGL

    27/37

    Ilustracin 21 Lectura de pxeles con g lReadPixeles()

    1. Si el formato no es GL_COLOR_INDEX o GL_STENCIL_INDEX (estoes, los pxeles que se van a leer no son ndices), los componentes setraducen a valores de rango 0.0 1.0 (de forma opuesta a la escritura).

    2. En caso de que sean ndices, se desplazan.3. Se aplican las escalas y distorsiones a cada componente. Se ajustan

    otra vez los valores a 0.0 1.0 en caso de que GL_MAP_COLOR seaTRUE. En caso de que se desee usar luminancia en vez de RGB, sesuman las tres componentes RGB.

    4. Si se trata de ndices, se enmascaran al nmero de bits del tipo dealmacenamiento (8,16 o 32 bits) y empaquetados en memoria.

    5. En caso de usarse el modo RGBA, se mapea el resultado con un mapandice a RGBA.

    6. Se empaqueta el resultado en memoria con las opciones que tuvieseglPixelStore * ().

    Los valores de escala y distorsin son los mismo que los usados cuando se realiz la

    escritura, as que sise estn haciendo las dos operaciones a la vez, hay que vigilar que

    estos datos son apropiados, puesto que de lo contrario podran ocurrir errores. Si se usan

    mapas para lectura y para escritura (dibujo), hay que reestablecer esos mapas.

  • 7/22/2019 Graficos, Planos en OpenGL

    28/37

    7 Formatos de imagen

    Las imgenes pueden ser guardadas en archivos usando diferentesformatos, ejemplos de ellos son el BMP, JPG y GIF, que quiz sean los msextendidos, o si no los ms conocidos. Todos ellos emplean una compresin delos datos, aunque cada uno define su algoritmo hacindolo mejor o peor paradeterminados usos. An as todos ellos contienen una estructura similar.Existir una cabecera con informacin acerca del tipo de imagen, tamao,nmero de colores, compresin utilizada, etc.; seguida de la informacin, esdecir de los datos de la imagen, comprimida.

    La calidad de la imagen la da el nmero de colores utilizados paradibujarla. Normalmente el nmero de colores es de 2, 16, 256 o 16 millones, lo

    que requiere el uso de 1, 4, 16 o 24 bits por pxel.

    Como ya sabemos el formato usado para representar el color es el RGB.Segn esto un color es la mezcla de la intensidad de tres colores, rojo, verde yazul. En una representacin binaria, un color vendra dado por 3 bytes: elprimer byte dara la intensidad del color rojo, el segundo la del color verde y eltercero la del color azul. Pues bien, se plantea un problema. En el caso de unaimagen de 16 millones de colores se tienen 24 bits por pxel, un byte para cadacolor del RGB, especifica el color real. Pero en el caso de imgenes queutilicen 4 o 16 bits por pxel hay que decir que intensidad de rojo, verde o azulse utilizar para representar el color real. Hay que crear una tabla que asocia

    cada color (serie de 4 o 16 bits) a las correspondientes cantidades de rojo,verde y azul. Esta tabla recibe el nombre de paleta de colores que ser distintaa cada imagen, por tanto debe aparecer junto a la cabecera del archivo.

    Por tanto, sealar a modo de resumen, que un fichero grfico contendr,independientemente del formato utilizado, una cabecera, la paleta de colores ylos datos de los pxeles (informacin de la imagen).

    El formato BMP

    EL formato BMP (BitMaP) es el formato mas extendido en los sistemasWindows y OS/2. Es quiz el formato de ficheros de imgenes ms simple queexiste y aunque admite compresin, en la prctica casi nunca se usa.

    Los archivos de mapas de bitsse componen de direcciones asociadas acdigos de color, uno para cada cuadro en una matriz de pixelestal como seesquematizara un dibujo de "colorea los cuadros" para nios pequeos.Normalmente, se caracterizan por ser muy poco eficientes en su uso deespacio en disco, pero pueden mostrar un buen nivel de calidad.

    Un fichero de este tipo consta de una cabecera de archivo con las letras'BM' (0x42 0x4D), una cabecera de informacin, la paleta (en caso de notratarse de una imagen de 16 millones de colores) y la informacin o datos.

    http://es.wikipedia.org/wiki/Bithttp://es.wikipedia.org/wiki/Pixelhttp://es.wikipedia.org/wiki/Pixelhttp://es.wikipedia.org/wiki/Bit
  • 7/22/2019 Graficos, Planos en OpenGL

    29/37

    Esta estructura queda resumida de la siguiente forma (utilizando os tiposdeclarados en Windows):

    BITMAPFILEHEADER.BITMAPINFOHEADER.

    RGBQUAD.BYTE.

    A continuacin se pasar a explicar cada una de estas partes utilizando lasestructuras y variables definidas en Windows.

    La cabecera de archivo. Es una estructura con los siguientes campos:

    typedef struct tagBITMAPFILEHEADER {UINT bfType;DWORD bfSize;

    UINT bfReserved1;UINT bfReserved2;DWORD bfOffBits;

    } BITMAPFILEHEADER;

    El campo bfTypeocupa dos bytes y se utiliza para especificar el tipo deformato grfico utilizado por el fichero, en el caso de BMP ser BM. bfSizeocupa cuatro bytes y contiene el tamao, en bytes, del archivo. Los siguientesparmetros estn reservados, y no nos interesan para nuestro propsito. Elltimo parmetro tambin ocupa cuatro bytes e indica el desplazamiento, enbytes, desde el inicio del archivo hasta el comienzo de la informacin grfica.

    La cabecera de informacin. Se sita dentro de otra estructura que contieneadems la paleta de colores.

    typedef struct tagBITMAPINFO {BITMAPINFOHEADER bmiHeader;RGBQUAD bmiColors[ 1 ];

    } BITMAPINFO;

    typedef struct tagBITMAPINFOHEADER {

    DWORD biSize;DWORD biWidth;DWORD biHeight;WORD biPlanes;WORD biBitCount;DWORD biCompression;DWORD biSizeImage;DWORD biXpelsPerMeter;DWORD biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant;

    } BITMAPINFOHEADER;

  • 7/22/2019 Graficos, Planos en OpenGL

    30/37

    El primer parmetro (4 bytes) da el tamao (siempre en bytes) de lacabecera de informacin, que ser 40. Los dos siguientes (4 bytes ambos) danel tamao (ancho y alto) en pxeles de la imagen. El atributo biPlanes, queocupa 2 bytes, informa del nmero de planos de la imagen, generalmente uno.El siguiente es biBitCount, de 2 bytes de tamao, que da el nmero de bits por

    pxel, esto es, 1, 4, 8 o 24. Los seis parmetros que restan ocupan todos 4bytes y sus funciones son: dar la compresin utilizada (se explicar masadelante), pudiendo tomar los valores BI_RGB si no hay compresin, BI_RLE8si la compresin es RLE para 8 bits por pxel y BI_RLE si es para 4 bits porpxel); dar el tamao de la imagen; dar los pxeles por metro horizontal yvertical; dar el nmero de colores usados (con biClrUsed); y cuales son losimportantes (si biClrImportantvale 0 todos son importantes).

    La paleta de color. Definida como un array de estructuras RGBQUAD ycontiene los colores del mapa de bits. Si se tiene una imagen de 1 bit por pxel,significa que se tiene una imagen monocroma, la paleta tiene dos entradas

    (array de tamao 2). Si es de 4 bits por pxel la paleta de colores es de 16entradas. Si es de 8 bits por pxel la paleta es de 256 entradas.

    La estructura RGBQUADtiene la siguiente forma:

    typedef struct tagRGBQUAD {BYTE rgbBlue;BYTE rgbGreen;BYTE rgbRed;BYTE rgbReserved;

    } RGBQUAD;

    Determina los valores de intensidad de los colores rojo verde y azul paraun color dado (ndice del array).

    Los datos. A continuacin de la estructura BITMAPINFO aparece ya lainformacin grfica del fichero. Un array de bytes que representan los pxelesdel mapa de bits. Recordar que un bitmap se comienza definiendo por laesquina inferior izquierda, y aadir que el valor del color tambin esta el revs,es decir, se comienza dando un valor para el azul, luego para el verde y porltimo para el rojo.

    La imagen de un fichero BMP se almacena en formato DIB (DeviceIndependent Bitmap -Mapa de bits independiente de dispositivo-), que permiteal sistema Windows visualizar el mapa de bits en cualquier tipo de dispositivode visualizacin puesto que el fichero especifica el color de un pxel de formaindependiente del mtodo usado para representar el color (1, 4, 8, 24 bits porpxel).

    Como ya se dijo antes, el formato BMP soporta compresin pero casinunca se usa, es esto lo que hace que los ficheros sean tan grandes. Elalgoritmo de compresin utilizada es el RLE(run-length encoded), que permite

    comprimir los ficheros que utilicen una representacin de 4 y 8 bits por pxel.

  • 7/22/2019 Graficos, Planos en OpenGL

    31/37

    8 Manejo de ficheros BMP en OpenGL

    Ahora que ya conocemos la estructura de un fichero BMP, podemosutilizarlo para incorporarlo a nuestra aplicacin OpenGL bajo Windows,principalmente para la incorporacin de texturas.

    Para ayudar a su comprensin se acompaa de cdigo fuente extrado delejemplo FicheroBMP que visualiza, guarda e imprime un archivo de imagenBMP. A partir de este ejemplo se proceder a detallar las operaciones demanejo de ficheros de tipo Bitmap.

    Lectura de un Fichero . Debe abrirse el fichero para lectura binaria, leerlas cabeceras, para obtener el tamao de la informacin y as reservar espacio

    suficiente en memoria.

    /* Carga un fichero desde desde el disco a memoria */

    void *CargarBMP (char *archivo, BITMAPINFO **info){FILE *f;void *bits;long tamanoBMP, tamanoInfo;BITMAPFILEHEADER cabecera;

    if ((f = fopen(archivo, "rb")) == NULL)return (NULL);

    /*Leer la cabecera del archivo y comprobar si se trataen verdad de un archibo BMP*/

    if (fread(&cabecera, sizeof(BITMAPFILEHEADER), 1, f) < 1){fclose(f);return (NULL);

    };if (cabecera.bfType != 'MB'){

    /*Si no es BMP aboratar*/fclose(f);return (NULL);

    };

  • 7/22/2019 Graficos, Planos en OpenGL

    32/37

    /*Obtener el tamao de la cabecera de informacionrestando el tamao de la cabecera del archivo altamao de las dos cabeceras (desplazamiento delinicio del archivo al inicio de la informacion)*/

    tamanoInfo = cabecera.bfOffBits - sizeof(BITMAPFILEHEADER);if ((*info = (BITMAPINFO *)malloc(tamanoInfo)) == NULL){

    fclose(f);return (NULL);

    };

    /*Obtener la cabecera de informacion*/if (fread(*info, 1, tamanoInfo, f) < tamanoInfo){

    free(*info);fclose(f);return (NULL);

    };

    /*Obtener el tamano en bytes de la informacion del archivoy reservar espacio en memoria para guardarlo*/

    if ((tamanoBMP = (*info)->bmiHeader.biSizeImage) == 0)tamanoBMP = ((*info)->bmiHeader.biWidth * (*info)-

    >bmiHeader.biBitCount + 7) / 8 * abs((*info)->bmiHeader.biHeight);if ((bits = malloc(tamanoBMP)) == NULL){

    free(*info);fclose(f);

    return (NULL);};

    /*Cargar la informacion*/if (fread(bits, 1, tamanoBMP, f) < tamanoBMP){

    free(*info);free(bits);fclose(f);return (NULL);

    };fclose(f);

    return (bits);}

    Guardar una imagen en disco. Para guardar una imagen que esta enpantalla, previamente hay que leerla, pasarla a formato BMP y posteriormenteguardarla en disco.

  • 7/22/2019 Graficos, Planos en OpenGL

    33/37

    /* Guarda una imagen BMP leida previamente a disco */

    int GuardarBMP (char *archivo, BITMAPINFO *info, void *bits) {FILE *f;long tamanoArchivo, tamanoInfo, tamanoBMP;

    BITMAPFILEHEADER cabecera;

    /*Abrir el archivo en escritura binaria*/if ((f = fopen(archivo, "wb")) == NULL)

    return (-1);

    /*Obtener el tamao de los datos de igualforma que antes*/

    if (info->bmiHeader.biSizeImage == 0) /* Figure out the bitmap size*/

    tamanoBMP = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount + 7) / 8 * abs(info->bmiHeader.biHeight);

    elsetamanoBMP = info->bmiHeader.biSizeImage;

    /*Obtener al tamao de la cabecera deinformacion*/

    tamanoInfo = sizeof(BITMAPINFOHEADER);

    /*Editar campos de la cabecera en funcionde la compresin usada*/

    switch (info->bmiHeader.biCompression){case BI_BITFIELDS :tamanoInfo += 12; /* Aadir 3 mascaras RGB de 4

    bytes (double)*/if (info->bmiHeader.biClrUsed == 0)

    break;case BI_RGB :

    if (info->bmiHeader.biBitCount > 8 && info->bmiHeader.biClrUsed == 0)

    break;case BI_RLE8 :

    case BI_RLE4 :if (info->bmiHeader.biClrUsed == 0)

    tamanoInfo += (1 bmiHeader.biBitCount) * 4;

    /* bmiHeader.biClrUsed * 4;break;

    }

  • 7/22/2019 Graficos, Planos en OpenGL

    34/37

    /*Calcular el tamao del archivo*/tamanoArchivo = sizeof(BITMAPFILEHEADER) +

    tamanoInfo + tamanoBMP;

    /*Completar los campos de las cabeceras*/

    cabecera.bfType = 'MB';cabecera.bfSize = tamanoArchivo;cabecera.bfReserved1 = 0;cabecera.bfReserved2 = 0;cabecera.bfOffBits = sizeof(BITMAPFILEHEADER) +

    tamanoInfo;

    /*Escribir en el fichero las cabecera y los datos*/if (fwrite(&cabecera, 1, sizeof(BITMAPFILEHEADER), f) bmiHeader.biWidth = viewport[2];(*info)->bmiHeader.biHeight = viewport[3];(*info)->bmiHeader.biPlanes = 1;(*info)->bmiHeader.biBitCount = 24;(*info)->bmiHeader.biCompression = BI_RGB;(*info)->bmiHeader.biSizeImage = tamanoBMP;(*info)->bmiHeader.biXPelsPerMeter = 2952;(*info)->bmiHeader.biYPelsPerMeter = 2952;(*info)->bmiHeader.biClrUsed = 0;(*info)->bmiHeader.biClrImportant = 0;

    return (bits);}

  • 7/22/2019 Graficos, Planos en OpenGL

    36/37

    Imprimir una imagen BMP. Para imprimir una imagen por impresoratambin hay que leerla de pantalla previamente. Despus de esto hay quemostrar el cuadro de dialogo de impresoras para que el usuario pueda elegir el

    color, el nmero de copias y dems opciones. Cuando el usuario acepte, secolocar el trabajo en la cola de impresin.

    /* Imprime por dispositivo una imagen leida de pantalla*/

    int ImprimirBMP (HWND padre, BITMAPINFO *info, void *bits){PRINTDLG pd;long xtam, ytam, xdesplazamiento, ydesplazamiento;RECT area;DOCINFO di;HDC hdc;HBITMAP bitmap;HBRUSH brocha;HCURSOR ocupado, cursorViejo;

    if (info == NULL || bits == NULL)return (0);

    /*Iniciar el cuadro de dialogo de usuario paraimpresoras*/

    memset(&pd, 0, sizeof(pd));pd.lStructSize = sizeof(pd);pd.hwndOwner = padre;pd.Flags = PD_RETURNDC;pd.hInstance = NULL;

    if (!PrintDlg(&pd))return (0); /*Si el usuario aborta*/

    /*Si se va a imprimir, cambiar el cursor mientras sehacen las gestiones*/

    ocupado = LoadCursor(NULL, IDC_WAIT);cursorViejo = SetCursor(ocupado);SetMapMode(pd.hDC, MM_TEXT);di.cbSize = sizeof(DOCINFO);di.lpszDocName = "Imagen BMP OpenGL";di.lpszOutput = NULL;StartDoc(pd.hDC, &di);StartPage(pd.hDC);

  • 7/22/2019 Graficos, Planos en OpenGL

    37/37

    /*Poner el fondo a blanco*/area.top = 0;area.left = 0;

    area.right = GetDeviceCaps(pd.hDC, HORZRES);area.bottom = GetDeviceCaps(pd.hDC, VERTRES);brocha = CreateSolidBrush(0x00ffffff);FillRect(pd.hDC, &area, brocha);

    /*Escalar el Bitmap para que entre en losmargenes de la pagina*/

    hdc = CreateCompatibleDC(pd.hDC);bitmap = CreateDIBitmap(hdc, &(info->bmiHeader), CBM_INIT,

    bits, info, DIB_RGB_COLORS);SelectObject(hdc, bitmap);

    xtam = area.right;ytam = xtam * info->bmiHeader.biHeight / info-

    >bmiHeader.biWidth;if (ytam > area.bottom){

    ytam = area.bottom;xtam = ytam * info->bmiHeader.biWidth / info-

    >bmiHeader.biHeight;};

    /*Margenes procesados tomando la mitad de la diferenciaentre anchuras y alturas*/xdesplazamiento = (area.right - xtam) / 2;ydesplazamiento = (area.bottom - ytam) / 2;

    StretchBlt(pd.hDC, xdesplazamiento, ydesplazamiento, xtam,ytam, hdc, 0, 0, info->bmiHeader.biWidth, info->bmiHeader.biHeight,SRCCOPY);

    /*Terminar el proceso*/EndPage(pd.hDC);

    EndDoc(pd.hDC);DeleteDC(pd.hDC);DeleteObject(bitmap);DeleteObject(brocha);DeleteObject(ocupado);DeleteDC(hdc);SetCursor(cursorViejo);return (1);

    }