diff --git a/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417.java b/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417.java index a9d63dc23..3402bb3d1 100644 --- a/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417.java +++ b/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417.java @@ -659,7 +659,8 @@ public final class PDF417 { String highLevel = PDF417HighLevelEncoder.encodeHighLevel(msg, compaction, encoding, autoECI); int sourceCodeWords = highLevel.length(); - int[] dimension = determineDimensions(sourceCodeWords, errorCorrectionCodeWords); + int[] dimension = determineDimensions(minCols, maxCols, minRows, maxRows, + sourceCodeWords, errorCorrectionCodeWords); int cols = dimension[0]; int rows = dimension[1]; @@ -692,16 +693,25 @@ public final class PDF417 { * Determine optimal nr of columns and rows for the specified number of * codewords. * + * @param minCols minimum number of columns + * @param maxCols maximum number of columns + * @param minRows minimum number of rows + * @param maxRows maximum number of rows * @param sourceCodeWords number of code words * @param errorCorrectionCodeWords number of error correction code words * @return dimension object containing cols as width and rows as height + * @throws WriterException when dimensions can't be determined */ - private int[] determineDimensions(int sourceCodeWords, int errorCorrectionCodeWords) throws WriterException { + protected static int[] determineDimensions(int minCols, int maxCols, + int minRows, int maxRows, + int sourceCodeWords, int errorCorrectionCodeWords) throws WriterException { float ratio = 0.0f; int[] dimension = null; + int currentCol = minCols; for (int cols = minCols; cols <= maxCols; cols++) { - + currentCol = cols; + int rows = calculateNumberOfRows(sourceCodeWords, errorCorrectionCodeWords, cols); if (rows < minRows) { @@ -725,7 +735,7 @@ public final class PDF417 { // Handle case when min values were larger than necessary if (dimension == null) { - int rows = calculateNumberOfRows(sourceCodeWords, errorCorrectionCodeWords, minCols); + int rows = calculateNumberOfRows(sourceCodeWords, errorCorrectionCodeWords, currentCol); if (rows < minRows) { dimension = new int[]{minCols, minRows}; } diff --git a/core/src/test/java/com/google/zxing/pdf417/encoder/PDF417EncoderTestCase.java b/core/src/test/java/com/google/zxing/pdf417/encoder/PDF417EncoderTestCase.java index 2f582b901..5374877a6 100644 --- a/core/src/test/java/com/google/zxing/pdf417/encoder/PDF417EncoderTestCase.java +++ b/core/src/test/java/com/google/zxing/pdf417/encoder/PDF417EncoderTestCase.java @@ -23,7 +23,10 @@ import java.util.UUID; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; +import com.google.zxing.Writer; import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.pdf417.PDF417Writer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -161,4 +164,43 @@ public final class PDF417EncoderTestCase extends Assert { public void testEncodeEmptyString() throws Exception { PDF417HighLevelEncoder.encodeHighLevel("", Compaction.AUTO, null, false); } + + @Test + public void testDimensions() throws Exception { + // test https://github.com/zxing/zxing/issues/1831 + String input = "0000000001000000022200000003330444400888888881010101010"; + testDimensions(input, new Dimensions(1, 30, 7, 10)); + testDimensions(input, new Dimensions(1, 40, 1, 7)); + testDimensions(input, new Dimensions(10, 30, 1, 5)); + testDimensions(input, new Dimensions(1, 3, 1, 15)); + testDimensions(input, new Dimensions(5, 30, 7, 7)); + testDimensions(input, new Dimensions(12, 12, 1, 17)); + testDimensions(input, new Dimensions(1, 30, 7, 7)); + } + + public static void testDimensions(String input, Dimensions dimensions) throws Exception { + int sourceCodeWords = 20; + int errorCorrectionCodeWords = 8; + + int[] calculated = PDF417.determineDimensions(dimensions.getMinCols(), dimensions.getMaxCols(), + dimensions.getMinRows(), dimensions.getMaxRows(), + sourceCodeWords, errorCorrectionCodeWords); + + assertNotNull(calculated); + assertEquals(2,calculated.length); + assertTrue(dimensions.getMinCols() <= calculated[0]); + assertTrue(dimensions.getMaxCols() >= calculated[0]); + assertTrue(dimensions.getMinRows() <= calculated[1]); + assertTrue(dimensions.getMaxRows() >= calculated[1]); + assertNotNull(generatePDF417BitMatrix(input, 371, null, dimensions)); + } + + public static BitMatrix generatePDF417BitMatrix(final String barcodeText, final int width, + final Integer heightRequested, final Dimensions dimensions) throws WriterException { + final Writer barcodeWriter = new PDF417Writer(); + final int height = heightRequested == null ? width / 4 : heightRequested; + final Map hints = Map.of(EncodeHintType.MARGIN, 0, + EncodeHintType.PDF417_DIMENSIONS, dimensions); + return barcodeWriter.encode(barcodeText, BarcodeFormat.PDF_417, width, height, hints); + } }