diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
new file mode 100644
index 0000000..f777984
--- /dev/null
+++ b/.github/workflows/ci.yaml
@@ -0,0 +1,23 @@
+name: CI
+
+on:
+ push:
+ branches:
+ - develop
+ pull_request:
+ branches:
+ - develop
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK
+ uses: actions/setup-java@v2
+ with:
+ java-version: '8'
+ distribution: 'adopt'
+ - name: Build
+ run: mvn --batch-mode --update-snapshots verify
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 9e0e981..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-language: java
-
-jdk:
- - oraclejdk8
-
-notifications:
- email: false
-
-# whitelist
-branches:
- only:
- - master
- - develop
diff --git a/README.md b/README.md
index d5fc6b9..c84dd3e 100755
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
# JNBIS
Java Implementation of NIST Biometric Image Software (NBIS)
-[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)
-* master [![Build Status](https://travis-ci.org/kareez/jnbis.svg?branch=master)](https://travis-ci.org/kareez/jnbis)
-* develop [![Build Status](https://travis-ci.org/kareez/jnbis.svg?branch=develop)](https://travis-ci.org/kareez/jnbis)
+![CI](https://github.com/mhshams/jnbis/actions/workflows/ci.yaml/badge.svg)
+[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.mhshams/jnbis/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.mhshams/jnbis)
+[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)
### About JNBIS
@@ -21,7 +21,7 @@ if you are using maven, add it to project dependencies.
```xml
- jnbis
+ com.github.mhshams
jnbis
2.x.x
@@ -80,7 +80,7 @@ Nist nist = Jnbis.nist().decode("/path/to/nist/file"));
Decode a NIST file with given **File** instance
```Java
-Nist nist = Jnbis.nist().decode(new File("/path/to/nist/file")));
+Nist nist = Jnbis.nist().decode(new File("/path/to/nist/file"));
```
Decode a NIST file with given **InputStream** instance
@@ -91,7 +91,7 @@ Nist nist = Jnbis.nist().decode(nistInputStream));
**Nist** instance contains different types of data, depending on file type.
Here is a sample code that extract all fingerprints and save them in individual files.
```Java
-Nist nist = Jnbis.nist().decode(new File("/path/to/nist/file")));
+Nist nist = Jnbis.nist().decode(new File("/path/to/nist/file"));
for (HighResolutionGrayscaleFingerprint fp : nist.getHiResGrayscaleFingerprints()) {
Jnbis.wsq()
diff --git a/pom.xml b/pom.xml
index e7d335d..7ec0fc3 100755
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
com.github.mhshams
jnbis
- 2.0.2
+ 2.0.3
jar
JNBIS
@@ -45,8 +45,8 @@
1.8
- 4.12
- 2.5.4
+ 4.13.2
+ 2.13.1
3.3
2.4
2.10.3
diff --git a/src/main/java/org/jnbis/api/model/Nist.java b/src/main/java/org/jnbis/api/model/Nist.java
index e0e801c..48d0a1f 100755
--- a/src/main/java/org/jnbis/api/model/Nist.java
+++ b/src/main/java/org/jnbis/api/model/Nist.java
@@ -37,5 +37,7 @@ public abstract class Nist {
public abstract List getVariableResPalmprints();
+ public abstract List getUserDefinedTestingImages();
+
public abstract List getIrisImages();
}
diff --git a/src/main/java/org/jnbis/api/model/record/UserDefinedTestingImage.java b/src/main/java/org/jnbis/api/model/record/UserDefinedTestingImage.java
new file mode 100644
index 0000000..ca48e4b
--- /dev/null
+++ b/src/main/java/org/jnbis/api/model/record/UserDefinedTestingImage.java
@@ -0,0 +1,81 @@
+package org.jnbis.api.model.record;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.jnbis.internal.record.BaseImageRecord;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author TeeSofteis
+ */
+public class UserDefinedTestingImage extends BaseImageRecord {
+
+ // 16.003 - 16.005 and 16.013 - 16.998
+ @JsonProperty("user_defined_fields")
+ private Map userDefinedFields;
+
+ public Map getUserDefinedFields() {
+ return userDefinedFields;
+ }
+
+ public void setUserDefinedFields(Map userDefinedFields) {
+ this.userDefinedFields = userDefinedFields;
+ }
+
+ public void addUserDefinedField(int key, String value) {
+ if (userDefinedFields == null) {
+ userDefinedFields = new HashMap<>();
+ }
+ userDefinedFields.put(key, value);
+ }
+
+ // 16.008 - SLC
+ @JsonProperty("scale_units")
+ private String scaleUnits;
+
+ // 16.009 - HPS
+ @JsonProperty("horizontal_pixel_scale")
+ private String horizontalPixelScale;
+
+ // 16.010 - VPS
+ @JsonProperty("vertical_pixel_scale")
+ private String verticalPixelScale;
+
+ // 16.012 - BPX
+ @JsonProperty("bits_per_pixel")
+ private String bitsPerPixel;
+
+ public String getScaleUnits() {
+ return scaleUnits;
+ }
+
+ public void setScaleUnits(String scaleUnits) {
+ this.scaleUnits = scaleUnits;
+ }
+
+ public String getHorizontalPixelScale() {
+ return horizontalPixelScale;
+ }
+
+ public void setHorizontalPixelScale(String horizontalPixelScale) {
+ this.horizontalPixelScale = horizontalPixelScale;
+ }
+
+ public String getVerticalPixelScale() {
+ return verticalPixelScale;
+ }
+
+ public void setVerticalPixelScale(String verticalPixelScale) {
+ this.verticalPixelScale = verticalPixelScale;
+ }
+
+ public String getBitsPerPixel() {
+ return bitsPerPixel;
+ }
+
+ public void setBitsPerPixel(String bitsPerPixel) {
+ this.bitsPerPixel = bitsPerPixel;
+ }
+
+}
diff --git a/src/main/java/org/jnbis/internal/InternalNist.java b/src/main/java/org/jnbis/internal/InternalNist.java
index 00f9bea..ead77bf 100755
--- a/src/main/java/org/jnbis/internal/InternalNist.java
+++ b/src/main/java/org/jnbis/internal/InternalNist.java
@@ -26,6 +26,7 @@ public class InternalNist extends Nist {
private final List variableResolutionLatentImages;
private final List variableResolutionFingerprints;
private final List variableResolutionPalmprints;
+ private final List userDefinedTestingImages;
private final List irisImages;
public InternalNist() {
@@ -41,6 +42,7 @@ public InternalNist() {
variableResolutionLatentImages = new ArrayList<>();
variableResolutionFingerprints = new ArrayList<>();
variableResolutionPalmprints = new ArrayList<>();
+ userDefinedTestingImages = new ArrayList<>();
irisImages = new ArrayList<>();
}
@@ -96,6 +98,9 @@ void addVariableResPalmprint(VariableResolutionPalmprint palmprint) {
variableResolutionPalmprints.add(palmprint);
}
+ void addUserDefinedTestingImage(UserDefinedTestingImage image) {
+ userDefinedTestingImages.add(image);
+ }
void addIrisImage(IrisImage image) {
irisImages.add(image);
}
@@ -152,6 +157,10 @@ public List getVariableResPalmprints() {
return variableResolutionPalmprints;
}
+ public List getUserDefinedTestingImages() {
+ return userDefinedTestingImages;
+ }
+
public List getIrisImages() {
return irisImages;
}
diff --git a/src/main/java/org/jnbis/internal/NistDecoder.java b/src/main/java/org/jnbis/internal/NistDecoder.java
index 4d033d5..f7ea02b 100755
--- a/src/main/java/org/jnbis/internal/NistDecoder.java
+++ b/src/main/java/org/jnbis/internal/NistDecoder.java
@@ -71,6 +71,9 @@ record = readerFactory.read(token);
} else if (record instanceof VariableResolutionPalmprint) {
decoded.addVariableResPalmprint((VariableResolutionPalmprint) record);
+ } else if (record instanceof UserDefinedTestingImage) {
+ decoded.addUserDefinedTestingImage((UserDefinedTestingImage) record);
+
} else if (record instanceof IrisImage) {
decoded.addIrisImage((IrisImage) record);
}
diff --git a/src/main/java/org/jnbis/internal/NistHelper.java b/src/main/java/org/jnbis/internal/NistHelper.java
index 7ba9fd6..67f948f 100755
--- a/src/main/java/org/jnbis/internal/NistHelper.java
+++ b/src/main/java/org/jnbis/internal/NistHelper.java
@@ -28,6 +28,7 @@ public class NistHelper {
public static final int RT_VR_LATENT_IMAGE = 13;
public static final int RT_VR_FINGERPRINT = 14;
public static final int RT_VR_PALMPRINT = 15;
+ public static final int RT_USER_DEFINED_TESTING_IMAGE = 16;
public static final int RT_IRIS_IMAGE = 17;
// Information separators
diff --git a/src/main/java/org/jnbis/internal/record/reader/RecordReaderFactory.java b/src/main/java/org/jnbis/internal/record/reader/RecordReaderFactory.java
index 3389473..134a8be 100644
--- a/src/main/java/org/jnbis/internal/record/reader/RecordReaderFactory.java
+++ b/src/main/java/org/jnbis/internal/record/reader/RecordReaderFactory.java
@@ -1,6 +1,7 @@
package org.jnbis.internal.record.reader;
+import org.jnbis.api.model.record.UserDefinedTestingImage;
import org.jnbis.internal.NistHelper;
import org.jnbis.internal.record.BaseRecord;
@@ -34,7 +35,7 @@ public BaseRecord read(NistHelper.Token token) {
READERS[NistHelper.RT_VR_LATENT_IMAGE] = new VariableResolutionLatentImageReader();
READERS[NistHelper.RT_VR_FINGERPRINT] = new VariableResolutionFingerprintReader();
READERS[NistHelper.RT_VR_PALMPRINT] = new VariableResolutionPalmprintReader();
- READERS[16] = NOT_SUPPORTED;
+ READERS[NistHelper.RT_USER_DEFINED_TESTING_IMAGE] = new UserDefinedTestingImageReader();
READERS[NistHelper.RT_IRIS_IMAGE] = new IrisImageReader();
}
diff --git a/src/main/java/org/jnbis/internal/record/reader/UserDefinedTestingImageReader.java b/src/main/java/org/jnbis/internal/record/reader/UserDefinedTestingImageReader.java
new file mode 100644
index 0000000..ae0022a
--- /dev/null
+++ b/src/main/java/org/jnbis/internal/record/reader/UserDefinedTestingImageReader.java
@@ -0,0 +1,85 @@
+package org.jnbis.internal.record.reader;
+
+import org.jnbis.internal.NistHelper;
+import org.jnbis.api.model.record.UserDefinedTestingImage;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * @author TeeSofteis
+ */
+public class UserDefinedTestingImageReader extends RecordReader {
+ @Override
+ public UserDefinedTestingImage read(NistHelper.Token token) {
+ if (token.pos >= token.buffer.length) {
+ throw new RuntimeException("T16::NULL pointer to T16 record");
+ }
+
+ UserDefinedTestingImage userDefinedTestingImage = new UserDefinedTestingImage();
+
+ int start = token.pos;
+
+ NistHelper.Tag tag = getTagInfo(token);
+ if (tag.field != 1) {
+ throw new RuntimeException("T16::Invalid Record type = " + tag.type);
+ }
+
+ Integer length = Integer.parseInt(nextWord(token, NistHelper.TAG_SEP_GSFS, NistHelper.FIELD_MAX_LENGTH - 1, false));
+ userDefinedTestingImage.setLogicalRecordLength(length.toString());
+
+ while (true) {
+ token.pos++;
+ tag = getTagInfo(token);
+
+ if (tag.field == 999) {
+ byte[] data = new byte[length - (token.pos - start)];
+ System.arraycopy(token.buffer, token.pos, data, 0, data.length);
+ token.pos = token.pos + data.length;
+ userDefinedTestingImage.setImageData(data);
+ break;
+ }
+
+ String word = nextWord(token, NistHelper.TAG_SEP_GSFS, NistHelper.FIELD_MAX_LENGTH - 1, false);
+ switch (tag.field) {
+ case 1:
+ userDefinedTestingImage.setLogicalRecordLength(word);
+ break;
+ case 2:
+ userDefinedTestingImage.setImageDesignationCharacter(word);
+ break;
+ case 6:
+ userDefinedTestingImage.setHorizontalLineLength(word);
+ break;
+ case 7:
+ userDefinedTestingImage.setVerticalLineLength(word);
+ break;
+ case 8:
+ userDefinedTestingImage.setScaleUnits(word);
+ break;
+ case 9:
+ userDefinedTestingImage.setHorizontalPixelScale(word);
+ break;
+ case 10:
+ userDefinedTestingImage.setVerticalPixelScale(word);
+ break;
+ case 11:
+ userDefinedTestingImage.setCompressionAlgorithm(word);
+ break;
+ case 12:
+ userDefinedTestingImage.setBitsPerPixel(word);
+ break;
+ default:
+ if ((2 < tag.field && tag.field < 6) || (12 < tag.field && tag.field < 999)) {
+ // User defined fields could be found at tag 3-5 and 13-998. As the name implies,
+ // it is not obvious which format the data has. From my point of view, the best
+ // solution is to handle the data as an array of text, therefore split data into
+ // sub fields and items as you need.
+ userDefinedTestingImage.addUserDefinedField(tag.field, word);
+ }
+ break;
+ }
+ }
+ return userDefinedTestingImage;
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/jnbis/Record16Test.java b/src/test/java/org/jnbis/Record16Test.java
new file mode 100644
index 0000000..3f3f8d1
--- /dev/null
+++ b/src/test/java/org/jnbis/Record16Test.java
@@ -0,0 +1,80 @@
+package org.jnbis;
+
+import org.jnbis.api.Jnbis;
+import org.jnbis.api.model.Nist;
+import org.jnbis.api.model.record.UserDefinedTestingImage;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author TeeSofteis
+ */
+public class Record16Test {
+ private static final String[] FILES = {
+ "samples/nist/rec01_rec02_rec16.nst"
+ };
+
+ @Test
+ public void type16() {
+ Nist decoded = decode(FILES[0]);
+ commonAssert(decoded);
+
+ // Record 01:
+ assertEquals("194", decoded.getTransactionInfo().getLogicalRecordLength()); // 1.001
+ assertEquals("ABC", decoded.getTransactionInfo().getTypeOfTransaction()); // 1.004
+ assertEquals("Wallace", decoded.getTransactionInfo().getDestinationAgencyId()); // 1.007
+ assertEquals("Gormit", decoded.getTransactionInfo().getOriginatingAgencyId()); // 1.008
+
+ // Record 16:
+ assertEquals("4733", decoded.getUserDefinedTestingImages().get(0).getLogicalRecordLength()); // 16.001
+ assertEquals("01", decoded.getUserDefinedTestingImages().get(0).getImageDesignationCharacter()); // 16.002
+
+ List rec16s = decoded.getUserDefinedTestingImages();
+ assertEquals(1, rec16s.size()); // only one record
+
+ UserDefinedTestingImage userDefinedTestingImage = rec16s.get(0);
+ assertEquals("4733", userDefinedTestingImage.getLogicalRecordLength());
+ assertEquals("1", userDefinedTestingImage.getScaleUnits());
+ assertEquals("1", userDefinedTestingImage.getHorizontalPixelScale());
+ assertEquals("1", userDefinedTestingImage.getVerticalPixelScale());
+ assertEquals("24", userDefinedTestingImage.getBitsPerPixel());
+
+ Map userDefinedFields = userDefinedTestingImage.getUserDefinedFields();
+ assertEquals(4, userDefinedFields.size());
+
+ // Tag 16.003
+ assertEquals("Wallace\u001FGromit\u001FMcGraw", userDefinedFields.get(3));
+
+ // Tag 16.004
+ assertEquals("Shaun\u001EPreston\u001EPiella Backleicht", userDefinedFields.get(4));
+
+ // Tag 16.005
+ assertEquals("single value", userDefinedFields.get(5));
+
+ // Tag 16.013
+ assertEquals("A1\u001FB1\u001FC1\u001EA2\u001FB2\u001FC2\u001EA3\u001FB3\u001FC3", userDefinedFields.get(13));
+ }
+
+ private void commonAssert(Nist decoded) {
+ assertNotNull(decoded.getTransactionInfo());
+ assertEquals(1, decoded.getUserDefinedTexts().size());
+
+ Map userDefinedFields = decoded.getUserDefinedTexts().get(0).getUserDefinedFields();
+ assertEquals("57", userDefinedFields.get(1));
+ assertEquals("00", userDefinedFields.get(2));
+ assertEquals("domain defined text place holder", userDefinedFields.get(3));
+ }
+
+ private Nist decode(String name) {
+ String fileName = FileUtils.absolute(name);
+ Nist nist = Jnbis.nist().decode(fileName);
+ assertNotNull(nist);
+ return nist;
+ }
+}
diff --git a/src/test/resources/samples/nist/rec01_rec02_rec16.nst b/src/test/resources/samples/nist/rec01_rec02_rec16.nst
new file mode 100644
index 0000000..032ab94
Binary files /dev/null and b/src/test/resources/samples/nist/rec01_rec02_rec16.nst differ