由于在zxing代码中找不到解决方案,我编写了自己的EAN13Writer。由于它们在zxing包中是package-private,所以我不得不复制粘贴一些方法和常量。
基本上,它只是将应该更长的线的位置存储在成员变量中。当BitMatrix被渲染时,每条不应该更长的线都会缩短5%。如果有人有同样的问题,这段代码可能会有帮助。
public class CustomEAN13Writer extends OneDimensionalCodeWriter {
static final int[] FIRST_DIGIT_ENCODINGS = {
0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A
};
static final int[] START_END_PATTERN = {1, 1, 1,};
static final int[][] L_AND_G_PATTERNS;
static final int[][] L_PATTERNS = {
{3, 2, 1, 1},
{2, 2, 2, 1},
{2, 1, 2, 2},
{1, 4, 1, 1},
{1, 1, 3, 2},
{1, 2, 3, 1},
{1, 1, 1, 4},
{1, 3, 1, 2},
{1, 2, 1, 3},
{3, 1, 1, 2}
};
static final int[] MIDDLE_PATTERN = {1, 1, 1, 1, 1};
static {
L_AND_G_PATTERNS = new int[20][];
System.arraycopy(L_PATTERNS, 0, L_AND_G_PATTERNS, 0, 10);
for (int i = 10; i < 20; i++) {
int[] widths = L_PATTERNS[i - 10];
int[] reversedWidths = new int[widths.length];
for (int j = 0; j < widths.length; j++) {
reversedWidths[j] = widths[widths.length - j - 1];
}
L_AND_G_PATTERNS[i] = reversedWidths;
}
}
private static final int CODE_WIDTH = 3 +
(7 * 6) +
5 +
(7 * 6) +
3;
private static final int DEFAULT_MARGIN = 10;
private List<Integer> mLongLinePositions;
public CustomEAN13Writer() {
mLongLinePositions = new ArrayList<>();
}
public int appendPatternAndConsiderLongLinePosition(boolean[] target, int pos, int[] pattern,
boolean startColor) {
boolean color = startColor;
int numAdded = 0;
for (int len : pattern) {
for (int j = 0; j < len; j++) {
if (pattern.equals(START_END_PATTERN) || pattern.equals(MIDDLE_PATTERN) || pattern
.equals(START_END_PATTERN)) {
mLongLinePositions.add(pos);
}
target[pos++] = color;
}
numAdded += len;
color = !color;
}
return numAdded;
}
@Override
public boolean[] encode(final String contents) {
if (contents.length() != 13) {
throw new IllegalArgumentException(
"Requested contents should be 13 digits long, but got " + contents.length());
}
try {
if (!checkStandardUPCEANChecksum(contents)) {
throw new IllegalArgumentException("Contents do not pass checksum");
}
} catch (FormatException ignored) {
throw new IllegalArgumentException("Illegal contents");
}
int firstDigit = Integer.parseInt(contents.substring(0, 1));
int parities = FIRST_DIGIT_ENCODINGS[firstDigit];
boolean[] result = new boolean[CODE_WIDTH];
int pos = 0;
pos += appendPatternAndConsiderLongLinePosition(result, pos, START_END_PATTERN, true);
for (int i = 1; i <= 6; i++) {
int digit = Integer.parseInt(contents.substring(i, i + 1));
if ((parities >> (6 - i) & 1) == 1) {
digit += 10;
}
pos += appendPatternAndConsiderLongLinePosition(result, pos, L_AND_G_PATTERNS[digit],
false);
}
pos += appendPatternAndConsiderLongLinePosition(result, pos, MIDDLE_PATTERN, false);
for (int i = 7; i <= 12; i++) {
int digit = Integer.parseInt(contents.substring(i, i + 1));
pos += appendPatternAndConsiderLongLinePosition(result, pos, L_PATTERNS[digit], true);
}
appendPatternAndConsiderLongLinePosition(result, pos, START_END_PATTERN, true);
return result;
}
public BitMatrix encodeAndRender(String contents, int width, int height) {
boolean[] code = encode(contents);
int inputWidth = code.length;
int fullWidth = inputWidth + DEFAULT_MARGIN;
int outputWidth = Math.max(width, fullWidth);
int outputHeight = Math.max(1, height);
int multiple = outputWidth / fullWidth;
int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
BitMatrix output = new BitMatrix(outputWidth, outputHeight);
for (int inputX = 0, outputX = leftPadding; inputX < inputWidth;
inputX++, outputX += multiple) {
if (code[inputX]) {
int barcodeHeight = outputHeight;
if (!mLongLinePositions.contains(inputX)) {
barcodeHeight = (int) ((float) outputHeight * 0.95f);
}
output.setRegion(outputX, 0, multiple, barcodeHeight);
}
}
return output;
}
static boolean checkStandardUPCEANChecksum(CharSequence s) throws FormatException {
int length = s.length();
if (length == 0) {
return false;
}
int sum = 0;
for (int i = length - 2; i >= 0; i -= 2) {
int digit = (int) s.charAt(i) - (int) '0';
if (digit < 0 || digit > 9) {
throw FormatException.getFormatInstance();
}
sum += digit;
}
sum *= 3;
for (int i = length - 1; i >= 0; i -= 2) {
int digit = (int) s.charAt(i) - (int) '0';
if (digit < 0 || digit > 9) {
throw FormatException.getFormatInstance();
}
sum += digit;
}
return sum % 10 == 0;
}
}