Error withit
Error withit

Reputation: 1

Getting incorrect width when decoding bitmap

I have an error with my source code which basically causes bitmap images to appear too wide. for example it will print the width and the height and the height is perfect (256) and the width should also be 256 but the programs says it is billions of pixels wide and it is different everytime. here is the source code.

#include "glob.h"

/* Image type - contains height, width, and data */
struct Image {
    unsigned long sizeX;
    unsigned long sizeY;
    char *data;
};
typedef struct Image Image;

int ImageLoad(char *filename, Image *image) {
    FILE *file;
    unsigned long size;                 // size of the image in bytes.
    unsigned long i;                    // standard counter.
    unsigned short int planes;          // number of planes in image (must be 1)
    unsigned short int bpp;             // number of bits per pixel (must be 24)
    char temp;                          // temporary color storage for bgr-rgb conversion.

    // make sure the file is there.
    if ((file = fopen(filename, "rb"))==NULL){
        printf("bitmap Not Found : %s\n",filename);
        return 0;
    }

    // seek through the bmp header, up to the width/height:
    fseek(file, 18, SEEK_CUR);

    // read the width
    if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
        printf("Error reading width from %s.\n", filename);
        return 0;
    }
    printf("Width of %s: %lu\n", filename, image->sizeX);

    // read the height
    if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
        printf("Error reading height from %s.\n", filename);
        return 0;
    }
    printf("Height of %s: %lu\n", filename, image->sizeY);

    // calculate the size (assuming 24 bits or 3 bytes per pixel).
    size = image->sizeX * image->sizeY * 3;

    // read the planes
    if ((fread(&planes, 2, 1, file)) != 1) {
        printf("Error reading planes from %s.\n", filename);
        return 0;
    }
    if (planes != 1) {
        printf("Planes from %s is not 1: %u\n", filename, planes);
        return 0;
    }

    // read the bpp
    if ((i = fread(&bpp, 2, 1, file)) != 1) {
        printf("Error reading bpp from %s.\n", filename);
        return 0;
    }
    if (bpp != 24) {
        printf("Bpp from %s is not 24: %u\n", filename, bpp);
        return 0;
    }

    // seek past the rest of the bitmap header.
    fseek(file, 24, SEEK_CUR);

    // read the data.
    image->data = (char *) malloc(size);
    if (image->data == NULL) {
        printf("Error allocating memory for color-corrected image data\n");
        return 0;
    }

    if ((i = fread(image->data, size, 1, file)) != 1) {
        printf("Error reading image data from %s.\n", filename);
        return 0;
    }

    for (i=0; i<size; i+=3) { // reverse all of the colors. (bgr -> rgb)
        temp = image->data[i];
        image->data[i] = image->data[i+2];
        image->data[i+2] = temp;
    }

    // we're done.
    return 0;
}

// Load Bitmaps And Convert To Textures
void glob::LoadGLTextures() {
    // Load Texture
    Image *image1;

    // allocate space for texture
    image1 = (Image *) malloc(sizeof(Image));
    if (image1 == NULL) {
        printf("(image1 == NULL)\n");
        exit(0);
    }

    ImageLoad("data/textures/NeHe.bmp", image1);

    // Create Texture
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);   // 2d texture (x and y size)

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture

    // 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
    // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
    glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
};

glob.h is this:

#ifndef GLOB_H_INCLUDED
#define GLOB_H_INCLUDED

#include <iostream>
#include <stdlib.h>
#include <stdio.h>      // Header file for standard file i/o.

#include <GL/glx.h>    /* this includes the necessary X headers */
#include <GL/gl.h>
//#include <GL/glut.h>    // Header File For The GLUT Library
//#include <GL/glu.h>   // Header File For The GLu32 Library

#include <X11/X.h>    /* X11 constant (e.g. TrueColor) */
#include <X11/keysym.h>

class glob {
    bool Running;
    GLuint texture; //make an array when we start using more then 1
    Display     *dpy;
    Window       win;
    XEvent       event;
    GLboolean    doubleBuffer;
    GLboolean    needRedraw;
    GLfloat      xAngle, yAngle, zAngle;
    float        camera_x, camera_y, camera_z;
public:
    glob();
    int OnExecute();
public:
    int init(int argc, char **argv);
    void LoadGLTextures();
    void OnEvent();
    void redraw(void);
};

#endif // GLOB_H_INCLUDED

can any body help me fix this problem?

Upvotes: 0

Views: 1496

Answers (1)

Adrian McCarthy
Adrian McCarthy

Reputation: 47962

Lots of things could be going wrong.

If it's a very old file, it could have a BITMAPCOREHEADER which has size fields that are only 2 bytes each.

Is your machine little endian? BMP files are stored little endian.

Note that height may be negative, (which implies it's a top-down bitmap instead of a bottom up one). If you interpret a small negative number as an unsigned 32-bit int, you'll see values in the billions.

Also, your seek to the actual pixel data assumes that it starts right after the bitmap header. This is common, but not required. The file header contains the offset of the actual pixel data. (Microsoft documentation calls this the "bitmap bits" or the "color data".)

I recommend doing a hex dump of the beginning of your file and step through it by hand to make sure all your offsets and assumptions are correct. Feel free to paste the beginning of a hex dump into your question.

Are you on Windows? Can you just call LoadImage?

Upvotes: 2

Related Questions