VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gvviewerwindow_curses.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gvviewerwindow_curses.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gvviewerwindow_curses.h"
23 #include "grscaler.h"
24 #include "grcolourspace.h"
25 #include "gcleanup.h"
26 #include "gassert.h"
27 #include <exception>
28 #include <cstdlib> // putenv
29 #include <cstring> // strdup
30 #include <curses.h>
31 
32 namespace
33 {
34  void end_curses( G::SignalSafe , const char * )
35  {
36  static bool ended = false ;
37  if( !ended ) endwin() ;
38  ended = true ;
39  }
40 }
41 
43  m_handler(handler) ,
44  m_config(config) ,
45  m_mask(dx,dy,m_config.m_mask_file)
46 {
47  initscr() ;
48 
49  // unset lines and columns so that xterm resizing works
50  putenv( strdup( "COLUMNS=" ) ) ; // leak
51  putenv( strdup( "LINES=" ) ) ; // leak
52 
53  G::Cleanup::add( end_curses , 0 ) ;
54  cbreak() ;
55  if( has_colors() )
56  {
57  start_color() ;
58  init_pair( 1, COLOR_RED, COLOR_BLACK ) ;
59  init_pair( 2, COLOR_GREEN, COLOR_BLACK ) ;
60  init_pair( 3, COLOR_YELLOW, COLOR_BLACK ) ;
61  init_pair( 4, COLOR_BLUE, COLOR_BLACK ) ;
62  init_pair( 5, COLOR_MAGENTA, COLOR_BLACK ) ;
63  init_pair( 6, COLOR_CYAN, COLOR_BLACK ) ;
64  init_pair( 7, COLOR_WHITE, COLOR_BLACK ) ;
65  }
66 }
67 
69 {
70  end_curses( G::SignalSafe() , 0 ) ;
71 }
72 
74 {
75 }
76 
77 void Gv::ViewerWindowCurses::display( int data_dx , int data_dy , int data_channels , const char * data_p , size_t data_n )
78 {
79  int x = -1 ;
80  int y = -1 ;
81  for( Gr::Scaler y_scaler(LINES,data_dy) ; !!y_scaler ; ++y_scaler )
82  {
83  int display_y = y_scaler.first() ;
84  G_ASSERT( display_y < LINES ) ;
85  if( display_y == y )
86  continue ;
87  y = display_y ;
88 
89  for( Gr::Scaler x_scaler(COLS,data_dx) ; !!x_scaler ; ++x_scaler )
90  {
91  int display_x = x_scaler.first() ;
92  G_ASSERT( display_x < COLS ) ;
93  if( display_x == x )
94  continue ;
95  x = display_x ;
96 
97  int data_x = x_scaler.second() ;
98  int data_y = y_scaler.second() ;
99  G_ASSERT( data_x < data_dx ) ;
100  G_ASSERT( data_y < data_dy ) ;
101 
102  int data_offset = data_y * data_dx + data_x ;
103  if( data_channels != 1 )
104  data_offset *= data_channels ;
105  const unsigned char * p = reinterpret_cast<const unsigned char *>(data_p+data_offset) ;
106 
107  const unsigned int r = *p++ ;
108  const unsigned int g = data_channels > 1 ? *p++ : r ;
109  const unsigned int b = data_channels > 2 ? *p++ : r ;
110 
111  const unsigned int range = std::max(r,std::max(g,b)) ;
112  const unsigned int threshold = range/2U + range/4U ;
113  const unsigned int index = ((r>threshold)?1U:0U) | ((g>threshold)?2U:0U) | ((b>threshold)?4U:0U) ;
114  const chtype colour = m_mask.masked(data_x,data_y) ? COLOR_PAIR(1) : COLOR_PAIR(index) ;
115 
116  const unsigned int luma = Gr::ColourSpace::yuv_int(Gr::ColourSpace::triple<unsigned char>(r,g,b)).y() ;
117  static const char * luma_map = " .,:;|(){}%%$@@##" ;
118  const chtype c = luma_map[(luma/16U)%16U] ;
119 
120  move( display_y , display_x ) ;
121  addch( c | colour ) ;
122  }
123  }
124 
125  if( !m_config.m_title.empty() )
126  {
127  move( 0 , 1 ) ;
128  for( std::string::iterator p = m_config.m_title.begin() ; p != m_config.m_title.end() ; ++p )
129  addch( *p ) ;
130  move( 0 , 0 ) ;
131  }
132 
133  refresh() ;
134 }
135 
137 {
138  return COLS ;
139 }
140 
142 {
143  return LINES ;
144 }
145 
146 /// \file gvviewerwindow_curses.cpp
ViewerWindowCurses(ViewerWindowHandler &, ViewerWindowConfig, int dx, int dy)
Constructor.
virtual ~ViewerWindowCurses()
Destructor.
An empty structure that is used to indicate a signal-safe, reentrant implementation.
Definition: gsignalsafe.h:36
A class that allows for iterating over one integer range while accessing values from another...
Definition: grscaler.h:89
virtual void init() override
Override from ViewerWindow.
A configuration structure for Gv::ViewerWindow.
virtual void display(int, int, int, const char *, size_t) override
Override from ViewerWindow.
virtual int dy() const override
Override from ViewerWindow.
triple< unsigned char > yuv_int(triple< unsigned char > rgb) g__noexcept
A fast conversion from rgb to yuv.
static void add(void(*fn)(SignalSafe, const char *), const char *arg)
Adds the given handler to the list of handlers that are to be called when the process terminates abno...
A callback interface for Gv::ViewerWindow.
virtual int dx() const override
Override from ViewerWindow.