E
E
Evgeny Trofimov2016-05-25 23:57:30
Programming
Evgeny Trofimov, 2016-05-25 23:57:30

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.
632a6d88b2e84dfead854bf4098b4fc8.bmpe35d1eee324944f5bc08846a86e165d8.bmp6ae74d3a142d436db87be5971daa8f9c.pngd9ec27f7e11f404788af5dd89ac56a62.png
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

1 answer(s)
A
Alexey, 2016-05-26
@deadrime

You don't have indexed color bmp for an hour?
Judging by how the beginning of the file looks like, there is something very similar to a palette.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question