Manualne wczytywanie i zapisywanie bmp

0

Witam!

Piszę programik do wczytywania pliku bmp bez użycia zewnętrznych bibliotek i do (jak na razie tylko) zapisu do nowego pliku.
Wszystko ładnie się wczytuje i zapisuje, nawet dla plików ważących ~30MB ale ... problem polega na tym, że mimo tego ze bitmapa jest 24bitowa to program podczas wczytywania kolorów "bardziej skomplikowanych"(które zostały namalowane np pędzlem w paincie z win7) odczytuje je błędnie, jako czarny.
Jeśli program napotka tego typu 'błąd' to już do końca wczytywania ciągnie ten błąd(nie czyta dalszych pikseli poprawnie tylko jako czarne).
'Odkryłem', że takim problematycznym kolorem jest np żółty:(R=243;G=193;B=26;). Strzelam, że jest więcej tego typu kolorów, które z niewiadomych mi przyczyn źle się wczytują. Dodam, że program nie wyrzuca żadnych wyjątków(exceptions). Jest na to jakaś rada ? Coś istotnego pominąłem? Bardzo liczę na jakąkolwiek pomoc.

Pewien przykład:
obrazek, który wczytuje:
user image
obrazek,który się zapisał:
user image

Kod całego programu:

//#ifdef WIN32
#include "stdafx.h"
#include <windows.h>
//#endif



#ifndef WIN32
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned int UNINT32;
typedef unsigned char BYTE;
typedef  long long DWORD64;/**/
#endif

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <stdint.h>



using namespace std;


class bmpfile_magic {
public:
   WORD bfType;
};

class bmpfile_header {
public:
   DWORD bfSize;
   WORD bfReserved1;
   WORD bfReserved2;
   DWORD bfOffBits;
};


class HeaderDIB{
public:
   DWORD   biSize;   //Wielkość nagłówka informacyjnego. Długość stąd do końca nagłówka – 40, czasem mniej
   DWORD   biWidth;   //Szerokość obrazu w pikselach
   DWORD   biHeight;   //Wysokość obrazu w pikselach
   WORD   biPlanes;   //Liczba warstw kolorów, zwykle 1
   WORD   biBitCount;   //Liczba bitów na piksel
   DWORD   biCompression;   //Algorytm kompresji
   DWORD   biSizeImage;   //Rozmiar samego rysunku
   DWORD   biXPelsPerMeter;   //Rozdzielczość pozioma
   DWORD   biYPelsPerMeter;   //Rozdzielczość pionowa
   DWORD   biClrUsed;   //Liczba kolorów w palecie
   BYTE   biClrImportant;   //Liczba ważnych kolorów w palecie (gdy 0 to wszystkie są ważne); pole to stosuje się przy animacji bitmap poprzez rotację kolorów. Oznacza od którego koloru paleta ma być podmieniana.
   BYTE   biClrRotation;   //flaga sygnalizująca czy ma następować rotacja palety (domyślnie 0-brak rotacji). Jeśli flaga jest ustawiona na 1 następuje podmiana palety.
   WORD   biReserved;

};

class pixel{
public:
   BYTE  B,G,R;

};

class RGBQuad { 
public:
   BYTE rgbBlue;
   BYTE rgbGreen;
   BYTE rgbRed;
   BYTE rgbReserved;
};

const short BITMAP_MAGIC_NUMBER=19778;

void toString(pixel p){


   cout<<(int)p.R<<"\t"<<(int)p.G<<"\t"<<(int)p.B<<endl;
}


class Picture{

   pixel ** obraz;
   pixel ** nowy;

