diff --git a/src/main/java/stirling/software/SPDF/controller/api/other/AutoRenameController.java b/src/main/java/stirling/software/SPDF/controller/api/other/AutoRenameController.java
index bfc7674ec..66fd70a69 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/other/AutoRenameController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/other/AutoRenameController.java
@@ -77,7 +77,7 @@ public class AutoRenameController {
     private static final Logger logger = LoggerFactory.getLogger(AutoRenameController.class);
 
     private static final float TITLE_FONT_SIZE_THRESHOLD = 20.0f;
-    private static final int LINE_LIMIT = 7;
+    private static final int LINE_LIMIT = 11;
 
     @PostMapping(consumes = "multipart/form-data", value = "/auto-rename")
     @Operation(summary = "Extract header from PDF file", description = "This endpoint accepts a PDF file and attempts to extract its title or header based on heuristics. Input:PDF Output:PDF Type:SISO")
@@ -136,12 +136,25 @@ public class AutoRenameController {
     	                super.getText(doc);
     	                processLine(); // Process the last line
 
-    	                // Sort lines by font size in descending order and get the first one
-    	                lineInfos.sort(Comparator.comparing((LineInfo li) -> li.fontSize).reversed());
-    	                String title = lineInfos.isEmpty() ? null : lineInfos.get(0).text;
+    	                // Merge lines with same font size
+    	                List<LineInfo> mergedLineInfos = new ArrayList<>();
+    	                for (int i = 0; i < lineInfos.size(); i++) {
+    	                    String mergedText = lineInfos.get(i).text;
+    	                    float fontSize = lineInfos.get(i).fontSize;
+    	                    while (i + 1 < lineInfos.size() && lineInfos.get(i + 1).fontSize == fontSize) {
+    	                        mergedText += " " + lineInfos.get(i + 1).text;
+    	                        i++;
+    	                    }
+    	                    mergedLineInfos.add(new LineInfo(mergedText, fontSize));
+    	                }
 
-    	                return title != null ? title : (useFirstTextAsFallback ? (lineInfos.isEmpty() ? null : lineInfos.get(lineInfos.size() - 1).text) : null);
+    	                // Sort lines by font size in descending order and get the first one
+    	                mergedLineInfos.sort(Comparator.comparing((LineInfo li) -> li.fontSize).reversed());
+    	                String title = mergedLineInfos.isEmpty() ? null : mergedLineInfos.get(0).text;
+
+    	                return title != null ? title : (useFirstTextAsFallback ? (mergedLineInfos.isEmpty() ? null : mergedLineInfos.get(mergedLineInfos.size() - 1).text) : null);
     	            }
+
     	        };
 
     	        String header = reader.getText(document);
diff --git a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java
index e3c7a41be..8fa57d08f 100644
--- a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java
+++ b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java
@@ -147,4 +147,6 @@ public class OtherWebController {
         return "other/auto-rename";
     }
     
+
+    
 }
diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties
index f28286ba3..15ff69d34 100644
--- a/src/main/resources/messages_en_GB.properties
+++ b/src/main/resources/messages_en_GB.properties
@@ -35,9 +35,11 @@ navbar.pageOps=Page Operations
 
 home.multiTool.title=PDF Multi Tool
 home.multiTool.desc=Merge, Rotate, Rearrange, and Remove pages
+multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side
 
 home.merge.title=Merge
 home.merge.desc=Easily merge multiple PDFs into one.
+merge.tags=merge,Page operations,Back end,server side
 
 home.split.title=Split
 home.split.desc=Split PDFs into multiple documents
