[戻る]

// decorders.h 

#include <stdio.h>

const char *ctohex( unsigned int    ) ;    // ※1は不要 
const char *stohex( unsigned char * ) ;    // バイト並びを へっくすで。
const char *stohex( unsigned char * , int ) ;    // サイズ指定版
const char *check_byte_order( BYTE *pb ) ;
const char *dump_struct( FILE *fp , LPBYTE data , char *format , int total_size ) ;
const char *visdig( unsigned int c )    ;
unsigned char *digitstring_toint8( char *digstring ) ;


char *G3digits( unsigned char sig ) ;
DWORD G3MHasBITSTR1728( char *dest , char *src , int size_dest ) ;


const char *visdig( unsigned int c )
{
// visualize as digits
#define UNIT_BUFF 33     // 32 + '1' for null termaination. 33 is for future's insurance.

static char ret[UNIT_BUFF * 8]   ; // 8 回まで同時可。printf などで同時に使うことはたまに良くある。
static char bctr        ; 
char *pret ;

pret = ret + UNIT_BUFF * bctr ;

int  ctr ;

for( ctr = 0 ; ctr < 8 ; ctr ++ , pret ++ )
{    if( c & ( 0x1 << ctr ) )
*pret = '1' ;
else *pret = '0' ;
}

*pret ++= '\0' ;

bctr ++ ;
if( bctr & 8 ) bctr = 0 ; // i.e bctr == 8 ;

pret += 24 ;

return pret - UNIT_BUFF ;

#undef UNIT_BUFF
}

unsigned char *digitstring_toint8( char *digstring )
{
unsigned int uiresult = 0 ;

static unsigned char retbuf[4096] ;
unsigned char *lpbuf = retbuf ;

int count ; unsigned int mask ;

for( count = 0 , mask = 0x1 ; *digstring 
; ( count == 7 ) ? count = 0 : count ++ , digstring ++ , count ? mask <<= 1 : mask = 0x1 )
{
if( *digstring == '0' ) ;
else
uiresult |= mask ;

if( count == 7 ) {
*lpbuf ++ = uiresult & 0xFF ;
uiresult = 0 ;
}
}

if( count ) *lpbuf ++ = uiresult & 0xFF ;


*lpbuf = '\0' ;

return retbuf ;

}


