The file gets more kB then the original ( 114KB to 914KB)
And something weird: when I try open the new file with the notepad, it loads forever and i get a program not responding message when I try to close it, with the original file it loads ok..

By the way the new file opens ok, its a pbm image file..

I guess Im missing something that I have to do when writing to binary files?

ofstream writer("out.pbm", ios::binary);
		writer << MV[0] << MV[1] << '\n';
		writer <<"# Created by me"<< '\n';
		writer << width << ' ' << height << '\n';

		for(long i=0; i < (width*height); i++){

			writer.write(&img_pix[i].rgbb[0],1);

		}

		writer.close();

edit: My program just loads the file , store its information and save it..

Recommended Answers

All 23 Replies

>>

writer.write(&img_pix[i].rgbb[0],1);

I don't know what is the type of img_pix but if it is not char, you better use a cast to char

writer.write(reinterpret_cast<char*>(&img_pix[i].rgbb[0]) ,sizeof(&img_pix[i].rgbb[0] );

Isn't a pbm a text file?
Shouldn't you be writing your numbers as text, with: writer << img_pix[i].rgbb[0];

Its a pointer to struct PIXELS with :
int rgb[3];//for ascii
char rgbb[3];//for binary

PIXELS *img_pix = new PIXELS[width*height];


I was thinking if a have to 'finish' the file in some way( like finishing a string with '\0'..?

Isn't a pbm a text file?
Shouldn't you be writing your numbers as text, with: writer << img_pix[i].rgbb[0];

all PNM files have an ascii and a binary version, in my case is the binary..

Hi again
I opened the new file with word pad, the problem is theres a lot of memory junk being writed on the end of the file (ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ...) lots and lots

Any idea of what can I be doing wrong?
Im reading the original file in the same way Im writing:

...
ifstream readPNM;
...
		for(long i=0; i < (width*height); i++){

			readPNM.read(&img_pix[i].rgbb[0],1);

		}

Hi again
I opened the new file with word pad, the problem is theres a lot of memory junk being writed on the end of the file (ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ...) lots and lots

Any idea of what can I be doing wrong?

You aren't doing anything wrong. You can't view binary files with Notepad because they contain binary data that Notepad doesn't know how to display. Notepad can only display text files, not binary files.

no no no no no..you get it wrong
The new file are getting bigger because theres a lot of memory junk being writed on it, comparing with the original one, with have no "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" at the end..get it?


I just opened it on wordpad to see whats going on

Its a pointer to struct PIXELS with :
int rgb[3];//for ascii
char rgbb[3];//for binary

why not just use a union, which means the same memory location could be accessed by either an int or char array

struct PICX
{
    union {
       int rgb[3];//for ascii
       char rgbb[sizeof(int)];//for binary
    }
};

>>PIXELS *img_pix = new PIXELS[width*height];

writer.write(reinterpret_cast<char*>(&img_pix.rgbb[0]) ,sizeof(&img_pix.rgbb[0] );

Does rgbb contain anything? Is it just an uninitialized array? Use the union concept mentioned above might resolve that if your program populates the int first.

[edit]
On second thought, if all you use rgbb for is to write out to the file, then you don't need it at all nor would you even need the union

writer.write(reinterpret_cast<char*>(&img_pix[i].rgb) ,sizeof(img_pix[i].rgb));

"Does rgbb contain anything?"
- If the PNM file Im trying to open is a Binary one, so I use rgbb to read the pixel map, and so write it to a new file( I though is better use chars to get binary stuff..?) but i have to save it in the same way ( binary mode )with no modification, just load and save it.

using this :

writer.write(reinterpret_cast<char*>(&img_pix[i].rgb) ,sizeof(img_pix[i].rgb));

the file gets 10,7 MB o__o"
using this :

writer.write(reinterpret_cast<char*>(&img_pix[i].rgb[0]) ,sizeof(img_pix[i].rgb[0]));

the file gets 3,4 MB ..
using this:

writer.write(&img_pix[i].rgbb[0],sizeof(img_pix[i].rgbb[0]));

the file gets 914KB
using this:

writer.write(reinterpret_cast<char*>(&img_pix[i].rgbb) ,sizeof(img_pix[i].rgbb));

the file gets 2,67 MB
using this:

writer.write(reinterpret_cast<char*>(&img_pix[i].rgbb[0]) ,sizeof(img_pix[i].rgbb[0]));

the file gets 914 KB

But with ALL the options the file keep being opened ok, with no corruption or image weird problems( since the file header have its width and height and the problem is just junk after the pixel map )
I dont understand that, how can the junk be added just at the end? isnt it suppose to add the junk after each bit?

BTW, in this case im using just rgbb[0] because im using a PBM file, with is a black and white and just use one bit per pixel, so i dont need rgbb[0] rgbb[1] rgbb[2]..but i keep the array because my program can open all types of pnm files(ppm, pbm, pgm, ascii and binary modes)
With the ascii files im having no problems..

From what you posted earlier it still looks like rgbb is uninitialized. Do you write rgbb in text files too?

From what you posted earlier it still looks like rgbb is uninitialized. Do you write rgbb in text files too?

For text files I use the int rgb[3]....
I dont get very well what do you mean, I do not initialize rgbb with default values, i just start use it when reading the pixel map from the original file:

readPNM.read(&img_pix[i].rgbb[0],1);

At this point I think you probably need to use your compiler's debugger, put a break point on that write line and inspect the value of that array. You have only posted one line from your program so its pretty impossible for anyone to tell you the solution to the problem. Possibly its not that line at all but somewhere else in the program, such as memory corruption.

It would seem impossible for your original code (in post 1) to write more than width * height + 25 bytes (give or take a few bytes for different widths since you are writing these as text), so if you are getting 8 times this many bytes your problem must lie elsewhere. You need to attach your (minimal) program and data file.

using this :

writer.write(reinterpret_cast<char*>(&img_pix[i].rgb) ,sizeof(img_pix[i].rgb));

the file gets 10,7 MB o__o"
using this :

writer.write(reinterpret_cast<char*>(&img_pix[i].rgb[0]) ,sizeof(img_pix[i].rgb[0]));

the file gets 3,4 MB ..
using this:

writer.write(&img_pix[i].rgbb[0],sizeof(img_pix[i].rgbb[0]));

the file gets 914KB
using this:

writer.write(reinterpret_cast<char*>(&img_pix[i].rgbb) ,sizeof(img_pix[i].rgbb));

the file gets 2,67 MB
using this:

writer.write(reinterpret_cast<char*>(&img_pix[i].rgbb[0]) ,sizeof(img_pix[i].rgbb[0]));

the file gets 914 KB

It seems that you are desperately trying various ways to write the file.

Maybe relax and try to master e.g. a binary .pnm file of a very small size, say 2x2 pixels hence being easily viewed in any hexeditor at a glance (notepad and wordpad surely are poor choices for checking the files' content).

Try for example the following struct for reading/writing

struct Pixel
{
    // 3 bytes represents a single pixel
    unsigned char rgb[3];
};

Then when you read in the file you might

// ... code here to read in the file's header ...

// allocate enough memory to read in rest of the file
const int pixels = width * height;
Pixel * p = new Pixel[pixels];

for(int ii = 0; ii < pixels; ++ii)
{
    // read 3 bytes at a time
    if( ! file.read(reinterpret_cast<char *>(p[ii].rgb), 3))
    {
        // should not happen, handle error ...
        break;
    }
}

// all done

Then to write the file, you can iterate over the array issuing file.write(reinterpret_cast<const char *>(p[ii].rgb), 3) Remember that the second parameter to both read() and write() determines how many bytes each I/O operation involves.

Im attaching a .zip file with the cpp and the image files im using to test the program..**

mitrmkar, but I think this is exactly what Im doing now, I tried with unsigned char and the method you said, and got the same 914KB result..

"determines how many bytes each I/O operation involves."
In the case of a pbm file, the map of pixels is just one bit per pixel( black or white)..

I still dont get how can the problem come just AFTER all the writing (or
reading)..?


Edit: Ah..I dont know how I can see whats going on by debugging it, since the array is dynamic allocated I cant watch it, and I dont have idea of how can I check the fstreams...

**Damn, Im getting upload error with the attachment of the file, is this temporary or I have problems?

+		rgbb	0x0044714c "øÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍþÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"	unsigned char [3]

Hey, look this..thats a watching to img_pix[10000] on the reading momment...Im imagining it are getting right the one bit it suppose to, but since i have a byte on rgbb[0] it let the empty spaces after the bit with junk..And when Im writing to a new file, it writes just the bits, and put all this junk just after it??...Am Im imagining too much?

+		rgbb	0x0044714c "øÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÿÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍþÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"	unsigned char [3]

And when Im writing to a new file, it writes just the bits, and put all this junk just after it??...Am Im imagining too much?

Now remember the second parameter to write() , that specifies how many bytes are written.

PS. Maybe you could try to re-post your code

I attached the files.

"and put all this junk just after it??"

I get it, but it puts the junk after ALL the bits, not just after each one, that is what Im not understanding.
And how can I say to read and write to get just a single bit?

After some testing with the code you just posted I found that the file marbles.pbm does not contain enough data --

Here is the output of my version of the read function:

Error reading bin file
Expecting 936576 bytes but found only 117071 bytes.

and the code I changed

void CarregaPNM::LoadPixels(){
<snip>
	else if( MV[1] == '4' ){//if is a bin pixel map (PBM P4)
        long max = width*height;
        long i;
        unsigned char* buf = new unsigned char[max];
        readPNM.read((char *)buf,max);
        if( (i = readPNM.gcount()) != max)
        {
            cout << "Error reading bin file\n";
            cout << "Expecting " << max << " bytes but found only " << i << " bytes.\n";
        }
        for(i = 0; i < max; ++i)
            img_pix[i].rgbb[0] = buf[i];
        delete[] buf;

My guess is the reason the file is not big enough is because the remaining unwritten bytes are some default value, such as -1 (or 0x255), 0 or some other default value. From this information I would presume not only do you have to save width and height, but also the number of bytes that are actually in the file so that you can write back out exactly what was read, which might be a value less than width*height.

The reason your file is 8 time bigger is because you are forgetting that each bit (in this format) represents a pixel. You are reading (and writing) 1152 * 813 bytes, but that is actually how many bits you should be reading! There will probably be some padding at the end of the picture rows, so there will be more than 1152 * 813 / 8 bytes. You will have to look up the info for the padding. You could try assuming that it's simply to the nearest byte and see if that works, but it could be rounded off to 4 bytes. At any rate, that's your basic problem.

The reason your file is 8 time bigger is because you are forgetting that each bit (in this format) represents a pixel. You are reading (and writing) 1152 * 813 bytes, but that is actually how many bits you should be reading! There will probably be some padding at the end of the picture rows, so there will be more than 1152 * 813 / 8 bytes. You will have to look up the info for the padding. You could try assuming that it's simply to the nearest byte and see if that works, but it could be rounded off to 4 bytes. At any rate, that's your basic problem.

Yes I think you might be right about that because that is just about the number of bytes my version of the program actually read.

AD: Our analyses seem to gell nicely. It explains why all the extra stuff is at the end. Icebone is basically reading and writing 8 times too many bytes. It could have caused a segfault but didn't in this case.

Simply adding / 8 after width * height in the two loops involved (the reading and writing loops) writes the file perfectly.

But a better solution (assuming padding to the nearest byte) might be:

int size = width / 8;
if (width % 8 != 0) ++size;
size *= height;

And use size in the loop conditions.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.