Skip to content

Commit 95d8a71

Browse files
dmitry.radchukvitali-pr
authored andcommitted
Add leptonica wrapper for different jdk support
DEVSIX-7068
1 parent f42dab5 commit 95d8a71

3 files changed

Lines changed: 151 additions & 30 deletions

File tree

pdfocr-tesseract4/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,9 @@
6666
<scope>test</scope>
6767
</dependency>
6868
</dependencies>
69+
70+
<properties>
71+
<sonar.exclusions>src/main/java/com/itextpdf/pdfocr/tesseract4/TesseractOcrUtil.java</sonar.exclusions>
72+
</properties>
73+
6974
</project>

pdfocr-tesseract4/src/main/java/com/itextpdf/pdfocr/tesseract4/ImagePreprocessingUtil.java

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ This file is part of the iText (R) project.
3939
import java.io.FileInputStream;
4040
import java.io.IOException;
4141
import javax.imageio.ImageIO;
42-
import net.sourceforge.lept4j.Leptonica;
4342
import net.sourceforge.lept4j.Pix;
4443
import org.slf4j.LoggerFactory;
4544

@@ -137,8 +136,7 @@ static BufferedImage readImageFromFile(final File inputFile)
137136
static BufferedImage readAsPixAndConvertToBufferedImage(
138137
final File inputImage)
139138
throws IOException {
140-
Pix pix = Leptonica.INSTANCE
141-
.pixRead(inputImage.getAbsolutePath());
139+
Pix pix = TesseractOcrUtil.readPixFromFile(inputImage);
142140
return TesseractOcrUtil.convertPixToImage(pix);
143141
}
144142

