合併重組切割 pdf 檔案的工具

因為常有重組或抽換 pdf 檔案中某些頁數的需求, 所以寫了一個可以在瀏覽器中離線運作的小工具 pdf-lib browser tool , 可以用來合併、抽換、重組 pdf 檔案成新的檔案, 也能載入多頁的 tiff,jpeg png gif 等其他圖檔。 除了線上版載入 javascript 外全程都在本機端執行, 主要是用 PDF-LIB 這個 js 函式庫做的。

讀取檔案

我寫的工具 pdf-lib browser tool , 載入檔案時可以用網頁上的 input file 以檔案選取對話框載入檔案, 或直接把檔案拖到 pdf list 下面的清單裡載入。

檔案及頁碼指定

載入後清單會顯示目前載入的檔案清單,從 0 開始編號。 重組 pdf 則是使用文字框來指定要輸出哪些檔案中的哪些頁數, 文字框中是一個二維 json 陣列, 第一個陣列是要依序輸出哪幾個檔案,其後的陣列則是每個檔案要輸出哪些頁數, 頁數一樣是從 0 開始編號。

像如果要跳過奇數頁, 可以寫 [[0], [1, 3, 5, 7, 9]] , 這樣就會輸出第 0 個檔案中的第 2 4 6 8 頁。 (0 對應到第 1 頁)

如果寫 [[0,1,0], [0,1,2], [0], [4,5]] , 則是輸出第 0 個檔案的 1-3 頁, 再來第 1 個檔案的第 1 頁,最後繼續輸出第 0 個檔案的 5-6 頁; 大概就是用第 1 個檔案的第 1 頁抽換掉第 0 個檔案的第 4 頁的意思。

在載入檔案時,下方的文字框預設會自動將載入的檔案的編號及所有頁數都加在最後面, 方便在頁碼很多時手動打要打很久; 如果打亂掉了,也可以按 重設 按鈕, 會把所有 pdf 按順序放進來。

下載 pdf

arrange 即可依指定的順序頁碼合成 pdf, 合成後會在新分頁開啟,如果要下載,在開啟中的分頁按下載, 或右鍵另存新檔皆可。 如果不小心關掉了,可以按 arrange 旁邊的 pdf link 連結重新開啟。

圖片格式支援

如果載入的格式是 jpeg gif png,會在載入時轉成單頁的 pdf, 並自動依長寬轉置成橫向或直向的 A4 大小,並縮放到最大。

自動轉置功能只會對 圖片 含 tiff 格式啟用, 如果輸入的是 pdf 則不會自動轉置。 如果要轉置可以參考下面的 手動指定頁面轉置 一節。

tiff 格式支援

這工具也能載入多頁的 tiff 檔案,一些掃描機的掃描結果是 tiff 格式, 在載入時會轉成相應的多頁 pdf 檔案,一樣會用圖片的方式自動轉置。 多頁 tiff 的轉換會稍久。

tiff 格式大小

tiff 預設是用無損格式轉成 pdf, 要是原本 tiff 內部是用 jpeg 編碼的話,轉 png 檔案大小會暴增個 4 5 倍。 如果想避免,可以在載入前勾選 use jpg lossy compression... 的選項, 並調整 tiff quality 的壓縮品質, 我的經驗是品質設到 0.7 就差不多了,很難再更小。

tiff 變大的原因我也不是很清楚, 據我所知 tiff 中有 jpg 或像 png 的無損式編碼, 大多時候只有原本已經是 jpg 的編碼能被壓縮, 如果是類 png 的無損式編碼轉成 jpg 反而會變大, 所以我在壓縮時只會把原本已經是 jpg 的頁面轉成 jpg,png 就保留不動。

而類 png 編碼轉成 pdf 時是用把圖片當成 png 再編碼一次, 這樣的作法會讓檔案變大,可能因為原本 tiff 只有黑白二色, 又用了特殊的技術去壓縮吧?

如果有人可以解決這個問題歡迎留言與我聯絡,我會很感謝的。

手動指定頁面轉置

如果對預設的轉向不滿意, 可以在 page processing script 文字框中 使用指令手動指定某些頁面的轉向。

文字框中的程式碼會在合成 pdf 時的每一頁呼叫, 呼叫時會傳入 page ref doc 三個參數。 ref 是一個長度 2 的陣列,可以用來判斷現在是合成第幾頁, ref 第一個數字是目前的頁面是來自第幾個檔案, 第二個數字則是該頁在該檔案中的頁碼。

