Compare commits

..

5 Commits

Author SHA1 Message Date
github-actions[bot] d1dd8fc604 Update index.yaml
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-04 20:13:48 +00:00
Anthony Stirling 24395a1ddd Update README.md 2024-10-31 21:54:41 +00:00
Anthony Stirling 02a3396b5f Update README.md 2024-10-31 21:51:51 +00:00
Anthony Stirling 64ae78ad7a Update README.md 2024-10-30 13:55:40 +00:00
a 00000344bb chore(docs): add README 2024-10-30 13:54:18 +00:00
174 changed files with 44 additions and 94274 deletions
-5
View File
@@ -1,5 +0,0 @@
# Ignore all JavaScript files in a directory
src/main/resources/static/pdfjs/* linguist-vendored
src/main/resources/static/css/bootstrap-icons.css linguist-vendored
src/main/resources/static/css/bootstrap.min.css linguist-vendored
src/main/resources/static/css/fonts/* linguist-vendored
-13
View File
@@ -1,13 +0,0 @@
# These are supported funding model platforms
github: Frooodle # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: ['https://paypal.me/froodleplex?country.x=GB&locale.x=en_GB'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
-11
View File
@@ -1,11 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gradle" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
-55
View File
@@ -1,55 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
name: "Build repo"
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '15 12 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
# - name: Initialize CodeQL
# uses: github/codeql-action/init@v2
# with:
# languages: java
- uses: gradle/gradle-build-action@v2.4.2
with:
gradle-version: 7.6
arguments: assemble --no-build-cache
#- name: Perform CodeQL analysis
# uses: github/codeql-action/analyze@v2
-74
View File
@@ -1,74 +0,0 @@
name: Push Docker Image with VersionNumber
on:
workflow_dispatch:
push:
branches:
- master
- main
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'
- uses: gradle/gradle-build-action@v2.4.2
with:
gradle-version: 7.6
arguments: clean build
- name: Make Gradle wrapper executable
run: chmod +x gradlew
- name: Get version number
id: versionNumber
run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"
- name: Login to Docker Hub
uses: docker/login-action@v2.1.0
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_API }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- 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
tags: |
${{ steps.versionNumber.outputs.versionNumber }}${{ github.ref == 'refs/heads/main' && '-alpha' || '' }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.1.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2.5.0
- name: Build and push
uses: docker/build-push-action@v4.0.0
with:
context: .
push: true
cache-from: type=gha
cache-to: type=gha,mode=max
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64/v8
-112
View File
@@ -1,112 +0,0 @@
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
.classpath
.project
# Gradle
.gradle
.lock
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
#.project
### Eclipse Patch ###
# Spring Boot Tooling
.sts4-cache/
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
/build
-1
View File
@@ -1 +0,0 @@
stirlingtools.com
-24
View File
@@ -1,24 +0,0 @@
# Build jbig2enc in a separate stage
FROM frooodle/stirling-pdf-base:beta2
# Create scripts folder and copy local scripts
RUN mkdir /scripts
COPY ./scripts/* /scripts/
# Copy the application JAR file
COPY build/libs/*.jar app.jar
# Expose the application port
EXPOSE 8080
# Set environment variables
ENV APP_HOME_NAME="Stirling PDF"
#ENV APP_HOME_DESCRIPTION="Personal PDF Website!"
#ENV APP_NAVBAR_NAME="Stirling PDF"
# Run the application
ENTRYPOINT ["/scripts/init.sh"]
CMD ["java", "-jar", "/app.jar"]
-62
View File
@@ -1,62 +0,0 @@
# Build jbig2enc in a separate stage
FROM debian:bullseye-slim as jbig2enc_builder
RUN apt-get update && \
apt-get install -y --no-install-recommends \
git \
automake \
autoconf \
libtool \
libleptonica-dev \
pkg-config \
ca-certificates \
zlib1g-dev \
make \
g++
RUN git clone https://github.com/agl/jbig2enc && \
cd jbig2enc && \
./autogen.sh && \
./configure && \
make && \
make install
# Main stage
FROM openjdk:17-jdk-slim AS base
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libreoffice-core \
libreoffice-common \
libreoffice-writer \
libreoffice-calc \
libreoffice-impress \
python3-uno \
python3-pip \
unoconv \
pngquant \
unpaper \
ocrmypdf && \
rm -rf /var/lib/apt/lists/* && \
mkdir /usr/share/tesseract-ocr-original && \
cp -r /usr/share/tesseract-ocr/* /usr/share/tesseract-ocr-original && \
rm -rf /usr/share/tesseract-ocr
# Python packages stage
FROM base AS python-packages
RUN apt-get update && \
apt-get install -y --no-install-recommends \
build-essential \
libffi-dev \
libssl-dev \
zlib1g-dev \
libjpeg-dev && \
pip install --upgrade pip && \
pip install --no-cache-dir \
opencv-python-headless && \
rm -rf /var/lib/apt/lists/*
# Final stage: Copy necessary files from the previous stage
FROM base
COPY --from=python-packages /usr/local /usr/local
COPY --from=jbig2enc_builder /usr/local/bin/jbig2 /usr/local/bin/jbig2
-31
View File
@@ -1,31 +0,0 @@
<p align="center"><img src="https://raw.githubusercontent.com/Frooodle/Stirling-PDF/main/docs/stirling.png" width="80" ><br><h1 align="center">Stirling-PDF</h1>
</p>
# How to add new languages to Stirling-PDF
Fork Stirling-PDF and make a new branch out of Main
Then add reference to the language in the navbar by adding a new language entry to the dropdown
https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/templates/fragments/navbar.html#L80
For example to add Polish you would add
```
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="pl_PL">Polish</a>
```
The data-language-code is the code used to reference the file in the next step.
Start by copying the existing english property file
[https://github.com/Frooodle/Stirling-PDF/tree/langSetup/src/main/resources/messages_en_GB.properties](https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/messages_en_US.properties)
Copy and rename it to messages_{your data-language-code here}.properties, in the polish example you would set the name to messages_pl_PL.properties
Then simply translate all property entries within that file and make a PR into main for others to use!
If you do not have a java IDE i am happy to verify the changes worked once you raise PR (but wont be able to verify the translations themselves)
-51
View File
@@ -1,51 +0,0 @@
# OCR Language Packs and Setup
This document provides instructions on how to add additional language packs for the OCR tab in Stirling-PDF, both inside and outside of Docker.
## How does the OCR Work
Stirling-PDF uses OCRmyPDF which in turn uses tesseract for its text recognition.
All credit goes to them for this awesome work!
## Language Packs
Tesseract OCR supports a variety of languages. You can find additional language packs in the Tesseract GitHub repositories:
- [tessdata_fast](https://github.com/tesseract-ocr/tessdata_fast): These language packs are smaller and faster to load, but may provide lower recognition accuracy.
- [tessdata](https://github.com/tesseract-ocr/tessdata): These language packs are larger and provide better recognition accuracy, but may take longer to load.
Depending on your requirements, you can choose the appropriate language pack for your use case. By default Stirling-PDF uses the tessdata_fast eng but this can be replaced.
### Installing Language Packs
1. Download the desired language pack(s) by selecting the `.traineddata` file(s) for the language(s) you need.
2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tesseract-ocr/4.00/tessdata`
# DO NOT REMOVE EXISTING ENG.TRAINEDDATA, ITS REQUIRED.
#### Docker
If you are using Docker, you need to expose the Tesseract tessdata directory as a volume in order to use the additional language packs.
#### Docker Compose
Modify your `docker-compose.yml` file to include the following volume configuration:
```yaml
services:
your_service_name:
image: your_docker_image_name
volumes:
- /usr/share/tesseract-ocr/4.00/tessdata:/location/of/trainingData
```
#### Docker run
Add the following to your existing docker run command
```bash
-v /usr/share/tesseract-ocr/4.00/tessdata:/location/of/trainingData
```
#### Non-Docker
If you are not using Docker, you need to install the OCR components, including the ocrmypdf app.
You can see [OCRmyPDF install guide](https://ocrmypdf.readthedocs.io/en/latest/installation.html)
Vendored
-33
View File
@@ -1,33 +0,0 @@
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'chmod 755 gradlew'
sh './gradlew build'
}
}
stage('Docker Build') {
steps {
script {
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
def image = "frooodle/s-pdf:$appVersion"
sh "docker build -t $image ."
}
}
}
stage('Docker Push') {
steps {
script {
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
def image = "frooodle/s-pdf:$appVersion"
withCredentials([string(credentialsId: 'docker_hub_access_token', variable: 'DOCKER_HUB_ACCESS_TOKEN')]) {
sh "docker login --username frooodle --password $DOCKER_HUB_ACCESS_TOKEN"
sh "docker push $image"
}
}
}
}
}
}
-201
View File
@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+20 -105
View File
@@ -1,105 +1,20 @@
<p align="center"><img src="https://raw.githubusercontent.com/Frooodle/Stirling-PDF/main/docs/stirling.png" width="80" ><br><h1 align="center">Stirling-PDF</h1>
</p>
[![Docker Pulls](https://img.shields.io/docker/pulls/frooodle/s-pdf)](https://hub.docker.com/r/frooodle/s-pdf)
[![Discord](https://img.shields.io/discord/1068636748814483718?label=Discord)](https://discord.gg/Cn8pWhQRxZ)
[![Docker Image Version (tag latest semver)](https://img.shields.io/docker/v/frooodle/s-pdf/latest)](https://github.com/Frooodle/Stirling-PDF/)
[![GitHub Repo stars](https://img.shields.io/github/stars/frooodle/stirling-pdf?style=social)](https://github.com/Frooodle/stirling-pdf)
[![Paypal Donate](https://img.shields.io/badge/Paypal%20Donate-yellow?style=flat&logo=paypal)](https://www.paypal.com/paypalme/froodleplex)
[![Github Sponser](https://img.shields.io/badge/Github%20Sponsor-yellow?style=flat&logo=github)](https://github.com/sponsors/Frooodle)
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.
Feel free to request any features or bug fixes either in github issues or our [Discord](https://discord.gg/Cn8pWhQRxZ)
![stirling-home](images/stirling-home.png)
## Features
- Full intractable 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
- Reorganize PDF pages into different orders.
- Add images to PDFs at specified locations. (WIP)
- Rotating PDFs in 90 degree increments.
- Compressing PDFs to decrease their filesize. (Using OCRMyPDF)
- Add and remove passwords
- Set PDF Permissions
- Add watermark(s)
- Convert Any common file to PDF (using LibreOffice)
- Convert PDF to Word/Powerpoint/Others (using LibreOffice)
- Extract images from PDF
- OCR on PDF (Using OCRMyPDF)
- Edit metadata
- Dark mode support.
- Custom download options (see [here](https://github.com/Frooodle/Stirling-PDF/blob/main/images/settings.png) for example)
- Parallel file processing and downloads
## Technologies used
- Spring Boot + Thymeleaf
- PDFBox
- [LibreOffice](https://www.libreoffice.org/discover/libreoffice/) for advanced conversions
- [OcrMyPdf](https://github.com/ocrmypdf/OCRmyPDF)
- HTML, CSS, JavaScript
- Docker
- PDF.js
- PDF-LIB.js
## How to use
### Locally
Prerequisites
- Java 17 or later
- Gradle 7.0 or later
1. Clone or download the repository.
2. Build the project using Gradle by running `./gradlew build`
3. Start the application by running `./gradlew bootRun` or by calling the build jar in build/libs with java -jar jarName.jar
### Docker
https://hub.docker.com/r/frooodle/s-pdf
Docker Run
```
docker run -p 8080:8080 frooodle/s-pdf
```
Docker Compose
```
version: '3.3'
services:
s-pdf:
ports:
- '8080:8080'
image: frooodle/s-pdf
```
## Enable OCR/Compression feature
Please view https://github.com/Frooodle/Stirling-PDF/blob/main/HowToUseOCR.md
## Want to add your own language?
If you want to add your own language to Stirling-PDF please refer
https://github.com/Frooodle/Stirling-PDF/blob/main/HowToAddNewLanguage.md
And please create a PR to merge it back in so others can use it!
Also please note as i add new features i will google translate existing languages so that they dont lose support. This could mean that new features need grammer corrections as added.
## How to View
1. Open a web browser and navigate to `http://localhost:8080/`
2. Use the application by following the instructions on the website.
## Customize App
Stirling PDF allows easy customization of the visible application name.
Simply use environment variables APP_HOME_NAME, APP_HOME_DESCRIPTION and APP_NAVBAR_NAME with Docker or Java.
If running Java directly, you can also pass these as properties using -D arguments.
Using the same method you can also change the default language by providing APP_LOCALE with values like de-DE fr-FR or ar-AR to select your default language (Will always default to English on invalid locale)
## API
For those wanting to use Stirling-PDFs backend API to link with their own custom scripting to edit PDFs you can view all existing API documentation
[here](https://app.swaggerhub.com/apis-docs/Frooodle/Stirling-PDF/1.0.0) or navigate to /swagger-ui/index.html of your stirling-pdf instance for your versions documentation
## Usage
[Helm](https://helm.sh) must be installed to use the charts. Please refer to
Helm's [documentation](https://helm.sh/docs) to get started.
Once Helm has been set up correctly, add the repo as follows:
`helm repo add <alias> https://docs.stirlingpdf.com/Stirling-PDF`
If you had already added this repo earlier, run `helm repo update` to retrieve
the latest versions of the packages. You can then run `helm search repo <alias>` to see the charts.
To install the <chart-name> chart:
helm install <chart-name> <alias>/<chart-name>
To uninstall the chart:
helm delete <chart-name>
-46
View File
@@ -1,46 +0,0 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.6'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'stirling.software'
version = '0.7.0'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
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'
// 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 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
//general PDF
implementation 'org.apache.pdfbox:pdfbox:2.0.28'
developmentOnly("org.springframework.boot:spring-boot-devtools")
}
jar {
enabled = false
manifest {
attributes 'Implementation-Title': 'Stirling-PDF',
'Implementation-Version': project.version
}
}
tasks.named('test') {
useJUnitPlatform()
}
task printVersion {
println project.version
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

-298
View File
@@ -1,298 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="99.537987mm"
height="95.209366mm"
viewBox="0 0 99.537987 95.209366"
version="1.1"
id="svg745"
xml:space="preserve"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="stirling-transparent.svg"
inkscape:export-filename="stirling.png"
inkscape:export-xdpi="80"
inkscape:export-ydpi="80"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview747"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.914906"
inkscape:cx="175.42786"
inkscape:cy="510.43495"
inkscape:window-width="2256"
inkscape:window-height="1428"
inkscape:window-x="0"
inkscape:window-y="40"
inkscape:window-maximized="1"
inkscape:current-layer="svg745" /><defs
id="defs742"><linearGradient
inkscape:collect="always"
id="linearGradient72198"><stop
style="stop-color:#ccd6d7;stop-opacity:1;"
offset="0"
id="stop72194" /><stop
style="stop-color:#0f3a3f;stop-opacity:1;"
offset="1"
id="stop72196" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient71928"><stop
style="stop-color:#4b0005;stop-opacity:1;"
offset="0"
id="stop71924" /><stop
style="stop-color:#8f000c;stop-opacity:1;"
offset="1"
id="stop71926" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient71920"><stop
style="stop-color:#4b0005;stop-opacity:1;"
offset="0"
id="stop71916" /><stop
style="stop-color:#8f000c;stop-opacity:1;"
offset="1"
id="stop71918" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient69598"><stop
style="stop-color:#6a0007;stop-opacity:1;"
offset="0"
id="stop69594" /><stop
style="stop-color:#b8000f;stop-opacity:1;"
offset="1"
id="stop69596" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient46361"><stop
style="stop-color:#f7f6f8;stop-opacity:1;"
offset="0"
id="stop46359" /><stop
style="stop-color:#b7b7b5;stop-opacity:1;"
offset="1"
id="stop46357" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient40554"><stop
style="stop-color:#f4f2f4;stop-opacity:1;"
offset="0"
id="stop40550" /><stop
style="stop-color:#57767b;stop-opacity:1;"
offset="1"
id="stop40552" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient39095"><stop
style="stop-color:#285459;stop-opacity:1;"
offset="0"
id="stop39093" /><stop
style="stop-color:#a6b6af;stop-opacity:1;"
offset="1"
id="stop39091" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient36672"><stop
style="stop-color:#da453f;stop-opacity:1;"
offset="0"
id="stop36668" /><stop
style="stop-color:#a60008;stop-opacity:1;"
offset="1"
id="stop36670" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient19524"><stop
style="stop-color:#3a4b4f;stop-opacity:1;"
offset="0"
id="stop19522" /><stop
style="stop-color:#617979;stop-opacity:0.97461927;"
offset="1"
id="stop19520" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient17996"><stop
style="stop-color:#401016;stop-opacity:1;"
offset="0"
id="stop17994" /><stop
style="stop-color:#761f19;stop-opacity:1;"
offset="1"
id="stop17992" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient15569"><stop
style="stop-color:#8ea8ad;stop-opacity:1;"
offset="0"
id="stop15565" /><stop
style="stop-color:#e9e7eb;stop-opacity:1;"
offset="1"
id="stop15567" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient15557"><stop
style="stop-color:#9b0e11;stop-opacity:1;"
offset="0"
id="stop15553" /><stop
style="stop-color:#370707;stop-opacity:1;"
offset="1"
id="stop15555" /></linearGradient><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15557"
id="linearGradient15559"
x1="120.06672"
y1="63.25761"
x2="135.16347"
y2="78.078682"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15569"
id="linearGradient15571"
x1="127.97037"
y1="101.66144"
x2="133.88971"
y2="104.77026"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient17996"
id="linearGradient17998"
x1="117.9284"
y1="86.055084"
x2="130.67392"
y2="76.945541"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient19524"
id="linearGradient19528"
x1="130.98172"
y1="82.402977"
x2="135.72115"
y2="86.45166"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient36672"
id="linearGradient36674"
x1="63.797714"
y1="74.81752"
x2="96.636673"
y2="120.29293"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient39095"
id="linearGradient39097"
x1="120.54506"
y1="124.76902"
x2="128.04152"
y2="126.0704"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient40554"
id="linearGradient40556"
x1="113.84585"
y1="114.04285"
x2="119.65858"
y2="128.50244"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient46361"
id="linearGradient46363"
x1="73.993439"
y1="114.13906"
x2="94.845322"
y2="71.247383"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient69598"
id="linearGradient69600"
x1="95.854446"
y1="114.66749"
x2="103.77842"
y2="120.1887"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient71920"
id="linearGradient71922"
x1="98.580376"
y1="87.186958"
x2="118.09738"
y2="101.19449"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient71928"
id="linearGradient71930"
x1="78.278267"
y1="97.433273"
x2="92.313202"
y2="104.33479"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient72198"
id="linearGradient72200"
x1="125.76636"
y1="138.46817"
x2="123.3327"
y2="126.03291"
gradientUnits="userSpaceOnUse" /></defs><g
inkscape:groupmode="layer"
id="layer5"
inkscape:label="shadow"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient72200);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 84.146049,134.73858 c 0,0 11.721038,2.48294 17.938661,2.91673 6.21763,0.43378 14.75251,0.59994 22.41237,-0.43379 8.01008,-1.081 13.19907,-2.22733 14.50043,-2.66112 1.30136,-0.43379 4.00784,-1.24297 4.15244,-2.25514 0.1446,-1.01217 -3.4703,-2.74733 -6.21763,-3.32571 -2.74732,-0.57838 -12.72444,-1.44596 -14.89337,-1.44596 -2.16894,0 -37.892901,7.20499 -37.892901,7.20499 z"
id="path72192"
sodipodi:nodetypes="cssssssc" /></g><g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Origami"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient40556);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 84.460552,134.86721 35.165798,-6.85679 16.15467,-42.7383 z"
id="path960"
sodipodi:nodetypes="cccc" /><path
style="fill:url(#linearGradient15571);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 135.71493,85.428056 0.3984,45.049024 -9.66213,-20.46173 z"
id="path964"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient39097);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 119.60518,128.00293 16.5337,2.48693 -9.68769,-20.5512 z"
id="path966"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient15559);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 118.42209,57.022622 12.70423,-2.766809 -0.0785,25.087175 -12.43878,-13.376518 z"
id="path968"
sodipodi:nodetypes="ccccc" /><path
style="display:inline;fill:url(#linearGradient19528);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 135.72114,85.386768 -4.84219,-6.459493 0.0305,11.126604 z"
id="path970"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient17998);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 119.10273,65.682415 11.96883,13.44935 -0.0899,10.819868 -11.88577,11.430427 z"
id="path972"
sodipodi:nodetypes="ccccc" /><path
style="display:inline;fill:url(#linearGradient36674);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 62.145635,130.15618 62.043392,65.435258 c 0,0 0.179321,-2.778132 1.89516,-4.036097 1.874923,-1.374597 4.341768,-1.894096 4.341768,-1.894096 l 50.91788,-11.349167 -0.0113,53.144272 -34.733274,33.56547 z"
id="path958"
sodipodi:nodetypes="ccsccccc" /></g><g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Letter"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient69600);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 94.780881,91.406803 16.870379,17.074877 -23.723345,23.00249 -18.122131,-17.99816 5.497473,-2.80607 18.404054,-0.0511 2.35163,-8.23071 z"
id="path54894"
sodipodi:nodetypes="cccccccc" /><path
style="display:inline;fill:url(#linearGradient71930);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 72.440405,92.224764 16.15467,15.745686 4.089788,-6.79927 z"
id="path54892" /><path
style="display:inline;fill:url(#linearGradient71922);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 95.138739,84.965385 1.124691,-14.109776 22.92453,22.286787 0.008,8.164604 -3.28863,3.16649 z"
id="path54890"
sodipodi:nodetypes="cccccc"
inkscape:label="path54890" /><path
style="display:inline;fill:url(#linearGradient46363);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 95.138739,84.965385 h 1.226936 l -0.05112,-14.109776 c 0,0 -5.776827,-3.220709 -12.167126,-2.40275 -6.390296,0.817957 -8.151582,2.1248 -10.58233,4.396523 -1.90229,1.777838 -2.913974,3.527446 -3.987546,7.157132 -0.512646,1.733226 -0.281963,5.988892 0.613471,8.537436 0.664591,1.891528 2.453873,4.294281 4.958868,6.134686 2.662335,1.956002 8.281825,3.527443 8.281825,3.527443 0,0 5.134614,1.887351 5.572338,4.294281 0.308137,1.69437 -0.102243,3.22071 -1.635914,4.95887 -1.258314,1.42609 -3.62969,1.99377 -6.288054,1.07357 -2.658364,-0.92021 -6.139514,-3.85065 -7.106009,-4.90775 -0.817958,-0.89464 -2.820665,-3.06173 -2.890231,-4.294021 -0.01209,-0.214205 -1.229505,-0.0963 -1.229505,-0.0963 l -0.0723,14.256941 5.879073,2.24938 c 0,0 5.214483,1.78929 8.946415,1.43143 3.731934,-0.35786 7.617235,-0.51122 11.604778,-5.16336 3.987542,-4.65213 3.680812,-12.831715 2.147141,-15.899056 -1.533673,-3.067344 -3.561212,-6.138812 -10.480087,-8.281826 -5.776829,-1.789283 -7.872846,-3.01622 -8.128458,-4.396524 -0.255611,-1.380305 0.0091,-4.253646 2.760607,-5.214481 3.220711,-1.124693 5.623462,-0.05112 7.05489,1.12469 1.431425,1.175817 5.572339,5.623462 5.572339,5.623462 z"
id="path46355"
sodipodi:nodetypes="cccssssscssssscccssssssscc" /></g></svg>

Before

Width:  |  Height:  |  Size: 14 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

-310
View File
@@ -1,310 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="99.537987mm"
height="95.209366mm"
viewBox="0 0 99.537987 95.209366"
version="1.1"
id="svg745"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
sodipodi:docname="stirling.svg"
inkscape:export-filename="stirling.png"
inkscape:export-xdpi="80"
inkscape:export-ydpi="80"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview747"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.914906"
inkscape:cx="184.17193"
inkscape:cy="509.88845"
inkscape:window-width="2293"
inkscape:window-height="1387"
inkscape:window-x="122"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="svg745" /><defs
id="defs742"><linearGradient
inkscape:collect="always"
id="linearGradient72198"><stop
style="stop-color:#ccd6d7;stop-opacity:1;"
offset="0"
id="stop72194" /><stop
style="stop-color:#0f3a3f;stop-opacity:1;"
offset="1"
id="stop72196" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient71928"><stop
style="stop-color:#4b0005;stop-opacity:1;"
offset="0"
id="stop71924" /><stop
style="stop-color:#8f000c;stop-opacity:1;"
offset="1"
id="stop71926" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient71920"><stop
style="stop-color:#4b0005;stop-opacity:1;"
offset="0"
id="stop71916" /><stop
style="stop-color:#8f000c;stop-opacity:1;"
offset="1"
id="stop71918" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient69598"><stop
style="stop-color:#6a0007;stop-opacity:1;"
offset="0"
id="stop69594" /><stop
style="stop-color:#b8000f;stop-opacity:1;"
offset="1"
id="stop69596" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient46361"><stop
style="stop-color:#f7f6f8;stop-opacity:1;"
offset="0"
id="stop46359" /><stop
style="stop-color:#b7b7b5;stop-opacity:1;"
offset="1"
id="stop46357" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient40554"><stop
style="stop-color:#f4f2f4;stop-opacity:1;"
offset="0"
id="stop40550" /><stop
style="stop-color:#57767b;stop-opacity:1;"
offset="1"
id="stop40552" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient39095"><stop
style="stop-color:#285459;stop-opacity:1;"
offset="0"
id="stop39093" /><stop
style="stop-color:#a6b6af;stop-opacity:1;"
offset="1"
id="stop39091" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient36672"><stop
style="stop-color:#da453f;stop-opacity:1;"
offset="0"
id="stop36668" /><stop
style="stop-color:#a60008;stop-opacity:1;"
offset="1"
id="stop36670" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient19524"><stop
style="stop-color:#3a4b4f;stop-opacity:1;"
offset="0"
id="stop19522" /><stop
style="stop-color:#617979;stop-opacity:0.97461927;"
offset="1"
id="stop19520" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient17996"><stop
style="stop-color:#401016;stop-opacity:1;"
offset="0"
id="stop17994" /><stop
style="stop-color:#761f19;stop-opacity:1;"
offset="1"
id="stop17992" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient15569"><stop
style="stop-color:#8ea8ad;stop-opacity:1;"
offset="0"
id="stop15565" /><stop
style="stop-color:#e9e7eb;stop-opacity:1;"
offset="1"
id="stop15567" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient15557"><stop
style="stop-color:#9b0e11;stop-opacity:1;"
offset="0"
id="stop15553" /><stop
style="stop-color:#370707;stop-opacity:1;"
offset="1"
id="stop15555" /></linearGradient><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15557"
id="linearGradient15559"
x1="120.06672"
y1="63.25761"
x2="135.16347"
y2="78.078682"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15569"
id="linearGradient15571"
x1="127.97037"
y1="101.66144"
x2="133.88971"
y2="104.77026"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient17996"
id="linearGradient17998"
x1="117.9284"
y1="86.055084"
x2="130.67392"
y2="76.945541"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient19524"
id="linearGradient19528"
x1="130.98172"
y1="82.402977"
x2="135.72115"
y2="86.45166"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient36672"
id="linearGradient36674"
x1="63.797714"
y1="74.81752"
x2="96.636673"
y2="120.29293"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient39095"
id="linearGradient39097"
x1="120.54506"
y1="124.76902"
x2="128.04152"
y2="126.0704"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient40554"
id="linearGradient40556"
x1="113.84585"
y1="114.04285"
x2="119.65858"
y2="128.50244"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient46361"
id="linearGradient46363"
x1="73.993439"
y1="114.13906"
x2="94.845322"
y2="71.247383"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient69598"
id="linearGradient69600"
x1="95.854446"
y1="114.66749"
x2="103.77842"
y2="120.1887"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient71920"
id="linearGradient71922"
x1="98.580376"
y1="87.186958"
x2="118.09738"
y2="101.19449"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient71928"
id="linearGradient71930"
x1="78.278267"
y1="97.433273"
x2="92.313202"
y2="104.33479"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient72198"
id="linearGradient72200"
x1="125.76636"
y1="138.46817"
x2="123.3327"
y2="126.03291"
gradientUnits="userSpaceOnUse" /></defs><g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="background"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><rect
style="display:inline;fill:#ccd6d7;fill-opacity:1;stroke:none;stroke-width:4.13755;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.2"
id="rect72067"
width="99.481979"
height="94.999512"
x="51.476147"
y="44.680138" /></g><g
inkscape:groupmode="layer"
id="layer5"
inkscape:label="shadow"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient72200);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 84.146049,134.73858 c 0,0 11.721038,2.48294 17.938661,2.91673 6.21763,0.43378 14.75251,0.59994 22.41237,-0.43379 8.01008,-1.081 13.19907,-2.22733 14.50043,-2.66112 1.30136,-0.43379 4.00784,-1.24297 4.15244,-2.25514 0.1446,-1.01217 -3.4703,-2.74733 -6.21763,-3.32571 -2.74732,-0.57838 -12.72444,-1.44596 -14.89337,-1.44596 -2.16894,0 -37.892901,7.20499 -37.892901,7.20499 z"
id="path72192"
sodipodi:nodetypes="cssssssc" /></g><g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Origami"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient40556);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 84.460552,134.86721 35.165798,-6.85679 16.15467,-42.7383 z"
id="path960"
sodipodi:nodetypes="cccc" /><path
style="fill:url(#linearGradient15571);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 135.71493,85.428056 0.3984,45.049024 -9.66213,-20.46173 z"
id="path964"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient39097);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 119.60518,128.00293 16.5337,2.48693 -9.68769,-20.5512 z"
id="path966"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient15559);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 118.42209,57.022622 12.70423,-2.766809 -0.0785,25.087175 -12.43878,-13.376518 z"
id="path968"
sodipodi:nodetypes="ccccc" /><path
style="display:inline;fill:url(#linearGradient19528);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 135.72114,85.386768 -4.84219,-6.459493 0.0305,11.126604 z"
id="path970"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient17998);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 119.10273,65.682415 11.96883,13.44935 -0.0899,10.819868 -11.88577,11.430427 z"
id="path972"
sodipodi:nodetypes="ccccc" /><path
style="display:inline;fill:url(#linearGradient36674);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 62.145635,130.15618 62.043392,65.435258 c 0,0 0.179321,-2.778132 1.89516,-4.036097 1.874923,-1.374597 4.341768,-1.894096 4.341768,-1.894096 l 50.91788,-11.349167 -0.0113,53.144272 -34.733274,33.56547 z"
id="path958"
sodipodi:nodetypes="ccsccccc" /></g><g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Letter"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient69600);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 94.780881,91.406803 16.870379,17.074877 -23.723345,23.00249 -18.122131,-17.99816 5.497473,-2.80607 18.404054,-0.0511 2.35163,-8.23071 z"
id="path54894"
sodipodi:nodetypes="cccccccc" /><path
style="display:inline;fill:url(#linearGradient71930);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 72.440405,92.224764 16.15467,15.745686 4.089788,-6.79927 z"
id="path54892" /><path
style="display:inline;fill:url(#linearGradient71922);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 95.138739,84.965385 1.124691,-14.109776 22.92453,22.286787 0.008,8.164604 -3.28863,3.16649 z"
id="path54890"
sodipodi:nodetypes="cccccc"
inkscape:label="path54890" /><path
style="display:inline;fill:url(#linearGradient46363);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 95.138739,84.965385 h 1.226936 l -0.05112,-14.109776 c 0,0 -5.776827,-3.220709 -12.167126,-2.40275 -6.390296,0.817957 -8.151582,2.1248 -10.58233,4.396523 -1.90229,1.777838 -2.913974,3.527446 -3.987546,7.157132 -0.512646,1.733226 -0.281963,5.988892 0.613471,8.537436 0.664591,1.891528 2.453873,4.294281 4.958868,6.134686 2.662335,1.956002 8.281825,3.527443 8.281825,3.527443 0,0 5.134614,1.887351 5.572338,4.294281 0.308137,1.69437 -0.102243,3.22071 -1.635914,4.95887 -1.258314,1.42609 -3.62969,1.99377 -6.288054,1.07357 -2.658364,-0.92021 -6.139514,-3.85065 -7.106009,-4.90775 -0.817958,-0.89464 -2.820665,-3.06173 -2.890231,-4.294021 -0.01209,-0.214205 -1.229505,-0.0963 -1.229505,-0.0963 l -0.0723,14.256941 5.879073,2.24938 c 0,0 5.214483,1.78929 8.946415,1.43143 3.731934,-0.35786 7.617235,-0.51122 11.604778,-5.16336 3.987542,-4.65213 3.680812,-12.831715 2.147141,-15.899056 -1.533673,-3.067344 -3.561212,-6.138812 -10.480087,-8.281826 -5.776829,-1.789283 -7.872846,-3.01622 -8.128458,-4.396524 -0.255611,-1.380305 0.0091,-4.253646 2.760607,-5.214481 3.220711,-1.124693 5.623462,-0.05112 7.05489,1.12469 1.431425,1.175817 5.572339,5.623462 5.572339,5.623462 z"
id="path46355"
sodipodi:nodetypes="cccssssscssssscccssssssscc" /></g></svg>

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.
-5
View File
@@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
-240
View File
@@ -1,240 +0,0 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
Vendored
-91
View File
@@ -1,91 +0,0 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

+24
View File
@@ -0,0 +1,24 @@
apiVersion: v1
entries:
stirling-pdf-chart:
- apiVersion: v2
appVersion: 0.31.1
created: "2024-11-04T20:13:48.298110043Z"
description: locally hosted web application that allows you to perform various
operations on PDF files
digest: 49a6e968f0203e7390094ae7fa20bc3fb0542ebdf426501c170641e98d2a45e2
home: https://github.com/Stirling-Tools/Stirling-PDF
keywords:
- stirling-pdf
- helm
- charts repo
maintainers:
- name: Stirling-Tools
url: https://github.com/Stirling-Tools/Stirling-PDF
name: stirling-pdf-chart
sources:
- https://github.com/Stirling-Tools/Stirling-PDF
urls:
- https://github.com/Stirling-Tools/Stirling-PDF/releases/download/stirling-pdf-chart-1.0.1/stirling-pdf-chart-1.0.1.tgz
version: 1.0.1
generated: "2024-11-04T20:13:48.29811941Z"
-9
View File
@@ -1,9 +0,0 @@
#!/bin/bash
# Copy the original tesseract-ocr files to the volume directory without overwriting existing files
echo "Copying original files without overwriting existing files"
mkdir -p /usr/share/tesseract-ocr
cp -rn /usr/share/tesseract-ocr-original/* /usr/share/tesseract-ocr
# Run the main command
exec "$@"
-134
View File
@@ -1,134 +0,0 @@
import sys
import cv2
import numpy as np
import os
def find_photo_boundaries(image, background_color, tolerance=30, min_area=10000, min_contour_area=500):
mask = cv2.inRange(image, background_color - tolerance, background_color + tolerance)
mask = cv2.bitwise_not(mask)
kernel = np.ones((5,5),np.uint8)
mask = cv2.dilate(mask, kernel, iterations=2)
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
photo_boundaries = []
for contour in contours:
x, y, w, h = cv2.boundingRect(contour)
area = w * h
contour_area = cv2.contourArea(contour)
if area >= min_area and contour_area >= min_contour_area:
photo_boundaries.append((x, y, w, h))
return photo_boundaries
def estimate_background_color(image, sample_points=5):
h, w, _ = image.shape
points = [
(0, 0),
(w - 1, 0),
(w - 1, h - 1),
(0, h - 1),
(w // 2, h // 2),
]
colors = []
for x, y in points:
colors.append(image[y, x])
return np.median(colors, axis=0)
def auto_rotate(image, angle_threshold=10):
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)
if len(contours) == 0:
return image
largest_contour = max(contours, key=cv2.contourArea)
mu = cv2.moments(largest_contour)
if mu["m00"] == 0:
return image
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
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
return cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)
def crop_borders(image, border_color, tolerance=30):
mask = cv2.inRange(image, border_color - tolerance, border_color + tolerance)
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if len(contours) == 0:
return image
largest_contour = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(largest_contour)
return image[y:y+h, x:x+w]
def split_photos(input_file, output_directory, tolerance=30, min_area=10000, min_contour_area=500, angle_threshold=10, border_size=0):
image = cv2.imread(input_file)
background_color = estimate_background_color(image)
# Add a constant border around the image
image = cv2.copyMakeBorder(image, border_size, border_size, border_size, border_size, cv2.BORDER_CONSTANT, value=background_color)
photo_boundaries = find_photo_boundaries(image, background_color, tolerance)
if not os.path.exists(output_directory):
os.makedirs(output_directory)
# Get the input file's base name without the extension
input_file_basename = os.path.splitext(os.path.basename(input_file))[0]
for idx, (x, y, w, h) in enumerate(photo_boundaries):
cropped_image = image[y:y+h, x:x+w]
cropped_image = auto_rotate(cropped_image, angle_threshold)
# Remove the added border
cropped_image = cropped_image[border_size:-border_size, border_size:-border_size]
output_path = os.path.join(output_directory, f"{input_file_basename}_{idx+1}.png")
cv2.imwrite(output_path, cropped_image)
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)
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)
-1
View File
@@ -1 +0,0 @@
rootProject.name = 'S-PDF'
@@ -1,96 +0,0 @@
package stirling.software.SPDF;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class LibreOfficeListener {
private static final long ACTIVITY_TIMEOUT = 20 * 60 * 1000; // 20 minutes
private static final LibreOfficeListener INSTANCE = new LibreOfficeListener();
private static final int LISTENER_PORT = 2002;
public static LibreOfficeListener getInstance() {
return INSTANCE;
}
private ExecutorService executorService;
private long lastActivityTime;
private Process process;
private LibreOfficeListener() {
}
private boolean isListenerRunning() {
try {
System.out.println("waiting for listener to start");
Socket socket = new Socket();
socket.connect(new InetSocketAddress("localhost", 2002), 1000); // Timeout after 1 second
socket.close();
return true;
} catch (IOException e) {
return false;
}
}
public void start() throws IOException {
// Check if the listener is already running
if (process != null && process.isAlive()) {
return;
}
// Start the listener process
process = Runtime.getRuntime().exec("unoconv --listener");
lastActivityTime = System.currentTimeMillis();
// Start a background thread to monitor the activity timeout
executorService = Executors.newSingleThreadExecutor();
executorService.submit(() -> {
while (true) {
long idleTime = System.currentTimeMillis() - lastActivityTime;
if (idleTime >= ACTIVITY_TIMEOUT) {
// If there has been no activity for too long, tear down the listener
process.destroy();
break;
}
try {
Thread.sleep(5000); // Check for inactivity every 5 seconds
} catch (InterruptedException e) {
break;
}
}
});
// Wait for the listener to start up
long startTime = System.currentTimeMillis();
long timeout = 30000; // Timeout after 30 seconds
while (System.currentTimeMillis() - startTime < timeout) {
if (isListenerRunning()) {
lastActivityTime = System.currentTimeMillis();
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // Check every 1 second
}
}
public synchronized void stop() {
// Stop the activity timeout monitor thread
executorService.shutdownNow();
// Stop the listener process
if (process != null && process.isAlive()) {
process.destroy();
}
}
}
@@ -1,11 +0,0 @@
package stirling.software.SPDF;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SPdfApplication {
public static void main(String[] args) {
SpringApplication.run(SPdfApplication.class, args);
}
}
@@ -1,42 +0,0 @@
package stirling.software.SPDF.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean(name = "appName")
public String appName() {
String appName = System.getProperty("APP_HOME_NAME");
if (appName == null)
appName = System.getenv("APP_HOME_NAME");
return (appName != null) ? appName : "Stirling PDF";
}
@Bean(name = "appVersion")
public String appVersion() {
String version = getClass().getPackage().getImplementationVersion();
return (version != null) ? version : "0.3.3";
}
@Bean(name = "homeText")
public String homeText() {
String homeText = System.getProperty("APP_HOME_DESCRIPTION");
if (homeText == null)
homeText = System.getenv("APP_HOME_DESCRIPTION");
return (homeText != null) ? homeText : "null";
}
@Bean(name = "navBarText")
public String navBarText() {
String navBarText = System.getProperty("APP_NAVBAR_NAME");
if (navBarText == null)
navBarText = System.getenv("APP_NAVBAR_NAME");
if (navBarText == null)
navBarText = System.getProperty("APP_HOME_NAME");
if (navBarText == null)
navBarText = System.getenv("APP_HOME_NAME");
return (navBarText != null) ? navBarText : "Stirling PDF";
}
}
@@ -1,53 +0,0 @@
package stirling.software.SPDF.config;
import java.util.Locale;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
@Configuration
public class Beans implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
registry.addInterceptor(new CleanUrlInterceptor());
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
String appLocaleEnv = System.getProperty("APP_LOCALE");
if (appLocaleEnv == null)
appLocaleEnv = System.getenv("APP_LOCALE");
Locale defaultLocale = Locale.UK; // Fallback to UK locale if environment variable is not set
if (appLocaleEnv != null && !appLocaleEnv.isEmpty()) {
Locale tempLocale = Locale.forLanguageTag(appLocaleEnv);
String 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.");
}
}
slr.setDefaultLocale(defaultLocale);
return slr;
}
}
@@ -1,45 +0,0 @@
package stirling.software.SPDF.config;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class CleanUrlInterceptor implements HandlerInterceptor {
private static final Pattern LANG_PATTERN = Pattern.compile("&?lang=([^&]+)");
@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) : "";
// Check if there are any other query parameters besides the lang parameter
String remainingQueryString = queryString.replaceAll(LANG_PATTERN.pattern(), "").replaceAll("&+", "&").replaceAll("^&|&$", "");
if (!remainingQueryString.isEmpty()) {
// Redirect to the URL without other query parameters
String redirectUrl = requestURI + (langQueryString.isEmpty() ? "" : "?" + langQueryString);
response.sendRedirect(redirectUrl);
return false;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
}
}
@@ -1,20 +0,0 @@
package stirling.software.SPDF.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI().components(new Components()).info(
new Info().title("Your API Title").version("1.0.0").description("Your API Description").license(new License().name("Your License Name").url("Your License URL")));
}
}
@@ -1,69 +0,0 @@
package stirling.software.SPDF.controller.api;
import java.io.IOException;
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.PDPageTree;
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 stirling.software.SPDF.utils.PdfUtils;
@RestController
public class MergeController {
private static final Logger logger = LoggerFactory.getLogger(MergeController.class);
private PDDocument mergeDocuments(List<PDDocument> documents) throws IOException {
// Create a new empty document
PDDocument mergedDoc = new PDDocument();
// Iterate over the list of documents and add their pages to the merged document
for (PDDocument doc : documents) {
// Get all pages from the current document
PDPageTree pages = doc.getPages();
// Iterate over the pages and add them to the merged document
for (PDPage page : pages) {
mergedDoc.addPage(page);
}
}
// Return the merged document
return mergedDoc;
}
@PostMapping(consumes = "multipart/form-data", value = "/merge-pdfs")
public ResponseEntity<byte[]> mergePdfs(@RequestPart(required = true, value = "fileInput") MultipartFile[] files) throws IOException {
// Read the input PDF files into PDDocument objects
List<PDDocument> documents = new ArrayList<>();
// Loop through the files array and read each file into a PDDocument
for (MultipartFile file : files) {
documents.add(PDDocument.load(file.getInputStream()));
}
PDDocument mergedDoc = mergeDocuments(documents);
// Return the merged PDF as a response
ResponseEntity<byte[]> response = PdfUtils.pdfDocToWebResponse(mergedDoc, files[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_merged.pdf");
for (PDDocument doc : documents) {
// Close the document after processing
doc.close();
}
return response;
}
}
@@ -1,109 +0,0 @@
package stirling.software.SPDF.controller.api;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PdfUtils;
@RestController
public class RearrangePagesPDFController {
private static final Logger logger = LoggerFactory.getLogger(RearrangePagesPDFController.class);
@PostMapping(consumes = "multipart/form-data", value = "/remove-pages")
public ResponseEntity<byte[]> deletePages(@RequestPart(required = true, value = "fileInput") MultipartFile pdfFile, @RequestParam("pagesToDelete") String pagesToDelete)
throws IOException {
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(",");
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 PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_removed_pages.pdf");
}
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);
}
}
return newPageOrder;
}
@PostMapping(consumes = "multipart/form-data", value = "/rearrange-pages")
public ResponseEntity<byte[]> rearrangePages(@RequestPart(required = true, value = "fileInput") MultipartFile pdfFile, @RequestParam("pageOrder") String pageOrder) {
try {
// Load the input PDF
PDDocument document = PDDocument.load(pdfFile.getInputStream());
// 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();
List<Integer> newPageOrder = pageOrderToString(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 PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_rearranged.pdf");
} catch (IOException e) {
logger.error("Failed rearranging documents", e);
return null;
}
}
}
@@ -1,41 +0,0 @@
package stirling.software.SPDF.controller.api;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageTree;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PdfUtils;
@RestController
public class RotationController {
private static final Logger logger = LoggerFactory.getLogger(RotationController.class);
@PostMapping(consumes = "multipart/form-data", value = "/rotate-pdf")
public ResponseEntity<byte[]> rotatePDF(@RequestPart(required = true, value = "fileInput") MultipartFile pdfFile, @RequestParam("angle") Integer angle) throws IOException {
// Load the PDF document
PDDocument document = PDDocument.load(pdfFile.getBytes());
// Get the list of pages in the document
PDPageTree pages = document.getPages();
for (PDPage page : pages) {
page.setRotation(page.getRotation() + angle);
}
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_rotated.pdf");
}
}
@@ -1,129 +0,0 @@
package stirling.software.SPDF.controller.api;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
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;
import java.util.zip.ZipOutputStream;
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;
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.multipart.MultipartFile;
@RestController
public class SplitPDFController {
private static final Logger logger = LoggerFactory.getLogger(SplitPDFController.class);
@PostMapping(consumes = "multipart/form-data", value = "/split-pages")
public ResponseEntity<Resource> splitPdf(@RequestPart(required = true, value = "fileInput") MultipartFile file, @RequestParam("pages") String pages) throws IOException {
// parse user input
// open the pdf document
InputStream inputStream = file.getInputStream();
PDDocument document = PDDocument.load(inputStream);
List<Integer> pageNumbers = new ArrayList<>();
pages = pages.replaceAll("\\s+", ""); // remove whitespaces
if (pages.toLowerCase().equals("all")) {
for (int i = 0; i < document.getNumberOfPages(); i++) {
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));
}
}
}
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) {
try (PDDocument splitDocument = new PDDocument()) {
for (int i = currentPage; i < pageNumber; 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);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
splitDocument.save(baos);
splitDocumentsBoas.add(baos);
} catch (Exception e) {
logger.error("Failed splitting documents and saving them", e);
throw e;
}
}
// closing the original document
document.close();
Path zipFile = Files.createTempFile("split_documents", ".zip");
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";
ByteArrayOutputStream baos = splitDocumentsBoas.get(i);
byte[] pdf = baos.toByteArray();
// Add PDF file to the zip
ZipEntry pdfEntry = new ZipEntry(fileName);
zipOut.putNextEntry(pdfEntry);
zipOut.write(pdf);
zipOut.closeEntry();
logger.info("Wrote split document {} to zip file", fileName);
}
} catch (Exception e) {
logger.error("Failed writing to zip", e);
throw e;
}
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);
}
}
@@ -1,86 +0,0 @@
package stirling.software.SPDF.controller.api.converters;
import java.io.IOException;
import org.apache.pdfbox.rendering.ImageType;
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.HttpStatus;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PdfUtils;
@RestController
public class ConvertImgPDFController {
private static final Logger logger = LoggerFactory.getLogger(ConvertImgPDFController.class);
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-img")
public ResponseEntity<Resource> convertToImage(@RequestPart(required = true, value = "fileInput") MultipartFile file, @RequestParam("imageFormat") String imageFormat,
@RequestParam("singleOrMultiple") String singleOrMultiple, @RequestParam("colorType") String colorType, @RequestParam("dpi") String dpi) throws IOException {
byte[] pdfBytes = file.getBytes();
ImageType colorTypeResult = ImageType.RGB;
if ("greyscale".equals(colorType)) {
colorTypeResult = ImageType.GRAY;
} else if ("blackwhite".equals(colorType)) {
colorTypeResult = ImageType.BINARY;
}
// returns bytes for image
boolean singleImage = singleOrMultiple.equals("single");
byte[] result = null;
try {
result = PdfUtils.convertFromPdf(pdfBytes, imageFormat.toUpperCase(), colorTypeResult, singleImage, Integer.valueOf(dpi));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (singleImage) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(getMediaType(imageFormat)));
ResponseEntity<Resource> response = new ResponseEntity<>(new ByteArrayResource(result), headers, HttpStatus.OK);
return response;
} else {
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")
.contentType(MediaType.APPLICATION_OCTET_STREAM).contentLength(resource.contentLength()).body(resource);
}
}
@PostMapping(consumes = "multipart/form-data", value = "/img-to-pdf")
public ResponseEntity<byte[]> convertToPdf(@RequestPart(required = true, value = "fileInput") MultipartFile[] file,
@RequestParam(defaultValue = "false", name = "stretchToFit") boolean stretchToFit, @RequestParam(defaultValue = "true", name = "autoRotate") boolean autoRotate)
throws IOException {
// Convert the file to PDF and get the resulting bytes
System.out.println(stretchToFit);
byte[] bytes = PdfUtils.imageToPdf(file, stretchToFit, autoRotate);
return PdfUtils.bytesToWebResponse(bytes, file[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_coverted.pdf");
}
private String getMediaType(String imageFormat) {
if (imageFormat.equalsIgnoreCase("PNG"))
return "image/png";
else if (imageFormat.equalsIgnoreCase("JPEG") || imageFormat.equalsIgnoreCase("JPG"))
return "image/jpeg";
else if (imageFormat.equalsIgnoreCase("GIF"))
return "image/gif";
else
return "application/octet-stream";
}
}
@@ -1,66 +0,0 @@
package stirling.software.SPDF.controller.api.converters;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.io.FilenameUtils;
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 stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.ProcessExecutor;
@RestController
public class ConvertOfficeController {
public byte[] convertToPdf(MultipartFile inputFile) throws IOException, InterruptedException {
// Check for valid file extension
String originalFilename = inputFile.getOriginalFilename();
if (originalFilename == null || !isValidFileExtension(FilenameUtils.getExtension(originalFilename))) {
throw new IllegalArgumentException("Invalid file extension");
}
// Save the uploaded file to a temporary location
Path tempInputFile = Files.createTempFile("input_", "." + FilenameUtils.getExtension(originalFilename));
Files.copy(inputFile.getInputStream(), tempInputFile, StandardCopyOption.REPLACE_EXISTING);
// Prepare the output file path
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
// Run the LibreOffice command
List<String> command = new ArrayList<>(Arrays.asList("unoconv", "-vvv", "-f", "pdf", "-o", tempOutputFile.toString(), tempInputFile.toString()));
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE).runCommandWithOutputHandling(command);
// Read the converted PDF file
byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
// Clean up the temporary files
Files.delete(tempInputFile);
Files.delete(tempOutputFile);
return pdfBytes;
}
private boolean isValidFileExtension(String fileExtension) {
String extensionPattern = "^(?i)[a-z0-9]{2,4}$";
return fileExtension.matches(extensionPattern);
}
@PostMapping(consumes = "multipart/form-data", value = "/file-to-pdf")
public ResponseEntity<byte[]> processPdfWithOCR(@RequestPart(required = true, value = "fileInput") MultipartFile inputFile) throws IOException, InterruptedException {
// unused but can start server instance if startup time is to long
// LibreOfficeListener.getInstance().start();
byte[] pdfByteArray = convertToPdf(inputFile);
return PdfUtils.bytesToWebResponse(pdfByteArray, inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_convertedToPDF.pdf");
}
}
@@ -1,52 +0,0 @@
package stirling.software.SPDF.controller.api.converters;
import java.io.IOException;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PDFToFile;
@RestController
public class ConvertPDFToOffice {
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-html")
public ResponseEntity<byte[]> processPdfToHTML(@RequestPart(required = true, value = "fileInput") MultipartFile inputFile) throws IOException, InterruptedException {
PDFToFile pdfToFile = new PDFToFile();
return pdfToFile.processPdfToOfficeFormat(inputFile, "html", "writer_pdf_import");
}
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-presentation")
public ResponseEntity<byte[]> processPdfToPresentation(@RequestPart(required = true, value = "fileInput") MultipartFile inputFile,
@RequestParam("outputFormat") String outputFormat) throws IOException, InterruptedException {
PDFToFile pdfToFile = new PDFToFile();
return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "impress_pdf_import");
}
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-text")
public ResponseEntity<byte[]> processPdfToRTForTXT(@RequestPart(required = true, value = "fileInput") MultipartFile inputFile,
@RequestParam("outputFormat") String outputFormat) throws IOException, InterruptedException {
PDFToFile pdfToFile = new PDFToFile();
return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "writer_pdf_import");
}
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-word")
public ResponseEntity<byte[]> processPdfToWord(@RequestPart(required = true, value = "fileInput") MultipartFile inputFile, @RequestParam("outputFormat") String outputFormat)
throws IOException, InterruptedException {
PDFToFile pdfToFile = new PDFToFile();
return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "writer_pdf_import");
}
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-xml")
public ResponseEntity<byte[]> processPdfToXML(@RequestPart(required = true, value = "fileInput") MultipartFile inputFile) throws IOException, InterruptedException {
PDFToFile pdfToFile = new PDFToFile();
return pdfToFile.processPdfToOfficeFormat(inputFile, "xml", "writer_pdf_import");
}
}
@@ -1,55 +0,0 @@
package stirling.software.SPDF.controller.api.converters;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
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 stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.ProcessExecutor;
@RestController
public class ConvertPDFToPDFA {
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-pdfa")
public ResponseEntity<byte[]> pdfToPdfA(@RequestPart(required = true, value = "fileInput") MultipartFile inputFile) throws IOException, InterruptedException {
// Save the uploaded file to a temporary location
Path tempInputFile = Files.createTempFile("input_", ".pdf");
inputFile.transferTo(tempInputFile.toFile());
// Prepare the output file path
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
// Prepare the OCRmyPDF command
List<String> command = new ArrayList<>();
command.add("ocrmypdf");
command.add("--skip-text");
command.add("--tesseract-timeout=0");
command.add("--output-type");
command.add("pdfa");
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.OCR_MY_PDF).runCommandWithOutputHandling(command);
// Read the optimized PDF file
byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
// Clean up the temporary files
Files.delete(tempInputFile);
Files.delete(tempOutputFile);
// Return the optimized PDF as a response
String outputFilename = inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_PDFA.pdf";
return PdfUtils.bytesToWebResponse(pdfBytes, outputFilename);
}
}
@@ -1,76 +0,0 @@
package stirling.software.SPDF.controller.api.other;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.ProcessExecutor;
@RestController
public class CompressController {
private static final Logger logger = LoggerFactory.getLogger(CompressController.class);
@PostMapping(consumes = "multipart/form-data", value = "/compress-pdf")
public ResponseEntity<byte[]> optimizePdf(@RequestPart(required = true, value = "fileInput") MultipartFile inputFile, @RequestParam("optimizeLevel") int optimizeLevel,
@RequestParam(name = "fastWebView", required = false) Boolean fastWebView, @RequestParam(name = "jbig2Lossy", required = false) Boolean jbig2Lossy)
throws IOException, InterruptedException {
// Save the uploaded file to a temporary location
Path tempInputFile = Files.createTempFile("input_", ".pdf");
inputFile.transferTo(tempInputFile.toFile());
// Prepare the output file path
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
// Prepare the OCRmyPDF command
List<String> command = new ArrayList<>();
command.add("ocrmypdf");
command.add("--skip-text");
command.add("--tesseract-timeout=0");
command.add("--optimize");
command.add(String.valueOf(optimizeLevel));
command.add("--output-type");
command.add("pdf");
if (fastWebView != null && fastWebView) {
long fileSize = inputFile.getSize();
long fastWebViewSize = (long) (fileSize * 1.25); // 25% higher than file size
command.add("--fast-web-view");
command.add(String.valueOf(fastWebViewSize));
}
if (jbig2Lossy != null && jbig2Lossy) {
command.add("--jbig2-lossy");
}
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.OCR_MY_PDF).runCommandWithOutputHandling(command);
// Read the optimized PDF file
byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
// Clean up the temporary files
Files.delete(tempInputFile);
Files.delete(tempOutputFile);
// Return the optimized PDF as a response
String outputFilename = inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_Optimized.pdf";
return PdfUtils.bytesToWebResponse(pdfBytes, outputFilename);
}
}
@@ -1,130 +0,0 @@
package stirling.software.SPDF.controller.api.other;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.imageio.ImageIO;
import org.apache.commons.io.FileUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.ProcessExecutor;
@RestController
public class ExtractImageScansController {
private static final Logger logger = LoggerFactory.getLogger(ExtractImageScansController.class);
@PostMapping(consumes = "multipart/form-data", value = "/extract-image-scans")
public ResponseEntity<byte[]> extractImageScans(@RequestPart(required = true, value = "fileInput") MultipartFile inputFile,
@RequestParam(name = "angle_threshold", defaultValue = "5") int angleThreshold, @RequestParam(name = "tolerance", defaultValue = "20") int tolerance,
@RequestParam(name = "min_area", defaultValue = "8000") int minArea, @RequestParam(name = "min_contour_area", defaultValue = "500") int minContourArea,
@RequestParam(name = "border_size", defaultValue = "1") int borderSize) throws IOException, InterruptedException {
String fileName = inputFile.getOriginalFilename();
String extension = fileName.substring(fileName.lastIndexOf(".") + 1);
List<String> images = new ArrayList<>();
// Check if input file is a PDF
if (extension.equalsIgnoreCase("pdf")) {
// Load PDF document
try (PDDocument document = PDDocument.load(new ByteArrayInputStream(inputFile.getBytes()))) {
PDFRenderer pdfRenderer = new PDFRenderer(document);
int pageCount = document.getNumberOfPages();
images = new ArrayList<>();
// Create images of all pages
for (int i = 0; i < pageCount; i++) {
// Create temp file to save the image
Path tempFile = Files.createTempFile("image_", ".png");
// Render image and save as temp file
BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300);
ImageIO.write(image, "png", tempFile.toFile());
// Add temp file path to images list
images.add(tempFile.toString());
}
}
} else {
Path tempInputFile = Files.createTempFile("input_", "." + extension);
Files.copy(inputFile.getInputStream(), tempInputFile, StandardCopyOption.REPLACE_EXISTING);
// Add input file path to images list
images.add(tempInputFile.toString());
}
List<byte[]> processedImageBytes = new ArrayList<>();
// Process each image
for (int i = 0; i < images.size(); i++) {
Path tempDir = Files.createTempDirectory("openCV_output");
List<String> command = new ArrayList<>(Arrays.asList("python3", "/scripts/split_photos.py", images.get(i), tempDir.toString(), String.valueOf(angleThreshold),
String.valueOf(tolerance), String.valueOf(minArea), String.valueOf(minContourArea), String.valueOf(borderSize)));
// Run CLI command
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV).runCommandWithOutputHandling(command);
// Read the output photos in temp directory
List<Path> tempOutputFiles = Files.list(tempDir).sorted().collect(Collectors.toList());
for (Path tempOutputFile : tempOutputFiles) {
byte[] imageBytes = Files.readAllBytes(tempOutputFile);
processedImageBytes.add(imageBytes);
}
// Clean up the temporary directory
FileUtils.deleteDirectory(tempDir.toFile());
}
// Create zip file if multiple images
if (processedImageBytes.size() > 1) {
String outputZipFilename = fileName.replaceFirst("[.][^.]+$", "") + "_processed.zip";
Path tempZipFile = Files.createTempFile("output_", ".zip");
try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(tempZipFile.toFile()))) {
// Add processed images to the zip
for (int i = 0; i < processedImageBytes.size(); i++) {
ZipEntry entry = new ZipEntry(fileName.replaceFirst("[.][^.]+$", "") + "_" + (i + 1) + ".png");
zipOut.putNextEntry(entry);
zipOut.write(processedImageBytes.get(i));
zipOut.closeEntry();
}
}
byte[] zipBytes = Files.readAllBytes(tempZipFile);
// Clean up the temporary zip file
Files.delete(tempZipFile);
return PdfUtils.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);
}
}
}
@@ -1,102 +0,0 @@
package stirling.software.SPDF.controller.api.other;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.imageio.ImageIO;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PdfUtils;
@RestController
public class ExtractImagesController {
private static final Logger logger = LoggerFactory.getLogger(ExtractImagesController.class);
@PostMapping(consumes = "multipart/form-data", value = "/extract-images")
public ResponseEntity<byte[]> extractImages(@RequestPart(required = true, value = "fileInput") MultipartFile file, @RequestParam("format") String format) throws IOException {
System.out.println(System.currentTimeMillis() + "file=" + file.getName() + ", format=" + format);
PDDocument document = PDDocument.load(file.getBytes());
// Create ByteArrayOutputStream to write zip file to byte array
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Create ZipOutputStream to create zip file
ZipOutputStream zos = new ZipOutputStream(baos);
// Set compression level
zos.setLevel(Deflater.BEST_COMPRESSION);
int imageIndex = 1;
int pageNum = 1;
// Iterate over each page
for (PDPage page : document.getPages()) {
++pageNum;
// Extract images from page
for (COSName name : page.getResources().getXObjectNames()) {
if (page.getResources().isImageXObject(name)) {
PDImageXObject image = (PDImageXObject) page.getResources().getXObject(name);
// Convert image to desired format
RenderedImage renderedImage = image.getImage();
BufferedImage bufferedImage = null;
if (format.equalsIgnoreCase("png")) {
bufferedImage = new BufferedImage(renderedImage.getWidth(), renderedImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
} else if (format.equalsIgnoreCase("jpeg") || format.equalsIgnoreCase("jpg")) {
bufferedImage = new BufferedImage(renderedImage.getWidth(), renderedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
} else if (format.equalsIgnoreCase("gif")) {
bufferedImage = new BufferedImage(renderedImage.getWidth(), renderedImage.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);
}
// Write image to zip file
String imageName = "Image " + imageIndex + " (Page " + pageNum + ")." + format;
ZipEntry zipEntry = new ZipEntry(imageName);
zos.putNextEntry(zipEntry);
Graphics2D g = bufferedImage.createGraphics();
g.drawImage((Image) renderedImage, 0, 0, null);
g.dispose();
// Write image bytes to zip file
ByteArrayOutputStream imageBaos = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, format, imageBaos);
zos.write(imageBaos.toByteArray());
zos.closeEntry();
imageIndex++;
}
}
}
// Close ZipOutputStream and PDDocument
zos.close();
document.close();
// Create ByteArrayResource from byte array
byte[] zipContents = baos.toByteArray();
return PdfUtils.boasToWebResponse(baos, file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_extracted-images.zip", MediaType.APPLICATION_OCTET_STREAM);
}
}
@@ -1,132 +0,0 @@
package stirling.software.SPDF.controller.api.other;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PdfUtils;
@RestController
public class MetadataController {
private String checkUndefined(String entry) {
// Check if the string is "undefined"
if ("undefined".equals(entry)) {
// Return null if it is
return null;
}
// Return the original string if it's not "undefined"
return entry;
}
@PostMapping(consumes = "multipart/form-data", value = "/update-metadata")
public ResponseEntity<byte[]> metadata(@RequestPart(required = true, value = "fileInput") MultipartFile pdfFile,
@RequestParam(value = "deleteAll", required = false, defaultValue = "false") Boolean deleteAll, @RequestParam(value = "author", required = false) String author,
@RequestParam(value = "creationDate", required = false) String creationDate, @RequestParam(value = "creator", required = false) String creator,
@RequestParam(value = "keywords", required = false) String keywords, @RequestParam(value = "modificationDate", required = false) String modificationDate,
@RequestParam(value = "producer", required = false) String producer, @RequestParam(value = "subject", required = false) String subject,
@RequestParam(value = "title", required = false) String title, @RequestParam(value = "trapped", required = false) String trapped,
@RequestParam Map<String, String> allRequestParams) throws IOException {
// Load the PDF file into a PDDocument
PDDocument document = PDDocument.load(pdfFile.getBytes());
// Get the document information from the PDF
PDDocumentInformation info = document.getDocumentInformation();
// Check if each metadata value is "undefined" and set it to null if it is
author = checkUndefined(author);
creationDate = checkUndefined(creationDate);
creator = checkUndefined(creator);
keywords = checkUndefined(keywords);
modificationDate = checkUndefined(modificationDate);
producer = checkUndefined(producer);
subject = checkUndefined(subject);
title = checkUndefined(title);
trapped = checkUndefined(trapped);
// If the "deleteAll" flag is set, remove all metadata from the document
// information
if (deleteAll) {
for (String key : info.getMetadataKeys()) {
info.setCustomMetadataValue(key, null);
}
// Remove metadata from the PDF history
document.getDocumentCatalog().getCOSObject().removeItem(COSName.getPDFName("Metadata"));
document.getDocumentCatalog().getCOSObject().removeItem(COSName.getPDFName("PieceInfo"));
author = null;
creationDate = null;
creator = null;
keywords = null;
modificationDate = null;
producer = null;
subject = null;
title = null;
trapped = null;
} else {
// Iterate through the request parameters and set the metadata values
for (Entry<String, String> entry : allRequestParams.entrySet()) {
String key = entry.getKey();
// Check if the key is a standard metadata key
if (!key.equalsIgnoreCase("Author") && !key.equalsIgnoreCase("CreationDate") && !key.equalsIgnoreCase("Creator") && !key.equalsIgnoreCase("Keywords")
&& !key.equalsIgnoreCase("modificationDate") && !key.equalsIgnoreCase("Producer") && !key.equalsIgnoreCase("Subject") && !key.equalsIgnoreCase("Title")
&& !key.equalsIgnoreCase("Trapped") && !key.contains("customKey") && !key.contains("customValue")) {
info.setCustomMetadataValue(key, entry.getValue());
} else if (key.contains("customKey")) {
int number = Integer.parseInt(key.replaceAll("\\D", ""));
String customKey = entry.getValue();
String customValue = allRequestParams.get("customValue" + number);
info.setCustomMetadataValue(customKey, customValue);
}
}
}
if (creationDate != null && creationDate.length() > 0) {
Calendar creationDateCal = Calendar.getInstance();
try {
creationDateCal.setTime(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(creationDate));
} catch (ParseException e) {
e.printStackTrace();
}
info.setCreationDate(creationDateCal);
} else {
info.setCreationDate(null);
}
if (modificationDate != null && modificationDate.length() > 0) {
Calendar modificationDateCal = Calendar.getInstance();
try {
modificationDateCal.setTime(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(modificationDate));
} catch (ParseException e) {
e.printStackTrace();
}
info.setModificationDate(modificationDateCal);
} else {
info.setModificationDate(null);
}
info.setCreator(creator);
info.setKeywords(keywords);
info.setAuthor(author);
info.setProducer(producer);
info.setSubject(subject);
info.setTitle(title);
info.setTrapped(trapped);
document.setDocumentInformation(info);
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_metadata.pdf");
}
}
@@ -1,175 +0,0 @@
package stirling.software.SPDF.controller.api.other;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.ProcessExecutor;
@RestController
public class OCRController {
private static final Logger logger = LoggerFactory.getLogger(OCRController.class);
public List<String> getAvailableTesseractLanguages() {
String tessdataDir = "/usr/share/tesseract-ocr/4.00/tessdata";
File[] files = new File(tessdataDir).listFiles();
if (files == null) {
return Collections.emptyList();
}
return Arrays.stream(files).filter(file -> file.getName().endsWith(".traineddata")).map(file -> file.getName().replace(".traineddata", ""))
.filter(lang -> !lang.equalsIgnoreCase("osd")).collect(Collectors.toList());
}
@PostMapping(consumes = "multipart/form-data", value = "/ocr-pdf")
public ResponseEntity<byte[]> processPdfWithOCR(@RequestPart(required = true, value = "fileInput") MultipartFile inputFile,
@RequestParam("languages") List<String> selectedLanguages, @RequestParam(name = "sidecar", required = false) Boolean sidecar,
@RequestParam(name = "deskew", required = false) Boolean deskew, @RequestParam(name = "clean", required = false) Boolean clean,
@RequestParam(name = "clean-final", required = false) Boolean cleanFinal, @RequestParam(name = "ocrType", required = false) String ocrType,
@RequestParam(name = "ocrRenderType", required = false, defaultValue = "hocr") String ocrRenderType,
@RequestParam(name = "removeImagesAfter", required = false) Boolean removeImagesAfter)
throws IOException, InterruptedException {
// --output-type pdfa
if (selectedLanguages == null || selectedLanguages.isEmpty()) {
throw new IOException("Please select at least one language.");
}
if(!ocrRenderType.equals("hocr") && !ocrRenderType.equals("sandwich")) {
throw new IOException("ocrRenderType wrong");
}
// Get available Tesseract languages
List<String> availableLanguages = getAvailableTesseractLanguages();
// Validate selected languages
selectedLanguages = selectedLanguages.stream().filter(availableLanguages::contains).toList();
if (selectedLanguages.isEmpty()) {
throw new IOException("None of the selected languages are valid.");
}
// Save the uploaded file to a temporary location
Path tempInputFile = Files.createTempFile("input_", ".pdf");
Files.copy(inputFile.getInputStream(), tempInputFile, StandardCopyOption.REPLACE_EXISTING);
// Prepare the output file path
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
// Prepare the output file path
Path sidecarTextPath = null;
// Run OCR Command
String languageOption = String.join("+", selectedLanguages);
List<String> command = new ArrayList<>(Arrays.asList("ocrmypdf", "--verbose", "2", "--output-type", "pdf", "--pdf-renderer" , ocrRenderType));
if (sidecar != null && sidecar) {
sidecarTextPath = Files.createTempFile("sidecar", ".txt");
command.add("--sidecar");
command.add(sidecarTextPath.toString());
}
if (deskew != null && deskew) {
command.add("--deskew");
}
if (clean != null && clean) {
command.add("--clean");
}
if (cleanFinal != null && cleanFinal) {
command.add("--clean-final");
}
if (ocrType != null && !ocrType.equals("")) {
if ("skip-text".equals(ocrType)) {
command.add("--skip-text");
} else if ("force-ocr".equals(ocrType)) {
command.add("--force-ocr");
} else if ("Normal".equals(ocrType)) {
}
}
command.addAll(Arrays.asList("--language", languageOption, tempInputFile.toString(), tempOutputFile.toString()));
// Run CLI command
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.OCR_MY_PDF).runCommandWithOutputHandling(command);
// Remove images from the OCR processed PDF if the flag is set to true
if (removeImagesAfter != null && removeImagesAfter) {
Path tempPdfWithoutImages = Files.createTempFile("output_", "_no_images.pdf");
List<String> gsCommand = Arrays.asList("gs", "-sDEVICE=pdfwrite", "-dFILTERIMAGE", "-o", tempPdfWithoutImages.toString(), tempOutputFile.toString());
int gsReturnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT).runCommandWithOutputHandling(gsCommand);
tempOutputFile = tempPdfWithoutImages;
}
// Read the OCR processed PDF file
byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
// Clean up the temporary files
Files.delete(tempInputFile);
// Return the OCR processed PDF as a response
String outputFilename = inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_OCR.pdf";
if (sidecar != null && sidecar) {
// Create a zip file containing both the PDF and the text file
String outputZipFilename = inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_OCR.zip";
Path tempZipFile = Files.createTempFile("output_", ".zip");
try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(tempZipFile.toFile()))) {
// Add PDF file to the zip
ZipEntry pdfEntry = new ZipEntry(outputFilename);
zipOut.putNextEntry(pdfEntry);
Files.copy(tempOutputFile, zipOut);
zipOut.closeEntry();
// Add text file to the zip
ZipEntry txtEntry = new ZipEntry(outputFilename.replace(".pdf", ".txt"));
zipOut.putNextEntry(txtEntry);
Files.copy(sidecarTextPath, zipOut);
zipOut.closeEntry();
}
byte[] zipBytes = Files.readAllBytes(tempZipFile);
// Clean up the temporary zip file
Files.delete(tempZipFile);
Files.delete(tempOutputFile);
Files.delete(sidecarTextPath);
// Return the zip file containing both the PDF and the text file
return PdfUtils.bytesToWebResponse(pdfBytes, outputZipFilename, MediaType.APPLICATION_OCTET_STREAM);
} else {
// Return the OCR processed PDF as a response
Files.delete(tempOutputFile);
return PdfUtils.bytesToWebResponse(pdfBytes, outputFilename);
}
}
}
@@ -1,36 +0,0 @@
package stirling.software.SPDF.controller.api.other;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PdfUtils;
@RestController
public class OverlayImageController {
private static final Logger logger = LoggerFactory.getLogger(OverlayImageController.class);
@PostMapping(consumes = "multipart/form-data", value = "/add-image")
public ResponseEntity<byte[]> overlayImage(@RequestPart(required = true, value = "fileInput") MultipartFile pdfFile, @RequestParam("fileInput2") MultipartFile imageFile,
@RequestParam("x") float x, @RequestParam("y") float y, @RequestParam("everyPage") boolean everyPage) {
try {
byte[] pdfBytes = pdfFile.getBytes();
byte[] imageBytes = imageFile.getBytes();
byte[] result = PdfUtils.overlayImage(pdfBytes, imageBytes, x, y, everyPage);
return PdfUtils.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);
}
}
}
@@ -1,66 +0,0 @@
package stirling.software.SPDF.controller.api.security;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PdfUtils;
@RestController
public class PasswordController {
private static final Logger logger = LoggerFactory.getLogger(PasswordController.class);
@PostMapping(consumes = "multipart/form-data", value = "/remove-password")
public ResponseEntity<byte[]> compressPDF(@RequestPart(required = true, value = "fileInput") MultipartFile fileInput, @RequestParam(name = "password") String password)
throws IOException {
PDDocument document = PDDocument.load(fileInput.getBytes(), password);
document.setAllSecurityToBeRemoved(true);
return PdfUtils.pdfDocToWebResponse(document, fileInput.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_password_removed.pdf");
}
@PostMapping(consumes = "multipart/form-data", value = "/add-password")
public ResponseEntity<byte[]> compressPDF(@RequestPart(required = true, value = "fileInput") MultipartFile fileInput,
@RequestParam(defaultValue = "", name = "password") String password, @RequestParam(defaultValue = "128", name = "keyLength") int keyLength,
@RequestParam(defaultValue = "false", name = "canAssembleDocument") boolean canAssembleDocument,
@RequestParam(defaultValue = "false", name = "canExtractContent") boolean canExtractContent,
@RequestParam(defaultValue = "false", name = "canExtractForAccessibility") boolean canExtractForAccessibility,
@RequestParam(defaultValue = "false", name = "canFillInForm") boolean canFillInForm, @RequestParam(defaultValue = "false", name = "canModify") boolean canModify,
@RequestParam(defaultValue = "false", name = "canModifyAnnotations") boolean canModifyAnnotations,
@RequestParam(defaultValue = "false", name = "canPrint") boolean canPrint, @RequestParam(defaultValue = "false", name = "canPrintFaithful") boolean canPrintFaithful)
throws IOException {
PDDocument document = PDDocument.load(fileInput.getBytes());
AccessPermission ap = new AccessPermission();
ap.setCanAssembleDocument(!canAssembleDocument);
ap.setCanExtractContent(!canExtractContent);
ap.setCanExtractForAccessibility(!canExtractForAccessibility);
ap.setCanFillInForm(!canFillInForm);
ap.setCanModify(!canModify);
ap.setCanModifyAnnotations(!canModifyAnnotations);
ap.setCanPrint(!canPrint);
ap.setCanPrintFaithful(!canPrintFaithful);
StandardProtectionPolicy spp = new StandardProtectionPolicy(password, password, ap);
spp.setEncryptionKeyLength(keyLength);
spp.setPermissions(ap);
document.protect(spp);
return PdfUtils.pdfDocToWebResponse(document, fileInput.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_passworded.pdf");
}
}
@@ -1,140 +0,0 @@
package stirling.software.SPDF.controller.api.security;
import java.awt.Color;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
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.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationMarkup;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
import org.apache.pdfbox.util.Matrix;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.WatermarkRemover;
@RestController
public class WatermarkController {
@PostMapping(consumes = "multipart/form-data", value = "/add-watermark")
public ResponseEntity<byte[]> addWatermark(@RequestPart(required = true, value = "fileInput") MultipartFile pdfFile, @RequestParam("watermarkText") String watermarkText,
@RequestParam(defaultValue = "30", name = "fontSize") float fontSize, @RequestParam(defaultValue = "0", name = "rotation") float rotation,
@RequestParam(defaultValue = "0.5", name = "opacity") float opacity, @RequestParam(defaultValue = "50", name = "widthSpacer") int widthSpacer,
@RequestParam(defaultValue = "50", name = "heightSpacer") int heightSpacer) throws IOException {
// Load the input PDF
PDDocument document = PDDocument.load(pdfFile.getInputStream());
// Create a page in the document
for (PDPage page : document.getPages()) {
// Get the page's content stream
PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true);
// Set transparency
PDExtendedGraphicsState graphicsState = new PDExtendedGraphicsState();
graphicsState.setNonStrokingAlphaConstant(opacity);
contentStream.setGraphicsStateParameters(graphicsState);
// Set font of watermark
PDFont font = PDType1Font.HELVETICA_BOLD;
contentStream.beginText();
contentStream.setFont(font, fontSize);
contentStream.setNonStrokingColor(Color.LIGHT_GRAY);
// Set size and location of watermark
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
float watermarkWidth = widthSpacer + font.getStringWidth(watermarkText) * fontSize / 1000;
float watermarkHeight = heightSpacer + fontSize;
int watermarkRows = (int) (pageHeight / watermarkHeight + 1);
int watermarkCols = (int) (pageWidth / watermarkWidth + 1);
// 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));
contentStream.showTextWithPositioning(new Object[] { watermarkText });
}
}
contentStream.endText();
// Close the content stream
contentStream.close();
}
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_watermarked.pdf");
}
@PostMapping(consumes = "multipart/form-data", value = "/remove-watermark")
public ResponseEntity<byte[]> removeWatermark(@RequestPart(required = true, value = "fileInput") MultipartFile pdfFile, @RequestParam("watermarkText") String watermarkText)
throws Exception {
// Load the input PDF
PDDocument document = PDDocument.load(pdfFile.getInputStream());
// Create a new PDF document for the output
PDDocument outputDocument = new PDDocument();
// Loop through the pages
int numPages = document.getNumberOfPages();
for (int i = 0; i < numPages; i++) {
PDPage page = document.getPage(i);
// Process the content stream to remove the watermark text
WatermarkRemover editor = new WatermarkRemover(watermarkText) {
};
editor.processPage(page);
editor.processPage(page);
// Add the page to the output document
outputDocument.addPage(page);
}
for (PDPage page : outputDocument.getPages()) {
List<PDAnnotation> annotations = page.getAnnotations();
List<PDAnnotation> annotationsToRemove = new ArrayList<>();
for (PDAnnotation annotation : annotations) {
if (annotation instanceof PDAnnotationMarkup) {
PDAnnotationMarkup markup = (PDAnnotationMarkup) annotation;
String contents = markup.getContents();
if (contents != null && contents.contains(watermarkText)) {
annotationsToRemove.add(markup);
}
}
}
annotations.removeAll(annotationsToRemove);
}
PDDocumentCatalog catalog = outputDocument.getDocumentCatalog();
PDAcroForm acroForm = catalog.getAcroForm();
if (acroForm != null) {
List<PDField> fields = acroForm.getFields();
for (PDField field : fields) {
String fieldValue = field.getValueAsString();
if (fieldValue.contains(watermarkText)) {
field.setValue(fieldValue.replace(watermarkText, ""));
}
}
}
return PdfUtils.pdfDocToWebResponse(outputDocument, "removed.pdf");
}
}
@@ -1,86 +0,0 @@
package stirling.software.SPDF.controller.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
import io.swagger.v3.oas.annotations.Hidden;
@Controller
public class ConverterWebController {
@GetMapping("/img-to-pdf")
@Hidden
public String convertImgToPdfForm(Model model) {
model.addAttribute("currentPage", "img-to-pdf");
return "convert/img-to-pdf";
}
@GetMapping("/pdf-to-img")
@Hidden
public String pdfToimgForm(Model model) {
model.addAttribute("currentPage", "pdf-to-img");
return "convert/pdf-to-img";
}
@GetMapping("/file-to-pdf")
@Hidden
public String convertToPdfForm(Model model) {
model.addAttribute("currentPage", "file-to-pdf");
return "convert/file-to-pdf";
}
//PDF TO......
@GetMapping("/pdf-to-html")
@Hidden
public ModelAndView pdfToHTML() {
ModelAndView modelAndView = new ModelAndView("convert/pdf-to-html");
modelAndView.addObject("currentPage", "pdf-to-html");
return modelAndView;
}
@GetMapping("/pdf-to-presentation")
@Hidden
public ModelAndView pdfToPresentation() {
ModelAndView modelAndView = new ModelAndView("convert/pdf-to-presentation");
modelAndView.addObject("currentPage", "pdf-to-presentation");
return modelAndView;
}
@GetMapping("/pdf-to-text")
@Hidden
public ModelAndView pdfToText() {
ModelAndView modelAndView = new ModelAndView("convert/pdf-to-text");
modelAndView.addObject("currentPage", "pdf-to-text");
return modelAndView;
}
@GetMapping("/pdf-to-word")
@Hidden
public ModelAndView pdfToWord() {
ModelAndView modelAndView = new ModelAndView("convert/pdf-to-word");
modelAndView.addObject("currentPage", "pdf-to-word");
return modelAndView;
}
@GetMapping("/pdf-to-xml")
@Hidden
public ModelAndView pdfToXML() {
ModelAndView modelAndView = new ModelAndView("convert/pdf-to-xml");
modelAndView.addObject("currentPage", "pdf-to-xml");
return modelAndView;
}
@GetMapping("/pdf-to-pdfa")
@Hidden
public String pdfToPdfAForm(Model model) {
model.addAttribute("currentPage", "pdf-to-pdfa");
return "convert/pdf-to-pdfa";
}
}
@@ -1,69 +0,0 @@
package stirling.software.SPDF.controller.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import io.swagger.v3.oas.annotations.Hidden;
@Controller
public class GeneralWebController {
@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
public String multiToolForm(Model model) {
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
public String pageDeleter(Model model) {
model.addAttribute("currentPage", "remove-pages");
return "remove-pages";
}
@GetMapping("/pdf-organizer")
@Hidden
public String pageOrganizer(Model model) {
model.addAttribute("currentPage", "pdf-organizer");
return "pdf-organizer";
}
@GetMapping("/rotate-pdf")
@Hidden
public String rotatePdfForm(Model model) {
model.addAttribute("currentPage", "rotate-pdf");
return "rotate-pdf";
}
@GetMapping("/split-pdfs")
@Hidden
public String splitPdfForm(Model model) {
model.addAttribute("currentPage", "split-pdfs");
return "split-pdfs";
}
}
@@ -1,84 +0,0 @@
package stirling.software.SPDF.controller.web;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
import io.swagger.v3.oas.annotations.Hidden;
@Controller
public class OtherWebController {
@GetMapping("/compress-pdf")
@Hidden
public String compressPdfForm(Model model) {
model.addAttribute("currentPage", "compress-pdf");
return "other/compress-pdf";
}
@GetMapping("/extract-image-scans")
@Hidden
public ModelAndView extractImageScansForm() {
ModelAndView modelAndView = new ModelAndView("other/extract-image-scans");
modelAndView.addObject("currentPage", "extract-image-scans");
return modelAndView;
}
@GetMapping("/extract-images")
@Hidden
public String extractImagesForm(Model model) {
model.addAttribute("currentPage", "extract-images");
return "other/extract-images";
}
@GetMapping("/change-metadata")
@Hidden
public String addWatermarkForm(Model model) {
model.addAttribute("currentPage", "change-metadata");
return "other/change-metadata";
}
public List<String> getAvailableTesseractLanguages() {
String tessdataDir = "/usr/share/tesseract-ocr/4.00/tessdata";
File[] files = new File(tessdataDir).listFiles();
if (files == null) {
return Collections.emptyList();
}
return Arrays.stream(files).filter(file -> file.getName().endsWith(".traineddata")).map(file -> file.getName().replace(".traineddata", ""))
.filter(lang -> !lang.equalsIgnoreCase("osd")).collect(Collectors.toList());
}
@GetMapping("/ocr-pdf")
@Hidden
public ModelAndView ocrPdfPage() {
ModelAndView modelAndView = new ModelAndView("other/ocr-pdf");
modelAndView.addObject("languages", getAvailableTesseractLanguages());
modelAndView.addObject("currentPage", "ocr-pdf");
return modelAndView;
}
@GetMapping("/add-image")
@Hidden
public String overlayImage(Model model) {
model.addAttribute("currentPage", "add-image");
return "other/add-image";
}
@GetMapping("/adjust-contrast")
@Hidden
public String contrast(Model model) {
model.addAttribute("currentPage", "adjust-contrast");
return "other/adjust-contrast";
}
}
@@ -1,46 +0,0 @@
package stirling.software.SPDF.controller.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import io.swagger.v3.oas.annotations.Hidden;
@Controller
public class SecurityWebController {
@GetMapping("/add-password")
@Hidden
public String addPasswordForm(Model model) {
model.addAttribute("currentPage", "add-password");
return "security/add-password";
}
@GetMapping("/change-permissions")
@Hidden
public String permissionsForm(Model model) {
model.addAttribute("currentPage", "change-permissions");
return "security/change-permissions";
}
@GetMapping("/remove-password")
@Hidden
public String removePasswordForm(Model model) {
model.addAttribute("currentPage", "remove-password");
return "security/remove-password";
}
@GetMapping("/add-watermark")
@Hidden
public String addWatermarkForm(Model model) {
model.addAttribute("currentPage", "add-watermark");
return "security/add-watermark";
}
//WIP
@GetMapping("/remove-watermark")
@Hidden
public String removeWatermarkForm(Model model) {
model.addAttribute("currentPage", "remove-watermark");
return "security/remove-watermark";
}
}
@@ -1,32 +0,0 @@
package stirling.software.SPDF.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.springframework.ui.Model;
import org.springframework.web.servlet.ModelAndView;
public class ErrorUtils {
public static Model exceptionToModel(Model model, Exception ex) {
StringWriter sw = new StringWriter();
ex.printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
model.addAttribute("errorMessage", ex.getMessage());
model.addAttribute("stackTrace", stackTrace);
return model;
}
public static ModelAndView exceptionToModelView(Model model, Exception ex) {
StringWriter sw = new StringWriter();
ex.printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("errorMessage", ex.getMessage());
modelAndView.addObject("stackTrace", stackTrace);
return modelAndView;
}
}
@@ -1,97 +0,0 @@
package stirling.software.SPDF.utils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
public class PDFToFile {
public ResponseEntity<byte[]> processPdfToOfficeFormat(MultipartFile inputFile, String outputFormat, String libreOfficeFilter) throws IOException, InterruptedException {
if (!"application/pdf".equals(inputFile.getContentType())) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
// Get the original PDF file name without the extension
String originalPdfFileName = inputFile.getOriginalFilename();
String pdfBaseName = originalPdfFileName.substring(0, originalPdfFileName.lastIndexOf('.'));
// Validate output format
List<String> allowedFormats = Arrays.asList("doc", "docx", "odt", "ppt", "pptx", "odp", "rtf", "html", "xml", "txt:Text");
if (!allowedFormats.contains(outputFormat)) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
Path tempInputFile = null;
Path tempOutputDir = null;
byte[] fileBytes;
String fileName = "temp.file";
try {
// Save the uploaded file to a temporary location
tempInputFile = Files.createTempFile("input_", ".pdf");
Files.copy(inputFile.getInputStream(), tempInputFile, StandardCopyOption.REPLACE_EXISTING);
// Prepare the output directory
tempOutputDir = Files.createTempDirectory("output_");
// Run the LibreOffice command
List<String> command = new ArrayList<>(
Arrays.asList("soffice", "--infilter=" + libreOfficeFilter, "--convert-to", outputFormat, "--outdir", tempOutputDir.toString(), tempInputFile.toString()));
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE).runCommandWithOutputHandling(command);
// Get output files
List<File> outputFiles = Arrays.asList(tempOutputDir.toFile().listFiles());
if (outputFiles.size() == 1) {
// Return single output file
File outputFile = outputFiles.get(0);
if (outputFormat.equals("txt:Text")) {
outputFormat = "txt";
}
fileName = pdfBaseName + "." + outputFormat;
fileBytes = FileUtils.readFileToByteArray(outputFile);
} else {
// Return output files in a ZIP archive
fileName = pdfBaseName + "To" + outputFormat + ".zip";
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream);
for (File outputFile : outputFiles) {
ZipEntry entry = new ZipEntry(outputFile.getName());
zipOutputStream.putNextEntry(entry);
FileInputStream fis = new FileInputStream(outputFile);
IOUtils.copy(fis, zipOutputStream);
fis.close();
zipOutputStream.closeEntry();
}
zipOutputStream.close();
fileBytes = byteArrayOutputStream.toByteArray();
}
} finally {
// Clean up the temporary files
if (tempInputFile != null)
Files.delete(tempInputFile);
if (tempOutputDir != null)
FileUtils.deleteDirectory(tempOutputDir.toFile());
}
return PdfUtils.bytesToWebResponse(fileBytes, fileName, MediaType.APPLICATION_OCTET_STREAM);
}
}
@@ -1,285 +0,0 @@
package stirling.software.SPDF.utils;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
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;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
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.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.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
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 ResponseEntity<byte[]> boasToWebResponse(ByteArrayOutputStream baos, String docName, MediaType mediaType) throws IOException {
return PdfUtils.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 byte[] convertFromPdf(byte[] inputStream, String imageType, ImageType colorType, boolean singleImage, int DPI) throws IOException, Exception {
try (PDDocument document = PDDocument.load(new ByteArrayInputStream(inputStream))) {
PDFRenderer pdfRenderer = new PDFRenderer(document);
int pageCount = document.getNumberOfPages();
List<BufferedImage> images = new ArrayList<>();
// Create images of all pages
for (int i = 0; i < pageCount; i++) {
images.add(pdfRenderer.renderImageWithDPI(i, 300, colorType));
}
if (singleImage) {
// Combine all images into a single big image
BufferedImage combined = new BufferedImage(images.get(0).getWidth(), images.get(0).getHeight() * pageCount, BufferedImage.TYPE_INT_RGB);
Graphics g = combined.getGraphics();
for (int i = 0; i < images.size(); i++) {
g.drawImage(images.get(i), 0, i * images.get(0).getHeight(), null);
}
images = Arrays.asList(combined);
}
// Create a ByteArrayOutputStream to save the image(s) to
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (singleImage) {
// Write the image to the output stream
ImageIO.write(images.get(0), imageType, baos);
// Log that the image was successfully written to the byte array
logger.info("Image successfully written to byte array");
} else {
// Zip the images and return as byte array
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
for (int i = 0; i < images.size(); i++) {
BufferedImage image = images.get(i);
try (ByteArrayOutputStream baosImage = new ByteArrayOutputStream()) {
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.write(baosImage.toByteArray());
}
}
// Log that the images were successfully written to the byte array
logger.info("Images successfully written to byte array as a zip");
}
}
return baos.toByteArray();
} catch (IOException e) {
// Log an error message if there is an issue converting the PDF to an image
logger.error("Error converting PDF to image", e);
throw e;
}
}
public static byte[] imageToPdf(MultipartFile[] files, boolean stretchToFit, boolean autoRotate) throws IOException {
try (PDDocument doc = new PDDocument()) {
for (MultipartFile file : files) {
// Create a temporary file for the image
File imageFile = Files.createTempFile("image", ".jpg").toFile();
try (FileOutputStream fos = new FileOutputStream(imageFile); InputStream input = file.getInputStream()) {
byte[] buffer = new byte[1024];
int len;
// Read from the input stream and write to the file
while ((len = input.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
logger.info("Image successfully written to file: {}", imageFile.getAbsolutePath());
} catch (IOException e) {
logger.error("Error writing image to file: {}", imageFile.getAbsolutePath(), e);
throw e;
}
// Create a new PDF page
PDPage page = new PDPage();
doc.addPage(page);
// Create an image object from the image file
PDImageXObject image = PDImageXObject.createFromFileByContent(imageFile, doc);
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
if (autoRotate && ((image.getWidth() > image.getHeight() && pageHeight > pageWidth) || (image.getWidth() < image.getHeight() && pageWidth > pageHeight))) {
// Rotate the page 90 degrees if the image better fits the page in landscape
// orientation
page.setRotation(90);
pageWidth = page.getMediaBox().getHeight();
pageHeight = page.getMediaBox().getWidth();
}
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
if (stretchToFit) {
if (page.getRotation() == 0 || page.getRotation() == 180) {
// Stretch the image to fit the whole page
contentStream.drawImage(image, 0, 0, pageWidth, pageHeight);
} else {
// Adjust the width and height of the page when rotated
contentStream.drawImage(image, 0, 0, pageHeight, pageWidth);
}
logger.info("Image successfully added to PDF, stretched to fit page");
} else {
// Ensure the image fits the page but maintain the image's aspect ratio
float imageAspectRatio = (float) image.getWidth() / (float) image.getHeight();
float pageAspectRatio = pageWidth / pageHeight;
// Determine the scale factor to fit the image onto the page
float scaleFactor = 1.0f;
if (imageAspectRatio > pageAspectRatio) {
// Image is wider than the page, scale to fit the width
scaleFactor = pageWidth / image.getWidth();
} else {
// Image is taller than the page, scale to fit the height
scaleFactor = pageHeight / image.getHeight();
}
// Calculate the position of the image on the page
float xPos = (pageWidth - (image.getWidth() * scaleFactor)) / 2;
float yPos = (pageHeight - (image.getHeight() * scaleFactor)) / 2;
// Draw the image onto the page
if (page.getRotation() == 0 || page.getRotation() == 180) {
contentStream.drawImage(image, xPos, yPos, image.getWidth() * scaleFactor, image.getHeight() * scaleFactor);
} else {
// Adjust the width and height of the page when rotated
contentStream.drawImage(image, yPos, xPos, image.getHeight() * scaleFactor, image.getWidth() * scaleFactor);
}
logger.info("Image successfully added to PDF, maintaining aspect ratio");
}
} catch (IOException e) {
logger.error("Error adding image to PDF", e);
throw e;
}
// Delete the temporary file
imageFile.delete();
}
// Create a ByteArrayOutputStream to save the PDF to
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
doc.save(byteArrayOutputStream);
logger.info("PDF successfully saved to byte array");
return byteArrayOutputStream.toByteArray();
}
}
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));
// Get the first page of the PDF
int pages = document.getNumberOfPages();
for (int i = 0; i < pages; i++) {
PDPage page = document.getPage(i);
try (PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true)) {
// Create an image object from the image bytes
PDImageXObject image = PDImageXObject.createFromByteArray(document, imageBytes, "");
// Draw the image onto the page at the specified x and y coordinates
contentStream.drawImage(image, x, y);
logger.info("Image successfully overlayed onto PDF");
if (!everyPage && i == 0) {
break;
}
} catch (IOException e) {
// Log an error message if there is an issue overlaying the image onto the PDF
logger.error("Error overlaying image onto PDF", e);
throw e;
}
}
// Create a ByteArrayOutputStream to save the PDF to
ByteArrayOutputStream baos = new ByteArrayOutputStream();
document.save(baos);
logger.info("PDF successfully saved to byte array");
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);
}
}
@@ -1,102 +0,0 @@
package stirling.software.SPDF.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
public class ProcessExecutor {
public enum Processes {
LIBRE_OFFICE, OCR_MY_PDF, PYTHON_OPENCV, GHOSTSCRIPT
}
private static final Map<Processes, ProcessExecutor> instances = new ConcurrentHashMap<>();
public static ProcessExecutor getInstance(Processes processType) {
return instances.computeIfAbsent(processType, key -> {
int semaphoreLimit = switch (key) {
case LIBRE_OFFICE -> 1;
case OCR_MY_PDF -> 2;
case PYTHON_OPENCV -> 8;
case GHOSTSCRIPT -> 16;
};
return new ProcessExecutor(semaphoreLimit);
});
}
private final Semaphore semaphore;
private ProcessExecutor(int semaphoreLimit) {
this.semaphore = new Semaphore(semaphoreLimit);
}
public int runCommandWithOutputHandling(List<String> command) throws IOException, InterruptedException {
int exitCode = 1;
semaphore.acquire();
try {
System.out.print("Running command: " + String.join(" ", command));
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();
// Read the error stream and standard output stream concurrently
List<String> errorLines = new ArrayList<>();
List<String> outputLines = new ArrayList<>();
Thread errorReaderThread = new Thread(() -> {
try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = errorReader.readLine()) != null) {
errorLines.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
});
Thread outputReaderThread = new Thread(() -> {
try (BufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = outputReader.readLine()) != null) {
outputLines.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
});
errorReaderThread.start();
outputReaderThread.start();
// Wait for the conversion process to complete
exitCode = process.waitFor();
// Wait for the reader threads to finish
errorReaderThread.join();
outputReaderThread.join();
if (outputLines.size() > 0) {
String outputMessage = String.join("\n", outputLines);
System.out.println("Command output:\n" + outputMessage);
}
if (errorLines.size() > 0) {
String errorMessage = String.join("\n", errorLines);
System.out.println("Command error output:\n" + errorMessage);
if (exitCode != 0) {
throw new IOException("Command process failed with exit code " + exitCode + ". Error message: " + errorMessage);
}
}
} finally {
semaphore.release();
}
return exitCode;
}
}
@@ -1,69 +0,0 @@
package stirling.software.SPDF.utils;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.pdfbox.contentstream.PDFStreamEngine;
import org.apache.pdfbox.contentstream.operator.Operator;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSString;
public class WatermarkRemover extends PDFStreamEngine {
private final Pattern pattern;
private final String watermarkText;
public WatermarkRemover(String watermarkText) {
this.watermarkText = watermarkText;
this.pattern = Pattern.compile(Pattern.quote(watermarkText));
}
@Override
protected void processOperator(Operator operator, List<COSBase> operands) throws IOException {
String operation = operator.getName();
boolean processText = false;
if ("Tj".equals(operation) || "TJ".equals(operation) || "'".equals(operation) || "\"".equals(operation)) {
processText = true;
}
if (processText) {
for (int j = 0; j < operands.size(); ++j) {
COSBase operand = operands.get(j);
if (operand instanceof COSString) {
COSString cosString = (COSString) operand;
String string = cosString.getString();
Matcher matcher = pattern.matcher(string);
if (matcher.find()) {
string = matcher.replaceAll("");
cosString.setValue(string.getBytes());
}
} else if (operand instanceof COSArray) {
COSArray array = (COSArray) operand;
for (int i = 0; i < array.size(); i++) {
COSBase item = array.get(i);
if (item instanceof COSString) {
COSString cosString = (COSString) item;
String string = cosString.getString();
Matcher matcher = pattern.matcher(string);
if (matcher.find()) {
System.out.println("operation =" + operation);
System.out.println("1 =" + string);
string = matcher.replaceAll("");
cosString.setValue(string.getBytes());
array.set(i, cosString);
operands.set(j, array);
}
}
}
}
}
}
super.processOperator(operator, operands);
}
}
-24
View File
@@ -1,24 +0,0 @@
spring.http.multipart.max-file-size=2GB
spring.http.multipart.max-request-size=2GB
multipart.enabled=true
multipart.max-file-size=2000MB
multipart.max-request-size=2000MB
spring.servlet.multipart.max-file-size=2000MB
spring.servlet.multipart.max-request-size=2000MB
server.forward-headers-strategy=NATIVE
server.error.path=/error
server.error.whitelabel.enabled=false
server.error.include-stacktrace=always
server.error.include-exception=true
server.error.include-message=always
server.servlet.session.tracking-modes=cookie
spring.devtools.restart.enabled=true
spring.devtools.livereload.enabled=true
spring.thymeleaf.encoding=UTF-8
-8
View File
@@ -1,8 +0,0 @@
log4j.rootLogger=ERROR,stdout
log4j.logger.com.endeca=INFO
# Logger for crawl metrics
log4j.logger.com.endeca.itl.web.metrics=INFO
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%p\t%d{ISO8601}\t%r\t%c\t[%t]\t%m%n
-11
View File
@@ -1,11 +0,0 @@
fileToPDF.fileTypesList=Microsoft Word: (DOC, DOCX, DOT, DOTX) <br> \
Microsoft Excel: (CSV, XLS, XLSX, XLT, XLTX, SLK, DIF) <br> \
Microsoft PowerPoint: (PPT, PPTX) <br> \
OpenDocument Formats: (ODT, OTT, ODS, OTS, ODP, OTP, ODG, OTG) <br> \
Plain Text: (TXT, TEXT, XML) <br> \
Rich Text Format: (RTF) <br> \
Images: (BMP, GIF, JPEG, PNG, TIF, PBM, PGM, PPM, RAS, XBM, XPM, SVG, SVM, WMF) <br> \
HTML: (HTML) <br> \
Lotus Word Pro: (LWP) <br> \
StarOffice formats: (SDA, SDC, SDD, SDW, STC, STD, STI, STW, SXD, SXG, SXI, SXW) <br> \
Other formats: (DBF, FODS, VSD, VOR, VOR3, VOR4, UOP, PCT, PS, PDF)
@@ -1,378 +0,0 @@
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#
# Translated by Google Translate #
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#
###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl=right to left)
language.direction=rtl
pdfPrompt=اختر PDF
multiPdfPrompt=اختر ملفات PDF (2+)
multiPdfDropPrompt=حدد (أو اسحب وأفلت) جميع ملفات PDF التي تحتاجها
imgPrompt=اختر صورة
genericSubmit=إرسال
processTimeWarning=تحذير: يمكن أن تستغرق هذه العملية ما يصل إلى دقيقة حسب حجم الملف
pageOrderPrompt=ترتيب الصفحات (أدخل قائمة بأرقام الصفحات مفصولة بفواصل):
goToPage=اذهب
true=\u0635\u062D\u064A\u062D
false=\u062E\u0637\u0623
unknown=\u063A\u064A\u0631 \u0645\u0639\u0631\u0648\u0641
save=\u062D\u0641\u0638
close=\u0625\u063A\u0644\u0627\u0642
#############
# 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 متعددة في ملف واحد بسهولة.
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=إضافة صورة إلى ملف PDF
home.addImage.desc=إضافة صورة إلى موقع معين في PDF (العمل قيد التقدم)
home.watermark.title=إضافة علامة مائية
home.watermark.desc=أضف علامة مائية مخصصة إلى مستند PDF الخاص بك.
home.remove-watermark.title=\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u0645\u0627\u0626\u064A\u0629
home.remove-watermark.desc=\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0639\u0644\u0627\u0645\u0627\u062A \u0627\u0644\u0645\u0627\u0626\u064A\u0629 \u0645\u0646 \u0645\u0633\u062A\u0646\u062F PDF \u0627\u0644\u062E\u0627\u0635 \u0628\u0643.
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=\u062A\u063A\u064A\u064A\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0648\u0635\u0641\u064A\u0629
home.changeMetadata.desc=\u062A\u063A\u064A\u064A\u0631 / \u0625\u0632\u0627\u0644\u0629 / \u0625\u0636\u0627\u0641\u0629 \u0628\u064A\u0627\u0646\u0627\u062A \u0623\u0648\u0644\u064A\u0629 \u0645\u0646 \u0645\u0633\u062A\u0646\u062F PDF
home.fileToPDF.title=\u062A\u062D\u0648\u064A\u0644 \u0627\u0644\u0645\u0644\u0641 \u0625\u0644\u0649 PDF
home.fileToPDF.desc=\u062A\u062D\u0648\u064A\u0644 \u0623\u064A \u0645\u0644\u0641 \u062A\u0642\u0631\u064A\u0628\u0627 \u0625\u0644\u0649 PDF (DOCX \u0648PNG \u0648XLS \u0648PPT \u0648TXT \u0648\u0627\u0644\u0645\u0632\u064A\u062F)
home.ocr.title=\u062A\u0634\u063A\u064A\u0644 OCR \u0639\u0644\u0649 PDF \u0648 / \u0623\u0648 \u0645\u0633\u062D \u0636\u0648\u0626\u064A
home.ocr.desc=\u064A\u0642\u0648\u0645 \u0628\u0631\u0646\u0627\u0645\u062C \u0627\u0644\u062A\u0646\u0638\u064A\u0641 \u0628\u0645\u0633\u062D \u0648\u0627\u0643\u062A\u0634\u0627\u0641 \u0627\u0644\u0646\u0635 \u0645\u0646 \u0627\u0644\u0635\u0648\u0631 \u062F\u0627\u062E\u0644 \u0645\u0644\u0641 PDF \u0648\u064A\u0639\u064A\u062F \u0625\u0636\u0627\u0641\u062A\u0647 \u0643\u0646\u0635
home.extractImages.title=\u0627\u0633\u062A\u062E\u0631\u0627\u062C \u0627\u0644\u0635\u0648\u0631
home.extractImages.desc=\u064A\u0633\u062A\u062E\u0631\u062C \u062C\u0645\u064A\u0639 \u0627\u0644\u0635\u0648\u0631 \u0645\u0646 \u0645\u0644\u0641 PDF \u0648\u064A\u062D\u0641\u0638\u0647\u0627 \u0641\u064A \u0627\u0644\u0631\u0645\u0632 \u0627\u0644\u0628\u0631\u064A\u062F\u064A
home.pdfToPDFA.title=\u062A\u062D\u0648\u064A\u0644 \u0645\u0644\u0641\u0627\u062A PDF \u0625\u0644\u0649 PDF / A
home.pdfToPDFA.desc=\u062A\u062D\u0648\u064A\u0644 PDF \u0625\u0644\u0649 PDF / A \u0644\u0644\u062A\u062E\u0632\u064A\u0646 \u0637\u0648\u064A\u0644 \u0627\u0644\u0645\u062F\u0649
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 إلى نص / RTF
home.PDFToText.desc=تحويل PDF إلى تنسيق نص أو 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=تقسيم عدة صور من داخل صورة / ملف PDF
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=\u0625\u0639\u062F\u0627\u062F\u0627\u062A
settings.title=\u0627\u0644\u0625\u0639\u062F\u0627\u062F\u0627\u062A
settings.update=\u0627\u0644\u062A\u062D\u062F\u064A\u062B \u0645\u062A\u0627\u062D
settings.appVersion=\u0625\u0635\u062F\u0627\u0631 \u0627\u0644\u062A\u0637\u0628\u064A\u0642:
settings.downloadOption.title=\u062A\u062D\u062F\u064A\u062F \u062E\u064A\u0627\u0631 \u0627\u0644\u062A\u0646\u0632\u064A\u0644 (\u0644\u0644\u062A\u0646\u0632\u064A\u0644\u0627\u062A \u0630\u0627\u062A \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0648\u0627\u062D\u062F \u063A\u064A\u0631 \u0627\u0644\u0645\u0636\u063A\u0648\u0637):
settings.downloadOption.1=\u0641\u062A\u062D \u0641\u064A \u0646\u0641\u0633 \u0627\u0644\u0646\u0627\u0641\u0630\u0629
settings.downloadOption.2=\u0641\u062A\u062D \u0641\u064A \u0646\u0627\u0641\u0630\u0629 \u062C\u062F\u064A\u062F\u0629
settings.downloadOption.3=\u062A\u0646\u0632\u064A\u0644 \u0627\u0644\u0645\u0644\u0641
settings.zipThreshold=\u0645\u0644\u0641\u0627\u062A \u0645\u0636\u063A\u0648\u0637\u0629 \u0639\u0646\u062F \u062A\u062C\u0627\u0648\u0632 \u0639\u062F\u062F \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u0645 \u062A\u0646\u0632\u064A\u0644\u0647\u0627
#OCR
ocr.title=\u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 / \u062A\u0646\u0638\u064A\u0641 \u0627\u0644\u0645\u0633\u062D \u0627\u0644\u0636\u0648\u0626\u064A
ocr.header=\u0645\u0633\u062D \u0627\u0644\u0645\u0633\u062D \u0627\u0644\u0636\u0648\u0626\u064A / \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 (\u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641)
ocr.selectText.1=\u062D\u062F\u062F \u0627\u0644\u0644\u063A\u0627\u062A \u0627\u0644\u062A\u064A \u0633\u064A\u062A\u0645 \u0627\u0643\u062A\u0634\u0627\u0641\u0647\u0627 \u062F\u0627\u062E\u0644 \u0645\u0644\u0641 PDF (\u0627\u0644\u0644\u063A\u0627\u062A \u0627\u0644\u0645\u062F\u0631\u062C\u0629 \u0647\u064A \u062A\u0644\u0643 \u0627\u0644\u062A\u064A \u062A\u0645 \u0627\u0643\u062A\u0634\u0627\u0641\u0647\u0627 \u062D\u0627\u0644\u064A\u064B\u0627):
ocr.selectText.2=\u0625\u0646\u062A\u0627\u062C \u0645\u0644\u0641 \u0646\u0635\u064A \u064A\u062D\u062A\u0648\u064A \u0639\u0644\u0649 \u0646\u0635 OCR \u0628\u062C\u0627\u0646\u0628 \u0645\u0644\u0641 PDF \u0627\u0644\u0630\u064A \u062A\u0645 \u0625\u0639\u062F\u0627\u062F\u0647 \u0628\u0648\u0627\u0633\u0637\u0629 OCR
ocr.selectText.3=\u062A\u0645 \u0645\u0633\u062D \u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u0635\u062D\u064A\u062D\u0629 \u0636\u0648\u0626\u064A\u064B\u0627 \u0628\u0632\u0627\u0648\u064A\u0629 \u0645\u0646\u062D\u0631\u0641\u0629 \u0639\u0646 \u0637\u0631\u064A\u0642 \u062A\u062F\u0648\u064A\u0631\u0647\u0627 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649 \u0641\u064A \u0645\u0643\u0627\u0646\u0647\u0627
ocr.selectText.4=\u0635\u0641\u062D\u0629 \u0646\u0638\u064A\u0641\u0629 \u0644\u0630\u0644\u0643 \u0645\u0646 \u063A\u064A\u0631 \u0627\u0644\u0645\u062D\u062A\u0645\u0644 \u0623\u0646 \u064A\u062C\u062F OCR \u0646\u0635\u064B\u0627 \u0641\u064A \u0636\u0648\u0636\u0627\u0621 \u0627\u0644\u062E\u0644\u0641\u064A\u0629. (\u0644\u0627 \u064A\u0648\u062C\u062F \u062A\u063A\u064A\u064A\u0631 \u0641\u064A \u0627\u0644\u0625\u062E\u0631\u0627\u062C)
ocr.selectText.5=\u0635\u0641\u062D\u0629 \u0646\u0638\u064A\u0641\u0629 \u060C \u0644\u0630\u0644\u0643 \u0645\u0646 \u063A\u064A\u0631 \u0627\u0644\u0645\u062D\u062A\u0645\u0644 \u0623\u0646 \u064A\u062C\u062F OCR \u0646\u0635\u064B\u0627 \u0641\u064A \u0636\u0648\u0636\u0627\u0621 \u0627\u0644\u062E\u0644\u0641\u064A\u0629 \u060C \u0648\u064A\u062D\u0627\u0641\u0638 \u0639\u0644\u0649 \u0627\u0644\u062A\u0646\u0638\u064A\u0641 \u0641\u064A \u0627\u0644\u0625\u062E\u0631\u0627\u062C.
ocr.selectText.6=\u064A\u062A\u062C\u0627\u0647\u0644 \u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u062D\u062A\u0648\u064A \u0639\u0644\u0649 \u0646\u0635 \u062A\u0641\u0627\u0639\u0644\u064A \u060C \u0641\u0642\u0637 \u0635\u0641\u062D\u0627\u062A OCRs \u0627\u0644\u062A\u064A \u0647\u064A \u0635\u0648\u0631
ocr.selectText.7=\u0641\u0631\u0636 \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 \u060C \u0633\u064A\u0624\u062F\u064A \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 \u0639\u0644\u0649 \u0643\u0644 \u0635\u0641\u062D\u0629 \u0625\u0644\u0649 \u0625\u0632\u0627\u0644\u0629 \u062C\u0645\u064A\u0639 \u0639\u0646\u0627\u0635\u0631 \u0627\u0644\u0646\u0635 \u0627\u0644\u0623\u0635\u0644\u064A
ocr.selectText.8=\u0639\u0627\u062F\u064A (\u062E\u0637\u0623 \u0625\u0630\u0627 \u0643\u0627\u0646 PDF \u064A\u062D\u062A\u0648\u064A \u0639\u0644\u0649 \u0646\u0635)
ocr.selectText.9=\u0625\u0639\u062F\u0627\u062F\u0627\u062A \u0625\u0636\u0627\u0641\u064A\u0629
ocr.selectText.10=\u0648\u0636\u0639 \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641
ocr.selectText.11 = إزالة الصور بعد التعرف الضوئي على الحروف (يزيل كل الصور ، يكون مفيدًا فقط إذا كان جزءًا من خطوة التحويل)
ocr.selectText.12 = نوع العرض (متقدم)
ocr.help=\u064A\u0631\u062C\u0649 \u0642\u0631\u0627\u0621\u0629 \u0647\u0630\u0647 \u0627\u0644\u0648\u062B\u0627\u0626\u0642 \u062D\u0648\u0644 \u0643\u064A\u0641\u064A\u0629 \u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0647\u0630\u0627 \u0644\u0644\u063A\u0627\u062A \u0623\u062E\u0631\u0649 \u0648 / \u0623\u0648 \u0627\u0644\u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0644\u064A\u0633 \u0641\u064A \u0639\u0627\u0645\u0644 \u0627\u0644\u0625\u0631\u0633\u0627\u0621
ocr.credit=\u062A\u0633\u062A\u062E\u062F\u0645 \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 OCRmyPDF \u0648 Tesseract \u0644 OCR.
ocr.submit=\u0645\u0639\u0627\u0644\u062C\u0629 PDF \u0628\u0627\u0633\u062A\u062E\u062F\u0627\u0645 OCR
extractImages.title=\u0627\u0633\u062A\u062E\u0631\u0627\u062C \u0627\u0644\u0635\u0648\u0631
extractImages.header=\u0627\u0633\u062A\u062E\u0631\u0627\u062C \u0627\u0644\u0635\u0648\u0631
extractImages.selectText=\u062D\u062F\u062F \u062A\u0646\u0633\u064A\u0642 \u0627\u0644\u0635\u0648\u0631\u0629 \u0644\u062A\u062D\u0648\u064A\u0644 \u0627\u0644\u0635\u0648\u0631 \u0627\u0644\u0645\u0633\u062A\u062E\u0631\u062C\u0629 \u0625\u0644\u0649
extractImages.submit=\u0627\u0633\u062A\u062E\u0631\u0627\u062C
#File \u0625\u0644\u0649 PDF
fileToPDF.title=\u0645\u0644\u0641 \u0625\u0644\u0649 PDF
fileToPDF.header=\u062A\u062D\u0648\u064A\u0644 \u0623\u064A \u0645\u0644\u0641 \u0625\u0644\u0649 PDF
fileToPDF.credit=\u062A\u0633\u062A\u062E\u062F\u0645 \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 \u0644\u064A\u0628\u0631 \u0623\u0648\u0641\u064A\u0633 \u0648\u0623\u0648\u0646\u0648\u0643\u0648\u0646\u0641 \u0644\u062A\u062D\u0648\u064A\u0644 \u0627\u0644\u0645\u0644\u0641\u0627\u062A.
fileToPDF.supportedFileTypes=\u064A\u062C\u0628 \u0623\u0646 \u062A\u062A\u0636\u0645\u0646 \u0623\u0646\u0648\u0627\u0639 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u0645\u062F\u0639\u0648\u0645\u0629 \u0645\u0627 \u064A\u0644\u064A \u0648\u0644\u0643\u0646 \u0644\u0644\u062D\u0635\u0648\u0644 \u0639\u0644\u0649 \u0642\u0627\u0626\u0645\u0629 \u0645\u062D\u062F\u062B\u0629 \u0643\u0627\u0645\u0644\u0629 \u0628\u0627\u0644\u062A\u0646\u0633\u064A\u0642\u0627\u062A \u0627\u0644\u0645\u062F\u0639\u0648\u0645\u0629 \u060C \u064A\u0631\u062C\u0649 \u0627\u0644\u0631\u062C\u0648\u0639 \u0625\u0644\u0649 \u0648\u062B\u0627\u0626\u0642 LibreOffice
fileToPDF.submit=\u062A\u062D\u0648\u064A\u0644 \u0625\u0644\u0649 PDF
#Add image
addImage.title=إضافة صورة
addImage.header=إضافة صورة إلى PDF (العمل قيد التقدم)
addImage.everyPage=كل صفحة؟
addImage.submit=إضافة صورة
#compress
compress.title=ضغط
compress.header=\u0636\u063A\u0637 PDF
compress.credit=\u062A\u0633\u062A\u062E\u062F\u0645 \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 OCRmyPDF \u0644\u0636\u063A\u0637 / \u062A\u062D\u0633\u064A\u0646 PDF.
compress.selectText.1=\u0645\u0633\u062A\u0648\u0649 \u0627\u0644\u062A\u062D\u0633\u064A\u0646:
compress.selectText.2=0 (\u0628\u062F\u0648\u0646 \u062A\u062D\u0633\u064A\u0646)
compress.selectText.3=1 (\u0627\u0641\u062A\u0631\u0627\u0636\u064A\u060C \u062A\u062D\u0633\u064A\u0646 \u0628\u062F\u0648\u0646 \u0641\u0642\u062F\u0627\u0646)
compress.selectText.4=2 (\u062A\u062D\u0633\u064A\u0646 \u0636\u064A\u0627\u0639)
compress.selectText.5=3 (\u062A\u062D\u0633\u064A\u0646 \u0636\u064A\u0627\u0639 \u060C \u0623\u0643\u062B\u0631 \u0639\u062F\u0648\u0627\u0646\u064A\u0629)
compress.selectText.6=\u062A\u0645\u0643\u064A\u0646 \u0639\u0631\u0636 \u0627\u0644\u0648\u064A\u0628 \u0627\u0644\u0633\u0631\u064A\u0639 (\u062E\u0637\u064A PDF)
compress.selectText.7=\u062A\u0645\u0643\u064A\u0646 \u062A\u0631\u0645\u064A\u0632 JBIG2 \u0627\u0644\u0645\u0641\u0642\u0648\u062F
compress.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 PDFS منفصلة مع:
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=Split
#merge
imageToPDF.title=صورة إلى PDF
imageToPDF.header=صورة إلى PDF
imageToPDF.submit=تحول
imageToPDF.selectText.1=\u062A\u0645\u062F\u062F \u0644\u0644\u0645\u0644\u0627\u0621\u0645\u0629
imageToPDF.selectText.2=\u062F\u0648\u0631\u0627\u0646 PDF \u062A\u0644\u0642\u0627\u0626\u064A\u064B\u0627
imageToPDF.selectText.3=\u0627\u0644\u0645\u0646\u0637\u0642 \u0627\u0644\u0645\u062A\u0639\u062F\u062F \u0644\u0644\u0645\u0644\u0641\u0627\u062A (\u0645\u0641\u0639\u0651\u0644 \u0641\u0642\u0637 \u0625\u0630\u0627 \u0643\u0646\u062A \u062A\u0639\u0645\u0644 \u0645\u0639 \u0635\u0648\u0631 \u0645\u062A\u0639\u062F\u062F\u0629)
imageToPDF.selectText.4=\u062F\u0645\u062C \u0641\u064A \u0645\u0644\u0641 PDF \u0648\u0627\u062D\u062F
imageToPDF.selectText.5=\u062A\u062D\u0648\u064A\u0644 \u0625\u0644\u0649 \u0645\u0644\u0641\u0627\u062A PDF \u0645\u0646\u0641\u0635\u0644\u0629
#pdfToImage
pdfToImage.title=تحويل PDF إلى صورة
pdfToImage.header=تحويل PDF إلى صورة
pdfToImage.selectText=تنسيق الصورة
pdfToImage.singleOrMultiple=\u0646\u0648\u0639 \u0646\u062A\u064A\u062C\u0629 \u0627\u0644\u0635\u0648\u0631\u0629
pdfToImage.single=\u0635\u0648\u0631\u0629 \u0648\u0627\u062D\u062F\u0629 \u0643\u0628\u064A\u0631\u0629
pdfToImage.multi=\u0635\u0648\u0631 \u0645\u062A\u0639\u062F\u062F\u0629
pdfToImage.colorType=\u0646\u0648\u0639 \u0627\u0644\u0644\u0648\u0646
pdfToImage.color=\u0627\u0644\u0644\u0648\u0646
pdfToImage.grey=\u062A\u062F\u0631\u062C \u0627\u0644\u0631\u0645\u0627\u062F\u064A
pdfToImage.blackwhite=\u0623\u0628\u064A\u0636 \u0648\u0623\u0633\u0648\u062F (\u0642\u062F \u064A\u0641\u0642\u062F \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A!)
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.submit=تشفير
#watermark
watermark.title=إضافة علامة مائية
watermark.header=إضافة علامة مائية
watermark.selectText.1=حدد PDF لإضافة العلامة المائية إلى:
watermark.selectText.2=نص العلامة المائية:
watermark.selectText.3=حجم الخط:
watermark.selectText.4=دوران (0-360):
watermark.selectText.5=widthSpacer (مسافة بين كل علامة مائية أفقيًا):
watermark.selectText.6=heightSpacer (مسافة بين كل علامة مائية عموديًا):
watermark.selectText.7=\u0627\u0644\u062A\u0639\u062A\u064A\u0645 (0\u066A - 100\u066A):
watermark.submit=إضافة علامة مائية
#remove-watermark
remove-watermark.title=\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u0645\u0627\u0626\u064A\u0629
remove-watermark.header=\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u0645\u0627\u0626\u064A\u0629
remove-watermark.selectText.1=\u062D\u062F\u062F PDF \u0644\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u0645\u0627\u0626\u064A\u0629 \u0645\u0646:
remove-watermark.selectText.2=\u0646\u0635 \u0627\u0644\u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u0645\u0627\u0626\u064A\u0629:
remove-watermark.submit=\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u0645\u0627\u0626\u064A\u0629
#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=\u062A\u063A\u064A\u064A\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0648\u0635\u0641\u064A\u0629
changeMetadata.header=\u062A\u063A\u064A\u064A\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0648\u0635\u0641\u064A\u0629
changeMetadata.selectText.1=\u064A\u0631\u062C\u0649 \u062A\u0639\u062F\u064A\u0644 \u0627\u0644\u0645\u062A\u063A\u064A\u0631\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u0631\u063A\u0628 \u0641\u064A \u062A\u063A\u064A\u064A\u0631\u0647\u0627
changeMetadata.selectText.2=\u062D\u0630\u0641 \u0643\u0644 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0623\u0648\u0644\u064A\u0629
changeMetadata.selectText.3=\u0625\u0638\u0647\u0627\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0623\u0648\u0644\u064A\u0629 \u0627\u0644\u0645\u062E\u0635\u0635\u0629:
changeMetadata.author=\u0627\u0644\u0645\u0624\u0644\u0641:
changeMetadata.creationDate=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u0625\u0646\u0634\u0627\u0621 (yyyy / MM / dd HH: mm: ss):
changeMetadata.creator=\u0627\u0644\u0645\u0646\u0634\u0626:
changeMetadata.keywords=\u0627\u0644\u0643\u0644\u0645\u0627\u062A \u0627\u0644\u0631\u0626\u064A\u0633\u064A\u0629:
changeMetadata.modDate=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u062A\u0639\u062F\u064A\u0644 (yyyy / MM / dd HH: mm: ss):
changeMetadata.producer=\u0627\u0644\u0645\u0646\u062A\u062C:
changeMetadata.subject=\u0627\u0644\u0645\u0648\u0636\u0648\u0639:
changeMetadata.title=\u0627\u0644\u0639\u0646\u0648\u0627\u0646:
changeMetadata.trapped=\u0645\u062D\u0627\u0635\u0631:
changeMetadata.selectText.4=\u0628\u064A\u0627\u0646\u0627\u062A \u0648\u0635\u0641\u064A\u0629 \u0623\u062E\u0631\u0649:
changeMetadata.selectText.5=\u0625\u0636\u0627\u0641\u0629 \u0625\u062F\u062E\u0627\u0644 \u0628\u064A\u0627\u0646\u0627\u062A \u0623\u0648\u0644\u064A\u0629 \u0645\u062E\u0635\u0635
changeMetadata.submit=\u062A\u063A\u064A\u064A\u0631
xlsToPdf.title=\u062A\u062D\u0648\u064A\u0644 Excel \u0625\u0644\u0649 PDF
xlsToPdf.header=\u062A\u062D\u0648\u064A\u0644 Excel \u0625\u0644\u0649 PDF
xlsToPdf.selectText.1=\u062D\u062F\u062F \u0648\u0631\u0642\u0629 \u0625\u0643\u0633\u0644 XLS \u0623\u0648 XLSX \u0644\u0644\u062A\u062D\u0648\u064A\u0644
xlsToPdf.convert=\u062A\u062D\u0648\u064A\u0644
pdfToPDFA.title=PDF \u0625\u0644\u0649 PDF / A
pdfToPDFA.header=PDF \u0625\u0644\u0649 PDF / A
pdfToPDFA.credit=\u062A\u0633\u062A\u062E\u062F\u0645 \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 OCRmyPDF \u0644\u062A\u062D\u0648\u064A\u0644 PDF / A.
pdfToPDFA.submit=\u062A\u062D\u0648\u064A\u0644
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 إلى نص / RTF
PDFToText.header=تحويل PDF إلى نص / 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=تحويل
@@ -1,395 +0,0 @@
###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl=right to left)
language.direction=ltr
pdfPrompt=PDF auswählen
multiPdfPrompt=PDFs auswählen(2+)
multiPdfDropPrompt=Wählen Sie alle gewünschten PDFs aus (oder ziehen Sie sie per Drag & Drop hierhin)
imgPrompt=Wählen Sie ein Bild
genericSubmit=Einreichen
processTimeWarning=Achtung: Abhängig von der Dateigröße kann dieser Prozess bis zu einer Minute dauern
pageOrderPrompt=Seitenreihenfolge (Geben Sie eine durch Komma getrennte Liste von Seitenzahlen ein):
goToPage=Los
true=Wahr
false=Falsch
unknown=Unbekannt
save=Speichern
close=Schließen
#############
# HOME-PAGE #
#############
home.desc=Ihr lokal gehosteter One-Stop-Shop für alle Ihre PDF-Anforderungen.
navbar.convert=Konvertieren
navbar.security=Sicherheit
navbar.other=Anderes
navbar.darkmode=Dark Mode
navbar.pageOps=Seitenoperationen
home.multiTool.title=PDF-Multitool
home.multiTool.desc=Seiten zusammenführen, drehen, neu anordnen und entfernen
home.merge.title=Zusammenführen
home.merge.desc=Mehrere PDF-Dateien zu einer einzigen zusammenführen.
home.split.title=Aufteilen
home.split.desc=PDFs in mehrere Dokumente aufteilen.
home.rotate.title=Drehen
home.rotate.desc=Drehen Sie Ihre PDFs ganz einfach.
home.imageToPdf.title=Bild zu PDF
home.imageToPdf.desc=Konvertieren Sie ein Bild (PNG, JPEG, GIF) in ein PDF.
home.pdfToImage.title=PDF zu Bild
home.pdfToImage.desc=Konvertieren Sie ein PDF in ein Bild (PNG, JPEG, GIF).
home.pdfOrganiser.title=Organisieren
home.pdfOrganiser.desc=Seiten entfernen und Seitenreihenfolge ändern.
home.addImage.title=Bild einfügen
home.addImage.desc=Fügt ein Bild an eine bestimmte Stelle im PDF ein (Work in progress).
home.watermark.title=Wasserzeichen hinzufügen
home.watermark.desc=Fügen Sie ein eigenes Wasserzeichen zu Ihrem PDF hinzu.
home.remove-watermark.title=Wasserzeichen entfernen
home.remove-watermark.desc=Wasserzeichen aus Ihrem PDF-Dokument entfernen.
home.permissions.title=Berechtigungen ändern
home.permissions.desc=Die Berechtigungen für Ihr PDF-Dokument verändern.
home.removePages.title=Entfernen
home.removePages.desc=Ungewollte Seiten aus dem PDF entfernen.
home.addPassword.title=Passwort hinzufügen
home.addPassword.desc=Das PDF mit einem Passwort verschlüsseln.
home.removePassword.title=Passwort entfernen
home.removePassword.desc=Den Passwortschutz eines PDFs entfernen.
home.compressPdfs.title=Komprimieren
home.compressPdfs.desc=PDF komprimieren um die Dateigröße zu reduzieren.
home.changeMetadata.title=Metadaten ändern
home.changeMetadata.desc=Ändern/Entfernen/Hinzufügen von Metadaten aus einem PDF-Dokument
home.fileToPDF.title=Datei in PDF konvertieren
home.fileToPDF.desc=Konvertieren Sie nahezu jede Datei in PDF (DOCX, PNG, XLS, PPT, TXT und mehr)
home.ocr.title=Führe OCR auf PDF- und/oder Cleanup-Scans aus
home.ocr.desc=Cleanup scannt und erkennt Text aus Bildern in einer PDF-Datei und fügt ihn erneut als Text hinzu.
home.extractImages.title=Bilder extrahieren
home.extractImages.desc=Extrahiert alle Bilder aus einer PDF-Datei und speichert sie als Zip-Datei
home.pdfToPDFA.title=PDF zu PDF/A konvertieren
home.pdfToPDFA.desc=PDF zu PDF/A für Langzeitarchivierung konvertieren
home.PDFToWord.title=PDF zu Word
home.PDFToWord.desc=PDF in Word-Formate konvertieren (DOC, DOCX und ODT)
home.PDFToPresentation.title=PDF zu Präsentation
home.PDFToPresentation.desc=PDF in Präsentationsformate konvertieren (PPT, PPTX und ODP)
home.PDFToText.title=PDF in Text/RTF
home.PDFToText.desc=PDF in Text- oder RTF-Format konvertieren
home.PDFToHTML.title=PDF in HTML
home.PDFToHTML.desc=PDF in HTML-Format konvertieren
home.PDFToXML.title=PDF in XML
home.PDFToXML.desc=PDF in XML-Format konvertieren
home.ScannerImageSplit.title=Gescannte Fotos erkennen/aufteilen
home.ScannerImageSplit.desc=Teilt mehrere Fotos innerhalb eines Fotos/PDF
ScannerImageSplit.selectText.1=Winkelschwelle:
ScannerImageSplit.selectText.2=Legt den minimalen absoluten Winkel fest, der erforderlich ist, damit das Bild gedreht werden kann (Standard: 10).
ScannerImageSplit.selectText.3=Toleranz:
ScannerImageSplit.selectText.4=Bestimmt den Bereich der Farbvariation um die geschätzte Hintergrundfarbe herum (Standard: 30).
ScannerImageSplit.selectText.5=Mindestbereich:
ScannerImageSplit.selectText.6=Legt den minimalen Bereichsschwellenwert für ein Foto fest (Standard: 10000).
ScannerImageSplit.selectText.7=Minimaler Konturbereich:
ScannerImageSplit.selectText.8=Legt den minimalen Konturbereichsschwellenwert für ein Foto fest
ScannerImageSplit.selectText.9=Randgröße:
ScannerImageSplit.selectText.10=Legt die Größe des hinzugefügten und entfernten Randes fest, um weiße Ränder in der Ausgabe zu verhindern (Standard: 1).
navbar.settings=Einstellungen
settings.title=Einstellungen
settings.update=Update verfügbar
settings.appVersion=App-Version:
settings.downloadOption.title=Download-Option wählen (für einzelne Dateien, die keine Zip-Downloads sind):
settings.downloadOption.1=Im selben Fenster öffnen
settings.downloadOption.2=In neuem Fenster öffnen
settings.downloadOption.3=Datei herunterladen
settings.zipThreshold=Dateien komprimieren, wenn die Anzahl der heruntergeladenen Dateien überschritten wird
#OCR
ocr.title=OCR / Scan-Bereinigung
ocr.header=Scans bereinigen / OCR (Optical Character Recognition)
ocr.selectText.1=Sprachen auswählen, die im PDF erkannt werden sollen (die aufgelisteten sind die aktuell erkannten):
ocr.selectText.2=Textdatei erzeugen, die OCR-Text neben dem OCR-bearbeiteten PDF enthält
ocr.selectText.3=Korrekte Seiten wurden in einem schiefen Winkel gescannt, indem sie wieder an ihren Platz gedreht wurden
ocr.selectText.4=Seite säubern, daher ist es weniger wahrscheinlich, dass OCR Text im Hintergrundrauschen findet. (Keine Ausgangsänderung)
ocr.selectText.5=Seite säubern, sodass es weniger wahrscheinlich ist, dass OCR Text im Hintergrundrauschen findet, Bereinigung der Ausgabe wird beibehalten.
ocr.selectText.6=Ignoriert Seiten mit interaktivem Text, nur OCR-Seiten, die Bilder sind
ocr.selectText.7=OCR erzwingen, OCR wird jede Seite entfernen und alle ursprünglichen Textelemente entfernen
ocr.selectText.8=Normal (Fehler, wenn PDF Text enthält)
ocr.selectText.9=Zusätzliche Einstellungen
ocr.selectText.10=OCR-Modus
ocr.selectText.11=Bilder nach OCR entfernen (Entfernt ALLE Bilder, nur sinnvoll, wenn Teil des Konvertierungsschritts)
ocr.selectText.12=Rendertyp (Erweitert)
ocr.help=Bitte lesen Sie diese Dokumentation, um zu erfahren, wie Sie dies für andere Sprachen verwenden und/oder nicht in Docker verwenden können
ocr.credit=Dieser Dienst verwendet OCRmyPDF und Tesseract für OCR.
ocr.submit=PDF mit OCR verarbeiten
extractImages.title=Bilder extrahieren
extractImages.header=Bilder extrahieren
extractImages.selectText=Wählen Sie das Bildformat aus, in das extrahierte Bilder konvertiert werden sollen
extractImages.submit=Extrahieren
#File to PDF
fileToPDF.title=Datei in PDF
fileToPDF.header=Beliebige Dateien in PDF konvertieren
fileToPDF.credit=Dieser Dienst verwendet LibreOffice und Unoconv für die Dateikonvertierung.
fileToPDF.supportedFileTypes=Unterstützte Dateitypen sollten die folgenden enthalten, eine vollständige aktualisierte Liste der unterstützten Formate finden Sie jedoch in der LibreOffice-Dokumentation
fileToPDF.submit=In PDF konvertieren
#Add image
addImage.title=Bild hinzufügen
addImage.header=Ein Bild einfügen (Work in progress)
addImage.everyPage=Jede Seite?
addImage.submit=Bild hinzufügen
#compress
compress.title=Komprimieren
compress.header=PDF komprimieren
compress.credit=Dieser Dienst verwendet OCRmyPDF für die PDF-Komprimierung/-Optimierung.
compress.selectText.1=Optimierungsstufe:
compress.selectText.2=0 (Keine Optimierung)
compress.selectText.3=1 (Standard, verlustfreie Optimierung)
compress.selectText.4=2 (Verlustbehaftete Optimierung)
compress.selectText.5=3 (Verlustbehaftete Optimierung, aggressiver)
compress.selectText.6=Schnelle Webansicht aktivieren (PDF linearisieren)
compress.selectText.7=Verlustbehaftete JBIG2-Kodierung aktivieren
compress.submit=Komprimieren
#merge
merge.title=Zusammenführen
merge.header=Mehrere PDFs zusammenführen (2+)
merge.submit=Zusammenführen
#pdfOrganiser
pdfOrganiser.title=Seiten anordnen
pdfOrganiser.header=PDF Seitenorganisation
pdfOrganiser.submit=Seiten anordnen
#Mehrfachwerkzeug
multiTool.title=PDF-Multitool
multiTool.header=PDF-Multitool
#pageRemover
pageRemover.title=Seiten entfernen
pageRemover.header=PDF Seiten entfernen
pageRemover.pagesToDelete=Seiten zu entfernen (geben Sie eine Kommagetrennte Liste der Seitenzahlen an):
pageRemover.submit=Seiten löschen
#rotate
rotate.title=PDF drehen
rotate.header=PDF drehen
rotate.selectAngle=Wählen Sie den Winkel (in Vielfachen von 90 Grad):
rotate.submit=Drehen
#merge
split.title=PDF aufteilen
split.header=PDF aufteilen
split.desc.1=Die Nummern, die Sie auswählen, sind die Seitenzahlen, an denen Sie aufteilen möchten.
split.desc.2=So würde die Auswahl von 1,3,7-8 ein 10-seitiges Dokument in 6 separate PDFs aufteilen, mit:
split.desc.3=Dokument #1: Seite 1
split.desc.4=Dokument #2: Seite 2 und 3
split.desc.5=Dokument #3: Seite 4, 5 und 6
split.desc.6=Dokument #4: Seite 7
split.desc.7=Dokument #5: Seite 8
split.desc.8=Dokument #6: Seite 9 und 10
split.splitPages=Geben Sie die Seiten an, an denen aufgeteilt werden soll:
split.submit=Aufteilen
#merge
imageToPDF.title=Bild zu PDF
imageToPDF.header=Bild zu PDF
imageToPDF.submit=Umwandeln
imageToPDF.selectText.1=Auf Seite strecken
imageToPDF.selectText.2=PDF automatisch drehen
imageToPDF.selectText.3=Mehrere Dateien verarbeiten (nur aktiv, wenn Sie mit mehreren Bildern arbeiten)
imageToPDF.selectText.4=In ein einziges PDF zusammenführen
imageToPDF.selectText.5=In separate PDFs konvertieren
#pdfToImage
pdfToImage.title=PDF zu Bild
pdfToImage.header=PDF zu Bild
pdfToImage.selectText=Bildformat
pdfToImage.singleOrMultiple=Bildergebnistyp
pdfToImage.single=Einzelnes großes Bild
pdfToImage.multi=Mehrere Bilder
pdfToImage.colorType=Farbtyp
pdfToImage.color=Farbe
pdfToImage.grey=Graustufen
pdfToImage.blackwhite=Schwarzweiß (Datenverlust möglich!)
pdfToImage.submit=Umwandeln
#addPassword
addPassword.title=Passwort hinzufügen
addPassword.header=Passwort hinzufügen (Verschlüsseln)
addPassword.selectText.1=Das zu verschlüsselnde PDF auswählen
addPassword.selectText.2=Passwort
addPassword.selectText.3=Länge des Schlüssels
addPassword.selectText.4=Größere Werte sind stärker, aber niedrigere Werte sind besser kompatibel.
addPassword.selectText.5=Zu setzende Berechtigungen
addPassword.selectText.6=Das zusammensetzen des PDFs verhindern
addPassword.selectText.7=Inhaltsextrahierung verhindern
addPassword.selectText.8=Inhaltsextrahierung zur Barrierefreiheit verhindern
addPassword.selectText.9=Ausfüllen des Formulars verhindern
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.submit=Verschlüsseln
#watermark
watermark.title=Wasserzeichen hinzufügen
watermark.header=Wasserzeichen hinzufügen
watermark.selectText.1=PDF auswählen, dem ein Wasserzeichen hinzugefügt werden soll:
watermark.selectText.2=Wasserzeichen Text:
watermark.selectText.3=Schriftgröße:
watermark.selectText.4=Drehung (0-360):
watermark.selectText.5=breiteSpacer (horizontaler Abstand zwischen den einzelnen Wasserzeichen):
watermark.selectText.6=höheSpacer (vertikaler Abstand zwischen den einzelnen Wasserzeichen):
watermark.selectText.7=Deckkraft (0% - 100 %):
watermark.submit=Wasserzeichen hinzufügen
#remove-watermark
remove-watermark.title=Wasserzeichen entfernen
remove-watermark.header=Wasserzeichen entfernen
remove-watermark.selectText.1=PDF auswählen, um Wasserzeichen zu entfernen von:
remove-watermark.selectText.2=Wasserzeichentext:
remove-watermark.submit=Wasserzeichen entfernen
#Change permissions
permissions.title=Berechtigungen ändern
permissions.header=Berechtigungen ändern
permissions.warning=Achtung: Damit diese Berechtigungen nicht geändert werden können, wird empfohlen, sie über die "Passwort hinzufügen"-Seite mit einem Passwort zu versehen
permissions.selectText.1=Das zu ändernde PDF auswählen
permissions.selectText.2=Zu setzende Berechtigungen
permissions.selectText.3=Das zusammensetzen des PDFs verhindern
permissions.selectText.4=Inhaltsextrahierung verhindern
permissions.selectText.5=Inhaltsextrahierung zur Barrierefreiheit verhindern
permissions.selectText.6=Ausfüllen des Formulars verhindern
permissions.selectText.7=Modifizierung verhindern
permissions.selectText.8=Ändern von Kommentaren verhindern
permissions.selectText.9=Drucken verhindern
permissions.selectText.10=Drucken verschiedener Formate verhindern
permissions.submit=Ändern
#remove password
removePassword.title=Passwort entfernen
removePassword.header=Passwort entfernen (Entschlüsseln)
removePassword.selectText.1=Das zu entschlüsselnde PDF auswählen
removePassword.selectText.2=Passwort
removePassword.submit=Entfernen
changeMetadata.title=Metadaten ändern
changeMetadata.header=Metadaten ändern
changeMetadata.selectText.1=Bitte bearbeiten Sie die Variablen, die Sie ändern möchten
changeMetadata.selectText.2=Alle Metadaten löschen
changeMetadata.selectText.3=Benutzerdefinierte Metadaten anzeigen:
changeMetadata.author=Autor:
changeMetadata.creationDate=Erstellungsdatum (jjjj/MM/tt HH:mm:ss):
changeMetadata.creator=Ersteller:
changeMetadata.keywords=Schlüsselwörter:
changeMetadata.modDate=Änderungsdatum (JJJJ/MM/TT HH:mm:ss):
changeMetadata.producer=Produzent:
changeMetadata.subject=Betreff:
changeMetadata.title=Titel:
changeMetadata.trapped=Gefangen:
changeMetadata.selectText.4=Andere Metadaten:
changeMetadata.selectText.5=Benutzerdefinierten Metadateneintrag hinzufügen
changeMetadata.submit=Ändern
xlsToPdf.title=Excel in PDF
xlsToPdf.header=Excel in PDF
xlsToPdf.selectText.1=XLS- oder XLSX-Excel-Tabelle zum Konvertieren auswählen
xlsToPdf.convert=konvertieren
pdfToPDFA.title=PDF zu PDF/A
pdfToPDFA.header=PDF zu PDF/A
pdfToPDFA.credit=Dieser Dienst verwendet OCRmyPDF für die PDF/A-Konvertierung
pdfToPDFA.submit=Konvertieren
PDFToWord.title=PDF zu Word
PDFToWord.header=PDF zu Word
PDFToWord.selectText.1=Ausgabedateiformat
PDFToWord.credit=Dieser Dienst verwendet LibreOffice für die Dateikonvertierung.
PDFToWord.submit=Konvertieren
PDFToPresentation.title=PDF zu Präsentation
PDFToPresentation.header=PDF zu Präsentation
PDFToPresentation.selectText.1=Ausgabedateiformat
PDFToPresentation.credit=Dieser Dienst verwendet LibreOffice für die Dateikonvertierung.
PDFToPresentation.submit=Konvertieren
PDFToText.title=PDF in Text/RTF
PDFToText.header=PDF in Text/RTF
PDFToText.selectText.1=Ausgabedateiformat
PDFToText.credit=Dieser Dienst verwendet LibreOffice für die Dateikonvertierung.
PDFToText.submit=Konvertieren
PDFToHTML.title=PDF in HTML
PDFToHTML.header=PDF in HTML
PDFToHTML.credit=Dieser Dienst verwendet LibreOffice für die Dateikonvertierung.
PDFToHTML.submit=Konvertieren
PDFToXML.title=PDF in XML
PDFToXML.header=PDF in XML
PDFToXML.credit=Dieser Dienst verwendet LibreOffice für die Dateikonvertierung.
PDFToXML.submit=Konvertieren
@@ -1,395 +0,0 @@
###########
# Generic #
###########
# the direction that the language is written (ltr = left to right, rtl = right to left)
language.direction=ltr
pdfPrompt=Select PDF(s)
multiPdfPrompt=Select PDFs (2+)
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) :
goToPage=Go
true=True
false=False
unknown=Unknown
save=Save
close=Close
#############
# HOME-PAGE #
#############
home.desc=Your locally hosted one-stop-shop for all your PDF needs.
navbar.convert=Convert
navbar.security=Security
navbar.other=Other
navbar.darkmode=Dark Mode
navbar.pageOps=Page Operations
home.multiTool.title=PDF Multi Tool
home.multiTool.desc=Merge, Rotate, Rearrange, and Remove pages
home.merge.title=Merge
home.merge.desc=Easily merge multiple PDFs into one.
home.split.title=Split
home.split.desc=Split PDFs into multiple documents
home.rotate.title=Rotate
home.rotate.desc=Easily rotate your PDFs.
home.imageToPdf.title=Image to PDF
home.imageToPdf.desc=Convert a image (PNG, JPEG, GIF) to PDF.
home.pdfToImage.title=PDF to Image
home.pdfToImage.desc=Convert a PDF to a image. (PNG, JPEG, GIF)
home.pdfOrganiser.title=Organise
home.pdfOrganiser.desc=Remove/Rearrange pages in any order
home.addImage.title=Add image onto PDF
home.addImage.desc=Adds a image onto a set location on the PDF (Work in progress)
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
home.removePages.title=Remove
home.removePages.desc=Delete unwanted pages from your PDF document.
home.addPassword.title=Add Password
home.addPassword.desc=Encrypt your PDF document with a password.
home.removePassword.title=Remove Password
home.removePassword.desc=Remove password protection from your PDF document.
home.compressPdfs.title=Compress
home.compressPdfs.desc=Compress PDFs to reduce their file size.
home.changeMetadata.title=Change Metadata
home.changeMetadata.desc=Change/Remove/Add metadata from a PDF document
home.fileToPDF.title=Convert file to PDF
home.fileToPDF.desc=Convert nearly any file to PDF (DOCX, PNG, XLS, PPT, TXT and more)
home.ocr.title=Run OCR and/or Cleanup scans
home.ocr.desc=Cleanup scans and detects text from images within a PDF and re-adds it as text.
home.extractImages.title=Extract Images
home.extractImages.desc=Extracts all images from a PDF and saves them to zip
home.pdfToPDFA.title=PDF to PDF/A
home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage
home.PDFToWord.title=PDF to Word
home.PDFToWord.desc=Convert PDF to Word formats (DOC, DOCX and ODT)
home.PDFToPresentation.title=PDF to Presentation
home.PDFToPresentation.desc=Convert PDF to Presentation formats (PPT, PPTX and ODP)
home.PDFToText.title=PDF to Text/RTF
home.PDFToText.desc=Convert PDF to Text or RTF format
home.PDFToHTML.title=PDF to HTML
home.PDFToHTML.desc=Convert PDF to HTML format
home.PDFToXML.title=PDF to XML
home.PDFToXML.desc=Convert PDF to XML format
home.ScannerImageSplit.title=Detect/Split Scanned photos
home.ScannerImageSplit.desc=Splits multiple photos from within a photo/PDF
ScannerImageSplit.selectText.1=Angle Threshold:
ScannerImageSplit.selectText.2=Sets the minimum absolute angle required for the image to be rotated (default: 10).
ScannerImageSplit.selectText.3=Tolerance:
ScannerImageSplit.selectText.4=Determines the range of color variation around the estimated background color (default: 30).
ScannerImageSplit.selectText.5=Minimum Area:
ScannerImageSplit.selectText.6=Sets the minimum area threshold for a photo (default: 10000).
ScannerImageSplit.selectText.7=Minimum Contour Area:
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
ScannerImageSplit.selectText.9=Border Size:
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
navbar.settings=Settings
settings.title=Settings
settings.update=Update available
settings.appVersion=App Version:
settings.downloadOption.title=Choose download option (For single file non zip downloads):
settings.downloadOption.1=Open in same window
settings.downloadOption.2=Open in new window
settings.downloadOption.3=Download file
settings.zipThreshold=Zip files when the number of downloaded files exceeds
#OCR
ocr.title=OCR / Scan Cleanup
ocr.header=Cleanup Scans / OCR (Optical Character Recognition)
ocr.selectText.1=Select languages that are to be detected within the PDF (Ones listed are the ones currently detected):
ocr.selectText.2=Produce text file containing OCR text alongside the OCR'ed PDF
ocr.selectText.3=Correct pages were scanned at a skewed angle by rotating them back into place
ocr.selectText.4=Clean page so its less likely that OCR will find text in background noise. (No output change)
ocr.selectText.5=Clean page so its less likely that OCR will find text in background noise, maintains cleanup in output.
ocr.selectText.6=Ignores pages that have interacive text on them, only OCRs pages that are images
ocr.selectText.7=Force OCR, will OCR Every page removing all original text elements
ocr.selectText.8=Normal (Will error if PDF contains text)
ocr.selectText.9=Additional Settings
ocr.selectText.10=OCR Mode
ocr.selectText.11=Remove images after OCR (Removes ALL images, only useful if part of conversion step)
ocr.selectText.12=Render Type (Advanced)
ocr.help=Please read this documentation on how to use this for other languages and/or use not in docker
ocr.credit=This service uses OCRmyPDF and Tesseract for OCR.
ocr.submit=Process PDF with OCR
extractImages.title=Extract Images
extractImages.header=Extract Images
extractImages.selectText=Select image format to convert extracted images to
extractImages.submit=Extract
#File to PDF
fileToPDF.title=File to PDF
fileToPDF.header=Convert any file to PDF
fileToPDF.credit=This service uses LibreOffice and Unoconv for file conversion.
fileToPDF.supportedFileTypes=Supported file types should include the below however for a full updated list of supported formats, please refer to the LibreOffice documentation
fileToPDF.submit=Convert to PDF
#compress
compress.title=Compress
compress.header=Compress PDF
compress.credit=This service uses OCRmyPDF for PDF Compress/Optimisation.
compress.selectText.1=Optimization level:
compress.selectText.2=0 (No optimization)
compress.selectText.3=1 (Default, lossless optimization)
compress.selectText.4=2 (Lossy optimization)
compress.selectText.5=3 (Lossy optimization, more aggressive)
compress.selectText.6=Enable fast web view (linearize PDF)
compress.selectText.7=Enable lossy JBIG2 encoding
compress.submit=Compress
#Add image
addImage.title=Add Image
addImage.header=Add image to PDF (Work in progress)
addImage.everyPage=Every Page?
addImage.submit=Add image
#merge
merge.title=Merge
merge.header=Merge multiple PDFs (2+)
merge.submit=Merge
#pdfOrganiser
pdfOrganiser.title=Page Organiser
pdfOrganiser.header=PDF Page Organiser
pdfOrganiser.submit=Rearrange Pages
#multiTool
multiTool.title=PDF Multi Tool
multiTool.header=PDF Multi Tool
#pageRemover
pageRemover.title=Page Remover
pageRemover.header=PDF Page remover
pageRemover.pagesToDelete=Pages to delete (Enter a comma-separated list of page numbers) :
pageRemover.submit=Delete Pages
#rotate
rotate.title=Rotate PDF
rotate.header=Rotate PDF
rotate.selectAngle=Select rotation angle (in multiples of 90 degrees):
rotate.submit=Rotate
#merge
split.title=Split PDF
split.header=Split PDF
split.desc.1=The numbers you select are the page number you wish to do a split on
split.desc.2=As such selecting 1,3,7-8 would split a 10 page document into 6 separate PDFS with:
split.desc.3=Document #1: Page 1
split.desc.4=Document #2: Page 2 and 3
split.desc.5=Document #3: Page 4, 5 and 6
split.desc.6=Document #4: Page 7
split.desc.7=Document #5: Page 8
split.desc.8=Document #6: Page 9 and 10
split.splitPages=Enter pages to split on:
split.submit=Split
#merge
imageToPDF.title=Image to PDF
imageToPDF.header=Image to PDF
imageToPDF.submit=Convert
imageToPDF.selectText.1=Stretch to fit
imageToPDF.selectText.2=Auto rotate PDF
imageToPDF.selectText.3=Multi file logic (Only enabled if working with multiple images)
imageToPDF.selectText.4=Merge into single PDF
imageToPDF.selectText.5=Convert to separate PDFs
#pdfToImage
pdfToImage.title=PDF to Image
pdfToImage.header=PDF to Image
pdfToImage.selectText=Image Format
pdfToImage.singleOrMultiple=Image result type
pdfToImage.single=Single Big Image
pdfToImage.multi=Multiple Images
pdfToImage.colorType=Colour type
pdfToImage.color=Colour
pdfToImage.grey=Greyscale
pdfToImage.blackwhite=Black and White (May lose data!)
pdfToImage.submit=Convert
#addPassword
addPassword.title=Add Password
addPassword.header=Add password (Encrypt)
addPassword.selectText.1=Select PDF to encrypt
addPassword.selectText.2=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.6=Prevent assembly of document
addPassword.selectText.7=Prevent content extraction
addPassword.selectText.8=Prevent extraction for accessibility
addPassword.selectText.9=Prevent filling in form
addPassword.selectText.10=Prevent modification
addPassword.selectText.11=Prevent annotation modification
addPassword.selectText.12=Prevent printing
addPassword.selectText.13=Prevent printing different formats
addPassword.submit=Encrypt
#watermark
watermark.title=Add Watermark
watermark.header=Add Watermark
watermark.selectText.1=Select PDF to add watermark to:
watermark.selectText.2=Watermark Text:
watermark.selectText.3=Font Size:
watermark.selectText.4=Rotation (0-360):
watermark.selectText.5=widthSpacer (Space between each watermark horizontally):
watermark.selectText.6=heightSpacer (Space between each watermark vertically):
watermark.selectText.7=Opacity (0% - 100%):
watermark.submit=Add Watermark
#remove-watermark
remove-watermark.title=Remove Watermark
remove-watermark.header=Remove Watermark
remove-watermark.selectText.1=Select PDF to remove watermark from:
remove-watermark.selectText.2=Watermark Text:
remove-watermark.submit=Remove Watermark
#Change permissions
permissions.title=Change Permissions
permissions.header=Change Permissions
permissions.warning=Warning to have these permissions be unchangeable it is recommended to set them with a password via the add-password page
permissions.selectText.1=Select PDF to change permissions
permissions.selectText.2=Permissions to set
permissions.selectText.3=Prevent assembly of document
permissions.selectText.4=Prevent content extraction
permissions.selectText.5=Prevent extraction for accessibility
permissions.selectText.6=Prevent filling in form
permissions.selectText.7=Prevent modification
permissions.selectText.8=Prevent annotation modification
permissions.selectText.9=Prevent printing
permissions.selectText.10=Prevent printing different formats
permissions.submit=Change
#remove password
removePassword.title=Remove password
removePassword.header=Remove password (Decrypt)
removePassword.selectText.1=Select PDF to Decrypt
removePassword.selectText.2=Password
removePassword.submit=Remove
changeMetadata.title=Change Metadata
changeMetadata.header=Change Metadata
changeMetadata.selectText.1=Please edit the variables you wish to change
changeMetadata.selectText.2=Delete all metadata
changeMetadata.selectText.3=Show Custom Metadata:
changeMetadata.author=Author:
changeMetadata.creationDate=Creation Date (yyyy/MM/dd HH:mm:ss):
changeMetadata.creator=Creator:
changeMetadata.keywords=Keywords:
changeMetadata.modDate=Modification Date (yyyy/MM/dd HH:mm:ss):
changeMetadata.producer=Producer:
changeMetadata.subject=Subject:
changeMetadata.title=Title:
changeMetadata.trapped=Trapped:
changeMetadata.selectText.4=Other Metadata:
changeMetadata.selectText.5=Add Custom Metadata Entry
changeMetadata.submit=Change
xlsToPdf.title=Excel to PDF
xlsToPdf.header=Excel to PDF
xlsToPdf.selectText.1=Select XLS or XLSX Excel sheet to convert
xlsToPdf.convert=convert
pdfToPDFA.title=PDF To PDF/A
pdfToPDFA.header=PDF To PDF/A
pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
pdfToPDFA.submit=Convert
PDFToWord.title=PDF to Word
PDFToWord.header=PDF to Word
PDFToWord.selectText.1=Output file format
PDFToWord.credit=This service uses LibreOffice for file conversion.
PDFToWord.submit=Convert
PDFToPresentation.title=PDF to Presentation
PDFToPresentation.header=PDF to Presentation
PDFToPresentation.selectText.1=Output file format
PDFToPresentation.credit=This service uses LibreOffice for file conversion.
PDFToPresentation.submit=Convert
PDFToText.title=PDF to Text/RTF
PDFToText.header=PDF to Text/RTF
PDFToText.selectText.1=Output file format
PDFToText.credit=This service uses LibreOffice for file conversion.
PDFToText.submit=Convert
PDFToHTML.title=PDF to HTML
PDFToHTML.header=PDF to HTML
PDFToHTML.credit=This service uses LibreOffice for file conversion.
PDFToHTML.submit=Convert
PDFToXML.title=PDF to XML
PDFToXML.header=PDF to XML
PDFToXML.credit=This service uses LibreOffice for file conversion.
PDFToXML.submit=Convert
@@ -1,378 +0,0 @@
###########
# Generic #
###########
# the direction that the language is written (ltr = left to right, rtl = right to left)
language.direction=ltr
pdfPrompt=Selecciona PDF(s)
multiPdfPrompt=Selecciona PDFs (2+)
multiPdfDropPrompt=Selecciona (o arrastra y suelta) todos los PDFs que quieras
imgPrompt=Selecciona 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
true=Verdadero
false=Falso
unknown=Desconocido
save=Guardar
close=Cerrar
#############
# HOME-PAGE #
#############
home.desc=Tu autohospedada ventanilla única para todas tus necesidades PDF.
navbar.convert=Convertir
navbar.security=Seguridad
navbar.other=Otro
navbar.darkmode=Modo oscuro
navbar.pageOps=Operaciones de página
home.multiTool.title=Multiherramienta 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.split.title=Divide
home.split.desc=Divide PDFs en múltiples documentos
home.rotate.title=Rota
home.rotate.desc=Rota fácilmente tus PDFs.
home.imageToPdf.title=Imagen a PDF
home.imageToPdf.desc=Convierte una imagen (PNG, JPEG, GIF) a PDF.
home.pdfToImage.title=PDF a Imagen
home.pdfToImage.desc=Convierte un PDF a una imagen. (PNG, JPEG, GIF)
home.pdfOrganiser.title=Organizador
home.pdfOrganiser.desc=Elimina/Reorganiza páginas en cualquier orden
home.addImage.title=Agregar imagen al PDF
home.addImage.desc=Agrega una imagen en una ubicación establecida en el PDF (trabajo en progreso)
home.watermark.title=Añade marca de agua
home.watermark.desc=Añade una marca de agua predefinida a tu documento PDF.
home.remove-watermark.title=Elimina marca de agua
home.remove-watermark.desc=Elimina marcas de agua de tu documento PDF.
home.permissions.title=Cambia Permisos
home.permissions.desc=Cambia los permisos de tu documento PDF
home.removePages.title=Elimina
home.removePages.desc=Elimina páginas no deseadas de tu documento PDF.
home.addPassword.title=Añade Contraseña
home.addPassword.desc=Encripta tu documento PDF con una contraseña.
home.removePassword.title=Elimina Contraseña
home.removePassword.desc=Elimina la contraseña de tu documento PDF.
home.compressPdfs.title=Comprime
home.compressPdfs.desc=Comprime PDFs para reducir el tamaño del fichero.
home.changeMetadata.title=Cambia Metadatos
home.changeMetadata.desc=Cambia/Elimina/Añade metadatos a tu documento PDF.
home.fileToPDF.title=Convierte fichero a PDF
home.fileToPDF.desc=Convierte casi cualquier archivo a PDF (DOCX, PNG, XLS, PPT, TXT y más)
home.ocr.title=Ejecute 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.extractImages.title=Extraer imágenes
home.extractImages.desc=Extrae todas las imágenes de un PDF y las guarda en zip
home.pdfToPDFA.title=Convierte PDF to PDF/A
home.pdfToPDFA.desc=Convierte PDF to PDF/A para almacenamiento a largo plazo
home.PDFToWord.title=PDF a Word
home.PDFToWord.desc=Convertir formatos PDF a Word (DOC, DOCX y ODT)
home.PDFToPresentation.title=PDF a presentación
home.PDFToPresentation.desc=Convertir PDF a formatos de presentación (PPT, PPTX y ODP)
home.PDFToText.title=PDF a texto/RTF
home.PDFToText.desc=Convertir PDF a texto o formato RTF
home.PDFToHTML.title=PDF a HTML
home.PDFToHTML.desc=Convertir PDF a formato HTML
home.PDFToXML.title=PDF a XML
home.PDFToXML.desc=Convertir PDF a formato XML
home.ScannerImageSplit.title=Detectar/Dividir fotos escaneadas
home.ScannerImageSplit.desc=Dividir varias fotos dentro de una foto/PDF
ScannerImageSplit.selectText.1=Umbral de ángulo:
ScannerImageSplit.selectText.2=Establece 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.5=Área mínima:
ScannerImageSplit.selectText.6=Establece 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.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).
navbar.settings=Ajustes
settings.title=Ajustes
settings.update=Actualización disponible
settings.appVersion=Version de la aplicacion:
settings.downloadOption.title=Elija 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.zipThreshold=Ficheros Zip cuando excede el número de ficheros descargados
#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.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
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.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.submit=Convertir a PDF
#compress
compress.title=Comprimir
compress.header=Comprimir PDF
compress.credit=Este servicio usa OCRmyPDF para la Compresión/Optimizatión del PDF.
compress.selectText.1=Nivel de Optimización:
compress.selectText.2=0 (Sin optimización)
compress.selectText.3=1 (Por defecto, optimización sin pérdidas)
compress.selectText.4=2 (Optimización con pérdida)
compress.selectText.5=3 (Optimización con pérdida, más agresiva)
compress.selectText.6=Habilita la vista web rápida (linealizar PDF)
compress.selectText.7=Habilita la codificación JBIG2 con pérdida
compress.submit=Comprimir
#Add image
addImage.title=Añade Imagen
addImage.header=Añade image de PDF (Trabajo en progreso)
addImage.everyPage=¿Todas las páginas?
addImage.submit=Añade imagen
#merge
merge.title=Une
merge.header=Une múltiples PDFs (2+)
merge.submit=Une
#pdfOrganiser
pdfOrganiser.title=Organizador de páginas
pdfOrganiser.header=Organizador de páginas PDF
pdfOrganiser.submit=Organiza páginas
#herramienta multiple
multiTool.title=Multiherramienta PDF
multiTool.header=Multiherramienta 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.submit=Elimina Páginas
#rotate
rotate.title=Rotar PDF
rotate.header=Rotar PDF
rotate.SeleccionaAngle=Selecciona ángulo de rotación (múltiple de 90 grados):
rotate.submit=Rotar
#merge
split.title=Dividir PDF
split.header=Dividir PDF
split.desc.1=Los números que selecciona 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
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=Introduzca las páginas para dividir:
split.submit=Dividir
#merge
imageToPDF.title=Imagen a PDF
imageToPDF.header=Imagen a PDF
imageToPDF.submit=Convertir
imageToPDF.selectText.1=Estirar para ajustar
imageToPDF.selectText.2=Auto rotación PDF
imageToPDF.selectText.3=Lógica de archivos múltiples (Únicamente activado si funciona con multiples imágenes)
imageToPDF.selectText.4=Une en un único PDF
imageToPDF.selectText.5=Convertir a PDFs separados
#pdfToImage
pdfToImage.title=PDF a Imagen
pdfToImage.header=PDF a Imagen
pdfToImage.selectText=Formato de Imagen
pdfToImage.singleOrMultiple=Tipo resultante de imagen
pdfToImage.single=Imagen Grande Única
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.submit=Convertir
#addPassword
addPassword.title=Añade Contraseña
addPassword.header=Añade contraseña (Encripta)
addPassword.selectText.1=Selecciona 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.5=Permisos para establecer
addPassword.selectText.6=Impedir el ensamblaje del documento
addPassword.selectText.7=Impedir la extracción de contenido
addPassword.selectText.8=Impedir la extracción para la accesibilidad
addPassword.selectText.9=Impedir rellenar formulario
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.submit=Encripta
#watermark
watermark.title=Añade marca de agua
watermark.header=Añade marca de agua
watermark.selectText.1=Selecciona PDF para añadir marca de agua:
watermark.selectText.2=Texto de la marca de agua:
watermark.selectText.3=Tamaño de la Fuente:
watermark.selectText.4=Rotación (0-360):
watermark.selectText.5=Ancho (Espacio entre cada marca de agua horizontalmente):
watermark.selectText.6=Alto (Espacio entre cada marca de agua verticalmente):
watermark.selectText.7=Opacidad (0% - 100%):
watermark.submit=Añade marca de agua
#remove-watermark
remove-watermark.title=Elimina marca de agua
remove-watermark.header=Elimina marca de agua
remove-watermark.selectText.1=Selecciona PDF para eliminar la marca de agua:
remove-watermark.selectText.2=Texto de la marca de agua:
remove-watermark.submit=Elimina marca de agua
#Change permissions
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=Selecciona PDF para cambiar los permisos
permissions.selectText.2=Permisos a establecer
permissions.selectText.3=Impedir el ensamblaje del documento
permissions.selectText.4=Impedir la extracción de contenido
permissions.selectText.5=Impedir la extracción para la accesibilidad
permissions.selectText.6=Impedir rellenar formulario
permissions.selectText.7=Impedir modificación
permissions.selectText.8=Impedir modificación de anotaciones
permissions.selectText.9=Impedir imprimir
permissions.selectText.10=Impedir imprimir diferentes formatos
permissions.submit=Cambiar
#remove password
removePassword.title=Elimina contraseña
removePassword.header=Elimina contraseña (Desencripta)
removePassword.selectText.1=Selecciona PDF para Desencriptar
removePassword.selectText.2=Contraseña
removePassword.submit=Elimina
changeMetadata.title=Cambia Metadatos
changeMetadata.header=Cambia Metadatos
changeMetadata.selectText.1=Edite las variables que desea cambiar
changeMetadata.selectText.2=Elimina todos los metadatos
changeMetadata.selectText.3=Mostrar metadatos personalizados:
changeMetadata.author=Autor:
changeMetadata.creationDate=Fecha de Creación (yyyy/MM/dd HH:mm:ss):
changeMetadata.creator=Creador:
changeMetadata.keywords=Palabras clave:
changeMetadata.modDate=Fecha de Modificación (yyyy/MM/dd HH:mm:ss):
changeMetadata.producer=Productor:
changeMetadata.subject=Asunto:
changeMetadata.title=Título:
changeMetadata.trapped=Trapped:
changeMetadata.selectText.4=Otros Metadatos:
changeMetadata.selectText.5=Agregar entrada de metadatos personalizados
changeMetadata.submit=Cambia
xlsToPdf.title=Excel a PDF
xlsToPdf.header=Excel a PDF
xlsToPdf.selectText.1=Selecciona hoja de cálculo de Excel XLS o XLSX para convertir
xlsToPdf.convert=convertir
pdfToPDFA.title=PDF a PDF/A
pdfToPDFA.header=PDF a PDF/A
pdfToPDFA.credit=Este servicio usa OCRmyPDF para la conversión a PDF/A
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.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.submit=Convertir
PDFToText.title=PDF a texto/RTF
PDFToText.header=PDF a texto/RTF
PDFToText.selectText.1=Formato de archivo de salida
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.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.submit=Convertir
@@ -1,379 +0,0 @@
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#
# Translated by Google Translate #
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#
###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl=right to left)
language.direction=ltr
pdfPrompt=Choisir PDF
multiPdfPrompt=Choisir des PDF (2+)
multiPdfDropPrompt=Sélectionnez (ou glissez-déposez) tous les PDF dont vous avez besoin
imgPrompt=Choisir une image
genericSubmit=Soumettre
processTimeWarning=Attention: ce processus peut prendre jusqu'à une minute en fonction de la taille du fichier
pageOrderPrompt=Ordre des pages (Entrez une liste de numéros de page séparés par des virgules):
goToPage=Aller
true=Vrai
false=Faux
unknown=Inconnu
save=Enregistrer
close=Fermer
#############
# HOME-PAGE #
#############
home.desc=Votre guichet unique hébergé localement pour tous vos besoins PDF.
navbar.convert=Convertir
navbar.security=Sécurité
navbar.other=Autre
navbar.darkmode=Mode sombre
navbar.pageOps=Opérations de page
home.multiTool.title=Multi-outil PDF
home.multiTool.desc=Fusionner, faire pivoter, réorganiser et supprimer des pages
home.merge.title=Fusionnez
home.merge.desc=Fusionnez facilement plusieurs PDF en un seul.
home.split.title=Fractionner
home.split.desc=Diviser les PDF en plusieurs documents
home.rotate.title=Tourner
home.rotate.desc=Faites pivoter facilement vos PDF.
home.imageToPdf.title=Image au format PDF
home.imageToPdf.desc=Convertir une image (PNG, JPEG, GIF) en PDF.
home.pdfToImage.title=PDF vers image
home.pdfToImage.desc=Convertir un PDF en image. (PNG, JPEG, GIF)
home.pdfOrganiser.title=Organisateur
home.pdfOrganiser.desc=Supprimer/Réorganiser les pages dans n'importe quel ordre
home.addImage.title=Ajouter une image au PDF
home.addImage.desc=Ajoute une image à un emplacement défini sur le PDF (Travail en cours)
home.watermark.title=Ajouter un filigrane
home.watermark.desc=Ajoutez un filigrane personnalisé à votre document PDF.
home.remove-watermark.title=Supprimer le filigrane
home.remove-watermark.desc=Supprimez les filigranes de votre document PDF.
home.permissions.title=Modifier les autorisations
home.permissions.desc=Modifier les permissions de votre document PDF
home.removePages.title=Supprimer
home.removePages.desc=Supprimez les pages inutiles de votre document PDF.
home.addPassword.title=Ajouter un mot de passe
home.addPassword.desc=Cryptez votre document PDF avec un mot de passe.
home.removePassword.title=Supprimer le mot de passe
home.removePassword.desc=Supprimez la protection par mot de passe de votre document PDF.
home.compressPdfs.title=Compresser
home.compressPdfs.desc=Compressez les PDF pour réduire leur taille de fichier.
home.changeMetadata.title=Modifier les métadonnées
home.changeMetadata.desc=Modifier/Supprimer/Ajouter des métadonnées d'un document PDF
home.fileToPDF.title=Convertir un fichier en PDF
home.fileToPDF.desc=Convertissez presque n\u2019importe quel fichier en PDF (DOCX, PNG, XLS, PPT, TXT et plus)
home.ocr.title=Exécuter l'OCR sur les scans PDF et/ou de nettoyage
home.ocr.desc=Le nettoyage analyse et détecte le texte des images dans un PDF et le rajoute en tant que texte.
home.extractImages.title=Extraire les images
home.extractImages.desc=Extrait toutes les images d\u2019un PDF et les enregistre au format zip
home.pdfToPDFA.title=Convertir PDF en PDF/A
home.pdfToPDFA.desc=Convertir un PDF en PDF/A pour un stockage à long terme
home.PDFToWord.title=PDF vers Word
home.PDFToWord.desc=Convertir les formats PDF en Word (DOC, DOCX et ODT)
home.PDFToPresentation.title=PDF vers présentation
home.PDFToPresentation.desc=Convertir des PDF en formats de présentation (PPT, PPTX et ODP)
home.PDFToText.title=PDF vers texte/RTF
home.PDFToText.desc=Convertir un PDF au format Texte ou RTF
home.PDFToHTML.title=PDF vers HTML
home.PDFToHTML.desc=Convertir le PDF au format HTML
home.PDFToXML.title=PDF vers XML
home.PDFToXML.desc=Convertir le PDF au format XML
home.ScannerImageSplit.title=Détecter/diviser les photos numérisées
home.ScannerImageSplit.desc=Divise plusieurs photos à partir d'une photo/PDF
ScannerImageSplit.selectText.1=Seuil d'angle :
ScannerImageSplit.selectText.2=Définit l'angle absolu minimum requis pour la rotation de l'image (par défaut : 10).
ScannerImageSplit.selectText.3=Tolérance :
ScannerImageSplit.selectText.4=Détermine la plage de variation de couleur autour de la couleur d'arrière-plan estimée (par défaut : 30).
ScannerImageSplit.selectText.5=Zone minimale :
ScannerImageSplit.selectText.6=Définit le seuil de zone minimum pour une photo (par défaut : 10000).
ScannerImageSplit.selectText.7=Zone de contour minimale :
ScannerImageSplit.selectText.8=Définit le seuil de zone de contour minimum pour une photo
ScannerImageSplit.selectText.9=Taille de la bordure :
ScannerImageSplit.selectText.10=Définit la taille de la bordure ajoutée et supprimée pour éviter les bordures blanches dans la sortie (par défaut : 1).
navbar.settings=Paramètres
settings.title=Paramètres
settings.update=Mise à jour disponible
settings.appVersion=Version de l'application :
settings.downloadOption.title=Choisissez l'option de téléchargement (pour les téléchargements sans fichier unique) :
settings.downloadOption.1=Ouvrir dans la même fenêtre
settings.downloadOption.2=Ouvrir dans une nouvelle fenêtre
settings.downloadOption.3=Fichier téléchargé
settings.zipThreshold=Zip les fichiers lorsque le nombre de fichiers téléchargés dépasse
#OCR
ocr.title=OCR / Nettoyage de numérisation
ocr.header=Nettoyage des scans / OCR (reconnaissance optique des caractères)
ocr.selectText.1=Sélectionnez les langues à détecter dans le PDF (celles répertoriées sont celles actuellement détectées) :
ocr.selectText.2=Produire un fichier texte contenant du texte OCR avec le PDF OCR
ocr.selectText.3=Les pages correctes ont été numérisées à un angle oblique en les remettant en place
ocr.selectText.4=Nettoyer la page pour qu'il soit moins probable que l'OCR trouve du texte dans le bruit de fond. (Pas de changement de sortie)
ocr.selectText.5=Nettoyer la page afin qu'il soit moins probable que l'OCR trouve du texte dans le bruit de fond, maintient le nettoyage dans la sortie.
ocr.selectText.6=Ignore les pages contenant du texte interactif, seulement les pages OCR qui sont des images
ocr.selectText.7=Forcer l'OCR, OCR chaque page supprimera tous les éléments de texte d'origine
ocr.selectText.8=Normal (Erreur si le PDF contient du texte)
ocr.selectText.9=Paramètres supplémentaires
ocr.selectText.10=Mode ROC
ocr.selectText.11=Supprimer les images après l'OCR (Supprime TOUTES les images, utile uniquement si elles font partie de l'étape de conversion)
ocr.selectText.12=Type de rendu (avancé)
ocr.help=Veuillez lire cette documentation pour savoir comment l'utiliser pour d'autres langues et/ou une utilisation non dans docker
ocr.credit=Ce service utilise OCRmyPDF et Tesseract pour l'OCR.
ocr.submit=Traiter PDF avec OCR
extractImages.title=Extraire les images
extractImages.header=Extraire les images
extractImages.selectText=Sélectionner le format d'image pour convertir les images extraites en
extractImages.submit=Extraire
#File to PDF
fileToPDF.title=Fichier au format PDF
fileToPDF.header=Convertir n'importe quel fichier au format PDF
fileToPDF.credit=Ce service utilise LibreOffice et Unoconv pour la conversion de fichiers.
fileToPDF.supportedFileTypes=Les types de fichiers pris en charge doivent inclure les éléments ci-dessous, mais pour une liste complète et mise à jour des formats pris en charge, veuillez vous référer à la documentation de LibreOffice.
fileToPDF.submit=Convertir en PDF
#Add image
addImage.title=Ajouter une image
addImage.header=Ajouter une image au PDF (Travail en cours)
addImage.everyPage=Chaque page?
addImage.submit=Ajouter une image
#compress
compress.title=Compresser
compress.header=Compresser le PDF
compress.credit=Ce service utilise OCRmyPDF pour la compression/optimisation PDF.
compress.selectText.1=Niveau d'optimisation :
compress.selectText.2=0 (pas d'optimisation)
compress.selectText.3=1 (par défaut, optimisation sans perte)
compress.selectText.4=2 (optimisation avec perte)
compress.selectText.5=3 (optimisation avec perte, plus agressive)
compress.selectText.6=Activer l'affichage Web rapide (linéariser PDF)
compress.selectText.7=Activer l'encodage JBIG2 avec perte
compress.submit=Compresser
#merge
merge.title=Fusionner
merge.header=Fusionner plusieurs PDF (2+)
merge.submit=Fusionner
#pdfOrganiser
pdfOrganiser.title=Organisateur de pages
pdfOrganiser.header=Organisateur de pages PDF
pdfOrganiser.submit=Réorganiser les pages
#Outil Multi-fonction
multiTool.title=Multi-outil PDF
multiTool.header=Outil multiple PDF
#pageRemover
pageRemover.title=Suppresseur de pages
pageRemover.header=Outil de suppression de pages PDF
pageRemover.pagesToDelete=Pages à supprimer (Entrez une liste de numéros de page séparés par des virgules):
pageRemover.submit=Supprimer des pages
#rotate
rotate.title=Faire pivoter le PDF
rotate.header=Faire pivoter le PDF
rotate.selectAngle=Sélectionner l'angle de rotation (en multiples de 90 degrés) :
rotate.submit=Rotation
#Split PDF
split.title=Fractionner le PDF
split.header=Diviser le PDF
split.desc.1=Les numéros que vous sélectionnez sont le numéro de page sur lequel vous souhaitez faire un fractionnement.
split.desc.2=Ainsi, la sélection de 1,3,7-8 diviserait un document de 10 pages en 6 PDF distincts avec :
split.desc.3=Document #1 : Page 1
split.desc.4=Document #2 : Pages 2 et 3
split.desc.5=Document #3 : Pages 4, 5 et 6
split.desc.6=Document #4 : Page 7
split.desc.7=Document #5 : Page 8
split.desc.8=Document #6 : Pages 9 et 10
split.splitPages=Entrez les pages sur lesquelles fractionner :
split.submit=Diviser
#imageToPDF
imageToPDF.title=Image au format PDF
imageToPDF.header=Image au format PDF
imageToPDF.submit=Convertir
imageToPDF.selectText.1=Étirer pour s'adapter
imageToPDF.selectText.2=Rotation automatique du PDF
imageToPDF.selectText.3=Logique de fichiers multiples (activé uniquement si vous travaillez avec plusieurs images)
imageToPDF.selectText.4=Fusionner en un seul PDF
imageToPDF.selectText.5=Convertir en PDFs distincts
#PDF to Image
pdfToImage.title=PDF vers image
pdfToImage.header=PDF vers image
pdfToImage.selectText=Format d'image
pdfToImage.singleOrMultiple=Type de résultat d'image
pdfToImage.single=Une seule grande image
pdfToImage.multi=Plusieurs images
pdfToImage.colorType=Type de couleur
pdfToImage.color=Couleur
pdfToImage.grey=Niveaux de gris
pdfToImage.blackwhite=Noir et Blanc (Peut perdre des données !)
pdfToImage.submit=Convertir
#addPassword
addPassword.title=Ajouter un mot de passe
addPassword.header=Ajouter un mot de passe (chiffrer)
addPassword.selectText.1=Sélectionnez le PDF à chiffrer
addPassword.selectText.2=Mot de passe
addPassword.selectText.3=Longueur de la clé de chiffrement
addPassword.selectText.4=Les valeurs supérieures sont plus fortes, mais les valeurs inférieures ont une meilleure compatibilité.
addPassword.selectText.5=Autorisations à définir
addPassword.selectText.6=Empêcher l'assemblage du document
addPassword.selectText.7=Empêcher l'extraction de contenu
addPassword.selectText.8=Empêcher l'extraction pour l'accessibilité
addPassword.selectText.9=Empêcher de remplir le formulaire
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.submit=Crypter
#watermark
watermark.title=Ajouter un filigrane
watermark.header=Ajouter un filigrane
watermark.selectText.1=Sélectionnez le PDF auquel ajouter un filigrane :
watermark.selectText.2=Texte du filigrane :
watermark.selectText.3=Taille de la police :
watermark.selectText.4=Rotation (0-360) :
watermark.selectText.5=widthSpacer (Espace entre chaque filigrane horizontalement) :
watermark.selectText.6=heightSpacer (Espace entre chaque filigrane verticalement) :
watermark.selectText.7=Opacité (0 % - 100 %) :
watermark.submit=Ajouter un filigrane
#remove-watermark
remove-watermark.title=Supprimer le filigrane
remove-watermark.header=Supprimer le filigrane
remove-watermark.selectText.1=Sélectionnez le PDF pour supprimer le filigrane :
remove-watermark.selectText.2=Texte du filigrane :
remove-watermark.submit=Supprimer le filigrane
#Change Permissions
permissions.title=Modifier les autorisations
permissions.header=Modifier les autorisations
permissions.warning=Attention pour que ces permissions soient immuables il est recommandé de les définir avec un mot de passe via la page add-password.
permissions.selectText.1=Sélectionnez le PDF pour modifier les autorisations :
permissions.selectText.2=Autorisations à définir :
permissions.selectText.3=Employer l'assemblage du document
permissions.selectText.4=Employer l'extraction de contenu
permissions.selectText.5=Employer l'extraction pour l'accessibilité
permissions.selectText.6=Employer pour remplir le formulaire
permissions.selectText.7=Employer pour la modification
permissions.selectText.8=Employer pour la modification des annotations
permissions.selectText.9=Employer pour l'impression
permissions.selectText.10=Empêcher l'impression de différents formats
permissions.submit=Modificateur
#supprimer le mot de passe
removePassword.title=Supprimer le mot de passe
removePassword.header=Supprimer le mot de passe (Déchiffrer)
removePassword.selectText.1=Sélectionnez le PDF à déchiffrer
removePassword.selectText.2=Mot de passe
removePassword.submit=Supprimer
#Change Metadata
changeMetadata.title=Modifier les métadonnées
changeMetadata.header=Modifier les métadonnées
changeMetadata.selectText.1=Veuillez modifier les variables que vous souhaitez modifier.
changeMetadata.selectText.2=Supprimer toutes les métadonnées.
changeMetadata.selectText.3=Afficher les métadonnées personnalisées :
changeMetadata.author=Auteur :
changeMetadata.creationDate=Date de création (aaaa/MM/jj HH:mm:ss) :
changeMetadata.creator=Créateur :
changeMetadata.keywords=Mots clés :
changeMetadata.modDate=Date de modification (aaaa/MM/jj HH:mm:ss) :
changeMetadata.producer=Producteur :
changeMetadata.subject=Objet :
changeMetadata.title=Titre :
changeMetadata.trapped=Piégé :
changeMetadata.selectText.4=Autres métadonnées :
changeMetadata.selectText.5=Ajouter une entrée de métadonnées personnalisées
changeMetadata.submit=Modifier
#XLS to PDF
xlsToPdf.title=Excel vers PDF
xlsToPdf.header=Excel en PDF
xlsToPdf.selectText.1=Sélectionnez une feuille Excel XLS ou XLSX à convertir.
xlsToPdf.convert=Convertir
pdfToPDFA.title=PDF vers PDF/A
pdfToPDFA.header=PDF vers PDF/A
pdfToPDFA.credit=Ce service utilise OCRmyPDF pour la conversion PDF/A
pdfToPDFA.submit=Convertir
PDFToWord.title=PDF vers Word
PDFToWord.header=PDF vers Word
PDFToWord.selectText.1=Format du fichier de sortie
PDFToWord.credit=Ce service utilise LibreOffice pour la conversion de fichiers.
PDFToWord.submit=Convertir
PDFToPresentation.title=PDF vers présentation
PDFToPresentation.header=PDF vers présentation
PDFToPresentation.selectText.1=Format du fichier de sortie
PDFToPresentation.credit=Ce service utilise LibreOffice pour la conversion de fichiers.
PDFToPresentation.submit=Convertir
PDFToText.title=PDF vers Texte/RTF
PDFToText.header=PDF vers texte/RTF
PDFToText.selectText.1=Format du fichier de sortie
PDFToText.credit=Ce service utilise LibreOffice pour la conversion de fichiers.
PDFToText.submit=Convertir
PDFToHTML.title=PDF vers HTML
PDFToHTML.header=PDF vers HTML
PDFToHTML.credit=Ce service utilise LibreOffice pour la conversion de fichiers.
PDFToHTML.submit=Convertir
PDFToXML.title=PDF vers XML
PDFToXML.header=PDF vers XML
PDFToXML.credit=Ce service utilise LibreOffice pour la conversion de fichiers.
PDFToXML.submit=Convertir
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -1,34 +0,0 @@
/* Dark Mode Styles */
body {
background-color: #333 !important;
color: #fff !important;
}
.dark-card {
background-color: #333 !important;
color: white !important;
}
.jumbotron {
background-color: #222; /* or any other dark color */
color: #fff !important; /* or any other light color */
}
.list-group {
background-color: #222 !important;
color: fff !important;
}
.list-group-item {
background-color: #222 !important;
color: fff !important;
}
#support-section {
background-color: #444 !important;
}
#pages-container-wrapper {
--background-color: rgba(255, 255, 255, 0.046) !important;
--scroll-bar-color: #4c4c4c !important;
--scroll-bar-thumb: #d3d3d3 !important;
--scroll-bar-thumb-hover: #ffffff !important;
}
@@ -1,78 +0,0 @@
#drag-container {
position: fixed;
display:flex;
inset: 0;
pointer-events: none;
z-index: 10000;
visibility: hidden;
}
#drag-container:not(:empty) {
visibility: visible;
}
#drag-container .dragged-img {
position: fixed;
max-width: 200px;
max-height: 200px;
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.58);
transform-origin: top left;
}
.drag-manager_dragging {
width: 0px;
visibility: hidden;
}
.drag-manager_draghover {
width: 375px !important;
}
.drag-manager_draghover .insert-file-button-container {
display: none !important;
}
.drag-manager_draghover .button-container {
visibility: hidden !important;
}
html[lang-direction=ltr] .drag-manager_draghover img {
left: calc(50% + 62.5px) !important;
}
html[lang-direction=rtl] .drag-manager_draghover img {
left: 125px
}
.drag-manager_dragging-container .hide-on-drag {
display: none !important;
}
.drag-manager_endpoint {
width: 80px;
height: 100%;
background-color: #FFFFFF10;
transition: width 0.1s;
animation: end-drop-expand .3s ease;
display: flex;
align-items: center;
justify-content: center;
}
.drag-manager_endpoint svg {
width: 50px;
height: 50px;
}
.drag-manager_endpoint.drag-manager_draghover {
width: 150px !important;
}
@keyframes end-drop-expand {
from {
width: 0;
}
to {
width: 80px;
}
}
-44
View File
@@ -1,44 +0,0 @@
#page-container {
min-height: 100vh;
display: flex;
flex-direction: column;
}
#content-wrap {
flex: 1;
}
#footer {
bottom: 0;
width: 100%;
}
html[lang-direction=ltr] * {
direction: ltr;
}
html[lang-direction=rtl] * {
direction: rtl;
text-align: right;
}
.align-top {
position: absolute;
top: 0;
}
.align-center-right {
position: absolute;
right: 0;
top: 50%;
}
.align-center-left {
position: absolute;
left: 0;
top: 50%;
}
.align-bottom {
position: absolute;
bottom: 0;
}
@@ -1,40 +0,0 @@
#image-highlighter {
position: fixed;
display:flex;
inset: 0;
z-index: 10000;
background-color: rgba(0, 0, 0, 0);
visibility: hidden;
align-items: center;
justify-content: center;
transition: visbility 0.1s linear, background-color 0.1s linear;
}
#image-highlighter > * {
max-width: 80vw;
max-height: 80vh;
animation: image-highlight .1s linear;
transition: transform .1s linear, opacity .1s linear;
}
#image-highlighter > *.remove {
transform: scale(0.8) !important;
opacity: 0 !important;
}
#image-highlighter:not(:empty) {
background-color: rgba(0, 0, 0, 0.37);
visibility: visible;
}
@keyframes image-highlight {
from {
transform: scale(0.8);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
@@ -1,87 +0,0 @@
.pdf-actions_button-container {
z-index: 2;
display:flex;
opacity: 0;
transition: opacity 0.1s linear;
}
.pdf-actions_container:hover .pdf-actions_button-container {
opacity: 1;
}
.pdf-actions_button-container > * {
padding: 0.25rem 0.5rem;
margin: 3px;
display: block;
}
.pdf-actions_container svg {
width: 16px;
height: 16px;
}
.pdf-actions_container:nth-child(1) .pdf-actions_move-left-button {
display: none;
}
.pdf-actions_container:last-child .pdf-actions_move-right-button {
display: none;
}
/* "insert pdf" buttons that appear on the right when hover */
.pdf-actions_insert-file-button-container {
translate: 0 -50%;
width: 80px;
height: 100%;
z-index: 1;
opacity: 0;
transition: opacity 0.2s;
}
.pdf-actions_insert-file-button-container.left {
left: -20px;
}
.pdf-actions_insert-file-button-container.right {
right: -20px;
}
html[lang-direction=ltr] .pdf-actions_insert-file-button-container.right {
display:none;
}
html[lang-direction=rtl] .pdf-actions_insert-file-button-container.left {
display:none;
}
.pdf-actions_insert-file-button-container.left .pdf-actions_insert-file-button {
left: 0;
translate: 0 -50%;
}
.pdf-actions_insert-file-button-container.right .pdf-actions_insert-file-button {
right: 0;
translate: 0 -50%;
}
html[lang-direction=ltr] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.right {
display: block;
}
html[lang-direction=rtl] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.left {
display: block;
}
.pdf-actions_insert-file-button-container:hover {
opacity: 1;
transition: opacity 0.05s;
}
.pdf-actions_insert-file-button {
position: absolute;
top: 50%;
right: 50%;
translate: 50% -50%;
aspect-ratio: 1;
border-radius: 100px;
}
@@ -1,35 +0,0 @@
/* Rainbow Mode Styles */
body {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%);
color: #fff !important;
}
.dark-card {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
color: white !important;
}
.jumbotron {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%);
color: #fff !important;
}
.list-group {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
color: fff !important;
}
.list-group-item {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
color: fff !important;
}
#support-section {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
}
#pages-container-wrapper {
--background-color: rgba(255, 255, 255, 0.046) !important;
--scroll-bar-color: #4c4c4c !important;
--scroll-bar-thumb: #d3d3d3 !important;
--scroll-bar-thumb-hover: #ffffff !important;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

-298
View File
@@ -1,298 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="99.537987mm"
height="95.209366mm"
viewBox="0 0 99.537987 95.209366"
version="1.1"
id="svg745"
xml:space="preserve"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="stirling-transparent.svg"
inkscape:export-filename="stirling.png"
inkscape:export-xdpi="80"
inkscape:export-ydpi="80"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview747"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.914906"
inkscape:cx="175.42786"
inkscape:cy="510.43495"
inkscape:window-width="2256"
inkscape:window-height="1428"
inkscape:window-x="0"
inkscape:window-y="40"
inkscape:window-maximized="1"
inkscape:current-layer="svg745" /><defs
id="defs742"><linearGradient
inkscape:collect="always"
id="linearGradient72198"><stop
style="stop-color:#ccd6d7;stop-opacity:1;"
offset="0"
id="stop72194" /><stop
style="stop-color:#0f3a3f;stop-opacity:1;"
offset="1"
id="stop72196" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient71928"><stop
style="stop-color:#4b0005;stop-opacity:1;"
offset="0"
id="stop71924" /><stop
style="stop-color:#8f000c;stop-opacity:1;"
offset="1"
id="stop71926" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient71920"><stop
style="stop-color:#4b0005;stop-opacity:1;"
offset="0"
id="stop71916" /><stop
style="stop-color:#8f000c;stop-opacity:1;"
offset="1"
id="stop71918" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient69598"><stop
style="stop-color:#6a0007;stop-opacity:1;"
offset="0"
id="stop69594" /><stop
style="stop-color:#b8000f;stop-opacity:1;"
offset="1"
id="stop69596" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient46361"><stop
style="stop-color:#f7f6f8;stop-opacity:1;"
offset="0"
id="stop46359" /><stop
style="stop-color:#b7b7b5;stop-opacity:1;"
offset="1"
id="stop46357" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient40554"><stop
style="stop-color:#f4f2f4;stop-opacity:1;"
offset="0"
id="stop40550" /><stop
style="stop-color:#57767b;stop-opacity:1;"
offset="1"
id="stop40552" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient39095"><stop
style="stop-color:#285459;stop-opacity:1;"
offset="0"
id="stop39093" /><stop
style="stop-color:#a6b6af;stop-opacity:1;"
offset="1"
id="stop39091" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient36672"><stop
style="stop-color:#da453f;stop-opacity:1;"
offset="0"
id="stop36668" /><stop
style="stop-color:#a60008;stop-opacity:1;"
offset="1"
id="stop36670" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient19524"><stop
style="stop-color:#3a4b4f;stop-opacity:1;"
offset="0"
id="stop19522" /><stop
style="stop-color:#617979;stop-opacity:0.97461927;"
offset="1"
id="stop19520" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient17996"><stop
style="stop-color:#401016;stop-opacity:1;"
offset="0"
id="stop17994" /><stop
style="stop-color:#761f19;stop-opacity:1;"
offset="1"
id="stop17992" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient15569"><stop
style="stop-color:#8ea8ad;stop-opacity:1;"
offset="0"
id="stop15565" /><stop
style="stop-color:#e9e7eb;stop-opacity:1;"
offset="1"
id="stop15567" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient15557"><stop
style="stop-color:#9b0e11;stop-opacity:1;"
offset="0"
id="stop15553" /><stop
style="stop-color:#370707;stop-opacity:1;"
offset="1"
id="stop15555" /></linearGradient><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15557"
id="linearGradient15559"
x1="120.06672"
y1="63.25761"
x2="135.16347"
y2="78.078682"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15569"
id="linearGradient15571"
x1="127.97037"
y1="101.66144"
x2="133.88971"
y2="104.77026"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient17996"
id="linearGradient17998"
x1="117.9284"
y1="86.055084"
x2="130.67392"
y2="76.945541"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient19524"
id="linearGradient19528"
x1="130.98172"
y1="82.402977"
x2="135.72115"
y2="86.45166"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient36672"
id="linearGradient36674"
x1="63.797714"
y1="74.81752"
x2="96.636673"
y2="120.29293"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient39095"
id="linearGradient39097"
x1="120.54506"
y1="124.76902"
x2="128.04152"
y2="126.0704"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient40554"
id="linearGradient40556"
x1="113.84585"
y1="114.04285"
x2="119.65858"
y2="128.50244"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient46361"
id="linearGradient46363"
x1="73.993439"
y1="114.13906"
x2="94.845322"
y2="71.247383"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient69598"
id="linearGradient69600"
x1="95.854446"
y1="114.66749"
x2="103.77842"
y2="120.1887"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient71920"
id="linearGradient71922"
x1="98.580376"
y1="87.186958"
x2="118.09738"
y2="101.19449"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient71928"
id="linearGradient71930"
x1="78.278267"
y1="97.433273"
x2="92.313202"
y2="104.33479"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient72198"
id="linearGradient72200"
x1="125.76636"
y1="138.46817"
x2="123.3327"
y2="126.03291"
gradientUnits="userSpaceOnUse" /></defs><g
inkscape:groupmode="layer"
id="layer5"
inkscape:label="shadow"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient72200);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 84.146049,134.73858 c 0,0 11.721038,2.48294 17.938661,2.91673 6.21763,0.43378 14.75251,0.59994 22.41237,-0.43379 8.01008,-1.081 13.19907,-2.22733 14.50043,-2.66112 1.30136,-0.43379 4.00784,-1.24297 4.15244,-2.25514 0.1446,-1.01217 -3.4703,-2.74733 -6.21763,-3.32571 -2.74732,-0.57838 -12.72444,-1.44596 -14.89337,-1.44596 -2.16894,0 -37.892901,7.20499 -37.892901,7.20499 z"
id="path72192"
sodipodi:nodetypes="cssssssc" /></g><g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Origami"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient40556);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 84.460552,134.86721 35.165798,-6.85679 16.15467,-42.7383 z"
id="path960"
sodipodi:nodetypes="cccc" /><path
style="fill:url(#linearGradient15571);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 135.71493,85.428056 0.3984,45.049024 -9.66213,-20.46173 z"
id="path964"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient39097);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 119.60518,128.00293 16.5337,2.48693 -9.68769,-20.5512 z"
id="path966"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient15559);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 118.42209,57.022622 12.70423,-2.766809 -0.0785,25.087175 -12.43878,-13.376518 z"
id="path968"
sodipodi:nodetypes="ccccc" /><path
style="display:inline;fill:url(#linearGradient19528);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 135.72114,85.386768 -4.84219,-6.459493 0.0305,11.126604 z"
id="path970"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient17998);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 119.10273,65.682415 11.96883,13.44935 -0.0899,10.819868 -11.88577,11.430427 z"
id="path972"
sodipodi:nodetypes="ccccc" /><path
style="display:inline;fill:url(#linearGradient36674);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 62.145635,130.15618 62.043392,65.435258 c 0,0 0.179321,-2.778132 1.89516,-4.036097 1.874923,-1.374597 4.341768,-1.894096 4.341768,-1.894096 l 50.91788,-11.349167 -0.0113,53.144272 -34.733274,33.56547 z"
id="path958"
sodipodi:nodetypes="ccsccccc" /></g><g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Letter"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient69600);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 94.780881,91.406803 16.870379,17.074877 -23.723345,23.00249 -18.122131,-17.99816 5.497473,-2.80607 18.404054,-0.0511 2.35163,-8.23071 z"
id="path54894"
sodipodi:nodetypes="cccccccc" /><path
style="display:inline;fill:url(#linearGradient71930);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 72.440405,92.224764 16.15467,15.745686 4.089788,-6.79927 z"
id="path54892" /><path
style="display:inline;fill:url(#linearGradient71922);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 95.138739,84.965385 1.124691,-14.109776 22.92453,22.286787 0.008,8.164604 -3.28863,3.16649 z"
id="path54890"
sodipodi:nodetypes="cccccc"
inkscape:label="path54890" /><path
style="display:inline;fill:url(#linearGradient46363);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 95.138739,84.965385 h 1.226936 l -0.05112,-14.109776 c 0,0 -5.776827,-3.220709 -12.167126,-2.40275 -6.390296,0.817957 -8.151582,2.1248 -10.58233,4.396523 -1.90229,1.777838 -2.913974,3.527446 -3.987546,7.157132 -0.512646,1.733226 -0.281963,5.988892 0.613471,8.537436 0.664591,1.891528 2.453873,4.294281 4.958868,6.134686 2.662335,1.956002 8.281825,3.527443 8.281825,3.527443 0,0 5.134614,1.887351 5.572338,4.294281 0.308137,1.69437 -0.102243,3.22071 -1.635914,4.95887 -1.258314,1.42609 -3.62969,1.99377 -6.288054,1.07357 -2.658364,-0.92021 -6.139514,-3.85065 -7.106009,-4.90775 -0.817958,-0.89464 -2.820665,-3.06173 -2.890231,-4.294021 -0.01209,-0.214205 -1.229505,-0.0963 -1.229505,-0.0963 l -0.0723,14.256941 5.879073,2.24938 c 0,0 5.214483,1.78929 8.946415,1.43143 3.731934,-0.35786 7.617235,-0.51122 11.604778,-5.16336 3.987542,-4.65213 3.680812,-12.831715 2.147141,-15.899056 -1.533673,-3.067344 -3.561212,-6.138812 -10.480087,-8.281826 -5.776829,-1.789283 -7.872846,-3.01622 -8.128458,-4.396524 -0.255611,-1.380305 0.0091,-4.253646 2.760607,-5.214481 3.220711,-1.124693 5.623462,-0.05112 7.05489,1.12469 1.431425,1.175817 5.572339,5.623462 5.572339,5.623462 z"
id="path46355"
sodipodi:nodetypes="cccssssscssssscccssssssscc" /></g></svg>

Before

Width:  |  Height:  |  Size: 14 KiB

@@ -1,10 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1_37)">
<path d="M13 0H6C5.46957 0 4.96086 0.210714 4.58579 0.585786C4.21071 0.960859 4 1.46957 4 2C3.46957 2 2.96086 2.21071 2.58579 2.58579C2.21071 2.96086 2 3.46957 2 4V14C2 14.5304 2.21071 15.0391 2.58579 15.4142C2.96086 15.7893 3.46957 16 4 16H11C11.5304 16 12.0391 15.7893 12.4142 15.4142C12.7893 15.0391 13 14.5304 13 14C13.5304 14 14.0391 13.7893 14.4142 13.4142C14.7893 13.0391 15 12.5304 15 12V2C15 1.46957 14.7893 0.960859 14.4142 0.585786C14.0391 0.210714 13.5304 0 13 0ZM13 13V4C13 3.46957 12.7893 2.96086 12.4142 2.58579C12.0391 2.21071 11.5304 2 11 2H5C5 1.73478 5.10536 1.48043 5.29289 1.29289C5.48043 1.10536 5.73478 1 6 1H13C13.2652 1 13.5196 1.10536 13.7071 1.29289C13.8946 1.48043 14 1.73478 14 2V12C14 12.2652 13.8946 12.5196 13.7071 12.7071C13.5196 12.8946 13.2652 13 13 13ZM3 4C3 3.73478 3.10536 3.48043 3.29289 3.29289C3.48043 3.10536 3.73478 3 4 3H11C11.2652 3 11.5196 3.10536 11.7071 3.29289C11.8946 3.48043 12 3.73478 12 4V14C12 14.2652 11.8946 14.5196 11.7071 14.7071C11.5196 14.8946 11.2652 15 11 15H4C3.73478 15 3.48043 14.8946 3.29289 14.7071C3.10536 14.5196 3 14.2652 3 14V4Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_1_37">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z"/>
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z"/>
</svg>

Before

Width:  |  Height:  |  Size: 352 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left-right" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 11.5a.5.5 0 0 0 .5.5h11.793l-3.147 3.146a.5.5 0 0 0 .708.708l4-4a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 11H1.5a.5.5 0 0 0-.5.5zm14-7a.5.5 0 0 1-.5.5H2.707l3.147 3.146a.5.5 0 1 1-.708.708l-4-4a.5.5 0 0 1 0-.708l4-4a.5.5 0 1 1 .708.708L2.707 4H14.5a.5.5 0 0 1 .5.5z"/>
</svg>

Before

Width:  |  Height:  |  Size: 453 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right-short" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M4 8a.5.5 0 0 1 .5-.5h5.793L8.146 5.354a.5.5 0 1 1 .708-.708l3 3a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708-.708L10.293 8.5H4.5A.5.5 0 0 1 4 8z"/>
</svg>

Before

Width:  |  Height:  |  Size: 316 B

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-card-list" viewBox="0 0 16 16">
<path d="M14.5 3a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h13zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13z"/>
<path d="M5 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 5 8zm0-2.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm0 5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-1-5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0zM4 8a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0zm0 2.5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0z"/>
</svg>

Before

Width:  |  Height:  |  Size: 638 B

@@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-data" viewBox="0 0 16 16">
<path d="M4 11a1 1 0 1 1 2 0v1a1 1 0 1 1-2 0v-1zm6-4a1 1 0 1 1 2 0v5a1 1 0 1 1-2 0V7zM7 9a1 1 0 0 1 2 0v3a1 1 0 1 1-2 0V9z"/>
<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/>
<path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/>
</svg>

Before

Width:  |  Height:  |  Size: 629 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="43" height="43" fill="#007bff" class="bi bi-discord" viewBox="0 0 16 16">
<path d="M13.545 2.907a13.227 13.227 0 0 0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.19 12.19 0 0 0-3.658 0 8.258 8.258 0 0 0-.412-.833.051.051 0 0 0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.041.041 0 0 0-.021.018C.356 6.024-.213 9.047.066 12.032c.001.014.01.028.021.037a13.276 13.276 0 0 0 3.995 2.02.05.05 0 0 0 .056-.019c.308-.42.582-.863.818-1.329a.05.05 0 0 0-.01-.059.051.051 0 0 0-.018-.011 8.875 8.875 0 0 1-1.248-.595.05.05 0 0 1-.02-.066.051.051 0 0 1 .015-.019c.084-.063.168-.129.248-.195a.05.05 0 0 1 .051-.007c2.619 1.196 5.454 1.196 8.041 0a.052.052 0 0 1 .053.007c.08.066.164.132.248.195a.051.051 0 0 1-.004.085 8.254 8.254 0 0 1-1.249.594.05.05 0 0 0-.03.03.052.052 0 0 0 .003.041c.24.465.515.909.817 1.329a.05.05 0 0 0 .056.019 13.235 13.235 0 0 0 4.001-2.02.049.049 0 0 0 .021-.037c.334-3.451-.559-6.449-2.366-9.106a.034.034 0 0 0-.02-.019Zm-8.198 7.307c-.789 0-1.438-.724-1.438-1.612 0-.889.637-1.613 1.438-1.613.807 0 1.45.73 1.438 1.613 0 .888-.637 1.612-1.438 1.612Zm5.316 0c-.788 0-1.438-.724-1.438-1.612 0-.889.637-1.613 1.438-1.613.807 0 1.451.73 1.438 1.613 0 .888-.631 1.612-1.438 1.612Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="50px" height="50px" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
<path stroke="#007bff" stroke-width="38" d="M 297.507 242.806 L 339.507 242.806 M 247.507 242.806 L 289.507 242.806 M 198.507 242.806 L 240.507 242.806 M 149.507 242.806 L 190.507 242.806 M 99.507 242.806 L 141.507 242.806 M 149.507 196.806 L 190.507 196.806 M 198.507 196.806 L 240.507 196.806 M 247.507 196.806 L 289.507 196.806 M 247.507 150.806 L 289.507 150.806"/>
<path fill="#007bff" d="M 473.507 244.806 C 473.507 244.806 455.507 227.806 418.507 233.806 C 414.507 204.806 383.507 187.806 383.507 187.806 C 383.507 187.806 354.507 222.806 375.507 261.806 C 369.507 264.806 359.507 268.806 344.507 268.806 L 69.507 268.806 C 64.507 287.806 64.507 413.806 202.507 413.806 C 301.507 413.806 375.507 367.806 410.507 283.806 C 462.507 287.806 473.507 244.806 473.507 244.806"/>
</svg>

Before

Width:  |  Height:  |  Size: 921 B

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-droplet" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M7.21.8C7.69.295 8 0 8 0c.109.363.234.708.371 1.038.812 1.946 2.073 3.35 3.197 4.6C12.878 7.096 14 8.345 14 10a6 6 0 0 1-12 0C2 6.668 5.58 2.517 7.21.8zm.413 1.021A31.25 31.25 0 0 0 5.794 3.99c-.726.95-1.436 2.008-1.96 3.07C3.304 8.133 3 9.138 3 10a5 5 0 0 0 10 0c0-1.201-.796-2.157-2.181-3.7l-.03-.032C9.75 5.11 8.5 3.72 7.623 1.82z"/>
<path fill-rule="evenodd" d="M4.553 7.776c.82-1.641 1.717-2.753 2.093-3.13l.708.708c-.29.29-1.128 1.311-1.907 2.87l-.894-.448z"/>
</svg>

Before

Width:  |  Height:  |  Size: 632 B

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-pdf" viewBox="0 0 16 16">
<path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/>
<path d="M4.603 14.087a.81.81 0 0 1-.438-.42c-.195-.388-.13-.776.08-1.102.198-.307.526-.568.897-.787a7.68 7.68 0 0 1 1.482-.645 19.697 19.697 0 0 0 1.062-2.227 7.269 7.269 0 0 1-.43-1.295c-.086-.4-.119-.796-.046-1.136.075-.354.274-.672.65-.823.192-.077.4-.12.602-.077a.7.7 0 0 1 .477.365c.088.164.12.356.127.538.007.188-.012.396-.047.614-.084.51-.27 1.134-.52 1.794a10.954 10.954 0 0 0 .98 1.686 5.753 5.753 0 0 1 1.334.05c.364.066.734.195.96.465.12.144.193.32.2.518.007.192-.047.382-.138.563a1.04 1.04 0 0 1-.354.416.856.856 0 0 1-.51.138c-.331-.014-.654-.196-.933-.417a5.712 5.712 0 0 1-.911-.95 11.651 11.651 0 0 0-1.997.406 11.307 11.307 0 0 1-1.02 1.51c-.292.35-.609.656-.927.787a.793.793 0 0 1-.58.029zm1.379-1.901c-.166.076-.32.156-.459.238-.328.194-.541.383-.647.547-.094.145-.096.25-.04.361.01.022.02.036.026.044a.266.266 0 0 0 .035-.012c.137-.056.355-.235.635-.572a8.18 8.18 0 0 0 .45-.606zm1.64-1.33a12.71 12.71 0 0 1 1.01-.193 11.744 11.744 0 0 1-.51-.858 20.801 20.801 0 0 1-.5 1.05zm2.446.45c.15.163.296.3.435.41.24.19.407.253.498.256a.107.107 0 0 0 .07-.015.307.307 0 0 0 .094-.125.436.436 0 0 0 .059-.2.095.095 0 0 0-.026-.063c-.052-.062-.2-.152-.518-.209a3.876 3.876 0 0 0-.612-.053zM8.078 7.8a6.7 6.7 0 0 0 .2-.828c.031-.188.043-.343.038-.465a.613.613 0 0 0-.032-.198.517.517 0 0 0-.145.04c-.087.035-.158.106-.196.283-.04.192-.03.469.046.822.024.111.054.227.09.346z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-ppt" viewBox="0 0 16 16">
<path d="M7 5.5a1 1 0 0 0-1 1V13a.5.5 0 0 0 1 0v-2h1.188a2.75 2.75 0 0 0 0-5.5H7zM8.188 10H7V6.5h1.188a1.75 1.75 0 1 1 0 3.5z"/>
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 439 B

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-richtext" viewBox="0 0 16 16">
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
<path d="M4.5 12.5A.5.5 0 0 1 5 12h3a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm0-2A.5.5 0 0 1 5 10h6a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm1.639-3.708 1.33.886 1.854-1.855a.25.25 0 0 1 .289-.047l1.888.974V8.5a.5.5 0 0 1-.5.5H5a.5.5 0 0 1-.5-.5V8s1.54-1.274 1.639-1.208zM6.25 6a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5z"/>
</svg>

Before

Width:  |  Height:  |  Size: 623 B

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-word" viewBox="0 0 16 16">
<path d="M5.485 6.879a.5.5 0 1 0-.97.242l1.5 6a.5.5 0 0 0 .967.01L8 9.402l1.018 3.73a.5.5 0 0 0 .967-.01l1.5-6a.5.5 0 0 0-.97-.242l-1.036 4.144-.997-3.655a.5.5 0 0 0-.964 0l-.997 3.655L5.485 6.88z"/>
<path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 510 B

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-x" viewBox="0 0 16 16">
<path d="M6.854 7.146a.5.5 0 1 0-.708.708L7.293 9l-1.147 1.146a.5.5 0 0 0 .708.708L8 9.707l1.146 1.147a.5.5 0 0 0 .708-.708L8.707 9l1.147-1.146a.5.5 0 0 0-.708-.708L8 8.293 6.854 7.146z"/>
<path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 496 B

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-pdf" viewBox="0 0 16 16">
<path d="M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H4zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1z"/>
<path d="M4.603 12.087a.81.81 0 0 1-.438-.42c-.195-.388-.13-.776.08-1.102.198-.307.526-.568.897-.787a7.68 7.68 0 0 1 1.482-.645 19.701 19.701 0 0 0 1.062-2.227 7.269 7.269 0 0 1-.43-1.295c-.086-.4-.119-.796-.046-1.136.075-.354.274-.672.65-.823.192-.077.4-.12.602-.077a.7.7 0 0 1 .477.365c.088.164.12.356.127.538.007.187-.012.395-.047.614-.084.51-.27 1.134-.52 1.794a10.954 10.954 0 0 0 .98 1.686 5.753 5.753 0 0 1 1.334.05c.364.065.734.195.96.465.12.144.193.32.2.518.007.192-.047.382-.138.563a1.04 1.04 0 0 1-.354.416.856.856 0 0 1-.51.138c-.331-.014-.654-.196-.933-.417a5.716 5.716 0 0 1-.911-.95 11.642 11.642 0 0 0-1.997.406 11.311 11.311 0 0 1-1.021 1.51c-.29.35-.608.655-.926.787a.793.793 0 0 1-.58.029zm1.379-1.901c-.166.076-.32.156-.459.238-.328.194-.541.383-.647.547-.094.145-.096.25-.04.361.01.022.02.036.026.044a.27.27 0 0 0 .035-.012c.137-.056.355-.235.635-.572a8.18 8.18 0 0 0 .45-.606zm1.64-1.33a12.647 12.647 0 0 1 1.01-.193 11.666 11.666 0 0 1-.51-.858 20.741 20.741 0 0 1-.5 1.05zm2.446.45c.15.162.296.3.435.41.24.19.407.253.498.256a.107.107 0 0 0 .07-.015.307.307 0 0 0 .094-.125.436.436 0 0 0 .059-.2.095.095 0 0 0-.026-.063c-.052-.062-.2-.152-.518-.209a3.881 3.881 0 0 0-.612-.053zM8.078 5.8a6.7 6.7 0 0 0 .2-.828c.031-.188.043-.343.038-.465a.613.613 0 0 0-.032-.198.517.517 0 0 0-.145.04c-.087.035-.158.106-.196.283-.04.192-.03.469.046.822.024.111.054.227.09.346z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-zip" viewBox="0 0 16 16">
<path d="M6.5 7.5a1 1 0 0 1 1-1h1a1 1 0 0 1 1 1v.938l.4 1.599a1 1 0 0 1-.416 1.074l-.93.62a1 1 0 0 1-1.109 0l-.93-.62a1 1 0 0 1-.415-1.074l.4-1.599V7.5zm2 0h-1v.938a1 1 0 0 1-.03.243l-.4 1.598.93.62.93-.62-.4-1.598a1 1 0 0 1-.03-.243V7.5z"/>
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2zm5.5-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H9v1H8v1h1v1H8v1h1v1H7.5V5h-1V4h1V3h-1V2h1V1z"/>
</svg>

Before

Width:  |  Height:  |  Size: 578 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark" viewBox="0 0 16 16">
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 304 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-filetype-html" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M14 4.5V11h-1V4.5h-2A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v9H2V2a2 2 0 0 1 2-2h5.5L14 4.5Zm-9.736 7.35v3.999h-.791v-1.714H1.79v1.714H1V11.85h.791v1.626h1.682V11.85h.79Zm2.251.662v3.337h-.794v-3.337H4.588v-.662h3.064v.662H6.515Zm2.176 3.337v-2.66h.038l.952 2.159h.516l.946-2.16h.038v2.661h.715V11.85h-.8l-1.14 2.596H9.93L8.79 11.85h-.805v3.999h.706Zm4.71-.674h1.696v.674H12.61V11.85h.79v3.325Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 565 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-filetype-txt" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M14 4.5V14a2 2 0 0 1-2 2h-2v-1h2a1 1 0 0 0 1-1V4.5h-2A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v9H2V2a2 2 0 0 1 2-2h5.5L14 4.5ZM1.928 15.849v-3.337h1.136v-.662H0v.662h1.134v3.337h.794Zm4.689-3.999h-.894L4.9 13.289h-.035l-.832-1.439h-.932l1.228 1.983-1.24 2.016h.862l.853-1.415h.035l.85 1.415h.907l-1.253-1.992 1.274-2.007Zm1.93.662v3.337h-.794v-3.337H6.619v-.662h3.064v.662H8.546Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 548 B

Some files were not shown because too many files have changed in this diff Show More