init ncurses version
authorLaurent Mazet <mazet@softndesign.org>
Thu, 3 Oct 2024 06:50:48 +0000 (08:50 +0200)
committerLaurent Mazet <mazet@softndesign.org>
Thu, 3 Oct 2024 06:50:48 +0000 (08:50 +0200)
makefile
ndisplay.c [new file with mode: 0644]

index 7c570fa68e99359546738c7a4b2a0d852b9fcc25..f1694f2547a6b6d13752ca98b93885361bf78b73 100644 (file)
--- a/makefile
+++ b/makefile
@@ -11,7 +11,7 @@ INCLUDES =
 #OFLAGS += -minline-all-stringops -fsingle-precision-constant
 #OFLAGS += -malign-double
 CFLAGS += -W -Wall -Wextra -g
-#CFLAGS += -std=c99 -D_XOPEN_SOURCE=500
+CFLAGS += -std=c99 -D_XOPEN_SOURCE=500
 CFLAGS += $(OFLAGS) $(INCLUDES) $(OPTIONS)
 LDFLAGS += -g $(LDOPTS) $(OPTIONS)
 
@@ -35,7 +35,7 @@ endif
 # Targets
 
 ALLEXE  =
-ALLEXE += display
+ALLEXE += display ndisplay
 
 SHELL = bash
 
