Author

Topic: I would like to buy your C++ expertise (Read 1397 times)

hero member
Activity: 504
Merit: 502
April 01, 2012, 11:55:59 AM
#17
Thanks for your help - can you elaborate on this a bit?

If you're going to reuse 'os' you should call 'os.str("")' after using it.

Because ostringstream is alway streaming in an append mode; if you want to reuse the same one to convert the next number in a sequence then you have to clear it between each use.
Code:
ostringstream os;

for(unsigned int filenum = 0; filenum < 100; filenum++ ) {
  os << filenum << ".pbm";
  ofstream file( os.str().c_str() );
  YourFunctionThatWritesToAStream( file );
  os.str("");
}

If you didn't have the
Code:
os.str("")
then os would have "0", "01", "012", "0123", "01234", "012345", etc, as the next number gets appended.

Also, when I compiled the code I got the following:

testbed1.cpp:21:28: error: no matching function for call to ‘std::basic_ofstream::basic_ofstream(std::basic_ostringstream::__string_type)’

Oops, wrote without compiling to catch errors. 9c5207677's correction is all you need -- os.str().c_str() will sort this error out.
newbie
Activity: 10
Merit: 0
April 01, 2012, 11:35:08 AM
#16
os.str() returns an object of type std::string, but ofstream does not have a constructor that takes a std::string argument. That's why you must call the c_str() function to return a pointer to a char array from the std::string object.

Try this:

Code:
#include
#include

int main()
{
  unsigned int filenum = 100;
  std::ostringstream os;
  os << filenum << ".pbm";

  std::ofstream file(os.str().c_str());
  file << "hello";
  file.close();

  return 0;
}
newbie
Activity: 31
Merit: 0
March 31, 2012, 06:20:39 PM
#15
Thanks for your help - can you elaborate on this a bit?

If you're going to reuse 'os' you should call 'os.str("")' after using it.

Also, when I compiled the code I got the following:

testbed1.cpp:21:28: error: no matching function for call to ‘std::basic_ofstream::basic_ofstream(std::basic_ostringstream::__string_type)’
hero member
Activity: 504
Merit: 502
March 31, 2012, 05:54:33 PM
#14
It's working fine - but now I want to have to have the output file be named to whatever the value of an integer variable is.  Say I have an integer variable called... filename.  If filename = 156 then I want to output to a file called 156.pbm.. I cant figure out how to do it.  Thanks in advance for any help. 

Simplest is probably this:

Code:
int main ()
{
  unsigned int filenumber = 156;
  ostringstream os;
  os << filenumber << ".pbm";


  ofstream myfile (os.str());
  myfile << "255"
  myfile.close();
  return 0;
}

If you're going to reuse 'os' you should call 'os.str("")' after using it.
newbie
Activity: 31
Merit: 0
March 31, 2012, 05:27:16 PM
#13
Hey, I have another one for you guys.  I have been writing to a .pbm file, thats working fine.  I am doing it this way

int main ()
{
ofstream myfile ("picture.pbm");
myfile << "255"
myfile.close();
return 0;
}

It's working fine - but now I want to have to have the output file be named to whatever the value of an integer variable is.  Say I have an integer variable called... filename.  If filename = 156 then I want to output to a file called 156.pbm.. I cant figure out how to do it.  Thanks in advance for any help. 
full member
Activity: 120
Merit: 144
March 30, 2012, 11:34:39 PM
#12
I wrote a raytracer for a computer graphics class in college and needed to write to BMP format. Here's my code:

bmpwriter.h:
Code:
bool write_bitmap(const char *filename, const char *buffer, int width, int height);

bmpwriter.cpp:
Code:
#include
#include "bmpwriter.h"

// stuff from wingdi.h
typedef unsigned short WORD;
typedef unsigned int DWORD;
#define FAR
#pragma pack(push, 2)
typedef struct tagBITMAPFILEHEADER {
        WORD    bfType;
        DWORD   bfSize;
        WORD    bfReserved1;
        WORD    bfReserved2;
        DWORD   bfOffBits;
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
typedef struct tagBITMAPCOREHEADER {
        DWORD   bcSize;                 /* used to get to color table */
        WORD    bcWidth;
        WORD    bcHeight;
        WORD    bcPlanes;
        WORD    bcBitCount;
} BITMAPCOREHEADER, FAR *LPBITMAPCOREHEADER, *PBITMAPCOREHEADER;
#pragma pack(pop)

bool write_bitmap(const char *filename, const char *buffer, int width, int height) {
BITMAPFILEHEADER bfh = { 0x4D42, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPCOREHEADER) + width * height * 3, 0, 0, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPCOREHEADER) };
BITMAPCOREHEADER bch = { sizeof(BITMAPCOREHEADER), width, height, 1, 24 };
FILE *pf = fopen(filename, "wb");
if (pf == NULL) {
return false;
}
else {
fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, pf);
fwrite(&bch, sizeof(BITMAPCOREHEADER), 1, pf);
fwrite(buffer, 3 * width, height, pf);
fclose(pf);
return true;
}
}

The buffer is an array of (3 × width × height) 8-bit samples, which are the RGB colors at each pixel in the image.  I don't remember whether BMP uses RGB or BGR ordering, so just play with it until you get it right.
newbie
Activity: 31
Merit: 0
March 30, 2012, 06:40:47 PM
#11
Thanks for all of the replies - I should have prefaced my question with the statement that I am a rank newbie at C++ programming and most of your responses were well over my head.  Hawkix suggested that I output Netpbm format instead of BMP and that worked out quite well.  I have donated a small sum him for his suggestion.

