stefanhaustein / TerminalImageViewer

Small C++ program to display images in a (modern) terminal using RGB ANSI codes and unicode block graphics characters
Other
1.56k stars 111 forks source link

ncurses support for the project #129

Closed MertGunduz closed 12 months ago

MertGunduz commented 1 year ago

Is your feature request related to a problem? Please describe.

Hi @stefanhaustein,


First of all, thanks a lot for creating tiv and this issue is a feature request for for ncurses based TUIs.

I was trying to open images by using tiv in a CLI ncurses-based TUI application.

But whenever I try to open some images with tiv on a ncurses window it doesn't shows the image.

So, in my opinion it would be a great idea to make it also usable in ncurses-based TUIs.

Also, if this sounds like a good idea, I can also work on it. But since the code has no documentation (as far as I know) it is really hard to implement this feature.


Example Code, this will not generate a healthy output.


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

int main() { // Initialize ncurses initscr(); cbreak();

// Check if the terminal supports colors
if (!has_colors()) 
{
    fprintf(stdout, "this terminal does not support colors!\n");
    return EXIT_FAILURE;
}

    start_color();
    init_pair(1, COLOR_BLACK, COLOR_WHITE); // Color for the window
    init_pair(2, COLOR_WHITE, COLOR_BLACK); // Color for the image
    wattron(stdscr, COLOR_PAIR(1));

// Set up tiv command to display an image
char *imageFile = "a92c5191f11b0e544f276011e898294f.png"; // Replace with your image file path
char tivCommand[256];
snprintf(tivCommand, sizeof(tivCommand), "tiv %s", imageFile);

// Display the image using tiv
system(tivCommand);
refresh();

// Wait for a key to close the TUI
getch();

// Clean up
endwin();

return 0;

}


### Describe the solution you'd like

### Creating a .h file

There is a solution we can use, creating a small .h file to handle this problems.

And by doing this, we could actually create a big revolution in the TUI history. It was always a big problem to put functional images to terminals.

#### Some of the ncurses headers:

<hr>

```c
<form.h>: Header file for working with forms in ncurses, which allows you to create interactive forms.

<menu.h>: Header file for creating menus in ncurses.

<panel.h>: Header file for using panels in ncurses, which allows you to manage overlapping windows.

<term.h>: Header file for terminal-related definitions and functions.

For example, we can implement our .h file like tiv.h (for normal output) and tivcurses.h (four ncurses output) to use it as a library.

Describe alternatives you've considered

Adding a new option

Also, writing a new option to tiv (terminal-image-viewer) can be helpful.

tiv --ncurses .*png

For example, by using the above command we can show them in a new window by using ncurses.

It will open a window in ncurses and list the images by using tiv, it will not output to stdout. Instead it will output to the stdscr or specified screen.

Additional context

Support

I can support the project by contributing the features and improving the current code by making it more readable.

Also doxygen or any kind of documenting tool would be helpful for other devs.

aaronliu0130 commented 1 year ago

But whenever I try to open some images with tiv on a ncurses window it doesn't shows the image.

What happens?

Other than the "adding a new option" and better documentation I'm not exactly sure what this means, does specifying the width and height (#37 basically) solve the issue?

Are you recommending the program have easily usable output? If so that might be #52.

P.S.: I've read the code before and quit soon after trying to read emit_image where the action happen. That was some years ago though, and my skills have improved since then. I'll see if I can add some Doxygen.

MertGunduz commented 1 year ago

Error

When I run the code the ncurses TUI opens and I can't see the tiv image output. After closing my TUI app it turns to my normal terminal and shows me the image in a corrupted way. I want tiv to output it to ncurses based TUI, so we have to output tiv to the stdscr or any ncurses-based window.

Also giving a set width doesn't helps with it. I set the width to 32 but didn't helped me to fix the issue.


1 -> running the executable (no image) [NCURSES BASED TUI]

First it opens the ncurses TUI and shows nothing, probably tiv outputs to stdout: image

2 -> closing the executable (corrupted image) [NORMAL TERMINAL]

After the ncurses based TUI app finishes, this happens on the normal terminal: image

MertGunduz commented 1 year ago

Also, about the documentation I meant making the code more readable and modular by using doxygen-like commenting and placing the codes and functions to seperate files.

If I could read the code I would handle this task but it is a very long code and nearly impossible to implement the feature with this way.

And if possible, could you give me some information about the code. What's the Java part do and C++ do?

aaronliu0130 commented 1 year ago

This project used to be coded in Java. Due to how slow that was for such simple tasks Stefan rewrote the project in C++. Currently only the C++ part matters and the Java implementation is deprecated. I understand what you mean about the documentation.

I think what's happening is that ncurses isn't capturing the output. All you did was run the tiv command, which ran in the background.

MertGunduz commented 1 year ago

This project used to be coded in Java. Due to how slow that was for such simple tasks Stefan rewrote the project in C++. Currently only the C++ part matters and the Java implementation is deprecated. I understand what you mean about the documentation.

I think what's happening is that ncurses isn't capturing the output. All you did was run the tiv command, which ran in the background.

I got it, thanks a lot. Do you think is there a way to output it to a ncurses window?

aaronliu0130 commented 1 year ago

https://stackoverflow.com/questions/41884266/system-output-in-ncurses says

The popen() function can be used to execute a command and to read its output programatically.

MertGunduz commented 1 year ago

https://stackoverflow.com/questions/41884266/system-output-in-ncurses says

The popen() function can be used to execute a command and to read its output programatically.

I've tried it doing with popen function, it gives me the ansi escape codes directly but I can't process them in ncurses terminal. Probably ncurses can't interprete the ANSI Escape Codes.

So I have to process them directly and output them in ncurses. This is at least a solution for my case.

Example ANSI Escape Code: ^[[48;2;23;19;16m


The code I've tried:

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

int main() 
{
    initscr();
    cbreak();
    noecho();
    curs_set(0);
    keypad(stdscr, TRUE);

    FILE *pipe = popen("tiv -w 16 photo-1608848461950-0fe51dfc41cb.jpeg", "r");
    char buffer[2048];

    while (fgets(buffer, 2047, pipe) != NULL)
    {
        for (int i = 0; i < strlen(buffer); i++)
        {
            printw("%s", buffer);
        }
        getch();
    }

    getch();
    endwin();
    return 0;
}

Output:

Screenshot from 2023-09-10 04-57-55

aaronliu0130 commented 1 year ago

Well, the only solution to that on our end I can think of is to separate tiv into a library. Great to hear that it worked.