Linux буфер рисования пикселей - PullRequest
0 голосов
/ 20 марта 2020

Проблема достаточно проста, у меня есть код, который генерирует пиксельный буфер. Теперь мне нужно представить этот пиксельный буфер вместо сохранения изображения и последующего его анализа.

Каким было бы решение:

  1. Открыть окно
  2. Заменить все пиксели в этом окне на мои пиксели RGB888

Итак Дальнейшее предложение было следующим: чтобы использовать opengl, создайте буфер вершин для прямоугольника, покрывающего окно, и используйте пиксельный шейдер для рисования ваших пикселей. Что явно не лучший способ поменять пиксельные буферы в окне.

Платформа: Ubuntu 18

Ответы [ 2 ]

1 голос
/ 21 марта 2020

Вы также можете довольно просто отобразить растровые изображения в окне с помощью SFML . На самом деле, он кажется значительно быстрее, чем CImg в моем другом ответе. Я не эксперт в этом, но следующий код делает то, что вам нужно:

// g++ -std=c++11 main.cpp $(pkg-config --libs --cflags sfml-graphics sfml-window)

#include <SFML/Graphics.hpp>
#include <iostream>
#include <cstdint>

int main()
{
    const unsigned width = 1024;
    const unsigned height= 768;

    // create the window
    sf::RenderWindow window(sf::VideoMode(width, height), "Some Funky Title");

    // create a texture
    sf::Texture texture;
    texture.create(width, height);

    // Create a pixel buffer to fill with RGBA data
    unsigned char *pixbuff = new unsigned char[width * height * 4];
    // Create uint32_t pointer to above for easy access as RGBA
    uint32_t * intptr = (uint32_t *)pixbuff;

    // The colour we will fill the window with
    unsigned char red  = 0;
    unsigned char blue = 255;

    // run the program as long as the window is open
    int frame = 0;
    while (window.isOpen())
    {
        // check all the window's events that were triggered since the last iteration of the loop
        sf::Event event;
        while (window.pollEvent(event))
        {
            // "close requested" event: we close the window
            if (event.type == sf::Event::Closed)
                window.close();
        }

        // clear the window with black color
        window.clear(sf::Color::Black);

        // Create RGBA value to fill screen with.
        // Increment red and decrement blue on each cycle. Leave green=0, and make opaque
        uint32_t RGBA;
        RGBA = (red++ << 24) | (blue-- << 16) | 255;
        // Stuff data into buffer
        for(int i=0;i<width*height;i++){
           intptr[i] = RGBA;
        }
        // Update screen
        texture.update(pixbuff);
        sf::Sprite sprite(texture);
        window.draw(sprite);

        // end the current frame
        window.display();
        std::cout << "Frame: " << frame << std::endl;
        frame++;
        if(frame==1000)break;
    }

    return 0;
}

enter image description here

На моей маме c, я достигается следующая частота кадров:

  • 700 кадров в секунду при разрешении 640x480
  • 384 кадров в секунду при разрешении 1024x768

Вы можете / могли создавать и заполнять текстуру без -экран во втором потоке, если вы хотите повысить производительность, но это уже довольно быстро.

Ключевые слова : C ++, обработка изображений, отображение, растровая графика, буфер пикселей, SFML, imshow , простое число

1 голос
/ 21 марта 2020

Вы можете использовать CImg , которая является небольшой, быстрой, современной библиотекой C ++. Это «только заголовок» , поэтому никаких сложных связей или зависимостей.

// http://cimg.eu/reference/group__cimg__tutorial.html

#include <iostream>
#include <string>
#include "CImg.h"

using namespace cimg_library;

int main(int argc,char **argv) {

   const unsigned char white[] = { 255,255,255 };
   const int width  = 320;
   const int height = 240;
   // Create 3-channel RGB image
   CImg<> img(width,height,1,3);

   // Create main window
   CImgDisplay main_window(img,"Random Data",0);
   int frame = 0;

   while (!main_window.is_closed()) {
     // Fill image with random noise
     img.rand(0,255);
     // Draw in frame counter
     std::string text = "Frame: " + std::to_string(frame);
     img.draw_text(10,10,text.c_str(),white,0,1,32);
     main_window.display(img);
     frame++;
     std::cout << "Frame: " << frame << std::endl;
   }
}

Вот оно в действии - качество не самое лучшее, потому что случайные данные плохо сжимаются и переполнение стека имеет Предел изображения 2 МБ. Это хорошо в реальной жизни.

enter image description here

Обратите внимание, что, поскольку я здесь использую X11, команда компиляции должна определить cimg_display, поэтому будет выглядеть что-то вроде:

g++ -Dcimg_display=1 -std=c++11 -I /opt/X11/include -L /opt/X11/lib -lx11 ...

Обратите внимание также, что я использую img.rand() для заполнения изображения данными, вы захотите получить img.data(), который является указателем на пиксельный буфер, а затем memcpy() ваш данные изображения в буфер по этому адресу.

Обратите внимание, что я также сделал кое-что с записью в кадровый буфер непосредственно в другой ответ . Это было в Python, но его легко адаптировать.

...