2016-04-07 19:13:43 +03:00
/* hanxin.c - Han Xin Code
libzint - the open source barcode library
Copyright ( C ) 2009 - 2016 Robin Stuart < rstuart114 @ gmail . com >
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE .
*/
/* This code attempts to implement Han Xin Code according to AIMD-015:2010 (Rev 0.8) */
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# ifdef _MSC_VER
# include <malloc.h>
# endif
# include "common.h"
# include "reedsol.h"
# include "hanxin.h"
2016-04-09 19:01:21 +03:00
/* Find which submode to use for a text character */
int getsubmode ( char input ) {
int submode = 2 ;
if ( ( input > = ' 0 ' ) & & ( input < = ' 9 ' ) ) {
submode = 1 ;
}
if ( ( input > = ' A ' ) & & ( input < = ' Z ' ) ) {
submode = 1 ;
}
if ( ( input > = ' a ' ) & & ( input < = ' z ' ) ) {
submode = 1 ;
}
return submode ;
}
2016-04-08 00:30:37 +03:00
/* Calculate the approximate length of the binary string */
2016-04-09 19:01:21 +03:00
int calculate_binlength ( char mode [ ] , const unsigned char source [ ] , int length ) {
2016-04-08 00:30:37 +03:00
int i ;
2016-04-10 22:36:57 +03:00
char lastmode = ' t ' ;
2016-04-08 00:30:37 +03:00
int est_binlen = 0 ;
2016-04-09 19:01:21 +03:00
int submode = 1 ;
2016-04-08 00:30:37 +03:00
for ( i = 0 ; i < length ; i + + ) {
switch ( mode [ i ] ) {
case ' n ' :
if ( lastmode ! = ' n ' ) {
est_binlen + = 14 ;
lastmode = ' n ' ;
}
est_binlen + = 4 ;
break ;
case ' t ' :
if ( lastmode ! = ' t ' ) {
est_binlen + = 10 ;
lastmode = ' t ' ;
2016-04-09 19:01:21 +03:00
submode = 1 ;
}
if ( getsubmode ( ( char ) source [ i ] ) ! = submode ) {
est_binlen + = 6 ;
submode = getsubmode ( ( char ) source [ i ] ) ;
2016-04-08 00:30:37 +03:00
}
est_binlen + = 6 ;
2016-04-10 22:36:57 +03:00
break ;
2016-04-08 00:30:37 +03:00
case ' b ' :
if ( lastmode ! = ' b ' ) {
est_binlen + = 17 ;
lastmode = ' b ' ;
}
2016-04-10 22:36:57 +03:00
est_binlen + = 8 ;
break ;
2016-04-08 00:30:37 +03:00
}
}
return est_binlen ;
}
/* Calculate mode switching */
void hx_define_mode ( char mode [ ] , const unsigned char source [ ] , int length ) {
int i ;
char lastmode = ' t ' ;
for ( i = 0 ; i < length ; i + + ) {
if ( ( source [ i ] > = ' 0 ' ) & & ( source [ i ] < = ' 9 ' ) ) {
mode [ i ] = ' n ' ;
if ( lastmode ! = ' n ' ) {
lastmode = ' n ' ;
}
} else {
if ( ( source [ i ] < = 127 ) & & ( ( source [ i ] < = 27 ) | | ( source [ i ] > = 32 ) ) ) {
mode [ i ] = ' t ' ;
if ( lastmode ! = ' t ' ) {
lastmode = ' t ' ;
}
} else {
mode [ i ] = ' b ' ;
if ( lastmode ! = ' b ' ) {
lastmode = ' b ' ;
}
}
}
}
mode [ length ] = ' \0 ' ;
}
/* Convert Text 1 sub-mode character to encoding value, as given in table 3 */
int lookup_text1 ( char input ) {
int encoding_value = 0 ;
if ( ( input > = ' 0 ' ) & & ( input < = ' 9 ' ) ) {
encoding_value = input - ' 0 ' ;
}
if ( ( input > = ' A ' ) & & ( input < = ' Z ' ) ) {
encoding_value = input - ' A ' + 10 ;
}
if ( ( input > = ' a ' ) & & ( input < = ' z ' ) ) {
encoding_value = input - ' a ' + 36 ;
}
return encoding_value ;
}
/* Convert Text 2 sub-mode character to encoding value, as given in table 4 */
int lookup_text2 ( char input ) {
int encoding_value = 0 ;
if ( ( input > = 0 ) & & ( input < = 27 ) ) {
encoding_value = input ;
}
if ( ( input > = ' ' ) & & ( input < = ' / ' ) ) {
encoding_value = input - ' ' + 28 ;
}
if ( ( input > = ' [ ' ) & & ( input < = 96 ) ) {
encoding_value = input - ' [ ' + 51 ;
}
if ( ( input > = ' { ' ) & & ( input < = 127 ) ) {
encoding_value = input - ' { ' + 57 ;
}
return encoding_value ;
}
/* Convert input data to binary stream */
void calculate_binary ( char binary [ ] , char mode [ ] , const unsigned char source [ ] , int length ) {
int block_length ;
int position = 0 ;
int i , p , count , encoding_value ;
int debug = 1 ;
do {
block_length = 0 ;
do {
block_length + + ;
} while ( mode [ position + block_length ] = = mode [ position ] ) ;
switch ( mode [ position ] ) {
case ' n ' :
/* Numeric mode */
/* Mode indicator */
strcat ( binary , " 0001 " ) ;
if ( debug ) {
printf ( " Numeric \n " ) ;
}
i = 0 ;
while ( i < block_length ) {
int first = 0 , second = 0 , third = 0 ;
first = posn ( NEON , ( char ) source [ position + i ] ) ;
count = 1 ;
encoding_value = first ;
if ( i + 1 < block_length & & mode [ position + i + 1 ] = = ' n ' ) {
second = posn ( NEON , ( char ) source [ position + i + 1 ] ) ;
count = 2 ;
encoding_value = ( encoding_value * 10 ) + second ;
if ( i + 2 < block_length & & mode [ position + i + 2 ] = = ' n ' ) {
third = posn ( NEON , ( char ) source [ position + i + 2 ] ) ;
count = 3 ;
encoding_value = ( encoding_value * 10 ) + third ;
}
}
for ( p = 0 ; p < 10 ; p + + ) {
if ( encoding_value & ( 0x200 > > p ) ) {
strcat ( binary , " 1 " ) ;
} else {
strcat ( binary , " 0 " ) ;
}
}
if ( debug ) {
printf ( " 0x%4X (%d) " , encoding_value , encoding_value ) ;
}
i + = count ;
}
/* Mode terminator depends on number of characters in last group (Table 2) */
switch ( count ) {
case 1 :
strcat ( binary , " 1111111101 " ) ;
break ;
case 2 :
strcat ( binary , " 1111111110 " ) ;
break ;
case 3 :
strcat ( binary , " 1111111111 " ) ;
break ;
}
if ( debug ) {
printf ( " (TERM %d) \n " , count ) ;
}
break ;
case ' t ' :
/* Text mode */
if ( position ! = 0 ) {
/* Mode indicator */
strcat ( binary , " 0010 " ) ;
if ( debug ) {
printf ( " Text \n " ) ;
}
}
int submode = 1 ;
i = 0 ;
while ( i < block_length ) {
if ( getsubmode ( source [ i + position ] ) ! = submode ) {
/* Change submode */
strcat ( binary , " 111110 " ) ;
submode = getsubmode ( source [ i + position ] ) ;
if ( debug ) {
printf ( " SWITCH " ) ;
}
}
if ( submode = = 1 ) {
encoding_value = lookup_text1 ( ( char ) source [ i + position ] ) ;
} else {
encoding_value = lookup_text2 ( ( char ) source [ i + position ] ) ;
}
for ( p = 0 ; p < 6 ; p + + ) {
if ( encoding_value & ( 0x20 > > p ) ) {
strcat ( binary , " 1 " ) ;
} else {
strcat ( binary , " 0 " ) ;
}
}
if ( debug ) {
printf ( " %c (%d) " , ( char ) source [ i ] , encoding_value ) ;
}
i + + ;
}
/* Terminator */
strcat ( binary , " 111111 " ) ;
if ( debug ) {
printf ( " \n " ) ;
}
break ;
case ' b ' :
/* Binary Mode */
/* Mode indicator */
strcat ( binary , " 0011 " ) ;
/* Count indicator */
for ( p = 0 ; p < 13 ; p + + ) {
if ( block_length & ( 0x1000 > > p ) ) {
strcat ( binary , " 1 " ) ;
} else {
strcat ( binary , " 0 " ) ;
}
}
if ( debug ) {
printf ( " Binary (length %d) \n " , block_length ) ;
}
i = 0 ;
while ( i < block_length ) {
/* 8-bit bytes with no conversion */
for ( p = 0 ; p < 8 ; p + + ) {
if ( source [ i + position ] & ( 0x80 > > p ) ) {
strcat ( binary , " 1 " ) ;
} else {
strcat ( binary , " 0 " ) ;
}
}
if ( debug ) {
printf ( " %d " , source [ i + position ] ) ;
}
i + + ;
}
if ( debug ) {
printf ( " \n " ) ;
}
break ;
}
position + = block_length ;
} while ( position < length ) ;
}
2016-04-09 19:01:21 +03:00
/* Finder pattern for top left of symbol */
void hx_place_finder_top_left ( unsigned char * grid , int size ) {
int xp , yp ;
int x = 0 , y = 0 ;
int finder [ ] = {
1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 0 , 0 , 0 , 0 , 0 , 0 ,
1 , 0 , 1 , 1 , 1 , 1 , 1 ,
1 , 0 , 1 , 0 , 0 , 0 , 0 ,
1 , 0 , 1 , 0 , 1 , 1 , 1 ,
1 , 0 , 1 , 0 , 1 , 1 , 1 ,
1 , 0 , 1 , 0 , 1 , 1 , 1
} ;
for ( xp = 0 ; xp < 7 ; xp + + ) {
for ( yp = 0 ; yp < 7 ; yp + + ) {
if ( finder [ xp + ( 7 * yp ) ] = = 1 ) {
grid [ ( ( yp + y ) * size ) + ( xp + x ) ] = 0x11 ;
} else {
grid [ ( ( yp + y ) * size ) + ( xp + x ) ] = 0x10 ;
}
}
}
}
/* Finder pattern for top right and bottom left of symbol */
void hx_place_finder ( unsigned char * grid , int size , int x , int y ) {
int xp , yp ;
int finder [ ] = {
1 , 1 , 1 , 1 , 1 , 1 , 1 ,
0 , 0 , 0 , 0 , 0 , 0 , 1 ,
1 , 1 , 1 , 1 , 1 , 0 , 1 ,
0 , 0 , 0 , 0 , 1 , 0 , 1 ,
1 , 1 , 1 , 0 , 1 , 0 , 1 ,
1 , 1 , 1 , 0 , 1 , 0 , 1 ,
1 , 1 , 1 , 0 , 1 , 0 , 1
} ;
for ( xp = 0 ; xp < 7 ; xp + + ) {
for ( yp = 0 ; yp < 7 ; yp + + ) {
if ( finder [ xp + ( 7 * yp ) ] = = 1 ) {
grid [ ( ( yp + y ) * size ) + ( xp + x ) ] = 0x11 ;
} else {
grid [ ( ( yp + y ) * size ) + ( xp + x ) ] = 0x10 ;
}
}
}
}
/* Finder pattern for bottom right of symbol */
void hx_place_finder_bottom_right ( unsigned char * grid , int size ) {
int xp , yp ;
int x = size - 7 , y = size - 7 ;
int finder [ ] = {
1 , 1 , 1 , 0 , 1 , 0 , 1 ,
1 , 1 , 1 , 0 , 1 , 0 , 1 ,
1 , 1 , 1 , 0 , 1 , 0 , 1 ,
0 , 0 , 0 , 0 , 1 , 0 , 1 ,
1 , 1 , 1 , 1 , 1 , 0 , 1 ,
0 , 0 , 0 , 0 , 0 , 0 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1
} ;
for ( xp = 0 ; xp < 7 ; xp + + ) {
for ( yp = 0 ; yp < 7 ; yp + + ) {
if ( finder [ xp + ( 7 * yp ) ] = = 1 ) {
grid [ ( ( yp + y ) * size ) + ( xp + x ) ] = 0x11 ;
} else {
grid [ ( ( yp + y ) * size ) + ( xp + x ) ] = 0x10 ;
}
}
}
}
/* Avoid plotting outside symbol or over finder patterns */
void hx_safe_plot ( unsigned char * grid , int size , int x , int y , int value ) {
if ( ( x > = 0 ) & & ( x < size ) ) {
if ( ( y > = 0 ) & & ( y < size ) ) {
if ( grid [ ( y * size ) + x ] = = 0 ) {
grid [ ( y * size ) + x ] = value ;
}
}
}
}
/* Plot an alignment pattern around top and right of a module */
void hx_plot_alignment ( unsigned char * grid , int size , int x , int y , int w , int h ) {
int i ;
hx_safe_plot ( grid , size , x , y , 0x11 ) ;
hx_safe_plot ( grid , size , x - 1 , y + 1 , 0x10 ) ;
for ( i = 1 ; i < = w ; i + + ) {
/* Top */
hx_safe_plot ( grid , size , x - i , y , 0x11 ) ;
hx_safe_plot ( grid , size , x - i - 1 , y + 1 , 0x10 ) ;
}
for ( i = 1 ; i < h ; i + + ) {
/* Right */
hx_safe_plot ( grid , size , x , y + i , 0x11 ) ;
hx_safe_plot ( grid , size , x - 1 , y + i + 1 , 0x10 ) ;
}
}
2016-04-10 22:36:57 +03:00
/* Plot assistant alignment patterns */
2016-04-09 19:01:21 +03:00
void hx_plot_assistant ( unsigned char * grid , int size , int x , int y ) {
hx_safe_plot ( grid , size , x - 1 , y - 1 , 0x10 ) ;
hx_safe_plot ( grid , size , x , y - 1 , 0x10 ) ;
hx_safe_plot ( grid , size , x + 1 , y - 1 , 0x10 ) ;
hx_safe_plot ( grid , size , x - 1 , y , 0x10 ) ;
hx_safe_plot ( grid , size , x , y , 0x11 ) ;
hx_safe_plot ( grid , size , x + 1 , y , 0x10 ) ;
hx_safe_plot ( grid , size , x - 1 , y + 1 , 0x10 ) ;
hx_safe_plot ( grid , size , x , y + 1 , 0x10 ) ;
hx_safe_plot ( grid , size , x + 1 , y + 1 , 0x10 ) ;
}
/* Put static elements in the grid */
void hx_setup_grid ( unsigned char * grid , int size , int version ) {
int i , j ;
for ( i = 0 ; i < size ; i + + ) {
for ( j = 0 ; j < size ; j + + ) {
grid [ ( i * size ) + j ] = 0 ;
}
}
/* Add finder patterns */
hx_place_finder_top_left ( grid , size ) ;
hx_place_finder ( grid , size , 0 , size - 7 ) ;
hx_place_finder ( grid , size , size - 7 , 0 ) ;
hx_place_finder_bottom_right ( grid , size ) ;
/* Add finder pattern separator region */
for ( i = 0 ; i < 8 ; i + + ) {
/* Top left */
grid [ ( 7 * size ) + i ] = 0x10 ;
grid [ ( i * size ) + 7 ] = 0x10 ;
/* Top right */
grid [ ( 7 * size ) + ( size - i - 1 ) ] = 0x10 ;
grid [ ( ( size - i - 1 ) * size ) + 7 ] = 0x10 ;
/* Bottom left */
grid [ ( i * size ) + ( size - 8 ) ] = 0x10 ;
grid [ ( ( size - 8 ) * size ) + i ] = 0x10 ;
/* Bottom right */
grid [ ( ( size - 8 ) * size ) + ( size - i - 1 ) ] = 0x10 ;
grid [ ( ( size - i - 1 ) * size ) + ( size - 8 ) ] = 0x10 ;
}
/* Reserve function information region */
for ( i = 0 ; i < 9 ; i + + ) {
/* Top left */
grid [ ( 8 * size ) + i ] = 0x10 ;
grid [ ( i * size ) + 8 ] = 0x10 ;
/* Top right */
grid [ ( 8 * size ) + ( size - i - 1 ) ] = 0x10 ;
grid [ ( ( size - i - 1 ) * size ) + 8 ] = 0x10 ;
/* Bottom left */
grid [ ( i * size ) + ( size - 9 ) ] = 0x10 ;
grid [ ( ( size - 9 ) * size ) + i ] = 0x10 ;
/* Bottom right */
grid [ ( ( size - 9 ) * size ) + ( size - i - 1 ) ] = 0x10 ;
grid [ ( ( size - i - 1 ) * size ) + ( size - 9 ) ] = 0x10 ;
}
if ( version > 3 ) {
int k = hx_module_k [ version - 1 ] ;
int r = hx_module_r [ version - 1 ] ;
int m = hx_module_m [ version - 1 ] ;
int x , y , row_switch , column_switch ;
int module_height , module_width ;
int mod_x , mod_y ;
/* Add assistant alignment patterns to left and right */
y = 0 ;
mod_y = 0 ;
do {
if ( mod_y < m ) {
module_height = k ;
} else {
module_height = r - 1 ;
}
if ( ( mod_y % 2 ) = = 0 ) {
if ( ( m % 2 ) = = 1 ) {
hx_plot_assistant ( grid , size , 0 , y ) ;
}
} else {
if ( ( m % 2 ) = = 0 ) {
hx_plot_assistant ( grid , size , 0 , y ) ;
}
hx_plot_assistant ( grid , size , size - 1 , y ) ;
}
mod_y + + ;
y + = module_height ;
} while ( y < size ) ;
/* Add assistant alignment patterns to top and bottom */
x = ( size - 1 ) ;
mod_x = 0 ;
do {
if ( mod_x < m ) {
module_width = k ;
} else {
module_width = r - 1 ;
}
if ( ( mod_x % 2 ) = = 0 ) {
if ( ( m % 2 ) = = 1 ) {
hx_plot_assistant ( grid , size , x , ( size - 1 ) ) ;
}
} else {
if ( ( m % 2 ) = = 0 ) {
hx_plot_assistant ( grid , size , x , ( size - 1 ) ) ;
}
hx_plot_assistant ( grid , size , x , 0 ) ;
}
mod_x + + ;
x - = module_width ;
} while ( x > = 0 ) ;
/* Add alignment pattern */
column_switch = 1 ;
y = 0 ;
mod_y = 0 ;
do {
if ( mod_y < m ) {
module_height = k ;
} else {
module_height = r - 1 ;
}
if ( column_switch = = 1 ) {
row_switch = 1 ;
column_switch = 0 ;
} else {
row_switch = 0 ;
column_switch = 1 ;
}
x = ( size - 1 ) ;
mod_x = 0 ;
do {
if ( mod_x < m ) {
module_width = k ;
} else {
module_width = r - 1 ;
}
if ( row_switch = = 1 ) {
if ( ! ( y = = 0 & & x = = ( size - 1 ) ) ) {
hx_plot_alignment ( grid , size , x , y , module_width , module_height ) ;
}
row_switch = 0 ;
} else {
row_switch = 1 ;
}
mod_x + + ;
x - = module_width ;
} while ( x > = 0 ) ;
mod_y + + ;
y + = module_height ;
} while ( y < size ) ;
}
}
2016-04-16 14:57:45 +03:00
/* Calculate error correction codes */
void hx_add_ecc ( unsigned char fullstream [ ] , unsigned char datastream [ ] , int version , int ecc_level ) {
unsigned char data_block [ 180 ] ;
unsigned char ecc_block [ 36 ] ;
//FIXME: Check that this is the correct method for assembling the data
int i , j , block ;
int batch_size , data_length , ecc_length ;
int input_position = - 1 ;
int output_position = - 1 ;
for ( i = 0 ; i < 3 ; i + + ) {
batch_size = hx_table_d1 [ ( ( ( version - 1 ) + ( ecc_level - 1 ) ) * 9 ) + ( 3 * i ) ] ;
data_length = hx_table_d1 [ ( ( ( version - 1 ) + ( ecc_level - 1 ) ) * 9 ) + ( 3 * i ) + 1 ] ;
ecc_length = hx_table_d1 [ ( ( ( version - 1 ) + ( ecc_level - 1 ) ) * 9 ) + ( 3 * i ) + 2 ] ;
for ( block = 0 ; block < batch_size ; block + + ) {
for ( j = 0 ; j < data_length ; j + + ) {
input_position + + ;
output_position + + ;
data_block [ j ] = datastream [ input_position ] ;
fullstream [ output_position ] = datastream [ input_position ] ;
}
rs_init_gf ( 0x163 ) ; // x^8 + x^6 + x^5 + x + 1 = 0
rs_init_code ( ecc_length , 1 ) ;
rs_encode ( data_length , data_block , ecc_block ) ;
rs_free ( ) ;
for ( j = 0 ; j < ecc_length ; j + + ) {
output_position + + ;
fullstream [ output_position ] = ecc_block [ ecc_length - j - 1 ] ;
}
}
}
}
/* Rearrange data in batches of 13 codewords (section 5.8.2) */
void make_picket_fence ( unsigned char fullstream [ ] , unsigned char picket_fence [ ] , int streamsize ) {
int i , start ;
int output_position = 0 ;
for ( start = 0 ; start < 13 ; start + + ) {
for ( i = start ; i < streamsize ; i + = 13 ) {
if ( i < streamsize ) {
picket_fence [ output_position ] = fullstream [ i ] ;
output_position + + ;
}
}
}
}
2016-04-08 00:30:37 +03:00
/* Han Xin Code - main */
2016-04-07 19:13:43 +03:00
int han_xin ( struct zint_symbol * symbol , const unsigned char source [ ] , int length ) {
2016-04-08 00:30:37 +03:00
char mode [ length + 1 ] ;
int est_binlen ;
2016-04-09 19:01:21 +03:00
int ecc_level = 1 ;
int i , j , version ;
2016-04-10 22:36:57 +03:00
int data_codewords , size ;
int est_codewords ;
2016-04-08 00:30:37 +03:00
hx_define_mode ( mode , source , length ) ;
2016-04-09 19:01:21 +03:00
est_binlen = calculate_binlength ( mode , source , length ) ;
2016-04-10 22:36:57 +03:00
est_codewords = est_binlen / 8 ;
if ( est_binlen % 8 ! = 0 ) {
est_codewords + + ;
}
char binary [ est_binlen + 1 ] ;
for ( i = 0 ; i < est_binlen + 1 ; i + + ) {
binary [ i ] = ' \0 ' ;
}
2016-04-08 00:30:37 +03:00
binary [ 0 ] = ' \0 ' ;
calculate_binary ( binary , mode , source , length ) ;
2016-04-09 19:01:21 +03:00
version = 85 ;
for ( i = 84 ; i > 0 ; i - - ) {
switch ( ecc_level ) {
case 1 :
2016-04-10 22:36:57 +03:00
if ( hx_data_codewords_L1 [ i - 1 ] > est_codewords ) {
2016-04-09 19:01:21 +03:00
version = i ;
2016-04-10 22:36:57 +03:00
data_codewords = hx_data_codewords_L1 [ i - 1 ] ;
2016-04-09 19:01:21 +03:00
}
break ;
case 2 :
2016-04-10 22:36:57 +03:00
if ( hx_data_codewords_L2 [ i - 1 ] > est_codewords ) {
2016-04-09 19:01:21 +03:00
version = i ;
2016-04-10 22:36:57 +03:00
data_codewords = hx_data_codewords_L2 [ i - 1 ] ;
2016-04-09 19:01:21 +03:00
}
break ;
case 3 :
2016-04-10 22:36:57 +03:00
if ( hx_data_codewords_L3 [ i - 1 ] > est_codewords ) {
2016-04-09 19:01:21 +03:00
version = i ;
2016-04-10 22:36:57 +03:00
data_codewords = hx_data_codewords_L3 [ i - 1 ] ;
2016-04-09 19:01:21 +03:00
}
break ;
case 4 :
2016-04-10 22:36:57 +03:00
if ( hx_data_codewords_L4 [ i - 1 ] > est_codewords ) {
2016-04-09 19:01:21 +03:00
version = i ;
2016-04-10 22:36:57 +03:00
data_codewords = hx_data_codewords_L4 [ i - 1 ] ;
2016-04-09 19:01:21 +03:00
}
break ;
}
}
if ( version = = 85 ) {
strcpy ( symbol - > errtxt , " Input too long for selected error correction level " ) ;
return ZINT_ERROR_TOO_LONG ;
}
size = ( version * 2 ) + 21 ;
2016-04-16 14:57:45 +03:00
2016-04-09 19:01:21 +03:00
# ifndef _MSC_VER
2016-04-16 14:57:45 +03:00
unsigned char datastream [ data_codewords ] ;
unsigned char fullstream [ hx_total_codewords [ version - 1 ] ] ;
unsigned char picket_fence [ hx_total_codewords [ version - 1 ] ] ;
2016-04-09 19:01:21 +03:00
unsigned char grid [ size * size ] ;
# else
2016-04-16 14:57:45 +03:00
datastream = ( unsigned char * ) _alloca ( ( data_codewords ) * sizeof ( unsigned char ) ) ;
fullstream = ( unsigned char * ) _alloca ( ( hx_total_codewords [ version - 1 ] ) * sizeof ( unsigned char ) ) ;
picket_fence = ( unsigned char * ) _alloca ( ( hx_total_codewords [ version - 1 ] ) * sizeof ( unsigned char ) ) ;
2016-04-09 19:01:21 +03:00
grid = ( unsigned char * ) _alloca ( ( size * size ) * sizeof ( unsigned char ) ) ;
# endif
2016-04-16 14:57:45 +03:00
2016-04-10 22:36:57 +03:00
for ( i = 0 ; i < data_codewords ; i + + ) {
datastream [ i ] = 0 ;
}
for ( i = 0 ; i < est_binlen ; i + + ) {
if ( binary [ i ] = = ' 1 ' ) {
datastream [ i / 8 ] + = 0x80 > > ( i % 8 ) ;
}
}
2016-04-16 14:57:45 +03:00
2016-04-09 19:01:21 +03:00
hx_setup_grid ( grid , size , version ) ;
2016-04-16 14:57:45 +03:00
2016-04-08 00:30:37 +03:00
printf ( " Binary: %s \n " , binary ) ;
2016-04-10 22:36:57 +03:00
printf ( " Data Codewords: \n " ) ;
for ( i = 0 ; i < data_codewords ; i + + ) {
printf ( " %2X " , datastream [ i ] ) ;
}
printf ( " \n " ) ;
2016-04-16 14:57:45 +03:00
hx_add_ecc ( fullstream , datastream , version , ecc_level ) ;
printf ( " Full stream, including ecc: \n " ) ;
for ( i = 0 ; i < hx_total_codewords [ version - 1 ] ; i + + ) {
printf ( " %2X " , fullstream [ i ] ) ;
}
printf ( " \n " ) ;
make_picket_fence ( fullstream , picket_fence , hx_total_codewords [ version - 1 ] ) ;
printf ( " Picket fence: \n " ) ;
for ( i = 0 ; i < hx_total_codewords [ version - 1 ] ; i + + ) {
printf ( " %2X " , picket_fence [ i ] ) ;
}
printf ( " \n " ) ;
printf ( " Version %d, ECC level %d \n " , version , ecc_level ) ;
2016-04-09 19:01:21 +03:00
symbol - > width = size ;
symbol - > rows = size ;
for ( i = 0 ; i < size ; i + + ) {
for ( j = 0 ; j < size ; j + + ) {
if ( grid [ ( i * size ) + j ] & 0x01 ) {
set_module ( symbol , i , j ) ;
}
}
symbol - > row_height [ i ] = 1 ;
}
2016-04-16 14:57:45 +03:00
return 1 ;
2016-04-07 19:13:43 +03:00
}