I have the following base code for a program I am writing that simply loads a bitmap from one location and transmits it to another (with limited compatibility). The problem is that when run it appears to go into an infinite loop. Any ideas why? (hoping its a stupid error and not something major) here is the code: Code: #include <fstream> using namespace std; class Bitmap { private: unsigned char ***ERROR3;//the error value //Some raw variables in the file data: unsigned char *HEADERS; unsigned char FTYPE[2];//should be MP int size; int start; int DIBsize; int width; int height; short BPP; int COMPMETHOD;//should be zero or we could likely have a major problem! //HERES THE IMAGE!!!!!! unsigned char ***IMAGE; //AND ONE WITH LESS MASSIVE RANGE, UPDATED BY A CALL TO UPDATE() int ***PICTURE; public: void UPDATE(); unsigned char ***OPEN(char *fname);//BETTER NAME WOULD BE READ... OH WELL! void CLOSE(char *fname);//BETTER NAME WOULD BE SAVE... OH WELL! }; void Bitmap::CLOSE(char *fname) { fstream FILE; FILE.open(fname, ios_base::in|ios_base::out|ios_base::binary); FILE<<HEADERS<<IMAGE; FILE.close(); } unsigned char ***Bitmap::OPEN(char *fname)//returns a 3Dimensional array for the image in the form of [h][w][rgb(a)] { unsigned char ***ERROR3=new unsigned char**[3]; for (int i=0; i<3; i++) { ERROR3[i]=new unsigned char*[3]; for (int ii=0; ii<3; ii++) { ERROR3[ii][i]=new unsigned char[3]; } } for (int i=0; i<3; i++) { for (int ii=0; ii<3; ii++) { for (int iii=0; iii<3; iii++) { ERROR3[i][ii][iii]=40; } } } fstream FILE; char Byte; int asize = 1; unsigned char *ARRAY = new unsigned char[asize]; FILE.open(fname, ios_base::in|ios_base::out|ios_base::binary); while (!(FILE.eof())) { FILE.read(&Byte, 1); unsigned char *TEMP = new unsigned char[asize]; TEMP = ARRAY; asize++; ARRAY = new unsigned char[asize]; for (int i = 0; i<asize-1; i++) { ARRAY[i] = TEMP[i]; } ARRAY[asize-1] = Byte; }//NOW ARRAY IS FULL OF THE CONTENTS OF FILE IN BINARY (IN ORDER) int loc = 0; unsigned char RFTYPE[2] = {ARRAY[loc], ARRAY[loc+1]};//Get the Magic Number (Should likely be MB[it is reversed]) FTYPE[0]=RFTYPE[0]; FTYPE[1]=RFTYPE[1]; loc += 2; unsigned char FSIZE[4] = {ARRAY[loc], ARRAY[loc+1], ARRAY[loc+2], ARRAY[loc+3]};//Get the Size in bytes, in bytes size = 0; size |= (FSIZE[3]<<24); size |= (FSIZE[2]<<16); size |= (FSIZE[1]<<8); size |= (FSIZE[0]);//size is now size of file in bytes! loc += 8;//includes the 4 reserved bytes of data if (loc > size) { FILE.close(); return ERROR3; }//now loc can be checked unsigned char FSTART[4] = {ARRAY[loc], ARRAY[loc+1], ARRAY[loc+2], ARRAY[loc+3]};//Get the start of image data, in bytes start = 0; start |= (FSIZE[3]<<24); start |= (FSIZE[2]<<16); start |= (FSIZE[1]<<8); start |= (FSIZE[0]);//start is now the beginning of image data loc += 4;//go to DIB header unsigned char FDIBSIZE[4] = {ARRAY[loc], ARRAY[loc+1], ARRAY[loc+2], ARRAY[loc+3]};//Get the length of the DIB header DIBsize = 0; DIBsize |= (FDIBSIZE[3]<<24); DIBsize |= (FDIBSIZE[2]<<16); DIBsize |= (FDIBSIZE[1]<<8); DIBsize |= (FDIBSIZE[0]); loc += 4; unsigned char IWIDTH[4]; unsigned char IHEIGHT[4]; unsigned char BitsPerPixel[2]; unsigned char CMETHOD[4]; short val; switch (DIBsize) { case 40://it is BITMAP INFO HEADER we can use it IWIDTH[0] = ARRAY[loc]; IWIDTH[1] = ARRAY[loc+1]; IWIDTH[2] = ARRAY[loc+2]; IWIDTH[3] = ARRAY[loc+3];//Get the width of the image width = 0; width |= (IWIDTH[3]<<24); width |= (IWIDTH[2]<<16); width |= (IWIDTH[1]<<8); width |= (IWIDTH[0]); loc += 4; IHEIGHT[0] = ARRAY[loc]; IHEIGHT[1] = ARRAY[loc+1]; IHEIGHT[2] = ARRAY[loc+2]; IHEIGHT[3] = ARRAY[loc+3];//Get the height of the image height = 0; height |= (IHEIGHT[3]<<24); height |= (IHEIGHT[2]<<16); height |= (IHEIGHT[1]<<8); height |= (IHEIGHT[0]); loc += 6;//to account for plane numbers which, if not one, will cause an error so we don't need to check it BitsPerPixel[0] = ARRAY[loc]; BitsPerPixel[1] = ARRAY[loc+1]; BPP = 0; BPP |= (BitsPerPixel[1]<<8); BPP |= (BitsPerPixel[0]);//sets the BPP of the image loc += 2; CMETHOD[0] = ARRAY[loc]; CMETHOD[1] = ARRAY[loc+1]; CMETHOD[2] = ARRAY[loc+2]; CMETHOD[3] = ARRAY[loc+3]; COMPMETHOD = 0; COMPMETHOD |= (CMETHOD[3]<<24); COMPMETHOD |= (CMETHOD[2]<<16); COMPMETHOD |= (CMETHOD[1]<<8); COMPMETHOD |= (CMETHOD[0]);//set the method of compression loc += 20;//we are done with the important stuff, since Pixels per meter and palettes are not going to change our program break; case 12://it is BITMAP CORE HEADER we can use it IWIDTH[0] = ARRAY[loc]; IWIDTH[1] = ARRAY[loc+1]; IWIDTH[2] = 0; IWIDTH[3] = 0; val = 0; val |= (IWIDTH[1]<<8); val |= (IWIDTH[0]); width = (int)val; loc += 2; IHEIGHT[0] = ARRAY[loc]; IHEIGHT[1] = ARRAY[loc+1]; IHEIGHT[2] = ARRAY[loc+2]; IHEIGHT[3] = ARRAY[loc+3]; val = 0; val |= (IHEIGHT[1]<<8); val |= (IHEIGHT[0]); height = (int)val; loc += 4;//Also includes plane numbers which, if not one, will cause an error so we don't need to check it BitsPerPixel[0] = ARRAY[loc]; BitsPerPixel[1] = ARRAY[loc+1]; BPP = 0; BPP |= (BitsPerPixel[1]<<8); BPP |= (BitsPerPixel[0]);//sets the BPP of the image loc += 2; break; default: FILE.close(); return ERROR3; } HEADERS=new unsigned char[DIBsize+14]; for (int i=0; i<DIBsize+14; i++) { HEADERS[i]=ARRAY[i]; } loc = start; unsigned char ***ret=new unsigned char**[BPP/8]; for (int i=0; i<3; i++) { ret[i]=new unsigned char*[3]; for (int ii=0; ii<3; ii++) { ret[ii][i]=new unsigned char[3]; } } switch (BPP) { case 24://RGB for (int y=0; y<height; y++) { for (int x=0; x<width; x++) { for (int i=0; i<3; i++) { ret[y][x][i]=ARRAY[loc]; loc++; } } loc += 2; } FILE.close(); return ret; break; case 32://RGBA for (int y=0; y<height; y++) { for (int x=0; x<width; x++) { for (int i=0; i<4; i++) { ret[y][x][i]=ARRAY[loc]; loc++; } } } FILE.close(); return ret; break; default://32 is generally highest and anything lower than 24 divides by less than a byte, and I cannot access data that precisely without structs and tons of data FILE.close(); return ERROR3; } } void Bitmap::UPDATE() { unsigned char ***ret=new unsigned char**[BPP/8]; for (int i=0; i<3; i++) { ret[i]=new unsigned char*[3]; for (int ii=0; ii<3; ii++) { ret[ii][i]=new unsigned char[3]; } } for (int y=0; y<height; y++) { for (int x=0; x<width; x++) { for (int i=0; i<(BPP/8); i++) { ret[y][x][i]=IMAGE[y][x][i]; } } } PICTURE=(int***)ret; } int main() { Bitmap PIC; PIC.OPEN(".\\TESTPIC.bmp"); PIC.CLOSE(".\\TESTPIC2.bmp"); return 0; }
I was thinking of maybe converting the 3-dim arrays to one dimensional and creating an access function, but I can't figure out what that access function could be.
Sorry, I can't edit my posts. I got the single dimensional array, three dimensional access function working, but the program itself still doesn't work. My hypothesis is that fstream cannot open .bmp files. So I was thinking maybe some kind of conversion might work. Any ideas how I could do this?!?!
Can you share where the infinite loop is because you have too many loops posted in the code and without running the program it is tedious to understand.
That is the problem, I have no idea where the infinite loop may be happening, I could try adding more comments to the code and reposting, to see if that clears things up a bit.
Here is some updated code, which has fewer loops: Code: #include <fstream> using namespace std; template <typename T> T &AT(int x, int y, int z, T *in, int ty, int tz) { return in[(x*(tz*ty))+z+tz*y]; } class Bitmap { private: unsigned char *ERROR3;//the error value //Some raw variables in the file data: unsigned char *HEADERS; unsigned char FTYPE[2];//should be MP int size; int start; int DIBsize; int width; int height; short BPP; int COMPMETHOD;//should be zero or we could likely have a major problem! //HERES THE IMAGE!!!!!! unsigned char *IMAGE; //AND ONE WITH LESS MASSIVE RANGE, UPDATED BY A CALL TO UPDATE() int *PICTURE; public: void UPDATE(); unsigned char *OPEN(char *fname);//BETTER NAME WOULD BE READ... OH WELL! void CLOSE(char *fname);//BETTER NAME WOULD BE SAVE... OH WELL! }; void Bitmap::CLOSE(char *fname) { fstream FILE; FILE.open(fname, ios_base::in|ios_base::out|ios_base::binary); FILE<<HEADERS<<IMAGE; FILE.close(); } unsigned char *Bitmap::OPEN(char *fname)//returns a 3Dimensional array for the image in the form of "H""W""RGB(A)" { unsigned char *ERROR3={0}; fstream FILE; char Byte; int asize = 1; unsigned char *ARRAY = new unsigned char[asize]; FILE.open(fname, ios_base::in|ios_base::out|ios_base::binary); while (!(FILE.eof())) { FILE.read(&Byte, 1); unsigned char *TEMP = new unsigned char[asize]; TEMP = ARRAY; asize++; ARRAY = new unsigned char[asize]; for (int i = 0; i<asize-1; i++) { ARRAY[i] = TEMP[i]; } ARRAY[asize-1] = Byte; }//NOW ARRAY IS FULL OF THE CONTENTS OF FILE IN BINARY (IN ORDER) int loc = 0; unsigned char RFTYPE[2] = {ARRAY[loc], ARRAY[loc+1]};//Get the Magic Number (Should likely be MB[it is reversed]) FTYPE[0]=RFTYPE[0]; FTYPE[1]=RFTYPE[1]; loc += 2; unsigned char FSIZE[4] = {ARRAY[loc], ARRAY[loc+1], ARRAY[loc+2], ARRAY[loc+3]};//Get the Size in bytes, in bytes size = 0; size |= (FSIZE[3]<<24); size |= (FSIZE[2]<<16); size |= (FSIZE[1]<<8); size |= (FSIZE[0]);//size is now size of file in bytes! loc += 8;//includes the 4 reserved bytes of data if (loc > size) { FILE.close(); return ERROR3; }//now loc can be checked unsigned char FSTART[4] = {ARRAY[loc], ARRAY[loc+1], ARRAY[loc+2], ARRAY[loc+3]};//Get the start of image data, in bytes start = 0; start |= (FSIZE[3]<<24); start |= (FSIZE[2]<<16); start |= (FSIZE[1]<<8); start |= (FSIZE[0]);//start is now the beginning of image data loc += 4;//go to DIB header unsigned char FDIBSIZE[4] = {ARRAY[loc], ARRAY[loc+1], ARRAY[loc+2], ARRAY[loc+3]};//Get the length of the DIB header DIBsize = 0; DIBsize |= (FDIBSIZE[3]<<24); DIBsize |= (FDIBSIZE[2]<<16); DIBsize |= (FDIBSIZE[1]<<8); DIBsize |= (FDIBSIZE[0]); loc += 4; unsigned char IWIDTH[4]; unsigned char IHEIGHT[4]; unsigned char BitsPerPixel[2]; unsigned char CMETHOD[4]; short val; switch (DIBsize) { case 40://it is BITMAP INFO HEADER we can use it IWIDTH[0] = ARRAY[loc]; IWIDTH[1] = ARRAY[loc+1]; IWIDTH[2] = ARRAY[loc+2]; IWIDTH[3] = ARRAY[loc+3];//Get the width of the image width = 0; width |= (IWIDTH[3]<<24); width |= (IWIDTH[2]<<16); width |= (IWIDTH[1]<<8); width |= (IWIDTH[0]); loc += 4; IHEIGHT[0] = ARRAY[loc]; IHEIGHT[1] = ARRAY[loc+1]; IHEIGHT[2] = ARRAY[loc+2]; IHEIGHT[3] = ARRAY[loc+3];//Get the height of the image height = 0; height |= (IHEIGHT[3]<<24); height |= (IHEIGHT[2]<<16); height |= (IHEIGHT[1]<<8); height |= (IHEIGHT[0]); loc += 6;//to account for plane numbers which, if not one, will cause an error so we don't need to check it BitsPerPixel[0] = ARRAY[loc]; BitsPerPixel[1] = ARRAY[loc+1]; BPP = 0; BPP |= (BitsPerPixel[1]<<8); BPP |= (BitsPerPixel[0]);//sets the BPP of the image loc += 2; CMETHOD[0] = ARRAY[loc]; CMETHOD[1] = ARRAY[loc+1]; CMETHOD[2] = ARRAY[loc+2]; CMETHOD[3] = ARRAY[loc+3]; COMPMETHOD = 0; COMPMETHOD |= (CMETHOD[3]<<24); COMPMETHOD |= (CMETHOD[2]<<16); COMPMETHOD |= (CMETHOD[1]<<8); COMPMETHOD |= (CMETHOD[0]);//set the method of compression loc += 20;//we are done with the important stuff, since Pixels per meter and palettes are not going to change our program break; case 12://it is BITMAP CORE HEADER we can use it IWIDTH[0] = ARRAY[loc]; IWIDTH[1] = ARRAY[loc+1]; IWIDTH[2] = 0; IWIDTH[3] = 0; val = 0; val |= (IWIDTH[1]<<8); val |= (IWIDTH[0]); width = (int)val; loc += 2; IHEIGHT[0] = ARRAY[loc]; IHEIGHT[1] = ARRAY[loc+1]; IHEIGHT[2] = ARRAY[loc+2]; IHEIGHT[3] = ARRAY[loc+3]; val = 0; val |= (IHEIGHT[1]<<8); val |= (IHEIGHT[0]); height = (int)val; loc += 4;//Also includes plane numbers which, if not one, will cause an error so we don't need to check it BitsPerPixel[0] = ARRAY[loc]; BitsPerPixel[1] = ARRAY[loc+1]; BPP = 0; BPP |= (BitsPerPixel[1]<<8); BPP |= (BitsPerPixel[0]);//sets the BPP of the image loc += 2; break; default: FILE.close(); return ERROR3; } HEADERS=new unsigned char[DIBsize+14]; for (int i=0; i<DIBsize+14; i++) { HEADERS[i]=ARRAY[i]; } loc = start; unsigned char *ret=new unsigned char[width*height*(BPP/8)]; switch (BPP) { case 24://RGB for (int y=0; y<height; y++) { for (int x=0; x<width; x++) { for (int i=0; i<3; i++) { AT<unsigned char>(x, y, i, ret, width, BPP/2)=ARRAY[loc]; loc++; } } loc += 2; } FILE.close(); return ret; break; case 32://RGBA for (int y=0; y<height; y++) { for (int x=0; x<width; x++) { for (int i=0; i<4; i++) { AT<unsigned char>(x, y, i, ret, width, BPP/2)=ARRAY[loc]; loc++; } } } FILE.close(); return ret; break; default://32 is generally highest and anything lower than 24 divides by less than a byte, and I cannot access data that precisely without structs and tons of data FILE.close(); return ERROR3; } } void Bitmap::UPDATE() { unsigned char *ret=new unsigned char[width*height*(BPP/8)]; for (int y=0; y<height; y++) { for (int x=0; x<width; x++) { for (int i=0; i<(BPP/8); i++) { AT<unsigned char>(x, y, i, ret, width, (BPP/8))=AT<unsigned char>(x, y, i, IMAGE, width, (BPP/8)); } } } PICTURE=(int*)ret; } int main() { Bitmap PIC; PIC.OPEN(".\\TESTPIC.bmp"); PIC.CLOSE(".\\TESTPIC2.bmp"); return 0; }
I don't, but when it runs I get a blank STD console that waits for a few minutes, then causes windows to throw an exception (error report).
It means there is some other issue then just an infinite loop. Debug and see where that exception happens
That is one of the biggest problem's, I am using Code::Blocks and this is not a project, just an individual cpp file. How do I debug this?
Alright I put the file into a blank project and debugged it. It all seemed fine except next to FILE it said incomplete type. What does this mean?
The error is in the debugging, I watch the variable called 'FILE' and it shows: FILE = <incomplete type> whereas next to Byte it shows Byte = 124 '|' I am also in the process of rewriting the program using fopen and such c-style file systems, hoping to avoid this error.
is the debugger giving <incompatible type> after this line of your code... fstream FILE; or this line:- FILE.open(fname, ios_base::in|ios_base:ut|ios_base::binary);
It does exist,, I was able to open it using fopen. I was thinking of trying to rewrite the code using fopen and fget, but I don't know how these work, i.e. fget returns an int (4 bytes) to show the contents of a char (1 byte), how does that work!