43 m_map_current(dx*dy) ,
50 G_ASSERT( m_dx > 0 && m_dy > 0 ) ;
54 findOrCreate( create ) ;
65 sample( image_data , info ) ;
71 for(
Gr::Scaler y_scaler(m_dy,info.
dy()) ; !!y_scaler ; ++y_scaler )
73 for(
Gr::Scaler x_scaler(m_dx,info.
dx()) ; !!x_scaler ; ++x_scaler )
77 bool masked = 0 == image_data.
r( x_scaler.second() , y_scaler.second() ) ;
78 if( masked ) m_empty = false ;
79 m_map[ y_scaler.first() * m_dx + x_scaler.first() ] = masked ;
84 void Gv::Mask::findOrCreate(
bool create )
91 G_DEBUG(
"Gv::Mask::ctor: exists=" << exists ) ;
92 if( !exists && !create )
93 throw std::runtime_error(
"cannot open mask file [" + m_path.str() +
"]" ) ;
98 void Gv::Mask::open( std::ifstream & file )
102 file.open( m_path.str().c_str() ) ;
111 reader.
decode( image_data , file ) ;
112 info = reader.
info() ;
113 G_DEBUG(
"Gv::Mask::ctor: P" << info.
pn() ) ;
115 catch( std::exception & )
117 G_ASSERT( !info.
valid() ) ;
119 if( !info.
valid() || ( info.
pn() != 1 && info.
pn() != 4 ) )
120 throw std::runtime_error(
"invalid mask file format: [" + m_path.str() +
"] is not a pgm bitmap" ) ;
136 G_DEBUG(
"Gv::Mask::write: writing [" << path <<
"]" ) ;
140 f.open( path.
str().c_str() , std::ios_base::trunc ) ;
143 throw std::runtime_error(
"cannot write mask file [" + path.
str() +
"]" ) ;
146 f << m_dx <<
" " << m_dy <<
"\n" ;
147 for(
int y = 0 ; y < m_dy ; y++ )
149 const char * sep =
"" ;
150 for(
int x = 0 ; x < m_dx ; x++ , sep =
" " )
152 f << sep << (m_map[y*m_dx+x]?
"1":
"0") ;
156 f <<
"\n" << std::flush ;
158 throw std::runtime_error(
"cannot write mask file [" + path.
str() +
"]" ) ;
161 int Gv::Mask::clip_x(
int x )
const
163 return std::min( std::max(0,x) , m_dx-1 ) ;
166 int Gv::Mask::clip_y(
int y )
const
168 return std::min( std::max(0,y) , m_dy-1 ) ;
174 m_down_x = m_move_x = clip_x( x ) ;
175 m_down_y = m_move_y = clip_y( y ) ;
176 m_down_shift = shift ;
183 fill( m_map_current , m_down_x , m_down_y , m_move_x , m_move_y ,
false ) ;
184 m_move_x = clip_x(x) ;
185 m_move_y = clip_y(y) ;
186 fill( m_map_current , m_down_x , m_down_y , m_move_x , m_move_y ,
true ) ;
190 bool Gv::Mask::fill( std::vector<bool> & map ,
int x0 ,
int y0 ,
int x1 ,
int y1 ,
bool b )
192 bool changed = false ;
193 for(
int x = std::min(x0,x1) ; x < std::max(x0,x1) ; x++ )
195 for(
int y = std::min(y0,y1) ; y < std::max(y0,y1) ; y++ )
197 size_t offset = y*m_dx+x ;
198 if( !changed && (map[offset]!= b) ) changed =
true ;
208 m_map_current.assign( m_map_current.size() , false ) ;
209 if( fill( m_map , m_down_x , m_down_y , clip_x(up_x) , clip_y(up_y) , !m_down_shift ) && !m_down_shift )
222 if( m_file_time ==
G::EpochTime(0) || new_time != m_file_time )
231 file.open( m_path.str().c_str() ) ;
233 info = read( file , image_data ) ;
235 catch( std::exception & e )
239 sample( image_data , info ) ;
240 m_file_time = new_time ;
std::string str() const
Returns the path string.
A subsecond-resolution timestamp based on a time_t.
bool valid() const
Returns true if successfully constructed.
int dx() const
Returns the image width.
A holder for image data, having eight bits per sample and one or three channels.
unsigned char r(int x, int y) const
Returns the R-value for a point.
int pn() const
Returns the p-number.
A class which acquires the process's special privileges on construction and releases them on destruct...
void up(int x, int y, bool shift, bool control)
Called on mouse-up. Commits any down()/move() edits.
A class that allows for iterating over one integer range while accessing values from another...
void move(int x, int y)
Called on mouse-move. Modifies the current edit.
bool empty() const
Returns true if empty.
G::EpochTime time() const
Returns the timestamp on the mask file at construction, not affected by any calls to write()...
bool update()
Updates the mask from the file. Returns true if updated.
int dy() const
Returns the image height.
void decode(ImageData &out, const G::Path &in)
Decodes a pnm file into an image. Throws on error.
void write(const G::Path &filename) const
Writes to file.
static bool exists(const Path &file)
Returns true if the file (directory, device etc.) exists.
Mask(int dx, int dy, const std::string &file=std::string(), bool create=false)
Constructor, optionally reading the mask from an existing file.
An overload discriminator class for File methods.
void down(int x, int y, bool shift, bool control)
Called on mouse-down. Starts an edit.
A structure holding portable-anymap metadata.
static EpochTime time(const Path &file)
Returns the file's timestamp.
A static interface for reading portable-anymap (pnm) files.
const PnmInfo & info() const
Returns the pnm header info, ignoring scaling.
A Path object represents a file system path.