/******************************************************************************* * モジュール名称 :Application Common Compression関数定義 * * モジュールラベル :Common App * * タスク区分 :Common Functions * * 機能 :MWをラップする共通関数定義を行う * * 使用上の注意 :特になし * * 作成日・作成者 :2012/3/22 Y.K. * *******************************************************************************/ #include "dpu_api.h" #include "dpu_api_proto.h" #include "app_core.h" #define d_END_OF_STREAM 256 // **** Local Prototype **** int MathCompressFile ( unsigned char uc_data[], unsigned char uc_data2[], int i_size, MATH * ); void MathExpandFile ( unsigned char uc_data[], unsigned char uc_data2[], int i_size, MATH * ); // *** ARRAY in MATH *** // short totals [258]; // 00000204 // unsigned int counts [256]; // 00000400 // unsigned char scaled_counts[256]; // 00000100 // =========================================================================== // int app_CompMath( unsigned char uc_data[], int i_size ) **** 数値圧縮 **** // [Input/Output] unsigned char uc_data [0x1000 max] Input Data --> Output Data // [return] int Data size >0: compressed // 0: non-compressed (larger than input) // -1: non-compressed (error) // =========================================================================== int app_CompMath( unsigned char uc_data[], unsigned char uc_data2[], int i_size, MATH * math ) { // ********************************************** // COMPRESS // ********************************************** math->out_size = 0; math->rack = 0; math->mask = 0x80; // **** COMPRESS! **** if ( MathCompressFile ( uc_data, uc_data2, i_size, math ) ) return(-1); if ( math->mask != 0x80 ) { uc_data2[ math->out_size ] = (unsigned char)math->rack; math->out_size ++; } return ( math->out_size ); } // ******************************************************************* // ****************** COMPRESS: General ****************************** // ******************************************************************* void MathOutputComps ( unsigned int, int, unsigned char uc_data2[], MATH * ); void MathOutputComp ( int, unsigned char uc_data2[], MATH * ); // //void MathBuild_model ( short * , unsigned char uc_data[] , unsigned char uc_data2[], int, MATH * ); //void MathCount_bytes ( unsigned int * , unsigned char uc_data[] , int ); void MathScale_counts ( unsigned int * , unsigned char * ); void MathBuild_totals ( unsigned char * , short * ); void MathOutput_counts ( unsigned char * , unsigned char uc_data2[], MATH * ); //void MathInitialize_arithmetic_encoder ( MATH * ); void MathFlush_arithmetic_encoder ( unsigned char uc_data2[], MATH * ); void MathConvert_int_to_symbol ( int , short * , MATH *); void MathEncode_symbol ( unsigned char uc_data2[], MATH * ); // **************************************************************** // **************************************************************** int MathCompressFile( unsigned char uc_data[], unsigned char uc_data2[], int i_size, MATH *math ) { int i; int c; // MathBuild_model( math->totals, uc_data, uc_data2, i_size, math ); // MathCount_bytes ( math->counts, uc_data, i_size ); for ( i = 0 ; i < 256 ; i++ ) math->counts[ i ] = 0; for ( i = 0 ; i < i_size ; i++ ) math->counts[ (uc_data[ i ]) ]++; // MathScale_counts ( math->counts, math->scaled_counts ); MathOutput_counts( math->scaled_counts , uc_data2, math ); MathBuild_totals ( math->scaled_counts , math->totals ); // // MathInitialize_arithmetic_encoder( math ); math->low = 0; math->high = 0xffff; math->underflow_bits = 0; // for ( i = 0 ; i < i_size; i++ ) { c = (int)(uc_data[i]); MathConvert_int_to_symbol( c, math->totals, math ); MathEncode_symbol( uc_data2, math ); if (math->out_size > i_size - 10) return(-1); // ** Compressed-size > Input-size ** } MathConvert_int_to_symbol( d_END_OF_STREAM, math->totals, math ); MathEncode_symbol( uc_data2, math ); MathFlush_arithmetic_encoder( uc_data2, math ); MathOutputComps( 0L, 16, uc_data2, math ); return( 0 ); } // **************************************************************** // **************************************************************** void MathOutputComp( int bit, unsigned char uc_data2[], MATH *math ) { unsigned char m; m = math->mask; if ( bit ) math->rack |= m; m >>= 1; if ( m == 0 ) { uc_data2[ math->out_size ] = (unsigned char)math->rack; math->out_size ++; math->rack = 0; m = 0x80; } math->mask = m; } void MathOutputComps( unsigned int code, int count, unsigned char uc_data2[], MATH *math ) { unsigned int mask; unsigned char m; m = math->mask; mask = 1L << ( count - 1 ); while ( mask != 0) { if ( mask & code ) math->rack |= m; m >>= 1; if ( m == 0 ) { uc_data2[ math->out_size ] = (unsigned char)math->rack; math->out_size ++; math->rack = 0; m = 0x80; } mask >>= 1; } math->mask = m; } // **************************************************************** // **************************************************************** /* void MathBuild_model( short * totals, unsigned char uc_data[], unsigned char uc_data2[], int i_size, MATH *math ) { MathCount_bytes ( math->counts, uc_data, i_size ); MathScale_counts ( math->counts, math->scaled_counts ); MathOutput_counts( math->scaled_counts , uc_data2, math ); MathBuild_totals ( math->scaled_counts , totals ); } */ /* void MathCount_bytes( unsigned int counts[], unsigned char uc_data[], int i_size ) { int i; for ( i = 0 ; i < 256 ; i++ ) counts[ i ] = 0; for ( i = 0 ; i < i_size ; i++ ) counts[ (uc_data[ i ]) ]++; } */ void MathScale_counts( unsigned int counts[], unsigned char scaled_counts[]) { int i; unsigned int max_count; unsigned int total; unsigned int scale; max_count = 0; for ( i = 0 ; i < 256 ; i++ ) if ( counts[ i ] > max_count ) max_count = counts[ i ]; scale = max_count / 256; scale = scale + 1; for ( i = 0 ; i < 256 ; i++ ) { scaled_counts[ i ] = (unsigned char ) ( counts[ i ] / scale ); if ( scaled_counts[ i ] == 0 && counts[ i ] != 0 ) scaled_counts[ i ] = 1; } total = 1; for ( i = 0 ; i < 256 ; i++ ) total += scaled_counts[ i ]; if ( total > ( 32767 - 256 ) ) scale = 4; else if ( total > 16383 ) scale = 2; else return; for ( i = 0 ; i < 256 ; i++ ) scaled_counts[ i ] /= scale; } void MathOutput_counts( unsigned char scaled_counts[], unsigned char uc_data2[], MATH *math ) { int first; int last; int next; int i; int j; first = 0; while ( first < 255 && scaled_counts[ first ] == 0 ) first++; j = math->out_size; for ( ; first < 256 ; first = next ) { last = first + 1; for ( ; ; ) { for ( ; last < 256 ; last++ ) if ( scaled_counts[ last ] == 0 ) break; last--; for ( next = last + 1; next < 256 ; next++ ) if ( scaled_counts[ next ] != 0 ) break; if ( next > 255 ) break; if ( ( next - last ) > 3 ) break; last = next; }; uc_data2[ j ] = (unsigned char)first; j ++; uc_data2[ j ] = (unsigned char)last; j ++; for ( i = first ; i <= last ; i++ ) { uc_data2[ j ] = scaled_counts[ i ]; j ++; } } uc_data2[ j ] = 0; j ++; math->out_size = j; } void MathBuild_totals( unsigned char scaled_counts[], short totals[] ) { int i; totals[ 0 ] = 0; for ( i = 0 ; i < d_END_OF_STREAM ; i++ ) totals[ i+1 ] = totals[ i ] + scaled_counts[ i ]; totals[ d_END_OF_STREAM + 1 ] = totals[ d_END_OF_STREAM ] + 1; } // **************************************************************** // **************************************************************** /* void MathInitialize_arithmetic_encoder( MATH *math) { math->low = 0; math->high = 0xffff; math->underflow_bits = 0; } */ void MathFlush_arithmetic_encoder( unsigned char uc_data2[], MATH *math ) { int i; unsigned short l; l = math->low; MathOutputComp( l & 0x4000, uc_data2, math ); i = math->underflow_bits + 1; while ( i > 0 ) { i--; MathOutputComp( ~l & 0x4000, uc_data2, math ); } math->underflow_bits = i; } void MathConvert_int_to_symbol( int c, short * totals, MATH *math ) { math->scale = totals[ d_END_OF_STREAM + 1 ]; math->low_count = totals[ c ]; math->high_count = totals[ c + 1 ]; } void MathEncode_symbol( unsigned char uc_data2[], MATH *math ) { int range; unsigned short l; unsigned short h; int u; h = math->high; l = math->low; u = math->underflow_bits; range = (int) ( h-l ) + 1; h = l + (unsigned short) (( range * math->high_count ) / math->scale - 1 ); l = l + (unsigned short) (( range * math->low_count ) / math->scale ); for ( ; ; ) { if ( ( h & 0x8000 ) == ( l & 0x8000 ) ) { MathOutputComp( h & 0x8000, uc_data2, math ); while ( u > 0 ) { MathOutputComp( ~h & 0x8000, uc_data2, math ); u--; } } else if ( ( l & 0x4000 ) && !( h & 0x4000 )) { u += 1; l &= 0x3fff; h |= 0x4000; } else { math->high = h; math->low = l; math->underflow_bits = u; return ; } l <<= 1; h <<= 1; h |= 1; } math->high = h; math->low = l; math->underflow_bits = u; } /* // =========================================================================== // int app_ExpdMath( unsigned char uc_data[], int i_size ) **** 数値圧縮 **** // [Input/Output] unsigned char uc_data [0x1000 max] Input Data --> Output Data // [return] int Data size >0: compressed // 0: non-compressed (larger than input) // -1: non-compressed (error) // =========================================================================== int app_ExpdMath( unsigned char uc_data[], unsigned char uc_data2[], int i_size, MATH * math ) { math->out_size = 0; math->rack = 0; math->mask = 0x80; // **** EXPAND! **** MathExpandFile ( uc_data, uc_data2, i_size, math ); return ( math->out_size ); } // ******************************************************************* // ****************** EXPAND: General ******************************** // ******************************************************************* int MathInputComp ( int * , unsigned char uc_data[], MATH * ); unsigned int MathInputComps ( int , int * , unsigned char uc_data[], MATH * ); void MathInput_counts ( int * , short * , unsigned char uc_data[], MATH * ); void MathInitialize_arithmetic_decoder( int * , unsigned char uc_data[], MATH * ); void MathRemove_symbol_from_stream ( int * , unsigned char uc_data[], MATH * ); void MathGet_symbol_scale ( short * , MATH *); int MathConvert_symbol_to_int ( int count, short * , MATH *); short MathGet_current_count ( ); void MathExpandFile( unsigned char uc_data[], unsigned char uc_data2[], int i_size, MATH *math ) { int c; int count; int out_position = 0; int in_position = 0; MathInput_counts( &in_position , math->totals, uc_data, math ); MathInitialize_arithmetic_decoder( &in_position, uc_data, math ); for ( ; ; ) { MathGet_symbol_scale( math->totals , math ); count = MathGet_current_count( ); c = MathConvert_symbol_to_int( count, math->totals, math ); if ( c == d_END_OF_STREAM ) break; if (in_position >= i_size) { math->out_size = 0; break; } MathRemove_symbol_from_stream( &in_position, uc_data, math ); uc_data2[ out_position ] = (unsigned char)c; out_position++; } math->out_size = out_position; } // ******************************************************************* // ******************************************************************* int MathInputComp( int * i, unsigned char uc_data[], MATH *math ) { int value; if ( math->mask == 0x80 ) { math->rack = (int)(uc_data[ *i ]); (*i)++; } value = math->rack & math->mask; math->mask >>= 1; if ( math->mask == 0 ) math->mask = 0x80; return( value ? 1 : 0 ); } unsigned int MathInputComps( int bit_count, int * i, unsigned char uc_data[], MATH *math ) { unsigned int mask; unsigned int return_value; mask = 1L << ( bit_count - 1 ); return_value = 0; while ( mask != 0) { if ( math->mask == 0x80 ) { math->rack = (int)(uc_data[ *i ]); (*i)++; } if ( math->rack & math->mask ) return_value |= mask; mask >>= 1; math->mask >>= 1; if ( math->mask == 0 ) math->mask = 0x80; } return( return_value ); } // ******************************************************************* // ******************************************************************* void MathInput_counts( int * in_position, short * totals, unsigned char uc_data[], MATH *math ) { int first; int last; int i; int c; for ( i = 0 ; i < 256 ; i++ ) math->scaled_counts[ i ] = 0; first = (int)(uc_data[ *in_position ]); (*in_position) ++; last = (int)(uc_data[ *in_position ]); (*in_position) ++; for ( ; ; ) { for ( i = first ; i <= last ; i++ ) { c = (int)(uc_data[ *in_position ]); (*in_position) ++; math->scaled_counts[ i ] = (unsigned char) c; } first = (int)(uc_data[ *in_position ]); (*in_position) ++; if ( first == 0 ) break; last = (int)(uc_data[ *in_position ]); (*in_position) ++; } MathBuild_totals( math->scaled_counts , totals); } void MathGet_symbol_scale( short * totals, MATH *math) { math->scale = totals[ d_END_OF_STREAM + 1 ]; } int MathConvert_symbol_to_int( int count, short * totals, MATH *math ) { int c; for ( c = d_END_OF_STREAM ; count < totals[ c ] ; c-- ) ; math->high_count = totals[ c + 1 ]; math->low_count = totals[ c ]; return( c ); } short MathGet_current_count( MATH *math) { int range; short count; range = (int) ( math->high - math->low ) + 1; count = (short) ((((int) ( math->code - math->low ) + 1 ) * math->scale-1 ) / range ); return( count ); } void MathInitialize_arithmetic_decoder( int * in_position, unsigned char uc_data[], MATH *math ) { int i; math->code = 0; for ( i = 0 ; i < 16 ; i++ ) { math->code <<= 1; math->code += MathInputComp( in_position, uc_data, math ); } math->low = 0; math->high = 0xffff; } void MathRemove_symbol_from_stream( int * in_position, unsigned char uc_data[], MATH *math ) { int range; range = (int)( math->high - math->low ) + 1; math->high = math->low + (unsigned short) (( range * math->high_count ) / math->scale - 1 ); math->low = math->low + (unsigned short) (( range * math->low_count ) / math->scale ); for ( ; ; ) { if ( ( math->high & 0x8000 ) == ( math->low & 0x8000 ) ) { } else if ((math->low & 0x4000) == 0x4000 && (math->high & 0x4000) == 0 ) { math->code ^= 0x4000; math->low &= 0x3fff; math->high |= 0x4000; } else return; math->low <<= 1; math->high <<= 1; math->high |= 1; math->code <<= 1; math->code += MathInputComp( in_position, uc_data, math ); } } // ************************** End of ARITH.C **************************** // ************************** End of ARITH.C **************************** // ************************** End of ARITH.C **************************** */