sign changes min size, lite docker, merge fix #172

This commit is contained in:
Anthony Stirling 2023-06-08 20:25:55 +01:00
parent ecba6461df
commit 04032c0dfe
11 changed files with 124 additions and 85 deletions

View file

@ -8,8 +8,14 @@ on:
- main - main
jobs: jobs:
push: push:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
matrix:
config: [
{ dockerfile: "./Dockerfile", tagSuffix: "" },
{ dockerfile: "./Dockerfile-ultra-lite", tagSuffix: "-ultra-lite" },
{ dockerfile: "./Dockerfile-lite", tagSuffix: "-lite" }
]
steps: steps:
- uses: actions/checkout@v3.5.2 - uses: actions/checkout@v3.5.2
@ -46,17 +52,10 @@ jobs:
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ github.token }} password: ${{ github.token }}
- name: Generate tags - name: Convert repository owner to lowercase
id: meta id: repoowner
uses: docker/metadata-action@v4.4.0 run: echo "::set-output name=lowercase::$(echo ${{ github.repository_owner }} | awk '{print tolower($0)}')"
with:
images: |
${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
ghcr.io/${{ github.repository_owner }}/s-pdf
tags: |
type=raw,value=${{ steps.versionNumber.outputs.versionNumber }},enable=${{ github.ref == 'refs/heads/master' }}
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }}
type=raw,value=alpha,enable=${{ github.ref == 'refs/heads/main' }}
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2.1.0 uses: docker/setup-qemu-action@v2.1.0
@ -64,44 +63,28 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2.5.0 uses: docker/setup-buildx-action@v2.5.0
- name: Build and push main Dockerfile
- name: Generate tags
id: meta
uses: docker/metadata-action@v4.4.0
with:
images: |
${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
ghcr.io/${{ steps.repoowner.outputs.lowercase }}/s-pdf
tags: |
type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}${{ matrix.config.tagSuffix }},enable=${{ github.ref == 'refs/heads/master' }}
type=raw,value=latest${{ matrix.config.tagSuffix }},enable=${{ github.ref == 'refs/heads/master' }}
type=raw,value=alpha,enable=${{ github.ref == 'refs/heads/main' }}
- name: Build and push Dockerfile
uses: docker/build-push-action@v4.0.0 uses: docker/build-push-action@v4.0.0
with: with:
context: . context: .
dockerfile: ./Dockerfile dockerfile: ${{ matrix.config.dockerfile }}
push: true push: true
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64/v8 platforms: linux/amd64,linux/arm64/v8
- name: Generate tags
id: meta2
uses: docker/metadata-action@v4.4.0
with:
images: |
${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
ghcr.io/${{ github.repository_owner }}/s-pdf
tags: |
type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-ultra-light,enable=${{ github.ref == 'refs/heads/master' }}
type=raw,value=latest-ultra-light,enable=${{ github.ref == 'refs/heads/master' }}
type=raw,value=alpha-ultra-light,enable=${{ github.ref == 'refs/heads/main' }}
- name: Convert repository owner to lowercase
id: repoowner
run: echo "::set-output name=lowercase::$(echo ${{ github.repository_owner }} | awk '{print tolower($0)}')"
- name: Build and push Dockerfile-ultralite
uses: docker/build-push-action@v4.0.0
with:
context: .
file: ./Dockerfile-ultralite
push: true
cache-from: type=gha
cache-to: type=gha,mode=max
tags: ${{ steps.meta2.outputs.tags }}
labels: ${{ steps.meta2.outputs.labels }}
platforms: linux/amd64,linux/arm64/v8

23
Dockerfile-lite Normal file
View file

@ -0,0 +1,23 @@
# Build jbig2enc in a separate stage
FROM bellsoft/liberica-openjdk-debian:17
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libreoffice-core-nogui \
libreoffice-common \
libreoffice-writer-nogui \
libreoffice-calc-nogui \
libreoffice-impress-nogui \
unoconv && \
rm -rf /var/lib/apt/lists/*
# Copy the application JAR file
COPY build/libs/*.jar app.jar
# Expose the application port
EXPOSE 8080
# Set environment variables
ENV GROUPS_TO_REMOVE=Python,OpenCV,OCRmyPDF
# Run the application
CMD ["java", "-jar", "/app.jar"]

View file

@ -1,5 +1,5 @@
# Build jbig2enc in a separate stage # Build jbig2enc in a separate stage
FROM openjdk:17-jdk-slim FROM bellsoft/liberica-openjdk-alpine:17
# Copy the application JAR file # Copy the application JAR file
COPY build/libs/*.jar app.jar COPY build/libs/*.jar app.jar

View file

@ -1,5 +1,5 @@
# Main stage # Main stage
FROM openjdk:17-jdk-slim AS base FROM bellsoft/liberica-openjdk-debian:17 AS base
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
libreoffice-core-nogui \ libreoffice-core-nogui \

View file

@ -14,13 +14,21 @@ def is_blank_image(image_path, threshold=10, white_percent=99, white_value=255,
blurred_image = cv2.GaussianBlur(image, (blur_size, blur_size), 0) blurred_image = cv2.GaussianBlur(image, (blur_size, blur_size), 0)
_, thresholded_image = cv2.threshold(blurred_image, white_value - threshold, white_value, cv2.THRESH_BINARY) _, thresholded_image = cv2.threshold(blurred_image, white_value - threshold, white_value, cv2.THRESH_BINARY)
# Calculate the percentage of white pixels in the thresholded image # Calculate the percentage of white pixels in the thresholded image
white_pixels = np.sum(thresholded_image == white_value) white_pixels = 0
total_pixels = thresholded_image.size total_pixels = thresholded_image.size
white_pixel_percentage = (white_pixels / total_pixels) * 100 for i in range(0, thresholded_image.shape[0], 2):
for j in range(0, thresholded_image.shape[1], 2):
if thresholded_image[i, j] == white_value:
white_pixels += 1
white_pixel_percentage = (white_pixels / (i * thresholded_image.shape[1] + j + 1)) * 100
if white_pixel_percentage < white_percent:
return False
print(f"Page has white pixel percent of {white_pixel_percentage}") print(f"Page has white pixel percent of {white_pixel_percentage}")
return white_pixel_percentage > white_percent return True
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -20,12 +20,14 @@ public class EndpointConfiguration {
} }
public void enableEndpoint(String endpoint) { public void enableEndpoint(String endpoint) {
endpointStatuses.put(endpoint, true); endpointStatuses.put(endpoint, true);
} }
public void disableEndpoint(String endpoint) { public void disableEndpoint(String endpoint) {
logger.info("Disabling {}", endpoint); if(!endpointStatuses.containsKey(endpoint) || endpointStatuses.get(endpoint) != false) {
endpointStatuses.put(endpoint, false); logger.info("Disabling {}", endpoint);
endpointStatuses.put(endpoint, false);
}
} }
public boolean isEndpointEnabled(String endpoint) { public boolean isEndpointEnabled(String endpoint) {

View file

@ -74,7 +74,9 @@ public class OtherWebController {
@Hidden @Hidden
public ModelAndView ocrPdfPage() { public ModelAndView ocrPdfPage() {
ModelAndView modelAndView = new ModelAndView("other/ocr-pdf"); ModelAndView modelAndView = new ModelAndView("other/ocr-pdf");
modelAndView.addObject("languages", getAvailableTesseractLanguages()); List<String> languages = getAvailableTesseractLanguages();
Collections.sort(languages);
modelAndView.addObject("languages", languages);
modelAndView.addObject("currentPage", "ocr-pdf"); modelAndView.addObject("currentPage", "ocr-pdf");
return modelAndView; return modelAndView;
} }

View file

@ -19,12 +19,13 @@ $(document).ready(function() {
$('#submitBtn').text('Processing...'); $('#submitBtn').text('Processing...');
try { try {
if (override === 'multi' || files.length > 1 && override !== 'single') { if(remoteCall === true) {
await submitMultiPdfForm(url, files); if (override === 'multi' || (!multiple && files.length > 1) && override !== 'single' ) {
} else { await submitMultiPdfForm(url, files);
await handleSingleDownload(url, formData); } else {
await handleSingleDownload(url, formData);
}
} }
$('#submitBtn').text(originalButtonText); $('#submitBtn').text(originalButtonText);
} catch (error) { } catch (error) {
handleDownloadError(error); handleDownloadError(error);

View file

@ -25,33 +25,50 @@ const DraggableUtils = {
}, },
}) })
.resizable({ .resizable({
edges: { left: true, right: true, bottom: true, top: true }, edges: { left: true, right: true, bottom: true, top: true },
listeners: { listeners: {
move: (event) => { move: (event) => {
var target = event.target var target = event.target
var x = (parseFloat(target.getAttribute('data-x')) || 0) var x = (parseFloat(target.getAttribute('data-x')) || 0)
var y = (parseFloat(target.getAttribute('data-y')) || 0) var y = (parseFloat(target.getAttribute('data-y')) || 0)
// update the element's style // check if control key is pressed
target.style.width = event.rect.width + 'px' if (event.ctrlKey) {
target.style.height = event.rect.height + 'px' const aspectRatio = target.offsetWidth / target.offsetHeight;
// preserve aspect ratio
let width = event.rect.width;
let height = event.rect.height;
// translate when resizing from top or left edges if (Math.abs(event.deltaRect.width) >= Math.abs(event.deltaRect.height)) {
x += event.deltaRect.left height = width / aspectRatio;
y += event.deltaRect.top } else {
width = height * aspectRatio;
}
target.style.transform = 'translate(' + x + 'px,' + y + 'px)' event.rect.width = width;
event.rect.height = height;
}
target.setAttribute('data-x', x) target.style.width = event.rect.width + 'px'
target.setAttribute('data-y', y) target.style.height = event.rect.height + 'px'
target.textContent = Math.round(event.rect.width) + '\u00D7' + Math.round(event.rect.height)
// translate when resizing from top or left edges
x += event.deltaRect.left
y += event.deltaRect.top
target.style.transform = 'translate(' + x + 'px,' + y + 'px)'
target.setAttribute('data-x', x)
target.setAttribute('data-y', y)
target.textContent = Math.round(event.rect.width) + '\u00D7' + Math.round(event.rect.height)
this.onInteraction(target);
},
},
this.onInteraction(target);
},
},
modifiers: [ modifiers: [
interact.modifiers.restrictSize({ interact.modifiers.restrictSize({
min: { width: 50, height: 50 }, min: { width: 5, height: 5 },
}), }),
], ],
inertia: true, inertia: true,

View file

@ -90,9 +90,11 @@
</dialog> </dialog>
</th:block> </th:block>
<th:block th:fragment="fileSelector(name, multiple)" th:with="accept=${accept} ?: '*/*', inputText=${inputText} ?: #{pdfPrompt}, remoteCall=${remoteCall} ?: 'true', notRequired=${notRequired} ?: false"> <th:block th:fragment="fileSelector(name, multiple)" th:with="accept=${accept} ?: '*/*', inputText=${inputText} ?: #{pdfPrompt}, remoteCall=${remoteCall} ?: true, notRequired=${notRequired} ?: false">
<script th:inline="javascript"> <script th:inline="javascript">
const pdfPasswordPrompt =/*[[#{error.pdfPassword}]]*/ ''; const pdfPasswordPrompt =/*[[#{error.pdfPassword}]]*/ '';
const multiple = [[${multiple}]] || false;
const remoteCall = [[${remoteCall}]] || true;
</script> </script>
<script src="js/downloader.js"></script> <script src="js/downloader.js"></script>

View file

@ -130,12 +130,13 @@
// When zoomed out to less than 100%, for some very strange reason, // When zoomed out to less than 100%, for some very strange reason,
// some browsers report devicePixelRatio as less than 1 // some browsers report devicePixelRatio as less than 1
// and only part of the canvas is cleared then. // and only part of the canvas is cleared then.
var ratio = Math.max(window.devicePixelRatio || 1, 1); var ratio = Math.max(window.devicePixelRatio || 1, 1);
var additionalFactor = 10;
signaturePadCanvas.width = signaturePadCanvas.offsetWidth * ratio * additionalFactor;
signaturePadCanvas.height = signaturePadCanvas.offsetHeight * ratio * additionalFactor;
signaturePadCanvas.getContext("2d").scale(ratio * additionalFactor, ratio * additionalFactor);
// This part causes the canvas to be cleared
signaturePadCanvas.width = signaturePadCanvas.offsetWidth * ratio;
signaturePadCanvas.height = signaturePadCanvas.offsetHeight * ratio;
signaturePadCanvas.getContext("2d").scale(ratio, ratio);
// This library does not listen for canvas changes, so after the canvas is automatically // This library does not listen for canvas changes, so after the canvas is automatically
// cleared by the browser, SignaturePad#isEmpty might still return false, even though the // cleared by the browser, SignaturePad#isEmpty might still return false, even though the