diff --git a/ndisplay.c b/ndisplay.c
new file mode 100644 (file)
index 0000000..fae2fdd
--- /dev/null
@@ -0,0 +1,220 @@
+/* depend: */
+/* cflags: */
+/* linker: color.o debug.o image.o pnm.o -lncursesw */
+/* doslnk: color.o debug.o image.o pnm.o -lpdc~2 */
+/* winlnk: color.o debug.o image.o pnm.o -lpdcursesw */
+
+#include <curses.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "color.h"
+#include "debug.h"
+#include "image.h"
+#include "pnm.h"
+
+#define min(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
+
+#define KEY_ESC 0x1b
+
+/* static variables */
+char *progname = NULL;
+char *version = "0.1";
+
+int colormap = 2;
+float gf[3] = { 1.0f, 1.0f, 1.0f };
+int mode = 0;
+
+char *help =
+    "<i> Move up\n"
+    "<j> Move left\n"
+    "<k> Move down\n"
+    "<l> Move right\n"
+    "<q> Quit\n"
+    ;
+
+int usage (int ret)
+{
+    FILE *fd = ret ? stderr : stdout;
+    fprintf (fd, "usage: %s [-g gamma] [-h] [-t|-w] [-v int] <file>\n", progname);
+    fprintf (fd, " -g: gamma correction (%.1f:%.1f:%.1f)\n", gf[0], gf[1], gf[2]);
+    fprintf (fd, " -h: help message\n");
+    fprintf (fd, " -t: thin mode (%s)\n", (mode == 0) ? "on" : "off");
+    fprintf (fd, " -v: verbose level (%d)\n", verbose);
+    fprintf (fd, " -w: wide mode (%s)\n", (mode == 1) ? "on" : "off");
+    fprintf (fd, "%s version %s\n", progname, version);
+
+    return ret;
+}
+
+/* main function */
+int main (int argc, char *argv[])
+{
+    char *filename = NULL;
+
+    /* get basename */
+    char *pt = progname = argv[0];
+    while (*pt) {
+        if ((*pt == '/') || (*pt == '\\')) {
+           progname = pt + 1;
+        }
+        pt++;
+    }
+
+    /* process argument */
+    while (argc-- > 1) {
+        char *arg = *(++argv);
+        if (arg[0] != '-') {
+            filename = arg;
+            continue;
+        }
+        char c = arg[1];
+        switch (c) {
+        case 'g':
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg == NULL) {
+                VERBOSE (ERROR, fprintf (stderr, "%s: no gamma specified\n", progname));
+                return usage (1);
+            }
+            gf[0] = strtof (arg, &pt);
+            if (*pt == '\0') {
+                gf[1] = gf[2] = gf[0];
+            } else if (*pt == ':') {
+                gf[1] = strtof (pt + 1, &pt);
+                if (*pt == ':') {
+                    gf[2] = strtof (pt + 1, &pt);
+                } else {
+                    gf[2] = 0;
+                }
+            } else {
+                gf[1] = gf[2] = 0;
+            }
+            break;
+        case 't':
+            mode = 0;
+            break;
+        case 'v':
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg == NULL) {
+                VERBOSE (ERROR, fprintf (stderr, "%s: missing verbose level\n", progname));
+                return usage (1);
+            }
+            verbose = atoi (arg);
+            break;
+        case 'w':
+            mode = 1;
+            break;
+        case 'h':
+        default:
+            return usage (c != 'h');
+        }
+    }
+
+    /* check */
+    if ((colormap < 0) || (colormap > 3)) {
+        VERBOSE (ERROR, fprintf (stderr, "incorrect colormap (%d)\n", colormap));
+        return 1;
+    }
+    if ((gf[0] <= 0) || (gf[1] <= 0) || (gf[2] <= 0)) {
+        VERBOSE (ERROR, fprintf (stderr, "incorrect gamma (%.1f:%.1f;%.1f)\n", gf[0], gf[1], gf[2]));
+        return 1;
+    }
+    if (filename == NULL) {
+        VERBOSE (ERROR, fprintf (stderr, "no file specified\n"));
+        return 1;
+    }
+
+    /* main process */
+    image_t *image = readpnm (filename);
+
+    /* init curses window */
+    initscr ();
+    noecho ();
+    cbreak ();
+    nonl ();
+    keypad (stdscr, TRUE);
+    curs_set (0);
+    start_color ();
+
+    /* cursor definition */
+    int xcursor = 0;
+    int ycursor = 0;
+
+    /* init colormap */
+    int c;
+    for (c = 0; c < 256; c++) {
+        init_pair (c, 0, c);
+    }
+
+    /* event loop */
+    int stop = 0;
+    while (!stop) {
+
+        int width = min (image->width - xcursor, COLS);
+        int height = min (image->height - ycursor, LINES);
+        int x, y;
+        for (y = 0; y < height; y++) {
+            for (x = 0; x < width; x++) {
+
+                int ind = (x + xcursor) + image->width * (y + ycursor);
+                color_t *color = findcolor (image->red[ind], image->green[ind], image->blue[ind], colormap);
+                //color_t *color = findcolor (correction (image->red[ind], gf[0]), correction (image->green[ind], gf[1]), correction (image->blue[ind], gf[2]), colormap);
+                attron (COLOR_PAIR (color->code));
+                
+                move (y, x);
+                cchar_t tmp;
+                wchar_t tmp_wchar[2] = {0};
+                tmp_wchar[0] = (wchar_t) ' ';
+                setcchar (&tmp, tmp_wchar, A_NORMAL, 0, NULL);
+                add_wch (&tmp);
+            }
+        }
+        refresh ();
+        attron (COLOR_PAIR (0));
+
+        switch (getch ()) {
+        case KEY_UP:
+        case 'i':
+            if (image->height - ycursor > LINES) {
+                ycursor--;
+            }
+            break;
+        case KEY_LEFT:
+        case 'j':
+            if (image->width - xcursor > COLS) {
+                xcursor--;
+            }
+            break;
+        case KEY_DOWN:
+        case 'k':
+            if (ycursor < 0) {
+                ycursor++;
+            }
+            break;
+        case KEY_RIGHT:
+        case 'l':
+            if (xcursor < 0) {
+                xcursor++;
+            }
+            break;
+        case KEY_ESC:
+        case 'q':
+            stop = 1;
+            break;
+        }
+    }
+
+    /* cleaning before quiting */
+    endwin ();
+    freeimage (image);
+
+    return 0;
+}
+
+/* test: ndisplay.exe -h | grep usage */
+/* test: ndisplay.exe -s 2>&1 | grep 'no scale' */
+/* test: ndisplay.exe -s 4 2>&1 | grep incorrect */
+/* test: ndisplay.exe -v 2>&1 | grep missing */
+/* test: ndisplay.exe _ 2>&1 | grep invalid */
+
+/* vim: set ts=4 sw=4 et: */