Thread: messing around with bitmaps

  1. #1
    Registered User
    Join Date
    Jan 2012
    Posts
    26

    messing around with bitmaps

    started writing this today; still new too writing files though. it's not working yet, the program runs and executes with out crashing but the file it creates can't be opened so i think i must have messed up the file header some where. It will be neat too get this working, with direct access to pixel data i am sure there are a lot of cool designs that can be created. I haven't really started de-buging it yet, wouldn't be surprised if it had an obvious problem.





    Code:
    #include "stdlib.h"
    #include "stdio.h"
    #include "conio.h"
    
    #define BI_RGB 0x00000000;
    
    typedef unsigned char byte;
    
    struct fileheaderstruct{
        unsigned short       bftype; // must be 19778
        unsigned int         bfsize; // size of file in bytes
        unsigned short  bfreserved1; // reserved, must equal zero
        unsigned short  bfreserved2; // reserved must equal zero
        unsigned int      bfoffbits; // offset from fileheader to pixel array
    };
    struct infoheaderstruct{
        unsigned int          bisize; // size of infoheader in bytes
        unsigned int         biwidth; //width in pixels
        unsigned int        biheight; //hieght in pixels
        unsigned short      biplanes; //number of bit map planes
        unsigned short    bibitcount; // bits per pixel (4, 8, 24)
        unsigned int    bicompresion; //compression used; BI_RGB no compression, BI_RL4, BI_RLE8
        unsigned int     bisizeimage; //size of bitmap image storage
        unsigned int bixpelspermeter; //horizontal resolution of target device
        unsigned int biypelspermeter; //vertical resolution of target device
        unsigned int       biclrused; //colors used, if zero reading uses max colors allowed by bibitcount
        unsigned int  biclrimportant; //colors important, if zero all colors are important
    };
    struct RGBquadstruct{       // color pallet structure
        byte      red; // intinsity of red, 0- 255
        byte     blue; // intensity of blue, 0- 255
        byte    green; // intensity of green, 0- 255
        byte reserved; // reserved, must be equal to zero
    };
    struct pixel24struct{
        byte red; 
        byte green;
        byte blue;
    };
    
    
    int main()
    {
        int high;
        int length;
    
        struct bitmap24struct{                  // defines truecolor bit map, no color pallet 1080x1920
        struct fileheaderstruct fileheader;
        struct infoheaderstruct infoheader;
        struct pixel24struct pixel[1080][1920];
        };
    
        bitmap24struct *bitmapfile;
    
        bitmapfile = (struct bitmap24struct*)malloc(sizeof(struct bitmap24struct));
        if(bitmapfile == NULL)
        {
            printf("\n****************memory allocation error*********************\n");
            getch();
            return 0;
        }
    
        bitmapfile->fileheader.bftype = 19778;
        bitmapfile->fileheader.bfsize = sizeof(struct bitmap24struct);
        bitmapfile->fileheader.bfreserved2 = 0;
        bitmapfile->fileheader.bfreserved1 = 0;
        bitmapfile->fileheader.bfoffbits = sizeof(struct infoheaderstruct);
    
        bitmapfile->infoheader.biheight = 1080;
        bitmapfile->infoheader.biwidth = 1920;
        bitmapfile->infoheader.biclrused = 0;
        bitmapfile->infoheader.biclrimportant = 0;
        bitmapfile->infoheader.bibitcount = 24;
        bitmapfile->infoheader.bisizeimage = 6220800;
        bitmapfile->infoheader.bicompresion = BI_RGB;
        bitmapfile->infoheader.biypelspermeter = 0;
        bitmapfile->infoheader.bixpelspermeter = 0;
        bitmapfile->infoheader.bisize = sizeof(struct infoheaderstruct);
        bitmapfile->infoheader.biplanes = 1;
    
        high = 0;
        while( high < 1080)
        {
            length = 0;
            while(length < 1920)
            {
                bitmapfile->pixel[high][length].red   = 128;
                bitmapfile->pixel[high][length].green = 128;
                bitmapfile->pixel[high][length].blue  = 128;
                length++;
            }
            high++;
    
        }
        fwrite(bitmapfile, 1, sizeof(struct bitmap24struct), fopen("mypicture.bmp", "w"));
        return 0;
    }

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    I would try applying it backward -- ie, read into the struct from a bitmap file you know is good, and compare this to one you created.

    One probable issue here is that compilers often pad structs out to four bytes. Since struct fileheaderstruct (btw adding "struct" to the end of all your struct names seems very German to me, lol) has three shorts in it, there could be an extra two bytes in it, which would throw everything else off. Check with sizeof() to see if it is the size you think it is. Two 4 byte ints plus three 2 byte shorts is 14, but I bet the struct is actually 16.

    Which raises another issue: you should use types with exact sizes:
    Code:
    #include <inttypes.h>
    int32_t a; // 4 byte integer
    int16_t b; // 2 byte integer
    Unfortunately, there is no standard way of preventing the compiler from adding padding. Fortunately, most of them can do it anyway, but how depends on the compiler. Eg, with gcc just add:
    Code:
    struct whateverstruct {
        int32_t a;
        int16_t b;
        #pragma pack(1);
    };
    This ensures that sizeof(struct whateverstruct) is exactly 6 bytes.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Excellent catch, MK27. I just tried it with #pragma pack(1) and it worked. That pragma should really be at the top before any structure declares.

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by nonoob View Post
    Excellent catch, MK27. I just tried it with #pragma pack(1) and it worked. That pragma should really be at the top before any structure declares.
    I actually didn't know you could declare it globally, but that makes sense.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    Jan 2012
    Posts
    26
    it worked! lol can you upload the photo? I don't think I have pragma pack, at least I never installed it. the photo is 1080x1920 all grey right?

  6. #6
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    There will be some way of packing structs with your compiler. Which are you using? Also, you should open your output file in binary mode ("wb" instead of just "w").

  7. #7
    Registered User
    Join Date
    Jan 2012
    Posts
    26
    I wrote this with visual studio 2010, I have code::blocks with the minGW compiler installed also but I have to run programs inside of code::blocks or else they don't hook into the right .dll's.

    Code:
        printf("%d\n", sizeof(struct fileheaderstruct));
        printf("%d", (sizeof(unsigned short) * 3)+(sizeof(unsigned int) * 2));
    returns;
    16
    14

  8. #8
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Have you tried putting
    Code:
    #pragma pack(1)
    just after your #include's?

  9. #9
    Registered User
    Join Date
    Jan 2012
    Posts
    26
    recompiled inside of code::blocks with #pragma pack(1); declared and it worked!!

  10. #10
    Registered User
    Join Date
    Jan 2012
    Posts
    26
    worked with pragma in vs 2010 also, thanks it would have taken me a very long time too figure that out

  11. #11
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Quote Originally Posted by MK27 View Post
    I actually didn't know you could declare it globally, but that makes sense.
    Well, as a compiler directive, it gets processed in order while reading the source file top-to-bottom. So the more closer to the top it is, the better the chances that it will affect all structure definitions. I wouldn't call it "global" though but I understand your meaning.

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Only the fileheaderstruct needs to be packed. All the others should align naturally.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  13. #13
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Seems to be true but there's no point in switching off the pack directive.
    I've noticed that "int" is used. That's flaky because the size of int can vary depending on compiler and/or memory model. It's safer to use 'short' and 'long'. But since it's working (I opened the .BMP with a viewer), the currently used compiler uses an 'int' size that matches the BMP file format.

  14. #14
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Quote Originally Posted by nonoob View Post
    I've noticed that "int" is used. That's flaky because the size of int can vary depending on compiler and/or memory model. It's safer to use 'short' and 'long'. But since it's working (I opened the .BMP with a viewer), the currently used compiler uses an 'int' size that matches the BMP file format.
    It's actually better to use standard sizes like MK27 already pointed out above.
    If you understand what you're doing, you're not learning anything.

  15. #15
    Registered User
    Join Date
    Jan 2012
    Posts
    26
    By setting the colors of the pixels to variables and assigning the variables values derived by using high and length as operands i've figured out how too make thick lines, divisions, gradients, and a weird rising sun picture with modulus. And when I mess up and get buffer over runs I can SEE it now lol.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. CWinThread messing itself up
    By LowlyIntern in forum C++ Programming
    Replies: 7
    Last Post: 01-16-2009, 08:08 AM
  2. Messing with folders
    By Probose in forum C++ Programming
    Replies: 2
    Last Post: 09-21-2006, 03:16 PM
  3. Is someone messing with m$ again?
    By exluddite in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 09-16-2004, 01:56 PM
  4. Messing with Large Integers
    By johnnie2 in forum Windows Programming
    Replies: 3
    Last Post: 11-16-2002, 01:22 PM
  5. Do you think this might be messing up my brain?
    By incognito in forum A Brief History of Cprogramming.com
    Replies: 9
    Last Post: 01-21-2002, 08:33 AM