/*  GNU Ocrad - Optical Character Recognition program
    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Antonio Diaz Diaz.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

class Mask;
class Rational;
class Track;

class Page_image : public Rectangle		// left,top is always 0,0
  {
public:
  struct Error
    {
    const char * s;
    Error( const char * p ) : s( p ) {}
    };

private:
  std::vector< std::vector< unsigned char > > data;	// 256 level greymap
  unsigned char maxval_, threshold_;		// x > threshold == white

  void read_p1( FILE * f, const bool invert ) throw( Error );
  void read_p4( FILE * f, const bool invert ) throw( Error );
  void read_p2( FILE * f, const Rational & th, const bool invert ) throw( Error );
  void read_p5( FILE * f, const Rational & th, const bool invert ) throw( Error );
  void read_p3( FILE * f, const Rational & th, const bool invert ) throw( Error );
  void read_p6( FILE * f, const Rational & th, const bool invert ) throw( Error );

public:
  // Creates a Page_image from a pbm, pgm or ppm file
  Page_image( FILE * f, const Rational & th, const bool invert ) throw( Error );

  // Creates a reduced Page_image
  Page_image( const Page_image & source, const int scale ) throw();

  using Rectangle::left;
  using Rectangle::top;
  using Rectangle::right;
  using Rectangle::bottom;
  using Rectangle::height;
  using Rectangle::width;
  void left  ( int ) throw( Error ) { throw Error( "Page_image resize not allowed." ); }
  void top   ( int ) throw( Error ) { left( 0 ); }
  void right ( int ) throw( Error ) { left( 0 ); }
  void bottom( int ) throw( Error ) { left( 0 ); }
  void height( int ) throw( Error ) { left( 0 ); }
  void width ( int ) throw( Error ) { left( 0 ); }

  bool get_bit( const int row, const int col ) const throw()
    { return data[row-top()][col-left()] <= threshold_; }
  bool get_bit( const int row, const int col, const unsigned char th ) const throw()
    { return data[row-top()][col-left()] <= th; }
  void set_bit( const int row, const int col, const bool bit ) throw()
    { data[row-top()][col-left()] = ( bit ? 0 : maxval_ ); }

  unsigned char maxval() const throw() { return maxval_; }
  unsigned char threshold() const throw() { return threshold_; }

  bool crop( const Rational ltrb[4], const Rational & th ) throw();
  void draw_mask( const Mask & m ) throw();
  void draw_rectangle( const Rectangle & re ) throw();
  void draw_track( const Track & tr ) throw();
  bool save( FILE * f, const char filetype ) const throw();
  bool scale( int n ) throw( Error );
  void transform( const Transformation & t ) throw();
  };
