2017-05-13 9 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은 멀티미디어 라이브러리이며 실제 이미징 라이브러리는 아닙니다. 당신은 확실히 일 당신이 그런 식으로 작업을 수행 할 수 있지만 정말에 최적화 아니에요 오버 헤드 참여 꽤가있다. 당신은 정말 그냥 픽셀 변환에 의해 픽셀을 수행하려는 경우

그러나, 나는 GPU에 대상 이미지를 렌더링하는 SFML를 사용하는 것이 좋습니다 것입니다. 이렇게하면 다소 간단합니다.

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

와우, 그게 공상이야, 고마워. 나는 shaders 등을 들여다 볼 것이고 더 빠른 것을 볼 것이다. –