[med-svn] [Git][med-team/bart-view][master] 35 commits: view: comment out unused function

Martin Uecker (@uecker-guest) gitlab at salsa.debian.org
Wed Jan 10 17:17:55 GMT 2024



Martin Uecker pushed to branch master at Debian Med / bart-view


Commits:
e0815991 by Christian Holme at 2023-04-28T14:14:12+02:00
view: comment out unused function

- - - - -
23b09045 by Christian Holme at 2023-07-27T14:28:51+02:00
Makefile: add option DEBUG

- - - - -
fe54be2e by Christian Holme at 2023-07-27T14:28:51+02:00
add turbo colormap, as a better jet

- - - - -
d82bf44a by Christian Holme at 2023-07-27T14:28:51+02:00
draw.c: linearly interpolate colormaps

- - - - -
07fe6e2f by Christian Holme at 2023-07-27T14:28:51+02:00
delete duplicate README

README.md covers the same info

- - - - -
9fb09b6c by Christian Holme at 2023-07-27T14:28:51+02:00
draw.c: handle NaNs, always drawing them black

this also fixes a segfault in the interpolation of colormaps (found by
Philip Schaten)

- - - - -
5fd7c7e2 by Christian Holme at 2023-07-27T14:28:51+02:00
draw: parallelize resample and draw()

- - - - -
60dc3314 by Martin Uecker at 2023-07-27T14:28:51+02:00
style

- - - - -
0a58b574 by Martin Uecker at 2023-07-28T11:05:12+02:00
add gitlab ci

- - - - -
0412d795 by Christian Holme at 2023-09-20T13:35:29+02:00
silence warning about unregistered file

bart will normally warn about using unregistered files. But here, we are
changing the filename that we are opening (by ignoring final `.hdr`, `.cfl`
or `.`), therefore confusing the checks. So now we do that manually.

- - - - -
1f0d99dc by Christian Holme at 2023-09-20T13:38:57+02:00
Makefile: create parent directory on `install`

- - - - -
11ce61fa by Christian Holme at 2023-09-24T14:52:37+02:00
cfl2png: add LIINCO interpolation

- - - - -
93f2daed by Christian Holme at 2023-09-24T14:52:37+02:00
LIINCO: fix use of uninit VLA `pos1`

and silence warning with some `assert()`

- - - - -
51cd4f6d by Christian Holme at 2023-09-25T10:20:13+02:00
cfl2png: rename loopflags to imflags

as those are the image flags, exactly the opposite of the loopflags

- - - - -
be056aab by Christian Holme at 2023-09-25T10:20:47+02:00
parallelize cfl2png, add OMP= option to Makefile

- - - - -
2c37ede0 by Christian Holme at 2023-09-25T11:48:20+02:00
move filename construction to separate function

as first step to moving it into bart.

additionally, add "_" between dimension names

- - - - -
5aeb188b by Moritz Blumenthal at 2023-09-25T12:12:19+02:00
Add nlinear interpolation on magnitude

- - - - -
08b77634 by Christian Holme at 2023-09-25T12:57:15+02:00
cfl2png: change unravel_index to same implementation as bart

this will make the switch to the bart version easier in the future

- - - - -
158fe27d by Christian Holme at 2023-09-26T10:39:45+02:00
view.c: style

- - - - -
84c263e6 by Christian Holme at 2023-09-26T10:42:41+02:00
view.c: avoid calling geom_callback from itself

Toggling a GTK_TOGGLE_BUTTON would also call the associated callback,
which means that toggling a button in geom_callback calls geom_callback.

This would break the logic for setting xdim and ydim in some cases, and
could lead to xdim==ydim.

- - - - -
9b06eb82 by Christian Holme at 2023-09-26T13:08:32+02:00
view: transpose by default

we might want to replace it by handling x and y differently at some
point in the future

- - - - -
44109913 by Christian Holme at 2023-09-26T13:09:52+02:00
view: make sync button active for new windows

currently, the button is off for active sync, and on when sync is
disabled. This changes it so that the state of the button is the same as
the state of sync

- - - - -
c963c2cf by Moritz Blumenthal at 2023-09-27T11:31:52+02:00
rename construct_filename and fixup sync

- - - - -
eb67494e by Moritz Blumenthal at 2023-09-27T11:32:16+02:00
Add absolute windowing

- - - - -
fe9a2817 by Moritz Blumenthal at 2023-10-07T21:04:33+02:00
fix linking dependencies

- - - - -
58351692 by Moritz Blumenthal at 2023-10-07T21:04:33+02:00
absolute windowing for view

- - - - -
3553e92f by Moritz Blumenthal at 2023-10-07T21:04:33+02:00
use c locale

- - - - -
1b4c9381 by Blumenthal, Moritz at 2023-11-11T12:16:27+01:00
fix absolute windowing

- - - - -
5ea16682 by Martin Uecker at 2024-01-10T14:31:38+01:00
updates to fix build + copyright

- - - - -
1bc73caf by Martin Uecker at 2024-01-10T14:36:05+01:00
copyright

- - - - -
4aeac649 by Martin Uecker at 2024-01-10T16:31:17+01:00
update makefile

- - - - -
460e4ca3 by Martin Uecker at 2024-01-10T17:25:06+01:00
change BART path

- - - - -
638015e3 by Martin Uecker at 2024-01-10T18:11:28+01:00
Merge branch 'upstream'

- - - - -
6f5c905b by Martin Uecker at 2024-01-10T18:11:43+01:00
new upstream version

- - - - -
9f1267ab by Martin Uecker at 2024-01-10T18:11:59+01:00
debian standard

- - - - -


21 changed files:

- + .gitlab-ci.yml
- LICENSE
- Makefile
- − README
- debian/changelog
- debian/control
- − debian/patches/0001-create-parent-directories.patch
- − debian/patches/0002-don-t-build-cfl2png.patch
- − debian/patches/0003-enable-cross-build.patch
- − debian/patches/0004-workaround-for-GCC-11-compiler-bug-debian-bug-100250.patch
- − debian/patches/0005-Enabling-hardening-options-to-fix-blhc.patch
- − debian/patches/0007-allow-overwriting-CFLAGS.patch
- − debian/patches/series
- src/cfl2png.c
- src/colormaps.inc
- src/draw.c
- src/draw.h
- src/main.c
- src/view.c
- src/view.h
- src/viewer.ui


Changes:

=====================================
.gitlab-ci.yml
=====================================
@@ -0,0 +1,23 @@
+variables:
+  OMP_NUM_THREADS: "1"
+
+
+before_script:
+  - apt-get update -qq && apt-get install -y -qq
+  - apt-get install -y -qq make git gcc
+  - apt-get install -y -qq libgtk-3-dev
+  - apt-get install -y -qq libbart-dev
+
+stages:
+  - build
+
+Build:
+  image: debian:bookworm
+  stage: build
+  script:
+    - make all
+  artifacts:
+    paths:
+      - view
+      - cfl2png
+


=====================================
LICENSE
=====================================
@@ -1,4 +1,5 @@
-Copyright (c) 2015-2022. Martin Uecker.
+Copyright (c) 2015-2023. Martin Uecker.
+Copyright (c) 2017-2023. AG Uecker. University Medical Center Göttingen.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without


=====================================
Makefile
=====================================
@@ -5,6 +5,9 @@
 CUDA?=0
 CUDA_BASE ?= /usr/local/cuda
 CUDA_LIB ?= lib
+DEBUG?=0
+OMP?=1
+PKG_CONFIG?=pkg-config
 
 BUILDTYPE = Linux
 UNAME = $(shell uname -s)
@@ -14,12 +17,12 @@ ifeq ($(UNAME),Darwin)
 endif
 
 
-ifeq ($(TOOLBOX_PATH),)
+ifeq ($(BART_TOOLBOX_PATH),)
 TOOLBOX_INC=/usr/include/bart/
 TOOLBOX_LIB=/usr/lib/bart/
 else
-TOOLBOX_INC=$(TOOLBOX_PATH)/src/
-TOOLBOX_LIB=$(TOOLBOX_PATH)/lib/
+TOOLBOX_INC=$(BART_TOOLBOX_PATH)/src/
+TOOLBOX_LIB=$(BART_TOOLBOX_PATH)/lib/
 endif
 
 
@@ -27,15 +30,27 @@ ifeq ($(origin CC), default)
 	CC = gcc
 endif
 
-CFLAGS = -Wall -O2
+CFLAGS ?= -Wall
 
+ifeq ($(DEBUG),1)
+	CFLAGS += -Og -g
+else
+	CFLAGS += -O2
+endif
 
 ifeq ($(BUILDTYPE), MacOSX)
-	CFLAGS += -std=c11 -Xpreprocessor -fopenmp
+	CFLAGS += -std=c11 -Xpreprocessor
 else
-	CFLAGS += -std=c11 -fopenmp
+	CFLAGS += -std=c11
 endif
 
+ifeq ($(OMP),1)
+	CFLAGS += -fopenmp
+else
+	CFLAGS += -Wno-unknown-pragmas
+endif
+
+
 # clang
 
 ifeq ($(findstring clang, $(CC)), clang)
@@ -68,14 +83,16 @@ src/viewer.inc: src/viewer.ui
 	@echo "STRINGIFY(`cat src/viewer.ui`)" > src/viewer.inc
 
 view:	src/main.c src/view.[ch] src/draw.[ch] src/viewer.inc
