Quick question about std::map, objects as values.
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
converter.h
converter.cpp
imagelist.cpp
main.cpp
I hope everything comes out properly. I was editing it at 1280*1024, in case something appear out of synch.
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.
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
Popular Topics
Advertisement