1-
2-
31use crate :: sampler3d;
42
5-
63pub struct MetaDataWidget < ' a > {
74 pub image_sampler : & ' a sampler3d:: Sampler3D ,
85 pub entries : Vec < ( String , String ) > ,
@@ -13,21 +10,82 @@ impl<'a> MetaDataWidget<'a> {
1310 pub fn new ( image_sampler : & ' a sampler3d:: Sampler3D ) -> Self {
1411 let ndim = image_sampler. header . dim [ 0 ] as usize ;
1512 let entries: Vec < ( String , String ) > = vec ! [
16- ( "Data type" . to_owned( ) , format!( "{:?}" , image_sampler. header. data_type( ) . unwrap( ) ) ) ,
17- ( "Ndim" . to_owned( ) , format!( "{}" , image_sampler. header. dim[ 0 ] ) ) ,
18- ( "Shape" . to_owned( ) , format!( "{:?}" , & image_sampler. header. dim[ 1 ..ndim + 1 ] ) ) ,
19- ( "Units" . to_owned( ) , format!( "{:?} (space); {:?} (time)" , & image_sampler. header. xyzt_to_space( ) . unwrap_or( nifti:: Unit :: Unknown ) , & image_sampler. header. xyzt_to_time( ) . unwrap_or( nifti:: Unit :: Unknown ) ) ) ,
20-
21- ( "Data scaling" . to_owned( ) , format!( "{} + {} * x" , image_sampler. header. scl_inter, image_sampler. header. scl_slope) ) ,
22- ( "Display range" . to_owned( ) , format!( "[{}, {}]" , image_sampler. header. cal_min, image_sampler. header. cal_max) ) ,
23- ( "Description" . to_owned( ) , format!( "'{}'" , String :: from_utf8( image_sampler. header. descrip. clone( ) ) . unwrap_or( "<error>" . to_owned( ) ) ) ) ,
24- ( "Intent" . to_owned( ) , format!( "'{}'" , String :: from_utf8( image_sampler. header. intent_name. to_vec( ) ) . unwrap_or( "<error>" . to_owned( ) ) ) ) ,
25- ( "Slice order" . to_owned( ) , format!( "{:?}" , & image_sampler. header. slice_order( ) . unwrap_or( nifti:: SliceOrder :: Unknown ) ) ) ,
26- ( "Slice duration" . to_owned( ) , format!( "{}" , image_sampler. header. slice_duration) ) ,
27- ( "Affine" . to_owned( ) , format!( "{:?}" , & image_sampler. header. srow_x) ) ,
13+ (
14+ "Data type" . to_owned( ) ,
15+ format!( "{:?}" , image_sampler. header. data_type( ) . unwrap( ) ) ,
16+ ) ,
17+ (
18+ "Ndim" . to_owned( ) ,
19+ format!( "{}" , image_sampler. header. dim[ 0 ] ) ,
20+ ) ,
21+ (
22+ "Shape" . to_owned( ) ,
23+ format!( "{:?}" , & image_sampler. header. dim[ 1 ..ndim + 1 ] ) ,
24+ ) ,
25+ (
26+ "Units" . to_owned( ) ,
27+ format!(
28+ "{:?} (space); {:?} (time)" ,
29+ & image_sampler
30+ . header
31+ . xyzt_to_space( )
32+ . unwrap_or( nifti:: Unit :: Unknown ) ,
33+ & image_sampler
34+ . header
35+ . xyzt_to_time( )
36+ . unwrap_or( nifti:: Unit :: Unknown )
37+ ) ,
38+ ) ,
39+ (
40+ "Data scaling" . to_owned( ) ,
41+ format!(
42+ "{} + {} * x" ,
43+ image_sampler. header. scl_inter, image_sampler. header. scl_slope
44+ ) ,
45+ ) ,
46+ (
47+ "Display range" . to_owned( ) ,
48+ format!(
49+ "[{}, {}]" ,
50+ image_sampler. header. cal_min, image_sampler. header. cal_max
51+ ) ,
52+ ) ,
53+ (
54+ "Description" . to_owned( ) ,
55+ format!(
56+ "'{}'" ,
57+ String :: from_utf8( image_sampler. header. descrip. clone( ) )
58+ . unwrap_or( "<error>" . to_owned( ) )
59+ ) ,
60+ ) ,
61+ (
62+ "Intent" . to_owned( ) ,
63+ format!(
64+ "'{}'" ,
65+ String :: from_utf8( image_sampler. header. intent_name. to_vec( ) )
66+ . unwrap_or( "<error>" . to_owned( ) )
67+ ) ,
68+ ) ,
69+ (
70+ "Slice order" . to_owned( ) ,
71+ format!(
72+ "{:?}" ,
73+ & image_sampler
74+ . header
75+ . slice_order( )
76+ . unwrap_or( nifti:: SliceOrder :: Unknown )
77+ ) ,
78+ ) ,
79+ (
80+ "Slice duration" . to_owned( ) ,
81+ format!( "{}" , image_sampler. header. slice_duration) ,
82+ ) ,
83+ (
84+ "Affine" . to_owned( ) ,
85+ format!( "{:?}" , & image_sampler. header. srow_x) ,
86+ ) ,
2887 ( "" . to_owned( ) , format!( "{:?}" , & image_sampler. header. srow_y) ) ,
2988 ( "" . to_owned( ) , format!( "{:?}" , & image_sampler. header. srow_z) ) ,
30-
3189 ] ;
3290
3391 let max_key_len = entries. iter ( ) . map ( |( k, _) | k. len ( ) ) . max ( ) . unwrap ( ) ;
@@ -42,17 +100,34 @@ impl<'a> MetaDataWidget<'a> {
42100
43101impl tui:: widgets:: Widget for MetaDataWidget < ' _ > {
44102 fn render ( self , area : tui:: layout:: Rect , buf : & mut tui:: buffer:: Buffer ) {
45-
46-
47103 for ( i, ( key, val) ) in self . entries . iter ( ) . enumerate ( ) {
48- if i < ( area. height -1 ) as usize {
49- buf. set_stringn ( area. x , area. y + i as u16 , key, self . max_key_len , tui:: style:: Style :: default ( ) . fg ( tui:: style:: Color :: Cyan ) . add_modifier ( tui:: style:: Modifier :: BOLD ) ) ;
50- buf. set_stringn ( area. x + self . max_key_len as u16 + 1 , area. y + i as u16 , val, area. width . into ( ) , tui:: style:: Style :: default ( ) ) ;
51- } else if i == ( area. height -1 ) as usize {
52- buf. set_stringn ( area. x + 1 , area. y + i as u16 , "[...]" , area. width . into ( ) , tui:: style:: Style :: default ( ) ) ;
104+ if i < ( area. height - 1 ) as usize {
105+ buf. set_stringn (
106+ area. x ,
107+ area. y + i as u16 ,
108+ key,
109+ self . max_key_len ,
110+ tui:: style:: Style :: default ( )
111+ . fg ( tui:: style:: Color :: Cyan )
112+ . add_modifier ( tui:: style:: Modifier :: BOLD ) ,
113+ ) ;
114+ buf. set_stringn (
115+ area. x + self . max_key_len as u16 + 1 ,
116+ area. y + i as u16 ,
117+ val,
118+ area. width . into ( ) ,
119+ tui:: style:: Style :: default ( ) ,
120+ ) ;
121+ } else if i == ( area. height - 1 ) as usize {
122+ buf. set_stringn (
123+ area. x + 1 ,
124+ area. y + i as u16 ,
125+ "[...]" ,
126+ area. width . into ( ) ,
127+ tui:: style:: Style :: default ( ) ,
128+ ) ;
53129 }
54130 }
55-
56131 }
57132}
58133
@@ -89,16 +164,15 @@ impl<'a> SliceWidget<'a> {
89164 }
90165}
91166
92-
93- pub fn colorous2tui ( value : colorous:: Color ) ->tui:: style:: Color {
167+ pub fn colorous2tui ( value : colorous:: Color ) -> tui:: style:: Color {
94168 tui:: style:: Color :: Rgb ( value. r , value. g , value. b )
95169}
96170
97171pub fn invert_color ( value : colorous:: Color ) -> colorous:: Color {
98- colorous:: Color {
99- r : 255 - value. r ,
100- g : 255 - value. g ,
101- b : 255 - value. b
172+ colorous:: Color {
173+ r : 255 - value. r ,
174+ g : 255 - value. g ,
175+ b : 255 - value. b ,
102176 }
103177}
104178
@@ -116,7 +190,7 @@ pub fn position_2d<T>(position: &Vec<T>, axis: usize) -> (&T, &T, &T) {
116190 2 => 1 ,
117191 _ => panic ! ( "Unsupported axis" ) ,
118192 } ] ;
119- return ( index, x_index, y_index)
193+ return ( index, x_index, y_index) ;
120194}
121195
122196lazy_static ! {
@@ -135,7 +209,6 @@ impl tui::widgets::Widget for SliceWidget<'_> {
135209 } ;
136210
137211 let ( index, x_index, y_index) = position_2d ( & self . slice_position , self . axis ) ;
138-
139212
140213 let sample = sampler3d:: ImageSample :: new (
141214 text_area. width ,
@@ -164,45 +237,75 @@ impl tui::widgets::Widget for SliceWidget<'_> {
164237 ( ( * y_index as f32 / img_sized_limits. 1 as f32 ) * ( img_sized. height ( ) ) as f32 ) as u32 ;
165238
166239 // write img_sized into buf
167- for y in ( 0 ..( ( img_sized. height ( ) / 2 ) * 2 ) ) . step_by ( 2 ) {
240+ for y in ( 0 ..( ( img_sized. height ( ) / 2 ) * 2 ) ) . step_by ( 2 ) {
168241 for x in 0 ..img_sized. width ( ) {
169- let ( ix, iy) : ( u16 , u16 ) = ( ( x + x_offset) as u16 , ( ( y + y_offset) / 2 ) as u16 ) ;
170- let val_upper = img_sized. get_pixel ( x, y+ 1 ) [ 0 ] as usize ;
242+ let ( ix, iy) : ( u16 , u16 ) = ( ( x + x_offset) as u16 , ( ( y + y_offset) / 2 ) as u16 ) ;
243+ let val_upper = img_sized. get_pixel ( x, y + 1 ) [ 0 ] as usize ;
171244 let val_lower = img_sized. get_pixel ( x, y) [ 0 ] as usize ;
172245
173246 let gradient = colorous:: INFERNO ;
174247 let col_upper = gradient. eval_rational ( val_upper, u16:: MAX as usize + 1 ) ;
175248 let col_lower = gradient. eval_rational ( val_lower, u16:: MAX as usize + 1 ) ;
176249
177- let c = buf
178- . get_mut ( text_area. left ( ) + ix, text_area. bottom ( ) - iy - 1 ) ;
179-
250+ let c = buf. get_mut ( text_area. left ( ) + ix, text_area. bottom ( ) - iy - 1 ) ;
180251
181- let symb = tui:: widgets:: BorderType :: line_symbols ( tui:: widgets:: BorderType :: Rounded ) ;
252+ let symb =
253+ tui:: widgets:: BorderType :: line_symbols ( tui:: widgets:: BorderType :: Rounded ) ;
182254
183- let crossair_y = ( y/ 2 ) == ( y_index_scaled/ 2 ) ;
255+ let crossair_y = y / 2 * 2 == y_index_scaled / 2 * 2 ;
184256 let crossair_x = x == x_index_scaled;
185257
186258 if crossair_x || crossair_y {
187- let col_average = gradient. eval_rational ( ( val_lower + val_upper) / 2 , u16:: MAX as usize + 1 ) ;
259+ let col_average =
260+ gradient. eval_rational ( ( val_lower + val_upper) / 2 , u16:: MAX as usize + 1 ) ;
188261 let col_inv = colorous2tui ( invert_color ( col_average) ) ;
189262 c. set_bg ( colorous2tui ( col_average) ) ;
190263
191264 match ( crossair_x, crossair_y) {
192- ( true , true ) => c. set_char ( symb. cross . chars ( ) . next ( ) . unwrap ( ) ) . set_fg ( col_inv) ,
193- ( true , false ) => c. set_char ( symb. vertical . chars ( ) . next ( ) . unwrap ( ) ) . set_fg ( col_inv) ,
194- ( false , true ) => c. set_char ( symb. horizontal . chars ( ) . next ( ) . unwrap ( ) ) . set_fg ( col_inv) ,
195- _ => panic ! ( )
265+ ( true , true ) => c
266+ . set_char ( symb. cross . chars ( ) . next ( ) . unwrap ( ) )
267+ . set_fg ( col_inv) ,
268+ ( true , false ) => c
269+ . set_char ( symb. vertical . chars ( ) . next ( ) . unwrap ( ) )
270+ . set_fg ( col_inv) ,
271+ ( false , true ) => c
272+ . set_char ( symb. horizontal . chars ( ) . next ( ) . unwrap ( ) )
273+ . set_fg ( col_inv) ,
274+ _ => panic ! ( ) ,
196275 } ;
197276
198- if x == 0 {
199- c. set_char ( position_2d :: < & str > ( & RAS_LABELS , self . axis ) . 1 . chars ( ) . nth ( 0 ) . unwrap ( ) ) ;
200- } else if y == 0 {
201- c. set_char ( position_2d :: < & str > ( & RAS_LABELS , self . axis ) . 2 . chars ( ) . nth ( 0 ) . unwrap ( ) ) ;
202- } else if y/2 == img_sized. height ( ) /2 -1 {
203- c. set_char ( position_2d :: < & str > ( & RAS_LABELS , self . axis ) . 2 . chars ( ) . nth ( 1 ) . unwrap ( ) ) ;
204- } else if x == img_sized. width ( ) -1 {
205- c. set_char ( position_2d :: < & str > ( & RAS_LABELS , self . axis ) . 1 . chars ( ) . nth ( 1 ) . unwrap ( ) ) ;
277+ if crossair_y && ( x == 0 ) {
278+ c. set_char (
279+ position_2d :: < & str > ( & RAS_LABELS , self . axis )
280+ . 1
281+ . chars ( )
282+ . nth ( 0 )
283+ . unwrap ( ) ,
284+ ) ;
285+ } else if crossair_x && ( y == 0 ) {
286+ c. set_char (
287+ position_2d :: < & str > ( & RAS_LABELS , self . axis )
288+ . 2
289+ . chars ( )
290+ . nth ( 0 )
291+ . unwrap ( ) ,
292+ ) ;
293+ } else if crossair_x && ( y / 2 == img_sized. height ( ) / 2 - 1 ) {
294+ c. set_char (
295+ position_2d :: < & str > ( & RAS_LABELS , self . axis )
296+ . 2
297+ . chars ( )
298+ . nth ( 1 )
299+ . unwrap ( ) ,
300+ ) ;
301+ } else if crossair_y && ( x == img_sized. width ( ) - 1 ) {
302+ c. set_char (
303+ position_2d :: < & str > ( & RAS_LABELS , self . axis )
304+ . 1
305+ . chars ( )
306+ . nth ( 1 )
307+ . unwrap ( ) ,
308+ ) ;
206309 }
207310 } else {
208311 c. set_bg ( colorous2tui ( col_upper) )
0 commit comments