2017-05-13 4 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(); 

実際のピクセル操作を行うファイルがもう1つ必要です。 を代わりに使用すると、これを文字列リテラルに入れることができますが、この方法で変更する方が簡単です。代替案として

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; 

そして、かなりあなたが考えることができない何か。このコードはテストされていませんが、動作する必要があります(おそらく1つまたは2つの小さな問題があります)。 SFMLのShaderの例を確認することもできます。

ターゲットとしてsf::RenderTextureを使用している場合は、画面に強制的に描画することなく、新しいイメージにファイルを保存できます。

+0

でした。うわー、おかげさまで、ありがとう。私はシェイダーなどを調べ、より速いものを見ます。 –

関連する問題