SFML加载、修改、显示位图

2024-03-23

我必须整天工作才能弄清楚如何加载、修改和显示位图。这是我的工作程序(Lubuntu,CodeBlocks 16.01)。我必须将这些库添加到项目>构建选项>链接器设置>其他链接器选项中:-lsfml-graphics、-lsfml-window和-lsfml-system。有什么改进建议吗?

#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;
}

首先,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();

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

着色器文件系统

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;

还有几乎所有您能想到的其他东西。请注意,此代码未经测试,但应该可以工作(可能存在一两个小问题)。您还可以检查 SFMLShader示例以获取更多信息。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SFML加载、修改、显示位图 的相关文章

随机推荐