diff --git a/src/test/java/LeptonicaFrameConverterTest.java b/src/test/java/LeptonicaFrameConverterTest.java new file mode 100644 index 00000000..d888d0b4 --- /dev/null +++ b/src/test/java/LeptonicaFrameConverterTest.java @@ -0,0 +1,130 @@ +import org.bytedeco.javacv.Frame; +import org.bytedeco.javacv.LeptonicaFrameConverter; +import org.bytedeco.javacv.OpenCVFrameConverter; +import org.bytedeco.leptonica.PIX; +import org.bytedeco.leptonica.global.leptonica; +import org.bytedeco.opencv.global.opencv_imgcodecs; +import org.bytedeco.opencv.opencv_core.Mat; +import org.bytedeco.opencv.opencv_core.Point; +import org.bytedeco.opencv.opencv_core.Scalar; +import org.junit.jupiter.api.function.Executable; +import org.junit.jupiter.api.io.CleanupMode; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.bytedeco.opencv.global.opencv_core.CV_8UC1; +import static org.bytedeco.opencv.global.opencv_core.CV_8UC3; +import static org.bytedeco.opencv.global.opencv_imgproc.line; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +/** + * These tests compare that the Frame to Leptonica PIX converter works correctly against known-good + * files that come in different stride lengths. + * + * @link Source bug + */ +public class LeptonicaFrameConverterTest { + @TempDir + static Path tempDir; + + @ParameterizedTest + @ValueSource(ints = {8, 9, 10, 11, 12}) + public void testBw(final int cols) { + LeptonicaFrameConverter lfcFixed = new LeptonicaFrameConverter(); + OpenCVFrameConverter.ToMat matConverter = new OpenCVFrameConverter.ToMat(); + + final int rows = 10; + + Mat originalImage = new Mat(rows, cols, CV_8UC1); + int stepX = 255 / cols; + int stepY = 255 / rows; + int stepTotal = Math.min(stepX, stepY); + for (int i = 0; i < originalImage.rows(); i++) { + for (int j = 0; j < originalImage.cols(); j++) { + line(originalImage, new Point(j, i), new Point(j, i), new Scalar(stepTotal * j)); + } + } + + //System.out.println(String.format("orig\n capacity %d\n w %d\n h %d\n ch %d\n dpt %d\n str %d", originalImage.asByteBuffer().capacity(), originalImage.cols(), originalImage.rows(), originalImage.channels(), originalImage.depth(), originalImage.step())); + opencv_imgcodecs.imwrite(tempDir + "/mat-bw-" + rows + "x" + cols + ".bmp", originalImage); + assertDoesNotThrow(new Executable() { + @Override + public void execute() throws Throwable { + assertArrayEquals( + Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("LeptonicaFrameConverter/mat-bw-" + rows + "x" + cols + ".bmp").getPath())), + Files.readAllBytes(Paths.get(tempDir + "/mat-bw-" + rows + "x" + cols + ".bmp")), + "Mat file differs"); + } + }); + + Frame ocrFrame = matConverter.convert(originalImage); + //System.out.println(String.format("frame\n capacity %d\n w %d\n h %d\n ch %d\n dpt %d\n str %d", ocrFrame.image[0].capacity(), ocrFrame.imageWidth, ocrFrame.imageHeight, ocrFrame.imageChannels, ocrFrame.imageDepth, ocrFrame.imageStride)); + + PIX converted = lfcFixed.convert(ocrFrame); + //System.out.println(String.format("fixconverted pix\n capacity %d\n w %d\n h %d\n ch %d\n dpt %d\n wpl %d", converted.createBuffer().capacity(), converted.w(), converted.h(), -1, converted.d(), converted.wpl())); + leptonica.pixWrite(tempDir + "/pix-bw-" + rows + "x" + cols + ".bmp", converted, leptonica.IFF_BMP); + assertDoesNotThrow(new Executable() { + @Override + public void execute() throws Throwable { + assertArrayEquals( + Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("LeptonicaFrameConverter/pix-bw-" + rows + "x" + cols + ".bmp").getPath())), + Files.readAllBytes(Paths.get(tempDir + "/pix-bw-" + rows + "x" + cols + ".bmp")), + "Pix file differs"); + } + }); + } + + @ParameterizedTest + @ValueSource(ints = {8, 9, 10, 11, 12}) + public void testRgb(final int cols) { + LeptonicaFrameConverter lfcFixed = new LeptonicaFrameConverter(); + OpenCVFrameConverter.ToMat matConverter = new OpenCVFrameConverter.ToMat(); + + final int rows = 10; + + Mat originalImage = new Mat(rows, cols, CV_8UC3); + int stepX = 255 / cols; + int stepY = 255 / rows; + for (int i = 0; i < originalImage.rows(); i++) { + for (int j = 0; j < originalImage.cols(); j++) { + // Warning: OpenCV uses BGR ordering under the hood! + // See https://learnopencv.com/why-does-opencv-use-bgr-color-format/ + line(originalImage, new Point(j, i), new Point(j, i), new Scalar(i * stepY, j * stepX, 0, 0)); + } + } + + //System.out.println(String.format("orig\n capacity %d\n w %d\n h %d\n ch %d\n dpt %d\n str %d", originalImage.asByteBuffer().capacity(), originalImage.cols(), originalImage.rows(), originalImage.channels(), originalImage.depth(), originalImage.step())); + opencv_imgcodecs.imwrite(tempDir + "/mat-rgb-" + rows + "x" + cols + ".bmp", originalImage); + assertDoesNotThrow(new Executable() { + @Override + public void execute() throws Throwable { + assertArrayEquals( + Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("LeptonicaFrameConverter/mat-rgb-" + rows + "x" + cols + ".bmp").getPath())), + Files.readAllBytes(Paths.get(tempDir + "/mat-rgb-" + rows + "x" + cols + ".bmp")), + "Mat file differs"); + } + }); + + Frame ocrFrame = matConverter.convert(originalImage); + //System.out.println(String.format("frame\n capacity %d\n w %d\n h %d\n ch %d\n dpt %d\n str %d", ocrFrame.image[0].capacity(), ocrFrame.imageWidth, ocrFrame.imageHeight, ocrFrame.imageChannels, ocrFrame.imageDepth, ocrFrame.imageStride)); + + PIX converted = lfcFixed.convert(ocrFrame); + //System.out.println(String.format("fixconverted pix\n capacity %d\n w %d\n h %d\n ch %d\n dpt %d\n wpl %d", converted.createBuffer().capacity(), converted.w(), converted.h(), -1, converted.d(), converted.wpl())); + leptonica.pixWrite(tempDir + "/pix-rgb-" + rows + "x" + cols + ".bmp", converted, leptonica.IFF_BMP); + assertDoesNotThrow(new Executable() { + @Override + public void execute() throws Throwable { + assertArrayEquals( + Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("LeptonicaFrameConverter/pix-rgb-" + rows + "x" + cols + ".bmp").getPath())), + Files.readAllBytes(Paths.get(tempDir + "/pix-rgb-" + rows + "x" + cols + ".bmp")), + "Pix file differs"); + } + }); + } +} diff --git a/src/test/resources/LeptonicaFrameConverter/mat-bw-10x10.bmp b/src/test/resources/LeptonicaFrameConverter/mat-bw-10x10.bmp new file mode 100644 index 00000000..06e89a84 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/mat-bw-10x10.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/mat-bw-10x11.bmp b/src/test/resources/LeptonicaFrameConverter/mat-bw-10x11.bmp new file mode 100644 index 00000000..091f7ceb Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/mat-bw-10x11.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/mat-bw-10x12.bmp b/src/test/resources/LeptonicaFrameConverter/mat-bw-10x12.bmp new file mode 100644 index 00000000..ac981087 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/mat-bw-10x12.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/mat-bw-10x8.bmp b/src/test/resources/LeptonicaFrameConverter/mat-bw-10x8.bmp new file mode 100644 index 00000000..07a89b97 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/mat-bw-10x8.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/mat-bw-10x9.bmp b/src/test/resources/LeptonicaFrameConverter/mat-bw-10x9.bmp new file mode 100644 index 00000000..da21367b Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/mat-bw-10x9.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x10.bmp b/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x10.bmp new file mode 100644 index 00000000..837f5336 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x10.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x11.bmp b/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x11.bmp new file mode 100644 index 00000000..5ec56025 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x11.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x12.bmp b/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x12.bmp new file mode 100644 index 00000000..f3535727 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x12.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x8.bmp b/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x8.bmp new file mode 100644 index 00000000..e6d49db5 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x8.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x9.bmp b/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x9.bmp new file mode 100644 index 00000000..f7643f18 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/mat-rgb-10x9.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/pix-bw-10x10.bmp b/src/test/resources/LeptonicaFrameConverter/pix-bw-10x10.bmp new file mode 100644 index 00000000..2dc2ddd2 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/pix-bw-10x10.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/pix-bw-10x11.bmp b/src/test/resources/LeptonicaFrameConverter/pix-bw-10x11.bmp new file mode 100644 index 00000000..5284fc17 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/pix-bw-10x11.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/pix-bw-10x12.bmp b/src/test/resources/LeptonicaFrameConverter/pix-bw-10x12.bmp new file mode 100644 index 00000000..89db6ce4 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/pix-bw-10x12.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/pix-bw-10x8.bmp b/src/test/resources/LeptonicaFrameConverter/pix-bw-10x8.bmp new file mode 100644 index 00000000..b6a6aed7 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/pix-bw-10x8.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/pix-bw-10x9.bmp b/src/test/resources/LeptonicaFrameConverter/pix-bw-10x9.bmp new file mode 100644 index 00000000..666648e3 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/pix-bw-10x9.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x10.bmp b/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x10.bmp new file mode 100644 index 00000000..4cdf370f Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x10.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x11.bmp b/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x11.bmp new file mode 100644 index 00000000..dc24a3fc Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x11.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x12.bmp b/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x12.bmp new file mode 100644 index 00000000..357292f5 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x12.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x8.bmp b/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x8.bmp new file mode 100644 index 00000000..5ee5131b Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x8.bmp differ diff --git a/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x9.bmp b/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x9.bmp new file mode 100644 index 00000000..b1e5b363 Binary files /dev/null and b/src/test/resources/LeptonicaFrameConverter/pix-rgb-10x9.bmp differ