David Chuan-En Lin commited on
Commit
18f2633
1 Parent(s): 8c334b4
Files changed (4) hide show
  1. README.md +19 -28
  2. app.py +96 -0
  3. example.png +0 -0
  4. 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
- # Configuration
12
 
13
- `title`: _string_
14
- Display title for the Space
 
15
 
16
- `emoji`: _string_
17
- Space emoji (emoji-only character allowed)
18
 
19
- `colorFrom`: _string_
20
- Color for Thumbnail gradient (red, yellow, green, blue, indigo, purple, pink, gray)
21
 
22
- `colorTo`: _string_
23
- Color for Thumbnail gradient (red, yellow, green, blue, indigo, purple, pink, gray)
 
 
24
 
25
- `sdk`: _string_
26
- Can be either `gradio` or `streamlit`
27
 
28
- `sdk_version` : _string_
29
- Only applicable for `streamlit` SDK.
30
- See [doc](https://hf.co/docs/hub/spaces) for more info on supported versions.
31
 
32
- `app_file`: _string_
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
- `pinned`: _boolean_
37
- Whether the Space stays on top of your list.
 
 
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