expand and shrink image
authorLaurent Mazet <mazet@softndesign.org>
Sun, 6 Oct 2024 21:57:27 +0000 (23:57 +0200)
committerLaurent Mazet <mazet@softndesign.org>
Sun, 6 Oct 2024 22:06:07 +0000 (00:06 +0200)
image.c
image.h
ndisplay.c

diff --git a/image.c b/image.c
index 72340845a1b716ac366aee1f554f59d47b03b75d..45d1aec5425fe962f7d4d3c1c80e6435c1916776 100644 (file)
--- a/image.c
+++ b/image.c
@@ -40,4 +40,56 @@ float correction (float value, float factor)
     return powf (value, 1. / factor);
 }
 
+image_t *expandimage (image_t *image, int scale)
+{
+    image_t *nimage = newimage (image->width * scale, image->height * scale, image->maxvalue);
+
+    int i, j;
+    for (i = 0; i < nimage->width; i++) {
+        for (j = 0; j < nimage->height; j++) {
+            int pos = i / scale + (j / scale) * image->width;
+            int Pos = i + j * nimage->width;
+            nimage->red[Pos] = image->red[pos];
+            nimage->green[Pos] = image->green[pos];
+            nimage->blue[Pos] = image->blue[pos];
+        }
+    }
+
+    return nimage;
+}
+
+image_t *shrinkimage (image_t *image, int scale)
+{
+    image_t *nimage = newimage ((image->width + scale - 1) / scale, (image->height + scale - 1) / scale, image->maxvalue);
+
+    int i, j;
+    for (i = 0; i < nimage->width; i++) {
+        for (j = 0; j < nimage->height; j++) {
+            float red = 0;
+            float green = 0;
+            float blue = 0;
+            int k, l, n = 0;
+            for (k = 0; k < scale; k++) {
+                for (l = 0; l < scale; l++) {
+                    int I = i * scale + k;
+                    int J = j * scale + l;
+                    if ((I < image->width) && (J < image->height)) {
+                        int Pos = I + J * image->width;
+                        red += image->red[Pos];
+                        green += image->green[Pos];
+                        blue += image->blue[Pos];
+                        n++;
+                    }
+                }
+            }
+            int pos = i + j * nimage->width;
+            nimage->red[pos] = red / n;
+            nimage->green[pos] = green / n;
+            nimage->blue[pos] = blue / n;
+        }
+    }
+
+    return nimage;
+}
+
 /* vim: set ts=4 sw=4 et: */
diff --git a/image.h b/image.h
index 155bab5202291f6488189559ebabd0de1d23b916..01f67f5e72f28651fcc5a388c5c6d5a43486eb44 100644 (file)
--- a/image.h
+++ b/image.h
@@ -20,4 +20,8 @@ int contain (char *str, char c);
 
 float correction (float value, float factor);
 
+image_t *expandimage (image_t *image, int scale);
+
+image_t *shrinkimage (image_t *image, int scale);
+
 #endif /* __IMAGE_H__ */
index 97a099a20cf10eb5118ac51798f21ffbe9c79367..5b84610b84c24d9e9c01d0ae045f182da736d668 100644 (file)
@@ -14,6 +14,7 @@
 #include "pnm.h"
 
 #define min(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
+#define max(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; })
 
 #define KEY_ESC 0x1b
 
@@ -24,6 +25,8 @@ char *version = "0.1";
 int colormap = 2;
 float gf[3] = { 1.0f, 1.0f, 1.0f };
 int mode = 1;
+int scale = 1;
+#define MAXSCALE 4
 
 char *help =
     "<i> Move up\n"
@@ -51,6 +54,7 @@ int usage (int ret)
 int main (int argc, char *argv[])
 {
     char *filename = NULL;
+    int i;
 
     /* get basename */
     char *pt = progname = argv[0];
@@ -125,7 +129,12 @@ int main (int argc, char *argv[])
     }
 
     /* main process */
-    image_t *image = readpnm (filename);
+    image_t *images[MAXSCALE + 1] = {0};
+    images[1] = readpnm (filename);
+    for (i = 2; i <= MAXSCALE; i++) {
+        images[i] = shrinkimage (images[1], i);
+    }
+    images[0] = expandimage (images[1], 2);
 
     /* init curses window */
     initscr ();
@@ -149,18 +158,33 @@ int main (int argc, char *argv[])
     /* event loop */
     int stop = 0;
     while (!stop) {
+        int x, y;
+
+        /* clear screen */
+        clear ();
+
+        /* check cursor location */
+        if (images[scale]->width - xcursor < COLS / mode) {
+            xcursor = max (0, images[scale]->width - COLS / mode);
+        }
+        if (images[scale]->height - ycursor < LINES) {
+            ycursor = max (0, images[scale]->height - LINES);
+        }
 
-        int width = min (image->width - xcursor, COLS / mode);
-        int height = min (image->height - ycursor, LINES);
+        /* display current image view */
+        int width = min (images[scale]->width - xcursor, COLS / mode);
+        int height = min (images[scale]->height - ycursor, LINES);
         VERBOSE (DEBUG, FILE *fd = fopen ("my.log", "a"); fprintf (fd, "(%d, %d)\n", width, height); fclose (fd));
-        int x, y;
         for (x = 0; x < width; x++) {
             for (y = 0; y < height; y++) {
 
-                int ind = (x + xcursor) + image->width * (y + ycursor);
-                color_t *color = findcolor (correction (image->red[ind], gf[0]),
-                                            correction (image->green[ind], gf[1]),
-                                            correction (image->blue[ind], gf[2]), colormap);
+                int ind = x + xcursor + images[scale]->width * (y + ycursor);
+                if (ind >= images[scale]->width * images[scale]->height) {
+                    continue;
+                }
+                color_t *color = findcolor (correction (images[scale]->red[ind], gf[0]),
+                                            correction (images[scale]->green[ind], gf[1]),
+                                            correction (images[scale]->blue[ind], gf[2]), colormap);
                 attron (COLOR_PAIR (color->code));
 
                 move (y, x * mode);
@@ -193,26 +217,54 @@ int main (int argc, char *argv[])
             break;
         case KEY_DOWN:
         case 'k':
-            if (image->height - ycursor > LINES) {
+            if (images[scale]->height - ycursor >= LINES) {
                 ycursor++;
             }
             break;
         case KEY_RIGHT:
         case 'l':
-            if (image->width - xcursor > COLS / mode) {
+            if (images[scale]->width - xcursor >= COLS / mode) {
                 xcursor++;
             }
             break;
+        case KEY_END:
+        case 'o':
+            if (scale < MAXSCALE) {
+                scale++;
+                if (scale > 1) {
+                    xcursor = (xcursor * (scale - 1)) / scale;
+                    ycursor = (ycursor * (scale - 1)) / scale;
+                } else {
+                    xcursor /= 2;
+                    ycursor /= 2;
+                }
+            }
+            break;
         case KEY_ESC:
         case 'q':
             stop = 1;
             break;
+        case KEY_HOME:
+        case 'u':
+            if (scale > 0) {
+                scale--;
+                if (scale > 0) {
+                    xcursor = (xcursor * (scale + 1)) / scale;
+                    ycursor = (ycursor * (scale + 1)) / scale;
+                } else { /* scale 0 is *2 */
+                    xcursor *= 2;
+                    ycursor *= 2;
+                }
+            }
+            break;
         }
     }
 
     /* cleaning before quiting */
     endwin ();
-    freeimage (image);
+    for (i = 0; i <= scale; i++) {
+        freeimage (images[i]);
+    }
 
     return 0;
 }