char *G3digits( unsigned char sig )
{
#define EASYCODE( x , disp )  case (x) : return #disp 

switch( sig )
{
EASYCODE( 0 + 4 + 128 , CFR0 ) ;
EASYCODE( 1 + 4 + 128 , CFR1 ) ;
EASYCODE( 1 + 64 , CIG ) ;
EASYCODE( 0 + 2 + 8 + 16 , CRP0 ) ;
EASYCODE( 1 + 2 + 8 + 16 , CRP1 ) ;
EASYCODE( 64 , CSI ) ;
EASYCODE( 0 + 2 + 16 , CTC0 ) ;
EASYCODE( 1 + 2 + 16 , CTC1 ) ;


EASYCODE( 0+4+64+128  , CTR0) ;
EASYCODE( 1+4+64+128  , CTR1) ;

EASYCODE( 0+2+8+16+32+64+128 , DCN0) ;
EASYCODE( 1+2+8+16+32+64+128 , DCN1) ;
EASYCODE( 0+2+128 , DCS0) ;
EASYCODE( 1+2+128 , DCS1) ;
EASYCODE( 128   , DIS) ;
EASYCODE( 1+128 , DTC) ;
EASYCODE( 0+2+4+8+128 ,EOM0 ) ;
EASYCODE( 1+2+4+8+128 ,EOM1 ) ;

EASYCODE( 0+2+4+8+32 , EOP0) ;
EASYCODE( 1+2+4+8+32 , EOP1) ;
EASYCODE( 0+2+4+8+64+128 , EORr0) ;
EASYCODE( 1+2+4+8+64+128 , EORr1) ;
EASYCODE( 0+4+8+16 , ERR0 ) ;
EASYCODE( 1+4+8+16 , ERR1 ) ;
EASYCODE( 0+4+8+16+32+64+128 , FDM0) ;
EASYCODE( 1+4+8+16+32+64+128 , FDM1) ;
EASYCODE( 0+4+64 , FTT0) ;
EASYCODE( 1+4+64 , FTT1) ;
EASYCODE( 0+4+8+128 , MCF0) ;
EASYCODE( 1+4+8+128 , MCF1) ;

EASYCODE( 0+2+4+8+64 , MPS0) ;
EASYCODE( 1+2+4+8+64 , MPS1) ;
EASYCODE( 1+32 , NSC ) ;
EASYCODE( 32   , NSF ) ;
EASYCODE( 0+2+32 , NSS0) ;
EASYCODE( 1+2+32 , NSS1) ;
EASYCODE( 0 , NULL ) ;
EASYCODE( 0+4+8+32 , PIN0) ;
EASYCODE( 1+4+8+32 , PIN1) ;

EASYCODE( 0+4+8+32+128 , PIP0) ;
EASYCODE( 1+4+8+32+128 , PIP1) ;
EASYCODE( 0+4+8+16+32+128 , PPR0) ;
EASYCODE( 1+4+8+16+32+128 , PPR1) ;
EASYCODE( 0+2+4+8+16+32+128 , PPSr0) ;
EASYCODE( 1+2+4+8+16+32+128 , PPSr1) ;
EASYCODE( 0+2+4+8+16+128 , PRI_EOM0) ;
EASYCODE( 1+2+4+8+16+128 , PRI_EOM1) ;
EASYCODE( 0+2+4+8+16+32 , PRI_EOP0) ;
EASYCODE( 1+2+4+8+16+32 , PRI_EOP1) ;
EASYCODE( 0+2+4+8+16+64 , PRI_MPS0) ;
EASYCODE( 1+2+4+8+16+64 , PRI_MPS1) ;
EASYCODE( 1+ 64+128 , PWD_TX ) ;
EASYCODE( 0+2+64+128 ,PWD_RX0 ) ;
EASYCODE( 1+2+64+128 ,PWD_RX1 ) ;
EASYCODE( 0+4+8+32+64+128 , RNR0) ;
EASYCODE( 1+4+8+32+64+128 , RNR1) ;
EASYCODE( 0+2+4+8+32+64 , RR0) ;
EASYCODE( 1+2+4+8+32+64 , RR1) ;
EASYCODE( 0+4+8+64 , RTN0) ;
EASYCODE( 1+4+8+64 , RTN1) ;
EASYCODE( 0+4+8+64+128 , RTP0) ;
EASYCODE( 1+4+8+64+128 , RTP1) ;
EASYCODE( 1+ 32+128 , SEP) ;

EASYCODE( 1 , _SOH_) ;
EASYCODE( 2 , _STX_) ;
EASYCODE( 3 , _ETX_) ;
EASYCODE( 4 , _EOT_) ;
EASYCODE( 16, _DLE_) ;

//        EASYCODE( 0+2+64+128 , SUB0) ; // same as PWD_RX0,1
//        EASYCODE( 1+2+64+128 , SUB1) ;
EASYCODE( 2+4 , FCD ) ;

default : break ;

}
return "?" ;
#undef ES

}


// Table 1
// Terminating Codes
// run length white code black code

struct ICPCP { int idx ; char *white ; char *black ; } ;

#define W_str(x) ( ((x)<64)? MHtable[(x)].white : MHtable[63+( (0x40 -1)&((x)>>6))].white )
#define B_str(x) ( ((x)<64)? MHtable[(x)].black : MHtable[63+( (0x40 -1)&((x)>>6))].black )

#define W_remainder( x) (((x)<64 /*|| ( (!((x)&(0x40-1)))&& ((x)%320) )*/ ) ? "" : MHtable[((x)&(0x40-1))].white )
#define B_remainder( x) (((x)<64 /*|| ( (!((x)&(0x40-1)))&& ((x)%320) )*/ ) ? "" : MHtable[((x)&(0x40-1))].black )
//w0b1728 が成功する以上、これでよいはず。