diff --git a/src/main/resources/static/css/home.css b/src/main/resources/static/css/home.css
index 94414be95..998278e16 100644
--- a/src/main/resources/static/css/home.css
+++ b/src/main/resources/static/css/home.css
@@ -1,3 +1,17 @@
+#searchBar { 
+	background-image: url('/images/search.svg'); 
+	background-position: 16px 16px; 
+	background-repeat: no-repeat; 
+	width: 100%; 
+	font-size: 16px; 
+	margin-bottom: 12px;
+	padding: 12px 20px 12px 40px; 
+	border: 1px solid #ddd;
+	
+	
+}
+
+
 .features-container {
     display: grid;
     grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
diff --git a/src/main/resources/static/css/navbar.css b/src/main/resources/static/css/navbar.css
index 60b612c52..5bb99a5ea 100644
--- a/src/main/resources/static/css/navbar.css
+++ b/src/main/resources/static/css/navbar.css
@@ -1,3 +1,41 @@
+
+
+#navbarSearch {
+    top: 100%;
+    right: 0;
+}
+
+#searchForm {
+    width: 200px;  /* Adjust this value as needed */
+}
+
+/* Style the search results to match the navbar */
+#searchResults {
+    max-height: 200px;  /* Adjust this value as needed */
+    overflow-y: auto;
+    width: 100%;
+}
+
+#searchResults .dropdown-item {
+    display: flex;
+    align-items: center;
+    white-space: nowrap;
+    height: 50px;  /* Fixed height */
+    overflow: hidden;  /* Hide overflow */
+}
+
+#searchResults .icon {
+    margin-right: 10px;
+}
+
+#searchResults .icon-text {
+    display: inline;
+    overflow: hidden;  /* Hide overflow */
+    text-overflow: ellipsis;  /* Add ellipsis for long text */
+}
+
+
+
 .main-icon {
 	width: 36px;
 	height: 36px;
diff --git a/src/main/resources/static/images/adjust-contrast.svg b/src/main/resources/static/images/adjust-contrast.svg
new file mode 100644
index 000000000..fea76d92d
--- /dev/null
+++ b/src/main/resources/static/images/adjust-contrast.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-palette" viewBox="0 0 16 16">
+  <path d="M8 5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm4 3a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM5.5 7a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm.5 6a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"/>
+  <path d="M16 8c0 3.15-1.866 2.585-3.567 2.07C11.42 9.763 10.465 9.473 10 10c-.603.683-.475 1.819-.351 2.92C9.826 14.495 9.996 16 8 16a8 8 0 1 1 8-8zm-8 7c.611 0 .654-.171.655-.176.078-.146.124-.464.07-1.119-.014-.168-.037-.37-.061-.591-.052-.464-.112-1.005-.118-1.462-.01-.707.083-1.61.704-2.314.369-.417.845-.578 1.272-.618.404-.038.812.026 1.16.104.343.077.702.186 1.025.284l.028.008c.346.105.658.199.953.266.653.148.904.083.991.024C14.717 9.38 15 9.161 15 8a7 7 0 1 0-7 7z"/>
+</svg>
\ No newline at end of file
diff --git a/src/main/resources/static/js/homecard.js b/src/main/resources/static/js/homecard.js
index f3d3de35e..fb962a12e 100644
--- a/src/main/resources/static/js/homecard.js
+++ b/src/main/resources/static/js/homecard.js
@@ -1,3 +1,24 @@
+function filterCards() {
+    var input = document.getElementById('searchBar');
+    var filter = input.value.toUpperCase();
+    var cards = document.querySelectorAll('.feature-card');
+
+    for (var i = 0; i < cards.length; i++) {
+        var card = cards[i];
+        var title = card.querySelector('h5.card-title').innerText;
+        var text = card.querySelector('p.card-text').innerText;
+        var tags = card.getAttribute('data-tags');
+        var content = title + ' ' + text + ' ' + tags;
+
+        if (content.toUpperCase().indexOf(filter) > -1) {
+            card.style.display = "";
+        } else {
+            card.style.display = "none";
+        }
+    }
+}
+
+
 function toggleFavorite(element) {
 	var img = element.querySelector('img');
 	var card = element.closest('.feature-card');
@@ -13,6 +34,7 @@ function toggleFavorite(element) {
 	}
 	reorderCards();
 	updateFavoritesDropdown();
+	filterCards();
 }
 
 function reorderCards() {
@@ -45,5 +67,7 @@ function initializeCards() {
 	});
 	reorderCards();
 	updateFavoritesDropdown();
+	filterCards();
 }
