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):
- Se ejecutó en Windows, no estoy seguro de otras plataformas.
- Funciona para imágenes BMP en color de 24 bits
- 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
- Decodifica el ancho y alto de la imagen como enteros little endian de 32 bits.
- 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;