page 則是 pdf-lib 函式庫中的 pdf page 物件, 可以呼叫 page.setRotation 方法來指定轉向。 但轉向參數不是直接輸入角度數值, 而是要用 PDFLib.degrees(90) 來把數值轉成角度再輸入。 轉向順時針為正,逆時針為負。

網頁中有給出範例,基本上就是用 if 判斷, 如果是想轉置的頁就呼叫 setRotation 來轉置。 然後要注意在 js 中二個內容相同的陣列不一定會相等: [1,2] != [1,2] ,但如果把陣列和字串比較, 則會把陣列內容用逗號連結成字串後再和字串比, 這樣就能方便的判斷是否在某頁了。

不可修改的 pdf

某些 pdf 有加密或有不可修改的數位簽章, 目前沒有處理這些問題,會跳錯誤訊息無法載入。 可以用列印為 pdf 的方式去除數位簽章或加密後再載入。

離線使用

github repo下載打包的 zip , 解壓縮後開啟 pdf-js-tool.html 即可使用。

結語

我知道用 json 指定頁碼和檔案很廢,但我就懶。 而且 json 用程式產生也方便,寫 ui 不知道要花多少時間。 如果想送 pr 幫我寫 ui 也歡迎。 有不會用的也歡迎提問。

更新 2023-12

更新了一些東西,在 json 格式外加了種純文字頁碼的格式,和加了幾個新按鈕。 主要是讓系統可以儘量全滑鼠操作。

純文字格式

基本上是把 json 二維陣列映射成用空格和換行符分隔的陣列, 一樣第一行是 pdf 檔案索引,之後每行對應一個 pdf 中的頁數。 空行和多餘的空白會被忽略,像行首行尾縮排。 另外為了方便在小鍵盤輸入,加號也視為空白。 舊的 json 格式也仍然是合法的輸入。

例如:

[
  [0, 1, 0],
  [0, 1],
  [0],
  [2, 4]
]

等同於:

0 1 0
0 1
0
2 4

按鈕

不知道怎麼寫 ui 的時候,寫成按鈕就對了!

re-add last files 按鈕可以重新讀取放在檔案輸入欄位裡的檔案, 主要是如果檔案太大,想調成用 jpeg 編碼,可以調了後按, 就會換成調整後的檔案。

remove odd page 按鈕是用來移除奇數頁用的, 主要是用在雙面掃描時,如果有很多單面頁,可以用這功能快速移除某些頁面。 (這功能在用純文字格式頁碼比較好用。) 選取文字框裡需要移除部份的文字,然後按按鈕, 就會把選取中每二個數字移除第一個數字(和實際數字奇偶無關)。 例如選取了 2 3 4 5 6 ,就會移除 2 4 6 這三個位於奇數序位的數字。 如果沒有選取,就會每行都移除一次。

delete text 很簡單,就是用來選取部份頁碼的, 主要是讓手可以不用離開滑鼠去按鍵盤上的 backspace。 然後按 ctrl 多重選取中也能生效, 為了這點還特別去找了古早時代的 document.execCommand api。

快速加入 pdf

按 pdf list 裡的檔名時,會把該檔案加到文件列表裡。 如果游標有在第一行,就會加入在游標處, 如果沒有就加入在第一行結尾。

全滑鼠操作

除了上面幾個按鈕和新功能,滑鼠操作還有個技巧, 在文字框裡選取文字後,可以拖曳選擇的文字到另一個地方來移動文字。 這樣大概就能涵蓋大多數在重排 pdf 時的動作。 然後還會在每行結尾多加一個空格, 這樣就能把頁碼拖曳到行尾時還有空格。

更新 2024-02,分割 pdf

加了一個分割 pdf 成多個檔案的功能 split pdf ,ui 是做成按鈕。 輸入格式一樣是多個檔案然後照 arrange 的功能那樣輸入文件編號和頁碼, 之後要多加最後一行是要分割出的 pdf 的起始頁數。

例如原本如下輸入 arrange 會產生 9 頁的 pdf:

0 2 1 2

0 3
1 2 3
10
0 0 0

如果想把這 9 頁分成各 2 3 4 頁共 3 個檔案, 就再加上最後一行,再按下 split pdf 鍵。

0 2 1 2

0 3
1 2 3
10
0 0 0

0 2 5

這樣就會從第 0 2 5 頁切成一個新檔案, 也就是頁碼 0-1 2-4 5-8 三個檔案,會依序下載。

空行都只是排版上美觀而已,實際處理時會忽略, 只要有多加最後一行就好了。 如果不只多加一行,就只會看最後一行。

留言

  • Webmention is supported