Once I get out of the newbie forum I plan on starting a thread where I will buy pointers on C++ and linux.  I have been using linux for well over a year, but have yet to dip my toe in the nuts and bolts of things.  I have learned a lot reading forums and books, but I have also wasted a lot of time because of getting hung up on small issues that a very frustrating.  Hopefully offering small bounties, on the order of 1 or 2 BTC, will encourage people to give me well thought out help.  If any of you are interested, keep an eye on the marketplace board soon.
hero member
Activity: 504
Merit: 502
March 26, 2012, 06:08:11 PM
#10
As general practical advice for C++ file format writing; I suggest the following.

  • Make child classes for elements off a streamable base class.  By "streamable" I mean make a virtual write() member function that accepts an "ostream &" as its parameter.
  • Build these elements as members of higher level streamable classes
  • The higher level classes then call the write() member in the more elemental class members

An example:

Code:
class TStreamable
{
  public:
    ostream &write( ostream & ) = 0;
};

class TUint16LE : public TStreamable
{
  public:
    ostream &write( ostream &s ) { s.put((Value>>0)&0xff); s.put((Value>>8)&0xff); return s;}
 
  uint16_t Value;
};

class TImageSize : public TStreamable
{
  public:
    ostream &write( ostream &s ) { Width.write(s); Height.write(s); return s; }

  TUint16LE  Width, Height;
};

Eventually you will have one top level class that writes the entire file; but it will call simpler writers, and they will call simpler writers, etc.  You can give that top-level class whatever more convenient member functions you want to set the data; and then leave the complicated writing to take care of itself.

Hope that helps.
vip
Activity: 1386
Merit: 1140
The Casascius 1oz 10BTC Silver Round (w/ Gold B)
March 26, 2012, 02:57:02 PM
#9
I too think this is drop dead simple.  Just figure out what the headers are for a BMP for the image size of your choice, and stick them in an array as constant bytes.  When you want to write the BMP file, write out the constant bytes and then the pixels.  Need not even mess with building a header - just save a BMP file in a paint program for the dimensions and color depth you want, and use the spec to figure out which bytes are the header and which are the pixels.

And that, of course, would be endian-neutral code, right ?

Yes because it would be an array of bytes (specifically chars in C++) which don't have endianness problems.

If he needed to change the array (e.g. to accommodate a different height or width for the image) then he'd need to make sure he puts the height and width into the header with proper respect for endianness.  But in the simplest case, he'd be using a fixed size image using a canned height and width.

Then when he gets to actually putting out the pixels, he puts 3 bytes (one for R, one for G, and one for B).

I recall the BMP format also requiring each row to start on a 32-bit boundary, so at the end of each row, up to three null bytes must be added for padding to accommodate this (the number of bytes needed depends on the image width).
vip
Activity: 1386
Merit: 1140
The Casascius 1oz 10BTC Silver Round (w/ Gold B)
March 26, 2012, 02:22:06 PM
#8
I too think this is drop dead simple.  Just figure out what the headers are for a BMP for the image size of your choice, and stick them in an array as constant bytes.  When you want to write the BMP file, write out the constant bytes and then the pixels.  Need not even mess with building a header - just save a BMP file in a paint program for the dimensions and color depth you want, and use the spec to figure out which bytes are the header and which are the pixels.
newbie
Activity: 26
Merit: 0
March 26, 2012, 02:12:28 PM
#7
This sounds like a school project  Grin

I don't think it would take much effort to do the whole thing yourself, as said by others, just look at the BMP spec to get what headers you need and just output the image to file.

I'm tempted to try this myself now just for personal interest...
hero member
Activity: 531
Merit: 505
March 25, 2012, 03:50:47 PM
#6
BMP is very easy format - its just some header and then the pixels, rows by rows. For fractals, you definitely will use 24bit RGB BMP format. I do not know what presentation API you use to show the fractals (GDI? OpenGL? DirectX? OtherWidgets?), but if you can recalculate the fractal image into memory matrix (or long array), you basically are done, just open binary file, write header (there are some gotchas, but most of them are well documented), then feed the whole pixels, done. In case of questions, contact me.
legendary
Activity: 1904
Merit: 1002
March 25, 2012, 03:45:47 PM
#5
I've read that - but this is my first time programming anything and I not clear on a few things. 

I'd hack it together for you for a few bitcoins, but I'm on vacation.  In the absence of spec-reading skills, I would suggest you look at this: http://www.cplusplus.com/forum/beginner/4307/, or as yogi suggested, use a library that does the heavy lifting for you.  I've not used wxBitmap, so I can't speak to it, but OpenCV has really easy image file writing APIs.  If you are using OpenGL, this link has code to write out a BMP from the buffer returned by glReadPixels: http://dave.thehorners.com/tech-talk/programming/124-opengl-writing-the-framebuffer-to-disk.  If you appreciate my google-fu, any bitcents sent to my signature address will be met with a corresponding level of gratitude.
legendary
Activity: 947
Merit: 1042
Hamster ate my bitcoin
March 25, 2012, 03:27:42 PM
#4
Have you looked at wxWidgets, it has a wxBitmap class.
newbie
Activity: 31
Merit: 0
March 25, 2012, 03:19:59 PM
#3
I've read that - but this is my first time programming anything and I not clear on a few things. 
legendary
Activity: 1904
Merit: 1002
newbie
Activity: 31
Merit: 0
March 25, 2012, 03:12:17 PM
#1
Long story short - I am writing a program to create fractals.  I am not having any trouble with that part of it, but I am finding it impossible to find somewhere on the interenet that will explain how to output to a .bmp (bitmap) file.  I dont want to output to screen and screen cap it, or anything like that - I want to be able to create and write directly to a bitmap.  If you think you can help me with this, please contact me and we will negotiate how much I should pay you.  BTC only.
Jump to: