c++ppm

PPM conversion char to int grants negative numbers


My task was to convert chars from PPM picture to int array, and later do other transformations on that array. I got formula, which supposed to convert 3 chars from PPM file (Red, Green and Blue in that order in file) to one int variable

int main(){
  ifstream obraz1;
  obraz1.open("start_1.ppm", ios::in);
  int x,y,colors;
  char proba[10000];
  string firstline; //P6

  getline(obraz1,firstline); //p6 scan
  //
  string line;
  getline(obraz1,line);
  sscanf(line.c_str(),"%d %d\n",&x,&y);
  getline(obraz1,line);
  sscanf(line.c_str(),"%d\n",&colors);

  int lenghtwithoutheader=obraz1.tellg();

  cout<<firstline<<" "<<endl;
  cout <<x<<" "<<y<<" "<<" "<<colors<<endl;

/////////////////LOAD////////////////////////
  int length;

  obraz1.seekg(0, std::ios::end); 
  length = obraz1.tellg();           // report location (this is the length)
  obraz1.seekg(lenghtwithoutheader, ios::beg);    
  char* buffor;
  cout<<"full pic: "<<length<<"pic without head : "<<lenghtwithoutheader<<endl;
  buffor = new char[length-lenghtwithoutheader];
  obraz1.read(buffor,length-lenghtwithoutheader);


   int *tabobraz=new int[(length-lenghtwithoutheader)/3];

  for(int i=0;i<length-lenghtwithoutheader;i=i+3){
    tabobraz[i]=(buffor[i]*(256*256))+(buffor[i+1]*256)+buffor[i+2];
    cout<<"to int "<<(int)buffor[i]<<" "<<(int)buffor[i+1]<<" "<<(int)buffor[i+2]<<" "<<endl;
    cout<<i<<" "<<buffor[i]<<" "<<buffor[i+1]<<" "<<buffor[i+2]<<" "<<endl;


  }



  return 0;
}

Somehow, i ended up with having negative numbers ( which is impossible for pictures):

to int 112 -72 -18
2247 p Ş ţ

My first thought is that maybe somehow i overflow int and it came back to negative numbers, but its impossible, maximum number of bytes that i can use with that numbers is 16-20 bytes from 32 of int. I tested it on diffrent system and hardware, so i dont think this is that matter. How can i make it work?


Solution

  • The problem is that char is signed on your implementation (the signedness of char is implementation-specific).

    Use an unsigned buffer and cast when you read:

    unsigned char* buffor = new unsigned char[length - lenghtwithoutheader];
    obraz1.read(reinterpret_cast<char*>(buffor), length - lenghtwithoutheader);