Jump to content
  • Advertisement
Sign in to follow this  

Really weird error compressing and saving data (c++)

This topic is 3608 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Sorry but this is going to be kinda long... So I'm making an application that takes a bitmap and compresses it into a .map file for one of my games. The map data basically consists only of walkable and non walkable area (which is represented by black and white in the bitmap). So I load in a black and white bitmap (which is still 24bpp by the way) and check if tiles of a certain area are white or black, then I bitwise 8 bool values into one byte. I keep going untill the entire thing is encoded. I'm starting with really tiny maps: 128 x 104 pixels.(the game is for cell phones) and each tile is 8x8 (16 tiles across and 13 down). I start with a bitmap thats 39kb and the result is a .map file that is 28 bytes. All of this worked fine untill I decompressed the data on my cell phone emulator and got unexpected results. I searched for the problem for ages but I didn't find it until I opened my .map files in a hex editor (admittedly I'm not great with hex but I figured It might help somehow). For some reason I find that the name of the file is encoded in the map data. For instance for TestMap3.map (made from TestMap3.bmp) this is the hex:
00000000:10 0d 00 00 0c 00 00 00 ff ff ff ff 54 65 73 74  -> ........ÿÿÿÿTest
00000010:4d 61 70 33 2e 62 6d 70 00 00 00 00              ->Map3.bmp....    

Since the file is only just big enough to store the map data, of course it must be obstructed by the name. I can't figure out for the life of me how the name got in my data. All my compression algorithm does is pack 8 bools into a byte depending on whether the tiles are black or white... By the way the file above is made from a bitmap that's totally black, so I expected something to the effect of: 00 00 00 00 00 00... ect. So heres my code. Its rushed and its really nothing fancy... All the cout<< statements are to check values to find errors.
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int* GetBMPData(string,unsigned char**);
int ShrinkData(unsigned char*, int, int, unsigned char**);
void createMap(string, unsigned char* shrunkData, int);
const string FILE_NAME="TestMap3";
const int TILE_DEMENSIONS = 8;
const int WIDTH=0;
const int HEIGHT=1;
int numbytes;

int main()
    unsigned char* data;
    unsigned char* compressedData;
    int* demensions = GetBMPData(FILE_NAME.data(), &data);
    int shrankSize=ShrinkData(data, demensions[WIDTH], demensions[HEIGHT], &compressedData);
    createMap(FILE_NAME, compressedData, shrankSize);

int* GetBMPData(string bmpFileName, unsigned char** data)
    unsigned char offset[4]; //stores the offset to the RGB data
    unsigned char width[4];  //stores the width of the image
    unsigned char height[4]; //stores the height of the image
    ifstream bitstream(bmpFileName.data()); //opens the file passed into the function
    bitstream.seekg(10); //seeks to the offset vale
    bitstream.get((char*)offset, 4); 
    bitstream.seekg(18); //seek to the width
    bitstream.seekg(22); //seek to the height
    numbytes= (*((int*)width)) * (*((int*)height)) * 3; //numbytes equals the width times the height times three (the thre RGB compotents of a pixel) gotta love c++ right?
                 delete (*data);//(this is supposed to prevent memory leaks)
    *data=(unsigned char*) new char[numbytes]; //data equals a new array which is just the right size
    bitstream.seekg(*offset); //seek to the RGB data
    bitstream.get((char*)(*data), numbytes);
    bitstream.close(); //close the stream... best to be tidy right?
    cout<<"Offset: "<<*((int*)offset)<<"\nWidth:  "<<*((int*)width)<<"\nHeight: " <<*((int*)height)<<"\n"; //check the values just in case
    int* returnVal = new int[2]; // return array for the width and height
    returnVal[WIDTH]=*((int*)width); //put width into first slot 
    returnVal[HEIGHT]=*((int*)height); //and height into second
    return returnVal;

int ShrinkData(unsigned char* data, int width, int height, unsigned char** shrunk)
     int numOfBlack=0;
     int numOfWhite=0;
     int numMapXTiles = width/TILE_DEMENSIONS;
     int numMapYTiles = height/TILE_DEMENSIONS;
     int eightcount=0;
     int shrunkSize=((numMapXTiles*numMapYTiles)/8) + 2;
     *shrunk = new unsigned char[shrunkSize];
     int offset=2; //offsets the firs two initial values

     for(int i=0; i<numMapYTiles; i++)
             for(int j=0; j<numMapXTiles; j++)
                     int bitPlace= eightcount%8; //this variable is how many places I shift the bits for compression
                     int dataOffset=(i*numMapXTiles*TILE_DEMENSIONS*TILE_DEMENSIONS*3) + (j*TILE_DEMENSIONS*3);
                     unsigned char* shrunkByte=((*shrunk)+(eightcount/8)+ offset);
                     unsigned char bitWiser;
                     unsigned char tileColor=*(data+dataOffset);
                     if( tileColor == 255)
                     else if( tileColor == 0)
                         cout<<"Fatal Error: "<<"\n";
                     //cout<<(i*16)+j<<": "<<(int)tileColor<<"\n";
                     //cout<<(i*16)+j<<": "<<(i*numMapXTiles*TILE_DEMENSIONS*TILE_DEMENSIONS*3) +(j*TILE_DEMENSIONS*3)<<"\n";
                     *shrunkByte=(*shrunkByte) | bitWiser;

     cout<<"Number of white tiles: "<<numOfWhite<<"\nNumber of black tiles: "<<numOfBlack;
//Note the white and black values are correct here but not after I decompress
     return shrunkSize;

void createMap(string fileName, unsigned char* shrankData, int shrankSize)
     ofstream mapFile(fileName.data(), ios::binary);
     mapFile.write((const char*)shrankData,shrankSize);

Sorry if thats hard to understand. Like I said its rushed. It was my goal to make the entire map system in one day. I thought it'd be simple enough. I did loads of debugging and cout-ing and I'm certain that all the data is correct when its loaded. The numOfBlack and numOfWhite variables are always right so I figure the compression is working well. For some reason though the .map file only contains the bitmap file name and a bit of useless data. In order for the code to work a white and black bitmap (24bpp) must be in the same path. Best to make it 128x104 if you run it yourself. I'm not sure how flexible it is. I should also tell you that when I used more white tiles (int the example near the top there were 0 white tiles) the name of file begins to get messed up in the hex file. For instance TestMap1 used half white tiles and half black and here's the hex:
00000000:10 0d 00 00 0d 01 00 00 ff ff ff ff 55 65 73 74    ........ÿÿÿÿUest
00000010:4d 61 70 31 2f 63 6d 70 01 01 00 00                Map1/cmp....

if anyone could help me with this I would greatly appreciate it. I'm really eager to get on with development. I'll elaborate on any part of the code that doesn't make sense to anyone. [Edited by - ForeverNoobie on December 26, 2008 6:38:40 PM]

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!