+
 window.onload = initializeCards;
\ No newline at end of file
diff --git a/src/main/resources/static/js/search.js b/src/main/resources/static/js/search.js
new file mode 100644
index 000000000..3c19ed84e
--- /dev/null
+++ b/src/main/resources/static/js/search.js
@@ -0,0 +1,72 @@
+// Toggle search bar when the search icon is clicked
+document.querySelector('#search-icon').addEventListener('click', function(e) {
+	e.preventDefault();
+	var searchBar = document.querySelector('#navbarSearch');
+	searchBar.classList.toggle('show');
+});
+window.onload = function() {
+    var items = document.querySelectorAll('.dropdown-item, .nav-link');
+    var dummyContainer = document.createElement('div');
+    dummyContainer.style.position = 'absolute';
+    dummyContainer.style.visibility = 'hidden';
+    dummyContainer.style.whiteSpace = 'nowrap';  // Ensure we measure full width
+    document.body.appendChild(dummyContainer);
+
+    var maxWidth = 0;
+
+    items.forEach(function(item) {
+        var clone = item.cloneNode(true);
+        dummyContainer.appendChild(clone);
+        var width = clone.offsetWidth;
+        if (width > maxWidth) {
+            maxWidth = width;
+        }
+        dummyContainer.removeChild(clone);
+    });
+
+    document.body.removeChild(dummyContainer);
+
+    // Store max width for later use
+    window.navItemMaxWidth = maxWidth;
+};
+
+// Show search results as user types in search box
+document.querySelector('#navbarSearchInput').addEventListener('input', function(e) {
+    var searchText = e.target.value.toLowerCase();
+    var items = document.querySelectorAll('.dropdown-item, .nav-link');
+    var resultsBox = document.querySelector('#searchResults');
+
+    // Clear any previous results
+    resultsBox.innerHTML = '';
+
+    items.forEach(function(item) {
+        var titleElement = item.querySelector('.icon-text');
+        var iconElement = item.querySelector('.icon');
+        var itemHref = item.getAttribute('href');
+        if (titleElement && iconElement && itemHref !== '#') {
+            var title = titleElement.innerText.toLowerCase();
+            if (title.indexOf(searchText) !== -1 && !resultsBox.querySelector(`a[href="${item.getAttribute('href')}"]`)) {
+                var result = document.createElement('a');
+                result.href = itemHref;
+                result.classList.add('dropdown-item');
+
+                var resultIcon = document.createElement('img');
+                resultIcon.src = iconElement.src;
+                resultIcon.alt = 'icon';
+                resultIcon.classList.add('icon');
+                result.appendChild(resultIcon);
+
+                var resultText = document.createElement('span');
+                resultText.textContent = title;
+                resultText.classList.add('icon-text');
+                result.appendChild(resultText);
+
+                resultsBox.appendChild(result);
+            }
+        }
+    });
+
+    // Set the width of the search results box to the maximum width
+    resultsBox.style.width = window.navItemMaxWidth + 'px';
+});
+
diff --git a/src/main/resources/templates/fragments/card.html b/src/main/resources/templates/fragments/card.html
index faa816a42..48142b033 100644
--- a/src/main/resources/templates/fragments/card.html
+++ b/src/main/resources/templates/fragments/card.html
@@ -1,4 +1,4 @@
-<div th:fragment="card" class="feature-card" th:id="${id}" th:if="${@endpointConfiguration.isEndpointEnabled(cardLink)}">
+<div th:fragment="card" class="feature-card" th:id="${id}" th:if="${@endpointConfiguration.isEndpointEnabled(cardLink)}" data-tags="${tags}">
     <a th:href="${cardLink}">
         <div class="d-flex align-items-center"> <!-- Add a flex container to align the SVG and title -->
             <img th:if="${svgPath}"  id="card-icon" class="home-card-icon home-card-icon-colour" th:src="${svgPath}" alt="Icon" width="30" height="30">