// where 'x' is equal to "runlength" .

ICPCP MHtable[124] =
{
{0 ,   "00110101" ,  "0000110111"},
{1 ,   "000111"   ,  "010"},
{2 ,   "0111"     ,  "11"},
{3 ,   "1000"     ,  "10"},
{4 ,   "1011"     ,  "011"},
{5 ,   "1100"     ,  "0011"},
{6 ,   "1110"     ,  "0010"},
{7 ,   "1111"     ,  "00011"},
{8 ,   "10011"    ,  "000101"},
{9 ,   "10100"    ,  "000100"},
{10,   "00111"    ,  "0000100"},
{11,   "01000"    ,  "0000101"},
{12,   "001000"   ,  "0000111"},
{13,   "000011"   ,  "00000100"},
{14,   "110100"   ,  "00000111"},
{15,   "110101"   ,  "000011000"},
{16,   "101010"   ,  "0000010111"},
{17,   "101011"   ,  "0000011000"},
{18,   "0100111"  ,  "0000001000"},

{19,   "0001100"  ,  "0000" "1" "100111" }, // 00001100111 ? YES !

{20,   "0001000"  ,  "00001101000"},

{21,   /**/ "0010111"  ,  "00001101100"}, // 001011?

{22,   "0000011"  ,  "00000110111"},
{23,   "0000100"  ,  "00000101000"},
{24,   "0101000"  ,  "00000010111"},
{25,   "0101011"  ,  "00000011000"},
{26,   "0010011"  ,  "000011001010"},
{27,   "0100100"  ,  "000011001011"},
{28,   "0011000"  ,  "000011001100"},
{29,   "00000010" ,  "000011001101"},
{30,   "00000011" ,  "000001101000"},
{31,   "00011010" ,  "000001101001"},
{32,   "00011011" ,  "000001101010"},
{33,   "00010010" ,  "000001101011"},
{34,   "00010011" ,  "000011010010"},
{35,   "00010100" ,  "000011010011"},
{36,   "00010101" ,  "000011010100"},
{37,   "00010110" ,  "000011010101"},
{38,   "00010111" ,  "000011010110"},
{39,   "00101000" ,  "000011010111"},
{40,   "00101001" ,  "000001101100"},
{41,   "00101010" ,  "000001101101"},
{42,   "00101011" ,  "000011011010"},
{43,   "00101100" ,  "000011011011"},
{44,   "00101101" ,  "000001010100"},
{45,   "00000100" ,  "000001010101"},
{46,   "00000101" ,  "000001010110"},
{47,   "00001010" ,  "000001010111"},
{48,   "00001011" ,  "000001100100"},
{49,   "01010010" ,  "000001100101"},
{50,   "01010011" ,  "000001010010"},
{51,   "01010100" ,  "000001010011"},
{52,   "01010101" ,  "000000100100"},
{53,   "00100100" ,  "000000110111"},
{54,   "00100101" ,  "000000111000"},
{55,   "01011000" ,  "000000100111"},
{56,   "01011001" ,  "000000101000"},
{57,   "01011010" ,  "000001011000"},
{58,   "01011011" ,  "000001011001"},
{59,   "01001010" ,  "000000101011"},
{60,   "01001011" ,  "000000101100"},
{61,   "00110010" ,  "000001011010"},
{62,   "00110011" ,  "000001100110"},
{63,   "00110100" ,  "000001100111"},
// 64
// Make-up Codes
// run length white code black code
{64  , "11011"    ,  "000000111" "1"},
{128 , "10010"    ,  "000011001000"},
{192 , "010111"   ,  "000011001001"},
{256 , "0110111"  ,  "000001011011"},
{320 , "00110110" ,  "000000110011"},
{384 , "00110111" ,  "000000110100"},
{448 , "01100100" ,  "000000110101"},
{512 , "01100101" ,  "0000001101100"},
{576 , "01101000" ,  "0000001101101"},
{640 , "01100111" ,  "0000001001010"},
{704 , "011001100",  "0000001001011"},
{768 , "011001101",  "0000001001100"},
{832 , "011010010",  "0000001001101"},
{896 , "011010011",  "0000001110010"},
{960 , "011010100",  "0000001110011"},
{1024, "011010101",  "0000001110100"},
{1088, "011010110",  "0000001110101"},
{1152, "011010111",  "0000001110110"},
{1216, "011011000",  "0000001110111"},
{1280, "011011001",  "0000001010010"},
{1344, "011011010",  "0000001010011"}, /**/
{1408, "011011011",  "0000001010100"},
{1472, "010011000",  "0000001010101"},
{1536, "010011001",  "0000001011010"},
{1600, "010011010",  "0000001011011"},
{1664, "011000"   ,  "0000001100100"},
{1728, "010011011",  "0000001100101"},
// 37
//Extended Make-up codes (white + black)

{1792, "00000001000" , ""},
{1856, "00000001100" , ""},
{1920, "00000001101" , ""},
{1984, "000000010010", ""},
{2048, "000000010011", ""},
{2112, "000000010100", ""},
{2176, "000000010101", ""},
{2240, "000000010110", ""},
{2304, "000000010111", ""},
{2368, "000000011100", ""},
{2432, "000000011101", ""},
{2496, "000000011110", ""},
{2560, "000000011111", ""},
// 23
} ;

