Простой способ отобразить непрерывно обновляющее изображение в C/Linux

Это всегда - хорошая идея посмотреть Google Collections Library для такого рода вещи. В этом случае Мультимножество добьется цели:

Multiset bag = Multisets.newHashMultiset();
String word = "foo";
bag.add(word);
bag.add(word);
System.out.println(bag.count(word)); // Prints 2

существуют подобные Карте методы для итерации по ключам/записям, и т.д. Внутренне реализация в настоящее время использует HashMap, таким образом, Вы не понесете расходы упаковки.

9
задан tkw954 7 September 2009 в 23:34
поделиться

4 ответа

If all you want to do is display the data (ie no need for a GUI), you might want to take a look at SDL: It's straight-forward to create a surface from your pixel data and then display it on screen.

Inspired by Artelius' answer, I also hacked up an example program:

#include <SDL/SDL.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>

#define WIDTH 256
#define HEIGHT 256

static _Bool init_app(const char * name, SDL_Surface * icon, uint32_t flags)
{
    atexit(SDL_Quit);
    if(SDL_Init(flags) < 0)
        return 0;

    SDL_WM_SetCaption(name, name);
    SDL_WM_SetIcon(icon, NULL);

    return 1;
}

static uint8_t * init_data(uint8_t * data)
{
    for(size_t i = WIDTH * HEIGHT * 3; i--; )
        data[i] = (i % 3 == 0) ? (i / 3) % WIDTH :
            (i % 3 == 1) ? (i / 3) / WIDTH : 0;

    return data;
}

static _Bool process(uint8_t * data)
{
    for(SDL_Event event; SDL_PollEvent(&event);)
        if(event.type == SDL_QUIT) return 0;

    for(size_t i = 0; i < WIDTH * HEIGHT * 3; i += 1 + rand() % 3)
        data[i] -= rand() % 8;

    return 1;
}

static void render(SDL_Surface * sf)
{
    SDL_Surface * screen = SDL_GetVideoSurface();
    if(SDL_BlitSurface(sf, NULL, screen, NULL) == 0)
        SDL_UpdateRect(screen, 0, 0, 0, 0);
}

static int filter(const SDL_Event * event)
{ return event->type == SDL_QUIT; }

#define mask32(BYTE) (*(uint32_t *)(uint8_t [4]){ [BYTE] = 0xff })

int main(int argc, char * argv[])
{
    (void)argc, (void)argv;
    static uint8_t buffer[WIDTH * HEIGHT * 3];

    _Bool ok =
        init_app("SDL example", NULL, SDL_INIT_VIDEO) &&
        SDL_SetVideoMode(WIDTH, HEIGHT, 24, SDL_HWSURFACE);

    assert(ok);

    SDL_Surface * data_sf = SDL_CreateRGBSurfaceFrom(
        init_data(buffer), WIDTH, HEIGHT, 24, WIDTH * 3,
        mask32(0), mask32(1), mask32(2), 0);

    SDL_SetEventFilter(filter);

    for(; process(buffer); SDL_Delay(10))
        render(data_sf);

    return 0;
}
19
ответ дан 4 December 2019 в 06:30
поделиться

Я бы тоже порекомендовал SDL. Тем не менее, вам нужно кое-что понять, если вы хотите писать быстрые программы, и это не самое простое решение.

Я бы предложил эту статью О'Рейли в качестве отправной точки.

Но я остановлюсь на наиболее важных моментах с точки зрения вычислений.

Двойная буферизация

То, что SDL называет «двойной буферизацией», обычно называется переворачиванием страниц .

Это в основном означает что на видеокарте есть два блока памяти, называемые страницами , каждый из них достаточно велик, чтобы вместить данные на экране. Один становится видимым на мониторе, другой доступен для вашей программы. Когда вы вызываете SDL_Flip () , графическая карта меняет свои роли (т. Е. Видимая становится доступной для программы, и наоборот).

Альтернативой является замена ролей ] страниц, вместо этого скопируйте данные со страницы, доступной для программы, на страницу монитора (с помощью SDL_UpdateRect () ).

Переворот страницы выполняется быстро, но имеет недостаток : после переворачивания страницы ваша программа будет представлена ​​с буфером, содержащим пиксели, полученные 2 кадра назад. Это нормально, если вам нужно пересчитывать каждый пиксель в каждом кадре.

Однако, если вам нужно изменять только небольшие области на экране в каждом кадре, а остальная часть экрана не нуждается в изменении, тогда UpdateRect может быть лучшим способом (см. также: SDL_UpdateRects () ).

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

Обратите внимание, что если ваше графическое оборудование не поддерживает переворачивание страниц, SDL будет изящно использовать для вас другой метод.