   bmpfile_header naglowek;
   HeaderDIB NaglowekDIB;
   int width,height;
   bmpfile_magic bmpmag;
  
public:
   Picture(string nazwa){

      
      fstream plikIN;


      plikIN.open(nazwa.c_str(),std::ios::in);
      if( ! plikIN.is_open() ){
         cout<<"Blad otwarcia pliku: "<<nazwa.c_str()<<endl;
         exit(-1);
      }


      try{
         plikIN.read((reinterpret_cast<char*>(&bmpmag)),sizeof(bmpmag));      
      }
      catch (exception& e)
      {
         cout << "Standard exception: " << e.what() << endl;
      }



      if(bmpmag.bfType!=BITMAP_MAGIC_NUMBER)
      {
         cout<<"to nie jest bmp, exiting!";
         getchar();
         exit(-1);

      }


      try{
         plikIN.read((reinterpret_cast<char*>(&naglowek)),sizeof(naglowek));
      }
      catch (exception& e)
      {
         cout << "Standard exception: " << e.what() << endl;
      }


      cout<<"Rozmiar pliku: "<<nazwa.c_str()<<" wynosi: "<<naglowek.bfSize<<endl;



      try{
         plikIN.read((reinterpret_cast<char*>(&NaglowekDIB)),sizeof(NaglowekDIB));      
      }
      catch (exception& e)
      {
         cout << "Standard exception: " << e.what() << endl;
      }


      width = NaglowekDIB.biWidth;
      height= NaglowekDIB.biHeight;

      cout<<"Wymiary obrazka: "<<width<<" x "<<height<<endl;
      cout<<"Liczba bitow na pixel: "<<NaglowekDIB.biBitCount<<endl;

      cout<<"naglowek.bfOffBits: "<<naglowek.bfOffBits<<endl;


      try{
         plikIN.seekg(naglowek.bfOffBits,ios::beg);
      }
      catch (exception& e)
      {
         cout << "Standard exception: " << e.what() << endl;
      }
     


      if (NaglowekDIB.biBitCount != 24)
      {
         //jest jeszcze paleta kolorow<--do odczytania/ominiecia
         //load the palette for 8 bits per pixel
         int   numColours=1<<NaglowekDIB.biBitCount;
         RGBQuad *colours;

         if(NaglowekDIB.biBitCount==8) {
            colours=new RGBQuad[numColours];
            plikIN.read( reinterpret_cast<char*>(&colours),sizeof(RGBQuad)*numColours);
         }

      } 
      else
      {

         try{
            obraz = new pixel*[height];
            for(int i=0 ; i < height ; i++)
               obraz[i] = new pixel  [width];
         }
         catch (bad_alloc e)
         {
            cout << "Standard exception: " << e.what() << endl;
         }


         //przesuniecie do offsetu danych
         //plik.seekg(naglowek.bfOffBits,ios::beg);

         


         cout<<"\tR\tG\tB"<<endl;


         for(int i=0 ; i < height ; i++){

            for ( int j=0 ; j < width ; j++)
            {


               pixel p;
               p.G=p.B=p.R=0;

               try{
                  plikIN.read(  reinterpret_cast<char*>(&p)  ,sizeof(pixel)   );
               }
               catch (exception& e)
               {
                  cout << "Standard exception: " << e.what() << endl;
               }


               if(p.B==0 && p.G==0 && p.R==0)
               {
                                                  //(w tym miejscu pojawia blad!)
                                                 //jesli tu wejdzie to od tego miejsca do konca wczytywania kazdy pixel jest odczytywany jako czarny: r=0  b =0  g=0
                                                  //jesli napotka kolory np ten nizej to dalej juz zle wczytuje
                  //p.B=26;
                  //p.G=193;
                  //p.R=243;

               }

               obraz[i][j]=p;   

               if (  (width-1) == j)
               {
                  BYTE a=0;

                    //uzupelnienie wiersza danych do wielokrotnosci 4 zerami
                  for (int k=0 ; k<width%4;k++)   {      
                     try{
                        plikIN.read(  reinterpret_cast<char*>(&a)  ,sizeof(a)   );
                     }
                     catch (exception& e)
                     {
                        cout << "Standard exception: " << e.what() << endl;
                     }
                  }
               }
               

            }

         }

         
      }
      try{
         plikIN.close();
      }
      catch (exception& e)
      {
         cout << "Standard exception: " << e.what() << endl;
      }

   }

   void obroc(){
      //obrot obrazu o 90st  lewo;

      /*
      //rezerwacja pamieci dla nowego pliku:
      nowy = new pixel*[width];
      for(int i=0 ; i < width ; i++)
      nowy[i] = new pixel  [height];
      //po rezerwacji:



      //obracanki cacanka...
      for(int i=0 ; i < height ; i++){

      for(int j=0; j < width; j++){

      nowy[j][i] = obraz[i][width-j-1];

      }
      }
      */

      nowy = obraz;




   }

   void save(string nazwa){

      fstream plikOUT;

      plikOUT.open(nazwa.c_str(), ios::trunc|ios::out);
      if( ! plikOUT.is_open() ){
         cout<<"Blad otwarcia pliku: "<<nazwa.c_str()<<endl;
         //throw new exception("Error: opening file");

      }


      try
      {
         plikOUT.write((reinterpret_cast<char*>(&bmpmag)),sizeof(bmpmag));      
      }
      catch (exception& e)
      {
         cout << "Standard exception: " << e.what() << endl;
      }




      try{
         plikOUT.write((reinterpret_cast<char*>(&naglowek)),sizeof(naglowek));
      }
      catch (exception& e)
      {
         cout << "Standard exception: " << e.what() << endl;
      }

     
      try{
         plikOUT.write((reinterpret_cast<char*>(&NaglowekDIB)),sizeof(NaglowekDIB));      
      }
      catch (exception& e)
      {
         cout << "Standard exception: " << e.what() << endl;
      }



      for (int i=0 ; i< height ;i++)
      {
         try{
            plikOUT.write((reinterpret_cast<char*>(nowy[i])),width*sizeof(pixel));
         }
         catch (exception& e)
         {
            cout << "Standard exception: " << e.what() << endl;
         }

         BYTE a=0;

         for (int k=0 ; k<width%4;k++)   {            
            try{
               plikOUT.write(  reinterpret_cast<char*>(&a)  ,sizeof(a)   );
            }
            catch (exception& e)
            {
               cout << "Standard exception: " << e.what() << endl;
            }
         }

      }


      try{
         plikOUT.close();
      }
      catch (exception& e)
      {
         cout << "Standard exception: " << e.what() << endl;
      }
      /**/
   }
};



int /*_t*/main(/*int argc*/)
{
   Picture *MyPicture;
   string name = "plik.bmp";
   //   string name = "24bits.bmp";
   //   string name = "256col.bmp";
   //   string name = "16col.bmp";
   //   string name = "monochr.bmp";

   string obr = "rotated_.bmp";
   try{
      MyPicture=new Picture( name );
      MyPicture->obroc();
      MyPicture->save(obr);

   }catch( exception e ){
      cout<<"Exc: "<<e.what()<<endl;
      getchar();
   }






   return 0;
}

i w ładniejszej wersji: http://wklej.org/id/855184/
Dzięki za każdą pomoc!

0

problem rozwiązany, problemem był: Windows (na ubuntu działa w porządku)

1 użytkowników online, w tym zalogowanych: 0, gości: 1