В поисках руководства по отображению изображений с веб-камеры с помощью GTK + и Cairo в C - PullRequest
0 голосов
/ 05 апреля 2019

В этом вопросе я в основном ищу советы и рекомендации по общему пониманию некоторых концепций рисования с GTK + и Cairo на языке Си (ИМО, информация по теме довольно скудная, а также мой опыт в действительно скромном).

Я пишу какое-то приложение для домашних животных, которое захватывает кадры с веб-камеры и отображает их в окне GTK.Мое приложение работает, но есть некоторые моменты, которые мне не совсем понятны.


Общий процесс:

У меня есть кадр веб-камеры в виде массива байтов mmapedс устройства веб-камеры в оперативную память моего приложения.Поэтому, когда захватывается другой кадр, получается массив длиной 640 * 480 * 3 байта, который обозначается как формат RGB24.После некоторого поиска он выглядит так, чтобы отображать его в окне GTK. Мне нужно создать объект, называемый областью рисования, с помощью gtk_drawing_area_new (), добавить обратный вызов «draw» и выполнить там «рисование» в назначенном обратном вызове.Итак, согласно Каиру «рисование» - это процесс применения «источника» к «месту назначения».Я предполагаю, что у меня уже есть источник - моя веб-камера mmaped пикселей, но, похоже, мне нужно использовать какой-то «источник», который Каир способен понять.Я нашел кандидата:

cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 640, 480);

Как я вижу, этот вызов создает некоторый Каирский приемлемый объект, который по пути выделяет буфер в памяти моего приложения, который я могу получить, используя:

unsigned char* surface_data = cairo_image_surface_get_data(surface);

В соответствии с документацией это буфер длиной 640x480x4 байта, который на небольших порядковых порядках должен быть заполнен отформатированными данными пикселей BGRA.Затем я должен изменить свои исходные пиксели веб-камеры для КАЖДОГО кадра, снятого следующим образом:

for (size_t idx_src=0, idx_dst=0; idx_src<640*480*3; idx_dst+=4, idx_src+=3) {
    surface_data[idx_dst] = image[idx_src+2]; //B [3rd pos -> 1st pos]
    surface_data[idx_dst+1] = image[idx_src+1]; //G [no change]
    surface_data[idx_dst+2] = image[idx_src]; //R [1st pos -> 3rd pos]
}

После этого я должен сделать «рисование» с помощью:

cairo_set_source_surface(cr, surface, 0, 0);
cairo_paint(cr);

Итак, вопросы:

  1. Это то, что должно быть сделано для выполнения поставленной задачи, или я что-то здесь упускаю полностью?
  2. Что меня смущает, так это то, что мне нужно переставить исходные пиксели веб-камеры для КАЖДОГО захваченного кадра (это, вероятно, потребляет некоторое время процессора, может быть ограничивающим фактором для захвата в разрешении HD при высокой частоте кадров).Есть какой-то другой способ?
  3. Давайте предположим, что я каким-то образом получаю пиксели с веб-камеры в формате, соответствующем Каиру, например, 640x480x4 отформатированных байтов BGRA.Есть ли способ «обернуть» эти данные в какой-нибудь приемлемый для Каира объект, чтобы исключить переупорядочение элементов изображения?
  4. Есть еще какие-нибудь мысли, которые я должен был рассмотреть?

Спасибо за внимание.

1 Ответ

1 голос
/ 06 апреля 2019

Для большинства ваших вопросов: Cairo поддерживает только некоторые форматы изображений. Поскольку ваши данные поступают в другом формате, вам придется конвертировать их. Все это копирование, вероятно, будет слишком медленным. Чтобы это работало с приемлемой скоростью, вам понадобится другой подход. Нет, у меня нет никаких полезных предложений здесь.

Бесполезно было бы: Есть ли какой-нибудь пример для этой веб-камеры, на который вы могли бы взглянуть?

Давайте предположим, что я каким-то образом получаю пиксели с веб-камеры в формате, соответствующем Каиру, например. 640x480x4 байтов в формате BGRA. Есть ли способ «обернуть» эти данные в какой-нибудь приемлемый для Каира объект, чтобы исключить изменение порядка пикселей?

Да. cairo_image_surface_create_for_data.

...