Программное обеспечение / оборудование / OpenGL

Это еще один вопрос, с которым вы сталкиваетесь. По сути, программные поверхности находятся в ОЗУ, аппаратные поверхности находятся в видеопамяти, а поверхности OpenGL управляются магией OpenGL.

В зависимости от вашего оборудования, ОС и версии SDL, программное изменение пикселей аппаратной поверхности может включать в себя МНОГОЧИСЛЕННОЕ копирования памяти (VRAM в RAM, а потом обратно!). Вы же не хотите, чтобы это происходило каждый кадр. В таких случаях программные поверхности работают лучше. Но тогда вы не можете воспользоваться ни двойной буферизацией, ни аппаратным ускорением блитов.

Блиты - это блочные копии пикселей с одной поверхности на другую. Это хорошо работает, если вы хотите нарисовать множество одинаковых значков на поверхности. Не очень полезно, если вы создаете карту температуры.

OpenGL позволяет вам делать гораздо больше с вашим графическим оборудованием (для начала, 3D-ускорение). Современные видеокарты обладают большой вычислительной мощностью, но их довольно сложно использовать, если вы не делаете 3D-симуляцию. Написание кода для графического процессора возможно, но оно сильно отличается от обычного C.

Demo

Вот небольшая демонстрационная программа SDL, которую я сделал. Это не должно быть идеальным примером и может иметь некоторые проблемы с переносимостью. (Я постараюсь отредактировать лучшую программу в этом посте, когда у меня будет время.)

#include "SDL.h"
#include <assert.h>
#include <math.h>

/* This macro simplifies accessing a given pixel component on a surface. */
#define pel(surf, x, y, rgb) ((unsigned char *)(surf->pixels))[y*(surf->pitch)+x*3+rgb]


int main(int argc, char *argv[])
{
    int x, y, t;

    /* Event information is placed in here */
    SDL_Event event;

    /* This will be used as our "handle" to the screen surface */
    SDL_Surface *scr;

    SDL_Init(SDL_INIT_VIDEO);

    /* Get a 640x480, 24-bit software screen surface */
    scr = SDL_SetVideoMode(640, 480, 24, SDL_SWSURFACE);
    assert(scr);

    /* Ensures we have exclusive access to the pixels */
    SDL_LockSurface(scr);

    for(y = 0; y < scr->h; y++)
        for(x = 0; x < scr->w; x++)
        {
            /* This is what generates the pattern based on the xy co-ord */
            t = ((x*x + y*y) & 511) - 256;
            if (t < 0)
                t = -(t + 1);

            /* Now we write to the surface */
            pel(scr, x, y, 0) = 255 - t; //red
            pel(scr, x, y, 1) = t; //green
            pel(scr, x, y, 2) = t; //blue
        }
    SDL_UnlockSurface(scr);

    /* Copies the `scr' surface to the _actual_ screen */
    SDL_UpdateRect(scr, 0, 0, 0, 0);


    /* Now we wait for an event to arrive */
    while(SDL_WaitEvent(&event))
    {
        /* Any of these event types will end the program */
        if (event.type == SDL_QUIT
         || event.type == SDL_KEYDOWN
         || event.type == SDL_KEYUP)
            break;
    }
    SDL_Quit();
    return EXIT_SUCCESS;
}
9
ответ дан 4 December 2019 в 06:30
поделиться

вы можете использовать:

richTextBox1.SelectionColor = Color.Yellow;
richTextBox1.SelectionBackColor = Color.Blue;

для выбора набора текста:

richTextBox1.SelectionStart = text_position_in_editor (caret position)

richTextBox1.SelectionLength = text_length

затем установить SelectionColor ... (просмотреть все свойства, начиная с Selection ...)

Или вы можете установить непосредственно свойство Rtf (или richTextBox1.SelectedRtf) , которое содержит информацию о форматировании.

Введите немного текст в WordPad, измените его форматирование, который часто используется для программирования игр. Учитывая, что вы хотите использовать высокую частоту кадров, я бы подумал о чем-то в этом роде. GTK и подобные не предназначены в первую очередь для быстрого обновления дисплеев.

2
ответ дан 4 December 2019 в 06:30
поделиться

Графический интерфейс - это колесо, которое регулярно изобретают заново, и нет причин не использовать фреймворк.

Я бы рекомендовал использовать либо QT4, либо wxWidgets. Если вы используете Ubuntu, GTK + будет достаточно, поскольку он взаимодействует с GNOME и может быть более удобным для вас (QT и wxWidgets требуют C ++).

Посмотрите GTK + , QT и wxWidgets .

Вот руководства для всех 3:

7
ответ дан 4 December 2019 в 06:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: