/* GNU Ocrad - Optical Character Recognition program
Copyright (C) 2003-2019 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 2 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 .
*/
#include
#include
#include
#include
#include
#include
#include "common.h"
#include "user_filter.h"
int verbosity = 0;
namespace {
const int charsets = 3;
const Charset::Value charset_value[charsets] =
{ Charset::ascii, Charset::iso_8859_9, Charset::iso_8859_15 };
const char * const charset_name[charsets] =
{ "ascii", "iso-8859-9", "iso-8859-15" };
struct F_entry
{
const char * const name;
Filter::Type type;
};
const F_entry F_table[] =
{
{ "letters", Filter::letters },
{ "letters_only", Filter::letters_only },
{ "numbers", Filter::numbers },
{ "numbers_only", Filter::numbers_only },
{ "same_height", Filter::same_height },
{ "text_block", Filter::text_block },
{ "upper_num", Filter::upper_num },
{ "upper_num_mark", Filter::upper_num_mark },
{ "upper_num_only", Filter::upper_num_only },
{ 0, Filter::user } // not a valid name
};
struct T_entry
{
const char * const name;
Transformation::Type type;
};
const T_entry T_table[] =
{
{ "none", Transformation::none },
{ "rotate90", Transformation::rotate90 },
{ "rotate180", Transformation::rotate180 },
{ "rotate270", Transformation::rotate270 },
{ "mirror_lr", Transformation::mirror_lr },
{ "mirror_tb", Transformation::mirror_tb },
{ "mirror_d1", Transformation::mirror_d1 },
{ "mirror_d2", Transformation::mirror_d2 },
{ 0, Transformation::none }
};
} // end namespace
void Ocrad::internal_error( const char * const msg )
{
std::fprintf( stderr, "ocrad: internal error: %s\n", msg );
std::exit( 3 );
}
bool Ocrad::similar( const int a, const int b,
const int percent_dif, const int abs_dif )
{
int difference = std::abs( a - b );
if( percent_dif > 0 && difference <= abs_dif ) return true;
int max_abs = std::max( std::abs( a ), std::abs( b ) );
return ( difference * 100 <= max_abs * percent_dif );
}
bool Charset::enable( const char * const name )
{
for( int i = 0; i < charsets; ++i )
if( std::strcmp( name, charset_name[i] ) == 0 )
{ charset_ |= charset_value[i]; return true; }
return false;
}
bool Charset::enabled( const Value cset ) const
{
if( !charset_ ) return cset == iso_8859_15; // default charset
return charset_ & cset;
}
bool Charset::only( const Value cset ) const
{
if( !charset_ ) return cset == iso_8859_15; // default charset
return charset_ == cset;
}
void Charset::show_error( const char * const program_name,
const char * const arg ) const
{
if( verbosity >= 0 )
{
if( arg && std::strcmp( arg, "help" ) != 0 )
std::fprintf( stderr,"%s: bad charset '%s'\n", program_name, arg );
std::fputs( "Valid charset names:", stderr );
for( int i = 0; i < charsets; ++i )
std::fprintf( stderr, " %s", charset_name[i] );
std::fputc( '\n', stderr );
}
}
bool Transformation::set( const char * const name )
{
for( int i = 0; T_table[i].name != 0; ++i )
if( std::strcmp( name, T_table[i].name ) == 0 )
{ type_ = T_table[i].type; return true; }
return false;
}
void Transformation::show_error( const char * const program_name,
const char * const arg ) const
{
if( verbosity >= 0 )
{
if( arg && std::strcmp( arg, "help" ) != 0 )
std::fprintf( stderr,"%s: bad bitmap trasformation '%s'\n", program_name, arg );
std::fputs( "Valid transformation names:", stderr );
for( int i = 0; T_table[i].name != 0; ++i )
std::fprintf( stderr, " %s", T_table[i].name );
std::fputs( "\nRotations are made counter-clockwise.\n", stderr );
}
}
Control::~Control()
{
for( unsigned f = filters.size(); f > 0; --f )
if( filters[f-1].user_filterp )
delete filters[f-1].user_filterp;
}
bool Control::add_filter( const char * const program_name,
const char * const name )
{
for( int i = 0; F_table[i].name != 0; ++i )
if( std::strcmp( name, F_table[i].name ) == 0 )
{ filters.push_back( Filter( F_table[i].type ) ); return true; }
if( verbosity >= 0 )
{
if( name && std::strcmp( name, "help" ) != 0 )
std::fprintf( stderr,"%s: bad filter '%s'\n", program_name, name );
std::fputs( "Valid filter names:", stderr );
for( int i = 0; F_table[i].name != 0; ++i )
std::fprintf( stderr, " %s", F_table[i].name );
std::fputc( '\n', stderr );
}
return false;
}
int Control::add_user_filter( const char * const program_name,
const char * const file_name )
{
const User_filter * const user_filterp = new User_filter( file_name );
const int retval = user_filterp->retval();
if( retval == 0 )
filters.push_back( Filter( user_filterp ) );
else
{
if( verbosity >= 0 )
std::fprintf( stderr,"%s: user filter: %s\n",
program_name, user_filterp->error().c_str() );
delete user_filterp;
}
return retval;
}
bool Control::set_format( const char * const name )
{
if( std::strcmp( name, "byte" ) == 0 ) { utf8 = false; return true; }
if( std::strcmp( name, "utf8" ) == 0 ) { utf8 = true; return true; }
return false;
}