Can someone help me fix my bitmap loader?

Started by
20 comments, last by Drakkcon 18 years, 9 months ago

#include "SDL.h"

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>

using namespace std;

void SetPixel8Bit(SDL_Surface *surface, int x, int y, Uint8 Color);
void SetPixel32Bit(SDL_Surface *surface, int x, int y, Uint32 Color);
SDL_Surface * Load24BitBitmap(char *FileName);

struct BitmapFileHeader
{
    unsigned short bfType; //must be 19778
    unsigned int bfSize;
    unsigned short bfReserved1, bfReserved2;
    unsigned int bfOffBits;
};

struct BitmapInfoHeader
{
    unsigned int biSize;
    unsigned int biWidth;
    unsigned int biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;
    unsigned int biCompression;
    unsigned int biSizeImage;
    unsigned int biXPelsPerMeter;
    unsigned int biYPelsPerMeter;
    unsigned int biClrUsed;
    unsigned int biClrImportant;
};

struct RgbQuadLilEndian
{
    char rgbBlue;
    char rgbGreen;
    char rgbRed;
    char rgbReserved;
};

struct Bitmap
{
    BitmapFileHeader BitmapFile;
    BitmapInfoHeader BitmapInfo;
    RgbQuadLilEndian* BitmapData;
};

int main(int argc, char **argv)
{
    SDL_Init(SDL_INIT_VIDEO);
    
    SDL_Surface *screen = SDL_SetVideoMode
        (640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
    
    srand(time(NULL));
    
    SDL_Surface *image = Load24BitBitmap("test2.bmp");
    
    SDL_BlitSurface(image, NULL, screen, NULL);
    
    SDL_Flip(screen);
    
    SDL_Delay(2000);
    
    SDL_Quit();
    
    
    return 0;
}

void SetPixel8Bit(SDL_Surface *surface, int x, int y, Uint8 Color)
{
    Uint8 *bufp;
    bufp = (Uint8 *)surface->pixels + y*surface->pitch + x;
    *bufp = Color;
}

void SetPixel32Bit(SDL_Surface *surface, int x, int y, Uint32 Color)
{
     Uint32 *pBuf = (Uint32*)surface->pixels + y * surface->pitch/4 + x;
    *(Uint32*)pBuf = Color;
}

SDL_Surface* Load24BitBitmap(char *FileName)
{
    Bitmap BitmapToLoad;  //bitmap structure
    SDL_Surface *surface; //surface to load the bitmap to
    
    fstream File(FileName, ios::in | ios::binary); //open bitmap file
    //load the bitmap File Header
    File.read((char*)&BitmapToLoad.BitmapFile.bfType, sizeof(unsigned short));
    File.read((char*)&BitmapToLoad.BitmapFile.bfSize, sizeof(unsigned int));
    File.read((char*)&BitmapToLoad.BitmapFile.bfReserved1, sizeof(unsigned short));
    File.read((char*)&BitmapToLoad.BitmapFile.bfReserved2, sizeof(unsigned short));
    File.read((char*)&BitmapToLoad.BitmapFile.bfOffBits, sizeof(unsigned int));
    //load the bitmap data header
    File.read((char*)&BitmapToLoad.BitmapInfo.biSize, sizeof(unsigned int));
    File.read((char*)&BitmapToLoad.BitmapInfo.biWidth, sizeof(unsigned int));
    File.read((char*)&BitmapToLoad.BitmapInfo.biHeight, sizeof(unsigned int));
    File.read((char*)&BitmapToLoad.BitmapInfo.biPlanes, sizeof(unsigned short));
    File.read((char*)&BitmapToLoad.BitmapInfo.biBitCount, sizeof(unsigned short));
    File.read((char*)&BitmapToLoad.BitmapInfo.biCompression, sizeof(unsigned int));
    File.read((char*)&BitmapToLoad.BitmapInfo.biSizeImage, sizeof(unsigned int));
    File.read((char*)&BitmapToLoad.BitmapInfo.biXPelsPerMeter, sizeof(unsigned int));
    File.read((char*)&BitmapToLoad.BitmapInfo.biYPelsPerMeter, sizeof(unsigned int));
    File.read((char*)&BitmapToLoad.BitmapInfo.biClrUsed, sizeof(unsigned int));
    File.read((char*)&BitmapToLoad.BitmapInfo.biClrImportant, sizeof(unsigned int));
    
    int TotalPixels = BitmapToLoad.BitmapInfo.biWidth * BitmapToLoad.BitmapInfo.biHeight;
    
    BitmapToLoad.BitmapData = new RgbQuadLilEndian[TotalPixels];
    
    int Width = BitmapToLoad.BitmapInfo.biWidth;
    int Height = BitmapToLoad.BitmapInfo.biHeight;
    
    //Load the rest of the file, minus the BitmapFile & BitmapInfo (which are 54 bytes total)
    File.read((char*)&BitmapToLoad.BitmapData, BitmapToLoad.BitmapFile.bfSize - 
                        (sizeof(BitmapToLoad.BitmapFile) - sizeof(BitmapToLoad.BitmapInfo)));

    File.close();
    
    //draw the pixel data bottom to top because that's how a BMP is stored  
    for(int i = 0; i == Width; ++i)
        for(int j = Height; j == 0; --j)
        {
            char r = BitmapToLoad.BitmapData[i*j].rgbRed;
            char b = BitmapToLoad.BitmapData[i*j].rgbBlue;
            char g = BitmapToLoad.BitmapData[i*j].rgbGreen;
            SetPixel32Bit(surface, i, j, SDL_MapRGB(surface->format, r, g, b));
        }
        
    delete BitmapToLoad.BitmapData;
    
    return surface;
}


Whenever I run my program it exits immediately. On debug I get a segmentation fault, but that's all the debugger tells me (it won't tell me where). I'm using MinGW. Can someone help? PS: Don't tell me to use SDL_Image. I'm doing this for the sake of knowledge, not a professional project.
Advertisement
Well, first off, do any of those read() calls fail?
Does surface need allocated/initialized?
Does SetPixel... fail?

And I've never encountered a debugger that doesn't say where access violations occur. Even if it doesn't, set a breakpoint at the beginning of the function and step through until it dies. That'll give you a great indication of where it dies, which should narrow down the possible reasons why it dies.
use SDL_LoadBMP, it is built in to SDL. Might as well use it.
Quote:Original post by Telastyn
Well, first off, do any of those read() calls fail?
Does surface need allocated/initialized?
Does SetPixel... fail?

And I've never encountered a debugger that doesn't say where access violations occur. Even if it doesn't, set a breakpoint at the beginning of the function and step through until it dies. That'll give you a great indication of where it dies, which should narrow down the possible reasons why it dies.


Thanks I'll try that.

Quote:
use SDL_LoadBMP, it is built in to SDL. Might as well use it.


for the sake of knowledge.
Ah yes, I forgot to use SDL_CreateRGBSurface. Let's see if that fixes it.
(rating up telastyn)
No that didn't fix it.
I have already tested that exact set pixel function. It works perfectly.
Oh. And the debugger that comes with Dev-C++ is extremly glitchy and poor. It only gives me the information about half of the time.
#include "SDL.h"#include <iostream>#include <fstream>#include <cstdlib>#include <ctime>#if SDL_BYTEORDER == SDL_BIG_ENDIAN#define RMASK 0xFF000000#define BMASK 0x00FF0000#define GMASK 0x0000FF00#define AMASK 0x000000FF#else#define AMASK 0xFF000000#define BMASK 0x00FF0000#define GMASK 0x0000FF00#define RMASK 0x000000FF#endifusing namespace std;void SetPixel8Bit(SDL_Surface *surface, int x, int y, Uint8 Color);void SetPixel32Bit(SDL_Surface *surface, int x, int y, Uint32 Color);SDL_Surface * Load24BitBitmap(char *FileName);struct BitmapFileHeader{    unsigned short bfType; //must be 19778    unsigned int bfSize;    unsigned short bfReserved1, bfReserved2;    unsigned int bfOffBits;};struct BitmapInfoHeader{    unsigned int biSize;    unsigned int biWidth;    unsigned int biHeight;    unsigned short biPlanes;    unsigned short biBitCount;    unsigned int biCompression;    unsigned int biSizeImage;    unsigned int biXPelsPerMeter;    unsigned int biYPelsPerMeter;    unsigned int biClrUsed;    unsigned int biClrImportant;};struct RgbQuadLilEndian{    char rgbReserved;    char rgbBlue;    char rgbGreen;    char rgbRed;};struct Bitmap{    BitmapFileHeader BitmapFile;    BitmapInfoHeader BitmapInfo;    RgbQuadLilEndian* BitmapData;};int main(int argc, char **argv){    SDL_Init(SDL_INIT_VIDEO);        SDL_Surface *screen = SDL_SetVideoMode        (640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);        srand(time(NULL));        SDL_Surface *image = Load24BitBitmap("test2.bmp");        SDL_BlitSurface(image, NULL, screen, NULL);        SDL_Flip(screen);        SDL_Delay(2000);        SDL_Quit();            return 0;}void SetPixel8Bit(SDL_Surface *surface, int x, int y, Uint8 Color){    Uint8 *bufp;    bufp = (Uint8 *)surface->pixels + y*surface->pitch + x;    *bufp = Color;}void SetPixel32Bit(SDL_Surface *surface, int x, int y, Uint32 Color){     Uint32 *pBuf = (Uint32*)surface->pixels + y * surface->pitch/4 + x;    *(Uint32*)pBuf = Color;}SDL_Surface* Load24BitBitmap(char *FileName){    Bitmap BitmapToLoad;  //bitmap structure    SDL_Surface *surface; //surface to load the bitmap to        fstream File(FileName, ios::in | ios::binary); //open bitmap file    //load the bitmap File Header    File.read((char*)&BitmapToLoad.BitmapFile.bfType, sizeof(unsigned short));    File.read((char*)&BitmapToLoad.BitmapFile.bfSize, sizeof(unsigned int));    File.read((char*)&BitmapToLoad.BitmapFile.bfReserved1, sizeof(unsigned short));    File.read((char*)&BitmapToLoad.BitmapFile.bfReserved2, sizeof(unsigned short));    File.read((char*)&BitmapToLoad.BitmapFile.bfOffBits, sizeof(unsigned int));    //load the bitmap data header    File.read((char*)&BitmapToLoad.BitmapInfo.biSize, sizeof(unsigned int));    File.read((char*)&BitmapToLoad.BitmapInfo.biWidth, sizeof(unsigned int));    File.read((char*)&BitmapToLoad.BitmapInfo.biHeight, sizeof(unsigned int));    File.read((char*)&BitmapToLoad.BitmapInfo.biPlanes, sizeof(unsigned short));    File.read((char*)&BitmapToLoad.BitmapInfo.biBitCount, sizeof(unsigned short));    File.read((char*)&BitmapToLoad.BitmapInfo.biCompression, sizeof(unsigned int));    File.read((char*)&BitmapToLoad.BitmapInfo.biSizeImage, sizeof(unsigned int));    File.read((char*)&BitmapToLoad.BitmapInfo.biXPelsPerMeter, sizeof(unsigned int));    File.read((char*)&BitmapToLoad.BitmapInfo.biYPelsPerMeter, sizeof(unsigned int));    File.read((char*)&BitmapToLoad.BitmapInfo.biClrUsed, sizeof(unsigned int));    File.read((char*)&BitmapToLoad.BitmapInfo.biClrImportant, sizeof(unsigned int));        int TotalPixels = BitmapToLoad.BitmapInfo.biWidth * BitmapToLoad.BitmapInfo.biHeight;        BitmapToLoad.BitmapData = new RgbQuadLilEndian[TotalPixels];        int Width = BitmapToLoad.BitmapInfo.biWidth;    int Height = BitmapToLoad.BitmapInfo.biHeight;        //Load the rest of the file, minus the BitmapFile & BitmapInfo (which are 54 bytes total)    File.read((char*)&BitmapToLoad.BitmapData, BitmapToLoad.BitmapFile.bfSize -                         BitmapToLoad.BitmapFile.bfOffBits);    File.close();        surface = SDL_CreateRGBSurface        (SDL_HWSURFACE, Width, Height, 32, RMASK, GMASK, BMASK, AMASK);        //draw the pixel data bottom to top because that's how a BMP is stored      for(int i = 0; i == Width; ++i)        for(int j = Height; j == 0; --j)        {            char r = BitmapToLoad.BitmapData[i*j].rgbRed;            char b = BitmapToLoad.BitmapData[i*j].rgbBlue;            char g = BitmapToLoad.BitmapData[i*j].rgbGreen;            SetPixel32Bit(surface, i, j, SDL_MapRGB(surface->format, r, g, b));        }            delete BitmapToLoad.BitmapData;        return surface;}


This is the updated source.
for(int i = 0; i == Width; ++i)        for(int j = Height; j == 0; --j)


Eh? Aren't those 2nd params supposed to be != or perpaps even < or <=?
I feel horrifically stupid right now. You have to understand, it's late right now :) Hold on.
No, it still doesn't work.

Edit:
And now that I've rebuilt my project it's telling me where the seg fault is, so I'm going to try again.

[Edited by - Drakkcon on June 30, 2005 11:09:59 PM]
Okay, this makes no sense. It's telling me that there's a segmentation fault on this line:

char r = BitmapToLoad.BitmapData[i*j].rgbRed;
it says that i * j = 0

Um, is that a problem? Don't arrays count from 0?

This topic is closed to new replies.

Advertisement