如何从BITMAP更改,修改,剪切和交换像素

时间:2011-02-04 14:41:44

标签: c++ opengl image-manipulation

我想修改位图:

  • 更改(交换)像素位置(以便以后修正鱼眼)

  • 在子位图中划分位图(例如,从1开始制作4位图)(以便以后对不同的GL_QUADS进行纹理化)

为此,我需要代码如何修改位图的像素。

以下代码示例可以从文件中创建纹理:

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);

获取Bit-Array需要哪些代码?

我已经尝试过GetDIBits(),但是这对你的IMAGE(struct)不起作用,你肯定知道:)

如何能够改变像素的位置?

非常感谢你!

2 个答案:

答案 0 :(得分:0)

好吧,由于位图是如此简单的文件,你可以只读取标题并构造像素的数组/向量并编辑。

这是我很久以前写的一个功能,它充满了一些糟糕的编码习惯。

m_imagefile是一个基本的结构,包含重要的图像信息,如width,height,bpp,format和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;
 }

答案 1 :(得分:0)

以下调用中的最后一个参数是像素的字节数组:

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

这意味着bmpOutput.bmBits指向包含以下字节数的数组中的第一个字节:

3 * bmpOutput.bmWidth * bmpOutput.bmHeight

这意味着每个像素3个字节(红色,绿色,蓝色各一个)。

说完所有这些,基于你的问题,听起来你真正想要的是能够将纹理的不同部分映射到不同的四边形。为此,您可以使用texture atlas。仅使用一个纹理对象,但调整每个四边形的纹理坐标以映射到纹理图像的不同部分。