Saltar al contenido

leer el valor de píxel en el archivo bmp

Después de de nuestra prolongada búsqueda de datos resolvimos este conflicto que suelen tener algunos lectores. Te brindamos la respuesta y nuestro deseo es resultarte de gran ayuda.

Solución:

El siguiente fragmento de código no está completo y contiene muchas suposiciones y errores ocultos. Lo escribí desde cero para un proyecto de curso universitario desde la mera observación, donde cumplía mínimamente con todos los requisitos. Ya no trabajé en él, porque debe haber bibliotecas que hagan el trabajo mucho mejor.

Estas son las condiciones en las que funcionó bien (algunas suposiciones se señalan en los comentarios):

  1. Se ejecutó en Windows, no estoy seguro de otras plataformas.
  2. Funciona para imágenes BMP en color de 24 bits
  3. Asume que el ancho de la imagen es un múltiplo de 4, por lo que no maneja los bytes de relleno en caso de que no lo sea
  4. Decodifica el ancho y alto de la imagen como enteros little endian de 32 bits.
  5. Devuelve un puntero a la memoria asignada dinámicamente, puede causar una pérdida de memoria si la persona que llama no la libera

Otras respuestas han cubierto algunos de estos problemas.


Puedes probar este:

unsigned char* readBMP(char* filename)

    int i;
    FILE* f = fopen(filename, "rb");
    unsigned char info[54];

    // read the 54-byte header
    fread(info, sizeof(unsigned char), 54, f); 

    // extract image height and width from header
    int width = *(int*)&info[18];
    int height = *(int*)&info[22];

    // allocate 3 bytes per pixel
    int size = 3 * width * height;
    unsigned char* data = new unsigned char[size];

    // read the rest of the data at once
    fread(data, sizeof(unsigned char), size, f); 
    fclose(f);

    for(i = 0; i < size; i += 3)
    
            // flip the order of every 3 bytes
            unsigned char tmp = data[i];
            data[i] = data[i+2];
            data[i+2] = tmp;
    

    return data;

Ahora data debe contener los valores (R, G, B) de los píxeles. El color del píxel (i, j) se almacena en data[3 * (i * width + j)], data[3 * (i * width + j) + 1] y data[3 * (i * width + j) + 2].

En la última parte, el intercambio entre cada primer y tercer píxel se realiza porque descubrí que los valores de color se almacenan como triples (B, G, R), no como (R, G, B).

Código de la función readBMP después de la corrección de relleno:

unsigned char* ReadBMP(char* filename)

    int i;
    FILE* f = fopen(filename, "rb");

    if(f == NULL)
        throw "Argument Exception";

    unsigned char info[54];
    fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header

    // extract image height and width from header
    int width = *(int*)&info[18];
    int height = *(int*)&info[22];

    cout << endl;
    cout << "  Name: " << filename << endl;
    cout << " Width: " << width << endl;
    cout << "Height: " << height << endl;

    int row_padded = (width*3 + 3) & (~3);
    unsigned char* data = new unsigned char[row_padded];
    unsigned char tmp;

    for(int i = 0; i < height; i++)
    
        fread(data, sizeof(unsigned char), row_padded, f);
        for(int j = 0; j < width*3; j += 3)
        
            // Convert (B, G, R) to (R, G, B)
            tmp = data[j];
            data[j] = data[j+2];
            data[j+2] = tmp;

            cout << "R: "<< (int)data[j] << " G: " << (int)data[j+1]<< " B: " << (int)data[j+2]<< endl;
        
    

    fclose(f);
    return data;

Aquí hay una versión funcional en C ++ de la respuesta:

#include 
#include 
#include 
#include 
#include 
#include 

std::vector readBMP(const std::string &file)

    static constexpr size_t HEADER_SIZE = 54;

    std::ifstream bmp(file, std::ios::binary);

    std::array header;
    bmp.read(header.data(), header.size());

    auto fileSize = *reinterpret_cast(&header[2]);
    auto dataOffset = *reinterpret_cast(&header[10]);
    auto width = *reinterpret_cast(&header[18]);
    auto height = *reinterpret_cast(&header[22]);
    auto depth = *reinterpret_cast(&header[28]);

    std::cout << "fileSize: " << fileSize << std::endl;
    std::cout << "dataOffset: " << dataOffset << std::endl;
    std::cout << "width: " << width << std::endl;
    std::cout << "height: " << height << std::endl;
    std::cout << "depth: " << depth << "-bit" << std::endl;

    std::vector img(dataOffset - HEADER_SIZE);
    bmp.read(img.data(), img.size());

    auto dataSize = ((width * 3 + 3) & (~3)) * height;
    img.resize(dataSize);
    bmp.read(img.data(), img.size());

    char temp = 0;

    for (auto i = dataSize - 4; i >= 0; i -= 3)
    
        temp = img[i];
        img[i] = img[i+2];
        img[i+2] = temp;

        std::cout << "R: " << int(img[i] & 0xff) << " G: " << int(img[i+1] & 0xff) << " B: " << int(img[i+2] & 0xff) << std::endl;
    

    return img;

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *