Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
bmp reader
#include <iostream>
#include <fstream>
#include "main.h"
int main(int argc, char *argv[])
{
if (argc < 2) {
std::cout << "Usage: " << argv[0] << " file_name" << std::endl;
return 0;
}
char *fileName = argv[1];
// открываем файл
std::ifstream fileStream(fileName, std::ifstream::binary);
if (!fileStream) {
std::cout << "Error opening file '" << fileName << "'." << std::endl;
return 0;
}
// заголовк изображения
BITMAPFILEHEADER fileHeader;
read(fileStream, fileHeader.bfType, sizeof(fileHeader.bfType));
read(fileStream, fileHeader.bfSize, sizeof(fileHeader.bfSize));
read(fileStream, fileHeader.bfReserved1, sizeof(fileHeader.bfReserved1));
read(fileStream, fileHeader.bfReserved2, sizeof(fileHeader.bfReserved2));
read(fileStream, fileHeader.bfOffBits, sizeof(fileHeader.bfOffBits));
if (fileHeader.bfType != 0x4D42) {
std::cout << "Error: '" << fileName << "' is not BMP file." << std::endl;
return 0;
}
// информация изображения
BITMAPINFOHEADER fileInfoHeader;
read(fileStream, fileInfoHeader.biSize, sizeof(fileInfoHeader.biSize));
// bmp core
if (fileInfoHeader.biSize >= 12) {
read(fileStream, fileInfoHeader.biWidth, sizeof(fileInfoHeader.biWidth));
read(fileStream, fileInfoHeader.biHeight, sizeof(fileInfoHeader.biHeight));
read(fileStream, fileInfoHeader.biPlanes, sizeof(fileInfoHeader.biPlanes));
read(fileStream, fileInfoHeader.biBitCount, sizeof(fileInfoHeader.biBitCount));
}
// получаем информацию о битности
int colorsCount = fileInfoHeader.biBitCount >> 3;
if (colorsCount < 3) {
colorsCount = 3;
}
int bitsOnColor = fileInfoHeader.biBitCount / colorsCount;
int maskValue = (1 << bitsOnColor) - 1;
// bmp v1
if (fileInfoHeader.biSize >= 40) {
read(fileStream, fileInfoHeader.biCompression, sizeof(fileInfoHeader.biCompression));
read(fileStream, fileInfoHeader.biSizeImage, sizeof(fileInfoHeader.biSizeImage));
read(fileStream, fileInfoHeader.biXPelsPerMeter, sizeof(fileInfoHeader.biXPelsPerMeter));
read(fileStream, fileInfoHeader.biYPelsPerMeter, sizeof(fileInfoHeader.biYPelsPerMeter));
read(fileStream, fileInfoHeader.biClrUsed, sizeof(fileInfoHeader.biClrUsed));
read(fileStream, fileInfoHeader.biClrImportant, sizeof(fileInfoHeader.biClrImportant));
}
// bmp v2
fileInfoHeader.biRedMask = 0;
fileInfoHeader.biGreenMask = 0;
fileInfoHeader.biBlueMask = 0;
if (fileInfoHeader.biSize >= 52) {
read(fileStream, fileInfoHeader.biRedMask, sizeof(fileInfoHeader.biRedMask));
read(fileStream, fileInfoHeader.biGreenMask, sizeof(fileInfoHeader.biGreenMask));
read(fileStream, fileInfoHeader.biBlueMask, sizeof(fileInfoHeader.biBlueMask));
}
// если маска не задана, то ставим маску по умолчанию
if (fileInfoHeader.biRedMask == 0 || fileInfoHeader.biGreenMask == 0 || fileInfoHeader.biBlueMask == 0) {
fileInfoHeader.biRedMask = maskValue << (bitsOnColor * 2);
fileInfoHeader.biGreenMask = maskValue << bitsOnColor;
fileInfoHeader.biBlueMask = maskValue;
}
// bmp v3
if (fileInfoHeader.biSize >= 56) {
read(fileStream, fileInfoHeader.biAlphaMask, sizeof(fileInfoHeader.biAlphaMask));
} else {
fileInfoHeader.biAlphaMask = maskValue << (bitsOnColor * 3);
}
// bmp v4
if (fileInfoHeader.biSize >= 108) {
read(fileStream, fileInfoHeader.biCSType, sizeof(fileInfoHeader.biCSType));
read(fileStream, fileInfoHeader.biEndpoints, sizeof(fileInfoHeader.biEndpoints));
read(fileStream, fileInfoHeader.biGammaRed, sizeof(fileInfoHeader.biGammaRed));
read(fileStream, fileInfoHeader.biGammaGreen, sizeof(fileInfoHeader.biGammaGreen));
read(fileStream, fileInfoHeader.biGammaBlue, sizeof(fileInfoHeader.biGammaBlue));
}
// bmp v5
if (fileInfoHeader.biSize >= 124) {
read(fileStream, fileInfoHeader.biIntent, sizeof(fileInfoHeader.biIntent));
read(fileStream, fileInfoHeader.biProfileData, sizeof(fileInfoHeader.biProfileData));
read(fileStream, fileInfoHeader.biProfileSize, sizeof(fileInfoHeader.biProfileSize));
read(fileStream, fileInfoHeader.biReserved, sizeof(fileInfoHeader.biReserved));
}
// проверка на поддерку этой версии формата
if (fileInfoHeader.biSize != 12 && fileInfoHeader.biSize != 40 && fileInfoHeader.biSize != 52 &&
fileInfoHeader.biSize != 56 && fileInfoHeader.biSize != 108 && fileInfoHeader.biSize != 124) {
std::cout << "Error: Unsupported BMP format." << std::endl;
return 0;
}
if (fileInfoHeader.biBitCount != 16 && fileInfoHeader.biBitCount != 24 && fileInfoHeader.biBitCount != 32) {
std::cout << "Error: Unsupported BMP bit count." << std::endl;
return 0;
}
if (fileInfoHeader.biCompression != 0 && fileInfoHeader.biCompression != 3) {
std::cout << "Error: Unsupported BMP compression." << std::endl;
return 0;
}
// rgb info
RGBQUAD **rgbInfo = new RGBQUAD*[fileInfoHeader.biHeight];
for (unsigned int i = 0; i < fileInfoHeader.biHeight; i++) {
rgbInfo[i] = new RGBQUAD[fileInfoHeader.biWidth];
}
// определение размера отступа в конце каждой строки
int linePadding = ((fileInfoHeader.biWidth * (fileInfoHeader.biBitCount / 8)) % 4) & 3;
// чтение
unsigned int bufer;
for (unsigned int i = 0; i < fileInfoHeader.biHeight; i++) {
for (unsigned int j = 0; j < fileInfoHeader.biWidth; j++) {
read(fileStream, bufer, fileInfoHeader.biBitCount / 8);
rgbInfo[i][j].rgbRed = bitextract(bufer, fileInfoHeader.biRedMask);
rgbInfo[i][j].rgbGreen = bitextract(bufer, fileInfoHeader.biGreenMask);
rgbInfo[i][j].rgbBlue = bitextract(bufer, fileInfoHeader.biBlueMask);
rgbInfo[i][j].rgbReserved = bitextract(bufer, fileInfoHeader.biAlphaMask);
}
fileStream.seekg(linePadding, std::ios_base::cur);
}
// вывод
for (unsigned int i = 0; i < fileInfoHeader.biHeight; i++) {
for (unsigned int j = 0; j < fileInfoHeader.biWidth; j++) {
std::cout << std::hex
<< +rgbInfo[i][j].rgbRed << " "
<< +rgbInfo[i][j].rgbGreen << " "
<< +rgbInfo[i][j].rgbBlue << " "
<< +rgbInfo[i][j].rgbReserved
<< std::endl;
}
std::cout << std::endl;
}
return 1;
}
unsigned char bitextract(const unsigned int byte, const unsigned int mask) {
if (mask == 0) {
return 0;
}
// определение количества нулевых бит справа от маски
int
maskBufer = mask,
maskPadding = 0;
while (!(maskBufer & 1)) {
maskBufer >>= 1;
maskPadding++;
}
// применение маски и смещение
return (byte & mask) >> maskPadding;
}
#ifndef MAIN_H_INCLUDED
#define MAIN_H_INCLUDED
// CIEXYZTRIPLE stuff
typedef int FXPT2DOT30;
typedef struct {
FXPT2DOT30 ciexyzX;
FXPT2DOT30 ciexyzY;
FXPT2DOT30 ciexyzZ;
} CIEXYZ;
typedef struct {
CIEXYZ ciexyzRed;
CIEXYZ ciexyzGreen;
CIEXYZ ciexyzBlue;
} CIEXYZTRIPLE;
// bitmap file header
typedef struct {
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
} BITMAPFILEHEADER;
// bitmap info header
typedef struct {
unsigned int biSize;
unsigned int biWidth;
unsigned int biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
unsigned int biXPelsPerMeter;
unsigned int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
unsigned int biRedMask;
unsigned int biGreenMask;
unsigned int biBlueMask;
unsigned int biAlphaMask;
unsigned int biCSType;
CIEXYZTRIPLE biEndpoints;
unsigned int biGammaRed;
unsigned int biGammaGreen;
unsigned int biGammaBlue;
unsigned int biIntent;
unsigned int biProfileData;
unsigned int biProfileSize;
unsigned int biReserved;
} BITMAPINFOHEADER;
// rgb quad
typedef struct {
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
} RGBQUAD;
// read bytes
template <typename Type>
void read(std::ifstream &fp, Type &result, std::size_t size) {
fp.read(reinterpret_cast<char*>(&result), size);
}
// bit extract
unsigned char bitextract(const unsigned int byte, const unsigned int mask);
#endif // MAIN_H_INCLUDEDs
@rubot813

This comment has been minimized.

Copy link

@rubot813 rubot813 commented Dec 8, 2020

	fileStream.seekg(linePadding, std::ios_base::cur);

Забавно. Что будешь делать если картинка без паддинга?
malloc/new нужного тебе размера (linePadding * height).

Если картинка без паддинга то linePadding == 0 . Но там и без этого вариант такой себе.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.