-	$(CC) $(CFLAGS) $(EXPDYN) -o view -I$(TOOLBOX_INC) `pkg-config --cflags gtk+-3.0` src/main.c src/view.c src/draw.c `pkg-config --libs gtk+-3.0` $(TOOLBOX_LIB)/libmisc.a $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(CUDA_L) $(LDFLAGS)
+	$(CC) $(CFLAGS) $(CPPFLAGS) $(EXPDYN) -o view -I$(TOOLBOX_INC) `$(PKG_CONFIG) --cflags gtk+-3.0` src/main.c src/view.c src/draw.c `$(PKG_CONFIG) --libs gtk+-3.0` $(TOOLBOX_LIB)/libmisc.a $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(TOOLBOX_LIB)/libmisc.a $(CUDA_L) $(LDFLAGS)
 
 cfl2png:	src/cfl2png.c src/view.[ch] src/draw.[ch] src/viewer.inc
-	$(CC) $(CFLAGS) $(EXPDYN) -o cfl2png -I$(TOOLBOX_INC) src/cfl2png.c src/draw.c $(TOOLBOX_LIB)/libmisc.a  $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(CUDA_L) $(LDFLAGS)
+	$(CC) $(CFLAGS) $(CPPFLAGS) $(EXPDYN) -o cfl2png -I$(TOOLBOX_INC) src/cfl2png.c src/draw.c $(TOOLBOX_LIB)/libmisc.a  $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(TOOLBOX_LIB)/libmisc.a $(CUDA_L) $(LDFLAGS)
 
 install:
-	install view $(DESTDIR)/usr/lib/bart/commands/
+	install -D view $(DESTDIR)/usr/lib/bart/commands/view
+	install cfl2png $(DESTDIR)/usr/lib/bart/commands/
 
 
 clean:
-	rm -f view cfl2png viewer.inc
+	rm -f view cfl2png src/viewer.inc
+


=====================================
README deleted
=====================================
@@ -1,30 +0,0 @@
-
-
-Small image viewer for multi-dimensional files. Compiles
-on Linux and Mac OS X. It needs some libraries from
-the Berkeley Advanced Reconstruction Toolbox (BART).
-
-https://mrirecon.github.io/bart/
-
-Requires BART 0.8.00 or later.
-
-
-Mac OS X:
-
-sudo port install pkgconfig
-sudo port install gtk3
-sudo port install adwaita-icon-theme
-sudo port install libomp
-
-
-Linux:
-sudo apt-get install libgtk-3-dev
-
-
-
-Compile with make after setting the TOOLBOX_PATH
-environment variable to the directory where BART
-is installed.
-
-
-


