1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
public abstract class Barcode {
protected static void writeDigits(ByteArrayOutputStream stream, int value, int length) {
System.out.println();
System.out.println(Integer.toBinaryString(value));
for(int i = length - 1; i>=0; i--) {
int b = (value >> i) & 1;
System.out.print(b);
stream.write( b );
}
System.out.println();
}
private static final int[] code128_encoding = new int[] {
0b11011001100, 0b11001101100, 0b11001100110, 0b10010011000,
0b10010001100, 0b10001001100, 0b10011001000, 0b10011000100,
0b10001100100, 0b11001001000, 0b11001000100, 0b11000100100,
0b10110011100, 0b10011011100, 0b10011001110, 0b10111001100,
0b10011101100, 0b10011100110, 0b11001110010, 0b11001011100,
0b11001001110, 0b11011100100, 0b11001110100, 0b11101101110,
0b11101001100, 0b11100101100, 0b11100100110, 0b11101100100,
0b11100110100, 0b11100110010, 0b11011011000, 0b11011000110,
0b11000110110, 0b10100011000, 0b10001011000, 0b10001000110,
0b10110001000, 0b10001101000, 0b10001100010, 0b11010001000,
0b11000101000, 0b11000100010, 0b10110111000, 0b10110001110,
0b10001101110, 0b10111011000, 0b10111000110, 0b10001110110,
0b11101110110, 0b11010001110, 0b11000101110, 0b11011101000,
0b11011100010, 0b11011101110, 0b11101011000, 0b11101000110,
0b11100010110, 0b11101101000, 0b11101100010, 0b11100011010,
0b11101111010, 0b11001000010, 0b11110001010, 0b10100110000,
0b10100001100, 0b10010110000, 0b10010000110, 0b10000101100,
0b10000100110, 0b10110010000, 0b10110000100, 0b10011010000,
0b10011000010, 0b10000110100, 0b10000110010, 0b11000010010,
0b11001010000, 0b11110111010, 0b11000010100, 0b10001111010,
0b10100111100, 0b10010111100, 0b10010011110, 0b10111100100,
0b10011110100, 0b10011110010, 0b11110100100, 0b11110010100,
0b11110010010, 0b11011011110, 0b11011110110, 0b11110110110,
0b10101111000, 0b10100011110, 0b10001011110, 0b10111101000,
0b10111100010, 0b11110101000, 0b11110100010, 0b10111011110,
0b10111101110, 0b11101011110, 0b11110101110, 0b11010000100,
0b11010010000, 0b11010011100, 0b11000111010
};
private static final int code128_bits = 11;
private static final String code128_tableB = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
public static byte[] code128 (CharSequence code) {
ByteArrayOutputStream result;
// check each characters
for(int i=0; i<code.length(); i++) {
if (code128_tableB.indexOf(code.charAt(i)) < 0) return null;
}
boolean tableCActivated = code.length() > 1;
for(int i=0; i<3 && i<code.length(); i++) {
char c = code.charAt(i);
tableCActivated &= c >= '0' && c <= '9';
}
int sum = tableCActivated ? 105 : 104;
result = new ByteArrayOutputStream();
writeDigits(result, code128_encoding[sum], code128_bits);
// result.write(code128_encoding[sum]);
int i = 0;
int isum = 0;
while (i < code.length()) {
if (!tableCActivated) {
int j = 0;
// check next character to activate C table if interresting
while ((i + j < code.length()) && (code.charAt(i + j) >= '0') && (code.charAt(i + j) <= '9')) j++;
// 6 min everywhere or 4 mini at the end
tableCActivated = (j > 5) || ((i + j - 1 == code.length()) && (j > 3));
if (tableCActivated) {
// result += this.code128_encoding[99]; // C table
writeDigits(result, code128_encoding[99], code128_bits);
sum += ++isum * 99;
}
// 2 min for table C so need table B
} else if ((i == code.length()) || (code.charAt(i) < '0') || (code.charAt(i) > '9') || (code.charAt(i + 1) < '0') || (code.charAt(i + 1) > '9')) {
tableCActivated = false;
// result += this.code128_encoding[100]; // B table
writeDigits(result, code128_encoding[100], code128_bits);
sum += ++isum * 100;
}
int value;
if (tableCActivated) {
value = 0;
char c = code.charAt(i);
if (c >= '0' && c <= '9') {
value = c - '0';
}
c = code.charAt(i+1);
if (c >= '0' && c <= '9') {
value = value * 10 + c - '0';
}
i += 2;
} else {
value = code128_tableB.indexOf(code.charAt(i)); // Add one character
i += 1;
}
writeDigits(result, code128_encoding[value], code128_bits);
sum += ++isum * value;
}
// Add CRC
writeDigits(result, code128_encoding[sum % 103], code128_bits);
// Stop
writeDigits(result, code128_encoding[106], code128_bits);
// Termination bar
writeDigits(result, 0b11, 2);
return result.toByteArray();
}
public static String toSvg(byte[] digit) {
StringBuilder sb = new StringBuilder();
try {
if (toSvg(digit, sb)) {
return sb.toString();
} else {
return null;
}
} catch (IOException e) {
throw new RuntimeRethrow(e);
}
}
public static boolean toSvg(byte[] digit, Appendable svg) throws IOException {
if (digit == null) return false;
svg.append(
"<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" preserveAspectRatio=\"none\" viewBox=\"0 0 ")
.append(String.valueOf(digit.length + 1))
.append(" 100\">");
int count = 0;
int i = 0;
while (i <= digit.length) {
if (i < digit.length && digit[i] > 0) {
count ++;
} else {
if (count > 0) {
svg.append("<rect width=\"").append(String.valueOf(count)).append("\" height=\"100\" x=\"")
.append(String.valueOf(i - count))
.append("\" y=\"0\" style=\"fill:black;stroke:none\"/>");
count = 0;
}
}
i++;
}
svg.append("</svg>");
return true;
}
public static String toString(byte[] digit) {
StringBuilder sb = new StringBuilder(digit.length);
for(byte d: digit) {
if (d == 0) sb.append('0');
else if (d == 1) sb.append('1');
else sb.append('?');
}
return sb.toString();
}
}