deadrime
@deadrime
Fullstack web developer

Почему не получается прочитать/записать bmp изображение?

Пытаюсь написать программу для работы с .bmp файлами, структуру брал с сайта майкрософта, она точно правильная)
Считать и записать InfoHeader и FileHeader у меня получается - все 1 в 1, а вот дальше - проблема.
Нужно считать данные RGB в динамический массив, и видимо я что-то делаю не так... Т.е я пробовал кучей способов, но работают(более или менее) пока только 2 - построчный(он почему-то только с lena.bmp работает, нравится ему девушка наверное..) и побайтовый. Но в результате размер выходного файла получается больше чем входного(почти в 3 раза), да и цвета все "ломаются" + куча шума.
632a6d88b2e84dfead854bf4098b4fc8.bmpe35d1eee324944f5bc08846a86e165d8.bmp6ae74d3a142d436db87be5971daa8f9c.pngd9ec27f7e11f404788af5dd89ac56a62.png

Т.е он почему-то пишет что-то лишнее, и в начале явно что-то не так...
Я знаю что я вообще не в том порядке считываю - надо в BGR, но я же не изменяю ничего, просто считываю а потом записываю.

Вот в общем код, помогите пожалуйста, по-любому какая-то очевидная ошибка..
#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;
}
  • Вопрос задан
  • 1776 просмотров
Решения вопроса 1
alsopub
@alsopub
У вас часом не indexed color bmp?
Судя по тому как выглядит начало файла - там что-то очень похожее на палитру.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы