Quick question about std::map, objects as values.

Started by
13 comments, last by Mawr 19 years, 6 months ago
You're welcome. Keep me posted.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Advertisement
Yaaarrrrgh. Well, for the last few hours or so, I've rebuilt my project with your advice in mind. Everything seems to be in working order, except the last bit of my image constructor. Keeps giving a segmentation fault when I exit the loop. If you want, I could post the entire class, and its associate, but I'd have to clean it up a bit.
Ok. Here's the code that I have. Each file includes comments, but if you need me to clarify, pm me, and I'll try my best. I'll be up for a few more hours tonight, but after that will be gone till next evening.


bitmap.cpp
#ifndef GUARD_BITMAP_CPP#define GUARD_BITMAP_CPP#include <fstream>#include <windows.h>#include <vector>#include <string> // Basic bitmap file, a bit too trusting, but works on files I create// Note: Does not work with images with dimensions not divisable by 4using namespace std;class Bitmap {public:    BITMAPFILEHEADER bmfh;  BITMAPINFOHEADER bmih;    vector<char> pixelData;  int width,height;  int bpp;      Bitmap()  {  };    Bitmap(string file)  {    loadBMP(file); //where everything gets done really  }      void loadBMP(string file)  {    //open file in binary    ifstream in(file.c_str(), ios::in | ios::binary);        //read in file headers    in.read((char*)&bmfh,sizeof(BITMAPFILEHEADER));    in.read((char*)&bmih,sizeof(BITMAPINFOHEADER));        //setup the final read in, and save appropriate information    width = bmih.biHeight;    height = bmih.biHeight;    bpp=bmih.biBitCount;    int size=bmfh.bfSize-bmfh.bfOffBits;           pixelData.resize(size);    unsigned char R,B;        //final read in of the actual pixel data    in.read(&pixelData[0],sizeof(unsigned char)*size);        //if height is positive, format read in was BGR instead of RGB, reverse it back    if(height>0)    {        for(int i=0;i<size;i+=3)      {        R=pixelData;        B=pixelData[i+2];        pixelData=B;        pixelData[i+2]=R;      }    }    }                                        };#endif



converter.h
//Only function inside of converter.cpp, but also contains a class, see converter.cpp#ifndef GUARD_CONVERTER_H#define GUARD_CONVERTER_H#include <string>#include <vector>void converter(std::vector<std::string> vc, std::string output);#endif


converter.cpp
/* This file is used to convert Bitmap files described in Bitmap.cpp into a globbed file   The converter first reads in the bitmaps specified by the vector<string> vc parameter.   Then, steps through the pixel data inside those bitmaps and finds every unique color,   stores that color into the BYTE3 data structure vector<BYTE3> clrTable, along with a number   starting at 1 (BYTE3.p), incrementing it after every found color.      Then the converter opens up the outputfile specified by the string output parameter.   Stepping through clrTable, it writes the data stored within in this format.      prgb   following immediatly is a 0, signaling that this is the end of the color table.      The converter then steps through stores Bitmaps again, writes the size of the name of the    file specified by the vector<string> vc parameter, then writes the actual name, followed   by the width, then height. Now looking at the pixelData that is inside the current bitmap,   it reads off the rgb values, and comparing it the clrTable built earlier finds the matching   color within, then writing to the file the p value of that color.      NOTE: The color table contains the unique colors from ALL the files specified. I realize that    using the unsigned char as the unique identifier for each color means I cannot hold more then   255 colors (0 as stop signal).  This was meant entirely as an glob image file for any basic   2d game I might make.*/   #ifndef GUARD_CONVERTER_CPP#define GUARD_CONVERTER_CPP#include <vector>#include <string>#include <fstream>#include "bitmap.cpp"using namespace std;//The class that stores the unique colors found within the bitmapsclass BYTE3  {    public:    unsigned char r,g,b,p;    BYTE3(unsigned char R, unsigned char G, unsigned char B, unsigned char P)    : r(R),g(G),b(B),p(P)    { // Look intializer list! :)    }};                    void converter(vector<string> vc, string output)  // the meat of this cpp file{  vector<Bitmap> Data;           //declarations  vector<BYTE3> clrTable;    int vsize = vc.size();  unsigned char clrNum=1;  bool bUnique=true;    for(int i=0;i<vsize;i++)  //Hopefully load in the Bitmap files  {    Bitmap bmp=Bitmap(vc);    Data.push_back(bmp);  }          for(int i=0;i<vsize;i++) //for each bitmap, look for unique colors  {    int size=Data.width*Data.height*Data.bpp/8;    for(int j=0;j<size;j+=3)    {      unsigned char R = Data.pixelData[j];      unsigned char G = Data.pixelData[j+1];      unsigned char B = Data.pixelData[j+2];                bUnique=true;      int tableSize=clrTable.size();                      for(int k=0;(k<tableSize)&&(bUnique);++k) //compare it to colors already found      {                        if((clrTable[k].r == R) &&         (clrTable[k].g == G) &&         (clrTable[k].b == B))         {           bUnique=false; //NOT unique color          }      }            if(bUnique)      {        BYTE3 bt= BYTE3(R,G,B,clrNum); //Unique color found, storing the RGB value away        clrTable.push_back(bt);        //With a additional value clrNum (the p value)        ++clrNum;                      //Incrementing the p value      }    }                   }    ofstream out(output.c_str(), ios::out | ios::binary);  //Opening the output file  for(int k=0;k<clrTable.size();++k)                     //Writing the color transulation table  {     out.write((char*)&clrTable[k].p,sizeof(unsigned char));    out.write((char*)&clrTable[k].r,sizeof(unsigned char));    out.write((char*)&clrTable[k].g,sizeof(unsigned char));    out.write((char*)&clrTable[k].b,sizeof(unsigned char));  }  unsigned char zero=0;  out.write((char*)&zero,sizeof(unsigned char));           //writing the end signal    for(int i=0;i<vsize;++i)                          //writing the header for the particular file  {    int size=Data.pixelData.size();    int strsize = vc.size();    out.write((char*)&strsize,sizeof(int));    out.write((char*)&vc,sizeof(char)*strsize);    out.write((char*)&Data.width,sizeof(int));    out.write((char*)&Data.height,sizeof(int));        for(int j=0;j<size;j+=3) //writing the pixel data from the file in interperated form    {      unsigned char R = Data.pixelData[j];      unsigned char G = Data.pixelData[j+1];      unsigned char B = Data.pixelData[j+2];                      bUnique=true;      int tableSize=clrTable.size();                      for(int k=0;(k<tableSize);++k)      {        if((clrTable[k].r == R) &&           (clrTable[k].g == G) &&           (clrTable[k].b == B))        {          out.write((char*)&clrTable[k].p,sizeof(unsigned char));        }      }    }  }    out.close();                        //done  return;    }    #endif 



imagelist.cpp
/*  The reverse of the converter.cpp, to return the stored data from its interperated form back into  a useable state.    Starts with the constructor of imagelist.  Opens up the file specified and tries to produce  image data types out of it.     First, it recreates the color table left by the converter function.  It reads it in as follows.    prgb    Untill it reads in the stop signal (p=0).  Once done, it passes off the file handle, and the   color table (clrTable) to the contructor for image(ifsteam &in, const vector<BYTE3> &clrTable).  BYTE3 is exactly the same as it was in converter.cpp.    Once inside the image constructor, it reads in the header information of that file.    (int)namesize  (char*Namesize)Name   (int)width  (int)height    Once it has this information, it sets up the vectors containing the final location of the data  and the temporary storage of the data.  The temporary storage is resized to width*height, while the   final storage is resized to width*height*3.    The temporary storage is filled, then the loop to uncompress the data back to the RGB format begins.    It steps through the values inside the temporary storage, and compares it to the BYTE3.p value  inside the clrTable. Once found, stores the RGB value from the current BYTE3 into the final  storage.  Repeats until all of temporary storage is taken care of. Once done, returns back to  the imagelist constructor so the next image can be built.    NOTE:  The interperating from the temporary storage to the final storage loop is where it produces  a segmentation fault.  As far as I can tell, the fault is produced when the loop is exiting. I've   tried ending the loop earlier (by setting the size to size-10, or such like it), but it still produces  the error on exit.*/#ifndef GUARD_IMAGELIST_CPP#define GUARD_IMAGELIST_CPP#include <vector>#include <string>#include <map>#include <gl/gl.h>#include <fstream>#include <iostream>using namespace std;class BYTE3  //same as before in converter.cpp{    public:    unsigned char r,g,b,p;    BYTE3(unsigned char R, unsigned char G, unsigned char B, unsigned char P)    : r(R),g(G),b(B),p(P)    {    }};   class image  //The actual container for the image data{  public:  vector<unsigned char> data; //final storage of the image data  int namesize;  string name;  int width,height;    image(ifstream &in, const vector<BYTE3> &clrTable)  {    //Reading in the header information        in.read((char*)&namesize,sizeof(namesize));    in.read((char*)&name,sizeof(char)*namesize);    in.read((char*)&width,sizeof(int));    in.read((char*)&height,sizeof(int));        //setup the sizes of the data in the color table, compressed data, and uncompressed data    int tablesize=clrTable.size();    int size=width*height;    bool FOUND=false;    data.resize(size*3);    vector<unsigned char> tempData;    tempData.resize(size);        //read the compressed data in    in.read((char*)&tempData[0],size);        //now interperate it from compressed to uncompressed    int j=0;    for(int i=0;i<=size;j+=3,++i) //setting the ending condition to (i<=size-10) doesn't seem to help    {      for(int k=0;(k<tablesize)&&(!FOUND);++k)      {        if(tempData==clrTable[k].p)        {          FOUND=true;  //set FOUND to true so it continues          data[j]=clrTable[k].r;  //storing the color table information into the final storage          data[j+1]=clrTable[k].g;          data[j+2]=clrTable[k].b;        }      }      FOUND=false;    }    //crashes before here    return;  }    image()  {  }  };class imagelist{  public:  map<string,image> imgList;                     //the map of the images for future look up    imagelist(string filename)  {        ifstream in;    in.open(filename.c_str());                   //opening the file, and declarations        bool FOUNDEND=false;    vector<BYTE3> clrTable;    unsigned char R=0;    unsigned char G=0;    unsigned char B=0;    unsigned char P=0;            for(;(!FOUNDEND);)                           //Reading and recreating color table    {      in.read((char*)&P,sizeof(unsigned char));                  if(P==0)                                   //P equaling 0 flags the end of the color table      {        FOUNDEND=true;       }      else       {        in.read((char*)&R,sizeof(unsigned char));        in.read((char*)&G,sizeof(unsigned char));        in.read((char*)&B,sizeof(unsigned char));                clrTable.push_back(BYTE3(R,G,B,P));      }      }        while(!(in.eof()))    {      image img = image(in,clrTable);            //Pass the file handle and the color table      imgList[img.name]=img;                        }    }      };#endif


main.cpp
#include "converter.h"#include "imagelist.cpp"#include <vector>using namespace std;int main(){  vector<string> vc;  vc.push_back("bmp1.bmp");  vc.push_back("bmp2.bmp");    converter(vc,"outputfile");    imagelist bmps =imagelist("outputfile");  return 0;}


I hope everything comes out properly. I was editing it at 1280*1024, in case something appear out of synch.
It's running all right here (after a few minor fixes)...
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
I'm an idiot. I needed to make a assignment constructor for my image class, because I needed to copy the data explicitly. Fruny, you outlined this in one of your posts on how to do this and why, so I feel all the more of a fool. Bleh, atleast it works now, time to start adding some functionality to my imagelist class to make it more then a wrapper to map<string, image>. I sincerely thank you for all your help.

This topic is closed to new replies.

Advertisement