Answer the question
In order to leave comments, you need to log in
Why can't read/write bmp image?
I'm trying to write a program for working with .bmp files, I took the structure from the Microsoft website, it's definitely correct)
I can read and write InfoHeader and FileHeader - everything is 1 in 1, but then there's a problem.
I need to read the RGB data into a dynamic array, and apparently I'm doing something wrong... That is, I tried a bunch of ways, but so far only 2 lines work (more or less) (for some reason it only works with lena.bmp works, he probably likes the girl ..) and byte by byte. But as a result, the size of the output file is larger than the input file (almost 3 times), and the colors all "break" + a lot of noise.
That is, for some reason he writes something superfluous, and something is clearly wrong at the beginning ...
I know that I’m reading in the wrong order at all - it’s necessary in BGR, but I don’t change anything, I just read then I write it down.
Here is the code in general, please help, in any way there is some obvious error ..
#include <iostream>
#include <stdio.h>
using namespace std;
typedef long DWORD;//4 байта
typedef short WORD;//2 байта
typedef unsigned char byte;//1 байт
#pragma pack(push,1)
struct BITMAPFILEHEADER
{
WORD Type; // ‘BM’ 0x4D42
DWORD Size; // Размер файла в байтах, BitCount*Height*Width+ OffsetBits
WORD Reserved1; // Зарезервирован; должен быть нуль
WORD Reserved2; // Зарезервирован; должен быть нуль
DWORD OffsetBits; // Смещение данных от начала файла в байтах// = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
};
#pragma pack(pop)
struct BITMAPINFOHEADER
{
DWORD Size; // Число байтов необходимое для структуры = 40
DWORD Width; // Ширина точечного рисунка в пикселях
DWORD Height; // Высота точечного рисунка в пикселях
WORD Planes; // Число плоскостей целевого устройства = 1
WORD BitCount; // Глубина цвета, число бит на точку = 0,1,4,8,16,24,32
DWORD Compression; // Тип сжатия = 0 для несжатого изображения
DWORD SizeImage; // Размер изображения в байтах BitCount*Height*Width
DWORD XPelsPerMeter; // Разрешающая способность по горизонтали
DWORD YPelsPerMeter; // Разрешающая способность по вертикали
DWORD ColorUsed; // Число индексов используемых цветов. Если все цвета = 0
DWORD ColorImportant; // Число необходимых цветов = 0
};
struct RGBTRIPLE
{
byte Blue;
byte Green;
byte Red;
};
struct RGBQUAD
{
byte Blue;
byte Green;
byte Red;
byte Reserved;
};
class Image {
BITMAPINFOHEADER BMInfoHeader;
BITMAPFILEHEADER BMFileHeader;
RGBTRIPLE **Rgbtriple;
// данные могут храниться и в одномерном массиве RGBTRIPLE *Rgbtriple, при этом изменяется способ обращения к пикселу Rgbtriple[i*Width+j] вместо Rgbtriple[i][j]
RGBQUAD **Rgbquad;
char fileName[100];
public:
Image (char *fileName); // Конструктор объекта изображения из файла
Image(); // Конструктор без параметров, создает пустой контейнер под изображение
~Image (); // Деструктор
int loadimage(char *fileName); // метод загрузки изображения
void writeimage(char *fileName); // метод записи изображения в файл
void imageinfo();
};
Image::Image()
{
Rgbtriple=NULL;
Rgbquad=NULL;
char tpm[] = "";
strcpy_s(fileName,tpm);
}
Image::~Image()
{
if(Rgbtriple) delete(Rgbtriple);
if(Rgbquad) delete(Rgbquad);
}
int Image::loadimage(char *filename)
{
FILE *f;
int imageIdx=0; //image index counter
fopen_s(&f,filename,"rb");//открываем файл
if (f == NULL) return 0;//если не смогли открыть - возвращаем код ошибки - 0
fread(&BMFileHeader, sizeof(BMFileHeader),1,f);//считали заголовок
if (BMFileHeader.Type !=0x4D42)//проверили - точно ли формат .bmp
{
fclose(f);
return 0;
}
fread(&BMInfoHeader, sizeof(BMInfoHeader),1,f); //считали информацию об изображении
this->imageinfo();//вывели информацию
fseek(f, BMFileHeader.OffsetBits, SEEK_SET); //переместили указатель в нужное место OffsetBits = 54
Rgbtriple=new RGBTRIPLE*[BMInfoHeader.Height];
for (int i=0;i<BMInfoHeader.Height;i++)
Rgbtriple[i]=new RGBTRIPLE[BMInfoHeader.Width];
///*
for (int i=0;i<BMInfoHeader.Height;i++)//побайтово
for (int j=0;j<BMInfoHeader.Width;j++)
{
fread(&(Rgbtriple[i][j].Red),1,1,f);
fread(&(Rgbtriple[i][j].Green),1,1,f);
fread(&(Rgbtriple[i][j].Blue),1,1,f);
}
//*/
/*
for (int i = 0; i < BMInfoHeader.Width; i++)//построчно
{
fread(Rgbtriple[i], sizeof(RGBTRIPLE), BMInfoHeader.Width, f);
}
*/
if(Rgbtriple) cout<<"Изображение успешно загружено!"<<endl;
else return 0;
fclose(f);
return 1;
}
void Image::imageinfo()
{
BITMAPINFOHEADER *bmp = &BMInfoHeader;
cout<<"Число байтов необходимое для структуры: "<<bmp->Size<<endl;
cout<<"Ширина: "<<bmp->Width<<endl;
cout<<"Высота: "<<bmp->Height<<endl;
cout<<"Число плоскостей целевого устройства: "<<bmp->Planes<<endl;
cout<<"Глубина цвета:"<<bmp->BitCount<<endl;
cout<<"Тип сжатия: "<<bmp->Compression<<endl;
cout<<"Размер изображения в байтах: "<<bmp->SizeImage<<endl;
cout<<"Разрешающая способность по горизонтали: "<<bmp->XPelsPerMeter<<endl;
cout<<"Разрешающая способность по вертикали: "<<bmp->YPelsPerMeter<<endl;
cout<<"Число индексов используемых цветов: "<<bmp->ColorUsed<<endl;
cout<<"Число необходимых цветов: "<<bmp->ColorImportant<<endl;
return;
}
void Image::writeimage(char *fileName)
{
FILE *f;
fopen_s(&f,fileName,"wb");
if (f==NULL)
{
cout<<"\n\nОшибочка!\n"<<endl;
return;
}
fwrite(&BMFileHeader, sizeof(BMFileHeader),1,f);//40
fwrite(&BMInfoHeader, sizeof(BMInfoHeader),1,f);//14
///*
for (int i=0;i<BMInfoHeader.Height;i++)//побайтово
for (int j=0;j<BMInfoHeader.Width;j++)
{
fwrite(&(Rgbtriple[i][j].Red),1,1,f);
fwrite(&(Rgbtriple[i][j].Green),1,1,f);
fwrite(&(Rgbtriple[i][j].Blue),1,1,f);
}
//*/
/*
for (int i = 0; i < BMInfoHeader.Width; i++)//построчно
{
fwrite(Rgbtriple[i], sizeof(RGBTRIPLE), BMInfoHeader.Width, f);
}
*/
fclose(f);
return;
}
int main ()
{
setlocale(LC_ALL,"RUS");
cout<<"Открыли исходное изображение: "<<endl;
Image img;
img.loadimage("sails.bmp");
img.writeimage("out.bmp");
system("PAUSE");
return 0;
}
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question