Capítulo 4 Pixels

FreeImage proporciona funciones para leer el valor de pixels y para modificarlos.

Leer datos de pixels

Podemos considerar que cada pixel tiene un valor numérico, que pude codificar un índice dentro de una paleta de colores o directamente un color.

Si nos interesa obtener un puntero a la zona de memoria que contiene la información de los pixels podemos usar la función FreeImage_GetBits, pasando como parámetro un puntero a un FIBITMAP. El puntero devuelto apunta a datos abstractos. Recordemos que cada pixel puede estar codificado en 1, 4, 8, 16, 24, 32 bits para mapas de bits estándar o 16, 32, 48, 64, 96 y 128 para los no estándar, y que el valor puede codificar un valor o ser el índice en una paleta de colores.

También es posible que el FIBITMAP no contenga información sobre los pixels, a veces sólo contiene la cabecera y metadatos. Podemos averiguar si un mapa de bits contiene información de pixels mediante la función FreeImage_HasPixels.

Si optamos por procesar la información de pixels a partir de los datos en crudo tendremos que obtener la información necesaria para interpretar los valores apuntados por ese puntero.

En general, los mapas de bits que usen 8 o menos bits por pixel tendrán una paleta. El resto codificarán cada componente de color en ciertos bits.

Para mapas de bits que no contengan paleta, podemos usar la función FreeImage_GetBPP para obtener el número de bits por pixel, y las funciones FreeImage_GetRedMask, FreeImage_GetGreenMask y FreeImage_GetBlueMask para obtener las máscaras para cada color básico.

Para obtener el color de un pixel en un mapa de bits sin paleta podemos usar una expresión de este tipo:

    DWORD valor=0;
    for(unsigned int i=0; i < nBytes; i++) {
        valor <<= 8;
        valor |= bits[y*(nBytes*FreeImage_GetWidth(dib))+x*nBytes+i];
    }

Para mapas de bits con paleta será necesario separar los bits correspondientes a cada pixel, que nos indicarán el índice de color dentro de la paleta.

    BYTE b = bits[y*(FreeImage_GetWidth(dib)/nPixels)+x];
    RGBQUAD color;
    int index;
    for(unsigned int i=0; i < nPixels; i++) {
        index = (int)((b & mask)>>(8-bpp));
        color = pal[index];
        b <<= bpp;
    }

Todo este proceso es bastante tedioso, pero en ciertas ocasiones puede ser más cómodo trabajar con los datos de este modo.

Si solo nos interesa obtener la dirección de los datos correspondientes a una línea concreta de un mapa de bits, podemos usar la función FreeImage_GetScanLine, indicando como parámetros el puntero a la estructura FIBITMAP con la imagen y la coordenada y de la línea que queremos recuperar.

Probablemente esta opción sea más interesante cuando el número de datos correspondientes a una línea no sea múltiplo del número de datos por pixel, ya que puede haber datos de "relleno" al final de cada línea de pixels.

Ejemplo 5

Nombre Fichero Fecha Tamaño Contador Descarga
Ejemplo 5 FreeImage005.zip 2023-04-26 1763 bytes 242

Consultar el color de pixels mediante coordenadas

Podemos obviar todo el proceso anterior mediante las funciones FreeImage_GetPixelColor, para mapas de bits sin paleta, y FreeImage_GetPixelIndex para mapa de bits con paleta.

Indicaremos en el primer parámetro el DIB, en el segundo la coordenada x, en el tercero la coordenada y.

Para la primera función, en el cuarto parámetro se pasa un puntero a una estructura RGBQUAD que recibirá el color del pixel indicado. Para la segunda pasaremos un puntero a un BYTE que recibirá el índice dentro de la paleta.

Los dos ejemplos anteriores quedan mucho más sencillos de expresar y comprender usando estas funciones:

    // Mapa de bits sin paleta:
    RGBQUAD valor;
    valor = FreeImage_GetPixelColor(dib, x, y, &valor);

    // Mapa de bits con paleta:
    BYTE b;
    FreeImage_GetPixelIndex(dib, x, y, &b);
    RGBQUAD valor = pal[b];

Modificar pixels

Para modificar el color de un pixel disponemos de dos funciones. FreeImage_SetPixelColor, para mapas de bits sin paleta, y FreeImage_SetPixelIndex para mapas de bits con paleta.

No se puede asignar un color directamente a un mapa de bits con paleta ya que los colores están limitados a los contenidos en la paleta, de modo que antes de asignar un color a un pixel deberemos, o bien buscarlo en la paleta y elegir el índice del color deseado o el del más parecido, o bien añadir el color a la paleta si quedan posiciones libres.

En mapas de bits sin paleta los colores disponibles están limitados por el número de bits, por lo que siempre será posible asignar un color, aunque podamos perder algunos bits al aplicar las máscaras de cada componente de color.

Ejemplo 6

Nombre Fichero Fecha Tamaño Contador Descarga
Ejemplo 6 FreeImage006.zip 2023-04-26 1593 bytes 224