From c6caab6e2600f52f1b1fdb52acdca3e6cb8623a7 Mon Sep 17 00:00:00 2001 From: kameshsr Date: Thu, 4 Jun 2026 16:52:55 +0530 Subject: [PATCH 1/4] Merge upstream v0.10.0 changes into develop-#1830 Integrates all changes from mosip/imagedecoder v0.10.0 tag: - [DSD-9524] Platform 1.2.1.0 GA release - [MOSIP-43734] Updated beta versions to snapshot - [MOSIP-42464][MOSIP-41674] Central Sonatype migration changes - [MOSIP-38849] Fix: comment coming as empty or null - [DSD-6825] Platform 1.2.1.0-beta-1 release - [MOSIP-36412] Update pom.xml Signed-off-by: kameshsr --- imagedecoder/pom.xml | 8 ++++---- .../mosip/imagedecoder/util/ByteStreamUtil.java | 11 +++++++++++ .../io/mosip/imagedecoder/wsq/WsqFetHelper.java | 1 - .../mosip/imagedecoder/wsq/WsqTableIOHelper.java | 15 ++++++++------- sample/pom.xml | 12 ++++++------ sample/run_jp2000_decoder.bat | 2 +- sample/run_wsq_decoder.bat | 2 +- 7 files changed, 31 insertions(+), 20 deletions(-) diff --git a/imagedecoder/pom.xml b/imagedecoder/pom.xml index c6303b4..5f9324d 100644 --- a/imagedecoder/pom.xml +++ b/imagedecoder/pom.xml @@ -6,7 +6,7 @@ io.mosip.imagedecoder imagedecoder - 0.0.1-SNAPSHOT + 0.10.0 Imagedecoder http://github.com/mosip/imagedecoder @@ -40,9 +40,9 @@ 3.0.1 - 1.2.1-SNAPSHOT - 1.2.1-SNAPSHOT - 1.2.1-SNAPSHOT + 1.3.0 + 1.3.0 + 1.3.0 diff --git a/imagedecoder/src/main/java/io/mosip/imagedecoder/util/ByteStreamUtil.java b/imagedecoder/src/main/java/io/mosip/imagedecoder/util/ByteStreamUtil.java index 3df0ce3..45005c5 100644 --- a/imagedecoder/src/main/java/io/mosip/imagedecoder/util/ByteStreamUtil.java +++ b/imagedecoder/src/main/java/io/mosip/imagedecoder/util/ByteStreamUtil.java @@ -53,6 +53,12 @@ public int getBuffer(ByteBufferContext byteBufCont, byte[] target, int size) { public int getBufferU(ByteBufferContext byteBufCont, byte[] target, int size) { int pos = byteBufCont.getBuffer().position(); + // Validate that the requested size does not exceed remaining bytes + int remaining = byteBufCont.getBuffer().remaining(); + if (size > remaining) { + size = remaining; + } + System.arraycopy(byteBufCont.getBuffer().array(), pos, target, 0, size); byteBufCont.getBuffer().position(pos + size); return size; @@ -60,6 +66,11 @@ public int getBufferU(ByteBufferContext byteBufCont, byte[] target, int size) { public int getBufferU(ByteBufferContext byteBufCont, byte[] target, int dstPos, int size) { int pos = byteBufCont.getBuffer().position(); + // Validate that the requested size does not exceed remaining bytes + int remaining = byteBufCont.getBuffer().remaining(); + if (size > remaining) { + size = remaining; + } System.arraycopy(byteBufCont.getBuffer().array(), pos, target, dstPos, size); byteBufCont.getBuffer().position(pos + size); return size; diff --git a/imagedecoder/src/main/java/io/mosip/imagedecoder/wsq/WsqFetHelper.java b/imagedecoder/src/main/java/io/mosip/imagedecoder/wsq/WsqFetHelper.java index 3bd2861..794fe19 100644 --- a/imagedecoder/src/main/java/io/mosip/imagedecoder/wsq/WsqFetHelper.java +++ b/imagedecoder/src/main/java/io/mosip/imagedecoder/wsq/WsqFetHelper.java @@ -161,7 +161,6 @@ public int reallocFet(WsqFet fet, int newlen) { @SuppressWarnings({ "java:S135", "java:S2629", "java:S3626" }) public int extractFet(StringBuilder value, char[] feature, WsqFet fet) { int item; - for (item = 0; (item < fet.getNum()); item++) { if (fet.getNames()[item] != null && feature != null) { if (StringUtil.getInstance().stringCompare(fet.getNames()[item].trim(), diff --git a/imagedecoder/src/main/java/io/mosip/imagedecoder/wsq/WsqTableIOHelper.java b/imagedecoder/src/main/java/io/mosip/imagedecoder/wsq/WsqTableIOHelper.java index 8545c1c..a54fa02 100644 --- a/imagedecoder/src/main/java/io/mosip/imagedecoder/wsq/WsqTableIOHelper.java +++ b/imagedecoder/src/main/java/io/mosip/imagedecoder/wsq/WsqTableIOHelper.java @@ -6,12 +6,11 @@ import java.nio.charset.StandardCharsets; import java.text.MessageFormat; - -import io.mosip.kernel.core.logger.spi.Logger; -import io.mosip.imagedecoder.logger.ImageDecoderLogger; +import java.util.Arrays; import io.mosip.imagedecoder.constant.wsq.WsqConstant; import io.mosip.imagedecoder.constant.wsq.WsqErrorCode; +import io.mosip.imagedecoder.logger.ImageDecoderLogger; import io.mosip.imagedecoder.model.ByteBufferContext; import io.mosip.imagedecoder.model.wsq.WsqFet; import io.mosip.imagedecoder.model.wsq.WsqHeaderForm; @@ -21,6 +20,7 @@ import io.mosip.imagedecoder.util.ByteStreamUtil; import io.mosip.imagedecoder.util.StringUtil; import io.mosip.imagedecoder.util.wsq.WsqUtil; +import io.mosip.kernel.core.logger.spi.Logger; public class WsqTableIOHelper { private Logger logger = ImageDecoderLogger.getLogger(WsqTableIOHelper.class); @@ -397,9 +397,11 @@ private int getComment(byte[] comment, ByteBufferContext cbufptr /* current byte /* have one here by default due to the calloc of one extra byte at */ /* the end. */ } catch (Exception ex) { - ex.printStackTrace(); - comment = " ".toString().getBytes(); + logger.info(LOGGER_SESSIONID, LOGGER_IDTYPE, LOGGER_EMPTY, "getComment : comment empty " + ex.getLocalizedMessage()); + Arrays.fill(comment, (byte) '\0'); } + // Add a null terminator at the end + comment[comment.length-1] = '\0'; // Null terminator (ASCII 0) return ret; } @@ -441,7 +443,6 @@ public int getWsqHeaderForm(WsqHeaderForm headerForm, /* frame header structure headerForm.setWsqEncoder((int) ByteStreamUtil.getInstance().getUByte(cbufptr)); headerForm.setSoftware(ByteStreamUtil.getInstance().getUShort(cbufptr)); - return ret; } @@ -482,9 +483,9 @@ public int getWsqNistCom(WsqFet nistcom, byte[] imageData, int imagelength) { int cs = hdrSize - 2; /* Allocate including a possible NULL terminator. */ byte[] comment = new byte[cs + 1]; - if ((ret = getComment(comment, cbufptr)) != 0) return ret; + commentText.append(new String(comment, StandardCharsets.UTF_8)); if ((ret = WsqFetHelper.getInstance().string2fet(nistcom, commentText.toString().toCharArray())) != 0) { diff --git a/sample/pom.xml b/sample/pom.xml index 74c07c2..39a41d5 100644 --- a/sample/pom.xml +++ b/sample/pom.xml @@ -5,7 +5,7 @@ io.mosip.imagedecoder sample-imagedecoder jar - 0.0.1-SNAPSHOT + 0.10.0-beta.1 imagedecoder http://maven.apache.org Image decoder testing sample @@ -32,17 +32,17 @@ 3.1.2 3.0.2 - 1.6.7 + 1.6.14 3.2.5 3.0.1 - 1.2.1-SNAPSHOT - 1.2.1-SNAPSHOT - 1.2.1-SNAPSHOT - 0.0.1-SNAPSHOT + 1.3.0-beta.1 + 1.3.0-beta.1 + 1.3.0-beta.1 + 0.10.0-beta.1 diff --git a/sample/run_jp2000_decoder.bat b/sample/run_jp2000_decoder.bat index 86fcc30..8e435b5 100644 --- a/sample/run_jp2000_decoder.bat +++ b/sample/run_jp2000_decoder.bat @@ -1 +1 @@ -java -cp sample-imagedecoder-0.0.1-SNAPSHOT.jar;lib\* io.mosip.imagedecoder.sample.SampleImageDecoderApplication "io.mosip.imagedecoder.image.type=0" "io.mosip.imagedecoder.image.folder.path=/BiometricInfo" \ No newline at end of file +java -cp sample-imagedecoder-0.10.0-SNAPSHOT.jar;lib\* io.mosip.imagedecoder.sample.SampleImageDecoderApplication "io.mosip.imagedecoder.image.type=0" "io.mosip.imagedecoder.image.folder.path=/BiometricInfo" \ No newline at end of file diff --git a/sample/run_wsq_decoder.bat b/sample/run_wsq_decoder.bat index 0111dac..d6f77bd 100644 --- a/sample/run_wsq_decoder.bat +++ b/sample/run_wsq_decoder.bat @@ -1 +1 @@ -java -cp sample-imagedecoder-0.0.1-SNAPSHOT.jar;lib\* io.mosip.imagedecoder.sample.SampleImageDecoderApplication "io.mosip.imagedecoder.image.type=1" "io.mosip.imagedecoder.image.folder.path=/BiometricInfo" \ No newline at end of file +java -cp sample-imagedecoder-0.10.0-SNAPSHOT.jar;lib\* io.mosip.imagedecoder.sample.SampleImageDecoderApplication "io.mosip.imagedecoder.image.type=1" "io.mosip.imagedecoder.image.folder.path=/BiometricInfo" \ No newline at end of file From 27361de6342f4ad4c34a12a0fdd53c231f8d4bb4 Mon Sep 17 00:00:00 2001 From: kameshsr Date: Thu, 4 Jun 2026 16:56:45 +0530 Subject: [PATCH 2/4] #1830 corrected snapshot Signed-off-by: kameshsr --- imagedecoder/pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imagedecoder/pom.xml b/imagedecoder/pom.xml index 5f9324d..4ead849 100644 --- a/imagedecoder/pom.xml +++ b/imagedecoder/pom.xml @@ -6,7 +6,7 @@ io.mosip.imagedecoder imagedecoder - 0.10.0 + 0.10.0-SNAPSHOT Imagedecoder http://github.com/mosip/imagedecoder @@ -40,9 +40,9 @@ 3.0.1 - 1.3.0 - 1.3.0 - 1.3.0 + 1.4.0-SNAPSHOT + 1.4.0-SNAPSHOT + 1.4.0-SNAPSHOT From 11f066b5c287762736bf35859c8f671adde4d6f2 Mon Sep 17 00:00:00 2001 From: kameshsr Date: Thu, 4 Jun 2026 17:01:54 +0530 Subject: [PATCH 3/4] #1830 Added agents.md Signed-off-by: kameshsr --- AGENTS.md | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..c7f9d1a --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,95 @@ +# AGENTS.md + +This file provides guidance to AI agents when working with code in this repository. +## Build Commands + +All commands run from the `imagedecoder/` directory: + +```bash +# Build and run tests +mvn clean install + +# Skip tests +mvn clean install -DskipTests + +# Run tests only +mvn test + +# Run a single test class +mvn test -Dtest=OpenJpegDecoderTest +mvn test -Dtest=WsqDecoderTest + +# Sonar analysis (requires secrets) +mvn verify sonar:sonar -Psonar +``` + +Build requires Java 21 with `--enable-preview` enabled (configured in both pom.xml files). Tests use the `maven-surefire-plugin` with several `--add-opens` JVM flags. + +## Architecture + +This is a pure-Java biometric image decoding library for the MOSIP identity platform. It ports two native C codec libraries to Java: + +- **JPEG2000** — ported from [OpenJPEG](https://github.com/lessandro/nbis) (`openjp2`) +- **WSQ** — ported from [NBIS WSQ](https://github.com/lessandro/nbis) + +### Module Layout + +- **`imagedecoder/`** — the published library (`io.mosip.imagedecoder:imagedecoder`) +- **`sample/`** — standalone CLI demo app that reads image files from disk and decodes them + +### Core API + +The single entry point is `IImageDecoderApi`: + +```java +Response decode(DecoderRequestInfo requestInfo); +``` + +- `DecoderRequestInfo` — takes raw image bytes (`imageData`) and a `isBufferedImage` flag +- `DecoderResponseInfo` — returns image metadata (width, height, DPI, color space, bit rate, compression ratio, lossless flag) plus the decoded pixel data as base64url-encoded bytes and optionally a `BufferedImage` +- `Response` — wraps any response with `statusCode`, `statusMessage`, and `response` + +Two implementations: +- `OpenJpegDecoder` — handles JPEG2000 (`.jp2`) +- `WsqDecoder` — handles WSQ (`.wsq`) + +### Package Structure (`imagedecoder/src/main/java/io/mosip/imagedecoder/`) + +| Package | Purpose | +|---|---| +| `spi/` | Public API interface (`IImageDecoderApi`) | +| `model/` | Request/response models; also C-struct mirrors under `model/openjpeg/` and `model/wsq/` | +| `openjpeg/` | JPEG2000 codec implementation — `OpenJpegDecoder` + many `*Helper` classes | +| `wsq/` | WSQ codec implementation — `WsqDecoder` + many `*Helper` classes | +| `constant/` | Error codes and named constants for both codecs | +| `exceptions/` | `DecoderException` | +| `util/` | `Base64UrlUtil`, `ByteStreamUtil`, `ByteSwapperUtil`, and codec-specific math/image utils | +| `logger/` | Thin wrapper around `kernel-logger-logback` | + +### Key Design Details + +The codec implementations (`openjpeg/` and `wsq/`) are direct Java ports of C code. The `model/openjpeg/` and `model/wsq/` packages contain Java classes that mirror C structs from the original libraries. `ByteBufferContext` is used to simulate C-style sequential byte reads. + +The `*Helper` classes (e.g., `J2KHelper`, `WsqDecoderHelper`) are large stateless utility classes containing the ported algorithm logic. They are called by the `Decoder` classes. + +Logging follows the MOSIP convention: `logger.info(LOGGER_SESSIONID, LOGGER_IDTYPE, LOGGER_EMPTY, message)`. + +### Sample Application + +The `sample/` module runs from its `target/` directory after `mvn package`: + +```bash +# Decode JPEG2000 files from a folder +java -cp sample-imagedecoder-*.jar;lib\* io.mosip.imagedecoder.sample.SampleImageDecoderApplication \ + "io.mosip.imagedecoder.image.type=0" "io.mosip.imagedecoder.image.folder.path=/BiometricInfo" + +# Decode WSQ files from a folder +java -cp sample-imagedecoder-*.jar;lib\* io.mosip.imagedecoder.sample.SampleImageDecoderApplication \ + "io.mosip.imagedecoder.image.type=1" "io.mosip.imagedecoder.image.folder.path=/BiometricInfo" +``` + +Image type: `0` = JP2000, `1` = WSQ. + +### CI/CD + +GitHub Actions (`.github/workflows/push-trigger.yml`) triggers on pushes to `master`, `develop*`, `1.*`, `release*`. It reuses shared MOSIP workflows from `mosip/kattu@master-java21` for build, Nexus publish, and Sonar analysis. Publishing to Maven Central uses the `central-publishing-maven-plugin` with `autoPublish=false`. \ No newline at end of file From ac35faa512e74328c8f47b91e46ea739b8b78637 Mon Sep 17 00:00:00 2001 From: kameshsr Date: Thu, 4 Jun 2026 17:03:28 +0530 Subject: [PATCH 4/4] #1830 corrected snapshot Signed-off-by: kameshsr --- sample/pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sample/pom.xml b/sample/pom.xml index 39a41d5..7f0d10d 100644 --- a/sample/pom.xml +++ b/sample/pom.xml @@ -5,7 +5,7 @@ io.mosip.imagedecoder sample-imagedecoder jar - 0.10.0-beta.1 + 0.10.0-SNAPSHOT imagedecoder http://maven.apache.org Image decoder testing sample @@ -39,10 +39,10 @@ 3.0.1 - 1.3.0-beta.1 - 1.3.0-beta.1 - 1.3.0-beta.1 - 0.10.0-beta.1 + 1.4.0-SNAPSHOT + 1.4.0-SNAPSHOT + 1.4.0-SNAPSHOT + 0.10.0-SNAPSHOT