DWORD G3MHasBITSTR1728( char *dest , char *src , int size_dest )
{   //    "00011101010000..." ビットマップ( 文字の '0' と '1' ) で構成された絵。
// => "省略"              G3 FAx の MH コード化を施したもの。'0' と '1' で構成された文字列の形。
// == バイナリ形式を、文字列の形に可視化したもの。!! 本当の意味でのバイナリ形式には、各自あとでする。

int pixline = 1728 ; int iscan = 0 ;
char *dest_ = dest ;

int mode = 0x0 ;
int ctctr = 0  ;

//if( *src != '0' ) { dest = stpcpy( dest , W_str(1) ) ;
//src ++ ; iscan ++ ; ctctr = 1 ; }

if( *src != '0' ) dest = stpcpy( dest , W_str(0) ) ;



for( ; dest - dest_ < size_dest && iscan <= pixline ;
src ++ , iscan ++ )
{
if( ! *src || pixline == iscan ) mode |= 0x2 ;
else
if( *src == '0' )
{   if( ! ( mode & 0x1 )) ctctr ++ ;
else mode |= 0x2 ;
}
else
{   if( mode & 0x1 ) ctctr ++ ;
else mode |= 0x2 ;
}

if( mode & 0x2 )
{   mode &= ~0x2 ;

if( ! (mode & 0x1) ) // 白
{   dest = stpcpy( dest , W_str(ctctr)) ;
dest = stpcpy( dest , W_remainder(ctctr)) ;
}
else // 黒
{   dest = stpcpy( dest , B_str(ctctr)) ;
dest = stpcpy( dest , B_remainder(ctctr)) ;
}

mode ^= 0x1 ; ctctr = 1 ;
}
if( ! *src ) { iscan ++ ; break ; }

}

if( iscan != ( pixline +1 ) )
{   // 正常に終われば pixline + 1 == iscan のはずである。
if( ! *src && iscan < pixline + 1 )
{   int ctremain = pixline - iscan ; // 少々ややこしいがこうなる。
// この場合黒で埋める。 
dest = stpcpy( dest , B_str( ctremain )) ;
dest = stpcpy( dest , B_remainder( ctremain )) ;
}

}

if( *src ) *stpcpy( dest ,
"00110101" "00000011" "00101" "000" "00000000" ) = '\0' ;
// エラー(1728以上のピクセル。)の場合、一行全部黒線の w0b1728 ( W_str(0) + B_str(1728) )

return 1 ;
}