Thread: write bmp

  1. #1
    Registered User
    Join Date
    Sep 2006
    Posts
    18

    write bmp

    Hi,
    I'm trying to output a plain red bitmap using only the C++ stl (so I can't use windows.h and it's functions). How would I go about doing this? At the moment, I've imported a (working) bitmap header file. I read this file in, and then output it to a new file using streams. The new file then ends up being a 700 x 700 bitmap file, like it should be. However, when I open it in windows picture viewer, it says drawing failed. I assume this is because I need to append some more information on to the end of the header. What would I append to the end of it in order to make it plain red?
    Thanks

  2. #2
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    You need to use the bitmap file format. Since you're not using windows.h, check here for that:

    http://www.wotsit.org/list.asp?al=B

    Useful thread: http://cboard.cprogramming.com/showt...ht=save+bitmap

    Search the boards for others.

    You might also want to check out msdn: bitmap structures(particularly BITMAPINFOHEADER and BITMAPFILEHEADER).

    edit: Also cygwin/mingw wingdi.h declares the relevant structures so you could just extract them from there after changing to non-windows types and ensuring the structures are properly aligned.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  3. #3
    Registered User
    Join Date
    Sep 2006
    Posts
    18
    Thanks for the reply. What would be the best way to be able to access (read and write) to each pixel? How would I go about getting a pixel, and storing it in an array?

  4. #4
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Use the link to Wotsit that Ken gave you - it has links to details about the BMP format, and they should have enough info to enable you to implement the code needed to read/write a BMP file. Make an attempt, post what you don't understand, and the board can work from there.

    If you don't want to implement it yourself, there are several libraries out there. Most graphics libraries (although they add a lot of unneeded bulk) can read/write a bitmap: Allegro and SDL can both do this, and I used Allegro to output BMPs for the longest time.
    Allegro, however, has more setup/stuff than is needed for just BMP work, so now I use gd for most of my image work. It has the added benefit that I can also save/load PNG, GIF, JPEG, etc. See: libgd
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    18
    Here's what I've got so far:
    Code:
    #include <fstream>
    #include <iostream>
    #include <vector>
    
    
    
    using namespace std;
    
    
    struct rgb { //declares pixel structure
    
    char b;
    char g;
    char r;
    
    
    };
    
    
    rgb *pixel = new rgb[700 * 700]; 
    
    int main()
    {
        char fileName[54];
        char buffer[255];
        
    
        ofstream fout("bitmap.bmp");
        
        ifstream fin("bmpH.hdr");
        char ch;
        
        while(fin.get(ch))     
        {
                               fout << ch;
        
                               
         }
              
    for (int j=(699); j >=0 ; j--){ //iterate through all the pixels
    for (int l=0; l<700; l++){
    
    int i = j+(((700-1)-l)*700); // flip image since it's upside down in a bitmap
    
    
    
    
    //paint every pixel yellow
    pixel[i].b = 0x00; 
    pixel[i].g = 0xFF;
    pixel[i].r = 0xFF;
    
     fout << pixel[i].b;
     fout << pixel[i].g;
     fout << pixel[i].r;
    
    
    
    
    
    }
    }
    
    
    //paint ONE pixel black (Doesn't work) 
    int i = (200)+(200 * 700);
    
    pixel[i].b = 0x00; 
    pixel[i].g = 0x00;
    pixel[i].r = 0x00;
     cout << pixel;
     
     fout << pixel[i].b;
     fout << pixel[i].g;
     fout << pixel[i].r;
     
    
    
        
             
    
    
        fout.close();
        fin.close();
        
      
        
       system("PAUSE");
       remove("bitmap.bmp");
        return 0;
        
    }
    It paints every pixel yellow, so I get a nice background. However, I can't seem to write the one black pixel. What am I doing wrong?
    Thank you for the help.

  6. #6
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901
    A bitmap file doesn't just start off with the image data, It contains a header, attributes, and then it chunks the red, green, and blue data in bytes that have to be interpreted as such.

  7. #7
    Registered User
    Join Date
    Sep 2006
    Posts
    18
    I've added the header file in, which I assume contains the attributes as well? I tried appending the information of the pixels (by setting fout as ios::app), but it didn't make a difference. Sorry, I'm really new to this and I've spent a long time looking at this and it just feels like I'm going in circles.

  8. #8
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901
    Are you looking to create an actual bitmap file, or just a replication of one? By Header I mean each bitmap has a header (54 bytes I believe) the first two bytes being the characters BM to identify it as a bitmap. Plus it has information regarding the width, height, etc. To correctly output a bitmap you have to know how it looks as a file, wotsit has specifications on a lot of files for the purpose of programming for them.

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    18
    Thanks for the information. I've been given a header file (54 bytes). I am supposed to create a new bitmap file, using the header file given. Then, I just need to create different shapes (like triangles) on to the bitmap. However, all I need to try and figure out is how to write one pixel, and I should be able to to do the rest of the maths.
    Thanks again.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > //paint ONE pixel black (Doesn't work)
    Well yeah, you need to output it at the correct part in the loop outputting the huge yellow thing.

    'Paint' all the things you want in the pixel array, then output the whole array when you've finished painting.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    May 2007
    Posts
    88
    First of all, the block for the bitmap data should be created like this:

    Code:
    char image_data[width*length*bytes_per_pixel];
    //White background
    memset(image_data, 0xFF, width*length*bytes_per_pixel);
    Assuming you're using 24-bit color, each pixel uses a whole byte for each primary color. BMP files are stored in BGR format, so, if I wanted to make the pixel at (x, y) red, I would do this:

    Code:
    enum {
    BLUE_OFF = 0,
    GREEN_OFF,
    RED_OFF
    };
    
    image_data[x*width + y + BLUE_OFF] = 0x00;
    image_data[x*width + y + GREEN_OFF] = 0x00;
    image_data[x*width + y + RED_OFF] = 0xFF;
    If you're using 16-bit color, a little more trickery is required. And if you're in 8-bit color, you need a palette.

  12. #12
    Registered User
    Join Date
    Sep 2006
    Posts
    18
    Thanks. I keep getting an error with the memset though. I commented it out, but the following code only works if the RGB values are all 0xFF (i.e. a plain white background) otherwise it comes up with 'drawing failed'.
    Code:
    #include <fstream>
    #include <iostream>
    
    
    
    using namespace std;
    
    
    
    enum {
    BLUE_OFF = 0,
    GREEN_OFF,
    RED_OFF
    };
    
    
    char pixel[700 * 700 * 3];
    //memset(pixel, 0xFF, 700 * 700 * 3);
    
    
    
    
    
    int main()
    {
        char fileName[54];
        char buffer[255];
        
    
        ofstream fout("bitmap.bmp", ios::app);
        
        ifstream fin("bmpH.hdr");
        char ch;
        
        while(fin.get(ch))     
        {
                               fout << ch;
        
                               
         }
              
         for (int j=(699); j >=0 ; j--){ 
         for (int l=0; l<700; l++){
    
    
                int i = l+(j*700);
    
                pixel[i + BLUE_OFF] = 0xFF;
                pixel[i + GREEN_OFF] = 0xFF;
                pixel[i + RED_OFF] = 0xFF;
                fout << pixel;
    
          }
          }
    
    
    
    
    
        
        fout.close();
        fin.close();
        
      
        
        system("PAUSE");
        remove("bitmap.bmp");
        return 0;
        
    }
    edit: It is a 24-bit bitmap. I've set it to append mode, because if I overwrite it, it would remove the header file that's already there. Could this be part of the problem?
    Last edited by namespace::me; 05-07-2007 at 03:36 PM.

  13. #13
    Registered User
    Join Date
    May 2007
    Posts
    88
    Try putting the pixel declaration and the memset call inside main. Also, you might try allocating pixel dynamically.

  14. #14
    Registered User
    Join Date
    Sep 2006
    Posts
    18
    Thanks, UMR_Student. I put the memset in the main, and it ran with no errors and I can have the background any colour I want. I noticed that if I have anything after the two FOR.....NEXT loops, they don't get recognised. I tried copy and pasting the another for loop and put it black. I was expecting that it would overwrite what was currently there, but it ignored it and just had the colours from the first loop.
    By allocating dynamically, due you mean creating it on the heap using New()?

  15. #15
    Registered User
    Join Date
    May 2007
    Posts
    88
    > By allocating dynamically, due you mean creating it on the heap using New()?

    Yes.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem reading BMP
    By Mortissus in forum C Programming
    Replies: 4
    Last Post: 02-02-2006, 06:32 AM
  2. Reroute where programs write to
    By willc0de4food in forum C Programming
    Replies: 7
    Last Post: 09-21-2005, 04:48 PM
  3. Strange problem with bmp
    By Victor in forum Linux Programming
    Replies: 2
    Last Post: 04-04-2005, 02:48 PM
  4. adding encryption to bmp
    By GiraffeMan in forum C Programming
    Replies: 10
    Last Post: 04-16-2002, 01:42 PM
  5. write in c
    By PutoAmo in forum C Programming
    Replies: 6
    Last Post: 04-03-2002, 07:53 PM