parent
673f005fe6
commit
51ad741744
9 changed files with 265 additions and 283 deletions
|
@ -218,7 +218,7 @@ public class EndpointConfiguration {
|
||||||
addEndpointToGroup("Java", "overlay-pdf");
|
addEndpointToGroup("Java", "overlay-pdf");
|
||||||
addEndpointToGroup("Java", "split-pdf-by-sections");
|
addEndpointToGroup("Java", "split-pdf-by-sections");
|
||||||
addEndpointToGroup("Java", "remove-blanks");
|
addEndpointToGroup("Java", "remove-blanks");
|
||||||
|
|
||||||
// Javascript
|
// Javascript
|
||||||
addEndpointToGroup("Javascript", "pdf-organizer");
|
addEndpointToGroup("Javascript", "pdf-organizer");
|
||||||
addEndpointToGroup("Javascript", "sign");
|
addEndpointToGroup("Javascript", "sign");
|
||||||
|
|
|
@ -25,16 +25,15 @@ $(document).ready(function () {
|
||||||
const originalButtonText = $("#submitBtn").text();
|
const originalButtonText = $("#submitBtn").text();
|
||||||
$("#submitBtn").text("Processing...");
|
$("#submitBtn").text("Processing...");
|
||||||
console.log(override);
|
console.log(override);
|
||||||
|
|
||||||
// Set a timeout to show the game button if operation takes more than 5 seconds
|
// Set a timeout to show the game button if operation takes more than 5 seconds
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
var boredWaiting = localStorage.getItem("boredWaiting") || "disabled";
|
var boredWaiting = localStorage.getItem("boredWaiting") || "disabled";
|
||||||
const showGameBtn = document.getElementById('show-game-btn');
|
const showGameBtn = document.getElementById("show-game-btn");
|
||||||
if(boredWaiting === "enabled" && showGameBtn){
|
if (boredWaiting === "enabled" && showGameBtn) {
|
||||||
showGameBtn.style.display = 'block';
|
showGameBtn.style.display = "block";
|
||||||
}
|
}
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (remoteCall === true) {
|
if (remoteCall === true) {
|
||||||
|
@ -46,9 +45,8 @@ $(document).ready(function () {
|
||||||
}
|
}
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
$("#submitBtn").text(originalButtonText);
|
$("#submitBtn").text(originalButtonText);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
handleDownloadError(error);
|
handleDownloadError(error);
|
||||||
$("#submitBtn").text(originalButtonText);
|
$("#submitBtn").text(originalButtonText);
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|
4
src/main/resources/static/pdfjs/js/viewer.js
vendored
4
src/main/resources/static/pdfjs/js/viewer.js
vendored
|
@ -3323,13 +3323,13 @@
|
||||||
kind: OptionKind.WORKER
|
kind: OptionKind.WORKER
|
||||||
},
|
},
|
||||||
workerSrc: {
|
workerSrc: {
|
||||||
value: "/pdfjs/pdf.worker.js",
|
value: "./pdfjs/pdf.worker.js",
|
||||||
kind: OptionKind.WORKER
|
kind: OptionKind.WORKER
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
{
|
{
|
||||||
defaultOptions.defaultUrl = {
|
defaultOptions.defaultUrl = {
|
||||||
value: "/pdfjs/example/Welcome.pdf",
|
value: "./pdfjs/example/Welcome.pdf",
|
||||||
kind: OptionKind.VIEWER
|
kind: OptionKind.VIEWER
|
||||||
};
|
};
|
||||||
defaultOptions.disablePreferences = {
|
defaultOptions.disablePreferences = {
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
<link rel="stylesheet" href="css/bootstrap-icons.min.css">
|
<link rel="stylesheet" href="css/bootstrap-icons.min.css">
|
||||||
|
|
||||||
<!-- PDF.js -->
|
<!-- PDF.js -->
|
||||||
<script src="pdfjs/pdf.js"></script>
|
<script th:src="@{pdfjs/pdf.js}"></script>
|
||||||
|
|
||||||
<!-- PDF-Lib -->
|
<!-- PDF-Lib -->
|
||||||
<script src="js/thirdParty/pdf-lib.min.js"></script>
|
<script src="js/thirdParty/pdf-lib.min.js"></script>
|
||||||
|
@ -70,24 +70,22 @@
|
||||||
<script>
|
<script>
|
||||||
console.log("loaded game");
|
console.log("loaded game");
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
// Find the file input within the form
|
||||||
// Find the file input within the form
|
var fileInput = $('input[type="file"]');
|
||||||
var fileInput = $('input[type="file"]');
|
|
||||||
|
// Find the closest enclosing form of the file input
|
||||||
// Find the closest enclosing form of the file input
|
var form = fileInput.closest('form');
|
||||||
var form = fileInput.closest('form');
|
|
||||||
|
// Find the submit button within the form
|
||||||
// Find the submit button within the form
|
var submitButton = form.find('button[type="submit"], input[type="submit"]');
|
||||||
var submitButton = form.find('button[type="submit"], input[type="submit"]');
|
|
||||||
|
// Create the 'show-game-btn' button
|
||||||
// Create the 'show-game-btn' button
|
var gameButton = $('<button type="button" class="btn btn-primary" id="show-game-btn" style="display:none;">Bored waiting?</button><br /><br />');
|
||||||
var gameButton = $('<button type="button" class="btn btn-primary" id="show-game-btn" style="display:none;">Bored waiting?</button><br /><br />');
|
|
||||||
|
// Insert the 'show-game-btn' just above the submit button
|
||||||
// Insert the 'show-game-btn' just above the submit button
|
submitButton.before(gameButton);
|
||||||
submitButton.before(gameButton);
|
|
||||||
|
|
||||||
|
|
||||||
function loadGameScript(callback) {
|
function loadGameScript(callback) {
|
||||||
console.log('loadGameScript called');
|
console.log('loadGameScript called');
|
||||||
const script = document.createElement('script');
|
const script = document.createElement('script');
|
||||||
|
@ -122,8 +120,6 @@
|
||||||
gameDialog.close();
|
gameDialog.close();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<div id="game-container">
|
<div id="game-container">
|
||||||
|
|
|
@ -4,272 +4,260 @@
|
||||||
<th:block th:insert="~{fragments/common :: head(title=#{adjustContrast.title}, header=#{adjustContrast.header})}"></th:block>
|
<th:block th:insert="~{fragments/common :: head(title=#{adjustContrast.title}, header=#{adjustContrast.header})}"></th:block>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="page-container">
|
<div id="page-container">
|
||||||
<div id="content-wrap">
|
<div id="content-wrap">
|
||||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div id="sliders-container" style="display:none;">
|
<div id="sliders-container" style="display:none;">
|
||||||
<h4>
|
<h4><span th:text="#{adjustContrast.contrast}"></span> <span id="contrast-val">100</span>%</h4>
|
||||||
<span th:text="#{adjustContrast.contrast}"></span> <span id="contrast-val">100</span>%
|
<input type="range" min="0" max="200" value="100" id="contrast-slider" />
|
||||||
</h4>
|
|
||||||
<input type="range" min="0" max="200" value="100" id="contrast-slider" />
|
|
||||||
|
|
||||||
<h4>
|
<h4><span th:text="#{adjustContrast.brightness}"></span> <span id="brightness-val">100</span>%</h4>
|
||||||
<span th:text="#{adjustContrast.brightness}"></span> <span id="brightness-val">100</span>%
|
<input type="range" min="0" max="200" value="100" id="brightness-slider" />
|
||||||
</h4>
|
|
||||||
<input type="range" min="0" max="200" value="100" id="brightness-slider" />
|
|
||||||
|
|
||||||
<h4>
|
<h4><span th:text="#{adjustContrast.saturation}"></span> <span id="saturation-val">100</span>%</h4>
|
||||||
<span th:text="#{adjustContrast.saturation}"></span> <span id="saturation-val">100</span>%
|
<input type="range" min="0" max="200" value="100" id="saturation-slider" />
|
||||||
</h4>
|
</div>
|
||||||
<input type="range" min="0" max="200" value="100" id="saturation-slider" />
|
</div>
|
||||||
</div>
|
<div class="col-md-7">
|
||||||
</div>
|
<h2 th:text="#{adjustContrast.header}"></h2>
|
||||||
<div class="col-md-7">
|
<div class="col-md-8">
|
||||||
<h2 th:text="#{adjustContrast.header}"></h2>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf', remoteCall='false')}"></div>
|
||||||
<div class="col-md-8">
|
</div>
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf', remoteCall='false')}"></div>
|
<br />
|
||||||
</div>
|
<canvas id="contrast-pdf-canvas"></canvas>
|
||||||
<br>
|
<button id="download-button" class="btn btn-primary" th:text="#{adjustContrast.download}"></button>
|
||||||
<canvas id="contrast-pdf-canvas"></canvas>
|
</div>
|
||||||
<button id="download-button" class="btn btn-primary" th:text="#{adjustContrast.download}"></button>
|
</div>
|
||||||
</div>
|
<style>
|
||||||
</div>
|
#flex-container {
|
||||||
<style>
|
display: flex;
|
||||||
#flex-container {
|
align-items: center;
|
||||||
display: flex;
|
}
|
||||||
align-items: center;
|
#sliders-container {
|
||||||
}
|
padding: 0 20px; /* Add some padding to separate sliders from canvas */
|
||||||
#sliders-container {
|
}
|
||||||
padding: 0 20px; /* Add some padding to separate sliders from canvas */
|
</style>
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var canvas = document.getElementById('contrast-pdf-canvas');
|
||||||
|
var context = canvas.getContext('2d');
|
||||||
|
var originalImageData = null;
|
||||||
|
var allPages = [];
|
||||||
|
var pdfDoc = null;
|
||||||
|
var pdf = null; // This is the current PDF document
|
||||||
|
|
||||||
<script src="pdfjs/pdf.js"></script>
|
async function renderPDFAndSaveOriginalImageData(file) {
|
||||||
<script>
|
var fileReader = new FileReader();
|
||||||
var canvas = document.getElementById('contrast-pdf-canvas');
|
fileReader.onload = async function() {
|
||||||
var context = canvas.getContext('2d');
|
var data = new Uint8Array(this.result);
|
||||||
var originalImageData = null;
|
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
|
||||||
var allPages = [];
|
pdf = await pdfjsLib.getDocument({data: data}).promise;
|
||||||
var pdfDoc = null;
|
|
||||||
var pdf = null; // This is the current PDF document
|
|
||||||
|
|
||||||
async function renderPDFAndSaveOriginalImageData(file) {
|
// Get the number of pages in the PDF
|
||||||
var fileReader = new FileReader();
|
var numPages = pdf.numPages;
|
||||||
fileReader.onload = async function() {
|
allPages = Array.from({length: numPages}, (_, i) => i + 1);
|
||||||
var data = new Uint8Array(this.result);
|
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
|
|
||||||
pdf = await pdfjsLib.getDocument({data: data}).promise;
|
|
||||||
|
|
||||||
// Get the number of pages in the PDF
|
// Create a new PDF document
|
||||||
var numPages = pdf.numPages;
|
pdfDoc = await PDFLib.PDFDocument.create();
|
||||||
allPages = Array.from({length: numPages}, (_, i) => i + 1);
|
// Render the first page in the viewer
|
||||||
|
await renderPageAndAdjustImageProperties(1);
|
||||||
|
document.getElementById("sliders-container").style.display = "block";
|
||||||
|
|
||||||
// Create a new PDF document
|
};
|
||||||
pdfDoc = await PDFLib.PDFDocument.create();
|
fileReader.readAsArrayBuffer(file);
|
||||||
// Render the first page in the viewer
|
}
|
||||||
await renderPageAndAdjustImageProperties(1);
|
|
||||||
document.getElementById("sliders-container").style.display = "block";
|
|
||||||
|
|
||||||
};
|
// This function is now async and returns a promise
|
||||||
fileReader.readAsArrayBuffer(file);
|
function renderPageAndAdjustImageProperties(pageNum) {
|
||||||
}
|
|
||||||
|
|
||||||
// This function is now async and returns a promise
|
|
||||||
function renderPageAndAdjustImageProperties(pageNum) {
|
|
||||||
return new Promise(async function(resolve, reject) {
|
return new Promise(async function(resolve, reject) {
|
||||||
var page = await pdf.getPage(pageNum);
|
var page = await pdf.getPage(pageNum);
|
||||||
var scale = 1.5;
|
var scale = 1.5;
|
||||||
var viewport = page.getViewport({ scale: scale });
|
var viewport = page.getViewport({ scale: scale });
|
||||||
|
|
||||||
canvas.height = viewport.height;
|
canvas.height = viewport.height;
|
||||||
canvas.width = viewport.width;
|
canvas.width = viewport.width;
|
||||||
|
|
||||||
var renderContext = {
|
var renderContext = {
|
||||||
canvasContext: context,
|
canvasContext: context,
|
||||||
viewport: viewport
|
viewport: viewport
|
||||||
};
|
};
|
||||||
|
|
||||||
var renderTask = page.render(renderContext);
|
var renderTask = page.render(renderContext);
|
||||||
renderTask.promise.then(function () {
|
renderTask.promise.then(function () {
|
||||||
originalImageData = context.getImageData(0, 0, canvas.width, canvas.height);
|
originalImageData = context.getImageData(0, 0, canvas.width, canvas.height);
|
||||||
adjustImageProperties();
|
adjustImageProperties();
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
canvas.classList.add("fixed-shadow-canvas");
|
canvas.classList.add("fixed-shadow-canvas");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function adjustImageProperties() {
|
function adjustImageProperties() {
|
||||||
var contrast = parseFloat(document.getElementById('contrast-slider').value);
|
var contrast = parseFloat(document.getElementById('contrast-slider').value);
|
||||||
var brightness = parseFloat(document.getElementById('brightness-slider').value);
|
var brightness = parseFloat(document.getElementById('brightness-slider').value);
|
||||||
var saturation = parseFloat(document.getElementById('saturation-slider').value);
|
var saturation = parseFloat(document.getElementById('saturation-slider').value);
|
||||||
|
|
||||||
contrast /= 100; // normalize to range [0, 2]
|
contrast /= 100; // normalize to range [0, 2]
|
||||||
brightness /= 100; // normalize to range [0, 2]
|
brightness /= 100; // normalize to range [0, 2]
|
||||||
saturation /= 100; // normalize to range [0, 2]
|
saturation /= 100; // normalize to range [0, 2]
|
||||||
|
|
||||||
if (originalImageData) {
|
if (originalImageData) {
|
||||||
var newImageData = context.createImageData(originalImageData.width, originalImageData.height);
|
var newImageData = context.createImageData(originalImageData.width, originalImageData.height);
|
||||||
newImageData.data.set(originalImageData.data);
|
newImageData.data.set(originalImageData.data);
|
||||||
|
|
||||||
for(var i=0; i<newImageData.data.length; i+=4)
|
for(var i=0; i<newImageData.data.length; i+=4) {
|
||||||
{
|
var r = newImageData.data[i];
|
||||||
var r = newImageData.data[i];
|
var g = newImageData.data[i+1];
|
||||||
var g = newImageData.data[i+1];
|
var b = newImageData.data[i+2];
|
||||||
var b = newImageData.data[i+2];
|
// Adjust contrast
|
||||||
// Adjust contrast
|
r = adjustContrastForPixel(r, contrast);
|
||||||
r = adjustContrastForPixel(r, contrast);
|
g = adjustContrastForPixel(g, contrast);
|
||||||
g = adjustContrastForPixel(g, contrast);
|
b = adjustContrastForPixel(b, contrast);
|
||||||
b = adjustContrastForPixel(b, contrast);
|
// Adjust brightness
|
||||||
// Adjust brightness
|
r = adjustBrightnessForPixel(r, brightness);
|
||||||
r = adjustBrightnessForPixel(r, brightness);
|
g = adjustBrightnessForPixel(g, brightness);
|
||||||
g = adjustBrightnessForPixel(g, brightness);
|
b = adjustBrightnessForPixel(b, brightness);
|
||||||
b = adjustBrightnessForPixel(b, brightness);
|
// Adjust saturation
|
||||||
// Adjust saturation
|
var rgb = adjustSaturationForPixel(r, g, b, saturation);
|
||||||
var rgb = adjustSaturationForPixel(r, g, b, saturation);
|
newImageData.data[i] = rgb[0];
|
||||||
newImageData.data[i] = rgb[0];
|
newImageData.data[i+1] = rgb[1];
|
||||||
newImageData.data[i+1] = rgb[1];
|
newImageData.data[i+2] = rgb[2];
|
||||||
newImageData.data[i+2] = rgb[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
context.putImageData(newImageData, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.putImageData(newImageData, 0, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function rgbToHsl(r, g, b) {
|
function rgbToHsl(r, g, b) {
|
||||||
r /= 255, g /= 255, b /= 255;
|
r /= 255, g /= 255, b /= 255;
|
||||||
|
|
||||||
var max = Math.max(r, g, b), min = Math.min(r, g, b);
|
var max = Math.max(r, g, b), min = Math.min(r, g, b);
|
||||||
var h, s, l = (max + min) / 2;
|
var h, s, l = (max + min) / 2;
|
||||||
|
|
||||||
if (max === min) {
|
if (max === min) {
|
||||||
h = s = 0; // achromatic
|
h = s = 0; // achromatic
|
||||||
} else {
|
} else {
|
||||||
var d = max - min;
|
var d = max - min;
|
||||||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||||
|
|
||||||
switch (max) {
|
switch (max) {
|
||||||
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
||||||
case g: h = (b - r) / d + 2; break;
|
case g: h = (b - r) / d + 2; break;
|
||||||
case b: h = (r - g) / d + 4; break;
|
case b: h = (r - g) / d + 4; break;
|
||||||
}
|
|
||||||
|
|
||||||
h /= 6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [h, s, l];
|
h /= 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
function hslToRgb(h, s, l) {
|
return [h, s, l];
|
||||||
var r, g, b;
|
}
|
||||||
|
|
||||||
if (s === 0) {
|
function hslToRgb(h, s, l) {
|
||||||
r = g = b = l; // achromatic
|
var r, g, b;
|
||||||
} 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;
|
if (s === 0) {
|
||||||
var p = 2 * l - q;
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
r = hue2rgb(p, q, h + 1 / 3);
|
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||||
g = hue2rgb(p, q, h);
|
var p = 2 * l - q;
|
||||||
b = hue2rgb(p, q, h - 1 / 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [r * 255, g * 255, b * 255];
|
r = hue2rgb(p, q, h + 1 / 3);
|
||||||
|
g = hue2rgb(p, q, h);
|
||||||
|
b = hue2rgb(p, q, h - 1 / 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
function adjustContrastForPixel(pixel, contrast) {
|
return [r * 255, g * 255, b * 255];
|
||||||
// Normalize to range [-0.5, 0.5]
|
}
|
||||||
var normalized = pixel / 255 - 0.5;
|
|
||||||
|
|
||||||
// Apply contrast
|
function adjustContrastForPixel(pixel, contrast) {
|
||||||
normalized *= contrast;
|
// Normalize to range [-0.5, 0.5]
|
||||||
|
var normalized = pixel / 255 - 0.5;
|
||||||
|
|
||||||
// Denormalize back to [0, 255]
|
// Apply contrast
|
||||||
return (normalized + 0.5) * 255;
|
normalized *= contrast;
|
||||||
}
|
|
||||||
function clamp(value, min, max) {
|
// Denormalize back to [0, 255]
|
||||||
return Math.min(Math.max(value, min), max);
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadPDF() {
|
||||||
|
for (var i = 0; i < allPages.length; i++) {
|
||||||
|
await renderPageAndAdjustImageProperties(allPages[i]);
|
||||||
|
const pngImageBytes = canvas.toDataURL('image/png');
|
||||||
|
const pngImage = await pdfDoc.embedPng(pngImageBytes);
|
||||||
|
const pngDims = pngImage.scale(1);
|
||||||
|
|
||||||
|
// Create a blank page matching the dimensions of the image
|
||||||
|
const page = pdfDoc.addPage([pngDims.width, pngDims.height]);
|
||||||
|
|
||||||
|
// Draw the PNG image
|
||||||
|
page.drawImage(pngImage, {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: pngDims.width,
|
||||||
|
height: pngDims.height
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function adjustSaturationForPixel(r, g, b, saturation) {
|
// Serialize the PDFDocument to bytes (a Uint8Array)
|
||||||
var hsl = rgbToHsl(r, g, b);
|
const pdfBytes = await pdfDoc.save();
|
||||||
|
|
||||||
// Adjust saturation
|
// Create a Blob
|
||||||
hsl[1] = clamp(hsl[1] * saturation, 0, 1);
|
const blob = new Blob([pdfBytes.buffer], {type: "application/pdf"});
|
||||||
|
|
||||||
// Convert back to RGB
|
// Create download link
|
||||||
var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
|
const downloadLink = document.createElement('a');
|
||||||
|
downloadLink.href = URL.createObjectURL(blob);
|
||||||
|
downloadLink.download = "download.pdf";
|
||||||
|
downloadLink.click();
|
||||||
|
|
||||||
// Return adjusted RGB values
|
// After download, reset the viewer and clear stored data
|
||||||
return rgb;
|
allPages = []; // Clear the pages
|
||||||
}
|
originalImageData = null; // Clear the image data
|
||||||
|
|
||||||
function adjustBrightnessForPixel(pixel, brightness) {
|
|
||||||
return Math.max(0, Math.min(255, pixel * brightness));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function downloadPDF() {
|
|
||||||
for (var i = 0; i < allPages.length; i++) {
|
|
||||||
await renderPageAndAdjustImageProperties(allPages[i]);
|
|
||||||
const pngImageBytes = canvas.toDataURL('image/png');
|
|
||||||
const pngImage = await pdfDoc.embedPng(pngImageBytes);
|
|
||||||
const pngDims = pngImage.scale(1);
|
|
||||||
|
|
||||||
// Create a blank page matching the dimensions of the image
|
|
||||||
const page = pdfDoc.addPage([pngDims.width, pngDims.height]);
|
|
||||||
|
|
||||||
// Draw the PNG image
|
|
||||||
page.drawImage(pngImage, {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: pngDims.width,
|
|
||||||
height: pngDims.height
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize the PDFDocument to bytes (a Uint8Array)
|
|
||||||
const pdfBytes = await pdfDoc.save();
|
|
||||||
|
|
||||||
// Create a Blob
|
|
||||||
const blob = new Blob([pdfBytes.buffer], {type: "application/pdf"});
|
|
||||||
|
|
||||||
// Create download link
|
|
||||||
const downloadLink = document.createElement('a');
|
|
||||||
downloadLink.href = URL.createObjectURL(blob);
|
|
||||||
downloadLink.download = "download.pdf";
|
|
||||||
downloadLink.click();
|
|
||||||
|
|
||||||
// After download, reset the viewer and clear stored data
|
|
||||||
allPages = []; // Clear the pages
|
|
||||||
originalImageData = null; // Clear the image data
|
|
||||||
|
|
||||||
// Go back to page 1 and render it in the viewer
|
|
||||||
if (pdf !== null) {
|
|
||||||
renderPageAndAdjustImageProperties(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Go back to page 1 and render it in the viewer
|
||||||
|
if (pdf !== null) {
|
||||||
|
renderPageAndAdjustImageProperties(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Event listeners
|
// Event listeners
|
||||||
document.getElementById('fileInput-input').addEventListener('change', function(e) {
|
document.getElementById('fileInput-input').addEventListener('change', function(e) {
|
||||||
|
@ -294,14 +282,14 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('download-button').addEventListener('click', function() {
|
document.getElementById('download-button').addEventListener('click', function() {
|
||||||
downloadPDF();
|
downloadPDF();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||||
</div>
|
</div>
|
||||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
</body>
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
<th:block th:insert="~{fragments/common :: head(title=#{compare.title}, header=#{compare.header})}"></th:block>
|
<th:block th:insert="~{fragments/common :: head(title=#{compare.title}, header=#{compare.header})}"></th:block>
|
||||||
<style>
|
<style>
|
||||||
.result-column {
|
.result-column {
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
height: calc(100vh - 400px);
|
height: calc(100vh - 400px);
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||||
<div id="page-container">
|
<div id="page-container">
|
||||||
<div id="content-wrap">
|
<div id="content-wrap">
|
||||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
||||||
|
|
|
@ -21,26 +21,26 @@
|
||||||
<script src="js/local-pdf-input-download.js"></script>
|
<script src="js/local-pdf-input-download.js"></script>
|
||||||
<script>
|
<script>
|
||||||
document.getElementById('pdfForm').addEventListener('submit', async (e) => {
|
document.getElementById('pdfForm').addEventListener('submit', async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const { PDFDocument } = PDFLib;
|
const { PDFDocument } = PDFLib;
|
||||||
|
|
||||||
const processFile = async (file) => {
|
const processFile = async (file) => {
|
||||||
const origFileUrl = URL.createObjectURL(file);
|
const origFileUrl = URL.createObjectURL(file);
|
||||||
const formPdfBytes = await fetch(origFileUrl).then(res => res.arrayBuffer());
|
const formPdfBytes = await fetch(origFileUrl).then(res => res.arrayBuffer());
|
||||||
const pdfDoc = await PDFDocument.load(formPdfBytes, { ignoreEncryption: true });
|
const pdfDoc = await PDFDocument.load(formPdfBytes, { ignoreEncryption: true });
|
||||||
|
|
||||||
const form = pdfDoc.getForm();
|
const form = pdfDoc.getForm();
|
||||||
form.flatten();
|
form.flatten();
|
||||||
|
|
||||||
const pdfBytes = await pdfDoc.save();
|
const pdfBytes = await pdfDoc.save();
|
||||||
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
|
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
|
||||||
const fileName = (file.name ? file.name.replace('.pdf', '') : 'pdf') + '_flattened.pdf';
|
const fileName = (file.name ? file.name.replace('.pdf', '') : 'pdf') + '_flattened.pdf';
|
||||||
|
|
||||||
return { processedData: pdfBlob, fileName };
|
return { processedData: pdfBlob, fileName };
|
||||||
};
|
};
|
||||||
|
|
||||||
await downloadFilesWithCallback(processFile);
|
await downloadFilesWithCallback(processFile);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -32,11 +32,11 @@ See https://github.com/adobe-type-tools/cmap-resources
|
||||||
<script src="js/thirdParty/bootstrap.min.js"></script>
|
<script src="js/thirdParty/bootstrap.min.js"></script>
|
||||||
|
|
||||||
<!-- This snippet is used in production (included from view-pdf.html) -->
|
<!-- This snippet is used in production (included from view-pdf.html) -->
|
||||||
<link rel="resource" type="application/l10n" href="pdfjs/locale/locale.properties">
|
<link rel="resource" type="application/l10n" th:href="@{pdfjs/locale/locale.properties}">
|
||||||
<script src="pdfjs/pdf.js"></script>
|
<script th:src="@{pdfjs/pdf.js}" type="module"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="pdfjs/css/viewer.css">
|
<link rel="stylesheet" th:href="@{/pdfjs/css/viewer.css}">
|
||||||
<script src="pdfjs/js/viewer.js"></script>
|
<script th:src="@{pdfjs/js/viewer.js}" type="module"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body tabindex="1">
|
<body tabindex="1">
|
||||||
|
|
Loading…
Reference in a new issue