Spaces:
Running
Running
David Chuan-En Lin
commited on
Commit
·
18f2633
1
Parent(s):
8c334b4
init
Browse files- README.md +19 -28
- app.py +96 -0
- example.png +0 -0
- requirements.txt +3 -0
README.md
CHANGED
@@ -1,37 +1,28 @@
|
|
1 |
-
|
2 |
-
title: Pdf2preview
|
3 |
-
emoji: 🦀
|
4 |
-
colorFrom: purple
|
5 |
-
colorTo: indigo
|
6 |
-
sdk: streamlit
|
7 |
-
app_file: app.py
|
8 |
-
pinned: false
|
9 |
-
---
|
10 |
|
11 |
-
|
12 |
|
13 |
-
|
14 |
-
|
|
|
15 |
|
16 |
-
|
17 |
-
Space emoji (emoji-only character allowed)
|
18 |
|
19 |
-
|
20 |
-
Color for Thumbnail gradient (red, yellow, green, blue, indigo, purple, pink, gray)
|
21 |
|
22 |
-
|
23 |
-
|
|
|
|
|
24 |
|
25 |
-
|
26 |
-
Can be either `gradio` or `streamlit`
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
|
32 |
-
|
33 |
-
Path to your main application file (which contains either `gradio` or `streamlit` Python code).
|
34 |
-
Path is relative to the root of the repository.
|
35 |
|
36 |
-
|
37 |
-
|
|
|
|
1 |
+
# PDF ➡️ Preview
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
+
A simple tool to save me time on Illustrator. Generates a preview image for a PDF file. Useful for sneak peeks to academic publications on project websites or presentation slides.
|
4 |
|
5 |
+
![Example](example.png)
|
6 |
+
|
7 |
+
---
|
8 |
|
9 |
+
## Getting Started
|
|
|
10 |
|
11 |
+
1. Clone the repository.
|
|
|
12 |
|
13 |
+
```python
|
14 |
+
git clone https://github.com/chuanenlin/pdf2preview.git
|
15 |
+
cd pdf2preview
|
16 |
+
```
|
17 |
|
18 |
+
2. Install package dependencies.
|
|
|
19 |
|
20 |
+
```python
|
21 |
+
pip install -r requirements.txt
|
22 |
+
```
|
23 |
|
24 |
+
3. Run the app.
|
|
|
|
|
25 |
|
26 |
+
```python
|
27 |
+
streamlit run pdf2preview.py
|
28 |
+
```
|
app.py
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from PIL import Image, ImageFilter, ImageOps
|
3 |
+
import sys
|
4 |
+
import io
|
5 |
+
import fitz #pip install PyMuPDF
|
6 |
+
|
7 |
+
def add_border(image, border):
|
8 |
+
img_with_border = ImageOps.expand(image, border=border, fill="black")
|
9 |
+
return img_with_border
|
10 |
+
|
11 |
+
def add_shadow(image, offset, shadow, border):
|
12 |
+
total_width = image.size[0] + abs(offset[0]) + 2 * border
|
13 |
+
total_height = image.size[1] + abs(offset[1]) + 2 * border
|
14 |
+
back = Image.new("RGBA", (total_width, total_height), (0, 0, 0, 0))
|
15 |
+
shadow = Image.new("RGBA", (image.size[0], image.size[1]), (0, 0, 0, 255))
|
16 |
+
shadow_left = border + max(offset[0], 0)
|
17 |
+
shadow_top = border + max(offset[1], 0)
|
18 |
+
back.alpha_composite(shadow, (shadow_left, shadow_top))
|
19 |
+
back = back.filter(ImageFilter.GaussianBlur(10))
|
20 |
+
back.convert("RGBA")
|
21 |
+
img_left = border - min(offset[0], 0)
|
22 |
+
img_top = border - min(offset[1], 0)
|
23 |
+
back.paste(image, (img_left, img_top), image.convert("RGBA"))
|
24 |
+
back.convert("RGBA")
|
25 |
+
return back
|
26 |
+
|
27 |
+
def stack(images, mode):
|
28 |
+
num_images = len(images)
|
29 |
+
widths, heights = zip(*(i.size for i in images))
|
30 |
+
if mode == "Unroll":
|
31 |
+
separation = 700
|
32 |
+
total_width = sum(widths) - separation * (num_images - 1)
|
33 |
+
max_height = max(heights)
|
34 |
+
new_im = Image.new("RGBA", (total_width, max_height))
|
35 |
+
x_offset = total_width - images[0].size[0]
|
36 |
+
for im in images:
|
37 |
+
new_im.alpha_composite(im, (x_offset, 0))
|
38 |
+
x_offset -= im.size[0] - separation
|
39 |
+
elif mode == "Stack":
|
40 |
+
separation = 10
|
41 |
+
total_width = widths[0] + separation * (num_images - 1)
|
42 |
+
total_height = heights[0] + separation * (num_images - 1)
|
43 |
+
new_im = Image.new("RGBA", (total_width, total_height))
|
44 |
+
x_offset = total_width - images[0].size[0]
|
45 |
+
y_offset = 0
|
46 |
+
for im in images:
|
47 |
+
new_im.alpha_composite(im, (x_offset, y_offset))
|
48 |
+
x_offset -= separation
|
49 |
+
y_offset += separation
|
50 |
+
elif mode == "Cover":
|
51 |
+
new_im = images[-1]
|
52 |
+
return new_im
|
53 |
+
|
54 |
+
st.set_page_config(page_title="pdf2preview", page_icon="📄", layout="centered", initial_sidebar_state="collapsed", menu_items=None)
|
55 |
+
hide_streamlit_style = """
|
56 |
+
<style>
|
57 |
+
MainMenu {visibility: hidden;}
|
58 |
+
footer {visibility: hidden;}
|
59 |
+
* {font-family: Avenir; text-align: center;}
|
60 |
+
.css-gma2qf {display: flex; justify-content: center; font-size: 36px; font-weight: bold;}
|
61 |
+
a:link {text-decoration: none;}
|
62 |
+
a:hover {text-decoration: none;}
|
63 |
+
.st-ba {font-family: Avenir;}
|
64 |
+
</style>
|
65 |
+
"""
|
66 |
+
st.markdown(hide_streamlit_style, unsafe_allow_html=True)
|
67 |
+
st.title("PDF ➡️ Preview")
|
68 |
+
|
69 |
+
col1, col2 = st.columns([1, 6])
|
70 |
+
with col1:
|
71 |
+
st.radio("Pick a layout", ("Unroll", "Stack", "Cover"), key="mode")
|
72 |
+
with col2:
|
73 |
+
st.image("example.png")
|
74 |
+
st.file_uploader("Upload your PDF", type="pdf", key="file")
|
75 |
+
|
76 |
+
if st.session_state.file is not None:
|
77 |
+
with st.spinner("Processing..."):
|
78 |
+
file = fitz.open("pdf", st.session_state.file.read())
|
79 |
+
zoom = 2
|
80 |
+
mat = fitz.Matrix(zoom, zoom)
|
81 |
+
num_pages = file.pageCount
|
82 |
+
imgs = []
|
83 |
+
for page_num in range(num_pages):
|
84 |
+
page = file.load_page(page_num)
|
85 |
+
pix = page.get_pixmap(matrix = mat)
|
86 |
+
data = pix.tobytes("format")
|
87 |
+
img = Image.open(io.BytesIO(data))
|
88 |
+
img_with_border = add_border(img, border=1)
|
89 |
+
img_with_shadow = add_shadow(img_with_border, offset=(0,0), shadow=(0,0,0,255), border=20)
|
90 |
+
imgs.append(img_with_shadow)
|
91 |
+
preview = stack(imgs[::-1], st.session_state.mode)
|
92 |
+
st.image(preview)
|
93 |
+
output = io.BytesIO()
|
94 |
+
preview.save(output, format="PNG")
|
95 |
+
output = output.getvalue()
|
96 |
+
download = st.download_button(label="Download image", data=output, file_name="pdf2preview.png", mime="image/png")
|
example.png
ADDED
![]() |
requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
Pillow
|
2 |
+
PyMuPDF
|
3 |
+
streamlit
|