在 C 中使用 ueberzug 在终端中覆盖图像

Overlay image in terminal using ueberzug within C

使用 ueberzug 库,可以在 X11 下的终端 windows 中叠加图像。 该库是用 python 编写的 - 为 bash 和 python.

提供了有关如何使用该库的示例

要在终端中叠加图像,只需 运行 ueberzug layer 然后输入 json 格式的字符串,如 {"action": "add", "x": 0, "y": 0, "identifier": "test", "path": "/tmp/image.jpg"}。这完美无缺。

我想在 C 中调用这个过程。 如果我理解正确,我只需生成一个新进程,然后写入其标准输入,这通常是一项简单的任务。

但是,在我的例子中,我可以看到图像在应用程序终止前闪烁了几分之一秒。这是我的代码:

#include <stdio.h>
#include <stdlib.h>

void run_ueberzug()
{
    FILE *output;
    output = popen("ueberzug layer", "w");

    if (!output)
    {
        fprintf(stderr, "Incorrect parameters or too many files.\n");
        exit(EXIT_FAILURE);
    }
    fprintf(output, "{\"action\": \"add\", \"x\": 0, \"y\": 0, \"identifier\": \"test\", \"path\": \"/tmp/image.jpg\"}\n");
    if (ferror(output))
    {
        fprintf(stderr, "Output to stream failed.\n");
        exit(EXIT_FAILURE);
    }
    if (pclose(output) != 0)
    {
        fprintf(stderr, "Could not run more or other error.\n");
        exit(EXIT_FAILURE);
    } 
}

int main(void)
{
    run_ueberzug();
    return 0;
}

如何解决图片显示不正确的问题? (不只是几分之一秒)

此外,我应该 运行 在单独的线程中吗?目标是能够正确控制 ueberzug 的行为,也就是以编程方式显示图像或 unshow/remove 图像,而不阻塞主应用程序。

为了总结评论,以下解决方案基于您的作品:

  • 通过popen你fork一个进程,创建一个双向管道并在子shell
  • 中启动命令
  • 随后,写入管道,向 ueberzug 发出命令
  • 管道必须 fflushed,否则只有在进程退出时才会传输
  • 如果子 shell 是 killed/quits
  • ,则信号处理程序会捕获 ueberzug 子进程

同时,main 可以继续 运行 您的代码。下面的代码循环显示 3 张图片。

#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

#define ERROR(text,error) do { fprintf(stderr, "ERROR:%s error:%d\n", (text), error); exit(error); } while(0)

static FILE *output = NULL;

void run_ueberzug()
{
    output = popen("/home/hpcraink/.local/bin/ueberzug layer --parser json ", "w");
    if (!output)
        ERROR("Incorrect parameters or too many files", errno);
}

void mysighandler(int signal) {
    int wstatus;
    wait(&wstatus);
    if (pclose(output) != 0)
        ERROR("Could not run more or other error", errno);
}

int main(void)
{
    int i = 0;
    const char * files[] = {
      "img0.jpg",
      "img1.jpg",
      "img2.jpg",
    };
    run_ueberzug(); 
    signal(SIGCHLD, &mysighandler);

    while (1) {
            fprintf(output, "{\"action\": \"remove\", \"identifier\": \"img\"}\n");
            fprintf(output, "{\"action\": \"add\", \"x\": 0, \"y\": 0, \"identifier\": \"img\", \"path\": \"%s\"}\n", files[i]);
            fflush(output);
            i = (i + 1) % (sizeof(files)/sizeof(files[0]));
            sleep(1);
    }

    return EXIT_SUCCESS;
}