Compare commits
175 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c4c22e861 | ||
|
|
00e27d9327 | ||
|
|
f082278041 | ||
|
|
09dde64c57 | ||
|
|
b52a6357f6 | ||
|
|
f14a566d06 | ||
|
|
b352ec6888 | ||
|
|
4ec1bad03d | ||
|
|
f20bbc119d | ||
|
|
8555c3d422 | ||
|
|
71f9d03b19 | ||
|
|
0b31379078 | ||
|
|
29c204b2c2 | ||
|
|
657e881963 | ||
|
|
ef6bdc70a4 | ||
|
|
e4a36115a2 | ||
|
|
325f86832c | ||
|
|
e3dbdd6b09 | ||
|
|
919041e879 | ||
|
|
182231a183 | ||
|
|
46d4ae8fc5 | ||
|
|
73ab1936a3 | ||
|
|
59c72527b5 | ||
|
|
5ea3bcc1dd | ||
|
|
c140052822 | ||
|
|
f7832774d9 | ||
|
|
279d25c03a | ||
|
|
f1984047a8 | ||
|
|
eae7c1bd60 | ||
|
|
d7f592ebda | ||
|
|
1798ce002a | ||
|
|
57a0cca595 | ||
|
|
b26fbd7693 | ||
|
|
43b0e25bdb | ||
|
|
3377af1305 | ||
|
|
c81c1006b7 | ||
|
|
f313857f96 | ||
|
|
d5fbe02149 | ||
|
|
159cee0b39 | ||
|
|
5da4dd6cca | ||
|
|
e9daf05f16 | ||
|
|
a12643194a | ||
|
|
25d8fc08f7 | ||
|
|
a72378dd4d | ||
|
|
9aed70408b | ||
|
|
5ae2c71c3a | ||
|
|
4edce515b8 | ||
|
|
67ff664eb8 | ||
|
|
71c1a4f102 | ||
|
|
ba4ba1b9fc | ||
|
|
59f10f06ca | ||
|
|
f7953cbc37 | ||
|
|
9a74e81754 | ||
|
|
420e4b6766 | ||
|
|
aed48ffc93 | ||
|
|
0cebe69ff8 | ||
|
|
e5990dba81 | ||
|
|
c9b0d01250 | ||
|
|
4918ed3f3c | ||
|
|
b176ce4251 | ||
|
|
518ff5409e | ||
|
|
803bd3c5b2 | ||
|
|
03d4e73304 | ||
|
|
55a820b09f | ||
|
|
f2a65dc360 | ||
|
|
7b4a889ea7 | ||
|
|
f627d251c3 | ||
|
|
d5b7125415 | ||
|
|
67dd3cf0e3 | ||
|
|
b8b62bb5af | ||
|
|
b4a9d1ac18 | ||
|
|
8aae651c2c | ||
|
|
fc9465b324 | ||
|
|
579a50be2c | ||
|
|
9c5b967e4c | ||
|
|
d41deb729b | ||
|
|
a93a89f3f0 | ||
|
|
11d642a25f | ||
|
|
67448498ea | ||
|
|
489b8da713 | ||
|
|
728d4d0fa8 | ||
|
|
e70f4ff3a6 | ||
|
|
04032c0dfe | ||
|
|
ecba6461df | ||
|
|
433ba6c250 | ||
|
|
ff6c55d1d0 | ||
|
|
d9f8facf2e | ||
|
|
6bd3e5cc8f | ||
|
|
936fb5ae45 | ||
|
|
8e661e1260 | ||
|
|
987d9b0502 | ||
|
|
f6a9169446 | ||
|
|
d5c1c43eb1 | ||
|
|
20c74dac60 | ||
|
|
30161275a3 | ||
|
|
7e9479806e | ||
|
|
39b9ea9f1d | ||
|
|
5a9165d7c6 | ||
|
|
4f851156b7 | ||
|
|
b8fa278173 | ||
|
|
2cfb344e13 | ||
|
|
1d2bf92abe | ||
|
|
cefcda9f40 | ||
|
|
a4bc67ff8e | ||
|
|
48b3dea256 | ||
|
|
1f5231d905 | ||
|
|
c526e18992 | ||
|
|
4594765cbd | ||
|
|
e2a787e519 | ||
|
|
45b3e0aa6a | ||
|
|
7bdb2615d4 | ||
|
|
019a502490 | ||
|
|
6793fd5bc7 | ||
|
|
8ac5cf759e | ||
|
|
19880567ba | ||
|
|
5c5a3fefc1 | ||
|
|
90057828a5 | ||
|
|
7cfc3a09a2 | ||
|
|
b8bbee27f8 | ||
|
|
8e5c665e49 | ||
|
|
7b1e6fb953 | ||
|
|
79936e69c5 | ||
|
|
a19cd327f3 | ||
|
|
5c831c156b | ||
|
|
602df08df5 | ||
|
|
3b8d06a9e3 | ||
|
|
5fd43b50e0 | ||
|
|
15d39413f3 | ||
|
|
5e01946981 | ||
|
|
576d11f09a | ||
|
|
a43c296eef | ||
|
|
6015591e34 | ||
|
|
6f5f031b24 | ||
|
|
1499e78795 | ||
|
|
1b45ab7222 | ||
|
|
005b158ad3 | ||
|
|
26d003e840 | ||
|
|
192fb39302 | ||
|
|
1650dfcc29 | ||
|
|
fda83c4c1d | ||
|
|
1a6ebbb8e5 | ||
|
|
ea1f8912b8 | ||
|
|
a5885d2628 | ||
|
|
716d4c6f28 | ||
|
|
b3a36c82bb | ||
|
|
75fff1d52f | ||
|
|
2d88987cb3 | ||
|
|
8bbbdbd359 | ||
|
|
8a2aa44de8 | ||
|
|
3715c555d3 | ||
|
|
5e4de6cc5f | ||
|
|
4cadfc64f6 | ||
|
|
a3f0d47cad | ||
|
|
bc55b5fdda | ||
|
|
43474712eb | ||
|
|
bf48cbb89c | ||
|
|
c50d8e216a | ||
|
|
8c160bcddf | ||
|
|
6fd6aa2733 | ||
|
|
d7431c459d | ||
|
|
464a11cd69 | ||
|
|
154535a7b1 | ||
|
|
f379a759bb | ||
|
|
8cbd7eafb8 | ||
|
|
6fb304d010 | ||
|
|
089b2290bd | ||
|
|
c4e5bfdabb | ||
|
|
9d5cb104c3 | ||
|
|
d577b8b34e | ||
|
|
6219cd1d86 | ||
|
|
dfd1ac7e99 | ||
|
|
e3838b291f | ||
|
|
04a073c7cf | ||
|
|
04d5c60957 | ||
|
|
2be6cad7e1 |
53
.github/workflows/push-docker.yml
vendored
53
.github/workflows/push-docker.yml
vendored
@@ -8,7 +8,6 @@ on:
|
||||
- main
|
||||
jobs:
|
||||
push:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -46,13 +45,17 @@ jobs:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ github.token }}
|
||||
|
||||
- name: Convert repository owner to lowercase
|
||||
id: repoowner
|
||||
run: echo "::set-output name=lowercase::$(echo ${{ github.repository_owner }} | awk '{print tolower($0)}')"
|
||||
|
||||
- name: Generate tags
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4.4.0
|
||||
with:
|
||||
images: |
|
||||
${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
|
||||
ghcr.io/${{ github.repository_owner }}/s-pdf
|
||||
ghcr.io/${{ steps.repoowner.outputs.lowercase }}/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' }}
|
||||
@@ -76,27 +79,27 @@ jobs:
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
platforms: linux/amd64,linux/arm64/v8
|
||||
|
||||
- name: Generate tags
|
||||
|
||||
|
||||
- name: Generate tags ultra-lite
|
||||
id: meta2
|
||||
uses: docker/metadata-action@v4.4.0
|
||||
if: github.ref != 'refs/heads/main'
|
||||
with:
|
||||
images: |
|
||||
${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
|
||||
ghcr.io/${{ github.repository_owner }}/s-pdf
|
||||
ghcr.io/${{ steps.repoowner.outputs.lowercase }}/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' }}
|
||||
type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-ultra-lite,enable=${{ github.ref == 'refs/heads/master' }}
|
||||
type=raw,value=latest-ultra-lite,enable=${{ github.ref == 'refs/heads/master' }}
|
||||
|
||||
- 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
|
||||
- name: Build and push Dockerfile-ultra-lite
|
||||
uses: docker/build-push-action@v4.0.0
|
||||
if: github.ref != 'refs/heads/main'
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile-ultralite
|
||||
file: ./Dockerfile-ultra-lite
|
||||
push: true
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
@@ -105,3 +108,29 @@ jobs:
|
||||
platforms: linux/amd64,linux/arm64/v8
|
||||
|
||||
|
||||
|
||||
- name: Generate tags lite
|
||||
id: meta3
|
||||
uses: docker/metadata-action@v4.4.0
|
||||
if: github.ref != 'refs/heads/main'
|
||||
with:
|
||||
images: |
|
||||
${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
|
||||
ghcr.io/${{ steps.repoowner.outputs.lowercase }}/s-pdf
|
||||
tags: |
|
||||
type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-lite,enable=${{ github.ref == 'refs/heads/master' }}
|
||||
type=raw,value=latest-lite,enable=${{ github.ref == 'refs/heads/master' }}
|
||||
|
||||
|
||||
- name: Build and push Dockerfile-lite
|
||||
uses: docker/build-push-action@v4.0.0
|
||||
if: github.ref != 'refs/heads/main'
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile-lite
|
||||
push: true
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
tags: ${{ steps.meta3.outputs.tags }}
|
||||
labels: ${{ steps.meta3.outputs.labels }}
|
||||
platforms: linux/amd64,linux/arm64/v8
|
||||
|
||||
45
.github/workflows/releaseArtifacts.yml
vendored
Normal file
45
.github/workflows/releaseArtifacts.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: Release Artifacts
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
jobs:
|
||||
push:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.5.2
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3.11.0
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Generate jar
|
||||
run: ./gradlew clean createExe
|
||||
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ./build/launch4j/Stirling-PDF.exe
|
||||
asset_name: Stirling-PDF.exe
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
||||
- name: Get version number
|
||||
id: versionNumber
|
||||
run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"
|
||||
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ./build/libs/Stirling-PDF-${{ steps.versionNumber.outputs.versionNumber }}.jar
|
||||
asset_name: Stirling-PDF.jar
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
||||
|
||||
37
.github/workflows/swagger.yml
vendored
Normal file
37
.github/workflows/swagger.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Update Swagger
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
push:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v3.5.2
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3.11.0
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Generate Swagger documentation
|
||||
run: ./gradlew generateOpenApiDocs
|
||||
|
||||
- name: Upload Swagger Documentation to SwaggerHub
|
||||
run: ./gradlew swaggerhubUpload
|
||||
env:
|
||||
SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_API_KEY }}
|
||||
|
||||
- name: Set API version as published and default on SwaggerHub
|
||||
run: |
|
||||
curl -X PUT -H "Authorization: ${SWAGGERHUB_API_KEY}" "https://api.swaggerhub.com/apis/Frooodle/Stirling-PDF/${{ steps.versionNumber.outputs.versionNumber }}/settings/lifecycle" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"published\":true,\"default\":true}"
|
||||
env:
|
||||
SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_API_KEY }}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,6 +14,7 @@ local.properties
|
||||
.recommenders
|
||||
.classpath
|
||||
.project
|
||||
version.properties
|
||||
|
||||
# Gradle
|
||||
.gradle
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
# Build jbig2enc in a separate stage
|
||||
FROM frooodle/stirling-pdf-base:beta3
|
||||
FROM frooodle/stirling-pdf-base:latest
|
||||
|
||||
# Create scripts folder and copy local scripts
|
||||
RUN mkdir /scripts
|
||||
COPY ./scripts/* /scripts/
|
||||
|
||||
#Install fonts
|
||||
RUN mkdir /usr/share/fonts/opentype/noto/
|
||||
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
||||
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
|
||||
RUN fc-cache -f -v
|
||||
|
||||
# Copy the application JAR file
|
||||
COPY build/libs/*.jar app.jar
|
||||
|
||||
|
||||
23
Dockerfile-lite
Normal file
23
Dockerfile-lite
Normal 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"]
|
||||
@@ -1,5 +1,5 @@
|
||||
# Build jbig2enc in a separate stage
|
||||
FROM openjdk:17-jdk-slim
|
||||
FROM bellsoft/liberica-openjdk-alpine:17
|
||||
|
||||
# Copy the application JAR file
|
||||
COPY build/libs/*.jar app.jar
|
||||
@@ -8,7 +8,7 @@ COPY build/libs/*.jar app.jar
|
||||
EXPOSE 8080
|
||||
|
||||
# Set environment variables
|
||||
ENV GROUPS_TO_REMOVE=LibreOffice,CLI
|
||||
ENV GROUPS_TO_REMOVE=CLI
|
||||
|
||||
# Run the application
|
||||
CMD ["java", "-jar", "/app.jar"]
|
||||
@@ -1,5 +1,5 @@
|
||||
# Main stage
|
||||
FROM openjdk:17-jdk-slim AS base
|
||||
FROM bellsoft/liberica-openjdk-debian:17 AS base
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
libreoffice-core-nogui \
|
||||
|
||||
35
Endpoint-groups.md
Normal file
35
Endpoint-groups.md
Normal file
@@ -0,0 +1,35 @@
|
||||
| Operation | PageOps | Convert | Security | Other | CLI | Python | OpenCV | LibreOffice | OCRmyPDF | Java | Javascript |
|
||||
|---------------------|---------|---------|----------|-------|------|--------|--------|-------------|----------|----------|------------|
|
||||
| merge-pdfs | ✔️ | | | | | | | | | ✔️ | |
|
||||
| multi-page-layout | ✔️ | | | | | | | | | ✔️ | |
|
||||
| pdf-organizer | ✔️ | | | | | | | | | ✔️ | ✔️ |
|
||||
| remove-pages | ✔️ | | | | | | | | | ✔️ | |
|
||||
| rotate-pdf | ✔️ | | | | | | | | | ✔️ | |
|
||||
| scale-pages | ✔️ | | | | | | | | | ✔️ | |
|
||||
| split-pdfs | ✔️ | | | | | | | | | ✔️ | |
|
||||
| file-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||
| img-to-pdf | | ✔️ | | | | | | | | ✔️ | |
|
||||
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||
| pdf-to-img | | ✔️ | | | | | | | | ✔️ | |
|
||||
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
|
||||
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||
| pdf-to-text | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||
| pdf-to-word | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||
| pdf-to-xml | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||
| xlsx-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||
| add-password | | | ✔️ | | | | | | | ✔️ | |
|
||||
| add-watermark | | | ✔️ | | | | | | | ✔️ | |
|
||||
| cert-sign | | | ✔️ | | | | | | | ✔️ | |
|
||||
| change-permissions | | | ✔️ | | | | | | | ✔️ | |
|
||||
| remove-password | | | ✔️ | | | | | | | ✔️ | |
|
||||
| add-image | | | | ✔️ | | | | | | ✔️ | |
|
||||
| change-metadata | | | | ✔️ | | | | | | ✔️ | |
|
||||
| compare | | | | ✔️ | | | | | | | ✔️ |
|
||||
| compress-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
|
||||
| extract-image-scans | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
|
||||
| extract-images | | | | ✔️ | | | | | | ✔️ | |
|
||||
| flatten | | | | ✔️ | | | | | | | |
|
||||
| ocr-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
|
||||
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
|
||||
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
|
||||
| sign | | | | ✔️ | | | | | | | ✔️ |
|
||||
@@ -123,7 +123,7 @@ This folder is required for the python scripts using OpenCV
|
||||
|
||||
```bash
|
||||
sudo mkdir /opt/Stirling-PDF &&\
|
||||
sudo mv /build/libs/S-PDF-*.jar /opt/Stirling-PDF/ &&\
|
||||
sudo mv ./build/libs/Stirling-PDF-*.jar /opt/Stirling-PDF/ &&\
|
||||
sudo mv scripts /opt/Stirling-PDF/ &&\
|
||||
echo "Scripts installed."
|
||||
```
|
||||
|
||||
24
README.md
24
README.md
@@ -10,7 +10,7 @@
|
||||
|
||||
This is a powerful locally hosted web based PDF manipulation tool using docker that allows you to perform various operations on PDF files, such as splitting merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application started as a 100% ChatGPT-made application and has evolved to include a wide range of features to handle all your PDF needs.
|
||||
|
||||
Stirling PDF makes no outbount calls for any record keeping or tracking.
|
||||
Stirling PDF makes no outbound calls for any record keeping or tracking.
|
||||
|
||||
All files and PDFs are either purely client side, in server memory only during the execution of the task or within a temporay file only for execution of the task.
|
||||
Any file which has been downloaded by the user will have already been deleted from the server by that time.
|
||||
@@ -21,7 +21,7 @@ Feel free to request any features or bug fixes either in github issues or our [D
|
||||

|
||||
|
||||
## Features
|
||||
- Full intractable GUI for merging/splitting/rotating/moving PDFs and their pages.
|
||||
- Full interactive GUI for merging/splitting/rotating/moving PDFs and their pages.
|
||||
- Split PDFs into multiple files at specified page numbers or extract all pages as individual files.
|
||||
- Merge multiple PDFs together into a single resultant file
|
||||
- Convert PDFs to and from images
|
||||
@@ -53,6 +53,7 @@ Hosted instance/demo of the app can be seen [here](https://pdf.adminforge.de/) h
|
||||
## Technologies used
|
||||
- Spring Boot + Thymeleaf
|
||||
- PDFBox
|
||||
- IText7
|
||||
- [LibreOffice](https://www.libreoffice.org/discover/libreoffice/) for advanced conversions
|
||||
- [OcrMyPdf](https://github.com/ocrmypdf/OCRmyPDF)
|
||||
- HTML, CSS, JavaScript
|
||||
@@ -68,13 +69,20 @@ Please view https://github.com/Frooodle/Stirling-PDF/blob/main/LocalRunGuide.md
|
||||
### Docker
|
||||
https://hub.docker.com/r/frooodle/s-pdf
|
||||
|
||||
Stirling PDF has 3 different versions, a Full version, Lite and ultra-Lite. Depending on the types of features you use you may want a smaller image to save on space.
|
||||
To see what the different versions offer please look at our [version mapping](https://github.com/Frooodle/Stirling-PDF/blob/main/Version-groups.md)
|
||||
For people that dont mind about space optimisation just use latest tag.
|
||||

|
||||

|
||||

|
||||
|
||||
Docker Run
|
||||
```
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
-v /location/of/trainingData:/usr/share/tesseract-ocr/4.00/tessdata \
|
||||
--name stirling-pdf \
|
||||
frooodle/s-pdf
|
||||
frooodle/s-pdf:latest
|
||||
|
||||
|
||||
Can also add these for customisation but are not required
|
||||
@@ -90,7 +98,7 @@ Docker Compose
|
||||
version: '3.3'
|
||||
services:
|
||||
stirling-pdf:
|
||||
image: frooodle/s-pdf
|
||||
image: frooodle/s-pdf:latest
|
||||
ports:
|
||||
- '8080:8080'
|
||||
volumes:
|
||||
@@ -111,7 +119,7 @@ services:
|
||||
Please view https://github.com/Frooodle/Stirling-PDF/blob/main/HowToUseOCR.md
|
||||
|
||||
## Want to add your own language?
|
||||
Stirling PDF currently supports
|
||||
Stirling PDF currently supports 16!
|
||||
- English (English) (en_GB)
|
||||
- Arabic (العربية) (ar_AR)
|
||||
- German (Deutsch) (de_DE)
|
||||
@@ -122,6 +130,12 @@ Stirling PDF currently supports
|
||||
- Italian (Italiano) (it_IT)
|
||||
- Swedish (Svenska) (sv_SE)
|
||||
- Polish (Polski) (pl_PL)
|
||||
- Romanian (Română) (ro_RO)
|
||||
- Korean (한국어) (ko_KR)
|
||||
- Portuguese Brazilian (Português) (pt_BR)
|
||||
- Russian (Русский) (ru_RU)
|
||||
- Basque (Euskara) (eu_ES)
|
||||
- Japanese (日本語) (ja_JP)
|
||||
|
||||
If you want to add your own language to Stirling-PDF please refer
|
||||
https://github.com/Frooodle/Stirling-PDF/blob/main/HowToAddNewLanguage.md
|
||||
|
||||
48
Version-groups.md
Normal file
48
Version-groups.md
Normal file
@@ -0,0 +1,48 @@
|
||||
|Technology | Ultra-Lite | Lite | Full |
|
||||
|----------------|:----------:|:----:|:----:|
|
||||
| Java | ✔️ | ✔️ | ✔️ |
|
||||
| JavaScript | ✔️ | ✔️ | ✔️ |
|
||||
| Libre | | ✔️ | ✔️ |
|
||||
| Python | | | ✔️ |
|
||||
| OpenCV | | | ✔️ |
|
||||
| OCRmyPDF | | | ✔️ |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Operation | Ultra-Lite | Lite | Full
|
||||
--------------------|------------|------|-----
|
||||
add-password | ✔️ | ✔️ | ✔️
|
||||
add-watermark | ✔️ | ✔️ | ✔️
|
||||
cert-sign | ✔️ | ✔️ | ✔️
|
||||
change-metadata | ✔️ | ✔️ | ✔️
|
||||
change-permissions | ✔️ | ✔️ | ✔️
|
||||
compare | ✔️ | ✔️ | ✔️
|
||||
extract-images | ✔️ | ✔️ | ✔️
|
||||
flatten | ✔️ | ✔️ | ✔️
|
||||
img-to-pdf | ✔️ | ✔️ | ✔️
|
||||
merge-pdfs | ✔️ | ✔️ | ✔️
|
||||
multi-page-layout | ✔️ | ✔️ | ✔️
|
||||
pdf-organizer | ✔️ | ✔️ | ✔️
|
||||
pdf-to-img | ✔️ | ✔️ | ✔️
|
||||
remove-pages | ✔️ | ✔️ | ✔️
|
||||
remove-password | ✔️ | ✔️ | ✔️
|
||||
rotate-pdf | ✔️ | ✔️ | ✔️
|
||||
scale-pages | ✔️ | ✔️ | ✔️
|
||||
sign | ✔️ | ✔️ | ✔️
|
||||
split-pdfs | ✔️ | ✔️ | ✔️
|
||||
add-image | ✔️ | ✔️ | ✔️
|
||||
file-to-pdf | | ✔️ | ✔️
|
||||
pdf-to-html | | ✔️ | ✔️
|
||||
pdf-to-presentation | | ✔️ | ✔️
|
||||
pdf-to-text | | ✔️ | ✔️
|
||||
pdf-to-word | | ✔️ | ✔️
|
||||
pdf-to-xml | | ✔️ | ✔️
|
||||
repair | | ✔️ | ✔️
|
||||
xlsx-to-pdf | | ✔️ | ✔️
|
||||
compress-pdf | | | ✔️
|
||||
extract-image-scans | | | ✔️
|
||||
ocr-pdf | | | ✔️
|
||||
pdf-to-pdfa | | | ✔️
|
||||
remove-blanks | | | ✔️
|
||||
63
build.gradle
63
build.gradle
@@ -1,24 +1,56 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '3.0.6'
|
||||
id 'org.springframework.boot' version '3.1.1'
|
||||
id 'io.spring.dependency-management' version '1.1.0'
|
||||
id 'org.springdoc.openapi-gradle-plugin' version '1.6.0'
|
||||
id "io.swagger.swaggerhub" version "1.2.0"
|
||||
id 'edu.sc.seis.launch4j' version '3.0.3'
|
||||
}
|
||||
|
||||
group = 'stirling.software'
|
||||
version = '0.9.0'
|
||||
version = '0.10.3'
|
||||
sourceCompatibility = '17'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
openApi {
|
||||
apiDocsUrl = "http://localhost:8080/v3/api-docs"
|
||||
outputDir = file("$projectDir")
|
||||
outputFileName = "SwaggerDoc.json"
|
||||
}
|
||||
|
||||
|
||||
launch4j {
|
||||
icon = "${projectDir}/src/main/resources/static/favicon.ico"
|
||||
|
||||
outfile="Stirling-PDF.exe"
|
||||
headerType="console"
|
||||
jarTask = tasks.bootJar
|
||||
|
||||
errTitle="Encountered error, Do you have Java 17?"
|
||||
downloadUrl="https://download.oracle.com/java/17/latest/jdk-17_windows-x64_bin.exe"
|
||||
variables=["BROWSER_OPEN=true"]
|
||||
jreMinVersion="17"
|
||||
|
||||
mutexName="Stirling-PDF"
|
||||
windowTitle="Stirling-PDF"
|
||||
|
||||
messagesStartupError="An error occurred while starting Stirling-PDF"
|
||||
//messagesJreNotFoundError="This application requires a Java Runtime Environment, Please download Java 17."
|
||||
messagesJreVersionError="You are running the wrong version of Java, Please download Java 17."
|
||||
messagesLauncherError="Java is corrupted. Please uninstall and then install Java 17."
|
||||
messagesInstanceAlreadyExists="Stirling-PDF is already running."
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web:3.0.6'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.0.6'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test:3.0.6'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web:3.1.0'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.1.1'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.0'
|
||||
// https://mvnrepository.com/artifact/org.apache.pdfbox/jbig2-imageio
|
||||
implementation group: 'org.apache.pdfbox', name: 'jbig2-imageio', version: '3.0.4'
|
||||
implementation 'commons-io:commons-io:2.11.0'
|
||||
implementation 'commons-io:commons-io:2.13.0'
|
||||
|
||||
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
|
||||
|
||||
@@ -34,6 +66,25 @@ dependencies {
|
||||
|
||||
}
|
||||
|
||||
task writeVersion {
|
||||
def propsFile = file('src/main/resources/version.properties')
|
||||
def props = new Properties()
|
||||
props.setProperty('version', version)
|
||||
props.store(propsFile.newWriter(), null)
|
||||
}
|
||||
|
||||
swaggerhubUpload {
|
||||
//dependsOn generateOpenApiDocs // Depends on your task generating Swagger docs
|
||||
api 'Stirling-PDF' // The name of your API on SwaggerHub
|
||||
owner 'Frooodle' // Your SwaggerHub username (or organization name)
|
||||
version project.version // The version of your API
|
||||
inputFile './SwaggerDoc.json' // The path to your Swagger docs
|
||||
token "${System.getenv('SWAGGERHUB_API_KEY')}" // Your SwaggerHub API key, passed as an environment variable
|
||||
oas '3.0.0' // The version of the OpenAPI Specification you're using
|
||||
}
|
||||
|
||||
|
||||
|
||||
jar {
|
||||
enabled = false
|
||||
manifest {
|
||||
|
||||
32
groups.md
32
groups.md
@@ -1,32 +0,0 @@
|
||||
Operation | PageOps | Convert | Security | Other | CLI | Python | OpenCV | LibreOffice | OCRmyPDF | Java | Javascript
|
||||
--------------------|---------|---------|----------|-------|------|--------|--------|-------------|--------- |-------- |-----------
|
||||
remove-pages | X | | | | | | | | | X |
|
||||
merge-pdfs | X | | | | | | | | | X |
|
||||
split-pdfs | X | | | | | | | | | X |
|
||||
pdf-organizer | X | | | | | | | | | X | X
|
||||
rotate-pdf | X | | | | | | | | | X |
|
||||
pdf-to-img | | X | | | | | | | | X |
|
||||
img-to-pdf | | X | | | | | | | | X |
|
||||
pdf-to-pdfa | | X | | | X | | | | X | |
|
||||
file-to-pdf | | X | | | X | | | X | | |
|
||||
xlsx-to-pdf | | X | | | X | | | X | | |
|
||||
pdf-to-word | | X | | | X | | | X | | |
|
||||
pdf-to-presentation | | X | | | X | | | X | | |
|
||||
pdf-to-text | | X | | | X | | | X | | |
|
||||
pdf-to-html | | X | | | X | | | X | | |
|
||||
pdf-to-xml | | X | | | X | | | X | | |
|
||||
add-password | | | X | | | | | | | X |
|
||||
remove-password | | | X | | | | | | | X |
|
||||
change-permissions | | | X | | | | | | | X |
|
||||
add-watermark | | | X | | | | | | | X |
|
||||
ocr-pdf | | | | X | X | | | | X | |
|
||||
add-image | | | | X | | | | | | X |
|
||||
compress-pdf | | | | X | X | | | | X
|
||||
extract-images | | | | X | | | | | | X |
|
||||
change-metadata | | | | X | | | | | | X |
|
||||
extract-image-scans | | | | X | X | X | X | | | |
|
||||
sign | | | | X | | | | | | | X
|
||||
flatten | | | | X | | | | | | |
|
||||
repair | | | | X | X | | | X | | |
|
||||
remove-blanks | | | | X | X | X | X | | | |
|
||||
compare | | | | X | | | | | | | X
|
||||
36
lauch4jConfig.xml
Normal file
36
lauch4jConfig.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<launch4jConfig>
|
||||
<dontWrapJar>false</dontWrapJar>
|
||||
<headerType>console</headerType>
|
||||
<jar>.\build\libs\S-PDF-0.10.1.jar</jar>
|
||||
<outfile>.\Stirling-PDF.exe</outfile>
|
||||
<errTitle>Please download Java17</errTitle>
|
||||
<cmdLine></cmdLine>
|
||||
<chdir>.</chdir>
|
||||
<priority>normal</priority>
|
||||
<downloadUrl>https://download.oracle.com/java/17/latest/jdk-17_windows-x64_bin.exe</downloadUrl>
|
||||
<supportUrl></supportUrl>
|
||||
<stayAlive>false</stayAlive>
|
||||
<restartOnCrash>false</restartOnCrash>
|
||||
<manifest></manifest>
|
||||
<icon>./src/main/resources/static/favicon.ico</icon>
|
||||
<var>BROWSER_OPEN=true</var>
|
||||
<singleInstance>
|
||||
<mutexName>Stirling-PDF</mutexName>
|
||||
<windowTitle>Stirling-PDF</windowTitle>
|
||||
</singleInstance>
|
||||
<jre>
|
||||
<path>%JAVA_HOME%;%PATH%</path>
|
||||
<requiresJdk>false</requiresJdk>
|
||||
<requires64Bit>false</requires64Bit>
|
||||
<minVersion>17</minVersion>
|
||||
<maxVersion></maxVersion>
|
||||
</jre>
|
||||
<messages>
|
||||
<startupErr>An error occurred while starting Stirling-PDF</startupErr>
|
||||
<jreNotFoundErr>This application requires a Java Runtime Environment, Please download Java 17.</jreNotFoundErr>
|
||||
<jreVersionErr>You are running the wrong version of Java, Please download Java 17.</jreVersionErr>
|
||||
<launcherErr>Java is corrupted. Please uninstall and then install Java 17.</launcherErr>
|
||||
<instanceAlreadyExistsMsg>Stirling-PDF is already running.</instanceAlreadyExistsMsg>
|
||||
</messages>
|
||||
</launch4jConfig>
|
||||
@@ -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)
|
||||
|
||||
_, thresholded_image = cv2.threshold(blurred_image, white_value - threshold, white_value, cv2.THRESH_BINARY)
|
||||
|
||||
|
||||
# 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
|
||||
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}")
|
||||
return white_pixel_percentage > white_percent
|
||||
return True
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import argparse
|
||||
import sys
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -36,33 +37,21 @@ def estimate_background_color(image, sample_points=5):
|
||||
|
||||
return np.median(colors, axis=0)
|
||||
|
||||
def auto_rotate(image, angle_threshold=10):
|
||||
def auto_rotate(image, angle_threshold=1):
|
||||
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
||||
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
|
||||
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
||||
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
|
||||
lines = cv2.HoughLines(edges, 1, np.pi / 180, 200)
|
||||
|
||||
if len(contours) == 0:
|
||||
if lines is None:
|
||||
return image
|
||||
|
||||
largest_contour = max(contours, key=cv2.contourArea)
|
||||
mu = cv2.moments(largest_contour)
|
||||
# compute the median angle of the lines
|
||||
angles = []
|
||||
for rho, theta in lines[:, 0]:
|
||||
angles.append((theta * 180) / np.pi - 90)
|
||||
|
||||
if mu["m00"] == 0:
|
||||
return image
|
||||
angle = np.median(angles)
|
||||
|
||||
x_centroid = int(mu["m10"] / mu["m00"])
|
||||
y_centroid = int(mu["m01"] / mu["m00"])
|
||||
|
||||
coords = np.column_stack(np.where(binary > 0))
|
||||
u, _, vt = np.linalg.svd(coords - np.array([[y_centroid, x_centroid]]), full_matrices=False)
|
||||
|
||||
angle = np.arctan2(u[1, 0], u[0, 0]) * 180 / np.pi
|
||||
|
||||
if angle < -45:
|
||||
angle = -(90 + angle)
|
||||
else:
|
||||
angle = -angle
|
||||
|
||||
if abs(angle) < angle_threshold:
|
||||
return image
|
||||
|
||||
@@ -73,6 +62,7 @@ def auto_rotate(image, angle_threshold=10):
|
||||
|
||||
|
||||
|
||||
|
||||
def crop_borders(image, border_color, tolerance=30):
|
||||
mask = cv2.inRange(image, border_color - tolerance, border_color + tolerance)
|
||||
|
||||
@@ -112,23 +102,15 @@ def split_photos(input_file, output_directory, tolerance=30, min_area=10000, min
|
||||
print(f"Saved {output_path}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python3 split_photos.py <input_file> <output_directory> [tolerance] [min_area] [min_contour_area] [angle_threshold] [border_size]")
|
||||
print("\nParameters:")
|
||||
print(" <input_file> - The input scanned image containing multiple photos.")
|
||||
print(" <output_directory> - The directory where the result images should be placed.")
|
||||
print(" [tolerance] - Optional. Determines the range of color variation around the estimated background color (default: 30).")
|
||||
print(" [min_area] - Optional. Sets the minimum area threshold for a photo (default: 10000).")
|
||||
print(" [min_contour_area] - Optional. Sets the minimum contour area threshold for a photo (default: 500).")
|
||||
print(" [angle_threshold] - Optional. Sets the minimum absolute angle required for the image to be rotated (default: 10).")
|
||||
print(" [border_size] - Optional. Sets the size of the border added and removed to prevent white borders in the output (default: 0).")
|
||||
sys.exit(1)
|
||||
parser = argparse.ArgumentParser(description="Split photos in an image")
|
||||
parser.add_argument("input_file", help="The input scanned image containing multiple photos.")
|
||||
parser.add_argument("output_directory", help="The directory where the result images should be placed.")
|
||||
parser.add_argument("--tolerance", type=int, default=30, help="Determines the range of color variation around the estimated background color (default: 30).")
|
||||
parser.add_argument("--min_area", type=int, default=10000, help="Sets the minimum area threshold for a photo (default: 10000).")
|
||||
parser.add_argument("--min_contour_area", type=int, default=500, help="Sets the minimum contour area threshold for a photo (default: 500).")
|
||||
parser.add_argument("--angle_threshold", type=int, default=10, help="Sets the minimum absolute angle required for the image to be rotated (default: 10).")
|
||||
parser.add_argument("--border_size", type=int, default=0, help="Sets the size of the border added and removed to prevent white borders in the output (default: 0).")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
input_file = sys.argv[1]
|
||||
output_directory = sys.argv[2]
|
||||
tolerance = int(sys.argv[3]) if len(sys.argv) > 3 else 20
|
||||
min_area = int(sys.argv[4]) if len(sys.argv) > 4 else 8000
|
||||
min_contour_area = int(sys.argv[5]) if len(sys.argv) > 5 else 500
|
||||
angle_threshold = int(sys.argv[6]) if len(sys.argv) > 6 else 60
|
||||
border_size = int(sys.argv[7]) if len(sys.argv) > 7 else 0
|
||||
split_photos(input_file, output_directory, tolerance=tolerance, min_area=min_area, min_contour_area=min_contour_area, angle_threshold=angle_threshold, border_size=border_size)
|
||||
split_photos(args.input_file, args.output_directory, tolerance=args.tolerance, min_area=args.min_area, min_contour_area=args.min_contour_area, angle_threshold=args.angle_threshold, border_size=args.border_size)
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = 'S-PDF'
|
||||
rootProject.name = 'Stirling-PDF'
|
||||
|
||||
@@ -1,11 +1,63 @@
|
||||
package stirling.software.SPDF;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
@SpringBootApplication
|
||||
//@EnableScheduling
|
||||
public class SPdfApplication {
|
||||
|
||||
@Autowired
|
||||
private Environment env;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// Check if the BROWSER_OPEN environment variable is set to true
|
||||
String browserOpenEnv = env.getProperty("BROWSER_OPEN");
|
||||
boolean browserOpen = browserOpenEnv != null && browserOpenEnv.equalsIgnoreCase("true");
|
||||
|
||||
if (browserOpen) {
|
||||
try {
|
||||
String port = env.getProperty("local.server.port");
|
||||
if(port == null || port.length() == 0) {
|
||||
port="8080";
|
||||
}
|
||||
String url = "http://localhost:" + port;
|
||||
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
Runtime rt = Runtime.getRuntime();
|
||||
if (os.contains("win")) {
|
||||
// For Windows
|
||||
rt.exec("rundll32 url.dll,FileProtocolHandler " + url);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SPdfApplication.class, args);
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println("Stirling-PDF Started.");
|
||||
|
||||
String port = System.getProperty("local.server.port");
|
||||
if(port == null || port.length() == 0) {
|
||||
port="8080";
|
||||
}
|
||||
String url = "http://localhost:" + port;
|
||||
System.out.println("Navigate to " + url);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@ public class AppConfig {
|
||||
@Bean(name = "appVersion")
|
||||
public String appVersion() {
|
||||
String version = getClass().getPackage().getImplementationVersion();
|
||||
return (version != null) ? version : "0.3.3";
|
||||
return (version != null) ? version : "0.0.0";
|
||||
}
|
||||
|
||||
@Bean(name = "homeText")
|
||||
|
||||
@@ -39,10 +39,17 @@ public class Beans implements WebMvcConfigurer {
|
||||
Locale tempLocale = Locale.forLanguageTag(appLocaleEnv);
|
||||
String tempLanguageTag = tempLocale.toLanguageTag();
|
||||
|
||||
if (appLocaleEnv.equalsIgnoreCase(tempLanguageTag)) {
|
||||
if (appLocaleEnv.equalsIgnoreCase(tempLanguageTag)) {
|
||||
defaultLocale = tempLocale;
|
||||
} else {
|
||||
System.err.println("Invalid APP_LOCALE environment variable value. Falling back to default Locale.UK.");
|
||||
tempLocale = Locale.forLanguageTag(appLocaleEnv.replace("_","-"));
|
||||
tempLanguageTag = tempLocale.toLanguageTag();
|
||||
|
||||
if (appLocaleEnv.equalsIgnoreCase(tempLanguageTag)) {
|
||||
defaultLocale = tempLocale;
|
||||
} else {
|
||||
System.err.println("Invalid APP_LOCALE environment variable value. Falling back to default Locale.UK.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -7,39 +9,71 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
public class CleanUrlInterceptor implements HandlerInterceptor {
|
||||
|
||||
private static final Pattern LANG_PATTERN = Pattern.compile("&?lang=([^&]+)");
|
||||
private static final List<String> ALLOWED_PARAMS = Arrays.asList("lang", "endpoint", "endpoints");
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
String queryString = request.getQueryString();
|
||||
if (queryString != null && !queryString.isEmpty()) {
|
||||
String requestURI = request.getRequestURI();
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
String queryString = request.getQueryString();
|
||||
if (queryString != null && !queryString.isEmpty()) {
|
||||
String requestURI = request.getRequestURI();
|
||||
|
||||
// Keep the lang parameter if it exists
|
||||
Matcher langMatcher = LANG_PATTERN.matcher(queryString);
|
||||
String langQueryString = langMatcher.find() ? "lang=" + langMatcher.group(1) : "";
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
|
||||
// Check if there are any other query parameters besides the lang parameter
|
||||
String remainingQueryString = queryString.replaceAll(LANG_PATTERN.pattern(), "").replaceAll("&+", "&").replaceAll("^&|&$", "");
|
||||
// Keep only the allowed parameters
|
||||
String[] queryParameters = queryString.split("&");
|
||||
for (String param : queryParameters) {
|
||||
String[] keyValue = param.split("=");
|
||||
if (keyValue.length != 2) {
|
||||
continue;
|
||||
}
|
||||
if (ALLOWED_PARAMS.contains(keyValue[0])) {
|
||||
parameters.put(keyValue[0], keyValue[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!remainingQueryString.isEmpty()) {
|
||||
// Redirect to the URL without other query parameters
|
||||
String redirectUrl = requestURI + (langQueryString.isEmpty() ? "" : "?" + langQueryString);
|
||||
response.sendRedirect(redirectUrl);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// If there are any parameters that are not allowed
|
||||
if (parameters.size() != queryParameters.length) {
|
||||
// Construct new query string
|
||||
StringBuilder newQueryString = new StringBuilder();
|
||||
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
||||
if (newQueryString.length() > 0) {
|
||||
newQueryString.append("&");
|
||||
}
|
||||
newQueryString.append(entry.getKey()).append("=").append(entry.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
|
||||
}
|
||||
// Redirect to the URL with only allowed query parameters
|
||||
String redirectUrl = requestURI + "?" + newQueryString;
|
||||
response.sendRedirect(redirectUrl);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
||||
}
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
ModelAndView modelAndView) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
Exception ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,14 @@ public class EndpointConfiguration {
|
||||
}
|
||||
|
||||
public void enableEndpoint(String endpoint) {
|
||||
endpointStatuses.put(endpoint, true);
|
||||
endpointStatuses.put(endpoint, true);
|
||||
}
|
||||
|
||||
public void disableEndpoint(String endpoint) {
|
||||
logger.info("Disabling {}", endpoint);
|
||||
endpointStatuses.put(endpoint, false);
|
||||
if(!endpointStatuses.containsKey(endpoint) || endpointStatuses.get(endpoint) != false) {
|
||||
logger.info("Disabling {}", endpoint);
|
||||
endpointStatuses.put(endpoint, false);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEndpointEnabled(String endpoint) {
|
||||
@@ -64,7 +66,9 @@ public class EndpointConfiguration {
|
||||
addEndpointToGroup("PageOps", "split-pdfs");
|
||||
addEndpointToGroup("PageOps", "pdf-organizer");
|
||||
addEndpointToGroup("PageOps", "rotate-pdf");
|
||||
|
||||
addEndpointToGroup("PageOps", "multi-page-layout");
|
||||
addEndpointToGroup("PageOps", "scale-pages");
|
||||
|
||||
// Adding endpoints to "Convert" group
|
||||
addEndpointToGroup("Convert", "pdf-to-img");
|
||||
addEndpointToGroup("Convert", "img-to-pdf");
|
||||
@@ -82,6 +86,9 @@ public class EndpointConfiguration {
|
||||
addEndpointToGroup("Security", "remove-password");
|
||||
addEndpointToGroup("Security", "change-permissions");
|
||||
addEndpointToGroup("Security", "add-watermark");
|
||||
addEndpointToGroup("Security", "cert-sign");
|
||||
|
||||
|
||||
|
||||
// Adding endpoints to "Other" group
|
||||
addEndpointToGroup("Other", "ocr-pdf");
|
||||
@@ -158,6 +165,9 @@ public class EndpointConfiguration {
|
||||
addEndpointToGroup("Java", "add-image");
|
||||
addEndpointToGroup("Java", "extract-images");
|
||||
addEndpointToGroup("Java", "change-metadata");
|
||||
addEndpointToGroup("Java", "cert-sign");
|
||||
addEndpointToGroup("Java", "multi-page-layout");
|
||||
addEndpointToGroup("Java", "scale-pages");
|
||||
|
||||
|
||||
//Javascript
|
||||
|
||||
@@ -27,7 +27,8 @@ public class MetricsFilter extends OncePerRequestFilter {
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
|
||||
//System.out.println("uri="+uri + ", method=" + request.getMethod() );
|
||||
// Ignore static resources
|
||||
if (!(uri.startsWith("/js") || uri.startsWith("/images") || uri.endsWith(".ico") || uri.endsWith(".css") || uri.endsWith(".svg")|| uri.endsWith(".js") || uri.contains("swagger") || uri.startsWith("/api"))) {
|
||||
Counter counter = Counter.builder("http.requests")
|
||||
@@ -36,6 +37,7 @@ public class MetricsFilter extends OncePerRequestFilter {
|
||||
.register(meterRegistry);
|
||||
|
||||
counter.increment();
|
||||
//System.out.println("Counted");
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -10,13 +14,23 @@ import io.swagger.v3.oas.models.info.Info;
|
||||
@Configuration
|
||||
public class OpenApiConfig {
|
||||
|
||||
@Bean
|
||||
public OpenAPI customOpenAPI() {
|
||||
String version = getClass().getPackage().getImplementationVersion();
|
||||
version = (version != null) ? version : "1.0.0";
|
||||
|
||||
return new OpenAPI().components(new Components()).info(
|
||||
new Info().title("Stirling PDF API").version(version).description("API documentation for all Server-Side processing.\nPlease note some functionality might be UI only and missing from here."));
|
||||
}
|
||||
@Bean
|
||||
public OpenAPI customOpenAPI() {
|
||||
String version = getClass().getPackage().getImplementationVersion();
|
||||
if (version == null) {
|
||||
Properties props = new Properties();
|
||||
try (InputStream input = getClass().getClassLoader().getResourceAsStream("version.properties")) {
|
||||
props.load(input);
|
||||
version = props.getProperty("version");
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
version = "1.0.0"; // default version if all else fails
|
||||
}
|
||||
}
|
||||
|
||||
return new OpenAPI().components(new Components()).info(
|
||||
new Info().title("Stirling PDF API").version(version).description("API documentation for all Server-Side processing.\nPlease note some functionality might be UI only and missing from here."));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "General", description = "General APIs")
|
||||
public class MergeController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MergeController.class);
|
||||
@@ -47,7 +49,7 @@ public class MergeController {
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/merge-pdfs")
|
||||
@Operation(
|
||||
summary = "Merge multiple PDF files into one",
|
||||
description = "This endpoint merges multiple PDF files into a single PDF file. The merged file will contain all pages from the input files in the order they were provided."
|
||||
description = "This endpoint merges multiple PDF files into a single PDF file. The merged file will contain all pages from the input files in the order they were provided. Input:PDF Output:PDF Type:MISO"
|
||||
)
|
||||
public ResponseEntity<byte[]> mergePdfs(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@@ -65,7 +67,7 @@ public class MergeController {
|
||||
|
||||
|
||||
// Return the merged PDF as a response
|
||||
ResponseEntity<byte[]> response = PdfUtils.pdfDocToWebResponse(mergedDoc, files[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_merged.pdf");
|
||||
ResponseEntity<byte[]> response = WebResponseUtils.pdfDocToWebResponse(mergedDoc, files[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_merged.pdf");
|
||||
|
||||
for (PDDocument doc : documents) {
|
||||
// Close the document after processing
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.kernel.geom.PageSize;
|
||||
import com.itextpdf.kernel.geom.Rectangle;
|
||||
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||
import com.itextpdf.kernel.pdf.PdfPage;
|
||||
import com.itextpdf.kernel.pdf.PdfReader;
|
||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
||||
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "General", description = "General APIs")
|
||||
public class MultiPageLayoutController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MultiPageLayoutController.class);
|
||||
|
||||
@PostMapping(value = "/multi-page-layout", consumes = "multipart/form-data")
|
||||
@Operation(summary = "Merge multiple pages of a PDF document into a single page", description = "This operation takes an input PDF file and the number of pages to merge into a single sheet in the output PDF file. Input:PDF Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> mergeMultiplePagesIntoOne(
|
||||
@Parameter(description = "The input PDF file", required = true) @RequestParam("fileInput") MultipartFile file,
|
||||
@Parameter(description = "The number of pages to fit onto a single sheet in the output PDF. Acceptable values are 2, 3, 4, 9, 16.", required = true, schema = @Schema(type = "integer", allowableValues = {
|
||||
"2", "3", "4", "9", "16" })) @RequestParam("pagesPerSheet") int pagesPerSheet)
|
||||
throws IOException {
|
||||
|
||||
if (pagesPerSheet != 2 && pagesPerSheet != 3
|
||||
&& pagesPerSheet != (int) Math.sqrt(pagesPerSheet) * Math.sqrt(pagesPerSheet)) {
|
||||
throw new IllegalArgumentException("pagesPerSheet must be 2, 3 or a perfect square");
|
||||
}
|
||||
|
||||
int cols = pagesPerSheet == 2 || pagesPerSheet == 3 ? pagesPerSheet : (int) Math.sqrt(pagesPerSheet);
|
||||
int rows = pagesPerSheet == 2 || pagesPerSheet == 3 ? 1 : (int) Math.sqrt(pagesPerSheet);
|
||||
|
||||
byte[] bytes = file.getBytes();
|
||||
PdfReader reader = new PdfReader(new ByteArrayInputStream(bytes));
|
||||
PdfDocument pdfDoc = new PdfDocument(reader);
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PdfWriter writer = new PdfWriter(baos);
|
||||
PdfDocument outputPdf = new PdfDocument(writer);
|
||||
PageSize pageSize = new PageSize(PageSize.A4.rotate());
|
||||
|
||||
int totalPages = pdfDoc.getNumberOfPages();
|
||||
float cellWidth = pageSize.getWidth() / cols;
|
||||
float cellHeight = pageSize.getHeight() / rows;
|
||||
|
||||
for (int i = 1; i <= totalPages; i += pagesPerSheet) {
|
||||
PdfPage page = outputPdf.addNewPage(pageSize);
|
||||
PdfCanvas pdfCanvas = new PdfCanvas(page);
|
||||
|
||||
for (int row = 0; row < rows; row++) {
|
||||
for (int col = 0; col < cols; col++) {
|
||||
int index = i + row * cols + col;
|
||||
if (index <= totalPages) {
|
||||
// Get the page and calculate scaling factors
|
||||
Rectangle rect = pdfDoc.getPage(index).getPageSize();
|
||||
float scaleWidth = cellWidth / rect.getWidth();
|
||||
float scaleHeight = cellHeight / rect.getHeight();
|
||||
float scale = Math.min(scaleWidth, scaleHeight);
|
||||
|
||||
PdfFormXObject formXObject = pdfDoc.getPage(index).copyAsFormXObject(outputPdf);
|
||||
float x = col * cellWidth + (cellWidth - rect.getWidth() * scale) / 2;
|
||||
float y = (rows - 1 - row) * cellHeight + (cellHeight - rect.getHeight() * scale) / 2;
|
||||
|
||||
// Save the graphics state, apply the transformations, add the object, and then
|
||||
// restore the graphics state
|
||||
pdfCanvas.saveState();
|
||||
pdfCanvas.concatMatrix(scale, 0, 0, scale, x, y);
|
||||
pdfCanvas.addXObject(formXObject, 0, 0);
|
||||
pdfCanvas.restoreState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outputPdf.close();
|
||||
byte[] pdfContent = baos.toByteArray();
|
||||
pdfDoc.close();
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(pdfContent, file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_layoutChanged.pdf");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,111 +17,193 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "General", description = "General APIs")
|
||||
public class RearrangePagesPDFController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(RearrangePagesPDFController.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(RearrangePagesPDFController.class);
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-pages")
|
||||
@Operation(summary = "Remove pages from a PDF file", description = "This endpoint removes specified pages from a given PDF file. Users can provide a comma-separated list of page numbers or ranges to delete. Input:PDF Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> deletePages(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file from which pages will be removed") MultipartFile pdfFile,
|
||||
@RequestParam("pagesToDelete") @Parameter(description = "Comma-separated list of pages or page ranges to delete, e.g., '1,3,5-8'") String pagesToDelete)
|
||||
throws IOException {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-pages")
|
||||
@Operation(summary = "Remove pages from a PDF file",
|
||||
description = "This endpoint removes specified pages from a given PDF file. Users can provide a comma-separated list of page numbers or ranges to delete.")
|
||||
public ResponseEntity<byte[]> deletePages(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file from which pages will be removed")
|
||||
MultipartFile pdfFile,
|
||||
@RequestParam("pagesToDelete")
|
||||
@Parameter(description = "Comma-separated list of pages or page ranges to delete, e.g., '1,3,5-8'")
|
||||
String pagesToDelete) throws IOException {
|
||||
PDDocument document = PDDocument.load(pdfFile.getBytes());
|
||||
|
||||
PDDocument document = PDDocument.load(pdfFile.getBytes());
|
||||
// Split the page order string into an array of page numbers or range of numbers
|
||||
String[] pageOrderArr = pagesToDelete.split(",");
|
||||
|
||||
// Split the page order string into an array of page numbers or range of numbers
|
||||
String[] pageOrderArr = pagesToDelete.split(",");
|
||||
List<Integer> pagesToRemove = GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages());
|
||||
|
||||
List<Integer> pagesToRemove = pageOrderToString(pageOrderArr, document.getNumberOfPages());
|
||||
for (int i = pagesToRemove.size() - 1; i >= 0; i--) {
|
||||
int pageIndex = pagesToRemove.get(i);
|
||||
document.removePage(pageIndex);
|
||||
}
|
||||
return WebResponseUtils.pdfDocToWebResponse(document,
|
||||
pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_removed_pages.pdf");
|
||||
|
||||
for (int i = pagesToRemove.size() - 1; i >= 0; i--) {
|
||||
int pageIndex = pagesToRemove.get(i);
|
||||
document.removePage(pageIndex);
|
||||
}
|
||||
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_removed_pages.pdf");
|
||||
}
|
||||
|
||||
}
|
||||
private enum CustomMode {
|
||||
REVERSE_ORDER, DUPLEX_SORT, BOOKLET_SORT, ODD_EVEN_SPLIT, REMOVE_FIRST, REMOVE_LAST, REMOVE_FIRST_AND_LAST,
|
||||
}
|
||||
|
||||
private List<Integer> pageOrderToString(String[] pageOrderArr, int totalPages) {
|
||||
List<Integer> newPageOrder = new ArrayList<>();
|
||||
// loop through the page order array
|
||||
for (String element : pageOrderArr) {
|
||||
// check if the element contains a range of pages
|
||||
if (element.contains("-")) {
|
||||
// split the range into start and end page
|
||||
String[] range = element.split("-");
|
||||
int start = Integer.parseInt(range[0]);
|
||||
int end = Integer.parseInt(range[1]);
|
||||
// check if the end page is greater than total pages
|
||||
if (end > totalPages) {
|
||||
end = totalPages;
|
||||
}
|
||||
// loop through the range of pages
|
||||
for (int j = start; j <= end; j++) {
|
||||
// print the current index
|
||||
newPageOrder.add(j - 1);
|
||||
}
|
||||
} else {
|
||||
// if the element is a single page
|
||||
newPageOrder.add(Integer.parseInt(element) - 1);
|
||||
}
|
||||
}
|
||||
private List<Integer> removeFirst(int totalPages) {
|
||||
if (totalPages <= 1)
|
||||
return new ArrayList<>();
|
||||
List<Integer> newPageOrder = new ArrayList<>();
|
||||
for (int i = 2; i <= totalPages; i++) {
|
||||
newPageOrder.add(i - 1);
|
||||
}
|
||||
return newPageOrder;
|
||||
}
|
||||
|
||||
return newPageOrder;
|
||||
}
|
||||
private List<Integer> removeLast(int totalPages) {
|
||||
if (totalPages <= 1)
|
||||
return new ArrayList<>();
|
||||
List<Integer> newPageOrder = new ArrayList<>();
|
||||
for (int i = 1; i < totalPages; i++) {
|
||||
newPageOrder.add(i - 1);
|
||||
}
|
||||
return newPageOrder;
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/rearrange-pages")
|
||||
@Operation(summary = "Rearrange pages in a PDF file",
|
||||
description = "This endpoint rearranges pages in a given PDF file based on the specified page order. Users can provide a page order as a comma-separated list of page numbers or page ranges.")
|
||||
public ResponseEntity<byte[]> rearrangePages(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to rearrange pages")
|
||||
MultipartFile pdfFile,
|
||||
@RequestParam("pageOrder")
|
||||
@Parameter(description = "The new page order as a comma-separated list of page numbers or page ranges (e.g., '1,3,5-7')")
|
||||
String pageOrder) {
|
||||
try {
|
||||
// Load the input PDF
|
||||
PDDocument document = PDDocument.load(pdfFile.getInputStream());
|
||||
private List<Integer> removeFirstAndLast(int totalPages) {
|
||||
if (totalPages <= 2)
|
||||
return new ArrayList<>();
|
||||
List<Integer> newPageOrder = new ArrayList<>();
|
||||
for (int i = 2; i < totalPages; i++) {
|
||||
newPageOrder.add(i - 1);
|
||||
}
|
||||
return newPageOrder;
|
||||
}
|
||||
|
||||
// Split the page order string into an array of page numbers or range of numbers
|
||||
String[] pageOrderArr = pageOrder.split(",");
|
||||
// int[] newPageOrder = new int[pageOrderArr.length];
|
||||
int totalPages = document.getNumberOfPages();
|
||||
private List<Integer> reverseOrder(int totalPages) {
|
||||
List<Integer> newPageOrder = new ArrayList<>();
|
||||
for (int i = totalPages; i >= 1; i--) {
|
||||
newPageOrder.add(i - 1);
|
||||
}
|
||||
return newPageOrder;
|
||||
}
|
||||
|
||||
List<Integer> newPageOrder = pageOrderToString(pageOrderArr, totalPages);
|
||||
private List<Integer> duplexSort(int totalPages) {
|
||||
List<Integer> newPageOrder = new ArrayList<>();
|
||||
int half = (totalPages + 1) / 2; // This ensures proper behavior with odd numbers of pages
|
||||
for (int i = 1; i <= half; i++) {
|
||||
newPageOrder.add(i - 1);
|
||||
if (i <= totalPages - half) { // Avoid going out of bounds
|
||||
newPageOrder.add(totalPages - i);
|
||||
}
|
||||
}
|
||||
return newPageOrder;
|
||||
}
|
||||
|
||||
// Create a new list to hold the pages in the new order
|
||||
List<PDPage> newPages = new ArrayList<>();
|
||||
for (int i = 0; i < newPageOrder.size(); i++) {
|
||||
newPages.add(document.getPage(newPageOrder.get(i)));
|
||||
}
|
||||
private List<Integer> bookletSort(int totalPages) {
|
||||
List<Integer> newPageOrder = new ArrayList<>();
|
||||
for (int i = 0; i < totalPages / 2; i++) {
|
||||
newPageOrder.add(i);
|
||||
newPageOrder.add(totalPages - i - 1);
|
||||
}
|
||||
return newPageOrder;
|
||||
}
|
||||
|
||||
// Remove all the pages from the original document
|
||||
for (int i = document.getNumberOfPages() - 1; i >= 0; i--) {
|
||||
document.removePage(i);
|
||||
}
|
||||
private List<Integer> oddEvenSplit(int totalPages) {
|
||||
List<Integer> newPageOrder = new ArrayList<>();
|
||||
for (int i = 1; i <= totalPages; i += 2) {
|
||||
newPageOrder.add(i - 1);
|
||||
}
|
||||
for (int i = 2; i <= totalPages; i += 2) {
|
||||
newPageOrder.add(i - 1);
|
||||
}
|
||||
return newPageOrder;
|
||||
}
|
||||
|
||||
// Add the pages in the new order
|
||||
for (PDPage page : newPages) {
|
||||
document.addPage(page);
|
||||
}
|
||||
private List<Integer> processCustomMode(String customMode, int totalPages) {
|
||||
try {
|
||||
CustomMode mode = CustomMode.valueOf(customMode.toUpperCase());
|
||||
switch (mode) {
|
||||
case REVERSE_ORDER:
|
||||
return reverseOrder(totalPages);
|
||||
case DUPLEX_SORT:
|
||||
return duplexSort(totalPages);
|
||||
case BOOKLET_SORT:
|
||||
return bookletSort(totalPages);
|
||||
case ODD_EVEN_SPLIT:
|
||||
return oddEvenSplit(totalPages);
|
||||
case REMOVE_FIRST:
|
||||
return removeFirst(totalPages);
|
||||
case REMOVE_LAST:
|
||||
return removeLast(totalPages);
|
||||
case REMOVE_FIRST_AND_LAST:
|
||||
return removeFirstAndLast(totalPages);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported custom mode");
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.error("Unsupported custom mode", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_rearranged.pdf");
|
||||
} catch (IOException e) {
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/rearrange-pages")
|
||||
@Operation(summary = "Rearrange pages in a PDF file", description = "This endpoint rearranges pages in a given PDF file based on the specified page order or custom mode. Users can provide a page order as a comma-separated list of page numbers or page ranges, or a custom mode. Input:PDF Output:PDF")
|
||||
public ResponseEntity<byte[]> rearrangePages(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file to rearrange pages") MultipartFile pdfFile,
|
||||
@RequestParam(required = false, value = "pageOrder") @Parameter(description = "The new page order as a comma-separated list of page numbers, page ranges (e.g., '1,3,5-7'), or functions in the format 'an+b' where 'a' is the multiplier of the page number 'n', and 'b' is a constant (e.g., '2n+1', '3n', '6n-5')") String pageOrder,
|
||||
@RequestParam(required = false, value = "customMode") @Parameter(schema = @Schema(implementation = CustomMode.class, description = "The custom mode for page rearrangement. "
|
||||
+ "Valid values are:\n" + "REVERSE_ORDER: Reverses the order of all pages.\n"
|
||||
+ "DUPLEX_SORT: Sorts pages as if all fronts were scanned then all backs in reverse (1, n, 2, n-1, ...). "
|
||||
+ "BOOKLET_SORT: Arranges pages for booklet printing (last, first, second, second last, ...).\n"
|
||||
+ "ODD_EVEN_SPLIT: Splits and arranges pages into odd and even numbered pages.\n"
|
||||
+ "REMOVE_FIRST: Removes the first page.\n" + "REMOVE_LAST: Removes the last page.\n"
|
||||
+ "REMOVE_FIRST_AND_LAST: Removes both the first and the last pages.\n")) String customMode) {
|
||||
try {
|
||||
// Load the input PDF
|
||||
PDDocument document = PDDocument.load(pdfFile.getInputStream());
|
||||
|
||||
logger.error("Failed rearranging documents", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Split the page order string into an array of page numbers or range of numbers
|
||||
String[] pageOrderArr = pageOrder != null ? pageOrder.split(",") : new String[0];
|
||||
int totalPages = document.getNumberOfPages();
|
||||
System.out.println("pageOrder=" + pageOrder);
|
||||
System.out.println("customMode length =" + customMode.length());
|
||||
List<Integer> newPageOrder;
|
||||
if (customMode != null && customMode.length() > 0) {
|
||||
newPageOrder = processCustomMode(customMode, totalPages);
|
||||
} else {
|
||||
newPageOrder = GeneralUtils.parsePageList(pageOrderArr, totalPages);
|
||||
}
|
||||
|
||||
// Create a new list to hold the pages in the new order
|
||||
List<PDPage> newPages = new ArrayList<>();
|
||||
for (int i = 0; i < newPageOrder.size(); i++) {
|
||||
newPages.add(document.getPage(newPageOrder.get(i)));
|
||||
}
|
||||
|
||||
// Remove all the pages from the original document
|
||||
for (int i = document.getNumberOfPages() - 1; i >= 0; i--) {
|
||||
document.removePage(i);
|
||||
}
|
||||
|
||||
// Add the pages in the new order
|
||||
for (PDPage page : newPages) {
|
||||
document.addPage(page);
|
||||
}
|
||||
|
||||
return WebResponseUtils.pdfDocToWebResponse(document,
|
||||
pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_rearranged.pdf");
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed rearranging documents", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -16,9 +16,11 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "General", description = "General APIs")
|
||||
public class RotationController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(RotationController.class);
|
||||
@@ -26,7 +28,7 @@ public class RotationController {
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/rotate-pdf")
|
||||
@Operation(
|
||||
summary = "Rotate a PDF file",
|
||||
description = "This endpoint rotates a given PDF file by a specified angle. The angle must be a multiple of 90."
|
||||
description = "This endpoint rotates a given PDF file by a specified angle. The angle must be a multiple of 90. Input:PDF Output:PDF Type:SISO"
|
||||
)
|
||||
public ResponseEntity<byte[]> rotatePDF(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@@ -46,7 +48,7 @@ public class RotationController {
|
||||
page.setRotation(page.getRotation() + angle);
|
||||
}
|
||||
|
||||
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_rotated.pdf");
|
||||
return WebResponseUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_rotated.pdf");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.kernel.geom.PageSize;
|
||||
import com.itextpdf.kernel.geom.Rectangle;
|
||||
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||
import com.itextpdf.kernel.pdf.PdfPage;
|
||||
import com.itextpdf.kernel.pdf.PdfReader;
|
||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.EventType;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.data.IEventData;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.listener.IEventListener;
|
||||
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "General", description = "General APIs")
|
||||
public class ScalePagesController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ScalePagesController.class);
|
||||
|
||||
@PostMapping(value = "/scale-pages", consumes = "multipart/form-data")
|
||||
@Operation(summary = "Change the size of a PDF page/document", description = "This operation takes an input PDF file and the size to scale the pages to in the output PDF file. Input:PDF Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> scalePages(
|
||||
@Parameter(description = "The input PDF file", required = true) @RequestParam("fileInput") MultipartFile file,
|
||||
@Parameter(description = "The scale of pages in the output PDF. Acceptable values are A0-A10, B0-B9, LETTER, TABLOID, LEDGER, LEGAL, EXECUTIVE.", required = true, schema = @Schema(type = "String", allowableValues = {
|
||||
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10", "B0", "B1", "B2", "B3", "B4",
|
||||
"B5", "B6", "B7", "B8", "B9", "LETTER", "TABLOID", "LEDGER", "LEGAL",
|
||||
"EXECUTIVE" })) @RequestParam("pageSize") String targetPageSize,
|
||||
@Parameter(description = "The scale of the content on the pages of the output PDF. Acceptable values are floats.", required = true, schema = @Schema(type = "float")) @RequestParam("scaleFactor") float scaleFactor)
|
||||
throws IOException {
|
||||
|
||||
Map<String, PageSize> sizeMap = new HashMap<>();
|
||||
// Add A0 - A10
|
||||
sizeMap.put("A0", PageSize.A0);
|
||||
sizeMap.put("A1", PageSize.A1);
|
||||
sizeMap.put("A2", PageSize.A2);
|
||||
sizeMap.put("A3", PageSize.A3);
|
||||
sizeMap.put("A4", PageSize.A4);
|
||||
sizeMap.put("A5", PageSize.A5);
|
||||
sizeMap.put("A6", PageSize.A6);
|
||||
sizeMap.put("A7", PageSize.A7);
|
||||
sizeMap.put("A8", PageSize.A8);
|
||||
sizeMap.put("A9", PageSize.A9);
|
||||
sizeMap.put("A10", PageSize.A10);
|
||||
// Add B0 - B9
|
||||
sizeMap.put("B0", PageSize.B0);
|
||||
sizeMap.put("B1", PageSize.B1);
|
||||
sizeMap.put("B2", PageSize.B2);
|
||||
sizeMap.put("B3", PageSize.B3);
|
||||
sizeMap.put("B4", PageSize.B4);
|
||||
sizeMap.put("B5", PageSize.B5);
|
||||
sizeMap.put("B6", PageSize.B6);
|
||||
sizeMap.put("B7", PageSize.B7);
|
||||
sizeMap.put("B8", PageSize.B8);
|
||||
sizeMap.put("B9", PageSize.B9);
|
||||
// Add other sizes
|
||||
sizeMap.put("LETTER", PageSize.LETTER);
|
||||
sizeMap.put("TABLOID", PageSize.TABLOID);
|
||||
sizeMap.put("LEDGER", PageSize.LEDGER);
|
||||
sizeMap.put("LEGAL", PageSize.LEGAL);
|
||||
sizeMap.put("EXECUTIVE", PageSize.EXECUTIVE);
|
||||
|
||||
if (!sizeMap.containsKey(targetPageSize)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid pageSize. It must be one of the following: A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10");
|
||||
}
|
||||
|
||||
PageSize pageSize = sizeMap.get(targetPageSize);
|
||||
|
||||
byte[] bytes = file.getBytes();
|
||||
PdfReader reader = new PdfReader(new ByteArrayInputStream(bytes));
|
||||
PdfDocument pdfDoc = new PdfDocument(reader);
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PdfWriter writer = new PdfWriter(baos);
|
||||
PdfDocument outputPdf = new PdfDocument(writer);
|
||||
|
||||
int totalPages = pdfDoc.getNumberOfPages();
|
||||
|
||||
for (int i = 1; i <= totalPages; i++) {
|
||||
PdfPage page = outputPdf.addNewPage(pageSize);
|
||||
PdfCanvas pdfCanvas = new PdfCanvas(page);
|
||||
|
||||
// Get the page and calculate scaling factors
|
||||
Rectangle rect = pdfDoc.getPage(i).getPageSize();
|
||||
float scaleWidth = pageSize.getWidth() / rect.getWidth();
|
||||
float scaleHeight = pageSize.getHeight() / rect.getHeight();
|
||||
float scale = Math.min(scaleWidth, scaleHeight) * scaleFactor;
|
||||
System.out.println("Scale: " + scale);
|
||||
|
||||
PdfFormXObject formXObject = pdfDoc.getPage(i).copyAsFormXObject(outputPdf);
|
||||
float x = (pageSize.getWidth() - rect.getWidth() * scale) / 2; // Center Page
|
||||
float y = (pageSize.getHeight() - rect.getHeight() * scale) / 2;
|
||||
|
||||
// Save the graphics state, apply the transformations, add the object, and then
|
||||
// restore the graphics state
|
||||
pdfCanvas.saveState();
|
||||
pdfCanvas.concatMatrix(scale, 0, 0, scale, x, y);
|
||||
pdfCanvas.addXObject(formXObject, 0, 0);
|
||||
pdfCanvas.restoreState();
|
||||
}
|
||||
|
||||
outputPdf.close();
|
||||
byte[] pdfContent = baos.toByteArray();
|
||||
pdfDoc.close();
|
||||
return WebResponseUtils.bytesToWebResponse(pdfContent,
|
||||
file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_scaled.pdf");
|
||||
}
|
||||
|
||||
//TODO
|
||||
@Hidden
|
||||
@PostMapping(value = "/auto-crop", consumes = "multipart/form-data")
|
||||
public ResponseEntity<byte[]> cropPdf(@RequestParam("fileInput") MultipartFile file) throws IOException {
|
||||
byte[] bytes = file.getBytes();
|
||||
PdfReader reader = new PdfReader(new ByteArrayInputStream(bytes));
|
||||
PdfDocument pdfDoc = new PdfDocument(reader);
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PdfWriter writer = new PdfWriter(baos);
|
||||
PdfDocument outputPdf = new PdfDocument(writer);
|
||||
|
||||
int totalPages = pdfDoc.getNumberOfPages();
|
||||
for (int i = 1; i <= totalPages; i++) {
|
||||
PdfPage page = pdfDoc.getPage(i);
|
||||
Rectangle originalMediaBox = page.getMediaBox();
|
||||
|
||||
Rectangle contentBox = determineContentBox(page);
|
||||
|
||||
// Make sure we don't go outside the original media box.
|
||||
Rectangle intersection = originalMediaBox.getIntersection(contentBox);
|
||||
page.setCropBox(intersection);
|
||||
|
||||
// Copy page to the new document
|
||||
outputPdf.addPage(page.copyTo(outputPdf));
|
||||
}
|
||||
|
||||
outputPdf.close();
|
||||
byte[] pdfContent = baos.toByteArray();
|
||||
pdfDoc.close();
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\""
|
||||
+ file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_cropped.pdf\"")
|
||||
.contentType(MediaType.APPLICATION_PDF).body(pdfContent);
|
||||
}
|
||||
|
||||
private Rectangle determineContentBox(PdfPage page) {
|
||||
// Extract the text from the page and find the bounding box.
|
||||
TextBoundingRectangleFinder finder = new TextBoundingRectangleFinder();
|
||||
PdfCanvasProcessor processor = new PdfCanvasProcessor(finder);
|
||||
processor.processPageContent(page);
|
||||
return finder.getBoundingBox();
|
||||
}
|
||||
|
||||
private static class TextBoundingRectangleFinder implements IEventListener {
|
||||
private List<Rectangle> allTextBoxes = new ArrayList<>();
|
||||
|
||||
public Rectangle getBoundingBox() {
|
||||
// Sort the text boxes based on their vertical position
|
||||
allTextBoxes.sort(Comparator.comparingDouble(Rectangle::getTop));
|
||||
|
||||
// Consider a box an outlier if its top is more than 1.5 times the IQR above the
|
||||
// third quartile.
|
||||
int q1Index = allTextBoxes.size() / 4;
|
||||
int q3Index = 3 * allTextBoxes.size() / 4;
|
||||
double iqr = allTextBoxes.get(q3Index).getTop() - allTextBoxes.get(q1Index).getTop();
|
||||
double threshold = allTextBoxes.get(q3Index).getTop() + 1.5 * iqr;
|
||||
|
||||
// Initialize boundingBox to the first non-outlier box
|
||||
int i = 0;
|
||||
while (i < allTextBoxes.size() && allTextBoxes.get(i).getTop() > threshold) {
|
||||
i++;
|
||||
}
|
||||
if (i == allTextBoxes.size()) {
|
||||
// If all boxes are outliers, just return the first one
|
||||
return allTextBoxes.get(0);
|
||||
}
|
||||
Rectangle boundingBox = allTextBoxes.get(i);
|
||||
|
||||
// Extend the bounding box to include all non-outlier boxes
|
||||
for (; i < allTextBoxes.size(); i++) {
|
||||
Rectangle textBoundingBox = allTextBoxes.get(i);
|
||||
if (textBoundingBox.getTop() > threshold) {
|
||||
// This box is an outlier, skip it
|
||||
continue;
|
||||
}
|
||||
float left = Math.min(boundingBox.getLeft(), textBoundingBox.getLeft());
|
||||
float bottom = Math.min(boundingBox.getBottom(), textBoundingBox.getBottom());
|
||||
float right = Math.max(boundingBox.getRight(), textBoundingBox.getRight());
|
||||
float top = Math.max(boundingBox.getTop(), textBoundingBox.getTop());
|
||||
|
||||
// Add a small padding around the bounding box
|
||||
float padding = 10;
|
||||
boundingBox = new Rectangle(left - padding, bottom - padding, right - left + 2 * padding,
|
||||
top - bottom + 2 * padding);
|
||||
}
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventOccurred(IEventData data, EventType type) {
|
||||
if (type == EventType.RENDER_TEXT) {
|
||||
TextRenderInfo renderInfo = (TextRenderInfo) data;
|
||||
allTextBoxes.add(renderInfo.getBaseline().getBoundingRectangle());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<EventType> getSupportedEvents() {
|
||||
return Collections.singleton(EventType.RENDER_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
@@ -16,9 +15,6 @@ import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -29,16 +25,20 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "General", description = "General APIs")
|
||||
public class SplitPDFController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SplitPDFController.class);
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/split-pages")
|
||||
@Operation(summary = "Split a PDF file into separate documents",
|
||||
description = "This endpoint splits a given PDF file into separate documents based on the specified page numbers or ranges. Users can specify pages using individual numbers, ranges, or 'all' for every page.")
|
||||
public ResponseEntity<Resource> splitPdf(
|
||||
description = "This endpoint splits a given PDF file into separate documents based on the specified page numbers or ranges. Users can specify pages using individual numbers, ranges, or 'all' for every page. Input:PDF Output:PDF Type:SIMO")
|
||||
public ResponseEntity<byte[]> splitPdf(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to be split")
|
||||
MultipartFile file,
|
||||
@@ -58,39 +58,28 @@ public class SplitPDFController {
|
||||
pageNumbers.add(i);
|
||||
}
|
||||
} else {
|
||||
List<String> pageNumbersStr = new ArrayList<>(Arrays.asList(pages.split(",")));
|
||||
if (!pageNumbersStr.contains(String.valueOf(document.getNumberOfPages()))) {
|
||||
String lastpage = String.valueOf(document.getNumberOfPages());
|
||||
pageNumbersStr.add(lastpage);
|
||||
}
|
||||
for (String page : pageNumbersStr) {
|
||||
if (page.contains("-")) {
|
||||
String[] range = page.split("-");
|
||||
int start = Integer.parseInt(range[0]);
|
||||
int end = Integer.parseInt(range[1]);
|
||||
for (int i = start; i <= end; i++) {
|
||||
pageNumbers.add(i);
|
||||
}
|
||||
} else {
|
||||
pageNumbers.add(Integer.parseInt(page));
|
||||
}
|
||||
String[] splitPoints = pages.split(",");
|
||||
for (String splitPoint : splitPoints) {
|
||||
List<Integer> orderedPages = GeneralUtils.parsePageList(new String[] {splitPoint}, document.getNumberOfPages());
|
||||
pageNumbers.addAll(orderedPages);
|
||||
}
|
||||
// Add the last page as a split point
|
||||
pageNumbers.add(document.getNumberOfPages() - 1);
|
||||
}
|
||||
|
||||
logger.info("Splitting PDF into pages: {}", pageNumbers.stream().map(String::valueOf).collect(Collectors.joining(",")));
|
||||
|
||||
// split the document
|
||||
List<ByteArrayOutputStream> splitDocumentsBoas = new ArrayList<>();
|
||||
int currentPage = 0;
|
||||
for (int pageNumber : pageNumbers) {
|
||||
int previousPageNumber = 0;
|
||||
for (int splitPoint : pageNumbers) {
|
||||
try (PDDocument splitDocument = new PDDocument()) {
|
||||
for (int i = currentPage; i < pageNumber; i++) {
|
||||
for (int i = previousPageNumber; i <= splitPoint; i++) {
|
||||
PDPage page = document.getPage(i);
|
||||
splitDocument.addPage(page);
|
||||
logger.debug("Adding page {} to split document", i);
|
||||
}
|
||||
currentPage = pageNumber;
|
||||
logger.debug("Setting current page to {}", currentPage);
|
||||
previousPageNumber = splitPoint + 1;
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
splitDocument.save(baos);
|
||||
@@ -102,15 +91,17 @@ public class SplitPDFController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// closing the original document
|
||||
document.close();
|
||||
|
||||
Path zipFile = Files.createTempFile("split_documents", ".zip");
|
||||
|
||||
String filename = file.getOriginalFilename().replaceFirst("[.][^.]+$", "");
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {
|
||||
// loop through the split documents and write them to the zip file
|
||||
for (int i = 0; i < splitDocumentsBoas.size(); i++) {
|
||||
String fileName = "split_document_" + (i + 1) + ".pdf";
|
||||
String fileName = filename + "_" + (i + 1) + ".pdf";
|
||||
ByteArrayOutputStream baos = splitDocumentsBoas.get(i);
|
||||
byte[] pdf = baos.toByteArray();
|
||||
|
||||
@@ -129,12 +120,11 @@ public class SplitPDFController {
|
||||
|
||||
logger.info("Successfully created zip file with split documents: {}", zipFile.toString());
|
||||
byte[] data = Files.readAllBytes(zipFile);
|
||||
ByteArrayResource resource = new ByteArrayResource(data);
|
||||
Files.delete(zipFile);
|
||||
|
||||
// return the Resource in the response
|
||||
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_split.zip")
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM).contentLength(resource.contentLength()).body(resource);
|
||||
return WebResponseUtils.bytesToWebResponse(data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,15 +20,18 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@RestController
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
public class ConvertImgPDFController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ConvertImgPDFController.class);
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-img")
|
||||
@Operation(summary = "Convert PDF to image(s)",
|
||||
description = "This endpoint converts a PDF file to image(s) with the specified image format, color type, and DPI. Users can choose to get a single image or multiple images.")
|
||||
description = "This endpoint converts a PDF file to image(s) with the specified image format, color type, and DPI. Users can choose to get a single image or multiple images. Input:PDF Output:Image Type:SI-Conditional")
|
||||
public ResponseEntity<Resource> convertToImage(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to be converted")
|
||||
@@ -56,8 +59,9 @@ public class ConvertImgPDFController {
|
||||
// returns bytes for image
|
||||
boolean singleImage = singleOrMultiple.equals("single");
|
||||
byte[] result = null;
|
||||
String filename = file.getOriginalFilename().replaceFirst("[.][^.]+$", "");
|
||||
try {
|
||||
result = PdfUtils.convertFromPdf(pdfBytes, imageFormat.toUpperCase(), colorTypeResult, singleImage, Integer.valueOf(dpi));
|
||||
result = PdfUtils.convertFromPdf(pdfBytes, imageFormat.toUpperCase(), colorTypeResult, singleImage, Integer.valueOf(dpi), filename);
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
@@ -74,14 +78,14 @@ public class ConvertImgPDFController {
|
||||
ByteArrayResource resource = new ByteArrayResource(result);
|
||||
// return the Resource in the response
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_convertedToImages.zip")
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename + "_convertedToImages.zip")
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM).contentLength(resource.contentLength()).body(resource);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/img-to-pdf")
|
||||
@Operation(summary = "Convert images to a PDF file",
|
||||
description = "This endpoint converts one or more images to a PDF file. Users can specify whether to stretch the images to fit the PDF page, and whether to automatically rotate the images.")
|
||||
description = "This endpoint converts one or more images to a PDF file. Users can specify whether to stretch the images to fit the PDF page, and whether to automatically rotate the images. Input:Image Output:PDF Type:SISO?")
|
||||
public ResponseEntity<byte[]> convertToPdf(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input images to be converted to a PDF file")
|
||||
@@ -97,7 +101,7 @@ public class ConvertImgPDFController {
|
||||
boolean autoRotate) throws IOException {
|
||||
// Convert the file to PDF and get the resulting bytes
|
||||
byte[] bytes = PdfUtils.imageToPdf(file, stretchToFit, autoRotate, colorType);
|
||||
return PdfUtils.bytesToWebResponse(bytes, file[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_coverted.pdf");
|
||||
return WebResponseUtils.bytesToWebResponse(bytes, file[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_converted.pdf");
|
||||
}
|
||||
|
||||
private String getMediaType(String imageFormat) {
|
||||
|
||||
@@ -17,10 +17,12 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
public class ConvertOfficeController {
|
||||
|
||||
public byte[] convertToPdf(MultipartFile inputFile) throws IOException, InterruptedException {
|
||||
@@ -57,8 +59,8 @@ public class ConvertOfficeController {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/file-to-pdf")
|
||||
@Operation(
|
||||
summary = "Convert a file to a PDF using OCR",
|
||||
description = "This endpoint converts a given file to a PDF using Optical Character Recognition (OCR). The filename of the resulting PDF will be the original filename with '_convertedToPDF.pdf' appended."
|
||||
summary = "Convert a file to a PDF using LibreOffice",
|
||||
description = "This endpoint converts a given file to a PDF using LibreOffice API Input:Any Output:PDF Type:SISO"
|
||||
)
|
||||
public ResponseEntity<byte[]> processPdfWithOCR(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@@ -72,7 +74,7 @@ public class ConvertOfficeController {
|
||||
// LibreOfficeListener.getInstance().start();
|
||||
|
||||
byte[] pdfByteArray = convertToPdf(inputFile);
|
||||
return PdfUtils.bytesToWebResponse(pdfByteArray, inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_convertedToPDF.pdf");
|
||||
return WebResponseUtils.bytesToWebResponse(pdfByteArray, inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_convertedToPDF.pdf");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,13 +12,15 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.PDFToFile;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
public class ConvertPDFToOffice {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-html")
|
||||
@Operation(summary = "Convert PDF to HTML", description = "This endpoint converts a PDF file to HTML format.")
|
||||
@Operation(summary = "Convert PDF to HTML", description = "This endpoint converts a PDF file to HTML format. Input:PDF Output:HTML Type:SISO")
|
||||
public ResponseEntity<byte[]> processPdfToHTML(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file to be converted to HTML format", required = true) MultipartFile inputFile)
|
||||
throws IOException, InterruptedException {
|
||||
@@ -27,7 +29,7 @@ public class ConvertPDFToOffice {
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-presentation")
|
||||
@Operation(summary = "Convert PDF to Presentation format", description = "This endpoint converts a given PDF file to a Presentation format.")
|
||||
@Operation(summary = "Convert PDF to Presentation format", description = "This endpoint converts a given PDF file to a Presentation format. Input:PDF Output:PPT Type:SISO")
|
||||
public ResponseEntity<byte[]> processPdfToPresentation(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file") MultipartFile inputFile,
|
||||
@RequestParam("outputFormat") @Parameter(description = "The output Presentation format", schema = @Schema(allowableValues = {
|
||||
@@ -38,7 +40,7 @@ public class ConvertPDFToOffice {
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-text")
|
||||
@Operation(summary = "Convert PDF to Text or RTF format", description = "This endpoint converts a given PDF file to Text or RTF format.")
|
||||
@Operation(summary = "Convert PDF to Text or RTF format", description = "This endpoint converts a given PDF file to Text or RTF format. Input:PDF Output:TXT Type:SISO")
|
||||
public ResponseEntity<byte[]> processPdfToRTForTXT(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file") MultipartFile inputFile,
|
||||
@RequestParam("outputFormat") @Parameter(description = "The output Text or RTF format", schema = @Schema(allowableValues = {
|
||||
@@ -49,7 +51,7 @@ public class ConvertPDFToOffice {
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-word")
|
||||
@Operation(summary = "Convert PDF to Word document", description = "This endpoint converts a given PDF file to a Word document format.")
|
||||
@Operation(summary = "Convert PDF to Word document", description = "This endpoint converts a given PDF file to a Word document format. Input:PDF Output:WORD Type:SISO")
|
||||
public ResponseEntity<byte[]> processPdfToWord(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file") MultipartFile inputFile,
|
||||
@RequestParam("outputFormat") @Parameter(description = "The output Word document format", schema = @Schema(allowableValues = {
|
||||
@@ -60,7 +62,7 @@ public class ConvertPDFToOffice {
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-xml")
|
||||
@Operation(summary = "Convert PDF to XML", description = "This endpoint converts a PDF file to an XML file.")
|
||||
@Operation(summary = "Convert PDF to XML", description = "This endpoint converts a PDF file to an XML file. Input:PDF Output:XML Type:SISO")
|
||||
public ResponseEntity<byte[]> processPdfToXML(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file to be converted to an XML file", required = true) MultipartFile inputFile)
|
||||
throws IOException, InterruptedException {
|
||||
|
||||
@@ -14,16 +14,18 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
public class ConvertPDFToPDFA {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-pdfa")
|
||||
@Operation(
|
||||
summary = "Convert a PDF to a PDF/A",
|
||||
description = "This endpoint converts a PDF file to a PDF/A file. PDF/A is a format designed for long-term archiving of digital documents."
|
||||
description = "This endpoint converts a PDF file to a PDF/A file. PDF/A is a format designed for long-term archiving of digital documents. Input:PDF Output:PDF Type:SISO"
|
||||
)
|
||||
public ResponseEntity<byte[]> pdfToPdfA(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@@ -58,7 +60,7 @@ public class ConvertPDFToPDFA {
|
||||
|
||||
// Return the optimized PDF as a response
|
||||
String outputFilename = inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_PDFA.pdf";
|
||||
return PdfUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
||||
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
package stirling.software.SPDF.controller.api.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Filter", description = "Filter APIs")
|
||||
public class FilterController {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/contains-text")
|
||||
@Operation(summary = "Checks if a PDF contains set text, returns true if does", description = "Input:PDF Output:Boolean Type:SISO")
|
||||
public Boolean containsText(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file to be converted to a PDF/A file", required = true) MultipartFile inputFile,
|
||||
@Parameter(description = "The text to check for", required = true) String text,
|
||||
@Parameter(description = "The page number to check for text on accepts 'All', ranges like '1-4'", required = false) String pageNumber)
|
||||
throws IOException, InterruptedException {
|
||||
PDDocument pdfDocument = PDDocument.load(inputFile.getInputStream());
|
||||
return PdfUtils.hasText(pdfDocument, pageNumber);
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/contains-image")
|
||||
@Operation(summary = "Checks if a PDF contains an image", description = "Input:PDF Output:Boolean Type:SISO")
|
||||
public Boolean containsImage(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file to be converted to a PDF/A file", required = true) MultipartFile inputFile,
|
||||
@Parameter(description = "The page number to check for image on accepts 'All', ranges like '1-4'", required = false) String pageNumber)
|
||||
throws IOException, InterruptedException {
|
||||
PDDocument pdfDocument = PDDocument.load(inputFile.getInputStream());
|
||||
return PdfUtils.hasImagesOnPage(null);
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/page-count")
|
||||
@Operation(summary = "Checks if a PDF is greater, less or equal to a setPageCount", description = "Input:PDF Output:Boolean Type:SISO")
|
||||
public Boolean pageCount(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file", required = true) MultipartFile inputFile,
|
||||
@Parameter(description = "Page Count", required = true) String pageCount,
|
||||
@Parameter(description = "Comparison type, accepts Greater, Equal, Less than", required = false) String comparator)
|
||||
throws IOException, InterruptedException {
|
||||
// Load the PDF
|
||||
PDDocument document = PDDocument.load(inputFile.getInputStream());
|
||||
int actualPageCount = document.getNumberOfPages();
|
||||
|
||||
// Perform the comparison
|
||||
switch (comparator) {
|
||||
case "Greater":
|
||||
return actualPageCount > Integer.parseInt(pageCount);
|
||||
case "Equal":
|
||||
return actualPageCount == Integer.parseInt(pageCount);
|
||||
case "Less":
|
||||
return actualPageCount < Integer.parseInt(pageCount);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid comparator: " + comparator);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/page-size")
|
||||
@Operation(summary = "Checks if a PDF is of a certain size", description = "Input:PDF Output:Boolean Type:SISO")
|
||||
public Boolean pageSize(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file", required = true) MultipartFile inputFile,
|
||||
@Parameter(description = "Standard Page Size", required = true) String standardPageSize,
|
||||
@Parameter(description = "Comparison type, accepts Greater, Equal, Less than", required = false) String comparator)
|
||||
throws IOException, InterruptedException {
|
||||
|
||||
// Load the PDF
|
||||
PDDocument document = PDDocument.load(inputFile.getInputStream());
|
||||
|
||||
PDPage firstPage = document.getPage(0);
|
||||
PDRectangle actualPageSize = firstPage.getMediaBox();
|
||||
|
||||
// Calculate the area of the actual page size
|
||||
float actualArea = actualPageSize.getWidth() * actualPageSize.getHeight();
|
||||
|
||||
// Get the standard size and calculate its area
|
||||
PDRectangle standardSize = PdfUtils.textToPageSize(standardPageSize);
|
||||
float standardArea = standardSize.getWidth() * standardSize.getHeight();
|
||||
|
||||
// Perform the comparison
|
||||
switch (comparator) {
|
||||
case "Greater":
|
||||
return actualArea > standardArea;
|
||||
case "Equal":
|
||||
return actualArea == standardArea;
|
||||
case "Less":
|
||||
return actualArea < standardArea;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid comparator: " + comparator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/file-size")
|
||||
@Operation(summary = "Checks if a PDF is a set file size", description = "Input:PDF Output:Boolean Type:SISO")
|
||||
public Boolean fileSize(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file", required = true) MultipartFile inputFile,
|
||||
@Parameter(description = "File Size", required = true) String fileSize,
|
||||
@Parameter(description = "Comparison type, accepts Greater, Equal, Less than", required = false) String comparator)
|
||||
throws IOException, InterruptedException {
|
||||
|
||||
// Get the file size
|
||||
long actualFileSize = inputFile.getSize();
|
||||
|
||||
// Perform the comparison
|
||||
switch (comparator) {
|
||||
case "Greater":
|
||||
return actualFileSize > Long.parseLong(fileSize);
|
||||
case "Equal":
|
||||
return actualFileSize == Long.parseLong(fileSize);
|
||||
case "Less":
|
||||
return actualFileSize < Long.parseLong(fileSize);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid comparator: " + comparator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/page-rotation")
|
||||
@Operation(summary = "Checks if a PDF is of a certain rotation", description = "Input:PDF Output:Boolean Type:SISO")
|
||||
public Boolean pageRotation(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file", required = true) MultipartFile inputFile,
|
||||
@Parameter(description = "Rotation in degrees", required = true) int rotation,
|
||||
@Parameter(description = "Comparison type, accepts Greater, Equal, Less than", required = false) String comparator)
|
||||
throws IOException, InterruptedException {
|
||||
|
||||
// Load the PDF
|
||||
PDDocument document = PDDocument.load(inputFile.getInputStream());
|
||||
|
||||
// Get the rotation of the first page
|
||||
PDPage firstPage = document.getPage(0);
|
||||
int actualRotation = firstPage.getRotation();
|
||||
|
||||
// Perform the comparison
|
||||
switch (comparator) {
|
||||
case "Greater":
|
||||
return actualRotation > rotation;
|
||||
case "Equal":
|
||||
return actualRotation == rotation;
|
||||
case "Less":
|
||||
return actualRotation < rotation;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid comparator: " + comparator);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,17 +28,19 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.ImageFinder;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class BlankPageController {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-blanks")
|
||||
@Operation(
|
||||
summary = "Remove blank pages from a PDF file",
|
||||
description = "This endpoint removes blank pages from a given PDF file. Users can specify the threshold and white percentage to tune the detection of blank pages."
|
||||
description = "This endpoint removes blank pages from a given PDF file. Users can specify the threshold and white percentage to tune the detection of blank pages. Input:PDF Output:PDF Type:SISO"
|
||||
)
|
||||
public ResponseEntity<byte[]> removeBlankPages(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@@ -71,7 +73,7 @@ public class BlankPageController {
|
||||
pagesToKeepIndex.add(pageIndex);
|
||||
System.out.println("page " + pageIndex + " has text");
|
||||
} else {
|
||||
boolean hasImages = hasImagesOnPage(page);
|
||||
boolean hasImages = PdfUtils.hasImagesOnPage(page);
|
||||
if (hasImages) {
|
||||
System.out.println("page " + pageIndex + " has image");
|
||||
|
||||
@@ -81,7 +83,7 @@ public class BlankPageController {
|
||||
BufferedImage image = pdfRenderer.renderImageWithDPI(pageIndex, 300);
|
||||
ImageIO.write(image, "png", tempFile.toFile());
|
||||
|
||||
List<String> command = new ArrayList<>(Arrays.asList("python3", System.getProperty("user.dir") + "scripts/detect-blank-pages.py", tempFile.toString() ,"--threshold", String.valueOf(threshold), "--white_percent", String.valueOf(whitePercent)));
|
||||
List<String> command = new ArrayList<>(Arrays.asList("python3", System.getProperty("user.dir") + "/scripts/detect-blank-pages.py", tempFile.toString() ,"--threshold", String.valueOf(threshold), "--white_percent", String.valueOf(whitePercent)));
|
||||
|
||||
// Run CLI command
|
||||
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV).runCommandWithOutputHandling(command);
|
||||
@@ -109,7 +111,7 @@ public class BlankPageController {
|
||||
}
|
||||
}
|
||||
|
||||
return PdfUtils.pdfDocToWebResponse(document, inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_blanksRemoved.pdf");
|
||||
return WebResponseUtils.pdfDocToWebResponse(document, inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_blanksRemoved.pdf");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
@@ -120,9 +122,5 @@ public class BlankPageController {
|
||||
}
|
||||
|
||||
|
||||
private static boolean hasImagesOnPage(PDPage page) throws IOException {
|
||||
ImageFinder imageFinder = new ImageFinder(page);
|
||||
imageFinder.processPage(page);
|
||||
return imageFinder.hasImages();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,16 +31,19 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class CompressController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CompressController.class);
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/compress-pdf")
|
||||
@Operation(summary = "Optimize PDF file", description = "This endpoint accepts a PDF file and optimizes it based on the provided parameters.")
|
||||
@Operation(summary = "Optimize PDF file", description = "This endpoint accepts a PDF file and optimizes it based on the provided parameters. Input:PDF Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> optimizePdf(
|
||||
@RequestPart(value = "fileInput") @Parameter(description = "The input PDF file to be optimized.", required = true) MultipartFile inputFile,
|
||||
@RequestParam(required = false, value = "optimizeLevel") @Parameter(description = "The level of optimization to apply to the PDF file. Higher values indicate greater compression but may reduce quality.", schema = @Schema(allowableValues = {
|
||||
@@ -55,7 +58,7 @@ public class CompressController {
|
||||
Long expectedOutputSize = 0L;
|
||||
boolean autoMode = false;
|
||||
if (expectedOutputSizeString != null && expectedOutputSizeString.length() > 1 ) {
|
||||
expectedOutputSize = PdfUtils.convertSizeToBytes(expectedOutputSizeString);
|
||||
expectedOutputSize = GeneralUtils.convertSizeToBytes(expectedOutputSizeString);
|
||||
autoMode = true;
|
||||
}
|
||||
|
||||
@@ -224,7 +227,7 @@ public class CompressController {
|
||||
|
||||
// Return the optimized PDF as a response
|
||||
String outputFilename = inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_Optimized.pdf";
|
||||
return PdfUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
||||
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,17 +31,19 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class ExtractImageScansController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ExtractImageScansController.class);
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/extract-image-scans")
|
||||
@Operation(summary = "Extract image scans from an input file",
|
||||
description = "This endpoint extracts image scans from a given file based on certain parameters. Users can specify angle threshold, tolerance, minimum area, minimum contour area, and border size.")
|
||||
description = "This endpoint extracts image scans from a given file based on certain parameters. Users can specify angle threshold, tolerance, minimum area, minimum contour area, and border size. Input:PDF Output:IMAGE/ZIP Type:SIMO")
|
||||
public ResponseEntity<byte[]> extractImageScans(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input file containing image scans")
|
||||
@@ -147,11 +149,11 @@ public class ExtractImageScansController {
|
||||
// Clean up the temporary zip file
|
||||
Files.delete(tempZipFile);
|
||||
|
||||
return PdfUtils.bytesToWebResponse(zipBytes, outputZipFilename, MediaType.APPLICATION_OCTET_STREAM);
|
||||
return WebResponseUtils.bytesToWebResponse(zipBytes, outputZipFilename, MediaType.APPLICATION_OCTET_STREAM);
|
||||
} else {
|
||||
// Return the processed image as a response
|
||||
byte[] imageBytes = processedImageBytes.get(0);
|
||||
return PdfUtils.bytesToWebResponse(imageBytes, fileName.replaceFirst("[.][^.]+$", "") + ".png", MediaType.IMAGE_PNG);
|
||||
return WebResponseUtils.bytesToWebResponse(imageBytes, fileName.replaceFirst("[.][^.]+$", "") + ".png", MediaType.IMAGE_PNG);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,15 +29,17 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class ExtractImagesController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ExtractImagesController.class);
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/extract-images")
|
||||
@Operation(summary = "Extract images from a PDF file",
|
||||
description = "This endpoint extracts images from a given PDF file and returns them in a zip file. Users can specify the output image format.")
|
||||
description = "This endpoint extracts images from a given PDF file and returns them in a zip file. Users can specify the output image format. Input:PDF Output:IMAGE/ZIP Type:SIMO")
|
||||
public ResponseEntity<byte[]> extractImages(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file containing images")
|
||||
@@ -59,7 +61,7 @@ public class ExtractImagesController {
|
||||
zos.setLevel(Deflater.BEST_COMPRESSION);
|
||||
|
||||
int imageIndex = 1;
|
||||
|
||||
String filename = file.getOriginalFilename().replaceFirst("[.][^.]+$", "");
|
||||
int pageNum = 1;
|
||||
// Iterate over each page
|
||||
for (PDPage page : document.getPages()) {
|
||||
@@ -81,7 +83,7 @@ public class ExtractImagesController {
|
||||
}
|
||||
|
||||
// Write image to zip file
|
||||
String imageName = "Image " + imageIndex + " (Page " + pageNum + ")." + format;
|
||||
String imageName = filename + "_" + imageIndex + " (Page " + pageNum + ")." + format;
|
||||
ZipEntry zipEntry = new ZipEntry(imageName);
|
||||
zos.putNextEntry(zipEntry);
|
||||
|
||||
@@ -106,7 +108,7 @@ public class ExtractImagesController {
|
||||
// Create ByteArrayResource from byte array
|
||||
byte[] zipContents = baos.toByteArray();
|
||||
|
||||
return PdfUtils.boasToWebResponse(baos, file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_extracted-images.zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||
return WebResponseUtils.boasToWebResponse(baos, filename + "_extracted-images.zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
package stirling.software.SPDF.controller.api.other;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
//Required for image manipulation
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ConvolveOp;
|
||||
import java.awt.image.Kernel;
|
||||
import java.awt.image.RescaleOp;
|
||||
//Required for file input/output
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
//Other required classes
|
||||
import java.util.Random;
|
||||
|
||||
//Required for image input/output
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.apache.pdfbox.rendering.ImageType;
|
||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.io.source.ByteArrayOutputStream;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class FakeScanControllerWIP {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FakeScanControllerWIP.class);
|
||||
|
||||
//TODO
|
||||
@Hidden
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/fakeScan")
|
||||
@Operation(
|
||||
summary = "Repair a PDF file",
|
||||
description = "This endpoint repairs a given PDF file by running Ghostscript command. The PDF is first saved to a temporary location, repaired, read back, and then returned as a response."
|
||||
)
|
||||
public ResponseEntity<byte[]> repairPdf(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to be repaired", required = true)
|
||||
MultipartFile inputFile) throws IOException, InterruptedException {
|
||||
|
||||
PDDocument document = PDDocument.load(inputFile.getBytes());
|
||||
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
||||
for (int page = 0; page < document.getNumberOfPages(); ++page)
|
||||
{
|
||||
BufferedImage image = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB);
|
||||
ImageIO.write(image, "png", new File("scanned-" + (page+1) + ".png"));
|
||||
}
|
||||
document.close();
|
||||
|
||||
// Constants
|
||||
int scannedness = 90; // Value between 0 and 100
|
||||
int dirtiness = 0; // Value between 0 and 100
|
||||
|
||||
// Load the source image
|
||||
BufferedImage sourceImage = ImageIO.read(new File("scanned-1.png"));
|
||||
|
||||
// Create the destination image
|
||||
BufferedImage destinationImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), sourceImage.getType());
|
||||
|
||||
// Apply a brightness and contrast effect based on the "scanned-ness"
|
||||
float scaleFactor = 1.0f + (scannedness / 100.0f) * 0.5f; // Between 1.0 and 1.5
|
||||
float offset = scannedness * 1.5f; // Between 0 and 150
|
||||
BufferedImageOp op = new RescaleOp(scaleFactor, offset, null);
|
||||
op.filter(sourceImage, destinationImage);
|
||||
|
||||
// Apply a rotation effect
|
||||
double rotationRequired = Math.toRadians((new Random().nextInt(3 - 1) + 1)); // Random angle between 1 and 3 degrees
|
||||
double locationX = destinationImage.getWidth() / 2;
|
||||
double locationY = destinationImage.getHeight() / 2;
|
||||
AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
|
||||
AffineTransformOp rotateOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
|
||||
destinationImage = rotateOp.filter(destinationImage, null);
|
||||
|
||||
// Apply a blur effect based on the "scanned-ness"
|
||||
float blurIntensity = scannedness / 100.0f * 0.2f; // Between 0.0 and 0.2
|
||||
float[] matrix = {
|
||||
blurIntensity, blurIntensity, blurIntensity,
|
||||
blurIntensity, blurIntensity, blurIntensity,
|
||||
blurIntensity, blurIntensity, blurIntensity
|
||||
};
|
||||
BufferedImageOp blurOp = new ConvolveOp(new Kernel(3, 3, matrix), ConvolveOp.EDGE_NO_OP, null);
|
||||
destinationImage = blurOp.filter(destinationImage, null);
|
||||
|
||||
// Add noise to the image based on the "dirtiness"
|
||||
Random random = new Random();
|
||||
for (int y = 0; y < destinationImage.getHeight(); y++) {
|
||||
for (int x = 0; x < destinationImage.getWidth(); x++) {
|
||||
if (random.nextInt(100) < dirtiness) {
|
||||
// Change the pixel color to black randomly based on the "dirtiness"
|
||||
destinationImage.setRGB(x, y, Color.BLACK.getRGB());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save the image
|
||||
ImageIO.write(destinationImage, "PNG", new File("scanned-1.png"));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PDDocument documentOut = new PDDocument();
|
||||
for (int page = 1; page <= document.getNumberOfPages(); ++page)
|
||||
{
|
||||
BufferedImage bim = ImageIO.read(new File("scanned-" + page + ".png"));
|
||||
|
||||
// Adjust the dimensions of the page
|
||||
PDPage pdPage = new PDPage(new PDRectangle(bim.getWidth() - 1, bim.getHeight() - 1));
|
||||
documentOut.addPage(pdPage);
|
||||
|
||||
PDImageXObject pdImage = LosslessFactory.createFromImage(documentOut, bim);
|
||||
PDPageContentStream contentStream = new PDPageContentStream(documentOut, pdPage);
|
||||
|
||||
// Draw the image with a slight offset and enlarged dimensions
|
||||
contentStream.drawImage(pdImage, -1, -1, bim.getWidth() + 2, bim.getHeight() + 2);
|
||||
contentStream.close();
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
documentOut.save(baos);
|
||||
documentOut.close();
|
||||
|
||||
// Return the optimized PDF as a response
|
||||
String outputFilename = inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_scanned.pdf";
|
||||
return WebResponseUtils.boasToWebResponse(baos, outputFilename);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,9 +19,11 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class MetadataController {
|
||||
|
||||
|
||||
@@ -38,7 +40,7 @@ public class MetadataController {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/update-metadata")
|
||||
@Operation(summary = "Update metadata of a PDF file",
|
||||
description = "This endpoint allows you to update the metadata of a given PDF file. You can add, modify, or delete standard and custom metadata fields.")
|
||||
description = "This endpoint allows you to update the metadata of a given PDF file. You can add, modify, or delete standard and custom metadata fields. Input:PDF Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> metadata(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to update metadata")
|
||||
@@ -73,6 +75,7 @@ public class MetadataController {
|
||||
@RequestParam(value = "trapped", required = false)
|
||||
@Parameter(description = "The trapped status of the document")
|
||||
String trapped,
|
||||
@Parameter(description = "Map list of key and value of custom parameters, note these must start with customKey and customValue if they are non standard")
|
||||
@RequestParam Map<String, String> allRequestParams)
|
||||
throws IOException {
|
||||
|
||||
@@ -159,7 +162,7 @@ public class MetadataController {
|
||||
info.setTrapped(trapped);
|
||||
|
||||
document.setDocumentInformation(info);
|
||||
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_metadata.pdf");
|
||||
return WebResponseUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_metadata.pdf");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,10 +27,12 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class OCRController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(OCRController.class);
|
||||
@@ -47,7 +49,7 @@ public class OCRController {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/ocr-pdf")
|
||||
@Operation(summary = "Process a PDF file with OCR",
|
||||
description = "This endpoint processes a PDF file using OCR (Optical Character Recognition). Users can specify languages, sidecar, deskew, clean, cleanFinal, ocrType, ocrRenderType, and removeImagesAfter options.")
|
||||
description = "This endpoint processes a PDF file using OCR (Optical Character Recognition). Users can specify languages, sidecar, deskew, clean, cleanFinal, ocrType, ocrRenderType, and removeImagesAfter options. Input:PDF Output:PDF Type:SI-Conditional")
|
||||
public ResponseEntity<byte[]> processPdfWithOCR(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to be processed with OCR")
|
||||
@@ -189,11 +191,11 @@ public class OCRController {
|
||||
Files.delete(sidecarTextPath);
|
||||
|
||||
// Return the zip file containing both the PDF and the text file
|
||||
return PdfUtils.bytesToWebResponse(pdfBytes, outputZipFilename, MediaType.APPLICATION_OCTET_STREAM);
|
||||
return WebResponseUtils.bytesToWebResponse(zipBytes, outputZipFilename, MediaType.APPLICATION_OCTET_STREAM);
|
||||
} else {
|
||||
// Return the OCR processed PDF as a response
|
||||
Files.delete(tempOutputFile);
|
||||
return PdfUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
||||
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,9 +14,12 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class OverlayImageController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(OverlayImageController.class);
|
||||
@@ -24,7 +27,7 @@ public class OverlayImageController {
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/add-image")
|
||||
@Operation(
|
||||
summary = "Overlay image onto a PDF file",
|
||||
description = "This endpoint overlays an image onto a PDF file at the specified coordinates. The image can be overlaid on every page of the PDF if specified."
|
||||
description = "This endpoint overlays an image onto a PDF file at the specified coordinates. The image can be overlaid on every page of the PDF if specified. Input:PDF/IMAGE Output:PDF Type:MF-SISO"
|
||||
)
|
||||
public ResponseEntity<byte[]> overlayImage(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@@ -47,7 +50,7 @@ public class OverlayImageController {
|
||||
byte[] imageBytes = imageFile.getBytes();
|
||||
byte[] result = PdfUtils.overlayImage(pdfBytes, imageBytes, x, y, everyPage);
|
||||
|
||||
return PdfUtils.bytesToWebResponse(result, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_overlayed.pdf");
|
||||
return WebResponseUtils.bytesToWebResponse(result, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_overlayed.pdf");
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to add image to PDF", e);
|
||||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||
|
||||
@@ -16,10 +16,12 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class RepairController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(RepairController.class);
|
||||
@@ -27,7 +29,7 @@ public class RepairController {
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/repair")
|
||||
@Operation(
|
||||
summary = "Repair a PDF file",
|
||||
description = "This endpoint repairs a given PDF file by running Ghostscript command. The PDF is first saved to a temporary location, repaired, read back, and then returned as a response."
|
||||
description = "This endpoint repairs a given PDF file by running Ghostscript command. The PDF is first saved to a temporary location, repaired, read back, and then returned as a response. Input:PDF Output:PDF Type:SISO"
|
||||
)
|
||||
public ResponseEntity<byte[]> repairPdf(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@@ -60,7 +62,7 @@ public class RepairController {
|
||||
|
||||
// Return the optimized PDF as a response
|
||||
String outputFilename = inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_repaired.pdf";
|
||||
return PdfUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
||||
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
package stirling.software.SPDF.controller.api.pipeline;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.model.PipelineConfig;
|
||||
import stirling.software.SPDF.model.PipelineOperation;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Pipeline", description = "Pipeline APIs")
|
||||
public class Controller {
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
|
||||
final String jsonFileName = "pipelineCofig.json";
|
||||
final String watchedFoldersDir = "watchedFolders/";
|
||||
@Scheduled(fixedRate = 5000)
|
||||
public void scanFolders() {
|
||||
Path watchedFolderPath = Paths.get(watchedFoldersDir);
|
||||
if (!Files.exists(watchedFolderPath)) {
|
||||
try {
|
||||
Files.createDirectories(watchedFolderPath);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try (Stream<Path> paths = Files.walk(watchedFolderPath)) {
|
||||
paths.filter(Files::isDirectory).forEach(t -> {
|
||||
try {
|
||||
if (!t.equals(watchedFolderPath) && !t.endsWith("processing")) {
|
||||
handleDirectory(t);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDirectory(Path dir) throws Exception {
|
||||
Path jsonFile = dir.resolve(jsonFileName);
|
||||
Path processingDir = dir.resolve("processing"); // Directory to move files during processing
|
||||
if (!Files.exists(processingDir)) {
|
||||
Files.createDirectory(processingDir);
|
||||
}
|
||||
|
||||
if (Files.exists(jsonFile)) {
|
||||
// Read JSON file
|
||||
String jsonString;
|
||||
try {
|
||||
jsonString = new String(Files.readAllBytes(jsonFile));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
// Decode JSON to PipelineConfig
|
||||
PipelineConfig config;
|
||||
try {
|
||||
config = objectMapper.readValue(jsonString, PipelineConfig.class);
|
||||
// Assuming your PipelineConfig class has getters for all necessary fields, you can perform checks here
|
||||
if (config.getOperations() == null || config.getOutputDir() == null || config.getName() == null) {
|
||||
throw new IOException("Invalid JSON format");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
// For each operation in the pipeline
|
||||
for (PipelineOperation operation : config.getOperations()) {
|
||||
// Collect all files based on fileInput
|
||||
File[] files;
|
||||
String fileInput = (String) operation.getParameters().get("fileInput");
|
||||
if ("automated".equals(fileInput)) {
|
||||
// If fileInput is "automated", process all files in the directory
|
||||
try (Stream<Path> paths = Files.list(dir)) {
|
||||
files = paths.filter(path -> !path.equals(jsonFile))
|
||||
.map(Path::toFile)
|
||||
.toArray(File[]::new);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// If fileInput contains a path, process only this file
|
||||
files = new File[]{new File(fileInput)};
|
||||
}
|
||||
|
||||
// Prepare the files for processing
|
||||
File[] filesToProcess = files.clone();
|
||||
for (File file : filesToProcess) {
|
||||
Files.move(file.toPath(), processingDir.resolve(file.getName()));
|
||||
}
|
||||
|
||||
// Process the files
|
||||
try {
|
||||
List<Resource> resources = handleFiles(filesToProcess, jsonString);
|
||||
|
||||
// Move resultant files and rename them as per config in JSON file
|
||||
for (Resource resource : resources) {
|
||||
String outputFileName = config.getOutputPattern().replace("{filename}", resource.getFile().getName());
|
||||
outputFileName = outputFileName.replace("{pipelineName}", config.getName());
|
||||
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||
outputFileName = outputFileName.replace("{date}", LocalDate.now().format(dateFormatter));
|
||||
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HHmmss");
|
||||
outputFileName = outputFileName.replace("{time}", LocalTime.now().format(timeFormatter));
|
||||
// {filename} {folder} {date} {tmime} {pipeline}
|
||||
|
||||
Files.move(resource.getFile().toPath(), Paths.get(config.getOutputDir(), outputFileName));
|
||||
}
|
||||
|
||||
// If successful, delete the original files
|
||||
for (File file : filesToProcess) {
|
||||
Files.deleteIfExists(processingDir.resolve(file.getName()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// If an error occurs, move the original files back
|
||||
for (File file : filesToProcess) {
|
||||
Files.move(processingDir.resolve(file.getName()), file.toPath());
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
List<Resource> processFiles(List<Resource> outputFiles, String jsonString) throws Exception{
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode jsonNode = mapper.readTree(jsonString);
|
||||
|
||||
JsonNode pipelineNode = jsonNode.get("pipeline");
|
||||
ByteArrayOutputStream logStream = new ByteArrayOutputStream();
|
||||
PrintStream logPrintStream = new PrintStream(logStream);
|
||||
|
||||
boolean hasErrors = false;
|
||||
|
||||
for (JsonNode operationNode : pipelineNode) {
|
||||
String operation = operationNode.get("operation").asText();
|
||||
JsonNode parametersNode = operationNode.get("parameters");
|
||||
String inputFileExtension = "";
|
||||
if(operationNode.has("inputFileType")) {
|
||||
inputFileExtension = operationNode.get("inputFileType").asText();
|
||||
} else {
|
||||
inputFileExtension=".pdf";
|
||||
}
|
||||
|
||||
List<Resource> newOutputFiles = new ArrayList<>();
|
||||
boolean hasInputFileType = false;
|
||||
|
||||
for (Resource file : outputFiles) {
|
||||
if (file.getFilename().endsWith(inputFileExtension)) {
|
||||
hasInputFileType = true;
|
||||
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
||||
body.add("fileInput", file);
|
||||
|
||||
Iterator<Map.Entry<String, JsonNode>> parameters = parametersNode.fields();
|
||||
while (parameters.hasNext()) {
|
||||
Map.Entry<String, JsonNode> parameter = parameters.next();
|
||||
body.add(parameter.getKey(), parameter.getValue().asText());
|
||||
}
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
||||
|
||||
HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
String url = "http://localhost:8080/" + operation;
|
||||
|
||||
ResponseEntity<byte[]> response = restTemplate.exchange(url, HttpMethod.POST, entity, byte[].class);
|
||||
|
||||
if (!response.getStatusCode().equals(HttpStatus.OK)) {
|
||||
logPrintStream.println("Error: " + response.getBody());
|
||||
hasErrors = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the response body is a zip file
|
||||
if (isZip(response.getBody())) {
|
||||
// Unzip the file and add all the files to the new output files
|
||||
newOutputFiles.addAll(unzip(response.getBody()));
|
||||
} else {
|
||||
Resource outputResource = new ByteArrayResource(response.getBody()) {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return file.getFilename(); // Preserving original filename
|
||||
}
|
||||
};
|
||||
newOutputFiles.add(outputResource);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasInputFileType) {
|
||||
logPrintStream.println("No files with extension " + inputFileExtension + " found for operation " + operation);
|
||||
hasErrors = true;
|
||||
}
|
||||
|
||||
outputFiles = newOutputFiles;
|
||||
}
|
||||
logPrintStream.close();
|
||||
|
||||
}
|
||||
return outputFiles;
|
||||
}
|
||||
|
||||
|
||||
List<Resource> handleFiles(File[] files, String jsonString) throws Exception{
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode jsonNode = mapper.readTree(jsonString);
|
||||
|
||||
JsonNode pipelineNode = jsonNode.get("pipeline");
|
||||
ByteArrayOutputStream logStream = new ByteArrayOutputStream();
|
||||
PrintStream logPrintStream = new PrintStream(logStream);
|
||||
|
||||
boolean hasErrors = false;
|
||||
List<Resource> outputFiles = new ArrayList<>();
|
||||
|
||||
for (File file : files) {
|
||||
Path path = Paths.get(file.getAbsolutePath());
|
||||
Resource fileResource = new ByteArrayResource(Files.readAllBytes(path)) {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return file.getName();
|
||||
}
|
||||
};
|
||||
outputFiles.add(fileResource);
|
||||
}
|
||||
return processFiles(outputFiles, jsonString);
|
||||
}
|
||||
|
||||
List<Resource> handleFiles(MultipartFile[] files, String jsonString) throws Exception{
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode jsonNode = mapper.readTree(jsonString);
|
||||
|
||||
JsonNode pipelineNode = jsonNode.get("pipeline");
|
||||
ByteArrayOutputStream logStream = new ByteArrayOutputStream();
|
||||
PrintStream logPrintStream = new PrintStream(logStream);
|
||||
|
||||
boolean hasErrors = false;
|
||||
List<Resource> outputFiles = new ArrayList<>();
|
||||
|
||||
for (MultipartFile file : files) {
|
||||
Resource fileResource = new ByteArrayResource(file.getBytes()) {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return file.getOriginalFilename();
|
||||
}
|
||||
};
|
||||
outputFiles.add(fileResource);
|
||||
}
|
||||
return processFiles(outputFiles, jsonString);
|
||||
}
|
||||
|
||||
@PostMapping("/handleData")
|
||||
public ResponseEntity<byte[]> handleData(@RequestPart("fileInput") MultipartFile[] files,
|
||||
@RequestParam("json") String jsonString) {
|
||||
try {
|
||||
|
||||
List<Resource> outputFiles = handleFiles(files, jsonString);
|
||||
|
||||
if (outputFiles.size() == 1) {
|
||||
// If there is only one file, return it directly
|
||||
Resource singleFile = outputFiles.get(0);
|
||||
InputStream is = singleFile.getInputStream();
|
||||
byte[] bytes = new byte[(int)singleFile.contentLength()];
|
||||
is.read(bytes);
|
||||
is.close();
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(bytes, singleFile.getFilename(), MediaType.APPLICATION_OCTET_STREAM);
|
||||
}
|
||||
|
||||
// Create a ByteArrayOutputStream to hold the zip
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ZipOutputStream zipOut = new ZipOutputStream(baos);
|
||||
|
||||
// Loop through each file and add it to the zip
|
||||
for (Resource file : outputFiles) {
|
||||
ZipEntry zipEntry = new ZipEntry(file.getFilename());
|
||||
zipOut.putNextEntry(zipEntry);
|
||||
|
||||
// Read the file into a byte array
|
||||
InputStream is = file.getInputStream();
|
||||
byte[] bytes = new byte[(int)file.contentLength()];
|
||||
is.read(bytes);
|
||||
|
||||
// Write the bytes of the file to the zip
|
||||
zipOut.write(bytes, 0, bytes.length);
|
||||
zipOut.closeEntry();
|
||||
|
||||
is.close();
|
||||
}
|
||||
|
||||
zipOut.close();
|
||||
|
||||
return WebResponseUtils.boasToWebResponse(baos, "output.zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isZip(byte[] data) {
|
||||
if (data == null || data.length < 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the first four bytes of the data against the standard zip magic number
|
||||
return data[0] == 0x50 && data[1] == 0x4B && data[2] == 0x03 && data[3] == 0x04;
|
||||
}
|
||||
|
||||
private List<Resource> unzip(byte[] data) throws IOException {
|
||||
List<Resource> unzippedFiles = new ArrayList<>();
|
||||
|
||||
try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
ZipInputStream zis = new ZipInputStream(bais)) {
|
||||
|
||||
ZipEntry entry;
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int count;
|
||||
|
||||
while ((count = zis.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, count);
|
||||
}
|
||||
|
||||
final String filename = entry.getName();
|
||||
Resource fileResource = new ByteArrayResource(baos.toByteArray()) {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
};
|
||||
|
||||
// If the unzipped file is a zip file, unzip it
|
||||
if (isZip(baos.toByteArray())) {
|
||||
unzippedFiles.addAll(unzip(baos.toByteArray()));
|
||||
} else {
|
||||
unzippedFiles.add(fileResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return unzippedFiles;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package stirling.software.SPDF.controller.api.security;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -51,8 +50,11 @@ import com.itextpdf.signatures.SignatureUtil;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@RestController
|
||||
@Tag(name = "Security", description = "Security APIs")
|
||||
public class CertSignController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CertSignController.class);
|
||||
@@ -63,7 +65,7 @@ public class CertSignController {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/cert-sign")
|
||||
@Operation(summary = "Sign PDF with a Digital Certificate",
|
||||
description = "This endpoint accepts a PDF file, a digital certificate and related information to sign the PDF. It then returns the digitally signed PDF file.")
|
||||
description = "This endpoint accepts a PDF file, a digital certificate and related information to sign the PDF. It then returns the digitally signed PDF file. Input:PDF Output:PDF Type:MF-SISO")
|
||||
public ResponseEntity<byte[]> signPDF(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to be signed")
|
||||
@@ -177,8 +179,17 @@ public class CertSignController {
|
||||
String signingDate = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z").format(new Date());
|
||||
|
||||
// Prepare the text for the digital signature
|
||||
String layer2Text = String.format("Digitally signed by: %s\nDate: %s\nReason: %s\nLocation: %s", name, signingDate, reason, location);
|
||||
StringBuilder layer2TextBuilder = new StringBuilder(String.format("Digitally signed by: %s\nDate: %s",
|
||||
name != null ? name : "Unknown", signingDate));
|
||||
|
||||
if (reason != null && !reason.isEmpty()) {
|
||||
layer2TextBuilder.append("\nReason: ").append(reason);
|
||||
}
|
||||
|
||||
if (location != null && !location.isEmpty()) {
|
||||
layer2TextBuilder.append("\nLocation: ").append(location);
|
||||
}
|
||||
String layer2Text = layer2TextBuilder.toString();
|
||||
// Get the PDF font and measure the width and height of the text block
|
||||
PdfFont font = PdfFontFactory.createFont(StandardFonts.HELVETICA_BOLD);
|
||||
float textWidth = Arrays.stream(layer2Text.split("\n"))
|
||||
@@ -206,12 +217,12 @@ public class CertSignController {
|
||||
|
||||
// Configure the appearance of the digital signature
|
||||
appearance.setPageRect(rect)
|
||||
.setContact(name)
|
||||
.setPageNumber(pageNumber)
|
||||
.setReason(reason)
|
||||
.setLocation(location)
|
||||
.setReuseAppearance(false)
|
||||
.setLayer2Text(layer2Text);
|
||||
.setContact(name != null ? name : "")
|
||||
.setPageNumber(pageNumber)
|
||||
.setReason(reason != null ? reason : "")
|
||||
.setLocation(location != null ? location : "")
|
||||
.setReuseAppearance(false)
|
||||
.setLayer2Text(layer2Text.toString());
|
||||
|
||||
signer.setFieldName("sig");
|
||||
} else {
|
||||
@@ -230,7 +241,7 @@ public class CertSignController {
|
||||
System.out.println("Signed PDF size: " + signedPdf.size());
|
||||
|
||||
System.out.println("PDF signed = " + isPdfSigned(signedPdf.toByteArray()));
|
||||
return PdfUtils.bytesToWebResponse(signedPdf.toByteArray(), "example.pdf");
|
||||
return WebResponseUtils.bytesToWebResponse(signedPdf.toByteArray(), "example.pdf");
|
||||
}
|
||||
|
||||
public boolean isPdfSigned(byte[] pdfData) throws IOException {
|
||||
|
||||
@@ -17,8 +17,10 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@RestController
|
||||
@Tag(name = "Security", description = "Security APIs")
|
||||
public class PasswordController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PasswordController.class);
|
||||
@@ -27,7 +29,7 @@ public class PasswordController {
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-password")
|
||||
@Operation(
|
||||
summary = "Remove password from a PDF file",
|
||||
description = "This endpoint removes the password from a protected PDF file. Users need to provide the existing password."
|
||||
description = "This endpoint removes the password from a protected PDF file. Users need to provide the existing password. Input:PDF Output:PDF Type:SISO"
|
||||
)
|
||||
public ResponseEntity<byte[]> removePassword(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@@ -38,20 +40,23 @@ public class PasswordController {
|
||||
String password) throws IOException {
|
||||
PDDocument document = PDDocument.load(fileInput.getBytes(), password);
|
||||
document.setAllSecurityToBeRemoved(true);
|
||||
return PdfUtils.pdfDocToWebResponse(document, fileInput.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_password_removed.pdf");
|
||||
return WebResponseUtils.pdfDocToWebResponse(document, fileInput.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_password_removed.pdf");
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/add-password")
|
||||
@Operation(
|
||||
summary = "Add password to a PDF file",
|
||||
description = "This endpoint adds password protection to a PDF file. Users can specify a set of permissions that should be applied to the file."
|
||||
description = "This endpoint adds password protection to a PDF file. Users can specify a set of permissions that should be applied to the file. Input:PDF Output:PDF"
|
||||
)
|
||||
public ResponseEntity<byte[]> addPassword(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to which the password should be added", required = true)
|
||||
MultipartFile fileInput,
|
||||
@RequestParam(defaultValue = "", name = "ownerPassword")
|
||||
@Parameter(description = "The owner password to be added to the PDF file (Restricts what can be done with the document once it is opened)")
|
||||
String ownerPassword,
|
||||
@RequestParam(defaultValue = "", name = "password")
|
||||
@Parameter(description = "The password to be added to the PDF file")
|
||||
@Parameter(description = "The password to be added to the PDF file (Restricts the opening of the document itself.)")
|
||||
String password,
|
||||
@RequestParam(defaultValue = "128", name = "keyLength")
|
||||
@Parameter(description = "The length of the encryption key", schema = @Schema(allowableValues = {"40", "128", "256"}))
|
||||
@@ -84,7 +89,6 @@ public class PasswordController {
|
||||
|
||||
PDDocument document = PDDocument.load(fileInput.getBytes());
|
||||
AccessPermission ap = new AccessPermission();
|
||||
|
||||
ap.setCanAssembleDocument(!canAssembleDocument);
|
||||
ap.setCanExtractContent(!canExtractContent);
|
||||
ap.setCanExtractForAccessibility(!canExtractForAccessibility);
|
||||
@@ -93,14 +97,17 @@ public class PasswordController {
|
||||
ap.setCanModifyAnnotations(!canModifyAnnotations);
|
||||
ap.setCanPrint(!canPrint);
|
||||
ap.setCanPrintFaithful(!canPrintFaithful);
|
||||
StandardProtectionPolicy spp = new StandardProtectionPolicy(password, password, ap);
|
||||
StandardProtectionPolicy spp = new StandardProtectionPolicy(ownerPassword, password, ap);
|
||||
|
||||
|
||||
|
||||
spp.setEncryptionKeyLength(keyLength);
|
||||
|
||||
spp.setPermissions(ap);
|
||||
|
||||
document.protect(spp);
|
||||
|
||||
return PdfUtils.pdfDocToWebResponse(document, fileInput.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_passworded.pdf");
|
||||
return WebResponseUtils.pdfDocToWebResponse(document, fileInput.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_passworded.pdf");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
package stirling.software.SPDF.controller.api.security;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.font.PDFont;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType0Font;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
|
||||
import org.apache.pdfbox.util.Matrix;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@@ -19,18 +27,26 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@RestController
|
||||
@Tag(name = "Security", description = "Security APIs")
|
||||
public class WatermarkController {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/add-watermark")
|
||||
@Operation(summary = "Add watermark to a PDF file",
|
||||
description = "This endpoint adds a watermark to a given PDF file. Users can specify the watermark text, font size, rotation, opacity, width spacer, and height spacer.")
|
||||
description = "This endpoint adds a watermark to a given PDF file. Users can specify the watermark text, font size, rotation, opacity, width spacer, and height spacer. Input:PDF Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> addWatermark(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to add a watermark")
|
||||
MultipartFile pdfFile,
|
||||
@RequestParam(defaultValue = "roman", name = "alphabet")
|
||||
@Parameter(description = "The selected alphabet",
|
||||
schema = @Schema(type = "string",
|
||||
allowableValues = {"roman","arabic","japanese","korean","chinese"},
|
||||
defaultValue = "roman"))
|
||||
String alphabet,
|
||||
@RequestParam("watermarkText")
|
||||
@Parameter(description = "The watermark text to add to the PDF file")
|
||||
String watermarkText,
|
||||
@@ -48,11 +64,11 @@ public class WatermarkController {
|
||||
int widthSpacer,
|
||||
@RequestParam(defaultValue = "50", name = "heightSpacer")
|
||||
@Parameter(description = "The height spacer between watermark texts", example = "50")
|
||||
int heightSpacer) throws IOException {
|
||||
int heightSpacer) throws IOException, Exception {
|
||||
|
||||
// Load the input PDF
|
||||
PDDocument document = PDDocument.load(pdfFile.getInputStream());
|
||||
|
||||
String producer = document.getDocumentInformation().getProducer();
|
||||
// Create a page in the document
|
||||
for (PDPage page : document.getPages()) {
|
||||
|
||||
@@ -64,8 +80,40 @@ public class WatermarkController {
|
||||
graphicsState.setNonStrokingAlphaConstant(opacity);
|
||||
contentStream.setGraphicsStateParameters(graphicsState);
|
||||
|
||||
// Set font of watermark
|
||||
PDFont font = PDType1Font.HELVETICA_BOLD;
|
||||
|
||||
String resourceDir = "";
|
||||
PDFont font = PDType1Font.HELVETICA_BOLD;
|
||||
switch (alphabet) {
|
||||
case "arabic":
|
||||
resourceDir = "static/fonts/NotoSansArabic-Regular.ttf";
|
||||
break;
|
||||
case "japanese":
|
||||
resourceDir = "static/fonts/Meiryo.ttf";
|
||||
break;
|
||||
case "korean":
|
||||
resourceDir = "static/fonts/malgun.ttf";
|
||||
break;
|
||||
case "chinese":
|
||||
resourceDir = "static/fonts/SimSun.ttf";
|
||||
break;
|
||||
case "roman":
|
||||
default:
|
||||
resourceDir = "static/fonts/NotoSans-Regular.ttf";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(!resourceDir.equals("")) {
|
||||
ClassPathResource classPathResource = new ClassPathResource(resourceDir);
|
||||
String fileExtension = resourceDir.substring(resourceDir.lastIndexOf("."));
|
||||
File tempFile = File.createTempFile("NotoSansFont", fileExtension);
|
||||
try (InputStream is = classPathResource.getInputStream(); FileOutputStream os = new FileOutputStream(tempFile)) {
|
||||
IOUtils.copy(is, os);
|
||||
}
|
||||
|
||||
font = PDType0Font.load(document, tempFile);
|
||||
tempFile.deleteOnExit();
|
||||
}
|
||||
contentStream.beginText();
|
||||
contentStream.setFont(font, fontSize);
|
||||
contentStream.setNonStrokingColor(Color.LIGHT_GRAY);
|
||||
@@ -81,17 +129,25 @@ public class WatermarkController {
|
||||
// Add the watermark text
|
||||
for (int i = 0; i < watermarkRows; i++) {
|
||||
for (int j = 0; j < watermarkCols; j++) {
|
||||
contentStream.setTextMatrix(Matrix.getRotateInstance((float) Math.toRadians(rotation), j * watermarkWidth, i * watermarkHeight));
|
||||
|
||||
if(producer.contains("Google Docs")) {
|
||||
//This fixes weird unknown google docs y axis rotation/flip issue
|
||||
//TODO: Long term fix one day
|
||||
//contentStream.setTextMatrix(1, 0, 0, -1, j * watermarkWidth, pageHeight - i * watermarkHeight);
|
||||
Matrix matrix = new Matrix(1, 0, 0, -1, j * watermarkWidth, pageHeight - i * watermarkHeight);
|
||||
contentStream.setTextMatrix(matrix);
|
||||
} else {
|
||||
contentStream.setTextMatrix(Matrix.getRotateInstance((float) Math.toRadians(rotation), j * watermarkWidth, i * watermarkHeight));
|
||||
}
|
||||
contentStream.showTextWithPositioning(new Object[] { watermarkText });
|
||||
}
|
||||
}
|
||||
|
||||
contentStream.endText();
|
||||
|
||||
// Close the content stream
|
||||
contentStream.close();
|
||||
}
|
||||
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_watermarked.pdf");
|
||||
return WebResponseUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_watermarked.pdf");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
@Controller
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
public class ConverterWebController {
|
||||
|
||||
@GetMapping("/img-to-pdf")
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
package stirling.software.SPDF.controller.web;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
@Controller
|
||||
@Tag(name = "General", description = "General APIs")
|
||||
public class GeneralWebController {
|
||||
@GetMapping("/pipeline")
|
||||
@Hidden
|
||||
public String pipelineForm(Model model) {
|
||||
model.addAttribute("currentPage", "pipeline");
|
||||
return "pipeline";
|
||||
}
|
||||
|
||||
@GetMapping("/merge-pdfs")
|
||||
@Hidden
|
||||
public String mergePdfForm(Model model) {
|
||||
model.addAttribute("currentPage", "merge-pdfs");
|
||||
return "merge-pdfs";
|
||||
}
|
||||
@GetMapping("/about")
|
||||
@Hidden
|
||||
public String gameForm(Model model) {
|
||||
model.addAttribute("currentPage", "about");
|
||||
return "about";
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/multi-tool")
|
||||
@Hidden
|
||||
@@ -29,17 +31,7 @@ public class GeneralWebController {
|
||||
model.addAttribute("currentPage", "multi-tool");
|
||||
return "multi-tool";
|
||||
}
|
||||
|
||||
@GetMapping("/")
|
||||
public String home(Model model) {
|
||||
model.addAttribute("currentPage", "home");
|
||||
return "home";
|
||||
}
|
||||
|
||||
@GetMapping("/home")
|
||||
public String root(Model model) {
|
||||
return "redirect:/";
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/remove-pages")
|
||||
@Hidden
|
||||
@@ -76,20 +68,4 @@ public class GeneralWebController {
|
||||
return "sign";
|
||||
}
|
||||
|
||||
@GetMapping(value = "/robots.txt", produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
@ResponseBody
|
||||
@Hidden
|
||||
public String getRobotsTxt() {
|
||||
String allowGoogleVisibility = System.getProperty("ALLOW_GOOGLE_VISIBILITY");
|
||||
if (allowGoogleVisibility == null)
|
||||
allowGoogleVisibility = System.getenv("ALLOW_GOOGLE_VISIBILITY");
|
||||
if (allowGoogleVisibility == null)
|
||||
allowGoogleVisibility = "false";
|
||||
if (Boolean.parseBoolean(allowGoogleVisibility)) {
|
||||
return "User-agent: Googlebot\nAllow: /\n\nUser-agent: *\nAllow: /";
|
||||
} else {
|
||||
return "User-agent: Googlebot\nDisallow: /\n\nUser-agent: *\nDisallow: /";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package stirling.software.SPDF.controller.web;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
|
||||
@Controller
|
||||
public class HomeWebController {
|
||||
|
||||
@GetMapping("/about")
|
||||
@Hidden
|
||||
public String gameForm(Model model) {
|
||||
model.addAttribute("currentPage", "about");
|
||||
return "about";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GetMapping("/")
|
||||
public String home(Model model) {
|
||||
model.addAttribute("currentPage", "home");
|
||||
return "home";
|
||||
}
|
||||
|
||||
@GetMapping("/home")
|
||||
public String root(Model model) {
|
||||
return "redirect:/";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GetMapping(value = "/robots.txt", produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
@ResponseBody
|
||||
@Hidden
|
||||
public String getRobotsTxt() {
|
||||
String allowGoogleVisibility = System.getProperty("ALLOW_GOOGLE_VISIBILITY");
|
||||
if (allowGoogleVisibility == null)
|
||||
allowGoogleVisibility = System.getenv("ALLOW_GOOGLE_VISIBILITY");
|
||||
if (allowGoogleVisibility == null)
|
||||
allowGoogleVisibility = "false";
|
||||
if (Boolean.parseBoolean(allowGoogleVisibility)) {
|
||||
return "User-agent: Googlebot\nAllow: /\n\nUser-agent: *\nAllow: /";
|
||||
} else {
|
||||
return "User-agent: Googlebot\nDisallow: /\n\nUser-agent: *\nDisallow: /";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,9 +12,12 @@ import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1")
|
||||
@Tag(name = "API", description = "Info APIs")
|
||||
public class MetricsController {
|
||||
|
||||
private final MeterRegistry meterRegistry;
|
||||
@@ -36,17 +39,31 @@ public class MetricsController {
|
||||
@GetMapping("/loads")
|
||||
@Operation(summary = "GET request count",
|
||||
description = "This endpoint returns the total count of GET requests or the count of GET requests for a specific endpoint.")
|
||||
public Double getPageLoads(@RequestParam Optional<String> endpoint) {
|
||||
public Double getPageLoads(@RequestParam(required = false, name = "endpoint") @Parameter(description = "endpoint") Optional<String> endpoint) {
|
||||
try {
|
||||
double count = 0.0;
|
||||
|
||||
double count = 0.0;
|
||||
|
||||
for (Meter meter : meterRegistry.getMeters()) {
|
||||
if (meter.getId().getName().equals("http.requests")) {
|
||||
String method = meter.getId().getTag("method");
|
||||
if (method != null && method.equals("GET")) {
|
||||
if (meter instanceof Counter) {
|
||||
count += ((Counter) meter).count();
|
||||
}
|
||||
|
||||
if (endpoint.isPresent() && !endpoint.get().isBlank()) {
|
||||
if(!endpoint.get().startsWith("/")) {
|
||||
endpoint = Optional.of("/" + endpoint.get());
|
||||
}
|
||||
System.out.println("loads " + endpoint.get() + " vs " + meter.getId().getTag("uri"));
|
||||
if(endpoint.get().equals(meter.getId().getTag("uri"))){
|
||||
if (meter instanceof Counter) {
|
||||
count += ((Counter) meter).count();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (meter instanceof Counter) {
|
||||
count += ((Counter) meter).count();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,10 +77,15 @@ public class MetricsController {
|
||||
@GetMapping("/requests")
|
||||
@Operation(summary = "POST request count",
|
||||
description = "This endpoint returns the total count of POST requests or the count of POST requests for a specific endpoint.")
|
||||
public Double getTotalRequests(@RequestParam Optional<String> endpoint) {
|
||||
public Double getTotalRequests(@RequestParam(required = false, name = "endpoint") @Parameter(description = "endpoint") Optional<String> endpoint) {
|
||||
try {
|
||||
Counter counter;
|
||||
if (endpoint.isPresent()) {
|
||||
if (endpoint.isPresent() && !endpoint.get().isBlank()) {
|
||||
if(!endpoint.get().startsWith("/")) {
|
||||
endpoint = Optional.of("/" + endpoint.get());
|
||||
}
|
||||
|
||||
System.out.println("loads " + endpoint.get() + " vs " + meterRegistry.get("http.requests").tags("uri", endpoint.get()).toString());
|
||||
counter = meterRegistry.get("http.requests")
|
||||
.tags("method", "POST", "uri", endpoint.get()).counter();
|
||||
} else {
|
||||
@@ -72,7 +94,8 @@ public class MetricsController {
|
||||
}
|
||||
return counter.count();
|
||||
} catch (Exception e) {
|
||||
return -1.0;
|
||||
e.printStackTrace();
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,8 +12,10 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
@Controller
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class OtherWebController {
|
||||
@GetMapping("/compress-pdf")
|
||||
@Hidden
|
||||
@@ -74,7 +76,9 @@ public class OtherWebController {
|
||||
@Hidden
|
||||
public ModelAndView ocrPdfPage() {
|
||||
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");
|
||||
return modelAndView;
|
||||
}
|
||||
@@ -108,4 +112,25 @@ public class OtherWebController {
|
||||
return "other/remove-blanks";
|
||||
}
|
||||
|
||||
@GetMapping("/multi-page-layout")
|
||||
@Hidden
|
||||
public String multiPageLayoutForm(Model model) {
|
||||
model.addAttribute("currentPage", "multi-page-layout");
|
||||
return "other/multi-page-layout";
|
||||
}
|
||||
|
||||
@GetMapping("/scale-pages")
|
||||
@Hidden
|
||||
public String scalePagesFrom(Model model) {
|
||||
model.addAttribute("currentPage", "scale-pages");
|
||||
return "other/scale-pages";
|
||||
}
|
||||
|
||||
@GetMapping("/auto-crop")
|
||||
@Hidden
|
||||
public String autoCropForm(Model model) {
|
||||
model.addAttribute("currentPage", "auto-crop");
|
||||
return "other/auto-crop";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
@Controller
|
||||
@Tag(name = "Security", description = "Security APIs")
|
||||
public class SecurityWebController {
|
||||
@GetMapping("/add-password")
|
||||
@Hidden
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package stirling.software.SPDF.model;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class PipelineConfig {
|
||||
private String name;
|
||||
|
||||
@JsonProperty("pipeline")
|
||||
private List<PipelineOperation> operations;
|
||||
|
||||
private String outputDir;
|
||||
|
||||
@JsonProperty("outputFileName")
|
||||
private String outputPattern;
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<PipelineOperation> getOperations() {
|
||||
return operations;
|
||||
}
|
||||
|
||||
public void setOperations(List<PipelineOperation> operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
public String getOutputDir() {
|
||||
return outputDir;
|
||||
}
|
||||
|
||||
public void setOutputDir(String outputDir) {
|
||||
this.outputDir = outputDir;
|
||||
}
|
||||
|
||||
public String getOutputPattern() {
|
||||
return outputPattern;
|
||||
}
|
||||
|
||||
public void setOutputPattern(String outputPattern) {
|
||||
this.outputPattern = outputPattern;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package stirling.software.SPDF.model;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class PipelineOperation {
|
||||
private String operation;
|
||||
private Map<String, Object> parameters;
|
||||
|
||||
|
||||
public String getOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
public void setOperation(String operation) {
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
public Map<String, Object> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(Map<String, Object> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
package stirling.software.SPDF.pdf;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
import java.io.IOException;
|
||||
91
src/main/java/stirling/software/SPDF/utils/GeneralUtils.java
Normal file
91
src/main/java/stirling/software/SPDF/utils/GeneralUtils.java
Normal file
@@ -0,0 +1,91 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GeneralUtils {
|
||||
|
||||
public static Long convertSizeToBytes(String sizeStr) {
|
||||
if (sizeStr == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
sizeStr = sizeStr.trim().toUpperCase();
|
||||
try {
|
||||
if (sizeStr.endsWith("KB")) {
|
||||
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024);
|
||||
} else if (sizeStr.endsWith("MB")) {
|
||||
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024 * 1024);
|
||||
} else if (sizeStr.endsWith("GB")) {
|
||||
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024 * 1024 * 1024);
|
||||
} else if (sizeStr.endsWith("B")) {
|
||||
return Long.parseLong(sizeStr.substring(0, sizeStr.length() - 1));
|
||||
} else {
|
||||
// Input string does not have a valid format, handle this case
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// The numeric part of the input string cannot be parsed, handle this case
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<Integer> parsePageList(String[] pageOrderArr, int totalPages) {
|
||||
List<Integer> newPageOrder = new ArrayList<>();
|
||||
|
||||
// loop through the page order array
|
||||
for (String element : pageOrderArr) {
|
||||
// check if the element contains a range of pages
|
||||
if (element.matches("\\d*n\\+?-?\\d*|\\d*\\+?n")) {
|
||||
// Handle page order as a function
|
||||
int coefficient = 0;
|
||||
int constant = 0;
|
||||
boolean coefficientExists = false;
|
||||
boolean constantExists = false;
|
||||
|
||||
if (element.contains("n")) {
|
||||
String[] parts = element.split("n");
|
||||
if (!parts[0].equals("") && parts[0] != null) {
|
||||
coefficient = Integer.parseInt(parts[0]);
|
||||
coefficientExists = true;
|
||||
}
|
||||
if (parts.length > 1 && !parts[1].equals("") && parts[1] != null) {
|
||||
constant = Integer.parseInt(parts[1]);
|
||||
constantExists = true;
|
||||
}
|
||||
} else if (element.contains("+")) {
|
||||
constant = Integer.parseInt(element.replace("+", ""));
|
||||
constantExists = true;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= totalPages; i++) {
|
||||
int pageNum = coefficientExists ? coefficient * i : i;
|
||||
pageNum += constantExists ? constant : 0;
|
||||
|
||||
if (pageNum <= totalPages && pageNum > 0) {
|
||||
newPageOrder.add(pageNum - 1);
|
||||
}
|
||||
}
|
||||
} else if (element.contains("-")) {
|
||||
// split the range into start and end page
|
||||
String[] range = element.split("-");
|
||||
int start = Integer.parseInt(range[0]);
|
||||
int end = Integer.parseInt(range[1]);
|
||||
// check if the end page is greater than total pages
|
||||
if (end > totalPages) {
|
||||
end = totalPages;
|
||||
}
|
||||
// loop through the range of pages
|
||||
for (int j = start; j <= end; j++) {
|
||||
// print the current index
|
||||
newPageOrder.add(j - 1);
|
||||
}
|
||||
} else {
|
||||
// if the element is a single page
|
||||
newPageOrder.add(Integer.parseInt(element) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return newPageOrder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public class ImageProcessingUtils {
|
||||
|
||||
static BufferedImage convertColorType(BufferedImage sourceImage, String colorType) {
|
||||
BufferedImage convertedImage;
|
||||
switch (colorType) {
|
||||
case "greyscale":
|
||||
convertedImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
|
||||
convertedImage.getGraphics().drawImage(sourceImage, 0, 0, null);
|
||||
break;
|
||||
case "blackwhite":
|
||||
convertedImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
|
||||
convertedImage.getGraphics().drawImage(sourceImage, 0, 0, null);
|
||||
break;
|
||||
default: // full color
|
||||
convertedImage = sourceImage;
|
||||
break;
|
||||
}
|
||||
return convertedImage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
public class PDFManipulationUtils {
|
||||
|
||||
}
|
||||
@@ -92,6 +92,6 @@ public class PDFToFile {
|
||||
if (tempOutputDir != null)
|
||||
FileUtils.deleteDirectory(tempOutputDir.toFile());
|
||||
}
|
||||
return PdfUtils.bytesToWebResponse(fileBytes, fileName, MediaType.APPLICATION_OCTET_STREAM);
|
||||
return WebResponseUtils.bytesToWebResponse(fileBytes, fileName, MediaType.APPLICATION_OCTET_STREAM);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,15 +8,7 @@ import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -30,46 +22,185 @@ import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.apache.pdfbox.rendering.ImageType;
|
||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
import org.apache.pdfbox.text.PDFTextStripper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.kernel.pdf.PdfPage;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.PdfTextExtractor;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.listener.SimpleTextExtractionStrategy;
|
||||
|
||||
import stirling.software.SPDF.pdf.ImageFinder;
|
||||
|
||||
public class PdfUtils {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PdfUtils.class);
|
||||
|
||||
public static ResponseEntity<byte[]> boasToWebResponse(ByteArrayOutputStream baos, String docName) throws IOException {
|
||||
return PdfUtils.bytesToWebResponse(baos.toByteArray(), docName);
|
||||
|
||||
public static PDRectangle textToPageSize(String size) {
|
||||
switch (size) {
|
||||
case "A0":
|
||||
return PDRectangle.A0;
|
||||
case "A1":
|
||||
return PDRectangle.A1;
|
||||
case "A2":
|
||||
return PDRectangle.A2;
|
||||
case "A3":
|
||||
return PDRectangle.A3;
|
||||
case "A4":
|
||||
return PDRectangle.A4;
|
||||
case "A5":
|
||||
return PDRectangle.A5;
|
||||
case "A6":
|
||||
return PDRectangle.A6;
|
||||
case "LETTER":
|
||||
return PDRectangle.LETTER;
|
||||
case "LEGAL":
|
||||
return PDRectangle.LEGAL;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid standard page size: " + size);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasImageInFile(PDDocument pdfDocument, String text, String pagesToCheck) throws IOException {
|
||||
PDFTextStripper textStripper = new PDFTextStripper();
|
||||
String pdfText = "";
|
||||
|
||||
if(pagesToCheck == null || pagesToCheck.equals("all")) {
|
||||
pdfText = textStripper.getText(pdfDocument);
|
||||
} else {
|
||||
// remove whitespaces
|
||||
pagesToCheck = pagesToCheck.replaceAll("\\s+", "");
|
||||
|
||||
String[] splitPoints = pagesToCheck.split(",");
|
||||
for (String splitPoint : splitPoints) {
|
||||
if (splitPoint.contains("-")) {
|
||||
// Handle page ranges
|
||||
String[] range = splitPoint.split("-");
|
||||
int startPage = Integer.parseInt(range[0]);
|
||||
int endPage = Integer.parseInt(range[1]);
|
||||
|
||||
for (int i = startPage; i <= endPage; i++) {
|
||||
textStripper.setStartPage(i);
|
||||
textStripper.setEndPage(i);
|
||||
pdfText += textStripper.getText(pdfDocument);
|
||||
}
|
||||
} else {
|
||||
// Handle individual page
|
||||
int page = Integer.parseInt(splitPoint);
|
||||
textStripper.setStartPage(page);
|
||||
textStripper.setEndPage(page);
|
||||
pdfText += textStripper.getText(pdfDocument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pdfDocument.close();
|
||||
|
||||
return pdfText.contains(text);
|
||||
}
|
||||
|
||||
public static boolean hasImagesOnPage(PDPage page) throws IOException {
|
||||
ImageFinder imageFinder = new ImageFinder(page);
|
||||
imageFinder.processPage(page);
|
||||
return imageFinder.hasImages();
|
||||
}
|
||||
|
||||
|
||||
public static boolean hasText(PDDocument document, String phrase) throws IOException {
|
||||
PDFTextStripper pdfStripper = new PDFTextStripper();
|
||||
String text = pdfStripper.getText(document);
|
||||
return text.contains(phrase);
|
||||
}
|
||||
|
||||
|
||||
public boolean containsTextInFile(PDDocument pdfDocument, String text, String pagesToCheck) throws IOException {
|
||||
PDFTextStripper textStripper = new PDFTextStripper();
|
||||
String pdfText = "";
|
||||
|
||||
if(pagesToCheck == null || pagesToCheck.equals("all")) {
|
||||
pdfText = textStripper.getText(pdfDocument);
|
||||
} else {
|
||||
// remove whitespaces
|
||||
pagesToCheck = pagesToCheck.replaceAll("\\s+", "");
|
||||
|
||||
String[] splitPoints = pagesToCheck.split(",");
|
||||
for (String splitPoint : splitPoints) {
|
||||
if (splitPoint.contains("-")) {
|
||||
// Handle page ranges
|
||||
String[] range = splitPoint.split("-");
|
||||
int startPage = Integer.parseInt(range[0]);
|
||||
int endPage = Integer.parseInt(range[1]);
|
||||
|
||||
for (int i = startPage; i <= endPage; i++) {
|
||||
textStripper.setStartPage(i);
|
||||
textStripper.setEndPage(i);
|
||||
pdfText += textStripper.getText(pdfDocument);
|
||||
}
|
||||
} else {
|
||||
// Handle individual page
|
||||
int page = Integer.parseInt(splitPoint);
|
||||
textStripper.setStartPage(page);
|
||||
textStripper.setEndPage(page);
|
||||
pdfText += textStripper.getText(pdfDocument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pdfDocument.close();
|
||||
|
||||
return pdfText.contains(text);
|
||||
}
|
||||
|
||||
public static ResponseEntity<byte[]> boasToWebResponse(ByteArrayOutputStream baos, String docName, MediaType mediaType) throws IOException {
|
||||
return PdfUtils.bytesToWebResponse(baos.toByteArray(), docName, mediaType);
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean pageCount(PDDocument pdfDocument, int pageCount, String comparator) throws IOException {
|
||||
int actualPageCount = pdfDocument.getNumberOfPages();
|
||||
pdfDocument.close();
|
||||
|
||||
switch(comparator.toLowerCase()) {
|
||||
case "greater":
|
||||
return actualPageCount > pageCount;
|
||||
case "equal":
|
||||
return actualPageCount == pageCount;
|
||||
case "less":
|
||||
return actualPageCount < pageCount;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid comparator. Only 'greater', 'equal', and 'less' are supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public static ResponseEntity<byte[]> bytesToWebResponse(byte[] bytes, String docName, MediaType mediaType) throws IOException {
|
||||
public boolean pageSize(PDDocument pdfDocument, String expectedPageSize) throws IOException {
|
||||
PDPage firstPage = pdfDocument.getPage(0);
|
||||
PDRectangle mediaBox = firstPage.getMediaBox();
|
||||
|
||||
// Return the PDF as a response
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(mediaType);
|
||||
headers.setContentLength(bytes.length);
|
||||
String encodedDocName = URLEncoder.encode(docName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
|
||||
headers.setContentDispositionFormData("attachment", encodedDocName);
|
||||
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
|
||||
float actualPageWidth = mediaBox.getWidth();
|
||||
float actualPageHeight = mediaBox.getHeight();
|
||||
|
||||
pdfDocument.close();
|
||||
|
||||
// Assumes the expectedPageSize is in the format "widthxheight", e.g. "595x842" for A4
|
||||
String[] dimensions = expectedPageSize.split("x");
|
||||
float expectedPageWidth = Float.parseFloat(dimensions[0]);
|
||||
float expectedPageHeight = Float.parseFloat(dimensions[1]);
|
||||
|
||||
// Checks if the actual page size matches the expected page size
|
||||
return actualPageWidth == expectedPageWidth && actualPageHeight == expectedPageHeight;
|
||||
}
|
||||
|
||||
public static ResponseEntity<byte[]> bytesToWebResponse(byte[] bytes, String docName) throws IOException {
|
||||
return bytesToWebResponse(bytes, docName, MediaType.APPLICATION_PDF);
|
||||
}
|
||||
|
||||
public static byte[] convertFromPdf(byte[] inputStream, String imageType, ImageType colorType, boolean singleImage, int DPI) throws IOException, Exception {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static byte[] convertFromPdf(byte[] inputStream, String imageType, ImageType colorType, boolean singleImage, int DPI, String filename) throws IOException, Exception {
|
||||
try (PDDocument document = PDDocument.load(new ByteArrayInputStream(inputStream))) {
|
||||
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
||||
int pageCount = document.getNumberOfPages();
|
||||
@@ -77,7 +208,7 @@ public class PdfUtils {
|
||||
|
||||
// Create images of all pages
|
||||
for (int i = 0; i < pageCount; i++) {
|
||||
images.add(pdfRenderer.renderImageWithDPI(i, 300, colorType));
|
||||
images.add(pdfRenderer.renderImageWithDPI(i, DPI, colorType));
|
||||
}
|
||||
|
||||
if (singleImage) {
|
||||
@@ -107,7 +238,7 @@ public class PdfUtils {
|
||||
ImageIO.write(image, imageType, baosImage);
|
||||
|
||||
// Add the image to the zip file
|
||||
zos.putNextEntry(new ZipEntry(String.format("page_%d.%s", i + 1, imageType.toLowerCase())));
|
||||
zos.putNextEntry(new ZipEntry(String.format(filename + "_%d.%s", i + 1, imageType.toLowerCase())));
|
||||
zos.write(baosImage.toByteArray());
|
||||
}
|
||||
}
|
||||
@@ -125,6 +256,7 @@ public class PdfUtils {
|
||||
public static byte[] imageToPdf(MultipartFile[] files, boolean stretchToFit, boolean autoRotate, String colorType) throws IOException {
|
||||
try (PDDocument doc = new PDDocument()) {
|
||||
for (MultipartFile file : files) {
|
||||
String contentType = file.getContentType();
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
if (originalFilename != null && (originalFilename.toLowerCase().endsWith(".tiff") || originalFilename.toLowerCase().endsWith(".tif")) ) {
|
||||
ImageReader reader = ImageIO.getImageReadersByFormatName("tiff").next();
|
||||
@@ -132,7 +264,7 @@ public class PdfUtils {
|
||||
int numPages = reader.getNumImages(true);
|
||||
for (int i = 0; i < numPages; i++) {
|
||||
BufferedImage pageImage = reader.read(i);
|
||||
BufferedImage convertedImage = convertColorType(pageImage, colorType);
|
||||
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(pageImage, colorType);
|
||||
PDImageXObject pdImage = LosslessFactory.createFromImage(doc, convertedImage);
|
||||
addImageToDocument(doc, pdImage, stretchToFit, autoRotate);
|
||||
}
|
||||
@@ -145,8 +277,13 @@ public class PdfUtils {
|
||||
fos.write(buffer, 0, len);
|
||||
}
|
||||
BufferedImage image = ImageIO.read(imageFile);
|
||||
BufferedImage convertedImage = convertColorType(image, colorType);
|
||||
PDImageXObject pdImage = LosslessFactory.createFromImage(doc, convertedImage);
|
||||
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(image, colorType);
|
||||
PDImageXObject pdImage;
|
||||
if (contentType != null && (contentType.equals("image/jpeg"))) {
|
||||
pdImage = JPEGFactory.createFromImage(doc, convertedImage);
|
||||
} else {
|
||||
pdImage = LosslessFactory.createFromImage(doc, convertedImage);
|
||||
}
|
||||
addImageToDocument(doc, pdImage, stretchToFit, autoRotate);
|
||||
} catch (IOException e) {
|
||||
logger.error("Error writing image to file: {}", imageFile.getAbsolutePath(), e);
|
||||
@@ -163,24 +300,6 @@ public class PdfUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static BufferedImage convertColorType(BufferedImage sourceImage, String colorType) {
|
||||
BufferedImage convertedImage;
|
||||
switch (colorType) {
|
||||
case "greyscale":
|
||||
convertedImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
|
||||
convertedImage.getGraphics().drawImage(sourceImage, 0, 0, null);
|
||||
break;
|
||||
case "blackwhite":
|
||||
convertedImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
|
||||
convertedImage.getGraphics().drawImage(sourceImage, 0, 0, null);
|
||||
break;
|
||||
default: // full color
|
||||
convertedImage = sourceImage;
|
||||
break;
|
||||
}
|
||||
return convertedImage;
|
||||
}
|
||||
|
||||
private static void addImageToDocument(PDDocument doc, PDImageXObject image, boolean stretchToFit, boolean autoRotate) throws IOException {
|
||||
boolean imageIsLandscape = image.getWidth() > image.getHeight();
|
||||
PDRectangle pageSize = PDRectangle.A4;
|
||||
@@ -217,33 +336,6 @@ public class PdfUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static X509Certificate[] loadCertificateChainFromKeystore(InputStream keystoreInputStream, String keystorePassword) throws Exception {
|
||||
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keystore.load(keystoreInputStream, keystorePassword.toCharArray());
|
||||
|
||||
String alias = keystore.aliases().nextElement();
|
||||
Certificate[] certChain = keystore.getCertificateChain(alias);
|
||||
X509Certificate[] x509CertChain = new X509Certificate[certChain.length];
|
||||
|
||||
for (int i = 0; i < certChain.length; i++) {
|
||||
x509CertChain[i] = (X509Certificate) certChain[i];
|
||||
}
|
||||
|
||||
return x509CertChain;
|
||||
}
|
||||
|
||||
public static KeyPair loadKeyPairFromKeystore(InputStream keystoreInputStream, String keystorePassword) throws Exception {
|
||||
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keystore.load(keystoreInputStream, keystorePassword.toCharArray());
|
||||
|
||||
String alias = keystore.aliases().nextElement();
|
||||
PrivateKey privateKey = (PrivateKey) keystore.getKey(alias, keystorePassword.toCharArray());
|
||||
Certificate cert = keystore.getCertificate(alias);
|
||||
PublicKey publicKey = cert.getPublicKey();
|
||||
|
||||
return new KeyPair(publicKey, privateKey);
|
||||
}
|
||||
|
||||
public static byte[] overlayImage(byte[] pdfBytes, byte[] imageBytes, float x, float y, boolean everyPage) throws IOException {
|
||||
|
||||
PDDocument document = PDDocument.load(new ByteArrayInputStream(pdfBytes));
|
||||
@@ -275,41 +367,7 @@ public class PdfUtils {
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public static ResponseEntity<byte[]> pdfDocToWebResponse(PDDocument document, String docName) throws IOException {
|
||||
|
||||
// Open Byte Array and save document to it
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
document.save(baos);
|
||||
// Close the document
|
||||
document.close();
|
||||
|
||||
return PdfUtils.boasToWebResponse(baos, docName);
|
||||
}
|
||||
|
||||
public static Long convertSizeToBytes(String sizeStr) {
|
||||
if (sizeStr == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
sizeStr = sizeStr.trim().toUpperCase();
|
||||
try {
|
||||
if (sizeStr.endsWith("KB")) {
|
||||
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024);
|
||||
} else if (sizeStr.endsWith("MB")) {
|
||||
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024 * 1024);
|
||||
} else if (sizeStr.endsWith("GB")) {
|
||||
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024 * 1024 * 1024);
|
||||
} else if (sizeStr.endsWith("B")) {
|
||||
return Long.parseLong(sizeStr.substring(0, sizeStr.length() - 1));
|
||||
} else {
|
||||
// Input string does not have a valid format, handle this case
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// The numeric part of the input string cannot be parsed, handle this case
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
public class WebResponseUtils {
|
||||
|
||||
public static ResponseEntity<byte[]> boasToWebResponse(ByteArrayOutputStream baos, String docName) throws IOException {
|
||||
return WebResponseUtils.bytesToWebResponse(baos.toByteArray(), docName);
|
||||
}
|
||||
|
||||
public static ResponseEntity<byte[]> boasToWebResponse(ByteArrayOutputStream baos, String docName, MediaType mediaType) throws IOException {
|
||||
return WebResponseUtils.bytesToWebResponse(baos.toByteArray(), docName, mediaType);
|
||||
}
|
||||
|
||||
public static ResponseEntity<byte[]> bytesToWebResponse(byte[] bytes, String docName, MediaType mediaType) throws IOException {
|
||||
|
||||
// Return the PDF as a response
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(mediaType);
|
||||
headers.setContentLength(bytes.length);
|
||||
String encodedDocName = URLEncoder.encode(docName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
|
||||
headers.setContentDispositionFormData("attachment", encodedDocName);
|
||||
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
public static ResponseEntity<byte[]> bytesToWebResponse(byte[] bytes, String docName) throws IOException {
|
||||
return bytesToWebResponse(bytes, docName, MediaType.APPLICATION_PDF);
|
||||
}
|
||||
|
||||
public static ResponseEntity<byte[]> pdfDocToWebResponse(PDDocument document, String docName) throws IOException {
|
||||
|
||||
// Open Byte Array and save document to it
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
document.save(baos);
|
||||
// Close the document
|
||||
document.close();
|
||||
|
||||
return boasToWebResponse(baos, docName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
spring.http.multipart.max-file-size=2GB
|
||||
spring.http.multipart.max-request-size=2GB
|
||||
spring.http.multipart.max-file-size=${MAX_FILE_SIZE:2000MB}
|
||||
spring.http.multipart.max-request-size=${MAX_FILE_SIZE:2000MB}
|
||||
|
||||
multipart.enabled=true
|
||||
multipart.max-file-size=2000MB
|
||||
multipart.max-request-size=2000MB
|
||||
multipart.max-file-size=${MAX_FILE_SIZE:2000MB}
|
||||
multipart.max-request-size=${MAX_FILE_SIZE:2000MB}
|
||||
|
||||
spring.servlet.multipart.max-file-size=2000MB
|
||||
spring.servlet.multipart.max-request-size=2000MB
|
||||
spring.servlet.multipart.max-file-size=${MAX_FILE_SIZE:2000MB}
|
||||
spring.servlet.multipart.max-request-size=${MAX_FILE_SIZE:2000MB}
|
||||
|
||||
server.forward-headers-strategy=NATIVE
|
||||
|
||||
@@ -22,7 +22,7 @@ server.servlet.context-path=${APP_ROOT_PATH:/}
|
||||
spring.devtools.restart.enabled=true
|
||||
spring.devtools.livereload.enabled=true
|
||||
|
||||
spring.thymeleaf.encoding=UTF-8
|
||||
spring.thymeleaf.encoding=UTF-8
|
||||
|
||||
server.connection-timeout=${CONNECTION_TIMEOUT:5m}
|
||||
spring.mvc.async.request-timeout=${ASYNC_CONNECTION_TIMEOUT:300000}
|
||||
|
||||
@@ -24,7 +24,7 @@ close=\u0625\u063A\u0644\u0627\u0642
|
||||
filesSelected = الملفات المحددة
|
||||
noFavourites = لم تتم إضافة أي مفضلات
|
||||
bored = الانتظار بالملل؟
|
||||
|
||||
alphabet=\u0627\u0644\u0623\u0628\u062C\u062F\u064A\u0629
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
@@ -129,15 +129,37 @@ home.repair.desc = يحاول إصلاح ملف PDF تالف / معطل
|
||||
home.removeBlanks.title = إزالة الصفحات الفارغة
|
||||
home.removeBlanks.desc = يكتشف ويزيل الصفحات الفارغة من المستند
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
|
||||
home.compare.title = قارن
|
||||
home.compare.desc = يقارن ويظهر الاختلافات بين 2 من مستندات PDF
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf = تنزيل PDF
|
||||
text=نص
|
||||
font=الخط
|
||||
selectFillter = - حدد -
|
||||
pageNum = رقم الصفحة
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title = توقيع الشهادة
|
||||
certSign.header = قم بتوقيع ملف PDF بشهادتك (العمل قيد التقدم)
|
||||
certSign.selectPDF = حدد ملف PDF للتوقيع:
|
||||
@@ -242,6 +264,7 @@ fileToPDF.submit=\u062A\u062D\u0648\u064A\u0644 \u0625\u0644\u0649 PDF
|
||||
addImage.title=إضافة صورة
|
||||
addImage.header=إضافة صورة إلى PDF
|
||||
addImage.everyPage=كل صفحة؟
|
||||
addImage.upload=إضافة صورة
|
||||
addImage.submit=إضافة صورة
|
||||
|
||||
#compress
|
||||
@@ -339,6 +362,9 @@ addPassword.selectText.10=منع التعديل
|
||||
addPassword.selectText.11=منع تعديل التعليقات التوضيحية
|
||||
addPassword.selectText.12=منع الطباعة
|
||||
addPassword.selectText.13=منع طباعة تنسيقات مختلفة
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=تشفير
|
||||
|
||||
#watermark
|
||||
|
||||
@@ -20,6 +20,7 @@ close=Tanca
|
||||
filesSelected=fitxers seleccionats
|
||||
noFavourites=No s'ha afegit cap favorit
|
||||
bored=Avorrit esperant?
|
||||
alphabet=Alfabet
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
@@ -122,15 +123,37 @@ home.repair.desc=Intenta reparar un PDF danyat o trencat
|
||||
home.removeBlanks.title=Elimina les pàgines en blanc
|
||||
home.removeBlanks.desc=Detecta i elimina les pàgines en blanc d'un document
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
|
||||
home.compare.title=Compara
|
||||
home.compare.desc=Compara i mostra les diferències entre 2 documents PDF
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf=Descarregueu PDF
|
||||
text=Text
|
||||
font=Tipus de lletra
|
||||
selectFillter=-- Selecciona --
|
||||
pageNum=Número de pàgina
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title=Significació del certificat
|
||||
certSign.header=Firmar un PDF amb el vostre certificat (Treball en curs)
|
||||
certSign.selectPDF=Seleccioneu un fitxer PDF per signar:
|
||||
@@ -250,6 +273,7 @@ compress.submit=Comprimir
|
||||
addImage.title=Afegir Imatge
|
||||
addImage.header=Afegir Imatge a PDF (en construcció)
|
||||
addImage.everyPage=Totes les pàgines?
|
||||
addImage.upload=Afegir Imatge
|
||||
addImage.submit=Afegir Imatge
|
||||
|
||||
|
||||
@@ -337,6 +361,9 @@ addPassword.selectText.10=Evita modificacions
|
||||
addPassword.selectText.11=Evita modificacions d'annotacions
|
||||
addPassword.selectText.12=Evita impressió
|
||||
addPassword.selectText.13=Evita impressió de diferents formats
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=Encripta
|
||||
|
||||
#watermark
|
||||
|
||||
@@ -20,6 +20,7 @@ close=Schließen
|
||||
filesSelected=Dateien ausgewählt
|
||||
noFavourites=Keine Favoriten hinzugefügt
|
||||
bored=Gelangweiltes Warten?
|
||||
alphabet=Alphabet
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
@@ -121,15 +122,37 @@ home.repair.desc=Versucht, ein beschädigtes/kaputtes PDF zu reparieren
|
||||
home.removeBlanks.title=Leere Seiten entfernen
|
||||
home.removeBlanks.desc=Erkennt und entfernt leere Seiten aus einem Dokument
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
|
||||
home.compare.title=Vergleichen
|
||||
home.compare.desc=Vergleicht und zeigt die Unterschiede zwischen zwei PDF-Dokumenten an
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf=PDF herunterladen
|
||||
text=Text
|
||||
font=Schriftart
|
||||
selectFillter=-- Auswählen --
|
||||
pageNum=Seitenzahl
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title=Zertifikatsignierung
|
||||
certSign.header=Signieren Sie ein PDF mit Ihrem Zertifikat (in Arbeit)
|
||||
certSign.selectPDF=Wählen Sie eine PDF-Datei zum Signieren aus:
|
||||
@@ -237,6 +260,7 @@ fileToPDF.submit=In PDF konvertieren
|
||||
addImage.title=Bild hinzufügen
|
||||
addImage.header=Ein Bild einfügen
|
||||
addImage.everyPage=Jede Seite?
|
||||
addImage.upload=Bild hinzufügen
|
||||
addImage.submit=Bild hinzufügen
|
||||
|
||||
#compress
|
||||
@@ -334,6 +358,9 @@ addPassword.selectText.10=Modifizierung verhindern
|
||||
addPassword.selectText.11=Ändern von Kommentaren verhindern
|
||||
addPassword.selectText.12=Drucken verhindern
|
||||
addPassword.selectText.13=Drucken verschiedener Formate verhindern
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=Verschlüsseln
|
||||
|
||||
#watermark
|
||||
|
||||
@@ -10,7 +10,7 @@ multiPdfDropPrompt=Select (or drag & drop) all PDFs you require
|
||||
imgPrompt=Select Image(s)
|
||||
genericSubmit=Submit
|
||||
processTimeWarning=Warning: This process can take up to a minute depending on file-size
|
||||
pageOrderPrompt=Page Order (Enter a comma-separated list of page numbers) :
|
||||
pageOrderPrompt=Custom Page Order (Enter a comma-separated list of page numbers or Functions like 2n+1) :
|
||||
goToPage=Go
|
||||
true=True
|
||||
false=False
|
||||
@@ -20,6 +20,7 @@ close=Close
|
||||
filesSelected=files selected
|
||||
noFavourites=No favourites added
|
||||
bored=Bored Waiting?
|
||||
alphabet=Alphabet
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
@@ -54,14 +55,11 @@ home.pdfOrganiser.title=Organise
|
||||
home.pdfOrganiser.desc=Remove/Rearrange pages in any order
|
||||
|
||||
home.addImage.title=Add image
|
||||
home.addImage.desc=Adds a image onto a set location on the PDF (Work in progress)
|
||||
home.addImage.desc=Adds a image onto a set location on the PDF
|
||||
|
||||
home.watermark.title=Add Watermark
|
||||
home.watermark.desc=Add a custom watermark to your PDF document.
|
||||
|
||||
home.remove-watermark.title=Remove Watermark
|
||||
home.remove-watermark.desc=Remove watermarks from your PDF document.
|
||||
|
||||
home.permissions.title=Change Permissions
|
||||
home.permissions.desc=Change the permissions of your PDF document
|
||||
|
||||
@@ -128,6 +126,16 @@ home.compare.desc=Compares and shows the differences between 2 PDF Documents
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of a page and/or its contents.
|
||||
|
||||
home.pipeline.title=Pipeline
|
||||
home.pipeline.desc=Pipeline desc.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf=Download PDF
|
||||
text=Text
|
||||
@@ -135,6 +143,19 @@ font=Font
|
||||
selectFillter=-- Select --
|
||||
pageNum=Page Number
|
||||
|
||||
pipeline.title=Pipeline
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title=Certificate Signing
|
||||
certSign.header=Sign a PDF with your certificate (Work in progress)
|
||||
certSign.selectPDF=Select a PDF File for Signing:
|
||||
@@ -258,6 +279,7 @@ compress.submit=Compress
|
||||
addImage.title=Add Image
|
||||
addImage.header=Add image to PDF
|
||||
addImage.everyPage=Every Page?
|
||||
addImage.upload=Add image
|
||||
addImage.submit=Add image
|
||||
|
||||
|
||||
@@ -333,10 +355,10 @@ pdfToImage.submit=Convert
|
||||
addPassword.title=Add Password
|
||||
addPassword.header=Add password (Encrypt)
|
||||
addPassword.selectText.1=Select PDF to encrypt
|
||||
addPassword.selectText.2=Password
|
||||
addPassword.selectText.2=User Password
|
||||
addPassword.selectText.3=Encryption Key Length
|
||||
addPassword.selectText.4=Higher values are stronger, but lower values have better compatibility.
|
||||
addPassword.selectText.5=Permissions to set
|
||||
addPassword.selectText.5=Permissions to set (Recommended to be used along with Owner password)
|
||||
addPassword.selectText.6=Prevent assembly of document
|
||||
addPassword.selectText.7=Prevent content extraction
|
||||
addPassword.selectText.8=Prevent extraction for accessibility
|
||||
@@ -345,6 +367,9 @@ addPassword.selectText.10=Prevent modification
|
||||
addPassword.selectText.11=Prevent annotation modification
|
||||
addPassword.selectText.12=Prevent printing
|
||||
addPassword.selectText.13=Prevent printing different formats
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=Encrypt
|
||||
|
||||
#watermark
|
||||
|
||||
@@ -11,7 +11,7 @@ imgPrompt=Seleccionar Imagen(es)
|
||||
genericSubmit=Enviar
|
||||
processTimeWarning=Advertencia: este proceso puede tardar hasta un minuto dependiendo del tamaño del archivo
|
||||
pageOrderPrompt=Orden de páginas (Introduzca una lista de números de página separados por coma):
|
||||
goToPage=Ir
|
||||
goToPage=Ir a
|
||||
true=Verdadero
|
||||
false=Falso
|
||||
unknown=Desconocido
|
||||
@@ -20,10 +20,11 @@ close=Cerrar
|
||||
filesSelected=archivos seleccionados
|
||||
noFavourites=No se agregaron favoritos
|
||||
bored=¿Aburrido de esperar?
|
||||
alphabet=Alfabeto
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=Tu autohospedada ventanilla única para todas tus necesidades PDF.
|
||||
home.desc=Tu ventanilla única autohospedada para todas tus necesidades PDF
|
||||
|
||||
navbar.convert=Convertir
|
||||
navbar.security=Seguridad
|
||||
@@ -35,19 +36,19 @@ home.multiTool.title=Multi-herramienta PDF
|
||||
home.multiTool.desc=Combinar, rotar, reorganizar y eliminar páginas
|
||||
|
||||
home.merge.title=Unir
|
||||
home.merge.desc=Unir fácilmente múltiples PDFs en uno.
|
||||
home.merge.desc=Unir fácilmente múltiples PDFs en uno
|
||||
|
||||
home.split.title=Dividir
|
||||
home.split.desc=Dividir PDFs en múltiples documentos
|
||||
|
||||
home.rotate.title=Rotar
|
||||
home.rotate.desc=Rotar fácilmente tus PDFs.
|
||||
home.rotate.desc=Rotar fácilmente tus PDFs
|
||||
|
||||
home.imageToPdf.title=Imagen a PDF
|
||||
home.imageToPdf.desc=Convertir una imagen (PNG, JPEG, GIF) a PDF.
|
||||
home.imageToPdf.desc=Convertir una imagen (PNG, JPEG, GIF) a PDF
|
||||
|
||||
home.pdfToImage.title=PDF a Imagen
|
||||
home.pdfToImage.desc=Convertir un PDF a una imagen. (PNG, JPEG, GIF)
|
||||
home.pdfToImage.desc=Convertir un PDF a una imagen (PNG, JPEG, GIF)
|
||||
|
||||
home.pdfOrganiser.title=Organizador
|
||||
home.pdfOrganiser.desc=Eliminar/Reorganizar páginas en cualquier orden
|
||||
@@ -56,37 +57,37 @@ home.addImage.title=Agregar imagen al PDF
|
||||
home.addImage.desc=Agregar una imagen en una ubicación establecida en el PDF (trabajo en progreso)
|
||||
|
||||
home.watermark.title=Añadir marca de agua
|
||||
home.watermark.desc=Añadir una marca de agua predefinida a tu documento PDF.
|
||||
home.watermark.desc=Añadir una marca de agua predefinida al documento PDF
|
||||
|
||||
home.remove-watermark.title=Eliminar marca de agua
|
||||
home.remove-watermark.desc=Eliminar marcas de agua de tu documento PDF.
|
||||
home.remove-watermark.desc=Eliminar marca de agua de tu documento PDF
|
||||
|
||||
home.permissions.title=Cambiar Permisos
|
||||
home.permissions.desc=Cambiar los permisos de tu documento PDF
|
||||
home.permissions.title=Cambiar permisos
|
||||
home.permissions.desc=Cambiar los permisos del documento PDF
|
||||
|
||||
home.removePages.title=Eliminar
|
||||
home.removePages.desc=Eliminar páginas no deseadas de tu documento PDF.
|
||||
home.removePages.desc=Eliminar páginas no deseadas del documento PDF
|
||||
|
||||
home.addPassword.title=Añadir Contraseña
|
||||
home.addPassword.desc=Encriptar el documento PDF con una contraseña.
|
||||
home.addPassword.title=Añadir contraseña
|
||||
home.addPassword.desc=Encriptar el documento PDF con una contraseña
|
||||
|
||||
home.removePassword.title=Eliminar Contraseña
|
||||
home.removePassword.desc=Eliminar la contraseña del documento PDF.
|
||||
home.removePassword.title=Eliminar contraseña
|
||||
home.removePassword.desc=Eliminar la contraseña del documento PDF
|
||||
|
||||
home.compressPdfs.title=Comprimir
|
||||
home.compressPdfs.desc=Comprimir PDFs para reducir el tamaño del fichero.
|
||||
home.compressPdfs.desc=Comprimir PDFs para reducir el tamaño del fichero
|
||||
|
||||
home.changeMetadata.title=Cambiar Metadatos
|
||||
home.changeMetadata.desc=Cambiar/Eliminar/Añadir metadatos al documento PDF.
|
||||
home.changeMetadata.title=Cambiar metadatos
|
||||
home.changeMetadata.desc=Cambiar/Eliminar/Añadir metadatos al documento PDF
|
||||
|
||||
home.fileToPDF.title=Convertir fichero a PDF
|
||||
home.fileToPDF.desc=Convertir casi cualquier archivo a PDF (DOCX, PNG, XLS, PPT, TXT y más)
|
||||
|
||||
home.ocr.title=Ejecutar OCR en PDF y/o escaneos de limpieza
|
||||
home.ocr.desc=Escaneos de limpieza y detecta texto de imágenes dentro de un PDF y lo vuelve a agregar como texto.
|
||||
home.ocr.desc=Escaneos de limpieza y detectar texto de imágenes dentro de un PDF y volver a agregarlo como texto
|
||||
|
||||
home.extractImages.title=Extraer imágenes
|
||||
home.extractImages.desc=Extraer todas las imágenes de un PDF y guardarlas en zip
|
||||
home.extractImages.desc=Extraer todas las imágenes de un PDF y guardarlas en ZIP
|
||||
|
||||
home.pdfToPDFA.title=Convertir PDF a PDF/A
|
||||
home.pdfToPDFA.desc=Convertir PDF a PDF/A para almacenamiento a largo plazo
|
||||
@@ -110,19 +111,30 @@ home.ScannerImageSplit.title=Detectar/Dividir fotos escaneadas
|
||||
home.ScannerImageSplit.desc=Dividir varias fotos dentro de una foto/PDF
|
||||
|
||||
home.sign.title=Firmar
|
||||
home.sign.desc=Añade firma a PDF mediante dibujo, texto o imagen
|
||||
home.sign.desc=Añadir firma a PDF mediante dibujo, texto o imagen
|
||||
|
||||
home.flatten.title=Aplanar
|
||||
home.flatten.desc=Eliminar todos los elementos y formularios interactivos de un PDF
|
||||
|
||||
home.repair.title=Reparar
|
||||
home.repair.desc=Intenta reparar un PDF corrupto/roto
|
||||
home.repair.desc=Intentar reparar un PDF corrupto/roto
|
||||
|
||||
home.removeBlanks.title=Eliminar páginas en blanco
|
||||
home.removeBlanks.descdetecta y elimina páginas en blanco de un documento
|
||||
home.removeBlanks.desc=Detectar y eliminar páginas en blanco de un documento
|
||||
|
||||
home.certSign.title=Firmar con certificado
|
||||
home.certSign.desc=Firmar un PDF con un Certificado/Clave (PEM/P12)
|
||||
|
||||
home.compare.title=Comparar
|
||||
home.compare.desc=Compara y muestra las diferencias entre 2 documentos PDF
|
||||
home.compare.desc=Comparar y mostrar las diferencias entre 2 documentos PDF
|
||||
|
||||
home.pageLayout.title=Diseño de varias páginas
|
||||
home.pageLayout.desc=Unir varias páginas de un documento PDF en una sola página
|
||||
|
||||
home.scalePages.title=Escalar/ajustar tamaño de página
|
||||
home.scalePages.desc=Escalar/cambiar el tamaño de una pagina y/o su contenido
|
||||
|
||||
error.pdfPassword=El documento PDF está protegido con contraseña y no se ha proporcionado o es incorrecta
|
||||
|
||||
downloadPdf=Descargar PDF
|
||||
text=Texto
|
||||
@@ -130,8 +142,19 @@ font=Fuente
|
||||
selectFilter=-- Seleccionar --
|
||||
pageNum=Número de página
|
||||
|
||||
pageLayout.title=Diseño de varias páginas
|
||||
pageLayout.header=Diseño de varias páginas
|
||||
pageLayout.pagesPerSheet=Páginas por hoja:
|
||||
pageLayout.submit=Entregar
|
||||
|
||||
scalePages.title=Ajustar escala de la página
|
||||
scalePages.header=Adjustar escala de la página
|
||||
scalePages.pageSize=Tamaño de la página del documento
|
||||
scalePages.scaleFactor=Nivel de zoom (recorte) de la página
|
||||
scalePages.submit=Entregar
|
||||
|
||||
certSign.title=Firma de certificado
|
||||
certSign.header=Firme un PDF con su certificado (Trabajo en progreso)
|
||||
certSign.header=Firmar un PDF con su certificado (Trabajo en progreso)
|
||||
certSign.selectPDF=Seleccione un archivo PDF para firmar:
|
||||
certSign.selectKey=Seleccione su archivo de clave privada (formato PKCS#8, podría ser .pem o .der):
|
||||
certSign.selectCert=Seleccione su archivo de certificado (formato X.509, podría ser .pem o .der):
|
||||
@@ -175,13 +198,13 @@ flatten.header=Acoplar archivos PDF
|
||||
flatten.submit=Aplanar
|
||||
|
||||
ScannerImageSplit.selectText.1=Umbral de ángulo:
|
||||
ScannerImageSplit.selectText.2=Establece el ángulo absoluto mínimo requerido para rotar la imagen (predeterminado: 10).
|
||||
ScannerImageSplit.selectText.2=Establecer el ángulo absoluto mínimo requerido para rotar la imagen (predeterminado: 10).
|
||||
ScannerImageSplit.selectText.3=Tolerancia:
|
||||
ScannerImageSplit.selectText.4=Determina el rango de variación de color alrededor del color de fondo estimado (predeterminado: 30).
|
||||
ScannerImageSplit.selectText.4=Determinar el rango de variación de color alrededor del color de fondo estimado (predeterminado: 30).
|
||||
ScannerImageSplit.selectText.5=Área mínima:
|
||||
ScannerImageSplit.selectText.6=Establece el umbral mínimo de área para una foto (predeterminado: 10000).
|
||||
ScannerImageSplit.selectText.6=Establecer el umbral mínimo de área para una foto (predeterminado: 10000).
|
||||
ScannerImageSplit.selectText.7=Área de contorno mínima:
|
||||
ScannerImageSplit.selectText.8=Establece el umbral mínimo del área de contorno para una foto
|
||||
ScannerImageSplit.selectText.8=Establecer el umbral mínimo del área de contorno para una foto
|
||||
ScannerImageSplit.selectText.9=Tamaño del borde:
|
||||
ScannerImageSplit.selectText.10=Establece el tamaño del borde agregado y eliminado para evitar bordes blancos en la salida (predeterminado: 1).
|
||||
|
||||
@@ -189,10 +212,10 @@ navbar.settings=Ajustes
|
||||
settings.title=Ajustes
|
||||
settings.update=Actualización disponible
|
||||
settings.appVersion=Versión de la aplicación:
|
||||
settings.downloadOption.title=Elige la opción de descarga (para descargas de un solo archivo sin ZIP):
|
||||
settings.downloadOption.1=Abre en la misma ventana
|
||||
settings.downloadOption.2=Abre en una nueva ventana
|
||||
settings.downloadOption.3=Descarga el fichero
|
||||
settings.downloadOption.title=Elegir la opción de descarga (para descargas de un solo archivo sin ZIP):
|
||||
settings.downloadOption.1=Abrir en la misma ventana
|
||||
settings.downloadOption.2=Abrir en una nueva ventana
|
||||
settings.downloadOption.3=Descargar el fichero
|
||||
settings.zipThreshold=Ficheros ZIP cuando excede el número de ficheros descargados
|
||||
|
||||
|
||||
@@ -201,54 +224,55 @@ settings.zipThreshold=Ficheros ZIP cuando excede el número de ficheros descarga
|
||||
#OCR
|
||||
ocr.title=OCR / Escaneo de limpieza
|
||||
ocr.header=Escaneos de limpieza / OCR (Reconocimiento óptico de caracteres)
|
||||
ocr.selectText.1=Selecciona los idiomas que se detectarán en el PDF (Los enumerados son los detectados actualmente):
|
||||
ocr.selectText.2=Produzca un archivo de texto que contenga texto OCR junto con el PDF editado con OCR
|
||||
ocr.selectText.3=Corrija las páginas que se escanearon en un ángulo torcido girándolas nuevamente a su lugar
|
||||
ocr.selectText.4=Limpie la página para que sea menos probable que el OCR encuentre texto en el ruido de fondo. (Sin cambio de salida)
|
||||
ocr.selectText.5=Limpie la página para que sea menos probable que el OCR encuentre texto en el ruido de fondo, mantiene la limpieza en la salida.
|
||||
ocr.selectText.6=Ignora las páginas que tienen texto interactivo, solo las páginas OCR que son imágenes
|
||||
ocr.selectText.7=Fuerza OCR, OCR eliminará en cada página todo el texto original
|
||||
ocr.selectText.8=Normal (Se producirá un error si el PDF contiene texto)
|
||||
ocr.selectText.9=Ajustes Adicionales
|
||||
ocr.selectText.1=Seleccionar los idiomas que se detectarán en el PDF (Los enumerados son los detectados actualmente):
|
||||
ocr.selectText.2=Producir un archivo de texto que contenga texto OCR junto con el PDF editado con OCR
|
||||
ocr.selectText.3=Corregir las páginas que se escanearon en un ángulo torcido girándolas nuevamente a su lugar
|
||||
ocr.selectText.4=Limpiar la página para que sea menos probable que el OCR encuentre texto en el ruido de fondo (Sin cambio de salida)
|
||||
ocr.selectText.5=Limpiar la página para que sea menos probable que el OCR encuentre texto en el ruido de fondo, mantiene la limpieza en la salida.
|
||||
ocr.selectText.6=Ignorar las páginas que tienen texto interactivo, solo las páginas OCR que son imágenes
|
||||
ocr.selectText.7=Forzar OCR, OCR eliminará en cada página todo el texto original
|
||||
ocr.selectText.8=Normal (se producirá un error si el PDF contiene texto)
|
||||
ocr.selectText.9=Ajustes adicionales
|
||||
ocr.selectText.10=Modo OCR
|
||||
ocr.selectText.11=Eliminar imágenes después de OCR (Elimina TODAS las imágenes, solo es útil si es parte del paso de conversión)
|
||||
ocr.selectText.12=Tipo de procesamiento (avanzado)
|
||||
ocr.help=Lea esta documentación sobre cómo usar esto para otros idiomas y/o no usarlo en docker
|
||||
ocr.credit=Este servicio utiliza OCRmyPDF y Tesseract para OCR.
|
||||
ocr.submit=Procesa PDF con OCR
|
||||
ocr.help=Lea esta documentación sobre cómo usar esto para otros idiomas y/o no usarlo en Docker
|
||||
ocr.credit=Este servicio utiliza OCRmyPDF y Tesseract para OCR
|
||||
ocr.submit=Procesar PDF con OCR
|
||||
|
||||
|
||||
|
||||
extractImages.title=Extraer imágenes
|
||||
extractImages.header=Extraer imágenes
|
||||
extractImages.selectText=Selecciona el formato de imagen para convertir las imágenes extraídas
|
||||
extractImages.selectText=Seleccionar el formato de imagen para convertir las imágenes extraídas
|
||||
extractImages.submit=Extraer
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=Fichero a PDF
|
||||
fileToPDF.header=Convierte cualquier fichero a PDF
|
||||
fileToPDF.credit=Este servicio usa LibreOffice y Unoconv para la conversión de ficheros.
|
||||
fileToPDF.supportedFileTypes=Los tipos de ficheros soportados deben incluir los de abajo; sin embargo para una completa y acutualizada lista de formatos soportados, por favor consulte la documentación de LibreOffice
|
||||
fileToPDF.title=Archivo a PDF
|
||||
fileToPDF.header=Convertir cualquier archivo a PDF
|
||||
fileToPDF.credit=Este servicio usa LibreOffice y Unoconv para la conversión de ficheros
|
||||
fileToPDF.supportedFileTypes=Los tipos de ficheros soportados deben incluir los de abajo; sin embargo, para una completa y acutualizada lista de formatos soportados, por favor consulte la documentación de LibreOffice
|
||||
fileToPDF.submit=Convertir a PDF
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=Comprimir
|
||||
compress.header=Comprimir PDF
|
||||
compress.credit=Este servicio utiliza Ghostscript para compresión/optimización de PDF.
|
||||
compress.credit=Este servicio utiliza Ghostscript para compresión/optimización de PDF
|
||||
compress.selectText.1=Modo manual - De 1 a 4
|
||||
compress.selectText.2=Nivel de optimización:
|
||||
compress.selectText.3=4 (Terrible para imágenes de texto)
|
||||
compress.selectText.4=Modo automático: ajusta automáticamente la calidad para que el PDF tenga el tamaño exacto
|
||||
compress.selectText.5=Tamaño de PDF esperado (por ejemplo, 25 MB, 10,8 MB, 25 KB)
|
||||
compress.selectText.5=Tamaño esperado del PDF (por ejemplo, 25 MB, 10.8 MB, 25 KB)
|
||||
compress.submit=Comprimir
|
||||
|
||||
|
||||
#Add image
|
||||
addImage.title=Añadir Imagen
|
||||
addImage.header=Añadir image de PDF
|
||||
addImage.title=Añadir imagen
|
||||
addImage.header=Añadir imagen de PDF
|
||||
addImage.everyPage=¿Todas las páginas?
|
||||
addImage.upload=Añadir imagen
|
||||
addImage.submit=Añadir imagen
|
||||
|
||||
|
||||
@@ -269,13 +293,13 @@ multiTool.header=Multi-herramienta PDF
|
||||
#pageRemover
|
||||
pageRemover.title=Eliminador de páginas
|
||||
pageRemover.header=Eliminador de páginas PDF
|
||||
pageRemover.pagesToDelete=Páginas a eliminar (Introduzca una lista de números de página separados por coma):
|
||||
pageRemover.pagesToDelete=Páginas a eliminar (introducir una lista de números de página separados por coma):
|
||||
pageRemover.submit=Eliminar Páginas
|
||||
|
||||
#rotate
|
||||
rotate.title=Rotar PDF
|
||||
rotate.header=Rotar PDF
|
||||
rotate.SeleccionaAngle=Seleccionar ángulo de rotación (múltiple de 90 grados):
|
||||
rotate.SeleccionaAngle=Seleccionar ángulo de rotación (múltiplo de 90 grados):
|
||||
rotate.submit=Rotar
|
||||
|
||||
|
||||
@@ -284,7 +308,7 @@ rotate.submit=Rotar
|
||||
#merge
|
||||
split.title=Dividir PDF
|
||||
split.header=Dividir PDF
|
||||
split.desc.1=Los números que selecciones son el número de página en el que desea hacer una división
|
||||
split.desc.1=Los números que seleccione son el número de página en el que desea hacer una división
|
||||
split.desc.2=Como tal, seleccionar 1,3,7-8 dividiría un documento de 10 páginas en 6 archivos PDF separados con:
|
||||
split.desc.3=Documento #1: Página 1
|
||||
split.desc.4=Documento #2: Páginas 2 y 3
|
||||
@@ -292,7 +316,7 @@ split.desc.5=Documento #3: Páginas 4, 5 y 6
|
||||
split.desc.6=Documento #4: Página 7
|
||||
split.desc.7=Documento #5: Página 8
|
||||
split.desc.8=Documento #6: Páginas 9 y 10
|
||||
split.splitPages=Introduce las páginas para dividir:
|
||||
split.splitPages=Introducir las páginas para dividir:
|
||||
split.submit=Dividir
|
||||
|
||||
|
||||
@@ -302,7 +326,7 @@ imageToPDF.header=Imagen a PDF
|
||||
imageToPDF.submit=Convertir
|
||||
imageToPDF.selectText.1=Estirar para ajustar
|
||||
imageToPDF.selectText.2=Rotación automática del PDF
|
||||
imageToPDF.selectText.3=Lógica de archivos múltiples (Únicamente activado si funciona con multiples imágenes)
|
||||
imageToPDF.selectText.3=Lógica de archivos múltiples (únicamente activado si funciona con multiples imágenes)
|
||||
imageToPDF.selectText.4=Unir en un único archivo PDF
|
||||
imageToPDF.selectText.5=Convertir a PDFs separados
|
||||
|
||||
@@ -311,21 +335,21 @@ pdfToImage.title=PDF a Imagen
|
||||
pdfToImage.header=PDF a Imagen
|
||||
pdfToImage.selectText=Formato de Imagen
|
||||
pdfToImage.singleOrMultiple=Tipo resultante de imagen
|
||||
pdfToImage.single=Una Imagen Grande Única
|
||||
pdfToImage.multi=Múltiples Imágenes
|
||||
pdfToImage.single=Una única imagen grande
|
||||
pdfToImage.multi=Múltiples imágenes
|
||||
pdfToImage.colorType=Tipo de color
|
||||
pdfToImage.color=Color
|
||||
pdfToImage.grey=Escala de Grises
|
||||
pdfToImage.blackwhite=Blanco y Negro (¡Puedes perder datos!)
|
||||
pdfToImage.grey=Escala de grises
|
||||
pdfToImage.blackwhite=Blanco y Negro (¡Puede perder datos!)
|
||||
pdfToImage.submit=Convertir
|
||||
|
||||
#addPassword
|
||||
addPassword.title=Añadir Contraseña
|
||||
addPassword.header=Añadir contraseña (Encriptar)
|
||||
addPassword.title=Añadir contraseña
|
||||
addPassword.header=Añadir contraseña (encriptar)
|
||||
addPassword.selectText.1=Seleccionar PDF para encriptar
|
||||
addPassword.selectText.2=Contraseña
|
||||
addPassword.selectText.3=Longitud de la clave de cifrado
|
||||
addPassword.selectText.4=Valores altos son más fuertes, pero valores bajos tienen mejor compatibilidad.
|
||||
addPassword.selectText.4=Valores altos son más fuertes, pero valores bajos tienen mejor compatibilidad
|
||||
addPassword.selectText.5=Permisos para establecer
|
||||
addPassword.selectText.6=Impedir el ensamblaje del documento
|
||||
addPassword.selectText.7=Impedir la extracción de contenido
|
||||
@@ -335,6 +359,9 @@ addPassword.selectText.10=Impedir modificación
|
||||
addPassword.selectText.11=Impedir modificación de anotaciones
|
||||
addPassword.selectText.12=Impedir imprimir
|
||||
addPassword.selectText.13=Impedir imprimir diferentes formatos
|
||||
addPassword.selectText.14=Contraseña
|
||||
addPassword.selectText.15=Restringe qué se puede hacer con el documento una vez abierto (no soportado por todos los lectores)
|
||||
addPassword.selectText.16=Restringe la apertura del propio documento
|
||||
addPassword.submit=Encriptar
|
||||
|
||||
#watermark
|
||||
@@ -357,8 +384,8 @@ remove-watermark.selectText.2=Texto de la marca de agua:
|
||||
remove-watermark.submit=Eliminar marca de agua
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Cambiar Permisos
|
||||
permissions.header=Cambiar Permisos
|
||||
permissions.title=Cambiar permisos
|
||||
permissions.header=Cambiar permisos
|
||||
permissions.warning=Advertencia: para que estos permisos no se puedan cambiar, se recomienda configurarlos con una contraseña a través de la página de cambio de contraseña
|
||||
permissions.selectText.1=Seleccionar PDF para cambiar los permisos
|
||||
permissions.selectText.2=Permisos a establecer
|
||||
@@ -374,21 +401,21 @@ permissions.submit=Cambiar
|
||||
|
||||
#remove password
|
||||
removePassword.title=Eliminar contraseña
|
||||
removePassword.header=Eliminar contraseña (Desencriptar)
|
||||
removePassword.selectText.1=Seleccionar PDF para Desencriptar
|
||||
removePassword.header=Eliminar contraseña (desencriptar)
|
||||
removePassword.selectText.1=Seleccionar PDF para desencriptar
|
||||
removePassword.selectText.2=Contraseña
|
||||
removePassword.submit=Eliminar
|
||||
|
||||
changeMetadata.title=Cambiar Metadatos
|
||||
changeMetadata.header=Cambiar Metadatos
|
||||
changeMetadata.title=Cambiar metadatos
|
||||
changeMetadata.header=Cambiar metadatos
|
||||
changeMetadata.selectText.1=Editar las variables que desea cambiar
|
||||
changeMetadata.selectText.2=Eliminar todos los metadatos
|
||||
changeMetadata.selectText.3=Mostrar metadatos personalizados:
|
||||
changeMetadata.author=Autor:
|
||||
changeMetadata.creationDate=Fecha de Creación (aaaa/MM/dd HH:mm:ss):
|
||||
changeMetadata.creationDate=Fecha de creación (aaaa/MM/dd HH:mm:ss):
|
||||
changeMetadata.creator=Creador:
|
||||
changeMetadata.keywords=Palabras clave:
|
||||
changeMetadata.modDate=Fecha de Modificación (aaaa/MM/dd HH:mm:ss):
|
||||
changeMetadata.modDate=Fecha de modificación (aaaa/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Productor:
|
||||
changeMetadata.subject=Asunto:
|
||||
changeMetadata.title=Título:
|
||||
@@ -415,29 +442,29 @@ pdfToPDFA.submit=Convertir
|
||||
PDFToWord.title=PDF a Word
|
||||
PDFToWord.header=PDF a Word
|
||||
PDFToWord.selectText.1=Formato de archivo de salida
|
||||
PDFToWord.credit=Este servicio utiliza LibreOffice para la conversión de archivos.
|
||||
PDFToWord.credit=Este servicio utiliza LibreOffice para la conversión de archivos
|
||||
PDFToWord.submit=Convertir
|
||||
|
||||
PDFToPresentation.title=PDF a presentación
|
||||
PDFToPresentation.header=PDF a presentación
|
||||
PDFToPresentation.selectText.1=Formato de archivo de salida
|
||||
PDFToPresentation.credit=Este servicio utiliza LibreOffice para la conversión de archivos.
|
||||
PDFToPresentation.credit=Este servicio utiliza LibreOffice para la conversión de archivos
|
||||
PDFToPresentation.submit=Convertir
|
||||
|
||||
|
||||
PDFToText.title=PDF a TXT/RTF
|
||||
PDFToText.header=PDF a TXT/RTF
|
||||
PDFToText.selectText.1=Formato de archivo de salida
|
||||
PDFToText.credit=Este servicio utiliza LibreOffice para la conversión de archivos.
|
||||
PDFToText.credit=Este servicio utiliza LibreOffice para la conversión de archivos
|
||||
PDFToText.submit=Convertir
|
||||
|
||||
|
||||
PDFToHTML.title=PDF a HTML
|
||||
PDFToHTML.header=PDF a HTML
|
||||
PDFToHTML.credit=Este servicio utiliza LibreOffice para la conversión de archivos.
|
||||
PDFToHTML.credit=Este servicio utiliza LibreOffice para la conversión de archivos
|
||||
PDFToHTML.submit=Convertir
|
||||
|
||||
PDFToXML.title=PDF a XML
|
||||
PDFToXML.header=PDF a XML
|
||||
PDFToXML.credit=Este servicio utiliza LibreOffice para la conversión de archivos.
|
||||
PDFToXML.credit=Este servicio utiliza LibreOffice para la conversión de archivos
|
||||
PDFToXML.submit=Convertir
|
||||
|
||||
470
src/main/resources/messages_eu_ES.properties
Normal file
470
src/main/resources/messages_eu_ES.properties
Normal file
@@ -0,0 +1,470 @@
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||
language.direction=ltr
|
||||
|
||||
pdfPrompt=Hautatu PDFa(k)
|
||||
multiPdfPrompt=Hautatu PDFak (2+)
|
||||
multiPdfDropPrompt=Hautatu (edo arrastatu eta jaregin) nahi dituzun PDFak
|
||||
imgPrompt=Hautatu Irudia(k)
|
||||
genericSubmit=Bidali
|
||||
processTimeWarning=Oharra: prozesu honetarako minutu bat ere beharko da fitxategiaren tamaiaren arabera
|
||||
pageOrderPrompt=Orrialdeen ordena (sartu komaz bereizitako orrialde-zenbakien zerrenda)
|
||||
goToPage=Joan
|
||||
true=Egiazkoa
|
||||
false=Faltsua
|
||||
unknown=Ezezaguna
|
||||
save=Gorde
|
||||
close=Itxi
|
||||
filesSelected=Hautatutako fitxategiak
|
||||
noFavourites=Ez dira gogokoak gehitu
|
||||
bored=Itxaroten aspertuta?
|
||||
alphabet=Alfabetoa
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=Zure leihatila bakarra autoostatatua zure PDF behar guztietarako
|
||||
|
||||
navbar.convert=Bihurtu
|
||||
navbar.security=Segurtasuna
|
||||
navbar.other=Beste bat
|
||||
navbar.darkmode=Modu iluna
|
||||
navbar.pageOps=Orrialde-eragiketak
|
||||
|
||||
home.multiTool.title=Erabilera anitzeko tresna PDF
|
||||
home.multiTool.desc= Orriak konbinatu, biratu, berrantolatu eta ezabatu
|
||||
|
||||
home.merge.title=Elkartu
|
||||
home.merge.desc=Elkartu zenbait PDF dokumentu bakar batean modu errazean
|
||||
|
||||
home.split.title=Zatitu
|
||||
home.split.desc=Zatitu PDFak zenbait dokumentutan
|
||||
|
||||
home.rotate.title=Biratu
|
||||
home.rotate.desc=Biratu PDFak modu errazean
|
||||
|
||||
home.imageToPdf.title=Irudia PDF bihurtu
|
||||
home.imageToPdf.desc=Irudi bat(PNG, JPEG, GIF)PDF bihurtu
|
||||
|
||||
home.pdfToImage.title=PDFa irudi bihurtu
|
||||
home.pdfToImage.desc=PDF bat irudi (PNG, JPEG, GIF) bihurtu
|
||||
|
||||
home.pdfOrganiser.title=Antolatzailea
|
||||
home.pdfOrganiser.desc=Ezabatu/Berrantolatu orrialdeak edozein ordenatan
|
||||
|
||||
home.addImage.title=Gehitu irudia PDFari
|
||||
home.addImage.desc=Gehitu irudi bat PDFan ezarritako kokaleku batean (lanean)
|
||||
|
||||
home.watermark.title=Gehitu ur-marka
|
||||
home.watermark.desc=Gehitu aurrez zehaztutako ur-marka bat PFD dokumentuari
|
||||
|
||||
home.remove-watermark.title= Ezabatu ur-marka
|
||||
home.remove-watermark.desc= Ezabatu ur-marka PDF dokumentutik
|
||||
|
||||
home.permissions.title=Aldatu baimenak
|
||||
home.permissions.desc=Aldatu PDF dokumentuaren baimenak
|
||||
|
||||
home.removePages.title=Ezabatu
|
||||
home.removePages.desc=Ezabatu nahi ez dituzun orrialdeak PDF dokumentutik
|
||||
|
||||
home.addPassword.title=Gehitu pasahitza
|
||||
home.addPassword.desc=Enkriptatu PDF dokumentua pasahitz batekin
|
||||
|
||||
home.removePassword.title=Ezabatu pasahitza
|
||||
home.removePassword.desc=Ezabatu pasahitza PDF dokumentutik
|
||||
|
||||
home.compressPdfs.title=Konprimatu
|
||||
home.compressPdfs.desc=Konprimatu PDFak fitxategiaren tamaina murrizteko
|
||||
|
||||
home.changeMetadata.title=Aldatu metadatuak
|
||||
home.changeMetadata.desc=Aldatu/Ezabatu/Gehitu metadatuak PDF dokumentuari
|
||||
|
||||
home.fileToPDF.title=Fitxategia PDF bihurtu
|
||||
home.fileToPDF.desc=PDF bihurtu ia edozein fitxategi (DOCX, PNG, XLS, PPT, TXT eta gehiago)
|
||||
|
||||
home.ocr.title=OCR exekutatu PDFan eta/edo garbiketa-eskaneatzeak
|
||||
home.ocr.desc=Garbiketa-eskaneatzeak eta irudi-testuak detektatu PDF baten barruan eta berriz ere gehitu testu gisa
|
||||
|
||||
home.extractImages.title=Atera irudiak
|
||||
home.extractImages.desc=Atera irudi guztiak PDF batetik eta ZIPen gorde
|
||||
|
||||
home.pdfToPDFA.title=PDFa PDF/A bihurtu
|
||||
home.pdfToPDFA.desc=PDFa PDF/A bihurtu luzaro biltegiratzeko
|
||||
|
||||
home.PDFToWord.title=PDFa Word Bihurtu
|
||||
home.PDFToWord.desc=PDF formatuak Word bihurtu (DOC, DOCX y ODT)
|
||||
|
||||
home.PDFToPresentation.title=PDFa aurkezpen bihurtu
|
||||
home.PDFToPresentation.desc=PDFa aurkezpen formatu bihurtu (PPT, PPTX y ODP)
|
||||
|
||||
home.PDFToText.title=PDFa TXT edo RTF bihurtu
|
||||
home.PDFToText.desc=PDFa TXT edo RTF formatu bihurtu
|
||||
|
||||
home.PDFToHTML.title=PDFa HTML bihurtu
|
||||
home.PDFToHTML.desc=PDFa HTML formatu bihurtu
|
||||
|
||||
home.PDFToXML.title=PDFa XML bihurtu
|
||||
home.PDFToXML.desc=PDFa XML formatu bihurtu
|
||||
|
||||
home.ScannerImageSplit.title=Detektatu/Zatitu argazki eskaneatuak
|
||||
home.ScannerImageSplit.desc=Hainbat argazki zatitu argazki/PDF baten barruan
|
||||
|
||||
home.sign.title=Sinatu
|
||||
home.sign.desc=Gehitu sinadura PDFari marrazki, testu edo irudi bidez
|
||||
|
||||
home.flatten.title=Lautu
|
||||
home.flatten.desc=PDF batetik elementu eta inprimaki interaktibo guztiak ezabatu
|
||||
|
||||
home.repair.title=Konpondu
|
||||
home.repair.desc=Saiatu PDF hondatu/kaltetu bat konpontzen
|
||||
|
||||
home.removeBlanks.title=Ezabatu orrialde zuriak
|
||||
home.removeBlanks.desc=Detektatu orrialde zuriak eta dokumentutik ezabatu
|
||||
|
||||
home.certSign.title=Sinatu ziurtagiriarekin
|
||||
home.certSign.desc=Sinatu PDF bat Ziurtagiri/Gako batekin (PEM/P12)
|
||||
|
||||
home.compare.title=Konparatu
|
||||
home.compare.desc=Konparatu eta erakutsi 2 PDF dokumenturen aldeak
|
||||
|
||||
home.pageLayout.title=Zenbait orrialderen diseinua
|
||||
home.pageLayout.desc=Elkartu orri bakar batean PDF dokumentu baten zenbait orrialde
|
||||
|
||||
home.scalePages.title=Eskalatu/Doitu orrialdearen tamaina
|
||||
home.scalePages.desc=Eskalatu/Aldatu orrialde baten tamaina eta/edo edukia
|
||||
|
||||
error.pdfPassword=PDF dokumentua pasahitzarekin babestuta dago eta pasahitza ez da sartu edo akastuna da
|
||||
|
||||
downloadPdf=PDFa deskargatu
|
||||
text=Testua
|
||||
font=Letra-tipoa
|
||||
selectFilter=-- Hautatu --
|
||||
pageNum=Orrialde-zenbakia
|
||||
|
||||
pageLayout.title=Hainbat orrialderen diseinua
|
||||
pageLayout.header=Hainbat orrialderen diseinua
|
||||
pageLayout.pagesPerSheet=Orrialdeak orriko:
|
||||
pageLayout.submit=Entregatu
|
||||
|
||||
scalePages.title=Doitu orrialdearen eskala
|
||||
scalePages.header=Doitu orrialdearen eskala
|
||||
scalePages.pageSize=Dokumentuaren orrialdearen tamaina
|
||||
scalePages.scaleFactor=Orriaren zoom maila (moztea)
|
||||
scalePages.submit=Entregatu
|
||||
|
||||
certSign.title=Ziurtagiriaren sinadura
|
||||
certSign.header=Sinatu PDF bat haren ziurtagiriarekin (lanean)
|
||||
certSign.selectPDF=Hautatu PDF fitxategi bat sinatzeko:
|
||||
certSign.selectKey=Hautatu gako pribatuko fitxategia (PKCS#8 formatua, .pem edo .der izan liteke):
|
||||
certSign.selectCert=Hautatu ziurtagiridun fitxategia (X.509 formatua, .pem edo .der izan liteke):
|
||||
certSign.selectP12=Hautatu gakoak gordetzeko fitxategia PKCS#12 (.p12 o .pfx) (Aukerakoa, ematen bada, gako pribatua eta ziurtagiria izan beharko ditu):
|
||||
certSign.certType=Ziurtagiri-mota
|
||||
certSign.password=Sartu zure gakoen biltegia edo gako pribatuko pasahitza (hala badagokio):
|
||||
certSign.showSig=Erakutsi sinadura
|
||||
certSign.reason=Arrazoia
|
||||
certSign.location=Kokalekua
|
||||
certSign.name=Izena
|
||||
certSign.submit=Sinatu PDFa
|
||||
|
||||
removeBlanks.title=Ezabatu zuriuneak
|
||||
removeBlanks.header=Ezabatu orrialde zuriak
|
||||
removeBlanks.threshold=Gutxieneko balioa:
|
||||
removeBlanks.thresholdDesc=Pixel bat zeinen zuri izan behar den ezartzeko gutxieneko balioa
|
||||
removeBlanks.whitePercent=Zuriaren protzentajea (%):
|
||||
removeBlanks.whitePercentDesc=Zuria izan behar den orriaren ehunekoa ezabatua izan dadin
|
||||
removeBlanks.submit=Ezabatu zuriuneak
|
||||
|
||||
compare.title=Konparatu
|
||||
compare.header=Konparatu PDF fitxategiak
|
||||
compare.document.1=1. dokumentua
|
||||
compare.document.2=2. dokumentua
|
||||
compare.submit=Konparatu
|
||||
|
||||
sign.title=Sinatu
|
||||
sign.header=Sinatu PDF fitxategiak
|
||||
sign.upload=Igo irudia
|
||||
sign.draw=Marraztu sinadura
|
||||
sign.text=Testua sartzea
|
||||
sign.clear=Garbitu
|
||||
sign.add=Gehitu
|
||||
|
||||
repair.title=Konpondu
|
||||
repair.header=Konpondu PDF fitxategiak
|
||||
repair.submit=Konpondu
|
||||
|
||||
flatten.title=Lautu
|
||||
flatten.header=Akoplatu PDF fitxategiak
|
||||
flatten.submit=Lautu
|
||||
|
||||
ScannerImageSplit.selectText.1=Angeluaren gutxieneko balioa:
|
||||
ScannerImageSplit.selectText.2=Ezarri eskatutako gutxieneko angelu absolutua irudia biratzeko (lehenetsia: 10).
|
||||
ScannerImageSplit.selectText.3=Tolerantzia:
|
||||
ScannerImageSplit.selectText.4=Ezarri kalkulatutako atzeko kolorearen inguruko kolorearen aldakuntza tartea (lehenetsia: 30).
|
||||
ScannerImageSplit.selectText.5=Gutxieneko area:
|
||||
ScannerImageSplit.selectText.6=Ezarri arearen gutxieneko balioa argazki batentzat (lehenetsia: 10000).
|
||||
ScannerImageSplit.selectText.7=Inguruko area gutxienekoa:
|
||||
ScannerImageSplit.selectText.8=Ezarri inguruko arearen gutxieneko balioa argazki batentzat
|
||||
ScannerImageSplit.selectText.9=Ertzaren tamaina:
|
||||
ScannerImageSplit.selectText.10=Ezarri gehitutako eta ezabatutako ertzaren tamaina irteeran ertz zuriak saihesteko (lehenetsia: 1).
|
||||
|
||||
navbar.settings=Ezarpenak
|
||||
settings.title=Ezarpenak
|
||||
settings.update=Eguneratze eskuragarria
|
||||
settings.appVersion=Aplikazioaren bertsioa:
|
||||
settings.downloadOption.title=Hautatu deskargatzeko aukera (fitxategi bakarra deskargatzeko ZIP gabe):
|
||||
settings.downloadOption.1=Ireki leiho berean
|
||||
settings.downloadOption.2=Ireki leiho berrian
|
||||
settings.downloadOption.3=Deskargatu fitxategia
|
||||
settings.zipThreshold=ZIP fitxategiak deskargatutako fitxategi kopurua gainditzen denean
|
||||
|
||||
|
||||
|
||||
|
||||
#OCR
|
||||
ocr.title=OCR / Garbiketa-eskaneatzea
|
||||
ocr.header=Garbiketa-eskaneatzea / OCR (Karaktere-ezagutze optikoa)
|
||||
ocr.selectText.1=Hautatu PDFan detektatuko diren hizkuntzak (zerrendatutakoak gaur egun detektatzen dituenak dira):
|
||||
ocr.selectText.2=Sortu OCR testua duen testu-fitxategi bat OCR-ren bidez editatutako PDFarekin batera
|
||||
ocr.selectText.3=Zuzendu angelu okertu batean eskaneatu ziren orrialdeak berriro beren lekura biratuta
|
||||
ocr.selectText.4=Garbitu orrialdea OCRk hondoko zaratan testua aurkitzeko probabilitate txikiagoa izan dezan (Irteeran aldatu gabe)
|
||||
ocr.selectText.5=Garbitu orrialdea OCRk hondoko zaratan testua aurkitzeko probabilitate txikiagoa izan dezan, irteeran garbi mantentzen du.
|
||||
ocr.selectText.6=Alde batera utzi testu interaktiboa duten orrialdeak, bakarrik irudi diren OCR orrialdeak
|
||||
ocr.selectText.7=OCR behartu, OCRk orrialde bakoitzean jatorrizko testu guztia ezabatuko du
|
||||
ocr.selectText.8=Normala (Errorea gertatuko da PDFak testua baldin badu)
|
||||
ocr.selectText.9=Ezarpen gehigarriak
|
||||
ocr.selectText.10=OCR modua
|
||||
ocr.selectText.11=Irudiak ezabatu OCR-ren ondoren (Irudi GUZTIAK ezabatzen ditu, bakarrik da erabilgarri bihurketa urratsaren parte baldin bada)
|
||||
ocr.selectText.12=Prozesaketa-mota (aurreratua)
|
||||
ocr.help=Irakurri honen erabilerari buruzko dokumentazioa beste hizkuntza batzuetarako eta/edo ez erabili Docker-en
|
||||
ocr.credit=Zerbitzu honek OCRmyPDF eta OCR-rako Tesseract erabiltzen ditu
|
||||
ocr.submit=PDF prozesatu OCR-rekin
|
||||
|
||||
|
||||
|
||||
extractImages.title=Atera irudiak
|
||||
extractImages.header=Atera irudiak
|
||||
extractImages.selectText=Hautatu irudi-formatua ateratako irudiak bihurtzeko
|
||||
extractImages.submit=Atera
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=Fitxategia PDF bihurtu
|
||||
fileToPDF.header=Edozein fitxategi PDF bihurtu
|
||||
fileToPDF.credit=Zerbitzu honek LibreOffice eta Unoconv erabiltzen ditu fitxategiak bihurtzeko
|
||||
fileToPDF.supportedFileTypes=Jasandako fitxategi-motek behekoak barne hartu behar dituzte; hala ere, jasandako formatuen zerrenda osoa eta eguneratua izateko, kontsultatu, mesedez, LibreOffice-en dokumentazioa
|
||||
fileToPDF.submit=PDF bihurtu
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=Konprimatu
|
||||
compress.header=PDFa konprimatu
|
||||
compress.credit=Zerbitzu honek Ghostscript erabiltzen du PDFak komprimatzeko/optimizatzeko
|
||||
compress.selectText.1=Eskuz 1etik 4ra
|
||||
compress.selectText.2=Optimizazio maila:
|
||||
compress.selectText.3=4 (Izugarria testu-irudietarako)
|
||||
compress.selectText.4=Automatikoa: automatikoki egokitzen du kalitatea PDFak tamaina doi-doia izan dezan
|
||||
compress.selectText.5=PDFaren espero den tamaina (adibidez, 25 MB, 10.8 MB, 25 KB)
|
||||
compress.submit=Konprimatu
|
||||
|
||||
|
||||
#Add image
|
||||
addImage.title=Gehitu irudia
|
||||
addImage.header=Gehitu PDF-irudia
|
||||
addImage.everyPage=Orrialde guztiak?
|
||||
addImage.upload=Gehitu irudia
|
||||
addImage.submit=Gehitu irudia
|
||||
|
||||
|
||||
#merge
|
||||
merge.title=Elkartu
|
||||
merge.header=Elkartu zenbait PDF (2+)
|
||||
merge.submit=Elkartu
|
||||
|
||||
#pdfOrganiser
|
||||
pdfOrganiser.title=Orrialdeen antolatzailea
|
||||
pdfOrganiser.header=PDF orrialdeen antolatzailea
|
||||
pdfOrganiser.submit=Antolatu orrialdeak
|
||||
|
||||
#herramienta multiple
|
||||
multiTool.title= PDF erabilera anitzeko tresna
|
||||
multiTool.header=PDF erabilera anitzeko tresna
|
||||
|
||||
#pageRemover
|
||||
pageRemover.title=Orrialdeen ezabatzailea
|
||||
pageRemover.header=PDF orrialdeen ezabatzailea
|
||||
pageRemover.pagesToDelete=Ezabatu beharreko orrialdeak (sartu komaz bereizitako orrialde-zenbakien zerrenda):
|
||||
pageRemover.submit=Ezabatu orrialdeak
|
||||
|
||||
#rotate
|
||||
rotate.title=Biratu PDFa
|
||||
rotate.header=Biratu PDFa
|
||||
rotate.SeleccionaAngle=Hautatu errotazio-angelua (90 graduren multiploa):
|
||||
rotate.submit=Biratu
|
||||
|
||||
|
||||
|
||||
|
||||
#merge
|
||||
split.title=Zatitu PDFa
|
||||
split.header=Zatitu PDFa
|
||||
split.desc.1=Hautatzen dituzun zenbakiak zatiketa egin nahi duzun orrialde-zenbakiak dira
|
||||
split.desc.2=Beraz, 1,3,7-8 hautatzean 10 orrialdeko dokumentua zatituko luke 6 PDF fitxategi bereizituetan
|
||||
split.desc.3=#1 Dokumentua: 1. orrialdea
|
||||
split.desc.4=#2 Dokumentua: 2. eta 3. orrialdeak
|
||||
split.desc.5=#3 Dokumentua: 4., 5. eta 6. orrialdeak
|
||||
split.desc.6=#4 Dokumentua: 7. orrialdea
|
||||
split.desc.7=#5 Dokumentua: 8. orrialdea
|
||||
split.desc.8=#6 Dokumentua: 9. eta 10. orrialdeak
|
||||
split.splitPages=Sartu orrialdeak zatitzeko:
|
||||
split.submit=Zatitu
|
||||
|
||||
|
||||
#merge
|
||||
imageToPDF.title=Irudia PDF bihurtu
|
||||
imageToPDF.header=Irudia PDF bihurtu
|
||||
imageToPDF.submit=Bihurtu
|
||||
imageToPDF.selectText.1=Zabaldu doitzeko
|
||||
imageToPDF.selectText.2=PDFaren errotazio automatikoa
|
||||
imageToPDF.selectText.3=Fitxategi askoren logika (gaituta bakarrik zenbait irudirekin ari denean)
|
||||
imageToPDF.selectText.4=Elkartu PDF bakar batean
|
||||
imageToPDF.selectText.5=Bihurtu eta PDF bereizituak sortu
|
||||
|
||||
#pdfToImage
|
||||
pdfToImage.title=PDFa irudi bihurtu
|
||||
pdfToImage.header=PDFa irudi bihurtu
|
||||
pdfToImage.selectText=Irudi-formatua
|
||||
pdfToImage.singleOrMultiple=Ondoriozko irudi-mota
|
||||
pdfToImage.single=Irudi handi bakarra
|
||||
pdfToImage.multi=Zenbait irudi
|
||||
pdfToImage.colorType=Kolore-mota
|
||||
pdfToImage.color=Kolorea
|
||||
pdfToImage.grey=Gris-eskala
|
||||
pdfToImage.blackwhite=Zuria eta Beltza (Datuak galdu ditzake!)
|
||||
pdfToImage.submit=Bihurtu
|
||||
|
||||
#addPassword
|
||||
addPassword.title=Gehitu pasahitza
|
||||
addPassword.header=Gehitu pasahitza (enkriptatu)
|
||||
addPassword.selectText.1=Hautatu PDFa enkriptatzeko
|
||||
addPassword.selectText.2=Pasahitza
|
||||
addPassword.selectText.3=Gakoaren luzera
|
||||
addPassword.selectText.4=Balio altuak sendoagoak dira, baina balio baxuek bateragarritasun hobea dute
|
||||
addPassword.selectText.5=Ezartzeko baimenak
|
||||
addPassword.selectText.6=Galarazi dokumentuaren mihiztaketa
|
||||
addPassword.selectText.7=Galarazi edukia ateratzea
|
||||
addPassword.selectText.8=Galarazi ateratzea irisgarritasunerako
|
||||
addPassword.selectText.9=Galarazi inprimakia betetzea
|
||||
addPassword.selectText.10=Galarazi aldaketak egitea
|
||||
addPassword.selectText.11=Galarazi oharrak aldatzea
|
||||
addPassword.selectText.12=Galarazi inprimatzea
|
||||
addPassword.selectText.13=Galarazi zenbait formatu inprimatzea
|
||||
addPassword.selectText.14=Pasahitza
|
||||
addPassword.selectText.15=Mugatu zer egin daitekeen dokumentuarekin behin zabalduta (Irakurle guztiek onartu gabe)
|
||||
addPassword.selectText.16=Mugatu dokumentu bera zabaltzeko aukera
|
||||
addPassword.submit=Enkriptatu
|
||||
|
||||
#watermark
|
||||
watermark.title=Gehitu ur-marka
|
||||
watermark.header=Gehitu ur-marka
|
||||
watermark.selectText.1=Hautatu PDFa ur-marka gehitzeko:
|
||||
watermark.selectText.2=Ur-markaren testua:
|
||||
watermark.selectText.3=Letra-tipoaren tamaina:
|
||||
watermark.selectText.4=Errotazioa (0-360):
|
||||
watermark.selectText.5=Zabalera (ur-marka bakoitzaren arteko espazioa horizontalean):
|
||||
watermark.selectText.6=Altuera (ur-marka bakoitzaren arteko espazioa bertikalean):
|
||||
watermark.selectText.7=Opakutasuna (0% - 100%):
|
||||
watermark.submit=Gehitu ur-marka
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=Ezabatu ur-marka
|
||||
remove-watermark.header=Ezabatu ur-marka
|
||||
remove-watermark.selectText.1=Hautatu PDFa ur-marka ezabatzeko:
|
||||
remove-watermark.selectText.2=Ur-markaren testua:
|
||||
remove-watermark.submit=Ezabatu ur-marka
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Aldatu baimenak
|
||||
permissions.header=Aldatu baimenak
|
||||
permissions.warning=Oharra: baimen hauek aldatzea ezinezkoa izan dadin, gomendatzen da pasahitz batekin konfiguratzea pasahitza aldatzeko orriaren bitartez
|
||||
permissions.selectText.1=Hautatu PDFa baimenak aldatzeko
|
||||
permissions.selectText.2=Baimenak, ezarri beharrekoak
|
||||
permissions.selectText.3=Galarazi dokumentuaren mihiztaketa
|
||||
permissions.selectText.4=Galarazi edukia ateratzea
|
||||
permissions.selectText.5=Galarazi ateratzea irisgarritasunerako
|
||||
permissions.selectText.6=Galarazi inprimakia betetzea
|
||||
permissions.selectText.7=Galarazi aldaketak egitea
|
||||
permissions.selectText.8=Galarazi oharrak aldatzea
|
||||
permissions.selectText.9=Galarazi inprimatzea
|
||||
permissions.selectText.10=Galarazi zenbait formatu inprimatzea
|
||||
permissions.submit=Aldatu
|
||||
|
||||
#remove password
|
||||
removePassword.title=Ezabatu pasahitza
|
||||
removePassword.header=Ezabatu pasahitza (desenkriptatu)
|
||||
removePassword.selectText.1=Hautatu PDFa desenkriptatzeko
|
||||
removePassword.selectText.2=Pasahitza
|
||||
removePassword.submit=Ezabatu
|
||||
|
||||
changeMetadata.title=Aldatu metadatuak
|
||||
changeMetadata.header=Aldatu metadatuak
|
||||
changeMetadata.selectText.1=Editatu aldatu nahi dituzun aldagaiak
|
||||
changeMetadata.selectText.2=Ezabatu metadatu guztiak
|
||||
changeMetadata.selectText.3=Erakutsi metadatu pertsonalizatuak:
|
||||
changeMetadata.author=Egilea:
|
||||
changeMetadata.creationDate=Sortze-data (aaaa/MM/dd HH:mm:ss):
|
||||
changeMetadata.creator=Sortzailea:
|
||||
changeMetadata.keywords=Gako-hitzak:
|
||||
changeMetadata.modDate=Aldatze-data (aaaa/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Ekoizlea:
|
||||
changeMetadata.subject=Gaia:
|
||||
changeMetadata.title=Izenburua:
|
||||
changeMetadata.trapped=Trapped:
|
||||
changeMetadata.selectText.4=Beste metadatu batzuk:
|
||||
changeMetadata.selectText.5=Gehitu metadatu pertsonalizatuen sarrera
|
||||
changeMetadata.submit=Aldatu
|
||||
|
||||
xlsToPdf.title=Excela PDF bihurtu
|
||||
xlsToPdf.header=Excela PDF bihurtu
|
||||
xlsToPdf.selectText.1=Hautatu Excel XLSren edo XLSXren kalkulu-orria bihurtzeko
|
||||
xlsToPdf.convert=Bikurtu
|
||||
|
||||
|
||||
|
||||
|
||||
pdfToPDFA.title=PDFa PDF/A bihurtu
|
||||
pdfToPDFA.header=PDFa PDF/A bihurtu
|
||||
pdfToPDFA.credit=Zerbitzu honek OCRmyPDF erabiltzen du PDFak PDF/A bihurtzeko
|
||||
pdfToPDFA.submit=Bihurtu
|
||||
|
||||
|
||||
|
||||
PDFToWord.title=PDFa Word bihurtu
|
||||
PDFToWord.header=PDFa Word bihurtu
|
||||
PDFToWord.selectText.1=Irteerako fitxategiaren formatua
|
||||
PDFToWord.credit=Zerbitzu honek LibreOffice erabiltzen du fitxategiak bihurtzeko
|
||||
PDFToWord.submit=Bihurtu
|
||||
|
||||
PDFToPresentation.title=PDFa aurkezpen bihurtu
|
||||
PDFToPresentation.header=PDFa aurkezpen bihurtu
|
||||
PDFToPresentation.selectText.1=Irteerako fitxategiaren formatua
|
||||
PDFToPresentation.credit=Zerbitzu honek LibreOffice erabiltzen du fitxategiak bihurtzeko
|
||||
PDFToPresentation.submit=Bihurtu
|
||||
|
||||
|
||||
PDFToText.title=PDFa TXT/RTF bihurtu
|
||||
PDFToText.header=PDFa TXT/RTF bihurtu
|
||||
PDFToText.selectText.1=Irteerako fitxategiaren formatua
|
||||
PDFToText.credit=Zerbitzu honek LibreOffice erabiltzen du fitxategiak bihurtzeko
|
||||
PDFToText.submit=Bihurtu
|
||||
|
||||
|
||||
PDFToHTML.title=PDFa HTML bihurtu
|
||||
PDFToHTML.header=PDFa HTML bihurtu
|
||||
PDFToHTML.credit=Zerbitzu honek LibreOffice erabiltzen du fitxategiak bihurtzeko
|
||||
PDFToHTML.submit=Bihurtu
|
||||
|
||||
PDFToXML.title=PDFa XML bihurtu
|
||||
PDFToXML.header=PDFa XML bihurtu
|
||||
PDFToXML.credit=Zerbitzu honek LibreOffice erabiltzen du fitxategiak bihurtzeko
|
||||
PDFToXML.submit=Bihurtu
|
||||
@@ -24,6 +24,7 @@ close=Fermer
|
||||
filesSelected=fichiers sélectionnés
|
||||
noFavourites=Aucun favori ajouté
|
||||
bored=Ennuyé d'attendre ?
|
||||
alphabet=Alphabet
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
@@ -127,15 +128,37 @@ home.repair.desc=Essaye de réparer un PDF corrompu/cassé
|
||||
home.removeBlanks.title=Supprimer les pages vierges
|
||||
home.removeBlanks.desc=Détecte et supprime les pages vierges d'un document
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
|
||||
home.compare.title=Comparer
|
||||
home.compare.desc=Compare et affiche les différences entre 2 documents PDF
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf=Télécharger le PDF
|
||||
text=Texte
|
||||
font=Police
|
||||
selectFilter=-- Sélectionner --
|
||||
pageNum=numéro de page
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title=Signature du certificat
|
||||
certSign.header=Signer un PDF avec votre certificat (Travail en cours)
|
||||
certSign.selectPDF=Sélectionnez un fichier PDF à signer :
|
||||
@@ -240,6 +263,7 @@ fileToPDF.submit=Convertir en PDF
|
||||
addImage.title=Ajouter une image
|
||||
addImage.header=Ajouter une image au PDF
|
||||
addImage.everyPage=Chaque page?
|
||||
addImage.upload=Ajouter une image
|
||||
addImage.submit=Ajouter une image
|
||||
|
||||
#compress
|
||||
@@ -334,6 +358,9 @@ addPassword.selectText.10=Empêcher la modification
|
||||
addPassword.selectText.11=Empêcher la modification des annotations
|
||||
addPassword.selectText.12=Empêcher l'impression
|
||||
addPassword.selectText.13=Empêcher l'impression de différents formats
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=Crypter
|
||||
|
||||
#watermark
|
||||
|
||||
@@ -20,6 +20,7 @@ close=Chiudi
|
||||
filesSelected=file selezionati
|
||||
noFavourites=Nessun preferito
|
||||
bored=Stanco di aspettare?
|
||||
alphabet=Alfabeto
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
@@ -122,15 +123,37 @@ home.repair.desc=Prova a riparare un PDF corrotto.
|
||||
home.removeBlanks.title=Rimuovi pagine vuote
|
||||
home.removeBlanks.desc=Trova e rimuovi pagine vuote da un PDF.
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
|
||||
home.compare.title=Compara
|
||||
home.compare.desc=Vedi e compara le differenze tra due PDF.
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf=Scarica PDF
|
||||
text=Testo
|
||||
font=Font
|
||||
selectFillter=-- Seleziona --
|
||||
pageNum=Numero pagina
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title=Firma del certificato
|
||||
certSign.header=Firma un PDF con il tuo certificato (Lavoro in corso)
|
||||
certSign.selectPDF=Seleziona un file PDF per la firma:
|
||||
@@ -248,8 +271,9 @@ compress.submit=Comprimi
|
||||
|
||||
#Add image
|
||||
addImage.title=Aggiungi Immagine
|
||||
addImage.header=Aggiungi un'immagine ad un PDF.
|
||||
addImage.header=Aggiungi un'immagine ad un PDF
|
||||
addImage.everyPage=Ogni pagina?
|
||||
addImage.upload=Aggiungi immagine
|
||||
addImage.submit=Aggiungi immagine
|
||||
|
||||
|
||||
@@ -337,6 +361,9 @@ addPassword.selectText.10=Previeni modifiche
|
||||
addPassword.selectText.11=Previeni annotazioni
|
||||
addPassword.selectText.12=Previeni stampa
|
||||
addPassword.selectText.13=Previeni stampa in diversi formati
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=Crittografa
|
||||
|
||||
#watermark
|
||||
|
||||
472
src/main/resources/messages_ja_JP.properties
Normal file
472
src/main/resources/messages_ja_JP.properties
Normal file
@@ -0,0 +1,472 @@
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||
language.direction=ltr
|
||||
|
||||
pdfPrompt=PDFを選択
|
||||
multiPdfPrompt=PDFを選択 (2つ以上)
|
||||
multiPdfDropPrompt=PDFを選択 (又はドラッグ&ドロップ)
|
||||
imgPrompt=画像を選択
|
||||
genericSubmit=送信
|
||||
processTimeWarning=警告:この処理はファイルサイズによって1分程度かかることがあります
|
||||
pageOrderPrompt=ページ順序 (ページ番号をカンマ区切り又は2n+1のような関数で入力):
|
||||
goToPage=移動
|
||||
true=True
|
||||
false=False
|
||||
unknown=不明
|
||||
save=保存
|
||||
close=閉じる
|
||||
filesSelected=選択されたファイル
|
||||
noFavourites=お気に入りはありません
|
||||
bored=待ち時間が退屈<EFBFBD><EFBFBD>
|
||||
alphabet=\u30A2\u30EB\u30D5\u30A1\u30D9\u30C3\u30C8<43>
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=PDFのあらゆるニーズに対応するローカルホスティングされた総合窓口です。
|
||||
|
||||
|
||||
navbar.convert=変換
|
||||
navbar.security=セキュリティ
|
||||
navbar.other=その他
|
||||
navbar.darkmode=ダークモード
|
||||
navbar.pageOps=ページ操作
|
||||
|
||||
home.multiTool.title=PDFマルチツール
|
||||
home.multiTool.desc=ページの結合、回転、並べ替え、削除します。
|
||||
|
||||
home.merge.title=結合
|
||||
home.merge.desc=複数のPDFを1つに結合します。
|
||||
|
||||
home.split.title=分割
|
||||
home.split.desc=PDFを複数のドキュメントに分割します。
|
||||
|
||||
home.rotate.title=回転
|
||||
home.rotate.desc=PDFを回転します。
|
||||
|
||||
home.imageToPdf.title=画像をPDFに変換
|
||||
home.imageToPdf.desc=画像 (PNG, JPEG, GIF) をPDFに変換します。
|
||||
|
||||
home.pdfToImage.title=PDFを画像に変換
|
||||
home.pdfToImage.desc=PDFを画像 (PNG, JPEG, GIF) に変換します。
|
||||
|
||||
home.pdfOrganiser.title=整理
|
||||
home.pdfOrganiser.desc=ページの削除/並べ替えします。
|
||||
|
||||
home.addImage.title=画像の追加
|
||||
home.addImage.desc=PDF上の任意の場所に画像を追加します。
|
||||
|
||||
home.watermark.title=透かしの追加
|
||||
home.watermark.desc=PDFに独自の透かしを追加します。
|
||||
|
||||
home.remove-watermark.title=透かしの削除
|
||||
home.remove-watermark.desc=PDFから透かしを削除します。
|
||||
|
||||
home.permissions.title=権限の変更
|
||||
home.permissions.desc=PDFの権限を変更します。
|
||||
|
||||
home.removePages.title=削除
|
||||
home.removePages.desc=PDFから不要なページを削除します。
|
||||
|
||||
home.addPassword.title=パスワードの追加
|
||||
home.addPassword.desc=PDFをパスワードで暗号化します。
|
||||
|
||||
home.removePassword.title=パスワードの削除
|
||||
home.removePassword.desc=PDFからパスワードの削除します。
|
||||
|
||||
home.compressPdfs.title=圧縮
|
||||
home.compressPdfs.desc=PDFを圧縮してファイルサイズを小さくします。
|
||||
|
||||
home.changeMetadata.title=メタデータの変更
|
||||
home.changeMetadata.desc=PDFのメタデータを変更/削除/追加します。
|
||||
|
||||
home.fileToPDF.title=ファイルをPDFに変換
|
||||
home.fileToPDF.desc=ほぼすべてのファイルをPDFに変換します。 (DOCX, PNG, XLS, PPT, TXTなど)
|
||||
|
||||
home.ocr.title=OCR / クリーンアップ
|
||||
home.ocr.desc=クリーンアップはPDF内の画像からテキストを検出してテキストとして再追加します。
|
||||
|
||||
home.extractImages.title=画像の抽出
|
||||
home.extractImages.desc=PDFからすべての画像を抽出してzipで保存します。
|
||||
|
||||
home.pdfToPDFA.title=PDFをPDF/Aに変換
|
||||
home.pdfToPDFA.desc=長期保存のためにPDFをPDF/Aに変換。
|
||||
|
||||
home.PDFToWord.title=PDFをWordに変換
|
||||
home.PDFToWord.desc=PDFをWord形式に変換します。 (DOC, DOCX および ODT)
|
||||
|
||||
home.PDFToPresentation.title=PDFをプレゼンテーションに変換
|
||||
home.PDFToPresentation.desc=PDFをプレゼンテーション形式に変換します。 (PPT, PPTX および ODP)
|
||||
|
||||
home.PDFToText.title=PDFをText/RTFに変換
|
||||
home.PDFToText.desc=PDFをTextまたはRTF形式に変換します。
|
||||
|
||||
home.PDFToHTML.title=PDFをHTMLに変換
|
||||
home.PDFToHTML.desc=PDFをHTML形式に変換します。
|
||||
|
||||
home.PDFToXML.title=PDFをXMLに変換
|
||||
home.PDFToXML.desc=PDFをXML形式に変換します。
|
||||
|
||||
home.ScannerImageSplit.title=スキャンされた画像の検出/分割
|
||||
home.ScannerImageSplit.desc=1枚の画像/PDFから複数の写真を分割します。
|
||||
|
||||
home.sign.title=署名
|
||||
home.sign.desc=手書き、テキストまたは画像によってPDFに署名を追加します。
|
||||
|
||||
home.flatten.title=平坦化
|
||||
home.flatten.desc=PDFからインタラクティブな要素とフォームをすべて削除します。
|
||||
|
||||
home.repair.title=修復
|
||||
home.repair.desc=破損したPDFの修復を試みます。
|
||||
|
||||
home.removeBlanks.title=空白ページの削除
|
||||
home.removeBlanks.desc=ドキュメントから空白ページを検出して削除します。
|
||||
|
||||
home.compare.title=比較
|
||||
home.compare.desc=2つのPDFを比較して表示します。
|
||||
|
||||
home.certSign.title=証明書による署名
|
||||
home.certSign.desc=証明書/キーを使用してPDFに署名します。 (PEM/P12)
|
||||
|
||||
home.pageLayout.title=マルチページレイアウト
|
||||
home.pageLayout.desc=PDFの複数のページを1ページに結合します。
|
||||
|
||||
home.scalePages.title=ページの縮尺の調整
|
||||
home.scalePages.desc=ページやコンテンツの縮尺を変更します。
|
||||
|
||||
error.pdfPassword=PDFにパスワードが設定されてますが、パスワードが入力されてないか間違ってます。
|
||||
|
||||
downloadPdf=PDFをダウンロード
|
||||
text=テキスト
|
||||
font=フォント
|
||||
selectFillter=-- 選択 --
|
||||
pageNum=ページ番号
|
||||
|
||||
pageLayout.title=マルチページレイアウト
|
||||
pageLayout.header=マルチページレイアウト
|
||||
pageLayout.pagesPerSheet=1枚あたりのページ数:
|
||||
pageLayout.submit=送信
|
||||
|
||||
scalePages.title=ページの縮尺の調整
|
||||
scalePages.header=ページの縮尺の調整
|
||||
scalePages.pageSize=1ページのサイズ
|
||||
scalePages.scaleFactor=1ページの拡大レベル (トリミング)。
|
||||
scalePages.submit=送信
|
||||
|
||||
certSign.title=証明書による署名
|
||||
certSign.header=証明書を使用してPDFに署名します。 (進行中)
|
||||
certSign.selectPDF=署名するPDFファイルを選択:
|
||||
certSign.selectKey=秘密キーファイルを選択 (PKCS#8形式、.pemまたは.der) :
|
||||
certSign.selectCert=証明書ファイルを選択 (X.509形式、.pemまたは.der) :
|
||||
certSign.selectP12=PKCS#12キーストアファイルを選択 (.p12または.pfx) (オプション。指定する場合は秘密キーと証明書が含まれている必要があります。):
|
||||
certSign.certType=証明書の種類
|
||||
certSign.password=キーストアまたは秘密キーのパスワードを入力 (ある場合) :
|
||||
certSign.showSig=署名を表示
|
||||
certSign.reason=理由
|
||||
certSign.location=場所
|
||||
certSign.name=名前
|
||||
certSign.submit=PDFに署名
|
||||
|
||||
removeBlanks.title=空白の削除
|
||||
removeBlanks.header=空白ページの削除
|
||||
removeBlanks.threshold=しきい値 :
|
||||
removeBlanks.thresholdDesc=白色ピクセルの白さを決めるためのしきい値
|
||||
removeBlanks.whitePercent=白比率
|
||||
removeBlanks.whitePercentDesc=削除するページの白の割合
|
||||
removeBlanks.submit=空白ページの削除
|
||||
|
||||
compare.title=比較
|
||||
compare.header=PDFの比較
|
||||
compare.document.1=ドキュメント 1
|
||||
compare.document.2=ドキュメント 2
|
||||
compare.submit=比較
|
||||
|
||||
sign.title=署名
|
||||
sign.header=PDFに署名
|
||||
sign.upload=画像をアップロード
|
||||
sign.draw=署名を書く
|
||||
sign.text=テキスト入力
|
||||
sign.clear=クリア
|
||||
sign.add=追加
|
||||
|
||||
repair.title=修復
|
||||
repair.header=PDFを修復
|
||||
repair.submit=修復
|
||||
|
||||
flatten.title=平坦化
|
||||
flatten.header=PDFを平坦化する
|
||||
flatten.submit=平坦化
|
||||
|
||||
ScannerImageSplit.selectText.1=角度のしきい値:
|
||||
ScannerImageSplit.selectText.2=画像を回転させるために必要な絶対角度の最小値を設定 (初期値:10)。
|
||||
ScannerImageSplit.selectText.3=許容範囲:
|
||||
ScannerImageSplit.selectText.4=推定された背景色周辺のカラーバリエーションの範囲を決定 (初期値:30)。
|
||||
ScannerImageSplit.selectText.5=最小面積:
|
||||
ScannerImageSplit.selectText.6=画像の最小面積のしきい値を設定 (初期値:10000)。
|
||||
ScannerImageSplit.selectText.7=最小輪郭面積:
|
||||
ScannerImageSplit.selectText.8=画像の最小の輪郭面積のしきい値を設定。
|
||||
ScannerImageSplit.selectText.9=境界線サイズ:
|
||||
ScannerImageSplit.selectText.10=出力に白い縁取りが出ないように追加・削除される境界線の大きさを設定 (初期値:1)。
|
||||
|
||||
navbar.settings=設定
|
||||
settings.title=設定
|
||||
settings.update=利用可能なアップデート
|
||||
settings.appVersion=Appバージョン:
|
||||
settings.downloadOption.title=ダウンロードオプション (zip以外の単一ファイル):
|
||||
settings.downloadOption.1=同じウィンドウで開く
|
||||
settings.downloadOption.2=新しいウィンドウで開く
|
||||
settings.downloadOption.3=ファイルをダウンロード
|
||||
settings.zipThreshold=このファイル数を超えたときにファイルを圧縮する
|
||||
|
||||
|
||||
|
||||
|
||||
#OCR
|
||||
ocr.title=OCR / クリーンアップ
|
||||
ocr.header=クリーンアップ / OCR (光学式文字認識)
|
||||
ocr.selectText.1=PDF内で検出される言語を選択 (リストされているものは現在検出されているものです):
|
||||
ocr.selectText.2=OCR処理されたPDFと一緒に、OCRしたテキストを含むテキストファイルを作成する
|
||||
ocr.selectText.3=斜めにスキャンされたページを回転させて修正する
|
||||
ocr.selectText.4=ページをきれいにして背景ノイズの中からテキストを検出しにくくする。(出力は変わりません)
|
||||
ocr.selectText.5=ページをきれいにして背景ノイズの中からテキストを検出しにくくし、出力はクリーンアップを維持する。
|
||||
ocr.selectText.6=インタラクティブなテキストを含むページを無視し、画像ページのみをOCRする
|
||||
ocr.selectText.7=強制OCR、全てのページで元のテキスト要素を全て削除してOCRする
|
||||
ocr.selectText.8=Normal (PDFにテキストが含まれている場合はエラーになります。)
|
||||
ocr.selectText.9=追加設定
|
||||
ocr.selectText.10=OCRモード
|
||||
ocr.selectText.11=OCR後に画像を削除する (すべての画像を削除します。変換ステップの一部である場合にのみ有効です)。
|
||||
ocr.selectText.12=レンダリングタイプ (高度)
|
||||
ocr.help=他の言語でこれを使用する方法やDocker以外で使用する方法についてはこのドキュメントをお読みください。
|
||||
ocr.credit=本サービスにはOCRにOCRmyPDFとTesseractを使用しています。
|
||||
ocr.submit=OCRでPDFを処理する
|
||||
|
||||
|
||||
|
||||
extractImages.title=画像の抽出
|
||||
extractImages.header=画像の抽出
|
||||
extractImages.selectText=抽出した画像のフォーマットを選択
|
||||
extractImages.submit=抽出
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=ファイルをPDFに変換
|
||||
fileToPDF.header=あらゆるファイルをPDFに変換
|
||||
fileToPDF.credit=本サービスはファイル変換にLibreOfficeとUnoconvを使用しています。
|
||||
fileToPDF.supportedFileTypes=サポートされるファイル形式には以下が含まれますが、完全な更新リストについてはLibreOfficeのドキュメントを参照してください。
|
||||
fileToPDF.submit=PDFを変換
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=圧縮
|
||||
compress.header=PDFを圧縮
|
||||
compress.credit=本サービスはPDFの圧縮/最適化にGhostscriptを使用しています。
|
||||
compress.selectText.1=手動モード - 1 から 4
|
||||
compress.selectText.2=品質レベル:
|
||||
compress.selectText.3=4 (テキスト画像は最悪)
|
||||
compress.selectText.4=自動モード - PDFを正確なサイズにするために品質を自動調整する。
|
||||
compress.selectText.5=PDFサイズ (例 25MB, 10.8MB, 25KB)
|
||||
compress.submit=圧縮
|
||||
|
||||
|
||||
#Add image
|
||||
addImage.title=画像の追加
|
||||
addImage.header=PDFに画像を追加
|
||||
addImage.everyPage=全ページ?
|
||||
addImage.upload=画像の追加
|
||||
addImage.submit=画像の追加
|
||||
|
||||
|
||||
#merge
|
||||
merge.title=結合
|
||||
merge.header=複数のPDFを結合 (2ファイル以上)
|
||||
merge.submit=結合
|
||||
|
||||
#pdfOrganiser
|
||||
pdfOrganiser.title=整理
|
||||
pdfOrganiser.header=PDFページの整理
|
||||
pdfOrganiser.submit=ページの整理
|
||||
|
||||
#multiTool
|
||||
multiTool.title=PDFマルチツール
|
||||
multiTool.header=PDFマルチツール
|
||||
|
||||
|
||||
#pageRemover
|
||||
pageRemover.title=ページ削除
|
||||
pageRemover.header=PDFページ削除
|
||||
pageRemover.pagesToDelete=削除するページ (ページ番号のカンマ区切りリストを入力してください):
|
||||
pageRemover.submit=ページ削除
|
||||
|
||||
#rotate
|
||||
rotate.title=PDFの回転
|
||||
rotate.header=PDFの回転
|
||||
rotate.selectAngle=回転角度を選択 (90度の倍数):
|
||||
rotate.submit=回転
|
||||
|
||||
|
||||
|
||||
|
||||
#merge
|
||||
split.title=PDFの分割
|
||||
split.header=PDFの分割
|
||||
split.desc.1=選択する番号は分割するページ番号です。
|
||||
split.desc.2=したがって、1,3,7-8を選択すると、10ページのドキュメントが以下のように6つのPDFに分割されることになります。
|
||||
split.desc.3=ドキュメント #1: ページ 1
|
||||
split.desc.4=ドキュメント #2: ページ 2, 3
|
||||
split.desc.5=ドキュメント #3: ページ 4, 5, 6
|
||||
split.desc.6=ドキュメント #4: ページ 7
|
||||
split.desc.7=ドキュメント #5: ページ 8
|
||||
split.desc.8=ドキュメント #6: ページ 9, 10
|
||||
split.splitPages=分割するページ番号を入力:
|
||||
split.submit=分割
|
||||
|
||||
|
||||
#merge
|
||||
imageToPDF.title=画像をPDFに変換
|
||||
imageToPDF.header=画像をPDFに変換
|
||||
imageToPDF.submit=変換
|
||||
imageToPDF.selectText.1=フィットするように引き伸ばす
|
||||
imageToPDF.selectText.2=PDFの自動回転
|
||||
imageToPDF.selectText.3=マルチファイルの処理 (複数の画像を操作する場合に有効になります)
|
||||
imageToPDF.selectText.4=1つのPDFに結合
|
||||
imageToPDF.selectText.5=個別のPDFに変換
|
||||
|
||||
#pdfToImage
|
||||
pdfToImage.title=PDFを画像に変換
|
||||
pdfToImage.header=PDFを画像に変換
|
||||
pdfToImage.selectText=画像の形式
|
||||
pdfToImage.singleOrMultiple=画像出力タイプ
|
||||
pdfToImage.single=単一の大きな画像
|
||||
pdfToImage.multi=複数の画像
|
||||
pdfToImage.colorType=カラーモード
|
||||
pdfToImage.color=カラー
|
||||
pdfToImage.grey=グレースケール
|
||||
pdfToImage.blackwhite=白黒 (データが失われる可能性があります!)
|
||||
pdfToImage.submit=変換
|
||||
|
||||
#addPassword
|
||||
addPassword.title=パスワードの追加
|
||||
addPassword.header=パスワードの追加 (暗号化)
|
||||
addPassword.selectText.1=暗号化するPDFを選択
|
||||
addPassword.selectText.2=ユーザーパスワード
|
||||
addPassword.selectText.3=暗号化キーの長さ
|
||||
addPassword.selectText.4=値が大きいほど強力ですが、値が小さいほど互換性が高くなります。
|
||||
addPassword.selectText.5=権限の設定 (所有者パスワードとの併用をおすすめします)
|
||||
addPassword.selectText.6=ドキュメントの組立を禁止
|
||||
addPassword.selectText.7=コンテンツの抽出を禁止
|
||||
addPassword.selectText.8=アクセシビリティのための抽出を禁止
|
||||
addPassword.selectText.9=フォームへの入力を禁止
|
||||
addPassword.selectText.10=変更を禁止
|
||||
addPassword.selectText.11=注釈の変更を禁止
|
||||
addPassword.selectText.12=印刷を禁止
|
||||
addPassword.selectText.13=異なる形式の印刷を禁止
|
||||
addPassword.selectText.14=所有者パスワード
|
||||
addPassword.selectText.15=ドキュメントを開いた後に実行できる操作を制限します (すべてのリーダーでサポートされているわけではありません)
|
||||
addPassword.selectText.16=ドキュメントを開くことを制限します
|
||||
addPassword.submit=暗号化
|
||||
|
||||
#watermark
|
||||
watermark.title=透かしの追加
|
||||
watermark.header=透かしの追加
|
||||
watermark.selectText.1=透かしを追加するPDFを選択:
|
||||
watermark.selectText.2=透かしのテキスト:
|
||||
watermark.selectText.3=文字サイズ:
|
||||
watermark.selectText.4=回転 (0-360):
|
||||
watermark.selectText.5=幅スペース (各透かし間の水平方向のスペース):
|
||||
watermark.selectText.6=高さスペース (各透かし間の垂直方向のスペース):
|
||||
watermark.selectText.7=不透明度 (0% - 100%):
|
||||
watermark.submit=透かしを追加
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=透かしの削除
|
||||
remove-watermark.header=透かしの削除
|
||||
remove-watermark.selectText.1=透かしを削除するPDFを選択:
|
||||
remove-watermark.selectText.2=透かしのテキスト:
|
||||
remove-watermark.submit=透かしを削除
|
||||
|
||||
#Change permissions
|
||||
permissions.title=権限の変更
|
||||
permissions.header=権限の変更
|
||||
permissions.warning=警告、これらの権限を変更できないようにするため、パスワードの追加ページでパスワードを設定することを推奨します。
|
||||
permissions.selectText.1=権限を変更するPDFを選択
|
||||
permissions.selectText.2=権限の設定
|
||||
permissions.selectText.3=ドキュメントの組立を禁止
|
||||
permissions.selectText.4=コンテンツの抽出を禁止
|
||||
permissions.selectText.5=アクセシビリティのための抽出を禁止
|
||||
permissions.selectText.6=フォームへの入力を禁止
|
||||
permissions.selectText.7=変更を禁止
|
||||
permissions.selectText.8=注釈の変更を禁止
|
||||
permissions.selectText.9=印刷を禁止
|
||||
permissions.selectText.10=異なる形式の印刷を禁止
|
||||
permissions.submit=変更
|
||||
|
||||
#remove password
|
||||
removePassword.title=パスワードの削除
|
||||
removePassword.header=パスワードの削除 (復号化)
|
||||
removePassword.selectText.1=復号化するPDFを選択
|
||||
removePassword.selectText.2=パスワード
|
||||
removePassword.submit=削除
|
||||
|
||||
changeMetadata.title=メタデータの変更
|
||||
changeMetadata.header=メタデータの変更
|
||||
changeMetadata.selectText.1=変更したい変数を編集してください
|
||||
changeMetadata.selectText.2=すべてのメタデータを削除
|
||||
changeMetadata.selectText.3=カスタムメタデータを表示
|
||||
changeMetadata.author=著者:
|
||||
changeMetadata.creationDate=作成日 (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.creator=作成者:
|
||||
changeMetadata.keywords=キーワード:
|
||||
changeMetadata.modDate=変更日 (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=プロデューサー:
|
||||
changeMetadata.subject=主題:
|
||||
changeMetadata.title=タイトル:
|
||||
changeMetadata.trapped=トラッピング:
|
||||
changeMetadata.selectText.4=その他のメタデータ:
|
||||
changeMetadata.selectText.5=カスタムメタデータの追加
|
||||
changeMetadata.submit=変更
|
||||
|
||||
xlsToPdf.title=ExcelをPDFに変換
|
||||
xlsToPdf.header=ExcelをPDFに変換
|
||||
xlsToPdf.selectText.1=変換するXLSまたはXLSX Execlシートを選択
|
||||
xlsToPdf.convert=変換
|
||||
|
||||
|
||||
|
||||
|
||||
pdfToPDFA.title=PDFをPDF/Aに変換
|
||||
pdfToPDFA.header=PDFをPDF/Aに変換
|
||||
pdfToPDFA.credit=本サービスはPDF/Aの変換にOCRmyPDFを使用しています。
|
||||
pdfToPDFA.submit=変換
|
||||
|
||||
|
||||
|
||||
PDFToWord.title=PDFをWordに変換
|
||||
PDFToWord.header=PDFをWordに変換
|
||||
PDFToWord.selectText.1=出力ファイル形式
|
||||
PDFToWord.credit=本サービスはファイル変換にLibreOfficeを使用しています。
|
||||
PDFToWord.submit=変換
|
||||
|
||||
PDFToPresentation.title=PDFをプレゼンテーションに変換
|
||||
PDFToPresentation.header=PDFをプレゼンテーションに変換
|
||||
PDFToPresentation.selectText.1=出力ファイル形式
|
||||
PDFToPresentation.credit=本サービスはファイル変換にLibreOfficeを使用しています。
|
||||
PDFToPresentation.submit=変換
|
||||
|
||||
|
||||
PDFToText.title=PDFをText/RTFに変換
|
||||
PDFToText.header=PDFをText/RTFに変換
|
||||
PDFToText.selectText.1=出力ファイル形式
|
||||
PDFToText.credit=本サービスはファイル変換にLibreOfficeを使用しています。
|
||||
PDFToText.submit=変換
|
||||
|
||||
|
||||
PDFToHTML.title=PDFをHTMLに変換
|
||||
PDFToHTML.header=PDFをHTMLに変換
|
||||
PDFToHTML.credit=本サービスはファイル変換にLibreOfficeを使用しています。
|
||||
PDFToHTML.submit=変換
|
||||
|
||||
PDFToXML.title=PDFをXMLに変換
|
||||
PDFToXML.header=PDFをXMLに変換
|
||||
PDFToXML.credit=本サービスはファイル変換にLibreOfficeを使用しています。
|
||||
PDFToXML.submit=変換
|
||||
512
src/main/resources/messages_ko_KR.properties
Normal file
512
src/main/resources/messages_ko_KR.properties
Normal file
@@ -0,0 +1,512 @@
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||
language.direction=ltr
|
||||
|
||||
pdfPrompt=PDF 선택
|
||||
multiPdfPrompt=PDF 선택(2개 이상)
|
||||
multiPdfDropPrompt=사용할 모든 PDF를 선택(또는 드래그 앤 드롭)하세요
|
||||
imgPrompt=이미지 선택
|
||||
genericSubmit=제출
|
||||
processTimeWarning=경고: 파일 크기에 따라 1분 정도 소요될 수 있습니다
|
||||
pageOrderPrompt=페이지 순서(쉼표로 구분된 페이지 번호 목록 입력):
|
||||
goToPage=이동
|
||||
true=참
|
||||
false=거짓
|
||||
unknown=알 수 없음
|
||||
save=저장
|
||||
close=닫기
|
||||
filesSelected=개 파일 선택됨
|
||||
noFavourites=즐겨찾기 없음
|
||||
bored=기다리는 게 지루하신가요?
|
||||
alphabet=\uC54C\uD30C\uBCB3
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=당신의 PDF에 필요한 모든 것이 있는 로컬 호스팅된 원스톱 숍입니다.
|
||||
|
||||
|
||||
navbar.convert=변환
|
||||
navbar.security=보안
|
||||
navbar.other=기타
|
||||
navbar.darkmode=다크 모드
|
||||
navbar.pageOps=Page Operations
|
||||
|
||||
home.multiTool.title=PDF 멀티 툴
|
||||
home.multiTool.desc=페이지를 병합, 회전, 재배열, 제거하세요.
|
||||
|
||||
home.merge.title=병합
|
||||
home.merge.desc=여러 개의 PDF를 쉽게 하나로 합치세요.
|
||||
|
||||
home.split.title=분할
|
||||
home.split.desc=PDF를 여러 개의 문서로 분할하세요.
|
||||
|
||||
home.rotate.title=회전
|
||||
home.rotate.desc=PDF를 쉽게 회전하세요.
|
||||
|
||||
home.imageToPdf.title=Image to PDF
|
||||
home.imageToPdf.desc=이미지(PNG, JPEG, GIF)를 PDF로 변환하세요.
|
||||
|
||||
home.pdfToImage.title=PDF to Image
|
||||
home.pdfToImage.desc=PDF를 이미지(PNG, JPEG, GIF)로 변환하세요.
|
||||
|
||||
home.pdfOrganiser.title=정렬
|
||||
home.pdfOrganiser.desc=페이지를 원하는 순서대로 제거/재배열하세요.
|
||||
|
||||
home.addImage.title=사진 추가
|
||||
home.addImage.desc=PDF의 설정된 위치에 이미지를 추가하세요.(개발 중)
|
||||
|
||||
home.watermark.title=워터마크 추가
|
||||
home.watermark.desc=PDF 문서에 사용자 지정 워터마크를 추가하세요.
|
||||
|
||||
home.remove-watermark.title=워터마크 제거
|
||||
home.remove-watermark.desc=PDF 문서에서 워터마크를 제거하세요.
|
||||
|
||||
home.permissions.title=권한 변경
|
||||
home.permissions.desc=PDF 문서의 권한을 변경하세요.
|
||||
|
||||
home.removePages.title=제거
|
||||
home.removePages.desc=PDF 문서에서 원치 않는 페이지를 제거하세요.
|
||||
|
||||
home.addPassword.title=비밀번호 추가
|
||||
home.addPassword.desc=PDF 문서를 비밀번호로 암호화하세요.
|
||||
|
||||
home.removePassword.title=비밀번호 제거
|
||||
home.removePassword.desc=PDF 문서에서 비밀번호를 제거하세요.
|
||||
|
||||
home.compressPdfs.title=압축
|
||||
home.compressPdfs.desc=파일 크기를 줄이기 위해 PDF 문서를 압축하세요.
|
||||
|
||||
home.changeMetadata.title=메타데이터 변경
|
||||
home.changeMetadata.desc=PDF 문서의 메타데이터를 수정/제거/추가하세요.
|
||||
|
||||
home.fileToPDF.title=파일을 PDF로 변환
|
||||
home.fileToPDF.desc=거의 모든 파일을 PDF로 변환하세요(DOCX, PNG, XLS, PPT, TXT 등)
|
||||
|
||||
home.ocr.title=OCR / 깔끔하게 스캔
|
||||
home.ocr.desc=깔끔하게 스캔하고 PDF 내의 이미지에서 텍스트를 감지하여 텍스트로 다시 추가합니다.
|
||||
|
||||
home.extractImages.title=이미지 추출
|
||||
home.extractImages.desc=PDF에서 모든 이미지를 추출하여 zip으로 저장합니다.
|
||||
|
||||
home.pdfToPDFA.title=PDF to PDF/A
|
||||
home.pdfToPDFA.desc=장기 보관을 위해 PDF를 PDF/A 문서로 변환하세요.
|
||||
|
||||
home.PDFToWord.title=PDF to Word
|
||||
home.PDFToWord.desc=PDF를 Word 형식으로 변환하세요. (DOC, DOCX, ODT)
|
||||
|
||||
home.PDFToPresentation.title=PDF to 프리젠테이션
|
||||
home.PDFToPresentation.desc=PDF를 프리젠테이션 형식으로 변환하세요. (PPT, PPTX, ODP)
|
||||
|
||||
home.PDFToText.title=PDF to 텍스트/RTF
|
||||
home.PDFToText.desc=PDF를 텍스트 또는 RTF 형식으로 변환하세요.
|
||||
|
||||
home.PDFToHTML.title=PDF to HTML
|
||||
home.PDFToHTML.desc=PDF를 HTML 형식으로 변환하세요.
|
||||
|
||||
home.PDFToXML.title=PDF to XML
|
||||
home.PDFToXML.desc=PDF를 XML 형식으로 변환하세요.
|
||||
|
||||
home.ScannerImageSplit.title=스캔한 사진 감지/분할
|
||||
home.ScannerImageSplit.desc=사진/PDF 내에서 여러 장의 사진을 분할합니다.
|
||||
|
||||
home.sign.title=서명
|
||||
home.sign.desc=PDF에 그림, 텍스트, 이미지로 서명을 추가합니다.
|
||||
|
||||
home.flatten.title=합치기
|
||||
home.flatten.desc=PDF에서 모든 인터랙션 요소와 양식을 제거하세요.
|
||||
|
||||
home.repair.title=복구
|
||||
home.repair.desc=손상된 PDF의 복구를 시도합니다.
|
||||
|
||||
home.removeBlanks.title=빈 페이지 제거
|
||||
home.removeBlanks.desc=문서에서 빈 페이지를 감지하고 제거합니다.
|
||||
|
||||
home.compare.title=비교
|
||||
home.compare.desc=2개의 PDF 문서를 비교하고 차이를 표시합니다.
|
||||
|
||||
home.certSign.title=인증서로 서명
|
||||
home.certSign.desc=PDF에 인증서/키로 서명합니다. (PEM/P12)
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf=PDF 다운로드
|
||||
text=텍스트
|
||||
font=폰트
|
||||
selectFillter=-- 선택 --
|
||||
pageNum=페이지 번호
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title=인증서로 서명
|
||||
certSign.header=PDF에 당신의 인증서로 서명하세요 (개발 중)
|
||||
certSign.selectPDF=서명할 PDF를 선택하세요:
|
||||
certSign.selectKey=개인 키 파일을 선택하세요 (PKCS#8 형식, .pem 또는 .der):
|
||||
certSign.selectCert=인증서 파일을 선택하세요 (X.509 형식, .pem 또는 .der):
|
||||
certSign.selectP12=PKCS#12 키 저장소 파일을 선택하세요 (.p12 or .pfx) (선택 사항, 선택할 경우, 개인 키와 인증서를 포함하고 있어야 합니다):
|
||||
certSign.certType=인증서 유형
|
||||
certSign.password=키 저장소 또는 개인 키 비밀번호를 입력하세요 (있는 경우):
|
||||
certSign.showSig=서명 보기
|
||||
certSign.reason=이유
|
||||
certSign.location=위치
|
||||
certSign.name=이름
|
||||
|
||||
certSign.submit=PDF 서명
|
||||
|
||||
|
||||
|
||||
removeBlanks.title=빈 페이지 제거
|
||||
removeBlanks.header=빈 페이지 제거
|
||||
removeBlanks.threshold=임계값:
|
||||
removeBlanks.thresholdDesc=흰색 픽셀이 얼마나 흰색이어야 하는지를 결정하는 임계값
|
||||
removeBlanks.whitePercent=흰색 비율 (%):
|
||||
removeBlanks.whitePercentDesc=제거될 페이지의 흰색 픽셀 비율
|
||||
removeBlanks.submit=빈 페이지 제거
|
||||
|
||||
compare.title=비교
|
||||
compare.header=PDF 비교
|
||||
compare.document.1=문서 1
|
||||
compare.document.2=문서 2
|
||||
compare.submit=비교
|
||||
|
||||
sign.title=서명
|
||||
sign.header=PDF에 서명
|
||||
sign.upload=이미지 업로드
|
||||
sign.draw=서명 그리기
|
||||
sign.text=텍스트 입력
|
||||
sign.clear=초기화
|
||||
sign.add=추가
|
||||
|
||||
repair.title=복구
|
||||
repair.header=PDF 복구
|
||||
repair.submit=복구
|
||||
|
||||
flatten.title=합치기
|
||||
flatten.header=PDF 합치기
|
||||
flatten.submit=합치기
|
||||
|
||||
ScannerImageSplit.selectText.1=각도 임계값:
|
||||
ScannerImageSplit.selectText.2=이미지를 회전하는 데 필요한 최소 절대 각도를 설정합니다(기본값: 10).
|
||||
ScannerImageSplit.selectText.3=오차 범위:
|
||||
ScannerImageSplit.selectText.4=예상 배경색 주변의 색상 변화 범위를 결정합니다(기본값: 30).
|
||||
ScannerImageSplit.selectText.5=최소 면적:
|
||||
ScannerImageSplit.selectText.6=사진의 최소 면적 임계값을 설정합니다 (기본값: 10000).
|
||||
ScannerImageSplit.selectText.7=최소 윤곽 영역:
|
||||
ScannerImageSplit.selectText.8=사진의 최소 윤곽선 영역 임계값을 설정합니다.
|
||||
ScannerImageSplit.selectText.9=테두리 크기:
|
||||
ScannerImageSplit.selectText.10=출력에서 흰색 테두리를 방지하기 위해 추가 및 제거되는 테두리의 크기를 설정합니다(기본값: 1).
|
||||
|
||||
navbar.settings=설정
|
||||
settings.title=설정
|
||||
settings.update=업데이트 가능
|
||||
settings.appVersion=앱 버전:
|
||||
settings.downloadOption.title=다운로드 옵션 선택 (zip 파일이 아닌 단일 파일 다운로드 시):
|
||||
settings.downloadOption.1=현재 창에서 열기
|
||||
settings.downloadOption.2=새 창에서 열기
|
||||
settings.downloadOption.3=다운로드
|
||||
settings.zipThreshold=다운로드한 파일 수가 초과된 경우 파일 압축하기
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#OCR
|
||||
ocr.title=OCR / 깔끔하게 스캔
|
||||
ocr.header=깔끔하게 스캔 / OCR (광학 문자 인식)
|
||||
ocr.selectText.1=PDF에서 감지할 언어를 선택하십시오 (현재 감지된 언어 목록):
|
||||
ocr.selectText.2=OCR 텍스트가 포함된 텍스트 파일을 OCR 처리된 PDF와 함께 생성
|
||||
ocr.selectText.3=비뚤어진 각도로 스캔한 페이지를 다시 제자리로 돌려 올바른 페이지로 스캔
|
||||
ocr.selectText.4=페이지를 깨끗하게 정리하여 OCR이 배경의 이물질에서 텍스트를 찾을 가능성 줄이기 (출력 변경 없음)
|
||||
ocr.selectText.5=페이지를 깨끗하게 정리하여 OCR이 배경의 이물질에서 텍스트를 찾을 가능성 줄이기 (출력 변경)
|
||||
ocr.selectText.6=인터랙티브 텍스트가 있는 페이지는 건너뛰고 이미지만 OCR
|
||||
ocr.selectText.7=OCR 강제(모든 페이지에서 원본 텍스트 제거하고 OCR로 대체)
|
||||
ocr.selectText.8=일반 (PDF에 텍스트가 포함된 경우 오류 발생)
|
||||
ocr.selectText.9=추가 설정
|
||||
ocr.selectText.10=OCR 모드
|
||||
ocr.selectText.11=OCR 후 이미지 제거(모든 이미지 제거, 변환 단계의 일부인 경우에만 유용)
|
||||
ocr.selectText.12=렌더 유형(고급)
|
||||
ocr.help=다른 언어 또는 Docker에 포함되지 않은 언어에 대해 사용하는 방법에 대해서는 이 문서를 참조하세요.
|
||||
ocr.credit=이 서비스는 OCR에 OCRmyPDF와 Tesseract를 사용합니다.
|
||||
ocr.submit=OCR로 PDF 처리
|
||||
|
||||
|
||||
|
||||
extractImages.title=이미지 추출
|
||||
extractImages.header=이미지 추출
|
||||
extractImages.selectText=추출된 이미지를 변환할 이미지 형식을 선택하세요.
|
||||
extractImages.submit=추출
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=File to PDF
|
||||
fileToPDF.header=모든 파일을 PDF로 변환
|
||||
fileToPDF.credit=이 서비스는 파일 변환에 LibreOffice와 Unoconv를 사용합니다.
|
||||
fileToPDF.supportedFileTypes=지원되는 파일 형식은 아래와 같지만, 지원되는 형식의 전체 업데이트 목록은 LibreOffice 설명서를 참조하세요.
|
||||
fileToPDF.submit=PDF로 변환
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=압축
|
||||
compress.header=PDF 압축
|
||||
compress.credit=이 서비스는 PDF 압축/최적화를 위해 Ghostscript를 사용합니다.
|
||||
compress.selectText.1=수동 모드 - 1에서 4
|
||||
compress.selectText.2=최적화 수준:
|
||||
compress.selectText.3=4 (텍스트 이미지에 적합하지 않음)
|
||||
compress.selectText.4=자동 - 정확한 크기의 PDF를 얻기 위해 품질 자동 조정
|
||||
compress.selectText.5=예상 PDF 크기 (예: 25MB, 10.8MB, 25KB)
|
||||
compress.submit=압축
|
||||
|
||||
|
||||
#Add image
|
||||
addImage.title=이미지 추가
|
||||
addImage.header=PDF에 이미지 추가
|
||||
addImage.everyPage=모든 페이지에 적용
|
||||
addImage.upload=이미지 추가
|
||||
addImage.submit=이미지 추가
|
||||
|
||||
|
||||
#merge
|
||||
merge.title=병합
|
||||
merge.header=여러 개의 PDF 병합 (2개 이상)
|
||||
merge.submit=병합
|
||||
|
||||
#pdfOrganiser
|
||||
pdfOrganiser.title=페이지 정렬 도구
|
||||
pdfOrganiser.header=PDF 페이지 정렬
|
||||
pdfOrganiser.submit=페이지 재정렬
|
||||
|
||||
#multiTool
|
||||
multiTool.title=PDF 멀티 툴
|
||||
multiTool.header=PDF 멀티 툴
|
||||
|
||||
|
||||
#pageRemover
|
||||
pageRemover.title=페이지 제거 도구
|
||||
pageRemover.header=PDF 페이지 제거 도구
|
||||
pageRemover.pagesToDelete=제거할 페이지 (쉼표로 구분된 페이지 번호 입력):
|
||||
pageRemover.submit=페이지 제거
|
||||
|
||||
#rotate
|
||||
rotate.title=PDF 회전
|
||||
rotate.header=PDF 회전
|
||||
rotate.selectAngle=회전 각도 선택 (90도의 배수로):
|
||||
rotate.submit=회전
|
||||
|
||||
|
||||
|
||||
|
||||
#merge
|
||||
split.title=PDF 분할
|
||||
split.header=PDF 분할
|
||||
split.desc.1=선택한 번호는 분할할 페이지 번호입니다.
|
||||
split.desc.2=예를 들어, 1,3,7-8을 선택하면 10페이지 문서를 아래와 같이 6개의 별도의 PDF로 분할하게 됩니다.
|
||||
split.desc.3=문서 #1: 페이지 1
|
||||
split.desc.4=문서 #2: 페이지 2, 3
|
||||
split.desc.5=문서 #3: 페이지 4, 5, 6
|
||||
split.desc.6=문서 #4: 페이지 7
|
||||
split.desc.7=문서 #5: 페이지 8
|
||||
split.desc.8=문서 #6: 페이지 9, 10
|
||||
split.splitPages=분할할 페이지 입력:
|
||||
split.submit=분할
|
||||
|
||||
|
||||
#imageToPdf
|
||||
imageToPDF.title=Image to PDF
|
||||
imageToPDF.header=이미지를 PDF로 변환
|
||||
imageToPDF.submit=변환
|
||||
imageToPDF.selectText.1=맞춤 크기로 늘리기
|
||||
imageToPDF.selectText.2=PDF 자동 회전
|
||||
imageToPDF.selectText.3=다중 파일 로직 (여러 이미지로 작업하는 경우에만 활성화됨)
|
||||
imageToPDF.selectText.4=단일 PDF로 병합
|
||||
imageToPDF.selectText.5=별개의 PDF로 변환
|
||||
|
||||
#pdfToImage
|
||||
pdfToImage.title=PDF to Image
|
||||
pdfToImage.header=PDF를 이미지로 변환
|
||||
pdfToImage.selectText=이미지 형식
|
||||
pdfToImage.singleOrMultiple=이미지 결과 유형
|
||||
pdfToImage.single=단일 큰 이미지
|
||||
pdfToImage.multi=여러 이미지
|
||||
pdfToImage.colorType=색상 유형
|
||||
pdfToImage.color=컬러
|
||||
pdfToImage.grey=그레이스케일
|
||||
pdfToImage.blackwhite=흑백 (데이터 손실 가능성 있음!)
|
||||
pdfToImage.submit=변환하기
|
||||
|
||||
|
||||
#imageToPdf
|
||||
imageToPDF.title=이미지를 PDF로 변환
|
||||
imageToPDF.header=이미지를 PDF로 변환
|
||||
imageToPDF.submit=변환하기
|
||||
imageToPDF.selectText.1=맞춤 크기로 늘리기
|
||||
imageToPDF.selectText.2=PDF 자동 회전
|
||||
imageToPDF.selectText.3=다중 파일 로직 (여러 이미지로 작업하는 경우에만 활성화됨)
|
||||
imageToPDF.selectText.4=단일 PDF로 병합
|
||||
imageToPDF.selectText.5=별도의 PDF로 변환
|
||||
|
||||
#pdfToImage
|
||||
pdfToImage.title=PDF를 이미지로 변환
|
||||
pdfToImage.header=PDF를 이미지로 변환
|
||||
pdfToImage.selectText=이미지 형식
|
||||
pdfToImage.singleOrMultiple=이미지 결과 유형
|
||||
pdfToImage.single=단일 큰 이미지
|
||||
pdfToImage.multi=여러 이미지
|
||||
pdfToImage.colorType=색상 유형
|
||||
pdfToImage.color=컬러
|
||||
pdfToImage.grey=그레이스케일
|
||||
pdfToImage.blackwhite=흑백 (데이터 손실 가능성 있음!)
|
||||
pdfToImage.submit=변환하기
|
||||
|
||||
#addPassword
|
||||
addPassword.title=암호 추가
|
||||
addPassword.header=암호 추가 (암호화)
|
||||
addPassword.selectText.1=암호화할 PDF 선택
|
||||
addPassword.selectText.2=암호
|
||||
addPassword.selectText.3=암호화 키 길이
|
||||
addPassword.selectText.4=값이 높을수록 강력하지만, 값이 낮을수록 호환성이 더 좋습니다.
|
||||
addPassword.selectText.5=설정할 권한
|
||||
addPassword.selectText.6=문서 조립 방지
|
||||
addPassword.selectText.7=콘텐츠 추출 방지
|
||||
addPassword.selectText.8=접근성을 위한 추출 방지
|
||||
addPassword.selectText.9=양식 작성 방지
|
||||
addPassword.selectText.10=수정 방지
|
||||
addPassword.selectText.11=주석 수정 방지
|
||||
addPassword.selectText.12=인쇄 방지
|
||||
addPassword.selectText.13=다른 형식으로 인쇄 방<>
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself<6C>
|
||||
addPassword.submit=암호화
|
||||
|
||||
#watermark
|
||||
watermark.title=워터마크 추가
|
||||
watermark.header=워터마크 추가
|
||||
watermark.selectText.1=워터마크를 추가할 PDF 선택:
|
||||
watermark.selectText.2=워터마크 텍스트:
|
||||
watermark.selectText.3=폰트 크기:
|
||||
watermark.selectText.4=회전 각도 (0-360):
|
||||
watermark.selectText.5=가로 간격 (각 워터마크 사이의 가로 공간):
|
||||
watermark.selectText.6=세로 간격 (각 워터마크 사이의 세로 공간):
|
||||
watermark.selectText.7=투명도 (0% - 100%):
|
||||
watermark.submit=워터마크 추가
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=워터마크 제거
|
||||
remove-watermark.header=워터마크 제거
|
||||
remove-watermark.selectText.1=워터마크를 제거할 PDF 선택:
|
||||
remove-watermark.selectText.2=워터마크 텍스트:
|
||||
remove-watermark.submit=워터마크 제거
|
||||
|
||||
#Change permissions
|
||||
permissions.title=권한 변경
|
||||
permissions.header=권한 변경
|
||||
permissions.warning=이 권한을 변경할 수 없도록 하기 위해서는 암호를 사용하여 비밀번호 추가 페이지에서 설정하는 것이 좋습니다.
|
||||
permissions.selectText.1=권한을 변경할 PDF 선택
|
||||
permissions.selectText.2=설정할 권한
|
||||
permissions.selectText.3=문서 조립 방지
|
||||
permissions.selectText.4=콘텐츠 추출 방지
|
||||
permissions.selectText.5=접근성을 위한 추출 방지
|
||||
permissions.selectText.6=양식 작성 방지
|
||||
permissions.selectText.7=수정 방지
|
||||
permissions.selectText.8=주석 수정 방지
|
||||
permissions.selectText.9=인쇄 방지
|
||||
permissions.selectText.10=다른 형식으로 인쇄 방지
|
||||
permissions.submit=변경
|
||||
|
||||
#remove password
|
||||
removePassword.title=암호 제거
|
||||
removePassword.header=암호 제거 (복호화)
|
||||
removePassword.selectText.1=복호화할 PDF 선택
|
||||
removePassword.selectText.2=암호
|
||||
removePassword.submit=제거
|
||||
|
||||
changeMetadata.title=메타데이터 변경
|
||||
changeMetadata.header=메타데이터 변경
|
||||
changeMetadata.selectText.1=변경하려는 변수를 편집해주세요
|
||||
changeMetadata.selectText.2=모든 메타데이터 삭제
|
||||
changeMetadata.selectText.3=사용자 정의 메타데이터 표시:
|
||||
changeMetadata.author=저자:
|
||||
changeMetadata.creationDate=작성일 (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.creator=제작자:
|
||||
changeMetadata.keywords=키워드:
|
||||
changeMetadata.modDate=수정일 (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=생성자:
|
||||
changeMetadata.subject=주제:
|
||||
changeMetadata.title=제목:
|
||||
changeMetadata.trapped=잠긴 상태:
|
||||
changeMetadata.selectText.4=기타 메타데이터:
|
||||
changeMetadata.selectText.5=사용자 정의 메타데이터 항목 추가
|
||||
changeMetadata.submit=변경
|
||||
|
||||
xlsToPdf.title=Excel to PDF
|
||||
xlsToPdf.header=Excel을 PDF로 변환
|
||||
xlsToPdf.selectText.1=변환할 XLS 또는 XLSX Excel 시트 선택
|
||||
xlsToPdf.convert=변환하기
|
||||
|
||||
|
||||
|
||||
|
||||
pdfToPDFA.title=PDF To PDF/A
|
||||
pdfToPDFA.header=PDF를 PDF/A로 변환
|
||||
pdfToPDFA.credit=이 서비스는 PDF/A 변환을 위해 OCRmyPDF를 사용합니다.
|
||||
pdfToPDFA.submit=변환
|
||||
|
||||
|
||||
|
||||
PDFToWord.title=PDF to Word
|
||||
PDFToWord.header=PDF를 Word로 변환
|
||||
PDFToWord.selectText.1=출력 파일 형식
|
||||
PDFToWord.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.
|
||||
PDFToWord.submit=변환
|
||||
|
||||
PDFToPresentation.title=PDF to Presentation
|
||||
PDFToPresentation.header=PDF를 프레젠테이션으로 변환
|
||||
PDFToPresentation.selectText.1=출력 파일 형식
|
||||
PDFToPresentation.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.
|
||||
PDFToPresentation.submit=변환
|
||||
|
||||
|
||||
PDFToText.title=PDF to Text/RTF
|
||||
PDFToText.header=PDF를 텍스트/RTF로 변환
|
||||
PDFToText.selectText.1=출력 파일 형식
|
||||
PDFToText.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.
|
||||
PDFToText.submit=변환
|
||||
|
||||
|
||||
PDFToHTML.title=PDF to HTML
|
||||
PDFToHTML.header=PDF를 HTML로 변환
|
||||
PDFToHTML.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.
|
||||
PDFToHTML.submit=변환
|
||||
|
||||
PDFToXML.title=PDF to XML
|
||||
PDFToXML.header=PDF를 XML로 변환
|
||||
PDFToXML.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.
|
||||
PDFToXML.submit=변환
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -12,14 +12,15 @@ genericSubmit=Wyślij
|
||||
processTimeWarning=Ostrzeżenie: Ten proces może potrwać do minuty, w zależności od rozmiaru pliku
|
||||
pageOrderPrompt=Kolejność stron (wprowadź listę numerów stron oddzielonych przecinkami) :
|
||||
goToPage=Idź
|
||||
true=Prawda
|
||||
false=Fałsz
|
||||
true=Tak
|
||||
false=Nie
|
||||
unknown=Nieznany
|
||||
save=Zapisz
|
||||
close=Zamknij
|
||||
filesSelected=wybrane pliki
|
||||
noFavourites=Nie dodano ulubionych
|
||||
bored=Znudzony czekaniem?
|
||||
alphabet=Alfabet
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
@@ -54,7 +55,7 @@ home.pdfOrganiser.title=Uporządkuj
|
||||
home.pdfOrganiser.desc=Usuń/Zmień kolejność stron w dowolnej kolejności
|
||||
|
||||
home.addImage.title=Dodaj obraz
|
||||
home.addImage.desc=Dodaje obraz w wybranym miejscu w dokumencie PDF (komponent w budowie)
|
||||
home.addImage.desc=Dodaje obraz w wybranym miejscu w dokumencie PDF (moduł w budowie)
|
||||
|
||||
home.watermark.title=Dodaj znak wodny
|
||||
home.watermark.desc=Dodaj niestandardowy znak wodny do dokumentu PDF.
|
||||
@@ -80,14 +81,14 @@ home.compressPdfs.desc=Kompresuj dokumenty PDF, aby zmniejszyć ich rozmiar.
|
||||
home.changeMetadata.title=Zmień metadane
|
||||
home.changeMetadata.desc=Zmień/Usuń/Dodaj metadane w dokumencie PDF
|
||||
|
||||
home.fileToPDF.title=Konwertuj plik do dokumentu PDF
|
||||
home.fileToPDF.desc=Konwertuj prawie każdy plik do dokumentu PDF (DOCX, PNG, XLS, PPT, TXT i więcej)
|
||||
home.fileToPDF.title=Konwertuj plik do PDF
|
||||
home.fileToPDF.desc=Konwertuj dowolny plik do dokumentu PDF (DOCX, PNG, XLS, PPT, TXT i więcej)
|
||||
|
||||
home.ocr.title=OCR / Zamiana na tekst
|
||||
home.ocr.desc=OCR skanuje i wykrywa tekst z obrazów w dokumencie PDF i zamienia go na tekst.
|
||||
|
||||
home.extractImages.title=Wyodrębnij obrazy
|
||||
home.extractImages.desc=Wyodrębnia wszystkie obrazy z dokumentu PDF i zapisuje je w formacie zip
|
||||
home.extractImages.desc=Wyodrębnia wszystkie obrazy z dokumentu PDF i zapisuje je w wybranym formacie
|
||||
|
||||
home.pdfToPDFA.title=PDF na PDF/A
|
||||
home.pdfToPDFA.desc=Konwertuj dokument PDF na PDF/A w celu długoterminowego przechowywania
|
||||
@@ -123,7 +124,18 @@ home.removeBlanks.title=Usuń puste strony
|
||||
home.removeBlanks.desc=Wykrywa i usuwa puste strony z dokumentu PDF
|
||||
|
||||
home.compare.title=Porównaj
|
||||
home.compare.desc=Porównuje i pokazuje różnice między 2 dokumentami PDF
|
||||
home.compare.desc=Porównuje i pokazuje różnice między dwoma dokumentami PDF
|
||||
|
||||
home.certSign.title=Podpisz certyfikatem
|
||||
home.certSign.desc=Podpisz dokument PDF za pomocą certyfikatu/klucza prywatnego (PEM/P12)
|
||||
|
||||
home.pageLayout.title=Układ wielu stron
|
||||
home.pageLayout.desc=Scal wiele stron dokumentu PDF w jedną stronę
|
||||
|
||||
home.scalePages.title=Dopasuj rozmiar stron
|
||||
home.scalePages.desc=Dopasuj rozmiar stron wybranego dokumentu PDF
|
||||
|
||||
error.pdfPassword=Dokument PDF jest zabezpieczony hasłem, musisz podać prawidłowe hasło.
|
||||
|
||||
downloadPdf=Pobierz PDF
|
||||
text=Tekst
|
||||
@@ -131,16 +143,27 @@ font=Czcionka
|
||||
selectFillter=-- Wybierz --
|
||||
pageNum=Numer strony
|
||||
|
||||
certSign.title=Podpisywanie certyfikatu
|
||||
certSign.header=Podpisz plik PDF swoim certyfikatem (prace w toku)
|
||||
certSign.selectPDF=Wybierz plik PDF do podpisania:
|
||||
pageLayout.title=Układ wielu stron
|
||||
pageLayout.header=Układ wielu stron
|
||||
pageLayout.pagesPerSheet=Stron na jednym arkuszu:
|
||||
pageLayout.submit=Wykonaj
|
||||
|
||||
scalePages.title=Dopasuj rozmiar stron
|
||||
scalePages.header=Dopasuj rozmiar stron
|
||||
scalePages.pageSize=Rozmiar stron dokumentu:
|
||||
scalePages.scaleFactor=Poziom powiększenia (przycięcia) stron:
|
||||
scalePages.submit=Wykonaj
|
||||
|
||||
certSign.title=Podpisywanie certyfikatem
|
||||
certSign.header=Podpisz dokument PDF certyfikatem prywatnym (moduł w budowie)
|
||||
certSign.selectPDF=Wybierz dokument PDF do podpisania:
|
||||
certSign.selectKey=Wybierz plik klucza prywatnego (format PKCS#8, może to być .pem lub .der):
|
||||
certSign.selectCert=Wybierz plik certyfikatu (format X.509, może to być .pem lub .der):
|
||||
certSign.selectP12=Wybierz plik magazynu kluczy PKCS#12 (.p12 lub .pfx) (opcjonalnie, jeśli jest podany, powinien zawierać klucz prywatny i certyfikat):
|
||||
certSign.certType=Typ certyfikatu
|
||||
certSign.password=Wprowadź hasło do magazynu kluczy lub klucza prywatnego (jeśli istnieje):
|
||||
certSign.showSig=Pokaż podpis
|
||||
certSign.reason=Powód
|
||||
certSign.showSig=Wyświetl podpis
|
||||
certSign.reason=Organizacja
|
||||
certSign.location=Lokalizacja
|
||||
certSign.name=Nazwa
|
||||
certSign.submit=Podpisz PDF
|
||||
@@ -223,13 +246,13 @@ ocr.submit=Przetwarzaj PDF za pomocą OCR
|
||||
|
||||
extractImages.title=Wyodrębnij obrazy
|
||||
extractImages.header=Wyodrębnij obrazy
|
||||
extractImages.selectText=Wybierz format obrazu, aby je przekonwertować
|
||||
extractImages.selectText=Wybierz format obrazu, na który chcesz przekonwertować wyodrębniony obraz.
|
||||
extractImages.submit=Wyodrębnij
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=Plik na PDF
|
||||
fileToPDF.header=Konwertuj kady plik na dokument PDF
|
||||
fileToPDF.header=Konwertuj dowolny plik na dokument PDF
|
||||
fileToPDF.credit=Ta usługa używa LibreOffice i Unoconv do konwersji plików.
|
||||
fileToPDF.supportedFileTypes=Obsługiwane typy plików powinny być zgodne z poniższymi, jednak pełną zaktualizowaną listę obsługiwanych formatów można znaleźć w dokumentacji LibreOffice
|
||||
fileToPDF.submit=Konwertuj na PDF
|
||||
@@ -250,6 +273,7 @@ compress.submit=Kompresuj
|
||||
addImage.title=Dodaj obraz
|
||||
addImage.header=Dodaj obraz do PDF
|
||||
addImage.everyPage=Każda strona?
|
||||
addImage.upload=Dodaj obraz
|
||||
addImage.submit=Dodaj obraz
|
||||
|
||||
|
||||
@@ -337,6 +361,9 @@ addPassword.selectText.10=Zablokuj modyfikacje
|
||||
addPassword.selectText.11=Zablokuj modyfikacje adnotacji
|
||||
addPassword.selectText.12=Zablokuj drukowanie
|
||||
addPassword.selectText.13=Zablokuj drukowanie różnych formatów
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=Zablokuj
|
||||
|
||||
#watermark
|
||||
@@ -346,8 +373,8 @@ watermark.selectText.1=Wybierz dokument PDF, do którego chcesz dodać znak wodn
|
||||
watermark.selectText.2=Treść znaku wodnego:
|
||||
watermark.selectText.3=Rozmiar czcionki:
|
||||
watermark.selectText.4=Obrót (0-360):
|
||||
watermark.selectText.5=odstępy poziomo (odstęp między każdym znakiem wodnym w poziomie):
|
||||
watermark.selectText.6=odstępy pionowo (odstęp między każdym znakiem wodnym w pionie):
|
||||
watermark.selectText.5=Odstęp w poziomie (odstęp między każdym znakiem wodnym w poziomie):
|
||||
watermark.selectText.6=Odstęp w pionie (odstęp między każdym znakiem wodnym w pionie):
|
||||
watermark.selectText.7=Nieprzezroczystość (0% - 100%):
|
||||
watermark.submit=Dodaj znak wodny
|
||||
|
||||
@@ -387,14 +414,14 @@ changeMetadata.selectText.1=Edytuj zmienne, które chcesz zmienić
|
||||
changeMetadata.selectText.2=Usuń wszystkie metadane
|
||||
changeMetadata.selectText.3=Pokaż niestandardowe metadane:
|
||||
changeMetadata.author=Autor:
|
||||
changeMetadata.creationDate=Data utworzenia (dd/MM/yyyy HH:mm:ss):
|
||||
changeMetadata.creationDate=Data utworzenia (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.creator=Twórca:
|
||||
changeMetadata.keywords=Słowa kluczowe:
|
||||
changeMetadata.modDate=Data modyfikacji (dd/MM/yyyy HH:mm:ss):
|
||||
changeMetadata.modDate=Data modyfikacji (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Producent:
|
||||
changeMetadata.subject=Temat:
|
||||
changeMetadata.title=Tytuł:
|
||||
changeMetadata.trapped=Uwięziony:
|
||||
changeMetadata.trapped=Zablokowany:
|
||||
changeMetadata.selectText.4=Inne metadane:
|
||||
changeMetadata.selectText.5=Dodaj niestandardowy wpis w metadanych
|
||||
changeMetadata.submit=Zmień
|
||||
|
||||
488
src/main/resources/messages_pt_BR.properties
Normal file
488
src/main/resources/messages_pt_BR.properties
Normal file
@@ -0,0 +1,488 @@
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr =esquerda para a direita, rtl = direita para a esquerda)
|
||||
language.direction=ltr
|
||||
|
||||
pdfPrompt=Selecione PDF(s)
|
||||
multiPdfPrompt=Selecione PDFs (2+)
|
||||
multiPdfDropPrompt=Selecione (ou arraste e solte) todos os PDFs necessários
|
||||
imgPrompt=Selecione a(s) imagem(ns)
|
||||
genericSubmit=Enviar
|
||||
processTimeWarning=Aviso: esse processo pode levar até um minuto, dependendo do tamanho do arquivo
|
||||
pageOrderPrompt=Ordem das páginas (digite uma lista separada por vírgulas de números de página):
|
||||
goToPage=Ir
|
||||
true=Verdadeiro
|
||||
false=Falso
|
||||
unknown=Desconhecido
|
||||
save=Salvar
|
||||
close=Fechar
|
||||
filesSelected=arquivos selecionados
|
||||
noFavourites=Nenhum favorito adicionado
|
||||
bored=Entediado esperando?
|
||||
alphabet=Alfabeto
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=Seu melhor utilitário para as necessidades de PDF.
|
||||
|
||||
|
||||
navbar.convert=Converter
|
||||
navbar.security=Segurança
|
||||
navbar.other=Outro
|
||||
navbar.darkmode=Modo Escuro
|
||||
navbar.pageOps=Operações de página
|
||||
|
||||
home.multiTool.title=Multiferramenta de PDF
|
||||
home.multiTool.desc=Mesclar, girar, reorganizar e remover páginas
|
||||
|
||||
home.merge.title=mesclar
|
||||
home.merge.desc=Mescle facilmente vários PDFs em um.
|
||||
|
||||
home.split.title=Dividir
|
||||
home.split.desc=Dividir PDFs em vários documentos
|
||||
|
||||
home.rotate.title=Girar
|
||||
home.rotate.desc=Gire facilmente seus PDFs.
|
||||
|
||||
home.imageToPdf.title=Imagem para PDF
|
||||
home.imageToPdf.desc=Converta uma imagem (PNG, JPEG, GIF) em PDF.
|
||||
|
||||
home.pdfToImage.title=PDF para imagem
|
||||
home.pdfToImage.desc=Converta um PDF em uma imagem. (PNG, JPG, GIF)
|
||||
|
||||
home.pdfOrganiser.title=Organizar
|
||||
home.pdfOrganiser.desc=Remova/reorganize as páginas em qualquer ordem
|
||||
|
||||
home.addImage.title=Adicionar imagem
|
||||
home.addImage.desc=Adiciona uma imagem em um local definido no PDF (trabalho em andamento)
|
||||
|
||||
home.watermark.title=Adicione uma Marca d'água
|
||||
home.watermark.desc=Adicione uma marca d'água personalizada ao seu documento PDF.
|
||||
|
||||
home.remove-watermark.title=Remover marca d'água
|
||||
home.remove-watermark.desc=Remova marcas d'água do seu documento PDF.
|
||||
|
||||
home.permissions.title=Alterar permissões
|
||||
home.permissions.desc=Altere as permissões do seu documento PDF
|
||||
|
||||
home.removePages.title=Remover
|
||||
home.removePages.desc=Exclua as páginas indesejadas do seu documento PDF.
|
||||
|
||||
home.addPassword.title=Adicionar senha
|
||||
home.addPassword.desc=Criptografe seu documento PDF com uma senha.
|
||||
|
||||
home.removePassword.title=Remover senha
|
||||
home.removePassword.desc=Remova a proteção por senha do seu documento PDF.
|
||||
|
||||
home.compressPdfs.title=Comprimir
|
||||
home.compressPdfs.desc=Comprima PDFs para reduzir o tamanho do arquivo.
|
||||
|
||||
home.changeMetadata.title=Alterar metadados
|
||||
home.changeMetadata.desc=Alterar/remover/adicionar metadados de um documento PDF
|
||||
|
||||
home.fileToPDF.title=Converter arquivo para PDF
|
||||
home.fileToPDF.desc=Converta praticamente qualquer arquivo em PDF (DOCX, PNG, XLS, PPT, TXT e mais)
|
||||
|
||||
home.ocr.title=OCR / Varreduras de limpeza
|
||||
home.ocr.desc=A limpeza verifica e detecta texto de imagens em um PDF e o adiciona novamente como texto.
|
||||
|
||||
home.extractImages.title=Extrair imagens
|
||||
home.extractImages.desc=Extrai todas as imagens de um PDF e as salva em zip
|
||||
|
||||
home.pdfToPDFA.title=PDF para PDF/A
|
||||
home.pdfToPDFA.desc=Converta PDF para PDF/A para armazenamento de longo prazo
|
||||
|
||||
home.PDFToWord.title=PDF para Word
|
||||
home.PDFToWord.desc=Converter PDF para formatos Word (DOC, DOCX e ODT)
|
||||
|
||||
home.PDFToPresentation.title=PDF para apresentação
|
||||
home.PDFToPresentation.desc=Converter PDF para formatos de apresentação (PPT, PPTX e ODP)
|
||||
|
||||
home.PDFToText.title=PDF para Texto/RTF
|
||||
home.PDFToText.desc=Converter PDF em formato de texto ou RTF
|
||||
|
||||
home.PDFToHTML.title=PDF para HTML
|
||||
home.PDFToHTML.desc=Converter PDF para o formato HTML
|
||||
|
||||
home.PDFToXML.title=PDF para XML
|
||||
home.PDFToXML.desc=Converter PDF para o formato XML
|
||||
|
||||
home.ScannerImageSplit.title=Detectar/dividir fotos digitalizadas
|
||||
home.ScannerImageSplit.desc=Divide várias fotos de dentro de uma foto/PDF
|
||||
|
||||
home.sign.title=Sinal
|
||||
home.sign.desc=Adiciona assinatura ao PDF por desenho, texto ou imagem
|
||||
|
||||
home.flatten.title=achatar
|
||||
home.flatten.desc=Remova todos os elementos e formulários interativos de um PDF
|
||||
|
||||
home.repair.title=Reparar
|
||||
home.repair.desc=Tenta reparar um PDF corrompido/quebrado
|
||||
|
||||
home.removeBlanks.title=Remover páginas em branco
|
||||
home.removeBlanks.desc=Detecta e remove páginas em branco de um documento
|
||||
|
||||
home.compare.title=Comparar
|
||||
home.compare.desc=Compara e mostra as diferenças entre 2 documentos PDF
|
||||
|
||||
home.certSign.title=Assinar com certificado
|
||||
home.certSign.desc=Assina um PDF com um Certificado/Chave (PEM/P12)
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf=baixar PDF
|
||||
text=Texto
|
||||
font=Fonte
|
||||
selectFillter=-- Selecione --
|
||||
pageNum=Número de página
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title=Assinatura de certificado
|
||||
certSign.header=Assine um PDF com seu certificado (Trabalho em andamento)
|
||||
certSign.selectPDF=Selecione um arquivo PDF para assinatura:
|
||||
certSign.selectKey=Selecione seu arquivo de chave privada (formato PKCS#8, pode ser .pem ou .der):
|
||||
certSign.selectCert=Selecione seu arquivo de certificado (formato X.509, pode ser .pem ou .der):
|
||||
certSign.selectP12=Selecione seu arquivo de armazenamento de chave PKCS#12 (.p12 ou .pfx) (opcional, se fornecido, deve conter sua chave privada e certificado):
|
||||
certSign.certType=tipo de certificado
|
||||
certSign.password=Digite seu armazenamento de chave ou senha de chave privada (se houver):
|
||||
certSign.showSig=Mostrar assinatura
|
||||
certSign.reason=Razão
|
||||
certSign.location=Localização
|
||||
certSign.name=Nome
|
||||
|
||||
certSign.submit=Assinar PDF
|
||||
|
||||
|
||||
|
||||
removeBlanks.title=Remover espaços em branco
|
||||
removeBlanks.header=Remover páginas em branco
|
||||
removeBlanks.threshold=Limite:
|
||||
removeBlanks.thresholdDesc=Limiar para determinar quão branco um pixel branco deve ser
|
||||
removeBlanks.whitePercent=Porcentagem branca (%):
|
||||
removeBlanks.whitePercentDesc=Porcentagem da página que deve ser branca para ser removida
|
||||
removeBlanks.submit=Remover espaços em branco
|
||||
|
||||
compare.title=Comparar
|
||||
compare.header=Comparar PDFs
|
||||
compare.document.1=Documento 1
|
||||
compare.document.2=Documento 2
|
||||
compare.submit=Comparar
|
||||
|
||||
sign.title=Sinal
|
||||
sign.header=Assinar PDFs
|
||||
sign.upload=Enviar Imagem
|
||||
sign.draw=Desenhar Assinatura
|
||||
sign.text=Entrada de texto
|
||||
sign.clear=Claro
|
||||
sign.add=Adicionar
|
||||
|
||||
repair.title=Reparar
|
||||
repair.header=Reparar PDFs
|
||||
repair.submit=Reparar
|
||||
|
||||
flatten.title=achatar
|
||||
flatten.header=Achatar PDFs
|
||||
flatten.submit=achatar
|
||||
|
||||
ScannerImageSplit.selectText.1=Limite de Ângulo:
|
||||
ScannerImageSplit.selectText.2=Define o ângulo absoluto mínimo necessário para que a imagem seja girada (padrão: 10).
|
||||
ScannerImageSplit.selectText.3=Tolerância:
|
||||
ScannerImageSplit.selectText.4=Determina o intervalo de variação de cor em torno da cor de fundo estimada (padrão: 30).
|
||||
ScannerImageSplit.selectText.5=Área Mínima:
|
||||
ScannerImageSplit.selectText.6=Define o limite mínimo de área para uma foto (padrão: 10000).
|
||||
ScannerImageSplit.selectText.7=Área mínima de contorno:
|
||||
ScannerImageSplit.selectText.8=Define o limite mínimo da área de contorno para uma foto
|
||||
ScannerImageSplit.selectText.9=Tamanho da Borda:
|
||||
ScannerImageSplit.selectText.10=Define o tamanho da borda adicionada e removida para evitar bordas brancas na saída (padrão: 1).
|
||||
|
||||
navbar.settings=Configurações
|
||||
settings.title=Configurações
|
||||
settings.update=Atualização disponível
|
||||
settings.appVersion=Versão do aplicativo:
|
||||
settings.downloadOption.title=Escolha a opção de download (para downloads não compactados de arquivo único):
|
||||
settings.downloadOption.1=Abrir na mesma janela
|
||||
settings.downloadOption.2=Abrir em nova janela
|
||||
settings.downloadOption.3=⇬ Fazer download do arquivo
|
||||
settings.zipThreshold=Compactar arquivos quando o número de arquivos baixados exceder
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#OCR
|
||||
ocr.title=OCR / Limpeza de digitalização
|
||||
ocr.header=Varreduras de limpeza / OCR (reconhecimento óptico de caracteres)
|
||||
ocr.selectText.1=Selecione os idiomas que devem ser detectados no PDF (os listados são os atualmente detectados):
|
||||
ocr.selectText.2=Produzir arquivo de texto contendo texto OCR ao lado do PDF com OCR
|
||||
ocr.selectText.3=As páginas corretas foram digitalizadas em um ângulo inclinado girando-as de volta ao lugar
|
||||
ocr.selectText.4=Limpe a página para que seja menos provável que o OCR encontre o texto no ruído de fundo. (Sem mudança de saída)
|
||||
ocr.selectText.5=Limpe a página para que seja menos provável que o OCR encontre texto no ruído de fundo, mantendo a limpeza na saída.
|
||||
ocr.selectText.6=Ignora as páginas que contêm texto interativo, apenas as páginas de OCR que são imagens
|
||||
ocr.selectText.7=Forçar OCR, irá OCR Todas as páginas removendo todos os elementos de texto originais
|
||||
ocr.selectText.8=Normal (será um erro se o PDF contiver texto)
|
||||
ocr.selectText.9=Configurações adicionais
|
||||
ocr.selectText.10=Modo OCR
|
||||
ocr.selectText.11=Remova as imagens após o OCR (remove TODAS as imagens, útil apenas se fizer parte da etapa de conversão)
|
||||
ocr.selectText.12=Tipo de renderização (avançado)
|
||||
ocr.help=Por favor, leia esta documentação sobre como usar isso para outros idiomas e/ou não usar no docker
|
||||
ocr.credit=Este serviço usa OCRmyPDF e Tesseract para OCR.
|
||||
ocr.submit=Processar PDF com OCR
|
||||
|
||||
|
||||
|
||||
extractImages.title=Extrair Imagens
|
||||
extractImages.header=Extrair Imagens
|
||||
extractImages.selectText=Selecione o formato de imagem para converter as imagens extraídas em
|
||||
extractImages.submit=Extrair
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=Arquivo para PDF
|
||||
fileToPDF.header=Converta qualquer arquivo para PDF
|
||||
fileToPDF.credit=Este serviço usa LibreOffice e Unoconv para conversão de arquivos.
|
||||
fileToPDF.supportedFileTypes=Os tipos de arquivo suportados devem incluir o abaixo, no entanto, para obter uma lista atualizada completa de formatos suportados, consulte a documentação do LibreOffice
|
||||
fileToPDF.submit=Converter para PDF
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=Comprimir
|
||||
compress.header=Comprimir PDF
|
||||
compress.credit=Este serviço usa o Ghostscript para compressão/otimização de PDF.
|
||||
compress.selectText.1=Modo Manual - De 1 a 4
|
||||
compress.selectText.2=Nível de otimização:
|
||||
compress.selectText.3=4 (Péssimo para imagens de texto)
|
||||
compress.selectText.4=Modo automático - Auto ajusta a qualidade para obter o tamanho exato do PDF
|
||||
compress.selectText.5=Tamanho esperado do PDF (por exemplo, 25 MB, 10,8 MB, 25 KB)
|
||||
compress.submit=Comprimir
|
||||
|
||||
|
||||
#Add image
|
||||
addImage.title=Adicionar imagem
|
||||
addImage.header=Adicionar imagem ao PDF
|
||||
addImage.everyPage=Cada página?
|
||||
addImage.upload=Adicionar imagem
|
||||
addImage.submit=Adicionar imagem
|
||||
|
||||
|
||||
#merge
|
||||
merge.title=mesclar
|
||||
merge.header=Mesclar vários PDFs (2+)
|
||||
merge.submit=mesclar
|
||||
|
||||
#pdfOrganiser
|
||||
pdfOrganiser.title=Organizador de página
|
||||
pdfOrganiser.header=Organizador de páginas PDF
|
||||
pdfOrganiser.submit=Reorganizar páginas
|
||||
|
||||
#multiTool
|
||||
multiTool.title=Multiferramenta de PDF
|
||||
multiTool.header=Multiferramenta de PDF
|
||||
|
||||
|
||||
#pageRemover
|
||||
pageRemover.title=Removedor de página
|
||||
pageRemover.header=Removedor de página PDF
|
||||
pageRemover.pagesToDelete=Páginas a serem excluídas (digite uma lista separada por vírgulas de números de página):
|
||||
pageRemover.submit=Excluir páginas
|
||||
|
||||
#rotate
|
||||
rotate.title=Girar PDF
|
||||
rotate.header=Girar PDF
|
||||
rotate.selectAngle=Selecione o ângulo de rotação (em múltiplos de 90 graus):
|
||||
rotate.submit=Girar
|
||||
|
||||
|
||||
|
||||
|
||||
#merge
|
||||
split.title=PDF dividido
|
||||
split.header=PDF dividido
|
||||
split.desc.1=Os números que você selecionar são o número da página na qual você deseja fazer uma divisão
|
||||
split.desc.2=Assim, selecionar 1,3,7-8 dividiria um documento de 10 páginas em 6 PDFS separados com:
|
||||
split.desc.3=Documento nº 1: página 1
|
||||
split.desc.4=Documento nº 2: páginas 2 e 3
|
||||
split.desc.5=Documento nº 3: Página 4, 5 e 6
|
||||
split.desc.6=Documento nº 4: página 7
|
||||
split.desc.7=Documento nº 5: página 8
|
||||
split.desc.8=Documento nº 6: páginas 9 e 10
|
||||
split.splitPages=Digite as páginas para dividir:
|
||||
split.submit=Dividir
|
||||
|
||||
|
||||
#merge
|
||||
imageToPDF.title=Imagem para PDF
|
||||
imageToPDF.header=Imagem para PDF
|
||||
imageToPDF.submit=Converter
|
||||
imageToPDF.selectText.1=Esticar para caber
|
||||
imageToPDF.selectText.2=Girar PDF automaticamente
|
||||
imageToPDF.selectText.3=Lógica de vários arquivos (Ativado apenas se estiver trabalhando com várias imagens)
|
||||
imageToPDF.selectText.4=Mesclar em um único PDF
|
||||
imageToPDF.selectText.5=Converter em PDFs separados
|
||||
|
||||
#pdfToImage
|
||||
pdfToImage.title=PDF para imagem
|
||||
pdfToImage.header=PDF para imagem
|
||||
pdfToImage.selectText=Formato de imagem
|
||||
pdfToImage.singleOrMultiple=Tipo de resultado de imagem
|
||||
pdfToImage.single=Imagem grande única
|
||||
pdfToImage.multi=Imagens múltiplas
|
||||
pdfToImage.colorType=tipo de cor
|
||||
pdfToImage.color=Cor
|
||||
pdfToImage.grey=Escala de cinza
|
||||
pdfToImage.blackwhite=Preto e branco (pode perder dados!)
|
||||
pdfToImage.submit=Converter
|
||||
|
||||
#addPassword
|
||||
addPassword.title=Adicionar senha
|
||||
addPassword.header=Adicionar senha (Criptografar)
|
||||
addPassword.selectText.1=Selecione PDF para criptografar
|
||||
addPassword.selectText.2=Senha
|
||||
addPassword.selectText.3=Comprimento da chave de criptografia
|
||||
addPassword.selectText.4=Valores mais altos são mais fortes, mas valores mais baixos têm melhor compatibilidade.
|
||||
addPassword.selectText.5=Permissões para definir
|
||||
addPassword.selectText.6=Impedir a montagem do documento
|
||||
addPassword.selectText.7=Impedir a extração de conteúdo
|
||||
addPassword.selectText.8=Impedir a extração para acessibilidade
|
||||
addPassword.selectText.9=Impedir o preenchimento do formulário
|
||||
addPassword.selectText.10=Impedir modificação
|
||||
addPassword.selectText.11=Impedir a modificação da anotação
|
||||
addPassword.selectText.12=Impedir a impressão
|
||||
addPassword.selectText.13=Impedir a impressão de formatos diferentes
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=criptografar
|
||||
|
||||
#watermark
|
||||
watermark.title=Adicione uma Marca d'água
|
||||
watermark.header=Adicione uma Marca d'água
|
||||
watermark.selectText.1=Selecione PDF para adicionar marca d'água a:
|
||||
watermark.selectText.2=Texto da marca d'água:
|
||||
watermark.selectText.3=Tamanho da fonte:
|
||||
watermark.selectText.4=Rotação (0-360):
|
||||
watermark.selectText.5=widthSpacer (espaço entre cada marca d'água horizontalmente):
|
||||
watermark.selectText.6=heightSpacer (espaço entre cada marca d'água verticalmente):
|
||||
watermark.selectText.7=Opacidade (0% - 100%):
|
||||
watermark.submit=Adicione uma Marca d'água
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=Remover marca d'água
|
||||
remove-watermark.header=Remover marca d'água
|
||||
remove-watermark.selectText.1=Selecione PDF para remover a marca d'água de:
|
||||
remove-watermark.selectText.2=Texto da marca d'água:
|
||||
remove-watermark.submit=Remover marca d'água
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Alterar permissões
|
||||
permissions.header=Alterar permissões
|
||||
permissions.warning=Aviso para que essas permissões sejam inalteráveis, é recomendável defini-las com uma senha por meio da página adicionar senha
|
||||
permissions.selectText.1=Selecione o PDF para alterar as permissões
|
||||
permissions.selectText.2=Permissões para definir
|
||||
permissions.selectText.3=Impedir a montagem do documento
|
||||
permissions.selectText.4=Impedir a extração de conteúdo
|
||||
permissions.selectText.5=Impedir extração para acessibilidade
|
||||
permissions.selectText.6=Impedir o preenchimento do formulário
|
||||
permissions.selectText.7=Impedir modificações
|
||||
permissions.selectText.8=Impedir a modificação da anotação
|
||||
permissions.selectText.9=Impedir a impressão
|
||||
permissions.selectText.10=Impedir a impressão de formatos diferentes
|
||||
permissions.submit=Mudar
|
||||
|
||||
#remove password
|
||||
removePassword.title=Remover senha
|
||||
removePassword.header=Remover senha (Descriptografar)
|
||||
removePassword.selectText.1=Selecione PDF para descriptografar
|
||||
removePassword.selectText.2=Senha
|
||||
removePassword.submit=Remover
|
||||
|
||||
changeMetadata.title=Alterar metadados
|
||||
changeMetadata.header=Alterar metadados
|
||||
changeMetadata.selectText.1=Edite as variáveis que deseja alterar
|
||||
changeMetadata.selectText.2=Excluir todos os metadados
|
||||
changeMetadata.selectText.3=Mostrar metadados personalizados:
|
||||
changeMetadata.author=Autor:
|
||||
changeMetadata.creationDate=Data de Criação (aaaa/MM/dd HH:mm:ss):
|
||||
changeMetadata.creator=O Criador:
|
||||
changeMetadata.keywords=Palavras-chave:
|
||||
changeMetadata.modDate=Data de modificação (aaaa/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Produtor:
|
||||
changeMetadata.subject=Assunto:
|
||||
changeMetadata.title=Título:
|
||||
changeMetadata.trapped=Encurralado:
|
||||
changeMetadata.selectText.4=Outros metadados:
|
||||
changeMetadata.selectText.5=Adicionar entrada de metadados personalizados
|
||||
changeMetadata.submit=Mudar
|
||||
|
||||
xlsToPdf.title=Excel para PDF
|
||||
xlsToPdf.header=Excel para PDF
|
||||
xlsToPdf.selectText.1=Selecione planilha Excel XLS ou XLSX para converter
|
||||
xlsToPdf.convert=converter
|
||||
|
||||
|
||||
|
||||
|
||||
pdfToPDFA.title=PDF para PDF/A
|
||||
pdfToPDFA.header=PDF para PDF/A
|
||||
pdfToPDFA.credit=Este serviço usa OCRmyPDF para conversão de PDF/A
|
||||
pdfToPDFA.submit=Converter
|
||||
|
||||
|
||||
|
||||
PDFToWord.title=PDF para Word
|
||||
PDFToWord.header=PDF para Word
|
||||
PDFToWord.selectText.1=Formato do arquivo de saída
|
||||
PDFToWord.credit=Este serviço usa o LibreOffice para conversão de arquivos.
|
||||
PDFToWord.submit=Converter
|
||||
|
||||
PDFToPresentation.title=PDF para apresentação
|
||||
PDFToPresentation.header=PDF para apresentação
|
||||
PDFToPresentation.selectText.1=Formato do arquivo de saída
|
||||
PDFToPresentation.credit=Este serviço usa o LibreOffice para conversão de arquivos.
|
||||
PDFToPresentation.submit=Converter
|
||||
|
||||
|
||||
PDFToText.title=PDF para Texto/RTF
|
||||
PDFToText.header=PDF para Texto/RTF
|
||||
PDFToText.selectText.1=Formato do arquivo de saída
|
||||
PDFToText.credit=Este serviço usa o LibreOffice para conversão de arquivos.
|
||||
PDFToText.submit=Converter
|
||||
|
||||
|
||||
PDFToHTML.title=PDF para HTML
|
||||
PDFToHTML.header=PDF para HTML
|
||||
PDFToHTML.credit=Este serviço usa o LibreOffice para conversão de arquivos.
|
||||
PDFToHTML.submit=Converter
|
||||
|
||||
PDFToXML.title=PDF para XML
|
||||
PDFToXML.header=PDF para XML
|
||||
PDFToXML.credit=Este serviço usa o LibreOffice para conversão de arquivos.
|
||||
PDFToXML.submit=Converter
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
441
src/main/resources/messages_ro_RO.properties
Normal file
441
src/main/resources/messages_ro_RO.properties
Normal file
@@ -0,0 +1,441 @@
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||
language.direction=ltr
|
||||
|
||||
pdfPrompt=Selectează fișiere PDF
|
||||
multiPdfPrompt=Selectează mai multe fișiere PDF (2+)
|
||||
multiPdfDropPrompt=Selectează (sau trage și plasează) toate fișierele PDF de care ai nevoie
|
||||
imgPrompt=Selectează imagini
|
||||
genericSubmit=Trimite
|
||||
processTimeWarning=Avertisment: Acest proces poate dura până la un minut în funcție de dimensiunea fișierului
|
||||
pageOrderPrompt=Ordinea paginilor (Introdu o listă separată prin virgulă de numere de pagină):
|
||||
goToPage=Mergi la pagină
|
||||
true=Adevărat
|
||||
false=Fals
|
||||
unknown=Necunoscut
|
||||
save=Salvează
|
||||
close=Închide
|
||||
filesSelected=fișiere selectate
|
||||
noFavourites=Niciun favorit adăugat
|
||||
bored=Plictisit așteptând?
|
||||
alphabet=Alfabet
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=Un singur punct de oprire găzduit local pentru toate nevoile tale legate de fișiere PDF.
|
||||
|
||||
navbar.convert=Converteste
|
||||
navbar.security=Securitate
|
||||
navbar.other=Altele
|
||||
navbar.darkmode=Mod întunecat
|
||||
navbar.pageOps=Operații pe pagină
|
||||
|
||||
home.multiTool.title=Instrument multiplu PDF
|
||||
home.multiTool.desc=Unifică, rotește, rearanjează și elimină pagini
|
||||
|
||||
home.merge.title=Unifică
|
||||
home.merge.desc=Unifică cu ușurință mai multe fișiere PDF într-unul singur.
|
||||
|
||||
home.split.title=Desparte
|
||||
home.split.desc=Desparte fișierele PDF în mai multe documente.
|
||||
|
||||
home.rotate.title=Rotește
|
||||
home.rotate.desc=Rotește cu ușurință fișierele PDF.
|
||||
|
||||
home.imageToPdf.title=Imagine în PDF
|
||||
home.imageToPdf.desc=Convertește o imagine (PNG, JPEG, GIF) în PDF.
|
||||
|
||||
home.pdfToImage.title=PDF în Imagine
|
||||
home.pdfToImage.desc=Convertește un fișier PDF în imagine (PNG, JPEG, GIF).
|
||||
|
||||
home.pdfOrganiser.title=Organizează
|
||||
home.pdfOrganiser.desc=Elimină/rearanjează pagini în orice ordine
|
||||
|
||||
home.addImage.title=Adaugă imagine
|
||||
home.addImage.desc=Adaugă o imagine într-o locație specifică pe PDF (în curs de dezvoltare)
|
||||
|
||||
home.watermark.title=Adaugă Filigran
|
||||
home.watermark.desc=Adaugă un filigran personalizat la documentul PDF.
|
||||
|
||||
home.remove-watermark.title=Elimină Filigran
|
||||
home.remove-watermark.desc=Elimină filigranele din documentul PDF.
|
||||
|
||||
home.permissions.title=Schimbă permisiuni
|
||||
home.permissions.desc=Schimbă permisiunile documentului PDF
|
||||
|
||||
home.removePages.title=Elimină
|
||||
home.removePages.desc=Șterge paginile nedorite din documentul PDF.
|
||||
|
||||
home.addPassword.title=Adaugă Parolă
|
||||
home.addPassword.desc=Criptează documentul PDF cu o parolă.
|
||||
home.removePassword.title=Elimină Parola
|
||||
home.removePassword.desc=Elimină protecția cu parolă din documentul PDF.
|
||||
home.compressPdfs.title=Comprimă
|
||||
home.compressPdfs.desc=Comprimă fișierele PDF pentru a reduce dimensiunea lor.
|
||||
home.changeMetadata.title=Schimbă Metadatele
|
||||
home.changeMetadata.desc=Schimbă/Elimină/Adaugă metadate într-un document PDF.
|
||||
home.fileToPDF.title=Convertește fișierul în PDF
|
||||
home.fileToPDF.desc=Convertește aproape orice fișier în format PDF (DOCX, PNG, XLS, PPT, TXT și altele).
|
||||
home.ocr.title=OCR / Curățare scanări
|
||||
home.ocr.desc=Curăță scanările și detectează textul din imaginile dintr-un PDF și îl adaugă ca text.
|
||||
home.extractImages.title=Extrage Imagini
|
||||
home.extractImages.desc=Extrage toate imaginile dintr-un PDF și le salvează într-un fișier zip.
|
||||
home.pdfToPDFA.title=PDF în PDF/A
|
||||
home.pdfToPDFA.desc=Convertește un document PDF în format PDF/A pentru stocare pe termen lung.
|
||||
home.PDFToWord.title=PDF în Word
|
||||
home.PDFToWord.desc=Convertește un document PDF în formate Word (DOC, DOCX și ODT).
|
||||
home.PDFToPresentation.title=PDF în Prezentare
|
||||
home.PDFToPresentation.desc=Convertește un document PDF în formate de prezentare (PPT, PPTX și ODP).
|
||||
home.PDFToText.title=PDF în Text/RTF
|
||||
home.PDFToText.desc=Convertește un document PDF în format Text sau RTF.
|
||||
home.PDFToHTML.title=PDF în HTML
|
||||
home.PDFToHTML.desc=Convertește un document PDF în format HTML.
|
||||
home.PDFToXML.title=PDF în XML
|
||||
home.PDFToXML.desc=Convertește un document PDF în format XML.
|
||||
home.ScannerImageSplit.title=Detectează/Împarte poze scanate
|
||||
home.ScannerImageSplit.desc=Împarte mai multe poze dintr-o poză/PDF.
|
||||
home.sign.title=Semnează
|
||||
home.sign.desc=Adaugă o semnătură la documentul PDF prin desenare, text sau imagine.
|
||||
home.flatten.title=Nivelare
|
||||
home.flatten.desc=Elimină toate elementele interactive și formularele dintr-un PDF.
|
||||
home.repair.title=Repară
|
||||
home.repair.desc=Încearcă să repare un document PDF corupt/defect.
|
||||
home.removeBlanks.title=Elimină pagini goale
|
||||
home.removeBlanks.desc=Detectează și elimină paginile goale dintr-un document.
|
||||
home.compare.title=Compară
|
||||
home.compare.desc=Compară și arată diferențele dintre 2 documente PDF.
|
||||
|
||||
home.certSign.title=Semnare cu certificat
|
||||
home.certSign.desc=Semnează un PDF cu un certificat/cheie (PEM/P12)
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf=Descarcă PDF
|
||||
text=Text
|
||||
font=Font
|
||||
selectFillter=-- Selectează --
|
||||
pageNum=Numărul paginii
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title = Semnare certificat
|
||||
certSign.header = Semnează un fișier PDF cu certificatul tău (În curs de desfășurare)
|
||||
certSign.selectPDF = Selectează un fișier PDF pentru semnare:
|
||||
certSign.selectKey = Selectează fișierul cheie privată (format PKCS#8, poate fi .pem sau .der):
|
||||
certSign.selectCert = Selectează fișierul de certificat (format X.509, poate fi .pem sau .der):
|
||||
certSign.selectP12 = Selectează fișierul de stocare cheie PKCS#12 (.p12 sau .pfx) (Opțional, dacă este furnizat, ar trebui să conțină cheia privată și certificatul tău):
|
||||
certSign.certType = Tipul certificatului
|
||||
certSign.password = Introdu parola pentru stocarea cheie sau cheia privată (dacă există):
|
||||
certSign.showSig = Afișează semnătura
|
||||
certSign.reason = Motivul
|
||||
certSign.location = Locația
|
||||
certSign.name = Numele
|
||||
|
||||
certSign.submit = Semnează PDF
|
||||
|
||||
removeBlanks.title=Elimină pagini goale
|
||||
removeBlanks.header=Elimină pagini goale
|
||||
removeBlanks.threshold=Prag:
|
||||
removeBlanks.thresholdDesc=Prag pentru determinarea cât de alb trebuie să fie un pixel alb
|
||||
removeBlanks.whitePercent=Procent alb (%):
|
||||
removeBlanks.whitePercentDesc=Procentul paginii care trebuie să fie alb pentru a fi eliminată
|
||||
removeBlanks.submit=Elimină pagini goale
|
||||
compare.title=Compară
|
||||
compare.header=Compară PDF-uri
|
||||
compare.document.1=Document 1
|
||||
compare.document.2=Document 2
|
||||
compare.submit=Compară
|
||||
|
||||
sign.title=Semnează
|
||||
sign.header=Semnează documente PDF
|
||||
sign.upload=Încarcă Imaginea
|
||||
sign.draw=Desenează Semnătura
|
||||
sign.text=Introdu Textul
|
||||
sign.clear=Curăță
|
||||
sign.add=Adaugă
|
||||
|
||||
repair.title=Repară
|
||||
repair.header=Repară documente PDF
|
||||
repair.submit=Repară
|
||||
|
||||
flatten.title=Nivelare
|
||||
flatten.header=Nivelează documente PDF
|
||||
flatten.submit=Nivelează
|
||||
|
||||
ScannerImageSplit.selectText.1=Prag unghi:
|
||||
ScannerImageSplit.selectText.2=Stabilește unghiul absolut minim necesar pentru ca imaginea să fie rotită (implicit: 5).
|
||||
ScannerImageSplit.selectText.3=Toleranță:
|
||||
ScannerImageSplit.selectText.4=Determină intervalul de variație a culorii în jurul culorii de fundal estimate (implicit: 20).
|
||||
ScannerImageSplit.selectText.5=Arie minimă:
|
||||
ScannerImageSplit.selectText.6=Stabilește pragul minim de arie pentru o fotografie (implicit: 8000).
|
||||
ScannerImageSplit.selectText.7=Arie minimă a conturului:
|
||||
ScannerImageSplit.selectText.8=Stabilește pragul minim de arie a conturului pentru o fotografie.
|
||||
ScannerImageSplit.selectText.9=Mărimea marginii:
|
||||
ScannerImageSplit.selectText.10=Stabilește mărimea marginii adăugate și eliminate pentru a evita marginile albe în rezultat (implicit: 1).
|
||||
|
||||
navbar.settings=Setări
|
||||
settings.title=Setări
|
||||
settings.update=Actualizare disponibilă
|
||||
settings.appVersion=Versiune aplicație:
|
||||
settings.downloadOption.title=Alege opțiunea de descărcare (pentru descărcarea unui singur fișier non-zip):
|
||||
settings.downloadOption.1=Deschide în aceeași fereastră
|
||||
settings.downloadOption.2=Deschide într-o fereastră nouă
|
||||
settings.downloadOption.3=Descarcă fișierul
|
||||
settings.zipThreshold=Împachetează fișierele când numărul de fișiere descărcate depășește
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#OCR
|
||||
ocr.title=OCR / Curățare scanare
|
||||
ocr.header=Curățare scanări / OCR (Recunoaștere optică a caracterelor)
|
||||
ocr.selectText.1=Selectați limbile care trebuie detectate în PDF (Cele listate sunt cele detectate în prezent):
|
||||
ocr.selectText.2=Produceți un fișier text care conține textul OCR împreună cu PDF-ul OCR
|
||||
ocr.selectText.3=Corectați paginile care au fost scanate în unghi înclinat prin rotirea lor în poziție corectă
|
||||
ocr.selectText.4=Curățați pagina astfel încât să fie mai puțin probabil ca OCR-ul să găsească text în zgomotul de fundal. (Nu se schimbă rezultatul)
|
||||
ocr.selectText.5=Curățați pagina astfel încât să fie mai puțin probabil ca OCR-ul să găsească text în zgomotul de fundal, menține curățarea în rezultat.
|
||||
ocr.selectText.6=Ignorați paginile care conțin text interactiv, OCR-ul se aplică doar paginilor care sunt imagini
|
||||
ocr.selectText.7=Forțează OCR-ul, va aplica OCR pe fiecare pagină, înlăturând toate elementele de text originale
|
||||
ocr.selectText.8=Normal (Va genera eroare dacă PDF-ul conține text)
|
||||
ocr.selectText.9=Setări suplimentare
|
||||
ocr.selectText.10=Mod OCR
|
||||
ocr.selectText.11=Elimină imaginile după OCR (Elimină TOATE imaginile, util doar în etapa de conversie)
|
||||
ocr.selectText.12=Tip de redare (Avansat)
|
||||
ocr.help=Citiți documentația pentru a afla cum să utilizați acest serviciu pentru alte limbi și/sau în afara mediului Docker
|
||||
ocr.credit=Acest serviciu utilizează OCRmyPDF și Tesseract pentru OCR.
|
||||
ocr.submit=Procesează PDF-ul cu OCR
|
||||
|
||||
extractImages.title=Extrage Imagini
|
||||
extractImages.header=Extrage Imagini
|
||||
extractImages.selectText=Selectați formatul imaginii în care să se convertească imaginile extrase
|
||||
extractImages.submit=Extrage
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=Fișier în PDF
|
||||
fileToPDF.header=Convertiți orice fișier în PDF
|
||||
fileToPDF.credit=Acest serviciu utilizează LibreOffice și Unoconv pentru conversia fișierelor.
|
||||
fileToPDF.supportedFileTypes=Tipurile de fișiere suportate ar trebui să includă cele de mai jos. Pentru o listă completă și actualizată a formatelor suportate, consultați documentația LibreOffice.
|
||||
fileToPDF.submit=Convertiți în PDF
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=Comprimare
|
||||
compress.header=Comprimare PDF
|
||||
compress.credit=Acest serviciu utilizează OCRmyPDF pentru comprimarea/optimalizarea PDF-urilor.
|
||||
compress.selectText.1=Nivel de optimizare:
|
||||
compress.selectText.2=0 (Fără optimizare)
|
||||
compress.selectText.3=1 (Implicit, optimizare fără pierdere)
|
||||
compress.selectText.4=2 (Optimizare cu pierdere)
|
||||
compress.selectText.5=3 (Optimizare cu pierdere, mai agresivă)
|
||||
compress.selectText.6=Activare vizualizare rapidă pe web (linearizare PDF)
|
||||
compress.selectText.7=Activare codificare JBIG2 cu pierdere
|
||||
compress.submit=Comprimare
|
||||
|
||||
#Add image
|
||||
addImage.title=Adăugare imagine
|
||||
addImage.header=Adăugare imagine în PDF
|
||||
addImage.everyPage=Pe fiecare pagină?
|
||||
addImage.upload=Adăugare imagine
|
||||
addImage.submit=Adăugare imagine
|
||||
|
||||
#merge
|
||||
merge.title=Unire
|
||||
merge.header=Unirea mai multor PDF-uri (2+)
|
||||
merge.submit=Unire
|
||||
|
||||
#pdfOrganiser
|
||||
pdfOrganiser.title=Organizator de pagini
|
||||
pdfOrganiser.header=Organizator de pagini PDF
|
||||
pdfOrganiser.submit=Rearanjați paginile
|
||||
|
||||
#multiTool
|
||||
multiTool.title=Instrument PDF multiplu
|
||||
multiTool.header=Instrument PDF multiplu
|
||||
|
||||
#pageRemover
|
||||
pageRemover.title=Înlăturare pagini
|
||||
pageRemover.header=Înlăturare pagini din PDF
|
||||
pageRemover.pagesToDelete=Pagini de șters (Introduceți o listă de numere de pagini separate prin virgulă):
|
||||
pageRemover.submit=Ștergere pagini
|
||||
|
||||
#rotate
|
||||
rotate.title=Rotește PDF
|
||||
rotate.header=Rotește PDF
|
||||
rotate.selectAngle=Selectați un unghi de rotație (în multiplicate de 90 de grade):
|
||||
rotate.submit=Rotește
|
||||
|
||||
#merge
|
||||
split.title=Împarte PDF
|
||||
split.header=Împarte PDF
|
||||
split.desc.1=Numerele pe care le selectați reprezintă numărul paginii pe care doriți să o împărțiți
|
||||
split.desc.2=Prin urmare, selectând 1,3,7-8, un document cu 10 pagini va fi împărțit în 6 PDF-uri separate, astfel:
|
||||
split.desc.3=Documentul #1: Pagina 1
|
||||
split.desc.4=Documentul #2: Paginile 2 și 3
|
||||
split.desc.5=Documentul #3: Paginile 4, 5 și 6
|
||||
split.desc.6=Documentul #4: Pagina 7
|
||||
split.desc.7=Documentul #5: Pagina 8
|
||||
split.desc.8=Documentul #6: Paginile 9 și 10
|
||||
split.splitPages=Introduceți paginile pe care să le împărțiți:
|
||||
split.submit=Împarte
|
||||
|
||||
|
||||
#merge
|
||||
imageToPDF.title=Imagine în PDF
|
||||
imageToPDF.header=Imagine în PDF
|
||||
imageToPDF.submit=Convertă
|
||||
imageToPDF.selectText.1=Redimensionare pentru a se potrivi
|
||||
imageToPDF.selectText.2=Rotire automată a PDF-ului
|
||||
imageToPDF.selectText.3=Logica pentru mai multe fișiere (activată numai dacă se lucrează cu mai multe imagini)
|
||||
imageToPDF.selectText.4=Unifică într-un singur PDF
|
||||
imageToPDF.selectText.5=Convertă în PDF-uri separate
|
||||
|
||||
#pdfToImage
|
||||
pdfToImage.title=PDF în Imagine
|
||||
pdfToImage.header=PDF în Imagine
|
||||
pdfToImage.selectText=Format imagine
|
||||
pdfToImage.singleOrMultiple=Tip rezultat imagine
|
||||
pdfToImage.single=O singură imagine mare
|
||||
pdfToImage.multi=Mai multe imagini
|
||||
pdfToImage.colorType=Tip culoare
|
||||
pdfToImage.color=Culoare
|
||||
pdfToImage.grey=Scală de gri
|
||||
pdfToImage.blackwhite=Alb și negru (Poate pierde date!)
|
||||
pdfToImage.submit=Convertă
|
||||
|
||||
#addPassword
|
||||
addPassword.title=Adăugați parolă
|
||||
addPassword.header=Adăugați o parolă (Criptare)
|
||||
addPassword.selectText.1=Selectați PDF-ul pentru criptare
|
||||
addPassword.selectText.2=Parolă
|
||||
addPassword.selectText.3=Lungime cheie de criptare
|
||||
addPassword.selectText.4=Valori mai mari sunt mai puternice, dar valorile mai mici au o compatibilitate mai bună.
|
||||
addPassword.selectText.5=Permisiuni de setare
|
||||
addPassword.selectText.6=Preveniți asamblarea documentului
|
||||
addPassword.selectText.7=Preveniți extragerea conținutului
|
||||
addPassword.selectText.8=Preveniți extragerea pentru accesibilitate
|
||||
addPassword.selectText.9=Preveniți completarea formularului
|
||||
addPassword.selectText.10=Preveniți modificarea
|
||||
addPassword.selectText.11=Preveniți modificarea adnotărilor
|
||||
addPassword.selectText.12=Preveniți tipărirea
|
||||
addPassword.selectText.13=Preveniți tipărirea în formate diferite
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=Criptare
|
||||
|
||||
#watermark
|
||||
watermark.title=Adăugați Filigran
|
||||
watermark.header=Adăugați Filigran
|
||||
watermark.selectText.1=Selectați PDF-ul la care să adăugați filigranul:
|
||||
watermark.selectText.2=Textul Filigranului:
|
||||
watermark.selectText.3=Mărimea fontului:
|
||||
watermark.selectText.4=Rotire (0-360):
|
||||
watermark.selectText.5=widthSpacer (Spațiu între fiecare filigran pe orizontală):
|
||||
watermark.selectText.6=heightSpacer (Spațiu între fiecare filigran pe verticală):
|
||||
watermark.selectText.7=Opacitate (0% - 100%):
|
||||
watermark.submit=Adăugați Filigran
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=Eliminați Filigran
|
||||
remove-watermark.header=Eliminați Filigran
|
||||
remove-watermark.selectText.1=Selectați PDF-ul de la care să eliminați filigranul:
|
||||
remove-watermark.selectText.2=Textul Filigranului:
|
||||
remove-watermark.submit=Eliminați Filigran
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Schimbați Permisiunile
|
||||
permissions.header=Schimbați Permisiunile
|
||||
permissions.warning=Pentru a face aceste permisiuni neschimbabile, se recomandă să le setați cu o parolă prin intermediul paginii de adăugare a parolei
|
||||
permissions.selectText.1=Selectați PDF-ul pentru a schimba permisiunile
|
||||
permissions.selectText.2=Permisiunile de setat
|
||||
permissions.selectText.3=Preveniți asamblarea documentului
|
||||
permissions.selectText.4=Preveniți extragerea conținutului
|
||||
permissions.selectText.5=Preveniți extragerea pentru accesibilitate
|
||||
permissions.selectText.6=Preveniți completarea formularului
|
||||
permissions.selectText.7=Preveniți modificarea
|
||||
permissions.selectText.8=Preveniți modificarea adnotărilor
|
||||
permissions.selectText.9=Preveniți tipărirea
|
||||
permissions.selectText.10=Preveniți tipărirea în formate diferite
|
||||
permissions.submit=Schimbare
|
||||
|
||||
#remove password
|
||||
removePassword.title=Eliminați parola
|
||||
removePassword.header=Eliminați parola (Decodificați)
|
||||
removePassword.selectText.1=Selectați PDF-ul pentru decodificare
|
||||
removePassword.selectText.2=Parolă
|
||||
removePassword.submit=Eliminați
|
||||
|
||||
changeMetadata.title=Schimbați Metadatele
|
||||
changeMetadata.header=Schimbați Metadatele
|
||||
changeMetadata.selectText.1=Vă rugăm să editați variabilele pe care doriți să le schimbați
|
||||
changeMetadata.selectText.2=Ștergeți toate metadatele
|
||||
changeMetadata.selectText.3=Afișați Metadatele Personalizate:
|
||||
changeMetadata.author=Autor:
|
||||
changeMetadata.creationDate=Data creării (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.creator=Creator:
|
||||
changeMetadata.keywords=Cuvinte cheie:
|
||||
changeMetadata.modDate=Data modificării (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Producător:
|
||||
changeMetadata.subject=Subiect:
|
||||
changeMetadata.title=Titlu:
|
||||
changeMetadata.trapped=Blocat:
|
||||
changeMetadata.selectText.4=Alte Metadate:
|
||||
changeMetadata.selectText.5=Adăugați Intrare Metadate Personalizate
|
||||
changeMetadata.submit=Schimbare
|
||||
|
||||
xlsToPdf.title=Excel to PDF
|
||||
xlsToPdf.header=Excel to PDF
|
||||
xlsToPdf.selectText.1=Selectați fișierul Excel XLS sau XLSX pentru a converti
|
||||
xlsToPdf.convert=convert
|
||||
|
||||
pdfToPDFA.title=PDF către PDF/A
|
||||
pdfToPDFA.header=PDF către PDF/A
|
||||
pdfToPDFA.credit=Acest serviciu utilizează OCRmyPDF pentru conversia în PDF/A
|
||||
pdfToPDFA.submit=Convert
|
||||
|
||||
PDFToWord.title=PDF către Word
|
||||
PDFToWord.header=PDF către Word
|
||||
PDFToWord.selectText.1=Format fișier de ieșire
|
||||
PDFToWord.credit=Acest serviciu utilizează LibreOffice pentru conversia fișierului.
|
||||
PDFToWord.submit=Convert
|
||||
|
||||
PDFToPresentation.title=PDF către Prezentare
|
||||
PDFToPresentation.header=PDF către Prezentare
|
||||
PDFToPresentation.selectText.1=Format fișier de ieșire
|
||||
PDFToPresentation.credit=Acest serviciu utilizează LibreOffice pentru conversia fișierului.
|
||||
PDFToPresentation.submit=Convert
|
||||
|
||||
PDFToText.title=PDF către Text/RTF
|
||||
PDFToText.header=PDF către Text/RTF
|
||||
PDFToText.selectText.1=Format fișier de ieșire
|
||||
PDFToText.credit=Acest serviciu utilizează LibreOffice pentru conversia fișierului.
|
||||
PDFToText.submit=Convert
|
||||
|
||||
PDFToHTML.title=PDF către HTML
|
||||
PDFToHTML.header=PDF către HTML
|
||||
PDFToHTML.credit=Acest serviciu utilizează LibreOffice pentru conversia fișierului.
|
||||
PDFToHTML.submit=Convert
|
||||
|
||||
PDFToXML.title=PDF către XML
|
||||
PDFToXML.header=PDF către XML
|
||||
PDFToXML.credit=Acest serviciu utilizează LibreOffice pentru conversia fișierului.
|
||||
PDFToXML.submit=Convert
|
||||
@@ -20,6 +20,7 @@ close=Закрыть
|
||||
filesSelected=файлов выбрано
|
||||
noFavourites=Нет избранного
|
||||
bored=Скучно ждать?
|
||||
alphabet=\u0430\u043B\u0444\u0430\u0432\u0438\u0442
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
@@ -125,12 +126,34 @@ home.removeBlanks.desc=Обнаруживает и удаляет пустые
|
||||
home.compare.title=Сравнение
|
||||
home.compare.desc=Сравнивает и показывает различия между двумя PDF-документами
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf=Скачать PDF
|
||||
text=Текст
|
||||
font=Шрифт
|
||||
selectFillter=-- Выбрать --
|
||||
pageNum=номер страницы
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title=Подписание сертификата
|
||||
certSign.header=Подпишите PDF своим сертификатом (работа в процессе)
|
||||
certSign.selectPDF=Выберите файл PDF для подписи:
|
||||
@@ -251,6 +274,7 @@ compress.submit=Сжать
|
||||
addImage.title=Добавить изображение
|
||||
addImage.header=Добавить изображение в PDF
|
||||
addImage.everyPage=Каждая страница?
|
||||
addImage.upload=Добавить изображение
|
||||
addImage.submit=Добавить изображение
|
||||
|
||||
|
||||
@@ -338,6 +362,9 @@ addPassword.selectText.10=Предотвратить модификацию
|
||||
addPassword.selectText.11=Запретить модификацию аннотаций
|
||||
addPassword.selectText.12=Запретить печать
|
||||
addPassword.selectText.13=Запретить печать разных форматов
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=Шифровать
|
||||
|
||||
#watermark
|
||||
|
||||
@@ -20,6 +20,7 @@ close=Stäng
|
||||
filesSelected=filer valda
|
||||
noFavourites=Inga favoriter har lagts till
|
||||
bored=Utråkad att vänta?
|
||||
alphabet=Alfabet
|
||||
#############
|
||||
# HEMSIDA #
|
||||
#############
|
||||
@@ -125,12 +126,34 @@ home.removeBlanks.desc=Känner av och tar bort tomma sidor från ett dokument
|
||||
home.compare.title=Jämför
|
||||
home.compare.desc=Jämför och visar skillnaderna mellan 2 PDF-dokument
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf=Ladda ner PDF
|
||||
text=Text
|
||||
font=Teckensnitt
|
||||
selectFillter=-- Välj --
|
||||
pageNum=Sidnummer
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title=Certifikatsignering
|
||||
certSign.header=Skriv under en PDF med ditt certifikat (Pågående arbete)
|
||||
certSign.selectPDF=Välj en PDF-fil för signering:
|
||||
@@ -251,6 +274,7 @@ compress.submit=Komprimera
|
||||
addImage.title=Lägg till bild
|
||||
addImage.header=Lägg till bild till PDF
|
||||
addImage.everyPage=Varje sida?
|
||||
addImage.upload=Lägg till bild
|
||||
addImage.submit=Lägg till bild
|
||||
|
||||
|
||||
@@ -338,6 +362,9 @@ addPassword.selectText.10=Förhindra modifiering
|
||||
addPassword.selectText.11=Förhindra anteckningsändring
|
||||
addPassword.selectText.12=Förhindra utskrift
|
||||
addPassword.selectText.13=Förhindra utskrift av olika format
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=Kryptera
|
||||
|
||||
#vattenstämpel
|
||||
|
||||
@@ -20,6 +20,7 @@ close=关闭
|
||||
filesSelected=\u9009\u62E9\u7684\u6587\u4EF6
|
||||
noFavourites=\u6CA1\u6709\u6DFB\u52A0\u6536\u85CF\u5939
|
||||
bored=\u65E0\u804A\u7B49\u5F85\uFF1F
|
||||
alphabet=\u5B57\u6BCD\u8868
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
@@ -125,12 +126,34 @@ home.removeBlanks.desc=\u68C0\u6D4B\u5E76\u5220\u9664\u6587\u6863\u4E2D\u7684\u7
|
||||
home.compare.title=\u6BD4\u8F83
|
||||
home.compare.desc=\u6BD4\u8F83\u5E76\u663E\u793A 2 \u4E2A PDF \u6587\u6863\u4E4B\u95F4\u7684\u5DEE\u5F02
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
|
||||
downloadPdf=\u4E0B\u8F7DPDF
|
||||
text=\u6587\u672C
|
||||
font=\u5B57\u4F53
|
||||
selectFillter=-- 选择--
|
||||
pageNum=页码
|
||||
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
certSign.title=证书签名
|
||||
certSign.header=使用您的证书签署 PDF(进行中)
|
||||
certSign.selectPDF=选择要签名的 PDF 文件:
|
||||
@@ -250,6 +273,7 @@ compress.submit=压缩
|
||||
addImage.title=添加图像
|
||||
addImage.header=添加图片到PDF (Work in progress)
|
||||
addImage.everyPage=每一页?
|
||||
addImage.upload=添加图片
|
||||
addImage.submit=添加图片
|
||||
|
||||
|
||||
@@ -336,7 +360,10 @@ addPassword.selectText.9=防止填写表格
|
||||
addPassword.selectText.10=防止修改
|
||||
addPassword.selectText.11=防止修改注释
|
||||
addPassword.selectText.12=防止打印
|
||||
addPassword.selectText.13=防止打印不同的格式
|
||||
addPassword.selectText.13=防止打印不同的格<EFBFBD>
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself<6C>
|
||||
addPassword.submit=加密
|
||||
|
||||
#watermark
|
||||
|
||||
94
src/main/resources/static/css/errorBanner.css
Normal file
94
src/main/resources/static/css/errorBanner.css
Normal file
@@ -0,0 +1,94 @@
|
||||
#errorContainer {
|
||||
margin: 20px; /* adjust this value as needed */
|
||||
}
|
||||
|
||||
#helpModalDialog {
|
||||
width: 90%;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
#helpModal h1 {
|
||||
text-align: center;
|
||||
margin-top: 10%;
|
||||
}
|
||||
|
||||
#helpModal p {
|
||||
text-align: center;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
#helpModal .button:hover {
|
||||
background-color: #005b7f;
|
||||
}
|
||||
|
||||
#helpModal .features-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
|
||||
gap: 25px 30px;
|
||||
}
|
||||
|
||||
#helpModal .feature-card {
|
||||
border: 1px solid rgba(0, 0, 0, .125);
|
||||
border-radius: 0.25rem;
|
||||
padding: 1.25rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
#helpModal .feature-card .card-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#support-section {
|
||||
background-color: #f9f9f9;
|
||||
padding: 4rem;
|
||||
margin-top: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#support-section h1 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
#support-section p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
#button-group {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#github-button, #discord-button {
|
||||
display: inline-block;
|
||||
padding: 1rem 2rem;
|
||||
margin: 1rem;
|
||||
background-color: #008CBA;
|
||||
color: #fff;
|
||||
font-size: 1.2rem;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border-radius: 3rem;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
#github-button:hover, #discord-button:hover, #home-button:hover {
|
||||
background-color: #005b7f;
|
||||
}
|
||||
|
||||
#home-button {
|
||||
display: block;
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
margin: 2em auto;
|
||||
background-color: #008CBA;
|
||||
color: white;
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
border-radius: 25px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
10
src/main/resources/static/css/fileSelect.css
Normal file
10
src/main/resources/static/css/fileSelect.css
Normal file
@@ -0,0 +1,10 @@
|
||||
.custom-file-label {
|
||||
padding-right: 90px;
|
||||
}
|
||||
|
||||
.selected-files {
|
||||
margin-top: 10px;
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
49
src/main/resources/static/css/game.css
Normal file
49
src/main/resources/static/css/game.css
Normal file
@@ -0,0 +1,49 @@
|
||||
#game-container {
|
||||
position: relative;
|
||||
width: 100vh;
|
||||
height: 0;
|
||||
padding-bottom: 75%; /* 4:3 aspect ratio */
|
||||
background-color: transparent;
|
||||
margin: auto;
|
||||
overflow: hidden;
|
||||
border: 2px solid black; /* Add border */
|
||||
}
|
||||
|
||||
.pdf, .player, .projectile {
|
||||
position: absolute;
|
||||
}
|
||||
.pdf {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
.player {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
.projectile {
|
||||
background-color: black !important;
|
||||
width: 5px;
|
||||
height: 10px;
|
||||
}
|
||||
#score, #level, #lives, #high-score {
|
||||
color: black;
|
||||
font-family: sans-serif;
|
||||
position: absolute;
|
||||
font-size: calc(14px + 0.25vw); /* Reduced font size */
|
||||
}
|
||||
#score {
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
#lives {
|
||||
top: 10px;
|
||||
left: calc(7vw); /* Adjusted position */
|
||||
}
|
||||
#high-score {
|
||||
top: 10px;
|
||||
left: calc(14vw); /* Adjusted position */
|
||||
}
|
||||
#level {
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
70
src/main/resources/static/css/home.css
Normal file
70
src/main/resources/static/css/home.css
Normal file
@@ -0,0 +1,70 @@
|
||||
.features-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
|
||||
gap: 25px 30px;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
border: 2px solid rgba(0, 0, 0, .25);
|
||||
border-radius: 0.25rem;
|
||||
padding: 1.25rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
background: rgba(13, 110, 253, 0.05);
|
||||
transition: transform 0.3s, border 0.3s;
|
||||
}
|
||||
|
||||
.feature-card a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.feature-card .card-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
border: 1px solid rgba(0, 0, 0, .5);
|
||||
cursor: pointer;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.feature-card:hover .card-title {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.card-title.text-primary {
|
||||
color: #000; /* Replace with your desired shade of blue */
|
||||
}
|
||||
|
||||
.home-card-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
.home-card-icon-colour {
|
||||
filter: invert(0.2) sepia(2) saturate(50) hue-rotate(190deg);
|
||||
}
|
||||
|
||||
.favorite-icon {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
/* Only show the favorite icons when the parent card is being hovered over */
|
||||
.feature-card:hover .favorite-icon {
|
||||
display: block;
|
||||
}
|
||||
.favorite-icon img {
|
||||
filter: brightness(0);
|
||||
}
|
||||
|
||||
.jumbotron {
|
||||
padding: 3rem 3rem; /* Reduce vertical padding */
|
||||
}
|
||||
25
src/main/resources/static/css/merge.css
Normal file
25
src/main/resources/static/css/merge.css
Normal file
@@ -0,0 +1,25 @@
|
||||
.list-group-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filename {
|
||||
flex-grow: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.arrows {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.move-up span,
|
||||
.move-down span {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
42
src/main/resources/static/css/navbar.css
Normal file
42
src/main/resources/static/css/navbar.css
Normal file
@@ -0,0 +1,42 @@
|
||||
.main-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
vertical-align: middle;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: middle;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.icon+.icon {
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.nav-item-separator {
|
||||
position: relative;
|
||||
margin: 0 4px; /* Adjust the margin as needed */
|
||||
}
|
||||
|
||||
.nav-item-separator::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 10%; /* Adjust the top and bottom margins as needed */
|
||||
bottom: 10%;
|
||||
width: 1px;
|
||||
background-color: #ccc; /* Adjust the color as needed */
|
||||
}
|
||||
|
||||
.navbar-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
BIN
src/main/resources/static/favicon.ico
Normal file
BIN
src/main/resources/static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 201 KiB |
BIN
src/main/resources/static/fonts/Meiryo.ttf
Normal file
BIN
src/main/resources/static/fonts/Meiryo.ttf
Normal file
Binary file not shown.
BIN
src/main/resources/static/fonts/NotoSans-Regular.ttf
Normal file
BIN
src/main/resources/static/fonts/NotoSans-Regular.ttf
Normal file
Binary file not shown.
BIN
src/main/resources/static/fonts/NotoSansArabic-Regular.ttf
Normal file
BIN
src/main/resources/static/fonts/NotoSansArabic-Regular.ttf
Normal file
Binary file not shown.
BIN
src/main/resources/static/fonts/NotoSansJP-Regular.ttf
Normal file
BIN
src/main/resources/static/fonts/NotoSansJP-Regular.ttf
Normal file
Binary file not shown.
BIN
src/main/resources/static/fonts/NotoSansSC-Regular.ttf
Normal file
BIN
src/main/resources/static/fonts/NotoSansSC-Regular.ttf
Normal file
Binary file not shown.
BIN
src/main/resources/static/fonts/SimSun.ttf
Normal file
BIN
src/main/resources/static/fonts/SimSun.ttf
Normal file
Binary file not shown.
BIN
src/main/resources/static/fonts/malgun.ttf
Normal file
BIN
src/main/resources/static/fonts/malgun.ttf
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/static/fonts/static/NotoSansJP-Regular.ttf
Normal file
BIN
src/main/resources/static/fonts/static/NotoSansJP-Regular.ttf
Normal file
Binary file not shown.
5
src/main/resources/static/images/flags/eu.svg
Normal file
5
src/main/resources/static/images/flags/eu.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-es-pv" viewBox="0 0 640 480">
|
||||
<path fill="#D52B1E" d="m0 0h640v480h-640z" />
|
||||
<path fill="#009B48" d="m0 0h53.1l133.4 100.1c73.4 55 133.4 100 133.5 100 0.1 0 60.1-45 266.9-200.1h53.1v39.9l-133.4 100c-73.4 55-133.4 100.1-133.4 100.1 0 0 60 45.1 266.8 200.2v39.8h-53.1l-133.4-100c-73.4-55.1-133.4-100.1-133.5-100.1-0.1 0-60.1 45-266.9 200.1h-53.1v-39.8l133.4-100.1c73.4-55 133.4-100.1 133.4-100.1 0 0-60-45.1-266.8-200.1v-20z" />
|
||||
<path fill="#FFF" d="m288.1 0h63.8v208.1h288.1v63.8h-288.1v208.1h-63.8v-208.1h-288.1v-63.8h288.1v-104z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 602 B |
11
src/main/resources/static/images/flags/jp.svg
Normal file
11
src/main/resources/static/images/flags/jp.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-jp" viewBox="0 0 640 480">
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill-opacity=".7" d="M-88 32h640v480H-88z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g fill-rule="evenodd" stroke-width="1pt" clip-path="url(#a)" transform="translate(88 -32)">
|
||||
<path fill="#fff" d="M-128 32h720v480h-720z"/>
|
||||
<circle cx="523.1" cy="344.1" r="194.9" fill="#bc002d" transform="translate(-168.4 8.6) scale(.76554)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 465 B |
24
src/main/resources/static/images/flags/kr.svg
Executable file
24
src/main/resources/static/images/flags/kr.svg
Executable file
@@ -0,0 +1,24 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="flag-icons-kr" viewBox="0 0 640 480">
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill-opacity=".7" d="M-95.8-.4h682.7v512H-95.8z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g fill-rule="evenodd" clip-path="url(#a)" transform="translate(89.8 .4) scale(.9375)">
|
||||
<path fill="#fff" d="M-95.8-.4H587v512H-95.8Z"/>
|
||||
<g transform="rotate(-56.3 361.6 -101.3) scale(10.66667)">
|
||||
<g id="c">
|
||||
<path id="b" d="M-6-26H6v2H-6Zm0 3H6v2H-6Zm0 3H6v2H-6Z"/>
|
||||
<use xlink:href="#b" width="100%" height="100%" y="44"/>
|
||||
</g>
|
||||
<path stroke="#fff" d="M0 17v10"/>
|
||||
<path fill="#cd2e3a" d="M0-12a12 12 0 0 1 0 24Z"/>
|
||||
<path fill="#0047a0" d="M0-12a12 12 0 0 0 0 24A6 6 0 0 0 0 0Z"/>
|
||||
<circle cy="-6" r="6" fill="#cd2e3a"/>
|
||||
</g>
|
||||
<g transform="rotate(-123.7 191.2 62.2) scale(10.66667)">
|
||||
<use xlink:href="#c" width="100%" height="100%"/>
|
||||
<path stroke="#fff" d="M0-23.5v3M0 17v3.5m0 3v3"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user