How to change, modify, cut and swap pixels from BI

2019-09-01 07:52发布

问题:

I want to modify a bitmap:

  • change (swap) pixel position (for later rectification of fish eye)

  • divide bitmap in sub-bitmaps (e. g. make 4 bitmaps out of 1) (for later texturizing of different GL_QUADS)

For this I need the code how to modify pixels of a bitmap.

The follwing code example works and creates a texture from a file:

HBITMAP hbpInput = (HBITMAP)::LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);

BITMAP bmpOutput;
::GetObject (hbpInput, sizeof (bmpOutput), &bmpOutput);

(...)

glTexImage2D(GL_TEXTURE_2D, 0, 3, bmpOutput.bmWidth, bmpOutput.bmHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bmpOutput.bmBits);

Which code is necessary to get the Bit-Array?

I tried already GetDIBits(), but this does not work für IMAGE (struct) as you surely know :)

Any concrete ideas how to be able to change the pixels' position?

Thank you a lot!

回答1:

The last argument in the following call is the byte array for the pixels:

glTexImage2D(GL_TEXTURE_2D, 0, 3, bmpOutput.bmWidth, bmpOutput.bmHeight,
             0, GL_RGB, GL_UNSIGNED_BYTE, bmpOutput.bmBits);

This means bmpOutput.bmBits points to the first byte in an array containing the following number of bytes:

3 * bmpOutput.bmWidth * bmpOutput.bmHeight

This means 3 bytes per pixel (one each for red, green, blue).

Having said all this, based on your question, it sounds like what you're really looking for is to be able to map different parts of the texture onto different quads. For this, you can use a texture atlas. Use just one texture object, but adjust the texture coordinates for each quad to map to different parts of the texture image.



回答2:

Well, as bitmaps are such simple files, you could just read the header and construct the array/vector of pixels and edit away.

Here's a func i wrote long time ago, tho it's filled with some bad coding habits.

m_imagefile is a basic struct here with important image info such as width, height, bpp, format and the raw byte array.

m_imagefile *loadBMP(char *Filename) {
    FILE        *BMPFile=NULL;
    errno_t     error;
    m_imagefile *IMG=NULL;

    error=fopen_s(&BMPFile, Filename, "rb");
    if(error!=0) {
        return NULL;
    }

    IMG=new m_imagefile;

    GLshort magic=0;

    fseek(BMPFile, 0x00, SEEK_SET);
    fread(&magic, sizeof(GLshort), 1, BMPFile);
    fseek(BMPFile, 0x12, SEEK_SET);
    fread(&IMG->width, sizeof(GLint), 1, BMPFile);
    fseek(BMPFile, 0x16, SEEK_SET);
    fread(&IMG->height, sizeof(GLint), 1, BMPFile);
    fseek(BMPFile, 0x1C, SEEK_SET);
    fread(&IMG->bpp, sizeof(GLshort), 1, BMPFile);

    //First 2 bytes should be 0x424d or "BM" in ASCII
    if(IMG->width == 0 || IMG->height == 0 || !(magic & 0x424D)) {
        fclose(BMPFile);
        delete IMG;
        return NULL;
    }

    //Bitmaps are stored as BGR, not RGB
    if(IMG->bpp==24) {
        IMG->format = GL_BGR_EXT;
    } else if(IMG->bpp==32) {
        IMG->format = GL_BGRA_EXT;
    } else {
        fclose(BMPFile);
        delete IMG;
        return NULL;
    }

    IMG->data=new GLubyte[IMG->height*IMG->width*IMG->bpp/8];
    fseek(BMPFile, 54, SEEK_SET);
    fread(IMG->data, sizeof(GLbyte), IMG->height*IMG->width*IMG->bpp/8, BMPFile);

    fclose(BMPFile);

    return IMG;
 }