2017-05-13 35 views
0

我不得不整天工作以弄清楚如何加載,修改和顯示位圖。這是我的工作計劃(Lubuntu,CodeBlocks 16.01)。我不得不添加這些庫:-lsfml-graphics,-lsfml-window和-lsfml-system到項目>構建選項>鏈接器設置>其他鏈接器選項。任何改進建議?SFML加載,修改,顯示位圖

#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

有什麼理由不直接使用'sf :: Image'嗎?只需存儲'sf :: Image :: getPixelsPtr()'的返回值並使用它來代替'pixarray'。你只需要小心一些生命/鎖定。 – Mario

+0

我試過了,但getPixelsPtr()返回的指針原來是「只讀」的,所以我必須將像素數據放在另一個數組中以更改它們。 –

+0

發現我不得不 –

回答

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作爲目標,則可以將文件保存到新圖像,而不必強制在屏幕上繪製。

+0

哇,這很花哨,謝謝。我會研究着色器等,看看更快。 –