2023-11-10 06:38:12 +00:00
# include " imgprc_mgr.h "
# include <json/gb_json.h>
# include <sane_opt_json/device_opt.h>
# include "../../../sdk/include/huagao/hgscanner_error.h"
# include <ImageMatQueue.h>
# include <huagaoxxx_warraper_ex.h>
# include <imgproc-pak/fill_hole.h>
2023-11-15 01:06:28 +00:00
# include <imgproc-pak/multi_out.h>
2023-11-10 06:38:12 +00:00
static std : : string device_opt_json [ ] = {
" { \" dumpimg \" :{ \" cat \" : \" base \" , \" group \" : \" debug \" , \" title \" : \" \\ u8f93 \\ u51fa \\ u7b97 \\ u6cd5 \\ u4e2d \\ u95f4 \\ u56fe \\ u50cf \" , \" desc \" : \" \\ u6bcf \\ u4e2a \\ u7b97 \\ u6cd5 \\ u6267 \\ u884c \\ u540e \\ uff0c \\ u8f93 \\ u51fa \\ u4e2d \\ u95f4 \\ u7684 \\ u4e34 \\ u65f6 \\ u56fe \\ u50cf \" , \" type \" : \" bool \" , \" pos \" :10, \" size \" :4, \" cur \" :false, \" default \" :false}, \" dump-path \" :{ \" cat \" : \" base \" , \" group \" : \" debug \" , \" title \" : \" \\ u4e2d \\ u95f4 \\ u56fe \\ u50cf \\ u8f93 \\ u51fa \\ u8def \\ u5f84 \" , \" desc \" : \" \\ u6bcf \\ u4e2a \\ u7b97 \\ u6cd5 \\ u6267 \\ u884c \\ u540e \\ uff0c \\ u8f93 \\ u51fa \\ u4e2d \\ u95f4 \\ u4e34 \\ u65f6 \\ u56fe \\ u50cf \\ u7684 \\ u5b58 \\ u653e \\ u8def \\ u5f84 \" , \" type \" : \" string \" , \" pos \" :10, \" size \" :260, \" cur \" : \" \" , \" default \" : \" \" , \" depend \" : \" dumpimg==true \" }} "
} ;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// imgproc_mgr
imgproc_mgr : : imgproc_mgr ( device_option * devopts
, bool dumpimg
, const char * dumpath )
: opts_ ( devopts ) , dump_path_ ( dumpath ? dumpath : " " )
, dumpf_ ( dumpimg ? & imgproc_mgr : : dump_real : & imgproc_mgr : : dump_empty )
, dumpusbf_ ( dumpimg ? & imgproc_mgr : : dump_usb_img_real : & imgproc_mgr : : dump_usb_img_empty )
{
std : : string text ( " " ) ;
gb_json * jsn = new gb_json ( ) ;
for ( auto & v : device_opt_json )
text + = v ;
if ( jsn - > attach_text ( & text [ 0 ] ) )
{
gb_json * child = nullptr ;
jsn - > get_value ( SANE_STD_OPT_NAME_DUMP_IMG , child ) ;
if ( child )
{
child - > set_value ( " cur " , dumpimg ) ;
child - > set_value ( " default " , dumpimg ) ;
child - > release ( ) ;
}
jsn - > get_value ( SANE_STD_OPT_NAME_DUMP_IMG_PATH , child ) ;
if ( child )
{
child - > set_value ( " cur " , dump_path_ . c_str ( ) ) ;
child - > set_value ( " default " , dump_path_ . c_str ( ) ) ;
child - > release ( ) ;
}
text = jsn - > to_string ( ) ;
}
jsn - > release ( ) ;
set_opt_json_text ( & text [ 0 ] ) ;
if ( opts_ )
opts_ - > add_ref ( ) ;
else
opts_ = new device_option ( ) ;
}
imgproc_mgr : : ~ imgproc_mgr ( )
{
clear ( ) ;
opts_ - > release ( ) ;
}
std : : vector < imgproc_mgr : : DECDAT > imgproc_mgr : : decode_before_simple ( uint8_t * data , size_t bytes , HGIMGINFO * info )
{
std : : vector < DECDAT > simple ;
DECDAT in ;
in . info = * info ;
in . img . reset ( new std : : vector < char > ( bytes ) ) ;
memcpy ( in . img - > data ( ) , data , bytes ) ;
simple . push_back ( in ) ;
return std : : move ( simple ) ;
}
std : : vector < imgproc_mgr : : DECDAT > imgproc_mgr : : decode_before_g200dsp ( uint8_t * data , size_t bytes , HGIMGINFO * info )
{
// pid == 0x100 || pid == 0x200
std : : vector < DECDAT > g200dsp ;
DECDAT f , b ;
int line = 1024 , off_f = 0 , off_b = 0 ;
f . info = * info ;
f . info . paper_side = PAPER_SIDE_FRONT ;
f . img . reset ( new std : : vector < char > ( bytes ) ) ;
b . info = * info ;
b . info . paper_side = PAPER_SIDE_BACK ;
b . img . reset ( new std : : vector < char > ( bytes ) ) ;
for ( int i = 0 ; i < bytes / line ; + + i )
{
if ( data [ line - 1 ] = = 0 )
{
// this is back
memcpy ( b . img - > data ( ) + off_b , data , line - 1 ) ;
off_b + = line - 1 ;
}
else if ( data [ line - 1 ] = = 0x0ff )
{
// this is front
memcpy ( f . img - > data ( ) + off_f , data , line - 1 ) ;
off_f + = line - 1 ;
}
data + = line ;
}
f . img - > resize ( off_f ) ;
b . img - > resize ( off_b ) ;
g200dsp . push_back ( b ) ;
g200dsp . push_back ( f ) ;
return std : : move ( g200dsp ) ;
}
void imgproc_mgr : : dump_real ( const std : : vector < PROCIMGINFO > & img , const char * after , int pos )
{
std : : string root ( dump_path_ + PATH_SEPARATOR ) ;
std : : vector < std : : string > existing ;
for ( auto & v : img )
{
char name [ 128 ] = { 0 } ;
int ind = 0 ;
sprintf ( name , " %04x-%d-%d-%04x-%s " , v . info . paper_ind , v . info . paper_side , v . info . split_ind , pos , after ) ;
while ( std : : find ( existing . begin ( ) , existing . end ( ) , name ) ! = existing . end ( ) )
sprintf ( name , " %04x-%d-%d-%04x-%s(%d) " , v . info . paper_ind , v . info . paper_side , v . info . split_ind , pos , after , + + ind ) ;
existing . push_back ( name ) ;
cv : : imwrite ( ( root + name + " .jpg " ) . c_str ( ) , v . img ) ;
}
}
void imgproc_mgr : : dump_empty ( const std : : vector < PROCIMGINFO > & img , const char * after , int pos )
{ }
std : : string imgproc_mgr : : dump_usb_img_real ( uint8_t * data , size_t bytes , HGIMGINFO * info , const char * tail )
{
std : : string root ( dump_path_ + PATH_SEPARATOR ) ;
char name [ 128 ] = { 0 } ;
const char * tail_leader = " " ;
FILE * dst = nullptr ;
int ind = 0 ;
if ( tail & & * tail )
tail_leader = " - " ;
else
tail = " " ;
sprintf ( name , " %04x-usb%s%s " , info - > paper_ind , tail_leader , tail ) ;
{
// check repeat ...
dst = fopen ( ( root + name + " .jpg " ) . c_str ( ) , " rb " ) ;
while ( dst )
{
fclose ( dst ) ;
sprintf ( name , " %04x-usb%s%s(%d) " , info - > paper_ind , tail_leader , tail , + + ind ) ;
dst = fopen ( ( root + name + " .jpg " ) . c_str ( ) , " rb " ) ;
}
}
dst = fopen ( ( root + name + " .jpg " ) . c_str ( ) , " wb " ) ;
if ( dst )
{
fwrite ( data , 1 , bytes , dst ) ;
fclose ( dst ) ;
utils : : to_log ( LOG_LEVEL_DEBUG , " Temporary file '%s' OK. \n " , ( root + name + " .jpg " ) . c_str ( ) ) ;
}
else
{
utils : : to_log ( LOG_LEVEL_DEBUG , " Temporary file '%s' failed with err: %d \n " , ( root + name + " .jpg " ) . c_str ( ) , errno ) ;
}
return std : : move ( root + name + " .jpg " ) ;
}
std : : string imgproc_mgr : : dump_usb_img_empty ( uint8_t * data , size_t bytes , HGIMGINFO * info , const char * tail )
{
return " " ;
}
int imgproc_mgr : : decode ( HGIMGINFO * info , uint8_t * data , size_t bytes , std : : vector < PROCIMGINFO > & result )
{
std : : vector < DECDAT > tmp ( info - > paper_side = = PAPER_SIDE_DSP ? imgproc_mgr : : decode_before_g200dsp ( data , bytes , info ) : imgproc_mgr : : decode_before_simple ( data , bytes , info ) ) ;
int ret = SCANNER_ERR_OK ;
( this - > * dumpusbf_ ) ( data , bytes , info , nullptr ) ;
for ( auto & v : tmp )
{
PROCIMGINFO pii ;
try
{
cv : : ImreadModes rmc = info - > channels > 1 ? cv : : IMREAD_COLOR : cv : : IMREAD_GRAYSCALE ;
if ( v . img - > at ( 0 ) = = 0x89 & & v . img - > at ( 1 ) = = ' P ' & & v . img - > at ( 2 ) = = ' N ' & & v . img - > at ( 2 ) = = ' G ' )
rmc = cv : : IMREAD_GRAYSCALE ;
memset ( & pii . info , 0 , sizeof ( pii . info ) ) ;
pii . info = v . info ;
pii . img = cv : : imdecode ( * v . img , rmc ) ;
if ( pii . img . empty ( ) )
{
std : : string f ( dump_usb_img_real ( ( uint8_t * ) & ( * v . img ) [ 0 ] , v . img - > size ( ) , info , " error " ) ) ;
utils : : to_log ( LOG_LEVEL_WARNING , " Warning: decode failure, source content save to file '%s' \n " , f . c_str ( ) ) ;
}
else
{
if ( info - > paper_side = = PAPER_SIDE_LEFT | | info - > paper_side = = PAPER_SIDE_RIGHT )
{
PROCIMGINFO front ( pii ) ;
front . info . paper_side = PAPER_SIDE_FRONT ;
if ( info - > paper_side = = PAPER_SIDE_LEFT )
{
front . img = pii . img ( cv : : Rect ( 0 , 0 , pii . img . cols / 2 , pii . img . rows ) ) ;
pii . img = pii . img ( cv : : Rect ( pii . img . cols / 2 , 0 , pii . img . cols / 2 , pii . img . rows ) ) ;
}
else
{
front . img = pii . img ( cv : : Rect ( pii . img . cols / 2 , 0 , pii . img . cols / 2 , pii . img . rows ) ) ;
pii . img = pii . img ( cv : : Rect ( 0 , 0 , pii . img . cols / 2 , pii . img . rows ) ) ;
}
result . push_back ( front ) ;
pii . info . paper_side = PAPER_SIDE_BACK ;
}
else if ( info - > paper_side = = PAPER_SIDE_TOP | | info - > paper_side = = PAPER_SIDE_BOTTOM )
{
PROCIMGINFO front ( pii ) ;
front . info . paper_side = PAPER_SIDE_FRONT ;
if ( info - > paper_side = = PAPER_SIDE_TOP )
{
front . img = pii . img ( cv : : Rect ( 0 , 0 , pii . img . cols , pii . img . rows / 2 ) ) ;
pii . img = pii . img ( cv : : Rect ( 0 , pii . img . rows / 2 , pii . img . cols , pii . img . rows / 2 ) ) ;
}
else
{
front . img = pii . img ( cv : : Rect ( 0 , pii . img . rows / 2 , pii . img . cols , pii . img . rows / 2 ) ) ;
pii . img = pii . img ( cv : : Rect ( 0 , 0 , pii . img . cols , pii . img . rows / 2 ) ) ;
}
result . push_back ( front ) ;
pii . info . paper_side = PAPER_SIDE_BACK ;
}
result . push_back ( pii ) ;
}
}
catch ( const std : : exception & e )
{
utils : : to_log ( LOG_LEVEL_FATAL , " FATAL: exception occurs when decode image %d-%d failed with reason '%s'! \n " , info - > paper_ind , pii . info . paper_side , e . what ( ) ) ;
std : : string f ( dump_usb_img_real ( ( uint8_t * ) & ( * v . img ) [ 0 ] , v . img - > size ( ) , info , " decode " ) ) ;
utils : : to_log ( LOG_LEVEL_WARNING , " FATAL: decode image %d-%d failed, source content save to file '%s' \n " , info - > paper_ind , pii . info . paper_side , f . c_str ( ) ) ;
//throw(e); // continue the error handling
ret = SCANNER_ERR_THROW_EXCEPTION ;
break ; // fatal occurs, stop
}
catch ( . . . )
{
utils : : to_log ( LOG_LEVEL_FATAL , " FATAL: exception occurs when decode image %d-%d failed \n " , info - > paper_ind , pii . info . paper_side ) ;
std : : string f ( dump_usb_img_real ( ( uint8_t * ) & ( * v . img ) [ 0 ] , v . img - > size ( ) , info , " decode " ) ) ;
utils : : to_log ( LOG_LEVEL_WARNING , " FATAL: decode image %d-%d failed, source content save to file '%s' \n " , info - > paper_ind , pii . info . paper_side , f . c_str ( ) ) ;
ret = SCANNER_ERR_THROW_EXCEPTION ;
break ; // fatal occurs, stop
}
}
tmp . clear ( ) ;
char errbuf [ 40 ] = { 0 } ;
utils : : to_log ( LOG_LEVEL_DEBUG , " Decode %u bytes to %u picture(s) = %s \n " , bytes , result . size ( ) , hg_scanner_err_name ( ret , errbuf ) ) ;
( this - > * dumpf_ ) ( result , " decode " , 10 ) ;
return ret ;
}
bool imgproc_mgr : : sort_processor_by_pos ( image_processor * l , image_processor * r )
{
return l - > get_position ( ) < r - > get_position ( ) ;
}
int imgproc_mgr : : set_value ( const char * name , void * val )
{
int ret = SCANNER_ERR_OK ;
if ( strcmp ( name , SANE_STD_OPT_NAME_DUMP_IMG ) = = 0 )
{
if ( * ( bool * ) val )
{
dumpf_ = & imgproc_mgr : : dump_real ;
dumpusbf_ = & imgproc_mgr : : dump_usb_img_real ;
}
else
{
dumpf_ = & imgproc_mgr : : dump_empty ;
dumpusbf_ = & imgproc_mgr : : dump_usb_img_empty ;
}
}
else if ( strcmp ( name , SANE_STD_OPT_NAME_DUMP_IMG_PATH ) = = 0 )
dump_path_ = ( char * ) val ;
else
ret = SCANNER_ERR_DEVICE_NOT_SUPPORT ;
return ret ;
}
int imgproc_mgr : : load_processor ( const char * path )
{
int ret = SCANNER_ERR_OK ;
2023-11-15 01:06:28 +00:00
# define ADD_IMG_PROCESSOR(cls) \
{ \
cls * obj = new cls ( ) ; \
opts_ - > add ( obj ) ; \
obj - > release ( ) ; \
}
ADD_IMG_PROCESSOR ( hole_filler ) ;
ADD_IMG_PROCESSOR ( multi_outer ) ;
2023-11-10 06:38:12 +00:00
std : : sort ( processors_ . begin ( ) , processors_ . end ( ) , & imgproc_mgr : : sort_processor_by_pos ) ;
return ret ;
}
int imgproc_mgr : : clear ( void )
{
for ( auto & v : processors_ )
v - > release ( ) ;
processors_ . clear ( ) ;
return 0 ;
}
int imgproc_mgr : : process ( HGIMGINFO * info , uint8_t * data , size_t bytes , std : : vector < PROCIMGINFO > & out )
{
std : : vector < PROCIMGINFO > mid [ 2 ] , in , * src = & in , * dst = & mid [ 0 ] ;
int ret = decode ( info , data , bytes , in ) , sn = 0 ;
if ( ret = = SCANNER_ERR_OK )
{
for ( auto & v : processors_ )
{
if ( v - > is_enable ( ) )
{
try
{
ret = v - > process ( * src , * dst ) ;
( this - > * dumpf_ ) ( * dst , v - > from ( ) . c_str ( ) , v - > get_position ( ) ) ;
if ( ret )
break ;
src = dst ;
sn ^ = 1 ;
dst = & mid [ sn ] ;
}
catch ( const std : : exception & e )
{
ret = SCANNER_ERR_THROW_EXCEPTION ;
utils : : to_log ( LOG_LEVEL_DEBUG , " FATAL: image %d process '%s' throws exception: %s! \n " , info - > paper_ind , v - > from ( ) . c_str ( ) , e . what ( ) ) ;
std : : string f ( dump_usb_img_real ( data , bytes , info , v - > from ( ) . c_str ( ) ) ) ;
utils : : to_log ( LOG_LEVEL_WARNING , " FATAL: process image %d failed on '%s', source content save to file '%s' \n " , info - > paper_ind , v - > from ( ) . c_str ( ) , f . c_str ( ) ) ;
break ;
}
catch ( . . . )
{
ret = SCANNER_ERR_THROW_EXCEPTION ;
utils : : to_log ( LOG_LEVEL_DEBUG , " FATAL: image process '%s' throws unknown exception! \n " , v - > from ( ) . c_str ( ) ) ;
std : : string f ( dump_usb_img_real ( data , bytes , info , v - > from ( ) . c_str ( ) ) ) ;
utils : : to_log ( LOG_LEVEL_WARNING , " FATAL: process image %d failed on '%s', source content save to file '%s' \n " , info - > paper_ind , v - > from ( ) . c_str ( ) , f . c_str ( ) ) ;
break ;
}
}
}
}
out = * src ;
return ret ;
}