我必须整天工作以弄清楚如何加载,修改和显示位图。这是我的工作计划(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;
}
答案 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
作为目标,则可以将文件保存到新图像,而不必强制在屏幕上绘制。