diff --git a/src/main/resources/templates/fragments/navbar.html b/src/main/resources/templates/fragments/navbar.html
index 9403af422..226141f63 100644
--- a/src/main/resources/templates/fragments/navbar.html
+++ b/src/main/resources/templates/fragments/navbar.html
@@ -205,6 +205,23 @@
                         </a>
 
                     </li>
+                    
+             <!-- Search Button and Search Bar -->
+<li class="nav-item position-relative">
+    <a href="#" class="nav-link" id="search-icon">
+        <img class="navbar-icon" src="images/search.svg" alt="icon" width="24" height="24">
+    </a>
+    <!-- Search Bar -->
+    <div class="collapse position-absolute" id="navbarSearch">
+        <form class="d-flex p-2 bg-white border" id="searchForm">
+            <input class="form-control" type="search" placeholder="Search" aria-label="Search" id="navbarSearchInput">
+        </form>
+        <!-- Search Results -->
+        <div id="searchResults" class="border p-2 bg-white"></div>
+    </div>
+</li>
+
+
                 </ul>
 
          
@@ -212,6 +229,7 @@
 
         </div>
         <script src="js/favourites.js"></script>
+        <script src="js/search.js"></script>
     </nav>
     
 	<div th:insert="~{fragments/errorBannerPerPage.html :: errorBannerPerPage}"></div>
diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html
index 33bf6b427..145b65d15 100644
--- a/src/main/resources/templates/home.html
+++ b/src/main/resources/templates/home.html
@@ -20,8 +20,13 @@
             </div>
 			<br class="d-md-none">
             <!-- Features -->
-            <div class="features-container container">
-            
+            <script src="js/homecard.js"></script>
+            	
+            <div class=" container">
+            <input type="text" id="searchBar" onkeyup="filterCards()" placeholder="Search for features...">
+            <div class="features-container ">
+            	
+            	
                  <div th:replace="~{fragments/card :: card(id='pipeline', cardTitle=#{home.pipeline.title}, cardText=#{home.pipeline.desc}, cardLink='pipeline', svgPath='images/pipeline.svg')}"></div>
                 
                 <div th:replace="~{fragments/card :: card(id='multi-tool', cardTitle=#{home.multiTool.title}, cardText=#{home.multiTool.desc}, cardLink='multi-tool', svgPath='images/tools.svg')}"></div>
@@ -70,13 +75,13 @@
                 
                 <div th:replace="~{fragments/card :: card(id='add-page-numbers', cardTitle=#{home.add-page-numbers.title}, cardText=#{home.add-page-numbers.desc}, cardLink='add-page-numbers', svgPath='images/add-page-numbers.svg')}"></div>
                 <div th:replace="~{fragments/card :: card(id='auto-rename', cardTitle=#{home.auto-rename.title}, cardText=#{home.auto-rename.desc}, cardLink='auto-rename', svgPath='images/fonts.svg')}"></div>
-                
+                <div th:replace="~{fragments/card :: card(id='adjust-contrast', cardTitle=#{home.adjust-contrast.title}, cardText=#{home.adjust-contrast.desc}, cardLink='adjust-contrast', svgPath='images/adjust-contrast.svg')}"></div>
 
                 
 		
-                <script src="js/homecard.js"></script>
+                
             </div>
-        </div>
+        </div> </div>
         <div th:insert="~{fragments/footer.html :: footer}"></div>
     </div>
 </body>
