-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvdiff
More file actions
executable file
·196 lines (151 loc) · 6.23 KB
/
vdiff
File metadata and controls
executable file
·196 lines (151 loc) · 6.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#!/bin/bash
# Function to display progress bar
show_progress() {
local progress=$1
local total=$2
local bar_width=75 # Set progress bar width to 75 characters
# Calculate the percentage completed as an integer
local percent=$(awk "BEGIN {printf \"%d\", ($progress/$total)*100}")
# Calculate the number of hashes for the progress bar
local num_hashes=$(awk "BEGIN {printf \"%d\", ($progress/$total)*$bar_width}")
# Ensure num_hashes is at least 1
if [ "$num_hashes" -lt 1 ]; then
num_hashes=1
fi
# Create the progress bar
local bar=$(printf "%.0s#" {1..5000} | cut -c1-$num_hashes)
# Print the progress bar and percentage as an integer
printf "\r[%-${bar_width}s] %s%%" "$bar" "$percent"
}
# Check if both PDFs are provided as arguments
if [ "$#" -lt 3 ]; then
echo "Usage: $0 <input_pdf1> <input_pdf2> <output_pdf> [--use-cache]"
exit 1
fi
# Assign input arguments to variables
pdf1=$1
pdf2=$2
output_pdf=$3
# Check if the use-cache flag is set
use_cache=false
if [ "$4" == "--use-cache" ]; then
use_cache=true
echo "Cache mode enabled. Cache will be preserved."
fi
# Create cache directory if it doesn't exist
mkdir -p cache
# Get the total number of pages in each PDF using pdfinfo
total_pages_pdf1=$(pdfinfo "$pdf1" | grep Pages | awk '{print $2}')
total_pages_pdf2=$(pdfinfo "$pdf2" | grep Pages | awk '{print $2}')
# Ensure both PDFs have the same number of pages
if [ "$total_pages_pdf1" -ne "$total_pages_pdf2" ]; then
echo "Error: The two PDFs do not have the same number of pages."
exit 1
fi
page_count=$total_pages_pdf1
# Output the page count
echo "Page count: $page_count"
# Function to reset progress
reset_progress() {
echo 0 > "$progress_file"
}
# Progress file to track completed tasks
progress_file=$(mktemp)
# Update progress after each task
update_progress() {
local total=$1
local progress=$(cat "$progress_file")
progress=$((progress + 1))
echo "$progress" > "$progress_file"
show_progress "$progress" "$total"
}
# Convert PDF1 and PDF2 to greyscale page by page
echo "Converting to greyscale..."
reset_progress # Reset progress before starting
for ((i=1; i<=$page_count; i++)); do
pdf1_grey="cache/pdf1_page_$(printf '%03d' $i).png"
pdf2_grey="cache/pdf2_page_$(printf '%03d' $i).png"
if [ "$use_cache" == false ] || [ ! -f "$pdf1_grey" ]; then
magick -density 300 "$pdf1[$((i-1))]" -colorspace Gray "$pdf1_grey"
fi
if [ "$use_cache" == false ] || [ ! -f "$pdf2_grey" ]; then
magick -density 300 "$pdf2[$((i-1))]" -colorspace Gray "$pdf2_grey"
fi
update_progress "$page_count"
done
echo ""
# Generate red-tinted images for PDF1
echo "Generating red-tinted images for PDF1..."
reset_progress # Reset progress before starting
magick -size 1x256 gradient:white-red "cache/red_gradient.png"
for ((i=1; i<=$page_count; i++)); do
img="cache/pdf1_page_$(printf '%03d' $i).png"
red_img="cache/red_page_$(printf '%03d' $i).png"
if [ "$use_cache" == false ] || [ ! -f "$red_img" ]; then
magick "$img" -negate cache/red_gradient.png -clut "$red_img"
fi
update_progress "$page_count"
done
echo ""
# Generate blue-tinted images for PDF2
echo "Generating blue-tinted images for PDF2..."
reset_progress # Reset progress before starting
magick -size 1x256 gradient:white-blue "cache/blue_gradient.png"
for ((i=1; i<=$page_count; i++)); do
img="cache/pdf2_page_$(printf '%03d' $i).png"
blue_img="cache/blue_page_$(printf '%03d' $i).png"
if [ "$use_cache" == false ] || [ ! -f "$blue_img" ]; then
magick "$img" -negate cache/blue_gradient.png -clut "$blue_img"
fi
update_progress "$page_count"
done
echo ""
# Combine and process the images, store everything in the cache folder
echo "Processing pages and combining outputs..."
reset_progress # Reset progress before starting
for ((i=1; i<=$page_count; i++)); do
grey_page1="cache/pdf1_page_$(printf '%03d' $i).png"
grey_page2="cache/pdf2_page_$(printf '%03d' $i).png"
red_page="cache/red_page_$(printf '%03d' $i).png"
blue_page="cache/blue_page_$(printf '%03d' $i).png"
final_page="cache/final_page_$(printf '%03d' $i).png"
if [ "$use_cache" == true ] && [ -f "$final_page" ]; then
update_progress "$page_count" # Increment progress even if the file already exists (cache hit)
continue
fi
diff_page="cache/diff_page_$(printf '%03d' $i).png"
mask_page="cache/mask_page_$(printf '%03d' $i).png"
similar_page="cache/similar_page_$(printf '%03d' $i).png"
blended_page="cache/blended_page_$(printf '%03d' $i).png"
# Compute the difference between the two images to find similarities
magick "$grey_page1" "$grey_page2" -compose Difference -composite "$diff_page"
# Threshold to highlight identical areas
magick "$diff_page" -threshold 0 -negate "$mask_page"
# Mask the original image to show only similarities
magick "$grey_page1" "$mask_page" -compose CopyOpacity -composite "$similar_page"
# Blend red and blue images at 50%
magick "$red_page" "$blue_page" -compose Blend -define compose:args=50,50 -composite "$blended_page"
# Combine the blended red/blue image with the greyscale similarities using Darken
magick "$blended_page" "$similar_page" -compose Darken -composite "$final_page"
update_progress "$page_count"
done
echo ""
# Combine all final images into a single output PDF
echo "Combining final images into $output_pdf..."
magick $(ls cache/final_page_*.png | sort) "$output_pdf"
# Compress the final PDF using Ghostscript with PDF compatibility level 1.5 and higher compression (/screen or /ebook)
compressed_output="compressed_output.pdf"
echo "Compressing final PDF for higher compression..."
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.5 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile="$compressed_output" "$output_pdf"
# Move the compressed PDF to overwrite the original output PDF
mv "$compressed_output" "$output_pdf"
# Clean up intermediate images
echo "Cleaning up..."
# Remove the cache folder unless --use-cache flag is present
if [ "$use_cache" == false ]; then
echo "Removing cache folder..."
rm -rf cache
fi
# Clean up progress file
rm "$progress_file"
echo "Done! The output is saved as $output"