SFML加载,修改,显示位图

时间:2017-05-13 16:05:08

标签: bitmap sfml

我必须整天工作以弄清楚如何加载,修改和显示位图。这是我的工作计划(Lubuntu,CodeBlocks 16.01)。我不得不添加这些库:-lsfml-graphics,-lsfml-window和-lsfml-system to project>构建选项>链接器设置>其他链接器选项。有任何改进建议吗?

#include <SFML/Graphics.hpp>

using namespace std;
using namespace sf;

struct pix {
    unsigned char r;  // could use Uint8
    unsigned char g;
    unsigned char b;
    unsigned char t;
};

// globals

pix pixarray[640][480];
Texture tex;
Sprite spr;

// functions

void loadbitmap();
void modifybitmap();
void displaybitmap();

int main() {

    RenderWindow window(VideoMode(640, 480), "Modify Bitmap");

    loadbitmap();
    modifybitmap();
    displaybitmap();

    while (window.isOpen()) {

        Event event;
        while (window.pollEvent(event)) {

            if (event.type == Event::Closed)
                window.close();
        }

        window.clear();

        window.draw(spr);

        window.display();
    }

    return 0;
}

//-------------------------------------------------------

void loadbitmap() {

    const unsigned char *pixptr;
    Image img;
    int i, j;

    img.loadFromFile("pic.bmp");
    pixptr = img.getPixelsPtr();   // notice its Pixels not Pixel

    // pixptr is read only, move pixels to your array

    for (i = 0; i < 640; ++i) {
        for (j = 0; j < 480; ++j) {
            pixarray[i][j].r = *pixptr++;
            pixarray[i][j].g = *pixptr++;
            pixarray[i][j].b = *pixptr++;
            pixarray[i][j].t = 255;
            pixptr++;
        }
    }
    return;
}

//---------------------------------------------------------

void modifybitmap() {

// turn up red in top half of your array

    int i, j;

    for (i = 0; i < 320; ++i) {
        for (j = 0; j < 480; ++j) {
            pixarray[i][j].r = 255;
        }
    }
    return;
}

//-------------------------------------------------------------

void displaybitmap() {

    Image img;
    unsigned char *ptr1;

    ptr1 = &pixarray[0][0].r;  // point to first byte

    img.create(640, 480, ptr1);
    tex.loadFromImage(img);
    spr.setTexture(tex);

    return;
}

1 个答案:

答案 0 :(得分:2)

首先,SFML是一个多媒体库,没有真正的成像库。你当然可以按照你的方式做事,但它并没有真正优化,并且涉及到相当多的开销。

但是,如果您真的只想逐像素转换,我建议使用SFML在GPU上渲染目标图像。这样做很简单:

sf::Texture source;
sf::Sprite sprite;
sf::Shader shader;

// I'll be skipping error checking for simplicity

// Load the shaders (see below)
shader.loadFromFile("shader.fs", sf::Shader::Fragment);

// Tell the shader to use the current texture (i.e. the one bound to the srite)
// This name has to match the one in the shader code; you can bind multiple textures, e.g. for blending
shader.setUniform("texture", sf::Shader::CurrentTexture);

// Load the image
sourceImage.loadFromFile("pic.bmp");

// Assign the texture
sprite.setTexture(sourceImage, true);

// Draw the sprite using the shader
// 'target' can be a 'sf::RenderWindow' or 'sf::RenderTexture'
target.clear();
target.draw(sprite, shader);
target.display();

您需要一个额外的文件,它具有您的实际像素操作。 作为替代方案,您可以将其放入字符串文字中,但这样更容易修改。

<强> shader.fs

uniform sampler2D texture;

in vec2 tex_coord;

void main()
{
    // Get this pixel's color
    vec4 pixel = gl_TexCoord[0].xy;

    // Let's set 'red' to full (i.e. 255/1.0)
    pixel.r = 1.0;

    // Return the pixel color
    gl_FragColor = pixel;
}

作为替代方案,您当然也可以交换绿色和蓝色通道:

float t = pixel.g;
pixel.g = pixel.b;
pixel.b = t;

几乎任何你能想到的东西。请注意,此代码未经测试,但应该有效(可能有一两个小问题)。您还可以查看SFML的着色器示例以获取更多信息。

如果您使用sf::RenderTexture作为目标,则可以将文件保存到新图像,而不必强制在屏幕上绘制。