【问题标题】:SFML load, modify, display bitmapSFML 加载、修改、显示位图
【发布时间】:2017-05-13 16:05:08
【问题描述】:

我不得不整天工作以弄清楚如何加载、修改和显示位图。这是我的工作程序(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;
}

【问题讨论】:

  • 您有什么理由不直接使用sf::Image 吗?只需存储sf::Image::getPixelsPtr() 的返回值并使用它来代替pixarray。你只需要对生命周期/锁定有点小心。
  • 我试过了,但是 getPixelsPtr() 返回的指针原来是“只读的”,所以我不得不将像素数据放在另一个数组中来更改它们。
  • 发现我必须这样做

标签: bitmap sfml


【解决方案1】:

首先,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 的 Shader 示例以获取更多信息。

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

【讨论】:

  • 哇,太棒了,谢谢。我会研究着色器等,看看什么更快。
猜你喜欢
  • 2015-04-28
  • 1970-01-01
  • 2013-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-24
  • 1970-01-01
  • 2017-06-08
相关资源
最近更新 更多