Repository: tanmoysrt/pyaadhaar (language: python)

Issue:
Updates regarding the Version-2 Aadhaar Cards of 2022
**The Issues which were being faced with the previous version**

1. When uploading a new 2022 Aadhaar Card, the library was through a string index out of bound error.

**Solution for that has been patched in this version**

- Essentially the QR code has an extra parameter of 'V2' at the start of the decompressed data string.  This resulted in a false allocation of data points in the key of "email_mobile_status", creating a problem in the whole parsing procedure. 

**FIX proposed**

- adding"version" and "email_mobile_status" in the details list.
- checking the presence of V2 at the start of the decompressed string. Suppose available V2 gets mapped to "version" from the details list. IF NOT, "version" is popped from the list.
- (-1) is appended at the start of the delimiter list. This helps us map all the details to their corresponding key-value pairs in a single for loop. (This was part of REFACTORING)


Discussion / hints:
The last 2 commits were for removing the testing lines, which are not needed essentially. The print statements are being removed.
Thanks @Arkajit-Datta for contribution. The request has been merged.

Fix patch:
diff --git a/.gitignore b/.gitignore
index 28e383e..1ff59cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,1 +1,2 @@
 /env/*
+.env/*
diff --git a/README.MD b/README.MD
index ccbe4eb..e111ff4 100644
--- a/README.MD
+++ b/README.MD
@@ -72,6 +72,18 @@ True  # True if Email Registered
 False # True if Mobile Number Registered
 ```
 
+#### **`=> Get if there exists any image in the QR CODE`**
+
+```
+image = obj.isImage()
+```
+**Output :**
+
+```
+True  # True if Image is there
+False # False if Image is not there
+```
+
 #### **`=> Get The Image Of User`**
 
 ```
diff --git a/build/lib/pyaadhaar/decode.py b/build/lib/pyaadhaar/decode.py
index 2347684..3554787 100644
--- a/build/lib/pyaadhaar/decode.py
+++ b/build/lib/pyaadhaar/decode.py
@@ -1,6 +1,7 @@
 import zlib
 from io import BytesIO
-from PIL import Image
+from PIL import Image, ImageFile
+ImageFile.LOAD_TRUNCATED_IMAGES = True
 import xml.etree.ElementTree as ET
 from io import BytesIO
 import base64
@@ -11,46 +12,51 @@
 class AadhaarSecureQr:
     # This is the class for Adhaar Secure Qr code..  In this version of code the data is in encrypted format
     # The special thing of this type of QR is that we can extract the photo of user from the data
+    # This class now supports 2022 version of Aadhaar QR codes [version-2]
     # For more information check here : https://103.57.226.101/images/resource/User_manulal_QR_Code_15032019.pdf
 
     def __init__(self, base10encodedstring):
         self.base10encodedstring = base10encodedstring
-        self.details = ["referenceid", "name", "dob", "gender", "careof", "district", "landmark",
-                        "house", "location", "pincode", "postoffice", "state", "street", "subdistrict", "vtc"]
-        self.delimeter = []
+        self.details = ["version","email_mobile_status","referenceid", "name", "dob", "gender", "careof", "district", "landmark",
+                        "house", "location", "pincode", "postoffice", "state", "street", "subdistrict", "vtc", "last_4_digits_mobile_no"]
+        self.delimeter = [-1]
         self.data = {}
-
-        bytes_array = base10encodedstring.to_bytes(5000, 'big').lstrip(b'\x00')
-
+        self._convert_base10encoded_to_decompressed_array()
+        self._check_aadhaar_version()
+        self._create_delimeter()
+        self._extract_info_from_decompressed_array()
+
+    def _convert_base10encoded_to_decompressed_array(self):
+        # This function converts base10encoded string to a decompressed array
+        bytes_array = self.base10encodedstring.to_bytes(5000, 'big').lstrip(b'\x00')
         self.decompressed_array = zlib.decompress(
             bytes_array, 16+zlib.MAX_WBITS)
 
+    def _check_aadhaar_version(self):
+        # This function will check for the new 2022 version-2 Aadhaar QRs
+        # If not found it will remove the "version" key from self.details, Defaulting to normal Secure QRs
+        if not self.decompressed_array[0:2].decode("ISO-8859-1") == 'V2':
+            self.details.pop(0) # Removing "Version"
+            self.details.pop() # Removing "Last_4_digits_of_mobile_no"
+    def _create_delimeter(self):
+        # This function creates the delimeter which is used to extract the information from the decompressed array
         for i in range(len(self.decompressed_array)):
             if self.decompressed_array[i] == 255:
                 self.delimeter.append(i)
 
-        self.data['email_mobile_status'] = self.decompressed_array[0:1].decode(
-            "ISO-8859-1")
-
-        for i in range(15):
-            self.data[self.details[i]] = self.decompressed_array[self.delimeter[i] +
-                                                                 1:self.delimeter[i+1]].decode("ISO-8859-1")
-
+    def _extract_info_from_decompressed_array(self):
+        for i in range(len(self.details)):
+            self.data[self.details[i]] = self.decompressed_array[self.delimeter[i] + 1:self.delimeter[i+1]].decode("ISO-8859-1")
         self.data['adhaar_last_4_digit'] = self.data['referenceid'][0:4]
         self.data['adhaar_last_digit'] = self.data['referenceid'][3]
-
-        if self.data['email_mobile_status'] == "0":
-            self.data['email'] = "no"
-            self.data['mobile'] = "no"
-        elif self.data['email_mobile_status'] == "1":
-            self.data['email'] = "yes"
-            self.data['mobile'] = "no"
-        elif self.data['email_mobile_status'] == "2":
-            self.data['email'] = "no"
-            self.data['mobile'] = "yes"
-        elif self.data['email_mobile_status'] == "3":
-            self.data['email'] = "yes"
-            self.data['mobile'] = "yes"
+        # Default values to 'email' and 'mobile
+        self.data['email'] = False
+        self.data['mobile'] = False
+        # Updating the fields of 'email' and 'mobile'
+        if int(self.data['email_mobile_status']) == 3 or int(self.data['email_mobile_status']) == 1:
+            self.data['email'] = True
+        if int(self.data['email_mobile_status']) == 3 or int(self.data['email_mobile_status']) == 2:
+            self.data['mobile'] = True
 
     def decodeddata(self):
         # Will return the personal data in a dictionary format
@@ -69,15 +75,11 @@ def signedData(self):
 
     def isMobileNoRegistered(self):
         # Will return True if mobile number is registered
-        if int(self.data['email_mobile_status']) == 3 or int(self.data['email_mobile_status']) == 1:
-            return True
-        return False
+        return self.data['mobile']
 
     def isEmailRegistered(self):
         # Will return True if email id is registered
-        if int(self.data['email_mobile_status']) == 3 or int(self.data['email_mobile_status']) == 2:
-            return True
-        return False
+        return self.data['email']
 
     def sha256hashOfEMail(self):
         # Will return the hash of the email id
@@ -85,7 +87,7 @@ def sha256hashOfEMail(self):
         if int(self.data['email_mobile_status']) == 3:
             tmp = self.decompressed_array[len(
                 self.decompressed_array)-256-32-32:len(self.decompressed_array)-256-32].hex()
-        elif int(self.data['email_mobile_status']) == 2:
+        elif int(self.data['email_mobile_status']) == 1:
             tmp = self.decompressed_array[len(
                 self.decompressed_array)-256-32:len(self.decompressed_array)-256].hex()
         return tmp
@@ -93,25 +95,41 @@ def sha256hashOfEMail(self):
     def sha256hashOfMobileNumber(self):
         # Will return the hash of mobile number
         tmp = ""
-        if int(self.data['email_mobile_status']) == 3 or int(self.data['email_mobile_status']) == 1:
+        if int(self.data['email_mobile_status']) == 3 or int(self.data['email_mobile_status']) == 2:
             tmp = self.decompressed_array[len(
                 self.decompressed_array)-256-32:len(self.decompressed_array)-256].hex()
         return tmp
 
+    def isImage(self, buffer = 10) -> bool:
+        # Will return bool for availability of image stream in the QR CODE
+        if int(self.data['email_mobile_status']) == 3:
+            if len(self.decompressed_array[self.delimeter[len(self.details)]+1:len(self.decompressed_array)]) < 256+32+32+buffer:
+                return False
+            else:
+                return True
+        elif int(self.data['email_mobile_status']) == 2 or int(self.data['email_mobile_status']) == 1:
+            if len(self.decompressed_array[self.delimeter[len(self.details)]+1:len(self.decompressed_array)]) < 256+32+buffer:
+                return False
+            else:
+                return True
+        elif int(self.data['email_mobile_status']) == 0:
+    
     def image(self):
         # Will return the image stream to be used in another function
         if int(self.data['email_mobile_status']) == 3:
-            return Image.open(BytesIO(self.decompressed_array[self.delimeter[15]+1:len(self.decompressed_array)-256-32-32]))
+            print("length --> ", len(self.decompressed_array[self.delimeter[len(self.details)]+1:len(self.decompressed_array)]))
+            return Image.open(BytesIO(self.decompressed_array[self.delimeter[len(self.details)]+1:len(self.decompressed_array)]))
         elif int(self.data['email_mobile_status']) == 2 or int(self.data['email_mobile_status']) == 1:
-            return Image.open(BytesIO(self.decompressed_array[self.delimeter[15]+1:len(self.decompressed_array)-256-32]))
+            return Image.open(BytesIO(self.decompressed_array[self.delimeter[len(self.details)]+1:len(self.decompressed_array)]))
         elif int(self.data['email_mobile_status']) == 0:
-            return Image.open(BytesIO(self.decompressed_array[self.delimeter[15]+1:len(self.decompressed_array)-256]))
+            return Image.open(BytesIO(self.decompressed_array[self.delimeter[len(self.details)]+1:len(self.decompressed_array)]))
         else:
             return None
 
     def saveimage(self, filename):
         # Will save the image of user
         image = self.image()
+        image.load()
         image.save(filename)
 
     def verifyEmail(self, emailid):
@@ -264,3 +282,4 @@ def verifyMobileNumber(self, mobileno):
             return True
         else:
             return False
+
diff --git a/pyaadhaar.egg-info/PKG-INFO b/pyaadhaar.egg-info/PKG-INFO
index b261e63..ffd2d73 100644
--- a/pyaadhaar.egg-info/PKG-INFO
+++ b/pyaadhaar.egg-info/PKG-INFO
@@ -6,6 +6,337 @@ Home-page: https://github.com/Tanmoy741127/pyaadhaar
 Author: Tanmoy Sarkar
 Author-email: ts741127@gmail.com
 License: MIT
+Description: ## PyAadhaar Library
+        
+        ---
+        
+        #### Designed to decode Aadhaar Old QR Code , Secure QR Code and also Offline XML
+        
+        ---
+        
+        ### **`|| Decode New Adhaar Secure QR Code ||`**
+        
+        ---
+        
+        #### **`=> Initialize Object & Print Decoded Data`**
+        
+        ```
+        from pyaadhaar.decode import AadhaarSecureQr
+        
+        obj  = AadhaarSecureQr(<:Data got from QR:>)
+        print(obj.decodeddata())
+        ```
+        
+        **Output :**
+        
+        ```
+        {'email_mobile_status': '2',
+        'referenceid': '345642020107890441252',
+        'name': 'X Das',
+        'dob': '01-01-2000',
+        'gender': 'F',
+        'careof': 'C/O: Y Das',
+        'district': 'Nadia',
+        'landmark': 'Primary School',
+        'house': 'N0456',
+        'location': 'Taherpur',
+        'pincode': '741159',
+        'postoffice': 'Taherpur',
+        'state': 'West Bengal',
+        'street': 'Taherpur Road',
+        'subdistrict': 'Ranaghat - I',
+        'vtc': 'Taherpur ',
+        'adhaar_last_4_digit': '3456',
+        'adhaar_last_digit': '6',
+        'email': 'no',
+        'mobile': 'yes'}
+        ```
+        
+        #### **`=> Verify Email Id Or Mobile`**
+        
+        ```
+        print(obj.verifyEmail("example@gmail.com"))
+        print(obj.verifyMobileNumber(9999999999))
+        ```
+        
+        **Output :**
+        
+        ```
+        True  # True if Email Verified
+        False # True if Mobile Number Verified
+        ```
+        
+        #### **`=> Check for Email Id Or Mobile Registration`**
+        
+        ```
+        print(obj.isEmailRegistered("example@gmail.com"))
+        print(obj.isMobileNoRegistered(9999999999))
+        ```
+        
+        **Output :**
+        
+        ```
+        True  # True if Email Registered
+        False # True if Mobile Number Registered
+        ```
+        
+        #### **`=> Get The Image Of User`**
+        
+        ```
+        image = obj.image()
+        ```
+        
+        #### **`=> Save The Image Of User`**
+        
+        ```
+        obj.saveimage("filename.jpg")
+        ```
+        
+        #### **`=> Get SHA256 Hash of Email`**
+        
+        ```
+        print(obj.sha256hashOfEMail())
+        ```
+        
+        **Output :**
+        
+        ```
+        d5598a28a82666c7ed9978h8936851189c494c84e62ab9782492fd038d9cb328
+        ```
+        
+        #### **`=> Get SHA256 Hash of Mobile Number`**
+        
+        ```
+        print(obj.sha256hashOfMobileNumber())
+        ```
+        
+        **Output :**
+        
+        ```
+        15a79565f9f1880e94dc62de51o9j7bd08542e7a6df82081ce1e72f0fb199e69
+        ```
+        
+        ---
+        
+        ---
+        
+        ### **`|| Decode Old Adhaar QR Code ||`**
+        
+        ---
+        
+        #### **`=> Initialize Object & Print Decoded Data`**
+        
+        ```
+        from pyaadhaar.decode import AadhaarOldQr
+        
+        obj  = AadhaarOldQr(<:Data got from QR:>)
+        print(obj.decodeddata())
+        ```
+        
+        **Output :**
+        
+        ```
+        {'uid': '6XXXXXXXX789',
+         'name': 'X Sarkar',
+         'gender': 'M',
+         'yob': '2001',
+         'gname': 'Y Sarkar',
+         'street': 'TAHERPUR ROAD',
+         'lm': 'TAHERPUR',
+         'loc': '-',
+         'vtc': 'Taherpur (P)',
+         'po': 'Taherpur',
+         'dist': 'Nadia',
+         'subdist': 'Ranaghat - I',
+         'state': 'West Bengal',
+         'pc': '741159',
+         'dob': '01/01/2001'}
+        ```
+        
+        ---
+        
+        ---
+        
+        ### **`|| Decode Adhaar Offline e-KYC XML ||`**
+        
+        ---
+        
+        #### **`=> Initialize Object & Print Decoded Data`**
+        
+        ```
+        from pyaadhaar.decode import AadhaarOfflineXML
+        
+        obj  = AadhaarOfflineXML(<:Offline e-KYC XML ZIP:>,<Passcode>)
+        print(obj.decodeddata())
+        ```
+        
+        **Output :**
+        
+        ```
+        {'email_mobile_status': '2',
+        'referenceid': '345642020107890441252',
+        'name': 'X Das',
+        'dob': '01-01-2000',
+        'gender': 'F',
+        'careof': 'C/O: Y Das',
+        'district': 'Nadia',
+        'landmark': 'Primary School',
+        'house': 'N0456',
+        'location': 'Taherpur',
+        'pincode': '741159',
+        'postoffice': 'Taherpur',
+        'state': 'West Bengal',
+        'street': 'Taherpur Road',
+        'subdistrict': 'Ranaghat - I',
+        'vtc': 'Taherpur ',
+        'adhaar_last_4_digit': '3456',
+        'adhaar_last_digit': '6',
+        'email': 'no',
+        'mobile': 'yes'}
+        ```
+        
+        #### **`=> Verify Email Id Or Mobile`**
+        
+        ```
+        print(obj.verifyEmail("example@gmail.com"))
+        print(obj.verifyMobileNumber(9999999999))
+        ```
+        
+        **Output :**
+        
+        ```
+        True  # True if Email Verified
+        False # True if Mobile Number Verified
+        ```
+        
+        #### **`=> Check for Email Id Or Mobile Registration`**
+        
+        ```
+        print(obj.isEmailRegistered("example@gmail.com"))
+        print(obj.isMobileNoRegistered(9999999999))
+        ```
+        
+        **Output :**
+        
+        ```
+        True  # True if Email Registered
+        False # True if Mobile Number Registered
+        ```
+        
+        #### **`=> Get The Image Of User`**
+        
+        ```
+        image = obj.image()
+        ```
+        
+        #### **`=> Save The Image Of User`**
+        
+        ```
+        obj.saveimage("filename.jpg")
+        ```
+        
+        #### **`=> Get SHA256 Hash of Email`**
+        
+        ```
+        print(obj.sha256hashOfEMail())
+        ```
+        
+        **Output :**
+        
+        ```
+        d5598a28a82666c7ed9978h8936851189c494c84e62ab9782492fd038d9cb328
+        ```
+        
+        #### **`=> Get SHA256 Hash of Mobile Number`**
+        
+        ```
+        print(obj.sha256hashOfMobileNumber())
+        ```
+        
+        **Output :**
+        
+        ```
+        15a79565f9f1880e94dc62de51o9j7bd08542e7a6df82081ce1e72f0fb199e69
+        ```
+        
+        ---
+        
+        ---
+        
+        ### **`|| Decode Image Of QR Code ||`**
+        
+        ---
+        
+        ```
+        from pyaadhaar.utils import Qr_img_to_text
+        
+        print(Qr_img_to_text(<Image File Location or Image file stream>))
+        ```
+        
+        **Output :**
+        
+        ```
+        ["google.com","amazon.in"] # Will return a list of data
+        ```
+        
+        ---
+        
+        ---
+        
+        ### **`|| Aadhaar Auto Initialize Class On QR code Type ||`**
+        
+        ---
+        
+        #### **`=> Initialize`**
+        
+        ```
+        
+        from pyaadhaar.utils import AadhaarQrAuto
+        
+        obj = AadhaarQrAuto(<Aadhaar QR code Data >)
+        ```
+        
+        - Then all the methods are same corresponding to
+          - AadhaarOldQr
+          - AadhaarSecureQr
+        
+        ---
+        
+        ---
+        
+        ### **`|| Aadhaar Check Old or Secure QR Code||`**
+        
+        ---
+        
+        #### **`=> Initialize`**
+        
+        ```
+        from pyaadhaar.utils import isSecureQr
+        
+        print(isSecureQr(<Aadhaar QR code Data >))
+        ```
+        
+        **Output :**
+        
+        ```
+        True # If it is a new secure QR code, else False
+        ```
+        
+        ---
+        
+        ---
+        
+        # Contributors
+        
+        #### Thanks to the developer of these libraries
+        
+        - [Opencv](https://pypi.org/project/opencv-python/)
+        - [Pillow](https://pypi.org/project/Pillow/)
+        - [Libjpeg](https://pypi.org/project/pylibjpeg-libjpeg/)
+        - [Numpy](https://pypi.org/project/numpy/)
+        
+        ---
+        
 Keywords: software development aadhaar e-kyc verification
 Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
@@ -15,336 +346,3 @@ Classifier: License :: OSI Approved :: MIT License
 Classifier: Programming Language :: Python :: 3.8
 Requires-Python: >=3.6
 Description-Content-Type: text/markdown
-
-## PyAadhaar Library
-
----
-
-#### Designed to decode Aadhaar Old QR Code , Secure QR Code and also Offline XML
-
----
-
-### **`|| Decode New Adhaar Secure QR Code ||`**
-
----
-
-#### **`=> Initialize Object & Print Decoded Data`**
-
-```
-from pyaadhaar.decode import AadhaarSecureQr
-
-obj  = AadhaarSecureQr(<:Data got from QR:>)
-print(obj.decodeddata())
-```
-
-**Output :**
-
-```
-{'email_mobile_status': '2',
-'referenceid': '345642020107890441252',
-'name': 'X Das',
-'dob': '01-01-2000',
-'gender': 'F',
-'careof': 'C/O: Y Das',
-'district': 'Nadia',
-'landmark': 'Primary School',
-'house': 'N0456',
-'location': 'Taherpur',
-'pincode': '741159',
-'postoffice': 'Taherpur',
-'state': 'West Bengal',
-'street': 'Taherpur Road',
-'subdistrict': 'Ranaghat - I',
-'vtc': 'Taherpur ',
-'adhaar_last_4_digit': '3456',
-'adhaar_last_digit': '6',
-'email': 'no',
-'mobile': 'yes'}
-```
-
-#### **`=> Verify Email Id Or Mobile`**
-
-```
-print(obj.verifyEmail("example@gmail.com"))
-print(obj.verifyMobileNumber(9999999999))
-```
-
-**Output :**
-
-```
-True  # True if Email Verified
-False # True if Mobile Number Verified
-```
-
-#### **`=> Check for Email Id Or Mobile Registration`**
-
-```
-print(obj.isEmailRegistered("example@gmail.com"))
-print(obj.isMobileNoRegistered(9999999999))
-```
-
-**Output :**
-
-```
-True  # True if Email Registered
-False # True if Mobile Number Registered
-```
-
-#### **`=> Get The Image Of User`**
-
-```
-image = obj.image()
-```
-
-#### **`=> Save The Image Of User`**
-
-```
-obj.saveimage("filename.jpg")
-```
-
-#### **`=> Get SHA256 Hash of Email`**
-
-```
-print(obj.sha256hashOfEMail())
-```
-
-**Output :**
-
-```
-d5598a28a82666c7ed9978h8936851189c494c84e62ab9782492fd038d9cb328
-```
-
-#### **`=> Get SHA256 Hash of Mobile Number`**
-
-```
-print(obj.sha256hashOfMobileNumber())
-```
-
-**Output :**
-
-```
-15a79565f9f1880e94dc62de51o9j7bd08542e7a6df82081ce1e72f0fb199e69
-```
-
----
-
----
-
-### **`|| Decode Old Adhaar QR Code ||`**
-
----
-
-#### **`=> Initialize Object & Print Decoded Data`**
-
-```
-from pyaadhaar.decode import AadhaarOldQr
-
-obj  = AadhaarOldQr(<:Data got from QR:>)
-print(obj.decodeddata())
-```
-
-**Output :**
-
-```
-{'uid': '6XXXXXXXX789',
- 'name': 'X Sarkar',
- 'gender': 'M',
- 'yob': '2001',
- 'gname': 'Y Sarkar',
- 'street': 'TAHERPUR ROAD',
- 'lm': 'TAHERPUR',
- 'loc': '-',
- 'vtc': 'Taherpur (P)',
- 'po': 'Taherpur',
- 'dist': 'Nadia',
- 'subdist': 'Ranaghat - I',
- 'state': 'West Bengal',
- 'pc': '741159',
- 'dob': '01/01/2001'}
-```
-
----
-
----
-
-### **`|| Decode Adhaar Offline e-KYC XML ||`**
-
----
-
-#### **`=> Initialize Object & Print Decoded Data`**
-
-```
-from pyaadhaar.decode import AadhaarOfflineXML
-
-obj  = AadhaarOfflineXML(<:Offline e-KYC XML ZIP:>,<Passcode>)
-print(obj.decodeddata())
-```
-
-**Output :**
-
-```
-{'email_mobile_status': '2',
-'referenceid': '345642020107890441252',
-'name': 'X Das',
-'dob': '01-01-2000',
-'gender': 'F',
-'careof': 'C/O: Y Das',
-'district': 'Nadia',
-'landmark': 'Primary School',
-'house': 'N0456',
-'location': 'Taherpur',
-'pincode': '741159',
-'postoffice': 'Taherpur',
-'state': 'West Bengal',
-'street': 'Taherpur Road',
-'subdistrict': 'Ranaghat - I',
-'vtc': 'Taherpur ',
-'adhaar_last_4_digit': '3456',
-'adhaar_last_digit': '6',
-'email': 'no',
-'mobile': 'yes'}
-```
-
-#### **`=> Verify Email Id Or Mobile`**
-
-```
-print(obj.verifyEmail("example@gmail.com"))
-print(obj.verifyMobileNumber(9999999999))
-```
-
-**Output :**
-
-```
-True  # True if Email Verified
-False # True if Mobile Number Verified
-```
-
-#### **`=> Check for Email Id Or Mobile Registration`**
-
-```
-print(obj.isEmailRegistered("example@gmail.com"))
-print(obj.isMobileNoRegistered(9999999999))
-```
-
-**Output :**
-
-```
-True  # True if Email Registered
-False # True if Mobile Number Registered
-```
-
-#### **`=> Get The Image Of User`**
-
-```
-image = obj.image()
-```
-
-#### **`=> Save The Image Of User`**
-
-```
-obj.saveimage("filename.jpg")
-```
-
-#### **`=> Get SHA256 Hash of Email`**
-
-```
-print(obj.sha256hashOfEMail())
-```
-
-**Output :**
-
-```
-d5598a28a82666c7ed9978h8936851189c494c84e62ab9782492fd038d9cb328
-```
-
-#### **`=> Get SHA256 Hash of Mobile Number`**
-
-```
-print(obj.sha256hashOfMobileNumber())
-```
-
-**Output :**
-
-```
-15a79565f9f1880e94dc62de51o9j7bd08542e7a6df82081ce1e72f0fb199e69
-```
-
----
-
----
-
-### **`|| Decode Image Of QR Code ||`**
-
----
-
-```
-from pyaadhaar.utils import Qr_img_to_text
-
-print(Qr_img_to_text(<Image File Location or Image file stream>))
-```
-
-**Output :**
-
-```
-["google.com","amazon.in"] # Will return a list of data
-```
-
----
-
----
-
-### **`|| Aadhaar Auto Initialize Class On QR code Type ||`**
-
----
-
-#### **`=> Initialize`**
-
-```
-
-from pyaadhaar.utils import AadhaarQrAuto
-
-obj = AadhaarQrAuto(<Aadhaar QR code Data >)
-```
-
-- Then all the methods are same corresponding to
-  - AadhaarOldQr
-  - AadhaarSecureQr
-
----
-
----
-
-### **`|| Aadhaar Check Old or Secure QR Code||`**
-
----
-
-#### **`=> Initialize`**
-
-```
-from pyaadhaar.utils import isSecureQr
-
-print(isSecureQr(<Aadhaar QR code Data >))
-```
-
-**Output :**
-
-```
-True # If it is a new secure QR code, else False
-```
-
----
-
----
-
-# Contributors
-
-#### Thanks to the developer of these libraries
-
-- [Opencv](https://pypi.org/project/opencv-python/)
-- [Pillow](https://pypi.org/project/Pillow/)
-- [Libjpeg](https://pypi.org/project/pylibjpeg-libjpeg/)
-- [Numpy](https://pypi.org/project/numpy/)
-
----
-
-
diff --git a/pyaadhaar.egg-info/SOURCES.txt b/pyaadhaar.egg-info/SOURCES.txt
index 7710f95..33aa720 100644
--- a/pyaadhaar.egg-info/SOURCES.txt
+++ b/pyaadhaar.egg-info/SOURCES.txt
@@ -1,6 +1,7 @@
 setup.py
 pyaadhaar/__init__.py
 pyaadhaar/decode.py
+pyaadhaar/tests.py
 pyaadhaar/utils.py
 pyaadhaar.egg-info/PKG-INFO
 pyaadhaar.egg-info/SOURCES.txt
diff --git a/pyaadhaar/__pycache__/decode.cpython-38.pyc b/pyaadhaar/__pycache__/decode.cpython-38.pyc
new file mode 100644
index 0000000..66124e3
Binary files /dev/null and b/pyaadhaar/__pycache__/decode.cpython-38.pyc differ
diff --git a/pyaadhaar/decode.py b/pyaadhaar/decode.py
index e4ac688..5366478 100644
--- a/pyaadhaar/decode.py
+++ b/pyaadhaar/decode.py
@@ -1,6 +1,7 @@
 import zlib
 from io import BytesIO
-from PIL import Image
+from PIL import Image, ImageFile
+ImageFile.LOAD_TRUNCATED_IMAGES = True
 import xml.etree.ElementTree as ET
 from io import BytesIO
 import base64
@@ -17,7 +18,7 @@ class AadhaarSecureQr:
     def __init__(self, base10encodedstring):
         self.base10encodedstring = base10encodedstring
         self.details = ["version","email_mobile_status","referenceid", "name", "dob", "gender", "careof", "district", "landmark",
-                        "house", "location", "pincode", "postoffice", "state", "street", "subdistrict", "vtc"]
+                        "house", "location", "pincode", "postoffice", "state", "street", "subdistrict", "vtc", "last_4_digits_mobile_no"]
         self.delimeter = [-1]
         self.data = {}
         self._convert_base10encoded_to_decompressed_array()
@@ -34,9 +35,9 @@ def _convert_base10encoded_to_decompressed_array(self):
     def _check_aadhaar_version(self):
         # This function will check for the new 2022 version-2 Aadhaar QRs
         # If not found it will remove the "version" key from self.details, Defaulting to normal Secure QRs
-        if not self.decompressed_array[0:2].decode("ISO-8859-1") == 'V2':
-            self.details.pop(0)
-
+        if self.decompressed_array[:2].decode("ISO-8859-1") != 'V2':
+            self.details.pop(0) # Removing "Version"
+            self.details.pop() # Removing "Last_4_digits_of_mobile_no"
     def _create_delimeter(self):
         # This function creates the delimeter which is used to extract the information from the decompressed array
         for i in range(len(self.decompressed_array)):
@@ -46,15 +47,15 @@ def _create_delimeter(self):
     def _extract_info_from_decompressed_array(self):
         for i in range(len(self.details)):
             self.data[self.details[i]] = self.decompressed_array[self.delimeter[i] + 1:self.delimeter[i+1]].decode("ISO-8859-1")
-        self.data['adhaar_last_4_digit'] = self.data['referenceid'][0:4]
+        self.data['adhaar_last_4_digit'] = self.data['referenceid'][:4]
         self.data['adhaar_last_digit'] = self.data['referenceid'][3]
         # Default values to 'email' and 'mobile
         self.data['email'] = False
         self.data['mobile'] = False
         # Updating the fields of 'email' and 'mobile'
-        if int(self.data['email_mobile_status']) == 3 or int(self.data['email_mobile_status']) == 1:
+        if int(self.data['email_mobile_status']) in {3, 1}:
             self.data['email'] = True
-        if int(self.data['email_mobile_status']) == 3 or int(self.data['email_mobile_status']) == 2:
+        if int(self.data['email_mobile_status']) in {3, 2}:
             self.data['mobile'] = True
 
     def decodeddata(self):
@@ -62,15 +63,10 @@ def decodeddata(self):
         return self.data
 
     def signature(self):
-        # Will return the signature value
-        signature = self.decompressed_array[len(
-            self.decompressed_array)-256:len(self.decompressed_array)]
-        return signature
+        return self.decompressed_array[len(self.decompressed_array) - 256 :]
 
     def signedData(self):
-        # Will return the signed data
-        signeddata = self.decompressed_array[:len(self.decompressed_array)-256]
-        return signeddata
+        return self.decompressed_array[:len(self.decompressed_array)-256]
 
     def isMobileNoRegistered(self):
         # Will return True if mobile number is registered
@@ -86,52 +82,99 @@ def sha256hashOfEMail(self):
         if int(self.data['email_mobile_status']) == 3:
             tmp = self.decompressed_array[len(
                 self.decompressed_array)-256-32-32:len(self.decompressed_array)-256-32].hex()
-        elif int(self.data['email_mobile_status']) == 2:
+        elif int(self.data['email_mobile_status']) == 1:
             tmp = self.decompressed_array[len(
                 self.decompressed_array)-256-32:len(self.decompressed_array)-256].hex()
         return tmp
 
     def sha256hashOfMobileNumber(self):
-        # Will return the hash of mobile number
-        tmp = ""
-        if int(self.data['email_mobile_status']) == 3 or int(self.data['email_mobile_status']) == 1:
-            tmp = self.decompressed_array[len(
-                self.decompressed_array)-256-32:len(self.decompressed_array)-256].hex()
-        return tmp
-
+        return (
+            self.decompressed_array[
+                len(self.decompressed_array)
+                - 256
+                - 32 : len(self.decompressed_array)
+                - 256
+            ].hex()
+            if int(self.data['email_mobile_status']) in {3, 2}
+            else ""
+        )
+
+    def isImage(self, buffer = 10) -> bool:
+        # Will return bool for availability of image stream in the QR CODE
+        if int(self.data['email_mobile_status']) == 3:
+            return (
+                len(
+                    self.decompressed_array[
+                        self.delimeter[len(self.details)] + 1 :
+                    ]
+                )
+                >= 256 + 32 + 32 + buffer
+            )
+        elif int(self.data['email_mobile_status']) in {2, 1}:
+            return (
+                len(
+                    self.decompressed_array[
+                        self.delimeter[len(self.details)] + 1 :
+                    ]
+                )
+                >= 256 + 32 + buffer
+            )
+        elif int(self.data['email_mobile_status']) == 0:
+            return (
+                len(
+                    self.decompressed_array[
+                        self.delimeter[len(self.details)] + 1 :
+                    ]
+                )
+                >= 256 + buffer
+            )
+            
     def image(self):
         # Will return the image stream to be used in another function
         if int(self.data['email_mobile_status']) == 3:
-            return Image.open(BytesIO(self.decompressed_array[self.delimeter[15]+1:len(self.decompressed_array)-256-32-32]))
-        elif int(self.data['email_mobile_status']) == 2 or int(self.data['email_mobile_status']) == 1:
-            return Image.open(BytesIO(self.decompressed_array[self.delimeter[15]+1:len(self.decompressed_array)-256-32]))
+            return Image.open(
+                BytesIO(
+                    self.decompressed_array[
+                        self.delimeter[len(self.details)] + 1 :
+                    ]
+                )
+            )
+        elif int(self.data['email_mobile_status']) in {2, 1}:
+            return Image.open(
+                BytesIO(
+                    self.decompressed_array[
+                        self.delimeter[len(self.details)] + 1 :
+                    ]
+                )
+            )
         elif int(self.data['email_mobile_status']) == 0:
-            return Image.open(BytesIO(self.decompressed_array[self.delimeter[15]+1:len(self.decompressed_array)-256]))
+            return Image.open(
+                BytesIO(
+                    self.decompressed_array[
+                        self.delimeter[len(self.details)] + 1 :
+                    ]
+                )
+            )
         else:
             return None
 
     def saveimage(self, filename):
         # Will save the image of user
         image = self.image()
+        image.load()
         image.save(filename)
 
     def verifyEmail(self, emailid):
         # Will return True if emailid match with the given email id
         generated_sha_mail = pyaadhaar.utils.SHAGenerator(
             emailid, self.data['adhaar_last_digit'])
-        if generated_sha_mail == self.sha256hashOfEMail():
-            return True
-        else:
-            return False
+        return generated_sha_mail == self.sha256hashOfEMail()
 
     def verifyMobileNumber(self, mobileno):
         # Will return True if mobileno match with the given mobile no
         generated_sha_mobile = pyaadhaar.utils.SHAGenerator(
             mobileno, self.data['adhaar_last_digit'])
-        if generated_sha_mobile == self.sha256hashOfMobileNumber():
-            return True
-        else:
-            return False
+        return generated_sha_mobile == self.sha256hashOfMobileNumber()
 
 
 class AadhaarOldQr:


Test patch:
diff --git a/build/lib/pyaadhaar/tests.py b/build/lib/pyaadhaar/tests.py
new file mode 100644
index 0000000..7e11968
--- /dev/null
+++ b/build/lib/pyaadhaar/tests.py
@@ -0,0 +1,24 @@
+from pdf2image import convert_from_path
+from pyzbar.pyzbar import decode
+from decode import AadhaarSecureQr
+
+filename = '/home/arkajit/Documents/Projects/pyaadhaar_updated/test_files/Test_Aadhar_Arkajit.pdf'
+working_file = '/home/arkajit/Downloads/new_aadhaar_pvc_4.pdf'
+pages = convert_from_path(filename)
+
+scale = 2
+extracted_info = []
+for page_idx,page in enumerate(pages):
+    page.save(f"{filename[:-4]}_page{page_idx+1}.png")
+    page = page.resize((page.width*scale, page.height*scale))
+    print(decode(page))
+    extracted_info.append(decode(page))
+
+temp = extracted_info[0]
+obj = AadhaarSecureQr(int(temp[0].data))
+extracted_fields = obj.decodeddata()
+print(extracted_fields)
+print(obj.signature())
+print("---------------------")
+print(obj.signedData())
+obj.saveimage("/home/arkajit/Documents/Projects/pyaadhaar_updated/test_files/test.png")