@@ -185,24 +183,24 @@ static BufferedImage readImage(File inputImage) {
185183
BufferedImage bufferedImage = null;
186184
try {
187185
bufferedImage = ImagePreprocessingUtil
188-
.readImageFromFile(inputImage);
186+
.readAsPixAndConvertToBufferedImage(
187+
inputImage);
189188
} catch (IllegalArgumentException | IOException ex) {
190-
LoggerFactory.getLogger(ImagePreprocessingUtil.class).info(
191-
MessageFormatUtil.format(
189+
LoggerFactory.getLogger(ImagePreprocessingUtil.class)
190+
.info(MessageFormatUtil.format(
192191
Tesseract4LogMessageConstant
193-
.CANNOT_CREATE_BUFFERED_IMAGE,
192+
.CANNOT_READ_INPUT_IMAGE,
194193
ex.getMessage()));
195194
}
196195
if (bufferedImage == null) {
197196
try {
198197
bufferedImage = ImagePreprocessingUtil
199-
.readAsPixAndConvertToBufferedImage(
200-
inputImage);
201-
} catch (IOException ex) {
202-
LoggerFactory.getLogger(ImagePreprocessingUtil.class)
203-
.info(MessageFormatUtil.format(
198+
.readImageFromFile(inputImage);
199+
} catch (IllegalArgumentException | IOException ex) {
200+
LoggerFactory.getLogger(ImagePreprocessingUtil.class).info(
201+
MessageFormatUtil.format(
204202
Tesseract4LogMessageConstant
205-
.CANNOT_READ_INPUT_IMAGE,
203+
.CANNOT_CREATE_BUFFERED_IMAGE,
206204
ex.getMessage()));
207205
}
208206
}

pdfocr-tesseract4/src/main/java/com/itextpdf/pdfocr/tesseract4/TesseractOcrUtil.java

Lines changed: 135 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ This file is part of the iText (R) project.
3131

3232
import com.ochafik.lang.jnaerator.runtime.NativeSize;
3333
import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference;
34+
import com.sun.jna.Pointer;
3435
import com.sun.jna.ptr.PointerByReference;
3536
import java.awt.image.BufferedImage;
3637
import java.io.ByteArrayInputStream;
@@ -50,6 +51,7 @@ This file is part of the iText (R) project.
5051
import javax.imageio.ImageIO;
5152
import net.sourceforge.lept4j.ILeptonica;
5253
import net.sourceforge.lept4j.Leptonica;
54+
import net.sourceforge.lept4j.Leptonica1;
5355
import net.sourceforge.lept4j.Pix;
5456
import net.sourceforge.tess4j.ITesseract;
5557
import net.sourceforge.tess4j.Tesseract;
@@ -150,15 +152,14 @@ static Pix preprocessPix(final Pix pix,
150152
* @return preprocessed {@link net.sourceforge.lept4j.Pix} object
151153
*/
152154
static Pix convertToGrayscale(final Pix pix) {
153-
Leptonica instance = Leptonica.INSTANCE;
154155
if (pix != null) {
155-
int depth = instance.pixGetDepth(pix);
156+
int depth = LeptonicaWrapper.pixGetDepth(pix);
156157

157158
if (depth == 32) {
158-
return instance.pixConvertRGBToLuminance(pix);
159+
return LeptonicaWrapper.pixConvertRGBToLuminance(pix);
159160
} else {
160-
return instance.pixRemoveColormap(pix,
161-
instance.REMOVE_CMAP_TO_GRAYSCALE);
161+
return LeptonicaWrapper.pixRemoveColormap(pix,
162+
ILeptonica.REMOVE_CMAP_TO_GRAYSCALE);
162163
}
163164
} else {
164165
return pix;
@@ -180,7 +181,7 @@ static Pix otsuImageThresholding(final Pix inputPix,
180181
Pix binarizedPix = null;
181182
if (inputPix.d == 8) {
182183
PointerByReference pointer = new PointerByReference();
183-
Leptonica.INSTANCE
184+
LeptonicaWrapper
184185
.pixOtsuAdaptiveThreshold(inputPix,
185186
getOtsuAdaptiveThresholdTileSize(inputPix.w,
186187
imagePreprocessingOptions.getTileWidth()),
@@ -253,7 +254,7 @@ static int getImagePixelColor(BufferedImage image, int x, int y) {
253254
*/
254255
static void destroyPix(Pix inputPix) {
255256
if (inputPix != null) {
256-
Leptonica.INSTANCE.lept_free(inputPix.getPointer());
257+
LeptonicaWrapper.lept_free(inputPix.getPointer());
257258
}
258259
}
259260

@@ -343,6 +344,10 @@ static void disposeTesseractInstance(
343344
final ITesseract tesseractInstance) {
344345
}
345346

347+
static Pix readPixFromFile(File inputImage) {
348+
return LeptonicaWrapper.pixRead(inputImage.getAbsolutePath());
349+
}
350+
346351
/**
347352
* Converts Leptonica {@link net.sourceforge.lept4j.Pix}
348353
* to {@link java.awt.image.BufferedImage} with
@@ -355,19 +360,18 @@ static void disposeTesseractInstance(
355360
static BufferedImage convertPixToImage(final Pix inputPix)
356361
throws IOException {
357362
if (inputPix != null) {
358-
Leptonica instance = Leptonica.INSTANCE;
359363
BufferedImage bi = null;
360364
PointerByReference pdata = new PointerByReference();
361365
try {
362366
NativeSizeByReference psize = new NativeSizeByReference();
363-
instance.pixWriteMem(pdata, psize, inputPix, ILeptonica.IFF_PNG);
367+
LeptonicaWrapper.pixWriteMem(pdata, psize, inputPix, ILeptonica.IFF_PNG);
364368
byte[] b = pdata.getValue().getByteArray(0,
365369
psize.getValue().intValue());
366370
try (InputStream in = new ByteArrayInputStream(b)) {
367371
bi = ImageIO.read(in);
368372
}
369373
} finally {
370-
instance.lept_free(pdata.getValue());
374+
LeptonicaWrapper.lept_free(pdata.getValue());
371375
}
372376
return bi;
373377
} else {
@@ -456,7 +460,7 @@ static void savePixToPngFile(final String filename,
456460
final Pix pix) {
457461
if (pix != null) {
458462
try {
459-
Leptonica.INSTANCE.pixWritePng(filename, pix,
463+
LeptonicaWrapper.pixWritePng(filename, pix,
460464
ILeptonica.IFF_PNG);
461465
} catch (Exception e) { // NOSONAR
462466
LOGGER.info(MessageFormatUtil.format(
@@ -659,7 +663,7 @@ static Pix readPix(final byte[] imageBytes) {
659663
try {
660664
ByteBuffer bb = ByteBuffer.wrap(imageBytes);
661665
NativeSize size = new NativeSize(imageBytes.length);
662-
pix = Leptonica.INSTANCE.pixReadMem(bb, size);
666+
pix = LeptonicaWrapper.pixReadMem(bb, size);
663667
} catch (Exception e) {
664668
LOGGER.error(MessageFormatUtil.format(
665669
Tesseract4LogMessageConstant.CANNOT_READ_INPUT_IMAGE,
@@ -767,14 +771,13 @@ static int readRotationFromMetadata(TiffImageMetadata tiffImageMetadata) {
767771
* @return rotated image, if rotation differs from 0
768772
*/
769773
static Pix rotate(final Pix pix, int rotation) {
770-
final Leptonica instance = Leptonica.INSTANCE;
771774
switch (rotation) {
772775
case ROTATION_90:
773-
return instance.pixRotate90(pix, 1);
776+
return LeptonicaWrapper.pixRotate90(pix, 1);
774777
case ROTATION_180:
775-
return instance.pixRotate180(pix, pix);
778+
return LeptonicaWrapper.pixRotate180(pix, pix);
776779
case ROTATION_270:
777-
return instance.pixRotate90(pix, -1);
780+
return LeptonicaWrapper.pixRotate90(pix, -1);
778781
default:
779782
return pix;
780783
}
@@ -795,7 +798,7 @@ static ImageData applyRotation(final ImageData imageData) {
795798
try {
796799
PointerByReference data = new PointerByReference();
797800
NativeSizeByReference size = new NativeSizeByReference();
798-
if (Leptonica.INSTANCE.pixWriteMemPng(data, size, pix, 0) == 0) {
801+
if (LeptonicaWrapper.pixWriteMemPng(data, size, pix, 0) == 0) {
799802
newImageData = ImageDataFactory.create(
800803
data.getValue().getByteArray(0, size.getValue().intValue())
801804
);
@@ -806,4 +809,119 @@ static ImageData applyRotation(final ImageData imageData) {
806809
return newImageData;
807810
}
808811
}
812+
813+
private static final class LeptonicaWrapper {
814+
private static final int LEPTONICA_NOT_SUPPORTED_JDK_VERSION = 19;
815+
private static final int JDK_MAJOR_VERSION = getJavaMajorVersion();
816+
817+
private LeptonicaWrapper() {}
818+
819+
public static int pixGetDepth(Pix pix) {
820+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
821+
return Leptonica.INSTANCE.pixGetDepth(pix);
822+
}
823+
return Leptonica1.pixGetDepth(pix);
824+
}
825+
826+
public static Pix pixConvertRGBToLuminance(Pix pix) {
827+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
828+
return Leptonica.INSTANCE.pixConvertRGBToLuminance(pix);
829+
}
830+
return Leptonica1.pixConvertRGBToLuminance(pix);
831+
}
832+
833+
public static Pix pixRemoveColormap(Pix pix, int option) {
834+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
835+
return Leptonica.INSTANCE.pixRemoveColormap(pix, option);
836+
}
837+
return Leptonica1.pixRemoveColormap(pix, option);
838+
}
839+
840+
public static Pix pixRead(String var1) {
841+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
842+
return Leptonica.INSTANCE.pixRead(var1);
843+
}
844+
return Leptonica1.pixRead(var1);
845+
}
846+
847+
public static void pixOtsuAdaptiveThreshold(Pix pix, int i, int i1, int i2, int i3, float v,
848+
PointerByReference pointerByReference, PointerByReference pointerByReference1) {
849+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
850+
Leptonica.INSTANCE.pixOtsuAdaptiveThreshold(pix, i, i1, i2, i3, v, pointerByReference,
851+
pointerByReference1);
852+
return;
853+
}
854+
Leptonica1.pixOtsuAdaptiveThreshold(pix, i, i1, i2, i3, v, pointerByReference, pointerByReference1);
855+
}
856+
857+
public static void lept_free(Pointer pointer) {
858+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
859+
Leptonica.INSTANCE.lept_free(pointer);
860+
return;
861+
}
862+
Leptonica1.lept_free(pointer);
863+
}
864+
865+
public static void pixWriteMem(PointerByReference pointer, NativeSizeByReference nativeSize, Pix pix, int i) {
866+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
867+
Leptonica.INSTANCE.pixWriteMem(pointer, nativeSize, pix, i);
868+
return;
869+
}
870+
Leptonica1.pixWriteMem(pointer, nativeSize, pix, i);
871+
}
872+
873+
public static int pixWriteMemPng(PointerByReference pointer, NativeSizeByReference nativeSize, Pix pix, int i) {
874+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
875+
return Leptonica.INSTANCE.pixWriteMemPng(pointer, nativeSize, pix, i);
876+
}
877+
return Leptonica1.pixWriteMemPng(pointer, nativeSize, pix, i);
878+
}
879+
880+
public static void pixWritePng(String s, Pix pix, float v) {
881+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
882+
Leptonica.INSTANCE.pixWritePng(s, pix, v);
883+
return;
884+
}
885+
Leptonica1.pixWritePng(s, pix, v);
886+
}
887+
888+
public static Pix pixReadMem(ByteBuffer buffer, NativeSize nativeSize) {
889+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
890+
return Leptonica.INSTANCE.pixReadMem(buffer, nativeSize);
891+
}
892+
return Leptonica1.pixReadMem(buffer, nativeSize);
893+
}
894+
895+
public static Pix pixRotate90(Pix pix, int i) {
896+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
897+
return Leptonica.INSTANCE.pixRotate90(pix, i);
898+
}
899+
return Leptonica1.pixRotate90(pix, i);
900+
}
901+
902+
public static Pix pixRotate180(Pix pix1, Pix pix2) {
903+
if (JDK_MAJOR_VERSION < LEPTONICA_NOT_SUPPORTED_JDK_VERSION) {
904+
return Leptonica.INSTANCE.pixRotate180(pix1, pix2);
905+
}
906+
return Leptonica1.pixRotate180(pix1, pix2);
907+
}
908+
909+
/**
910+
* gets java runtime version.
911+
*
912+
* @return major version of runtime java
913+
*/
914+
private static int getJavaMajorVersion() {
915+
String version = System.getProperty("java.version");
916+
if (version.startsWith("1.")) {
917+
version = version.substring(2, 3);
918+
} else {
919+
int dot = version.indexOf('.');
920+
if(dot != -1) {
921+
version = version.substring(0, dot);
922+
}
923+
}
924+
return Integer.parseInt(version);
925+
}
926+
}
809927
}

0 commit comments

Comments
 (0)