=====================================
debian/changelog
=====================================
@@ -1,3 +1,10 @@
+bart-view (0.3.00-1) UNRELEASED; urgency=medium
+
+  * New upstream version (Closes: #1058276, 1043926)
+  * Remove old patches.
+
+ -- Martin Uecker <uecker at tugraz.at>  Wed, 10 Jan 2024 16:32:35 +0100
+
 bart-view (0.2.00-1) unstable; urgency=medium
 
   * New upstream version (Closes: #1022324)


=====================================
debian/control
=====================================
@@ -6,7 +6,7 @@ Priority: optional
 Build-Depends: debhelper-compat (= 13),
                libbart-dev (>= 0.8.00),
                libgtk-3-dev
-Standards-Version: 4.6.1.0
+Standards-Version: 4.6.2
 Vcs-Browser: https://salsa.debian.org/med-team/bart-view
 Vcs-Git: https://salsa.debian.org/med-team/bart-view.git
 Homepage: https://github.com/mrirecon/view/


=====================================
debian/patches/0001-create-parent-directories.patch deleted
=====================================
@@ -1,21 +0,0 @@
-From: Martin Uecker <uecker at tugraz.at>
-Date: Mon, 24 Oct 2022 19:38:17 +0200
-Subject: create parent directories
-
----
- Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/Makefile b/Makefile
-index 54e52a7..a2b8df3 100644
---- a/Makefile
-+++ b/Makefile
-@@ -74,7 +74,7 @@ cfl2png:	src/cfl2png.c src/view.[ch] src/draw.[ch] src/viewer.inc
- 	$(CC) $(CFLAGS) $(EXPDYN) -o cfl2png -I$(TOOLBOX_INC) src/cfl2png.c src/draw.c $(TOOLBOX_LIB)/libmisc.a  $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(CUDA_L) $(LDFLAGS)
- 
- install:
--	install view $(DESTDIR)/usr/lib/bart/commands/
-+	install -D view $(DESTDIR)/usr/lib/bart/commands/view
- 
- 
- clean:


=====================================
debian/patches/0002-don-t-build-cfl2png.patch deleted
=====================================
@@ -1,23 +0,0 @@
-From: Martin Uecker <uecker at tugraz.at>
-Date: Mon, 24 Oct 2022 19:38:57 +0200
-Subject: don't build cfl2png
-
----
- Makefile | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/Makefile b/Makefile
-index a2b8df3..508e8e3 100644
---- a/Makefile
-+++ b/Makefile
-@@ -62,7 +62,9 @@ endif
- 
- 
- 
--all: view cfl2png
-+all: view
-+
-+#cfl2png
- 
- src/viewer.inc: src/viewer.ui
- 	@echo "STRINGIFY(`cat src/viewer.ui`)" > src/viewer.inc


=====================================
debian/patches/0003-enable-cross-build.patch deleted
=====================================
@@ -1,30 +0,0 @@
-From: Martin Uecker <uecker at tugraz.at>
-Date: Mon, 24 Oct 2022 19:40:15 +0200
-Subject: enable cross build
-
----
- Makefile | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/Makefile b/Makefile
-index 508e8e3..cc409a1 100644
---- a/Makefile
-+++ b/Makefile
-@@ -2,6 +2,8 @@
- 
- -include Makefile.local
- 
-+PKG_CONFIG ?= pkg-config
-+
- CUDA?=0
- CUDA_BASE ?= /usr/local/cuda
- CUDA_LIB ?= lib
-@@ -70,7 +72,7 @@ src/viewer.inc: src/viewer.ui
- 	@echo "STRINGIFY(`cat src/viewer.ui`)" > src/viewer.inc
- 
- view:	src/main.c src/view.[ch] src/draw.[ch] src/viewer.inc
--	$(CC) $(CFLAGS) $(EXPDYN) -o view -I$(TOOLBOX_INC) `pkg-config --cflags gtk+-3.0` src/main.c src/view.c src/draw.c `pkg-config --libs gtk+-3.0` $(TOOLBOX_LIB)/libmisc.a $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(CUDA_L) $(LDFLAGS)
-+	$(CC) $(CFLAGS) $(EXPDYN) -o view -I$(TOOLBOX_INC) `$(PKG_CONFIG) --cflags gtk+-3.0` src/main.c src/view.c src/draw.c `$(PKG_CONFIG) --libs gtk+-3.0` $(TOOLBOX_LIB)/libmisc.a $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(CUDA_L) $(LDFLAGS)
- 
- cfl2png:	src/cfl2png.c src/view.[ch] src/draw.[ch] src/viewer.inc
- 	$(CC) $(CFLAGS) $(EXPDYN) -o cfl2png -I$(TOOLBOX_INC) src/cfl2png.c src/draw.c $(TOOLBOX_LIB)/libmisc.a  $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(CUDA_L) $(LDFLAGS)


=====================================
debian/patches/0004-workaround-for-GCC-11-compiler-bug-debian-bug-100250.patch deleted
=====================================
@@ -1,21 +0,0 @@
-From: Martin Uecker <uecker at tugraz.at>
-Date: Mon, 24 Oct 2022 19:41:28 +0200
-Subject: workaround for GCC 11 compiler bug (debian bug #1002505)
-
----
- src/draw.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/draw.h b/src/draw.h
-index 143bf9a..b6b7bfd 100644
---- a/src/draw.h
-+++ b/src/draw.h
-@@ -7,7 +7,7 @@ enum mode_t { MAGN, MAGN_VIRIDS, CMPL, CMPL_MYGBM, PHSE, PHSE_MYGBM, REAL, FLOW
- enum flip_t { OO, XO, OY, XY };
- enum interp_t { NLINEAR, NEAREST, LIINCO };
- 
--extern complex float sample(int N, const float pos[N], const long dims[N], const long strs[N], enum interp_t interpolation, const complex float* in);
-+extern complex float sample(int N, const float pos[/*N*/], const long dims[/*N*/], const long strs[/*N*/], enum interp_t interpolation, const complex float* in);
- 
- extern void resample(int X, int Y, long str, complex float* buf,
- 	int N, const double pos[N], const double dx[N], const double dy[N], 


=====================================
debian/patches/0005-Enabling-hardening-options-to-fix-blhc.patch deleted
=====================================
@@ -1,25 +0,0 @@
-From: Martin Uecker <uecker at tugraz.at>
-Date: Mon, 24 Oct 2022 19:42:47 +0200
-Subject: Enabling hardening options to fix blhc
-
----
- Makefile | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/Makefile b/Makefile
-index cc409a1..a56a25e 100644
---- a/Makefile
-+++ b/Makefile
-@@ -72,10 +72,10 @@ src/viewer.inc: src/viewer.ui
- 	@echo "STRINGIFY(`cat src/viewer.ui`)" > src/viewer.inc
- 
- view:	src/main.c src/view.[ch] src/draw.[ch] src/viewer.inc
--	$(CC) $(CFLAGS) $(EXPDYN) -o view -I$(TOOLBOX_INC) `$(PKG_CONFIG) --cflags gtk+-3.0` src/main.c src/view.c src/draw.c `$(PKG_CONFIG) --libs gtk+-3.0` $(TOOLBOX_LIB)/libmisc.a $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(CUDA_L) $(LDFLAGS)
-+	$(CC) $(CFLAGS) $(CPPFLAGS) $(EXPDYN) -o view -I$(TOOLBOX_INC) `$(PKG_CONFIG) --cflags gtk+-3.0` src/main.c src/view.c src/draw.c `$(PKG_CONFIG) --libs gtk+-3.0` $(TOOLBOX_LIB)/libmisc.a $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(CUDA_L) $(LDFLAGS)
- 
- cfl2png:	src/cfl2png.c src/view.[ch] src/draw.[ch] src/viewer.inc
--	$(CC) $(CFLAGS) $(EXPDYN) -o cfl2png -I$(TOOLBOX_INC) src/cfl2png.c src/draw.c $(TOOLBOX_LIB)/libmisc.a  $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(CUDA_L) $(LDFLAGS)
-+	$(CC) $(CFLAGS) $(CPPFLAGS) $(EXPDYN) -o cfl2png -I$(TOOLBOX_INC) src/cfl2png.c src/draw.c $(TOOLBOX_LIB)/libmisc.a  $(TOOLBOX_LIB)/libgeom.a $(TOOLBOX_LIB)/libnum.a $(CUDA_L) $(LDFLAGS)
- 
- install:
- 	install -D view $(DESTDIR)/usr/lib/bart/commands/view


=====================================
debian/patches/0007-allow-overwriting-CFLAGS.patch deleted
=====================================
@@ -1,21 +0,0 @@
-From: Martin Uecker <uecker at tugraz.at>
-Date: Tue, 25 Oct 2022 17:32:10 +0200
-Subject: allow overwriting CFLAGS
-
----
- Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/Makefile b/Makefile
-index a56a25e..f781bfe 100644
---- a/Makefile
-+++ b/Makefile
-@@ -29,7 +29,7 @@ ifeq ($(origin CC), default)
- 	CC = gcc
- endif
- 
--CFLAGS = -Wall -O2
-+CFLAGS ?= -Wall -O2
- 
- 
- ifeq ($(BUILDTYPE), MacOSX)


=====================================
debian/patches/series deleted
=====================================
@@ -1,6 +0,0 @@
-0001-create-parent-directories.patch
-0002-don-t-build-cfl2png.patch
-0003-enable-cross-build.patch
-0004-workaround-for-GCC-11-compiler-bug-debian-bug-100250.patch
-0005-Enabling-hardening-options-to-fix-blhc.patch
-0007-allow-overwriting-CFLAGS.patch


=====================================
src/cfl2png.c
=====================================
@@ -1,3 +1,7 @@
+/* Copyright 2017-2023. AG Uecker. University Medical Center Göttingen.
+ * All rights reserved. Use of this source code is governed by
+ * a BSD-style license which can be found in the LICENSE file.
+ */
 
 #include <stdio.h>
 #include <assert.h>
@@ -13,6 +17,12 @@
 #include "misc/mmio.h"
 #include "misc/opts.h"
 #include "misc/png.h"
+#if 0
+#include "misc/io.h"
+#else
+extern void io_reserve_input(const char* name);
+extern void io_unregister(const char* name);
+#endif
 
 #include "draw.h"
 
@@ -25,7 +35,7 @@
 #endif
 
 
-static void export_images(const char* output_prefix, int xdim, int ydim, float windowing[2], float zoom, enum mode_t mode, enum flip_t flip, enum interp_t interpolation, const long dims[DIMS], const complex float* idata);
+static void export_images(const char* output_prefix, int xdim, int ydim, float windowing[2], bool absolute_windowing, float zoom, enum mode_t mode, enum flip_t flip, enum interp_t interpolation, const long dims[DIMS], const complex float* idata);
 
 
 static const char help_str[] = "Export images to png.";
@@ -47,6 +57,7 @@ int main(int argc, char* argv[argc])
 	int xdim = 0;
 	int ydim = 0;
 	float windowing[2] = {0.f, 1.f};
+	bool absolute_windowing = false;
 	enum mode_t mode = MAGN;
 	float zoom =2.f;
 	enum flip_t flip = OO;
@@ -60,6 +71,7 @@ int main(int argc, char* argv[argc])
 		OPT_SELECT('P', enum mode_t, &mode, PHSE, 		"phase"),
 		OPT_SELECT('Y', enum mode_t, &mode, PHSE_MYGBM, 	"phase MYGBM"),
 		OPT_SELECT('R', enum mode_t, &mode, REAL, 		"real"),
+		OPT_SELECT('T', enum mode_t, &mode, MAGN_TURBO,		"magnitude turbo"),
 		OPT_SELECT('F', enum mode_t, &mode, FLOW, 		"flow"),
 	};
 
@@ -72,7 +84,9 @@ int main(int argc, char* argv[argc])
 
 	struct opt_s interpopt[] = {
 		OPT_SELECT('L', enum interp_t, &interpolation, NLINEAR, 		"n-linear interpolation"),
+		OPT_SELECT('M', enum interp_t, &interpolation, NLINEARMAG, 		"n-linear interpolation on the magnitude"),
 		OPT_SELECT('N', enum interp_t, &interpolation, NEAREST, 		"nearest neighbor interpolation"),
+		OPT_SELECT('C', enum interp_t, &interpolation, LIINCO, 			"line-integral convolution"),
 	};
 
 	const struct opt_s opts[] = {
@@ -80,6 +94,7 @@ int main(int argc, char* argv[argc])
 		OPT_INT('y', &ydim, "ydim", "output ydim (default: 0). If both are zero, first two non-singleton dims are used."),
 		OPT_FLOAT('l', &windowing[0], "l", "lower windowing value"),
 		OPT_FLOAT('u', &windowing[1], "u", "upper windowing value"),
+		OPT_SET('A', &absolute_windowing, "use absolute windowing"),
 		OPT_FLOAT('z', &zoom, "z", "zoom factor (default: 2) "),
 		OPT_SUBOPT('C', "cmap", "colormap. -Ch for help.", ARRAY_SIZE(modeopt), modeopt),
 		OPT_SUBOPT('F', "flip", "flip. -Fh for help.", ARRAY_SIZE(flipopt), flipopt),
@@ -89,9 +104,10 @@ int main(int argc, char* argv[argc])
 
 	cmdline(&argc, argv, ARRAY_SIZE(args), args, help_str, ARRAY_SIZE(opts), opts);
 
-	assert(    (windowing[0] >= 0.f)
-		&& (windowing[1] <= 1.f)
-		&& (windowing[0] < windowing[1]));
+	if (!absolute_windowing)
+		assert(    (windowing[0] >= 0.f)
+			&& (windowing[1] <= 1.f)
+			&& (windowing[0] < windowing[1]));
 
 	assert((0 <= xdim) && (xdim < DIMS));
 	assert((0 <= ydim) && (ydim < DIMS));
@@ -100,6 +116,7 @@ int main(int argc, char* argv[argc])
 	 * If the filename ends in ".hdr", ".cfl" or just "." (from
 	 * tab-completion), just replace the "." with a \0-character.
 	 */
+	io_unregister(in_file);
 	char* dot = strrchr(in_file, '.');
 
 	if (   (NULL != dot)
@@ -108,6 +125,7 @@ int main(int argc, char* argv[argc])
 		|| !strcmp(dot, ".")))
 		*dot = '\0';
 
+	io_reserve_input(in_file);
 
 	long dims[DIMS];
 	complex float* idata = load_cfl(in_file, DIMS, dims);
@@ -122,7 +140,7 @@ int main(int argc, char* argv[argc])
 			*ext = '\0';
 	}
 
-	export_images(out_prefix, xdim, ydim, windowing, zoom, mode, flip, interpolation, dims, idata);
+	export_images(out_prefix, xdim, ydim, windowing, absolute_windowing, zoom, mode, flip, interpolation, dims, idata);
 
 
 	unmap_cfl(DIMS, dims, idata);
@@ -131,25 +149,24 @@ int main(int argc, char* argv[argc])
 }
 
 
-
 /**
  * Convert flat index to pos
  *
  */
-static void unravel_index(unsigned int D, long pos[D], const long dims[D], long index)
+static void unravel_index(int D, long pos[D], unsigned long flags, const long dims[D], long index)
 {
-	for (unsigned int d = 0; d < D; ++d) {
+	long ind = index;
+	for (int d = 0; d < D; ++d) {
 
-		if (1 == dims[d])
+		if (!MD_IS_SET(flags, d))
 			continue;
 
-		pos[d] = index % dims[d];
-		index /= dims[d];
+		pos[d] = ind % dims[d];
+		ind /= dims[d];
 	}
 }
 
-
-void export_images(const char* output_prefix, int xdim, int ydim, float windowing[2], float zoom, enum mode_t mode, enum flip_t flip, enum interp_t interpolation, const long dims[DIMS], const complex float* idata)
+void export_images(const char* output_prefix, int xdim, int ydim, float windowing[2], bool absolute_windowing, float zoom, enum mode_t mode, enum flip_t flip, enum interp_t interpolation, const long dims[DIMS], const complex float* idata)
 {
 	if (xdim == ydim) {
 
@@ -167,83 +184,71 @@ void export_images(const char* output_prefix, int xdim, int ydim, float windowin
 	}
 
 	double max = 0.;
-	for (long j = 0; j < md_calc_size(DIMS, dims); j++)
-		if (max < cabsf(idata[j]))
-			max = cabsf(idata[j]);
 
-	if (0. == max)
+	if (absolute_windowing) {
+
 		max = 1.;
+	} else {
+
+		for (long j = 0; j < md_calc_size(DIMS, dims); j++)
+			if (max < cabsf(idata[j]))
+				max = cabsf(idata[j]);
+
+		if (0. == max)
+			max = 1.;
+	}
 
 	int rgbw = dims[xdim] * zoom;
 	int rgbh = dims[ydim] * zoom;
 	int rgbstr = 4 * rgbw;
-	unsigned char* rgb = xmalloc(rgbh * rgbstr);
-
-	complex float* buf = xmalloc(rgbh * rgbw * sizeof(complex float));
 
 	// loop over all dims other than xdim and ydim
 	long loopdims[DIMS];
-	unsigned long loopflags = (MD_BIT(xdim)|MD_BIT(ydim));
-	md_select_dims(DIMS, ~loopflags, loopdims, dims);
+	unsigned long imflags = (MD_BIT(xdim)|MD_BIT(ydim));
+	md_select_dims(DIMS, ~imflags, loopdims, dims);
 
-	debug_printf(DP_DEBUG3, "flags: %lu\nloopdims: ", loopflags);
+	debug_printf(DP_DEBUG3, "imflags: %lu\nloopdims: ", imflags);
 	debug_print_dims(DP_DEBUG3, DIMS, loopdims);
 
 
 
-	long pos[DIMS] = { [0 ... DIMS - 1] = 0  };
 	long strs[DIMS];
 	md_calc_strides(DIMS, strs, dims, sizeof(complex float));
 
-	for (unsigned long d = 0l; d < md_calc_size(DIMS, loopdims); ++d){
 
-		unravel_index(DIMS, pos, loopdims, d);
+#pragma omp parallel for
+	for (unsigned long d = 0l; d < md_calc_size(DIMS, loopdims); ++d) {
+
+		long pos[DIMS] = { [0 ... DIMS - 1] = 0  };
+		unravel_index(DIMS, pos, ~0L, loopdims, d);
 
 		debug_printf(DP_DEBUG3, "\ti: %lu\n\t", d);
 		debug_print_dims(DP_DEBUG3, DIMS, pos);
 
 		// Prepare output filename
-		static const char* spec = "xyzcmnopqsfrtuvw";
-		int len = 0;
-
-		len += snprintf(NULL, 0, "%s_", output_prefix);
-
-		for (unsigned int i = 0; i < DIMS; i++)
-			if (1 != loopdims[i])
-				len += snprintf(NULL, 0, "%c%04ld", spec[i], pos[i]);
-
-		len += snprintf(NULL, 0, ".png");
-		len++;
-
-		char* name = xmalloc(len);
-		int off = 0;
-
-		off += snprintf(name + off, len - off, "%s_", output_prefix);
-
-		for (unsigned int i = 0; i < DIMS; i++)
-			if (1 != loopdims[i])
-				off += snprintf(name + off, len - off, "%c%04ld", spec[i], pos[i]);
-
-		off += snprintf(name + off, len - off, ".png");
+		char* name = construct_filename_view(DIMS, loopdims, pos, output_prefix, "png");
 
 		debug_printf(DP_DEBUG2, "\t%s\n", name);
 
+		complex float* buf = xmalloc(rgbh * rgbw * sizeof(complex float));
+
 		update_buf(xdim, ydim, DIMS, dims, strs, pos,
 			   flip, interpolation, zoom, zoom, false,
 			   rgbw, rgbh, idata, buf);
 
+		unsigned char* rgb = xmalloc(rgbh * rgbstr);
+
 		draw(rgbw, rgbh, rgbstr, (unsigned char(*)[rgbw][rgbstr / 4][4])rgb,
 			mode, 1. / max, windowing[0], windowing[1], 0,
 			rgbw, buf);
 
+		xfree(buf);
+
 		if (0 != png_write_bgr32(name, rgbw, rgbh, 0, rgb))
 			error("Error: writing image file.\n");
 
+		xfree(rgb);
 		xfree(name);
 	}
-
-// 	free(source);
-	free(buf);
-	free(rgb);
 }
 


=====================================
src/colormaps.inc
=====================================
@@ -543,3 +543,22 @@ static const double viridis[256][3] = {
 	{0.983868, 0.904867, 0.136897},
 	{0.993248, 0.906157, 0.143936},
 };
+
+
+
+
+// The Turbo colormap is a replacement for jet, the old default colormap of
+// matlab. Turbo, like jet, is a rainbow colormap, but unlike jet it does not
+// have its banding problems, so it does not introduce false detail.
+// It is available from Google LLC under the Apache-2.0 license.
+// This particular look-up table was adapted from
+// https://gist.github.com/mikhailov-work/6a308c20e494d9e0ccc29036b28faa7a
+
+// Copyright 2019 Google LLC.
+// SPDX-License-Identifier: Apache-2.0
+
+// Author: Anton Mikhailov
+
+// The look-up tables contains 256 entries. Each entry is a an sRGB triplet.
+
+static const double turbo[256][3] = {{0.18995,0.07176,0.23217},{0.19483,0.08339,0.26149},{0.19956,0.09498,0.29024},{0.20415,0.10652,0.31844},{0.20860,0.11802,0.34607},{0.21291,0.12947,0.37314},{0.21708,0.14087,0.39964},{0.22111,0.15223,0.42558},{0.22500,0.16354,0.45096},{0.22875,0.17481,0.47578},{0.23236,0.18603,0.50004},{0.23582,0.19720,0.52373},{0.23915,0.20833,0.54686},{0.24234,0.21941,0.56942},{0.24539,0.23044,0.59142},{0.24830,0.24143,0.61286},{0.25107,0.25237,0.63374},{0.25369,0.26327,0.65406},{0.25618,0.27412,0.67381},{0.25853,0.28492,0.69300},{0.26074,0.29568,0.71162},{0.26280,0.30639,0.72968},{0.26473,0.31706,0.74718},{0.26652,0.32768,0.76412},{0.26816,0.33825,0.78050},{0.26967,0.34878,0.79631},{0.27103,0.35926,0.81156},{0.27226,0.36970,0.82624},{0.27334,0.38008,0.84037},{0.27429,0.39043,0.85393},{0.27509,0.40072,0.86692},{0.27576,0.41097,0.87936},{0.27628,0.42118,0.89123},{0.27667,0.43134,0.90254},{0.27691,0.44145,0.91328},{0.27701,0.45152,0.92347},{0.27698,0.46153,0.93309},{0.27680,0.47151,0.94214},{0.27648,0.48144,0.95064},{0.27603,0.49132,0.95857},{0.27543,0.50115,0.96594},{0.27469,0.51094,0.97275},{0.27381,0.52069,0.97899},{0.27273,0.53040,0.98461},{0.27106,0.54015,0.98930},{0.26878,0.54995,0.99303},{0.26592,0.55979,0.99583},{0.26252,0.56967,0.99773},{0.25862,0.57958,0.99876},{0.25425,0.58950,0.99896},{0.24946,0.59943,0.99835},{0.24427,0.60937,0.99697},{0.23874,0.61931,0.99485},{0.23288,0.62923,0.99202},{0.22676,0.63913,0.98851},{0.22039,0.64901,0.98436},{0.21382,0.65886,0.97959},{0.20708,0.66866,0.97423},{0.20021,0.67842,0.96833},{0.19326,0.68812,0.96190},{0.18625,0.69775,0.95498},{0.17923,0.70732,0.94761},{0.17223,0.71680,0.93981},{0.16529,0.72620,0.93161},{0.15844,0.73551,0.92305},{0.15173,0.74472,0.91416},{0.14519,0.75381,0.90496},{0.13886,0.76279,0.89550},{0.13278,0.77165,0.88580},{0.12698,0.78037,0.87590},{0.12151,0.78896,0.86581},{0.11639,0.79740,0.85559},{0.11167,0.80569,0.84525},{0.10738,0.81381,0.83484},{0.10357,0.82177,0.82437},{0.10026,0.82955,0.81389},{0.09750,0.83714,0.80342},{0.09532,0.84455,0.79299},{0.09377,0.85175,0.78264},{0.09287,0.85875,0.77240},{0.09267,0.86554,0.76230},{0.09320,0.87211,0.75237},{0.09451,0.87844,0.74265},{0.09662,0.88454,0.73316},{0.09958,0.89040,0.72393},{0.10342,0.89600,0.71500},{0.10815,0.90142,0.70599},{0.11374,0.90673,0.69651},{0.12014,0.91193,0.68660},{0.12733,0.91701,0.67627},{0.13526,0.92197,0.66556},{0.14391,0.92680,0.65448},{0.15323,0.93151,0.64308},{0.16319,0.93609,0.63137},{0.17377,0.94053,0.61938},{0.18491,0.94484,0.60713},{0.19659,0.94901,0.59466},{0.20877,0.95304,0.58199},{0.22142,0.95692,0.56914},{0.23449,0.96065,0.55614},{0.24797,0.96423,0.54303},{0.26180,0.96765,0.52981},{0.27597,0.97092,0.51653},{0.29042,0.97403,0.50321},{0.30513,0.97697,0.48987},{0.32006,0.97974,0.47654},{0.33517,0.98234,0.46325},{0.35043,0.98477,0.45002},{0.36581,0.98702,0.43688},{0.38127,0.98909,0.42386},{0.39678,0.99098,0.41098},{0.41229,0.99268,0.39826},{0.42778,0.99419,0.38575},{0.44321,0.99551,0.37345},{0.45854,0.99663,0.36140},{0.47375,0.99755,0.34963},{0.48879,0.99828,0.33816},{0.50362,0.99879,0.32701},{0.51822,0.99910,0.31622},{0.53255,0.99919,0.30581},{0.54658,0.99907,0.29581},{0.56026,0.99873,0.28623},{0.57357,0.99817,0.27712},{0.58646,0.99739,0.26849},{0.59891,0.99638,0.26038},{0.61088,0.99514,0.25280},{0.62233,0.99366,0.24579},{0.63323,0.99195,0.23937},{0.64362,0.98999,0.23356},{0.65394,0.98775,0.22835},{0.66428,0.98524,0.22370},{0.67462,0.98246,0.21960},{0.68494,0.97941,0.21602},{0.69525,0.97610,0.21294},{0.70553,0.97255,0.21032},{0.71577,0.96875,0.20815},{0.72596,0.96470,0.20640},{0.73610,0.96043,0.20504},{0.74617,0.95593,0.20406},{0.75617,0.95121,0.20343},{0.76608,0.94627,0.20311},{0.77591,0.94113,0.20310},{0.78563,0.93579,0.20336},{0.79524,0.93025,0.20386},{0.80473,0.92452,0.20459},{0.81410,0.91861,0.20552},{0.82333,0.91253,0.20663},{0.83241,0.90627,0.20788},{0.84133,0.89986,0.20926},{0.85010,0.89328,0.21074},{0.85868,0.88655,0.21230},{0.86709,0.87968,0.21391},{0.87530,0.87267,0.21555},{0.88331,0.86553,0.21719},{0.89112,0.85826,0.21880},{0.89870,0.85087,0.22038},{0.90605,0.84337,0.22188},{0.91317,0.83576,0.22328},{0.92004,0.82806,0.22456},{0.92666,0.82025,0.22570},{0.93301,0.81236,0.22667},{0.93909,0.80439,0.22744},{0.94489,0.79634,0.22800},{0.95039,0.78823,0.22831},{0.95560,0.78005,0.22836},{0.96049,0.77181,0.22811},{0.96507,0.76352,0.22754},{0.96931,0.75519,0.22663},{0.97323,0.74682,0.22536},{0.97679,0.73842,0.22369},{0.98000,0.73000,0.22161},{0.98289,0.72140,0.21918},{0.98549,0.71250,0.21650},{0.98781,0.70330,0.21358},{0.98986,0.69382,0.21043},{0.99163,0.68408,0.20706},{0.99314,0.67408,0.20348},{0.99438,0.66386,0.19971},{0.99535,0.65341,0.19577},{0.99607,0.64277,0.19165},{0.99654,0.63193,0.18738},{0.99675,0.62093,0.18297},{0.99672,0.60977,0.17842},{0.99644,0.59846,0.17376},{0.99593,0.58703,0.16899},{0.99517,0.57549,0.16412},{0.99419,0.56386,0.15918},{0.99297,0.55214,0.15417},{0.99153,0.54036,0.14910},{0.98987,0.52854,0.14398},{0.98799,0.51667,0.13883},{0.98590,0.50479,0.13367},{0.98360,0.49291,0.12849},{0.98108,0.48104,0.12332},{0.97837,0.46920,0.11817},{0.97545,0.45740,0.11305},{0.97234,0.44565,0.10797},{0.96904,0.43399,0.10294},{0.96555,0.42241,0.09798},{0.96187,0.41093,0.09310},{0.95801,0.39958,0.08831},{0.95398,0.38836,0.08362},{0.94977,0.37729,0.07905},{0.94538,0.36638,0.07461},{0.94084,0.35566,0.07031},{0.93612,0.34513,0.06616},{0.93125,0.33482,0.06218},{0.92623,0.32473,0.05837},{0.92105,0.31489,0.05475},{0.91572,0.30530,0.05134},{0.91024,0.29599,0.04814},{0.90463,0.28696,0.04516},{0.89888,0.27824,0.04243},{0.89298,0.26981,0.03993},{0.88691,0.26152,0.03753},{0.88066,0.25334,0.03521},{0.87422,0.24526,0.03297},{0.86760,0.23730,0.03082},{0.86079,0.22945,0.02875},{0.85380,0.22170,0.02677},{0.84662,0.21407,0.02487},{0.83926,0.20654,0.02305},{0.83172,0.19912,0.02131},{0.82399,0.19182,0.01966},{0.81608,0.18462,0.01809},{0.80799,0.17753,0.01660},{0.79971,0.17055,0.01520},{0.79125,0.16368,0.01387},{0.78260,0.15693,0.01264},{0.77377,0.15028,0.01148},{0.76476,0.14374,0.01041},{0.75556,0.13731,0.00942},{0.74617,0.13098,0.00851},{0.73661,0.12477,0.00769},{0.72686,0.11867,0.00695},{0.71692,0.11268,0.00629},{0.70680,0.10680,0.00571},{0.69650,0.10102,0.00522},{0.68602,0.09536,0.00481},{0.67535,0.08980,0.00449},{0.66449,0.08436,0.00424},{0.65345,0.07902,0.00408},{0.64223,0.07380,0.00401},{0.63082,0.06868,0.00401},{0.61923,0.06367,0.00410},{0.60746,0.05878,0.00427},{0.59550,0.05399,0.00453},{0.58336,0.04931,0.00486},{0.57103,0.04474,0.00529},{0.55852,0.04028,0.00579},{0.54583,0.03593,0.00638},{0.53295,0.03169,0.00705},{0.51989,0.02756,0.00780},{0.50664,0.02354,0.00863},{0.49321,0.01963,0.00955},{0.47960,0.01583,0.01055}};


=====================================
src/draw.c
=====================================
@@ -9,6 +9,7 @@
 #include <math.h>
 #include <complex.h>
 #include <assert.h>
+#include <stdio.h>
 
 #include "misc/misc.h"
 
@@ -46,15 +47,29 @@ static void trans_magnitude(double rgb[3], double a, double b, complex double va
 	rgb[2] *= magn;
 }
 
+static void interpolate_cmap(double rgb[3], double x, const double cmap[256][3])
+{
+	int a = x * 255;
+	int b = MIN(255, a + 1);
+
+	double f = x * 255. - a;
+
+	for (int i = 0; i < 3; ++i)
+		rgb[i] *= cmap[a][i] + f * (cmap[b][i] - cmap[a][i]);
+}
+
 static void trans_magnitude_viridis(double rgb[3], double a, double b, complex double value)
 {
 	double magn = window(a, b, cabs(value));
 
-	int subscript = magn * 255.;
+	interpolate_cmap(rgb, magn, viridis);
+}
 
-	rgb[0] *= viridis[subscript][0];
-	rgb[1] *= viridis[subscript][1];
-	rgb[2] *= viridis[subscript][2];
+static void trans_magnitude_turbo(double rgb[3], double a, double b, complex double value)
+{
+	double magn = window(a, b, cabs(value));
+
+	interpolate_cmap(rgb, magn, turbo);
 }
 
 static void trans_real(double rgb[3], double a, double b, complex double value)
@@ -83,13 +98,10 @@ static void trans_phase_MYGBM(double rgb[3], double a, double b, complex double
 
 	if (isfinite(arg)) {
 
-		int subscript = (arg + M_PI) / 2. / M_PI * 255.;
-
-		assert((0 <= subscript) && (subscript <= 255));
+		double val = (arg + M_PI) / 2. / M_PI;
+		assert((0.0 <= val) && (val <= 1.0));
 	
-		rgb[0] *= cyclic_mygbm[subscript][0];
-		rgb[1] *= cyclic_mygbm[subscript][1];
-		rgb[2] *= cyclic_mygbm[subscript][2];
+		interpolate_cmap(rgb, val, cyclic_mygbm);
 	}
 }
 
@@ -126,6 +138,13 @@ static complex float int_nlinear(int N, const float x[N], const long strs[N], co
 		           +       x[N - 1]  * int_nlinear(N - 1, x, strs, in + strs[N - 1]));
 }
 
+static complex float int_nlinearmag(int N, const float x[N], const long strs[N], const complex float* in)
+{
+	return (0 == N) ? cabsf(in[0])
+			: (  (1. - x[N - 1]) * int_nlinearmag(N - 1, x, strs, in + 0)
+		           +       x[N - 1]  * int_nlinearmag(N - 1, x, strs, in + strs[N - 1]));
+}
+
 
 static complex float int_nearest(int N, const float x[N], const long strs[N], const complex float* in)
 {
@@ -199,6 +218,9 @@ complex float sample(int N, const float pos[N], const long dims[N], const long s
 	case NLINEAR:
 		return int_nlinear(D, rem, strs2, (const complex float*)(((char*)in) + off0));
 
+	case NLINEARMAG:
+		return int_nlinearmag(D, rem, strs2, (const complex float*)(((char*)in) + off0));
+
 	case NEAREST:
 		return int_nearest(D, rem, strs2, (const complex float*)(((char*)in) + off0));
 
@@ -237,12 +259,11 @@ complex float lic_sample(int N, const float pos[N], const long dims[N], const lo
 	complex float out = 0.;
 
 	float pos1[N];
-
-	complex float val = sample(N, pos1, dims, strs, NLINEAR, in);
-
 	for (int i = 0; i < N; i++)
 		pos1[i] = pos[i];
 
+
+	complex float val = sample(N, pos1, dims, strs, NLINEAR, in);
 	for (int i = 0; i < L; i++) {
 
 		complex float a = sample(N, pos1, dims, strs, NLINEAR, in);
@@ -292,6 +313,7 @@ extern void resample(int X, int Y, long str, complex float* buf,
 	int N, const double pos[N], const double dx[N], const double dy[N], 
 	const long dims[N], const long strs[N], enum interp_t interpolation, const complex float* in)
 {
+#pragma omp parallel for collapse(2)
 	for (int x = 0; x < X; x++) {
 		for (int y = 0; y < Y; y++) {
 
@@ -327,26 +349,37 @@ extern void draw(int X, int Y, int rgbstr, unsigned char (*rgbbuf)[Y][rgbstr / 4
 	enum mode_t mode, float scale, float winlow, float winhigh, float phrot,
 	long str, const complex float* buf)
 {
+#pragma omp parallel for collapse(2)
 	for (int x = 0; x < X; x++) {
 		for (int y = 0; y < Y; y++) {
 
+			double rgb[3] = { 1., 1., 1. };
+
 			complex float val = scale * buf[str * y + x];
 
-			val *= cexpf(1.i * phrot);
+			if (isfinite(crealf(val)) && isfinite(cimagf(val))) {
 
-			double rgb[3] = { 1., 1., 1. };
+				val *= cexpf(1.i * phrot);
+
+				switch (mode) {
+
+				case MAGN: trans_magnitude(rgb, winlow, winhigh, val); break;
+				case MAGN_VIRIDS: trans_magnitude_viridis(rgb, winlow, winhigh, val); break;
+				case PHSE: trans_phase(rgb, winlow, winhigh, val); break;
+				case PHSE_MYGBM: trans_phase_MYGBM(rgb, winlow, winhigh, val); break;
+				case CMPL: trans_complex(rgb, winlow, winhigh, val); break;
+				case CMPL_MYGBM: trans_complex_MYGBM(rgb, winlow, winhigh, val); break;
+				case REAL: trans_real(rgb, winlow, winhigh, val); break;
+				case MAGN_TURBO: trans_magnitude_turbo(rgb, winlow, winhigh, val); break;
+				case FLOW: trans_flow(rgb, winlow, winhigh, val); break;
+				default: assert(0);
+				}
+
+			} else {
 
-			switch (mode) {
-
-			case MAGN: trans_magnitude(rgb, winlow, winhigh, val); break;
-			case MAGN_VIRIDS: trans_magnitude_viridis(rgb, winlow, winhigh, val); break;
-			case PHSE: trans_phase(rgb, winlow, winhigh, val); break;
-			case PHSE_MYGBM: trans_phase_MYGBM(rgb, winlow, winhigh, val); break;
-			case CMPL: trans_complex(rgb, winlow, winhigh, val); break;
-			case CMPL_MYGBM: trans_complex_MYGBM(rgb, winlow, winhigh, val); break;
-			case REAL: trans_real(rgb, winlow, winhigh, val); break;
-			case FLOW: trans_flow(rgb, winlow, winhigh, val); break;
-			default: assert(0);
+				rgb[0] = 0.;
+				rgb[1] = 0.;
+				rgb[2] = 0.;
 			}
 
 			(*rgbbuf)[y][x][0] = 255. * rgb[2];
@@ -402,6 +435,8 @@ void update_buf(long xdim, long ydim, int N, const long dims[N], const long strs
 			dy[ydim] *= -1.;
 		}
 	}
+	assert(xdim < N);
+	assert(ydim < N);
 
 	dx[xdim] = dx[xdim] / xzoom;
 	dy[ydim] = dy[ydim] / yzoom;
@@ -503,3 +538,35 @@ extern void draw_plot(int X, int Y, int rgbstr, unsigned char (*rgbbuf)[Y][rgbst
 	}
 }
 
+
+static const char* spec = "xyzcmnopqsfrtuvw";
+
+char* construct_filename_view(unsigned int D, const long loopdims[D], const long pos[D], const char* prefix, const char* ext)
+{
+	// Prepare output filename
+
+	int len = 0;
+
+	len += snprintf(NULL, 0, "%s", prefix);
+
+	for (unsigned int i = 0; i < D; i++)
+		if (1 != loopdims[i])
+			len += snprintf(NULL, 0, "_%c%04ld", spec[i], pos[i]);
+
+	len += snprintf(NULL, 0, ".%s", ext);
+	len++;
+
+	char* name = xmalloc(len);
+	int off = 0;
+
+	off += snprintf(name + off, len - off, "%s", prefix);
+
+	for (unsigned int i = 0; i < D; i++)
+		if (1 != loopdims[i])
+			off += snprintf(name + off, len - off, "_%c%04ld", spec[i], pos[i]);
+
+	off += snprintf(name + off, len - off, ".%s", ext);
+
+	return name;
+}
+


=====================================
src/draw.h
=====================================
@@ -3,9 +3,9 @@
 #include <stdbool.h>
 
 
-enum mode_t { MAGN, MAGN_VIRIDS, CMPL, CMPL_MYGBM, PHSE, PHSE_MYGBM, REAL, FLOW };
+enum mode_t { MAGN, MAGN_VIRIDS, CMPL, CMPL_MYGBM, PHSE, PHSE_MYGBM, REAL, MAGN_TURBO, FLOW };
 enum flip_t { OO, XO, OY, XY };
-enum interp_t { NLINEAR, NEAREST, LIINCO };
+enum interp_t { NLINEAR, NLINEARMAG, NEAREST, LIINCO };
 
 extern complex float sample(int N, const float pos[N], const long dims[N], const long strs[N], enum interp_t interpolation, const complex float* in);
 
@@ -32,3 +32,4 @@ extern const char color_white[3];
 extern const char color_red[3];
 extern const char color_blue[3];
 
+extern char* construct_filename_view(unsigned int D, const long loopdims[D], const long pos[D], const char* prefix, const char* ext);


=====================================
src/main.c
=====================================
@@ -1,9 +1,6 @@
-/* Copyright 2015-2016. Martin Uecker.
+/* Copyright 2015-2023. Martin Uecker.
  * All rights reserved. Use of this source code is governed by
  * a BSD-style license which can be found in the LICENSE file.
- *
- * Author:
- *	2015-2016 Martin Uecker <martin.uecker at med.uni-goettinge.de>
  */
 
 #include <complex.h>
@@ -17,6 +14,12 @@
 #include "misc/misc.h"
 #include "misc/mmio.h"
 #include "misc/opts.h"
+#if 0
+#include "misc/io.h"
+#else
+extern void io_reserve_input(const char* name);
+extern void io_unregister(const char* name);
+#endif
 
 #include "view.h"
 
@@ -27,6 +30,7 @@ static const char help_str[] = "View images.";
 
 int main(int argc, char* argv[argc])
 {
+	gtk_disable_setlocale();
 	gtk_init(&argc, &argv);
 
 	long count;
@@ -37,10 +41,11 @@ int main(int argc, char* argv[argc])
 		ARG_TUPLE(true, &count, 1, { OPT_INFILE, sizeof(char*), &in_files, "image" }),
 	};
 
-
+	bool absolute_windowing = false;
 
 	const struct opt_s opts[] = {
 
+		OPT_SET('a', &absolute_windowing, "Use absolute windowing"),
 	};
 
 	cmdline(&argc, argv, ARRAY_SIZE(args), args, help_str, ARRAY_SIZE(opts), opts);
@@ -60,6 +65,7 @@ int main(int argc, char* argv[argc])
 		 * a file manager.
 		 */
 
+		io_unregister(in_files[i]);
 		char* dot = strrchr(in_files[i], '.');
 
 		if ((NULL != dot) && (	 !strcmp(dot, ".cfl") 
@@ -67,12 +73,13 @@ int main(int argc, char* argv[argc])
 				      || !strcmp(dot, ".")))
 			*dot = '\0';
 
+		io_reserve_input(in_files[i]);
 		complex float* x = load_cfl(in_files[i], DIMS, dims);
 
 
 
 		// FIXME: we never delete them
-		struct view_s* v2 = window_new(in_files[i], NULL, dims, x);
+		struct view_s* v2 = window_new(in_files[i], NULL, dims, x, absolute_windowing);
 
 		// If multiple files are passed on the commandline, add them to window
 		// list. This enables sync of windowing and so on...


=====================================
src/view.c
=====================================
@@ -60,6 +60,7 @@ struct view_s {
 
 	// representation
 	bool plot;
+	bool absolute_windowing;
 	enum mode_t mode;
 	double winhigh;
 	double winlow;
@@ -97,11 +98,19 @@ struct view_s {
 	GtkWidget* gtk_viewport;
 	GtkAdjustment* gtk_winlow;
 	GtkAdjustment* gtk_winhigh;
+	GtkSpinButton* gtk_button_winlow;
+	GtkSpinButton* gtk_button_winhigh;
+	GtkToolItem* toolbar_scale1;
+	GtkToolItem* toolbar_scale2;
+	GtkToolItem* toolbar_button1;
+	GtkToolItem* toolbar_button2;
 	GtkAdjustment* gtk_zoom;
 	GtkAdjustment* gtk_aniso;
 	GtkEntry* gtk_entry;
 	GtkToggleToolButton* gtk_transpose;
 	GtkToggleToolButton* gtk_fit;
+	GtkToggleToolButton* gtk_sync;
+	GtkToggleToolButton* gtk_absolutewindowing;
 
 	GtkAdjustment* gtk_posall[DIMS];
 	GtkCheckButton* gtk_checkall[DIMS];
@@ -116,7 +125,7 @@ struct view_s {
 };
 
 
-
+#if 0
 static void add_text(cairo_surface_t* surface, int x, int y, int size, const char* text)
 {
 	cairo_t* cr = cairo_create(surface);
@@ -143,7 +152,7 @@ static void add_text(cairo_surface_t* surface, int x, int y, int size, const cha
 	g_object_unref(layout);
 	cairo_destroy(cr);
 }
-
+#endif
 
 extern void update_geom(struct view_s* v)
 {
@@ -241,18 +250,61 @@ extern void view_setpos(struct view_s* v, unsigned int flags, const long pos[DIM
 
 extern void view_refresh(struct view_s* v)
 {
-	v->invalid = true;
+	if (v->absolute_windowing) {
+
+		long idims[DIMS];
+		md_select_dims(DIMS, MD_BIT(v->xdim) | MD_BIT(v->ydim), idims, v->dims);
+	
+		complex float* tmp = md_alloc(DIMS, idims, sizeof(complex float));
+		
+		long pos[DIMS];
+		md_copy_dims(DIMS, pos, v->pos);
+		pos[v->xdim] = 0;
+		pos[v->ydim] = 0;
+
+		md_slice(DIMS, ~(MD_BIT(v->xdim) | MD_BIT(v->ydim)), pos, v->dims, tmp, v->data, sizeof(complex float));
+
+		long size = md_calc_size(DIMS, idims);
+
+		double max = 0.;
+		for (long j = 0; j < size; j++)
+			if (max < cabsf(tmp[j]))
+				max = cabsf(tmp[j]);
+
+		max = MIN(1.e10, max);
+
+		md_free(tmp);
+
+		if (0 == v->max) {
+
+			gtk_adjustment_set_upper(v->gtk_winhigh, max);
+			gtk_adjustment_set_value(v->gtk_winhigh, max);
+			gtk_adjustment_set_upper(v->gtk_winlow, max);
+			v->max = max;
+		}
+
+		if (v->max < max) {
 
-	long size = md_calc_size(DIMS, v->dims);
-	double max = 0.;
-	for (long j = 0; j < size; j++)
-		if (max < cabsf(v->data[j]))
-			max = cabsf(v->data[j]);
+			gtk_adjustment_set_upper(v->gtk_winhigh, max);
+			gtk_adjustment_set_upper(v->gtk_winlow, max);
+			v->max = max;
+		}
+	} else {
+
+		long size = md_calc_size(DIMS, v->dims);
+		double max = 0.;
+
+		for (long j = 0; j < size; j++)
+			if (max < cabsf(v->data[j]))
+				max = cabsf(v->data[j]);
+		
+		max = MIN(1.e10, max);
 
-	if (0. == max)
-		max = 1.;
+		if (0. == max)
+			max = 1.;
 
-	v->max = max;
+		v->max = max;
+	}
 
 	update_view(v);
 }
@@ -281,6 +333,14 @@ extern gboolean geom_callback(GtkWidget *widget, gpointer data)
 	UNUSED(widget);
 	struct view_s* v = data;
 
+
+	// Avoid calling this function from itself.
+	// Toggling the GTK_TOOGLE_BUTTONs below would normally lead to another call of this function.
+	static bool in_callback = false;
+	if (in_callback)
+		return FALSE;
+	in_callback = true;
+
 	for (int j = 0; j < DIMS; j++) {
 
 		v->pos[j] = gtk_adjustment_get_value(v->gtk_posall[j]);
@@ -289,10 +349,10 @@ extern gboolean geom_callback(GtkWidget *widget, gpointer data)
 		if (!check)
 			continue;
 
-		if (1 == v->dims[j])
+		if (1 == v->dims[j]) {
+
 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(v->gtk_checkall[j]), FALSE);
-		else
-		if ((j != v->xdim) && (j != v->ydim)) {
+		} else if ((j != v->xdim) && (j != v->ydim)) {
 
 			for (int i = 0; i < DIMS; i++) {
 
@@ -353,6 +413,7 @@ extern gboolean geom_callback(GtkWidget *widget, gpointer data)
 	update_geom(v);
 	update_view(v);
 
+	in_callback = false;
 	return FALSE;
 }
 
@@ -390,38 +451,15 @@ static void update_buf_view(struct view_s* v)
 }
 
 
-static const char* spec = "xyzcmnopqsfrtuvw";
-
 extern gboolean save_callback(GtkWidget *widget, gpointer data)
 {
 	UNUSED(widget);
 	struct view_s* v = data;
-	
-	int len = 0;
-
-	len += snprintf(NULL, 0, "%s_", v->name);
-
-	for (int i = 0; i < DIMS; i++)
-		if ((v->dims[i] != 1) && (i != v->xdim) && (i != v->ydim))
-			len += snprintf(NULL, 0, "%c%04ld", spec[i], v->pos[i]);
-
-	len += snprintf(NULL, 0, ".png");
-
-	len++;
-
-	char* name = xmalloc(len);
-
-	int off = 0;
-
-	off += snprintf(name + off, len - off, "%s_", v->name);
-
-	for (int i = 0; i < DIMS; i++)
-		if ((v->dims[i] != 1) && (i != v->xdim) && (i != v->ydim))
-			off += snprintf(name + off, len - off, "%c%04ld", spec[i], v->pos[i]);
-
-	off += snprintf(name + off, len - off, ".png");
 
+	long loopdims[DIMS];
+	md_select_dims(DIMS, ~(MD_BIT(v->xdim) | MD_BIT(v->ydim)), loopdims, v->dims);
 
+	char* name = construct_filename_view(DIMS, loopdims, v->pos, v->name, "png");
 
 	v->dialog = gtk_file_chooser_dialog_new("Save File",
                                       v->window,
@@ -619,7 +657,7 @@ extern gboolean draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data)
 
 		(v->plot ? draw_plot : draw)(v->rgbw, v->rgbh, v->rgbstr,
 			(unsigned char(*)[v->rgbw][v->rgbstr / 4][4])v->rgb,
-			v->mode, 1. / v->max, v->winlow, v->winhigh, v->phrot,
+			v->mode, v->absolute_windowing ? 1. : 1. / v->max, v->winlow, v->winhigh, v->phrot,
 			v->rgbw, v->buf);
 
 		v->rgb_invalid = false;
@@ -688,7 +726,7 @@ struct view_s* create_view(const char* name, const long pos[DIMS], const long di
 	v->status_bar = false;
 
 	v->name = name;
-	v->max = 1.;
+	v->max = 0.;
 
 	v->pos = xmalloc(DIMS * sizeof(long));
 
@@ -748,7 +786,7 @@ extern gboolean toggle_sync(GtkToggleButton* button, gpointer data)
 {
 	UNUSED(button);
 	struct view_s* v = data;
-	v->sync = !v->sync;
+	v->sync = gtk_toggle_tool_button_get_active(v->gtk_sync);
 
 	return FALSE;
 }
@@ -769,6 +807,63 @@ extern gboolean toggle_plot(GtkToggleButton* button, gpointer data)
 	return FALSE;
 }
 
+static void set_windowing(struct view_s* v)
+{
+	double max = v->absolute_windowing ? v->max : 1;
+	max = MIN(1.e10, max);
+	double inc = exp(log(10) * round(log(max) / log(10.))) * 0.001;
+	int digits =  MAX(3, 3 - (int)round(log(max) / log(10.)));
+
+	gtk_adjustment_configure(v->gtk_winhigh, v->winhigh, 0, max, inc, gtk_adjustment_get_page_increment(v->gtk_winhigh), gtk_adjustment_get_page_size(v->gtk_winhigh));
+	gtk_adjustment_configure(v->gtk_winlow, v->winlow, 0, max, inc, gtk_adjustment_get_page_increment(v->gtk_winlow), gtk_adjustment_get_page_size(v->gtk_winlow));
+	gtk_spin_button_set_digits(v->gtk_button_winhigh, digits);
+	gtk_spin_button_set_digits(v->gtk_button_winlow, digits);
+
+	gtk_widget_set_visible(GTK_WIDGET(v->toolbar_scale1), v->absolute_windowing ? FALSE : TRUE);
+	gtk_widget_set_visible(GTK_WIDGET(v->toolbar_scale2), v->absolute_windowing ? FALSE : TRUE);
+	gtk_widget_set_visible(GTK_WIDGET(v->toolbar_button1), v->absolute_windowing ? TRUE : FALSE);
+	gtk_widget_set_visible(GTK_WIDGET(v->toolbar_button2), v->absolute_windowing ? TRUE : FALSE);
+}
+
+extern gboolean toogle_absolute_windowing(GtkToggleToolButton* button, gpointer data)
+{
+	UNUSED(button);
+	struct view_s* v = data;
+
+	if ((TRUE == gtk_toggle_tool_button_get_active(button)) == v->absolute_windowing)
+		return FALSE;
+
+	if (v->absolute_windowing) {
+
+		long size = md_calc_size(DIMS, v->dims);
+		double max = 0.;
+		
+		for (long j = 0; j < size; j++)
+			if (max < cabsf(v->data[j]))
+				max = cabsf(v->data[j]);
+
+		max = MIN(1.e10, max);
+
+		if (0. == max)
+			max = 1.;
+
+		v->max = max;
+		v->winhigh = MIN(v->winhigh / v->max, 1);
+		v->winlow = MIN(v->winlow / v->max, 1);
+
+		v->absolute_windowing = false;
+	} else {
+
+		v->winhigh *= v->max;
+		v->winlow *= v->max;
+		v->absolute_windowing = true;
+	}
+
+	set_windowing(v);
+
+	return FALSE;
+}
+
 
 extern void set_position(struct view_s* v, unsigned int dim, unsigned int p)
 {
@@ -831,8 +926,8 @@ extern gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gp
 			double low = gtk_adjustment_get_value(v->gtk_winlow);
 			double high = gtk_adjustment_get_value(v->gtk_winhigh);
 
-			low -= (x - v->lastx) / 200.;
-			high -= (y - v->lasty) / 200.;
+			low -= (x - v->lastx) * gtk_adjustment_get_step_increment(v->gtk_winlow) * 5;
+			high -= (y - v->lasty) * gtk_adjustment_get_step_increment(v->gtk_winhigh) * 5;
 
 			if (high > low) {
 
@@ -891,7 +986,7 @@ extern gboolean window_close(GtkWidget *widget, GdkEvent* event, gpointer data)
 
 
 
-extern struct view_s* window_new(const char* name, const long pos[DIMS], const long dims[DIMS], const complex float* x)
+extern struct view_s* window_new(const char* name, const long pos[DIMS], const long dims[DIMS], const complex float* x, bool absolute_windowing)
 {
 	struct view_s* v = create_view(name, pos, dims, x);
 
@@ -927,9 +1022,25 @@ extern struct view_s* window_new(const char* name, const long pos[DIMS], const l
 	gtk_combo_box_set_active(v->gtk_interp, 0);
     
 	v->gtk_transpose = GTK_TOGGLE_TOOL_BUTTON(gtk_builder_get_object(builder, "transpose"));
+	gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(v->gtk_transpose), TRUE);
 	v->gtk_fit = GTK_TOGGLE_TOOL_BUTTON(gtk_builder_get_object(builder, "fit"));
 	gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(v->gtk_fit), TRUE);
 
+	v->gtk_sync = GTK_TOGGLE_TOOL_BUTTON(gtk_builder_get_object(builder, "sync"));
+	gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(v->gtk_sync), v->sync ? TRUE : FALSE);
+
+	v->gtk_button_winlow = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "scale1_button"));
+	v->gtk_button_winhigh = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "scale2_button"));
+
+	v->toolbar_scale1 = GTK_TOOL_ITEM(gtk_builder_get_object(builder, "toolbar_scale1"));
+	v->toolbar_scale2 = GTK_TOOL_ITEM(gtk_builder_get_object(builder, "toolbar_scale2"));
+	v->toolbar_button1 = GTK_TOOL_ITEM(gtk_builder_get_object(builder, "toolbar_button1"));
+	v->toolbar_button2 = GTK_TOOL_ITEM(gtk_builder_get_object(builder, "toolbar_button2"));
+
+	v->absolute_windowing = absolute_windowing;
+	v->gtk_absolutewindowing = GTK_TOGGLE_TOOL_BUTTON(gtk_builder_get_object(builder, "abswindow"));
+	gtk_toggle_tool_button_set_active(v->gtk_absolutewindowing , absolute_windowing ? TRUE : FALSE);
+
 	for (int j = 0; j < DIMS; j++) {
 
 		char pname[10];
@@ -964,6 +1075,7 @@ extern struct view_s* window_new(const char* name, const long pos[DIMS], const l
 	refresh_callback(NULL, v);
 	geom_callback(NULL, v);
 	window_callback(NULL, v);
+	set_windowing(v);
 
 	return v;
 }
@@ -981,7 +1093,7 @@ void window_connect_sync(struct view_s* v, struct view_s* v2)
 
 struct view_s* view_clone(struct view_s* v, const long pos[DIMS])
 {
-	struct view_s* v2 = window_new(v->name, pos, v->dims, v->data);
+	struct view_s* v2 = window_new(v->name, pos, v->dims, v->data, v->absolute_windowing);
 
 	window_connect_sync(v, v2);
 


=====================================
src/view.h
=====================================
@@ -5,7 +5,7 @@
 
 struct view_s;
 
-extern struct view_s* window_new(const char* name, const long pos[DIMS], const long dims[DIMS], const complex float* x);
+extern struct view_s* window_new(const char* name, const long pos[DIMS], const long dims[DIMS], const complex float* x, _Bool absolute_windowing);
 
 extern void view_add_geometry(struct view_s* v, unsigned long flags, const float (*geom)[3][3]);
 extern void window_connect_sync(struct view_s* a, struct view_s* b);


=====================================
src/viewer.ui
=====================================
@@ -35,6 +35,9 @@
       <row>
         <col id="0" translatable="yes">REAL</col>
       </row>
+      <row>
+        <col id="0" translatable="yes">MAGNITUDE (turbo)</col>
+      </row>
       <row>
         <col id="0" translatable="yes">FLOW</col>
       </row>
@@ -69,6 +72,9 @@
       <row>
         <col id="0" translatable="yes">NLIN</col>
       </row>
+      <row>
+        <col id="0" translatable="yes">NLINMAG</col>
+      </row>
       <row>
         <col id="0" translatable="yes">NEAREST</col>
       </row>
@@ -368,7 +374,7 @@
               </packing>
             </child>
             <child>
-              <object class="GtkToggleToolButton" id="toolbutton13">
+              <object class="GtkToggleToolButton" id="sync">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="label" translatable="yes">sync</property>
@@ -395,6 +401,20 @@
                 <property name="homogeneous">True</property>
               </packing>
             </child>
+	    <child>
+              <object class="GtkToggleToolButton" id="abswindow">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">absolute windowing</property>
+                <property name="use_underline">True</property>
+                <property name="stock_id">gtk-italic</property>
+                <signal name="clicked" handler="toogle_absolute_windowing" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">True</property>
+              </packing>
+            </child>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -408,7 +428,7 @@
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <child>
-              <object class="GtkToolItem" id="toolbutton6">
+              <object class="GtkToolItem" id="toolbar_scale1">
                 <property name="width_request">100</property>
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
@@ -435,7 +455,29 @@
               </packing>
             </child>
             <child>
-              <object class="GtkToolItem" id="toolbutton7">
+              <object class="GtkToolItem" id="toolbar_button1">
+                <property name="width_request">100</property>
+                <property name="visible">False</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <child>
+		 <object class="GtkSpinButton" id="scale1_button">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="adjustment">winlow</property>
+                    	<property name="digits">3</property>
+                    	<property name="snap_to_ticks">False</property>
+                            <signal name="value-changed" handler="window_callback" swapped="no"/>
+                          </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolItem" id="toolbar_scale2">
                 <property name="width_request">100</property>
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
@@ -462,6 +504,28 @@
               </packing>
             </child>
             <child>
+              <object class="GtkToolItem" id="toolbar_button2">
+                <property name="width_request">100</property>
+                <property name="visible">False</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <child>
+		 <object class="GtkSpinButton" id="scale2_button">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="adjustment">winhigh</property>
+                    	<property name="digits">3</property>
+                    	<property name="snap_to_ticks">False</property>
+                            <signal name="value-changed" handler="window_callback" swapped="no"/>
+                          </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">True</property>
+              </packing>
+            </child>
+	    <child>
               <object class="GtkToolItem" id="toolbutton1">
                 <property name="width_request">100</property>
                 <property name="visible">True</property>



View it on GitLab: https://salsa.debian.org/med-team/bart-view/-/compare/2b21d8ece0fde51de9931a72d61e87481d35554b...9f1267ab64b6d1f41eb80a8efd96fc848a0c3071

-- 
View it on GitLab: https://salsa.debian.org/med-team/bart-view/-/compare/2b21d8ece0fde51de9931a72d61e87481d35554b...9f1267ab64b6d1f41eb80a8efd96fc848a0c3071
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20240110/eea00da4/attachment-0001.htm>


More information about the debian-med-commit mailing list