diff --git a/src/main/resources/templates/other/adjust-contrast.html b/src/main/resources/templates/other/adjust-contrast.html
index 87496d4f5..8250d6093 100644
--- a/src/main/resources/templates/other/adjust-contrast.html
+++ b/src/main/resources/templates/other/adjust-contrast.html
@@ -13,15 +13,215 @@
         <div class="row justify-content-center">
           <div class="col-md-6">
             <h2 th:text="#{extractImages.header}"></h2>
+			<input type="file" id="pdf-file" accept="application/pdf" />
+  <canvas id="pdf-canvas"></canvas>
 
-            <form id="multiPdfForm" th:action="@{adjust-contrast}" method="post" enctype="multipart/form-data">
-              <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
-                 <div class="form-group">
-                    <label for="contrastRange">Contrast</label>
-                    <input name="contrastRange" type="range" class="form-control-range" id="contrastRange" min="-100" max="100" value="0" step="1">
-                </div>
-              <button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{extractImages.submit}"></button>
-            </form>
+  <h4>Contrast: <span id="contrast-val">100</span>%</h4>
+  <input type="range" min="0" max="200" value="100" id="contrast-slider" />
+
+  <h4>Brightness: <span id="brightness-val">100</span>%</h4>
+  <input type="range" min="0" max="200" value="100" id="brightness-slider" />
+
+  <h4>Saturation: <span id="saturation-val">100</span>%</h4>
+  <input type="range" min="0" max="200" value="100" id="saturation-slider" />
+  
+  <button id="download-button">Download</button>
+
+  <script src="pdfjs/pdf.js"></script>
+  <script>
+    var canvas = document.getElementById('pdf-canvas');
+    var context = canvas.getContext('2d');
+    var originalImageData = null;
+
+    function renderPDFAndSaveOriginalImageData(file) {
+      var fileReader = new FileReader();
+      fileReader.onload = function() {
+        var data = new Uint8Array(this.result);
+        pdfjsLib.getDocument({data: data}).promise.then(function(pdf) {
+          pdf.getPage(1).then(function(page) {
+            var scale = 1.5;
+            var viewport = page.getViewport({ scale: scale });
+
+            canvas.height = viewport.height;
+            canvas.width = viewport.width;
+
+            var renderContext = {
+              canvasContext: context,
+              viewport: viewport
+            };
+
+            var renderTask = page.render(renderContext);
+            renderTask.promise.then(function () {
+              originalImageData = context.getImageData(0, 0, canvas.width, canvas.height);
+            });
+          });
+        });
+      };
+      fileReader.readAsArrayBuffer(file);
+    }
+
+    function adjustImageProperties() {
+        var contrast = parseFloat(document.getElementById('contrast-slider').value);
+        var brightness = parseFloat(document.getElementById('brightness-slider').value);
+        var saturation = parseFloat(document.getElementById('saturation-slider').value);
+
+        contrast /= 100; // normalize to range [0, 2]
+        brightness /= 100; // normalize to range [0, 2]
+        saturation /= 100; // normalize to range [0, 2]
+
+        if (originalImageData) {
+          var newImageData = context.createImageData(originalImageData.width, originalImageData.height);
+          newImageData.data.set(originalImageData.data);
+
+          for(var i=0; i<newImageData.data.length; i+=4)
+          {
+            var r = newImageData.data[i];
+            var g = newImageData.data[i+1];
+            var b = newImageData.data[i+2];
+            // Adjust contrast
+            r = adjustContrastForPixel(r, contrast);
+            g = adjustContrastForPixel(g, contrast);
+            b = adjustContrastForPixel(b, contrast);
+            // Adjust brightness
+            r = adjustBrightnessForPixel(r, brightness);
+            g = adjustBrightnessForPixel(g, brightness);
+            b = adjustBrightnessForPixel(b, brightness);
+            // Adjust saturation
+            if(i==100){
+            console.log('r',r)
+            console.log('g',g)
+            console.log('b',b)
+            console.log('saturation',saturation)
+          }
+            var rgb = adjustSaturationForPixel(r, g, b, saturation);
+            if(i==100){
+            console.log('rgb',rgb)
+            }
+            newImageData.data[i] = rgb[0];
+            newImageData.data[i+1] = rgb[1];
+            newImageData.data[i+2] = rgb[2];
+          }
+
+          context.putImageData(newImageData, 0, 0);
+        }
+      }
+
+    function rgbToHsl(r, g, b) {
+        r /= 255, g /= 255, b /= 255;
+
+        var max = Math.max(r, g, b), min = Math.min(r, g, b);
+        var h, s, l = (max + min) / 2;
+
+        if (max === min) {
+          h = s = 0; // achromatic
+        } else {
+          var d = max - min;
+          s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
+
+          switch (max) {
+            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
+            case g: h = (b - r) / d + 2; break;
+            case b: h = (r - g) / d + 4; break;
+          }
+
+          h /= 6;
+        }
+
+        return [h, s, l];
+      }
+
+      function hslToRgb(h, s, l) {
+        var r, g, b;
+
+        if (s === 0) {
+          r = g = b = l; // achromatic
+        } else {
+          var hue2rgb = function hue2rgb(p, q, t) {
+            if (t < 0) t += 1;
+            if (t > 1) t -= 1;
+            if (t < 1 / 6) return p + (q - p) * 6 * t;
+            if (t < 1 / 2) return q;
+            if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
+            return p;
+          };
+
+          var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+          var p = 2 * l - q;
+
+          r = hue2rgb(p, q, h + 1 / 3);
+          g = hue2rgb(p, q, h);
+          b = hue2rgb(p, q, h - 1 / 3);
+        }
+
+        return [r * 255, g * 255, b * 255];
+      }
+      
+      function adjustContrastForPixel(pixel, contrast) {
+          // Normalize to range [-0.5, 0.5]
+          var normalized = pixel / 255 - 0.5;
+
+          // Apply contrast
+          normalized *= contrast;
+
+          // Denormalize back to [0, 255]
+          return (normalized + 0.5) * 255;
+        }
+      function clamp(value, min, max) {
+    	  return Math.min(Math.max(value, min), max);
+    	}
+
+      function adjustSaturationForPixel(r, g, b, saturation) {
+          var hsl = rgbToHsl(r, g, b);
+          
+          // Adjust saturation
+          hsl[1] = clamp(hsl[1] * saturation, 0, 1);
+
+          // Convert back to RGB
+          var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
+
+          // Return adjusted RGB values
+          return rgb;
+        }
+      
+      function adjustBrightnessForPixel(pixel, brightness) {
+          return Math.max(0, Math.min(255, pixel * brightness));
+        }  
+      
+    function downloadImage() {
+      var downloadLink = document.createElement('a');
+      downloadLink.href = canvas.toDataURL('image/png');
+      downloadLink.download = 'download.png';
+      downloadLink.click();
+    }
+
+    // Event listeners
+    document.getElementById('pdf-file').addEventListener('change', function(e) {
+      if (e.target.files.length > 0) {
+        renderPDFAndSaveOriginalImageData(e.target.files[0]);
+      }
+    });
+
+    document.getElementById('contrast-slider').addEventListener('input', function() {
+      document.getElementById('contrast-val').textContent = this.value;
+      adjustImageProperties();
+    });
+
+    document.getElementById('brightness-slider').addEventListener('input', function() {
+      document.getElementById('brightness-val').textContent = this.value;
+      adjustImageProperties();
+    });
+
+    document.getElementById('saturation-slider').addEventListener('input', function() {
+      document.getElementById('saturation-val').textContent = this.value;
+      adjustImageProperties();
+    });
+
+    document.getElementById('download-button').addEventListener('click', function() {
+      downloadImage();
+    });
+  </script>
+      
+      
           </div>
         </div>
       </div>