diff --git a/mosip-identity-certify-plugin/pom.xml b/mosip-identity-certify-plugin/pom.xml
index 5ba256e..127d70b 100644
--- a/mosip-identity-certify-plugin/pom.xml
+++ b/mosip-identity-certify-plugin/pom.xml
@@ -170,6 +170,38 @@
jackson-annotations
2.15.4
+
+ io.mosip.image.compressor
+ image-compressor
+ 0.1.0
+
+
+ org.hibernate.validator
+ hibernate-validator-annotation-processor
+
+
+ org.bytedeco
+ opencv-platform
+
+
+
+
+ io.mosip.kernel
+ kernel-biometrics-api
+ 1.3.0
+ provided
+
+
+ org.json
+ json
+ 20241224
+
+
+ org.bytedeco
+ opencv-platform
+ 4.9.0-1.5.10
+ compile
+
diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/ImageCompressorUtil.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/ImageCompressorUtil.java
new file mode 100644
index 0000000..2dcd14d
--- /dev/null
+++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/ImageCompressorUtil.java
@@ -0,0 +1,119 @@
+package io.mosip.certify.mosipid.integration.helper;
+
+import io.mosip.biometrics.util.CommonUtil;
+import io.mosip.certify.api.exception.DataProviderExchangeException;
+import io.mosip.certify.mosipid.integration.service.ImageCompressorServiceImpl;
+import io.mosip.kernel.biometrics.entities.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.Base64;
+
+@Component
+@Slf4j
+public class ImageCompressorUtil {
+ private final ImageCompressorServiceImpl service;
+
+ @Autowired
+ public ImageCompressorUtil(ImageCompressorServiceImpl service) {
+ this.service = service;
+ }
+
+ @Value("${mosip.certify.image-compressor.image.max-allowed-size:4096}")
+ private int maxAllowedImageSize;
+
+ @Value("${mosip.certify.image-compressor.image.max-retry-attempts:3}")
+ private int maxRetryAttempts;
+
+
+ public byte[] compressImage(byte[] imageBytes) {
+ return service.doResizeAndCompress(imageBytes);
+ }
+
+ public String extractAndCompressImage(String imageData) throws DataProviderExchangeException {
+ try {
+ // --- Require Data URI with prefix only ---
+ if (imageData == null || imageData.isBlank() || !imageData.startsWith("data:") || !imageData.contains(";")
+ || !imageData.contains(",")) {
+ throw new IllegalArgumentException("Invalid image format. Upload a proper image type.");
+ }
+
+ // Basic structure guards
+ int colon = imageData.indexOf(':'); // should be 4 ("data:")
+ int semi = imageData.indexOf(';');
+ int comma = imageData.indexOf(',');
+ if (colon < 0 || semi < 0 || comma < 0 || colon >= semi || semi >= comma) {
+ throw new IllegalArgumentException("Invalid image format. Upload a proper image type.");
+ }
+
+ // Extract MIME (e.g., image/png, image/jpeg)
+ String mimeType = imageData.substring(colon + 1, semi).trim();
+
+ // Extract the format (e.g., "png", "jpeg", "jpg"); default "" if malformed
+ int slash = mimeType.indexOf('/');
+ String formatName = (slash >= 0 && slash < mimeType.length() - 1)
+ ? mimeType.substring(slash + 1).toLowerCase()
+ : "";
+
+ // Fallback rule: anything other than png/jpeg/jpg → force JPEG
+ boolean isPng = "png".equals(formatName);
+ boolean usePng = isPng; // only true when explicitly PNG
+
+ // Extract Base64 payload and decode
+ String base64Data = imageData.substring(comma + 1).trim();
+ byte[] inputBytes = Base64.getDecoder().decode(base64Data);
+
+ // Compress (assumed JP2 output)
+ int attempts = 0;
+ byte[] jp2Bytes;
+
+ while (true) {
+ jp2Bytes = compressImage(inputBytes);
+ attempts++;
+
+ if (jp2Bytes.length <= maxAllowedImageSize) {
+ break;
+ }
+ if (attempts >= maxRetryAttempts) {
+ throw new DataProviderExchangeException(
+ "FACE_IMAGE_TOO_LARGE",
+ "Unable to compress image with available compression. Check size or quality of the input image."
+ );
+ }
+
+ // use the last compressed output as the next input
+ inputBytes = jp2Bytes;
+ }
+
+ // Convert JP2 → desired output format
+ final byte[] outBytes;
+ final String outMime;
+ if (usePng) {
+ outBytes = CommonUtil.convertJP2ToPNGBytes(jp2Bytes);
+ outMime = "image/png";
+ } else {
+ outBytes = CommonUtil.convertJP2ToJPEGBytes(jp2Bytes);
+ outMime = "image/jpeg";
+ }
+
+ // Encode and return as Data URI
+ final String b64 = Base64.getEncoder().encodeToString(outBytes);
+ return "data:" + outMime + ";base64," + b64;
+
+ } catch (IllegalArgumentException iae) {
+ log.error("ERROR_PARSING_IMAGE_DATA", iae);
+ throw new DataProviderExchangeException("ERROR_PARSING_IMAGE_DATA", iae.getMessage());
+ } catch (DataProviderExchangeException e) {
+ log.error("MAX_ATTEMPTS_REACHED", e);
+ throw e;
+ } catch (Exception e) {
+ log.error("Image compression failed", e);
+ throw new DataProviderExchangeException(
+ "ERROR_COMPRESSING_IMAGE",
+ "Failed to compress image data. Check the image format and other properties."
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/IdaDataProviderPluginImpl.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/IdaDataProviderPluginImpl.java
index fbac2e2..ab47ba9 100644
--- a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/IdaDataProviderPluginImpl.java
+++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/IdaDataProviderPluginImpl.java
@@ -5,6 +5,7 @@
import io.mosip.certify.api.exception.DataProviderExchangeException;
import io.mosip.certify.api.spi.DataProviderPlugin;
import io.mosip.certify.mosipid.integration.dto.*;
+import io.mosip.certify.mosipid.integration.helper.ImageCompressorUtil;
import io.mosip.certify.mosipid.integration.helper.TransactionHelper;
import io.mosip.esignet.api.dto.*;
import io.mosip.esignet.api.exception.KycExchangeException;
@@ -14,6 +15,8 @@
import io.mosip.kernel.keymanagerservice.entity.KeyAlias;
import io.mosip.kernel.keymanagerservice.helper.KeymanagerDBHelper;
import lombok.extern.slf4j.Slf4j;
+import org.bytedeco.javacpp.Loader;
+import org.bytedeco.opencv.opencv_java;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
@@ -41,6 +44,21 @@ public class IdaDataProviderPluginImpl implements DataProviderPlugin {
// TODO: Clean up code
// TODO: Write unit tests
+ static {
+ /**
+ * load OpenCV library nu.pattern.OpenCV.loadShared();
+ * System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME);
+ */
+ /**
+ * In Java >= 12 it is no longer possible to use addLibraryPath, which modifies
+ * the ClassLoader's static usr_paths field. There does not seem to be any way
+ * around this so we fall back to loadLocally() and return.
+ */
+ nu.pattern.OpenCV.loadLocally();
+ Loader.load(opencv_java.class);
+ System.setProperty("OPENCV_IO_ENABLE_JASPER", "1");
+ }
+
private static final String ACCESS_TOKEN_HASH = "accessTokenHash";
public static final String SIGNATURE_HEADER_NAME = "signature";
public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
@@ -93,6 +111,9 @@ public class IdaDataProviderPluginImpl implements DataProviderPlugin {
@Autowired
TransactionHelper transactionHelper;
+ @Autowired
+ private ImageCompressorUtil imageCompressorUtil;
+
private Base64.Decoder urlSafeDecoder = Base64.getUrlDecoder();
@Override
@@ -106,7 +127,14 @@ public JSONObject fetchData(Map identityDetails) throws DataProv
Map claims = decodeClaimsFromJwt(encryptedKyc);
log.debug("JWT Claims: {}", claims);
- return new JSONObject(claims);
+ JSONObject jsonRes = new JSONObject(claims);
+
+ if(jsonRes.has("picture")) {
+ String imageData = jsonRes.getString("picture");
+ String compressedImageData = imageCompressorUtil.extractAndCompressImage(imageData);
+ jsonRes.put("compressedPicture", compressedImageData);
+ }
+ return jsonRes;
}
}
catch (JSONException | JsonProcessingException e) {
diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/ImageCompressorServiceImpl.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/ImageCompressorServiceImpl.java
new file mode 100644
index 0000000..711df1a
--- /dev/null
+++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/ImageCompressorServiceImpl.java
@@ -0,0 +1,23 @@
+package io.mosip.certify.mosipid.integration.service;
+
+import io.mosip.image.compressor.sdk.service.ImageCompressionService;
+import io.mosip.kernel.biometrics.constant.BiometricType;
+import io.mosip.kernel.biometrics.entities.BiometricRecord;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.List;
+
+@Component
+public class ImageCompressorServiceImpl extends ImageCompressionService {
+ @Autowired
+ public ImageCompressorServiceImpl(Environment env) {
+ super(env, new BiometricRecord(), List.of(BiometricType.FACE), new HashMap<>());
+ }
+
+ public byte[] doResizeAndCompress(byte[] imageBytes) {
+ return resizeAndCompress(imageBytes);
+ }
+}
\ No newline at end of file