顯示具有 pdf 標籤的文章。 顯示所有文章
顯示具有 pdf 標籤的文章。 顯示所有文章

星期二, 9月 15, 2026

壓縮pdf

MacOS的預覽程式本身就可以壓縮 pdf ,方法可以參考 Apple 官方網站的文章:https://support.apple.com/zh-tw/guide/preview/prvw1509/mac

開啟 pdf 以後,

  1. 選擇「檔案」>「輸出⋯」。
  2. 在「Quartz 濾鏡」彈出式選單中,選擇「減少檔案大小」。
  3. 儲存

這樣就可以了。

但….如果 pdf 已經壓縮過、包含向量圖、嵌入字型或特殊物件時,那麼反而可能得到反效果,檔案會變大。

我自己是有安裝 homebrew ,就想說是不是安裝什麼工具來作就好。

問了 AI ,他就說可以用 gs ,也就是 ghostscript 就可以解決。

先安裝

brew install ghostscript

接下來就執行 gs

gs \
  -sDEVICE=pdfwrite \
  -dCompatibilityLevel=1.4 \
  -dPDFSETTINGS=/ebook \
  -dNOPAUSE \
  -dQUIET \
  -dBATCH \
  -sOutputFile=output.pdf \
  input.pdf

把 input.pdf 跟 output.pdf 換掉就可以。

壓縮等級主要是調整 -dPDFSETTINGS= 參數,參數內容可以參考

參數品質檔案大小
/prepress最高最大
/printer較大
/ebook推薦
/screen最小

ghostscript 還可以調整 pdf 內的圖片解析度

gs \
 -sDEVICE=pdfwrite \
 -dCompatibilityLevel=1.4 \
 -dColorImageDownsampleType=/Bicubic \
 -dColorImageResolution=150 \
 -dGrayImageDownsampleType=/Bicubic \
 -dGrayImageResolution=150 \
 -dMonoImageDownsampleType=/Subsample \
 -dMonoImageResolution=300 \
 -dNOPAUSE \
 -dQUIET \
 -dBATCH \
 -sOutputFile=output.pdf \
 input.pdf

其他的方法還有 pdfcpu, ocrmypdf ,這些我就沒測試了。


星期日, 7月 16, 2023

paps

之前使用 enscript 來將文字檔轉為 pdf,但實測發現,若文字檔裡面是中文,那麼轉出來是亂碼。

只好找其他的方案,找到的是 paps: https://github.com/dov/paps

paps 比較麻煩的是需要自己安裝,安裝說明可以參考:https://github.com/dov/paps/blob/master/INSTALL.md

我的環境是 Ubuntu 20.04

第一個是需要 meson,這個直接用 apt-get 安裝就可以

sudo apt install meson

第二個是 fmtlib ,Ubuntu 20.04 內的 fmtlib 版本過舊,這邊需要借助 backports

sudo add-apt-repository ppa:savoury1/backports
sudo apt install libfmt-dev

最後就是編譯

https://github.com/dov/paps.git
cd paps
meson build
cd build && ninja
sudo ninja install

這樣就可以得到 paps 了。

星期六, 6月 17, 2023

大量程式碼輸出為pdf

因為客戶文件需要,得把一堆檔案輸出為pdf。懶人如我,當然要找一下是不是有好的方法可以達成這個需求。

第一個找到的是 pandoc ,這個工具好是好,但遇到 Ansible playbook ,pandoc 會以為檔案是設定檔,就沒辦法輸出。

第二個找到的是 enscript ,這工具就可以很輕易的將文字檔轉換為 postscript 檔案,同時還可以加上語法高亮效果,但可惜語法高亮效果不支援 Ansible playbook 。有了 postscript 檔案,接下來就可以用 ps2pdf 將 postscript 檔案轉換為 pdf。

# Ubuntu
sudo apt install ps2pdf enscript
enscript playbook.yml doc.ps
ps2pdf doc.ps doc.pdf

現在可以處理單一個檔案以後,接下來要想怎麼處理多個檔案,這裡透過 find, xargs 跟 enscript 的協作就可以做到

find . -name '*.yml' -print | xargs enscript --output=doc.ps
ps2pdf doc.ps doc.pdf

不免俗,還要加上頁首跟頁尾,頁尾也要加上頁次,這部份需要為 enscript 加上自訂的頁首跟調整頁尾的高度。

mkdir ~/.enscript
cp /usr/share/enscript/simple.hdr ~/.enscript/my.hdr

然後修改 ~/.enscript/my.hdr

% -- code follows this line --
%Format: fmodstr        $D{%a %b %d %H:%M:%S %Y}
%Format: pagenumstr     $V$%
%FooterHeight: 15

/do_header {    % print default simple header
  % Footer
  gsave
    d_footer_x d_footer_y HFpt_h 3 div add translate
    HF setfont

    user_footer_p {
      d_footer_x  d_footer_y moveto user_footer_left_str show

      d_footer_w user_footer_center_str stringwidth pop sub 2 div
      0 moveto user_footer_center_str show

      d_footer_x d_footer_w add user_footer_right_str stringwidth pop sub
      d_footer_y moveto user_footer_right_str show
    } if
  grestore

  % Header
  gsave
    d_header_x d_header_y HFpt_h 3 div add translate

    HF setfont
    user_header_p {
      5 0 moveto user_header_left_str show

      d_header_w user_header_center_str stringwidth pop sub 2 div
      0 moveto user_header_center_str show

      d_header_w user_header_right_str stringwidth pop sub 5 sub
      0 moveto user_header_right_str show
    } {
      5 0 moveto fname show
      45 0 rmoveto fmodstr show
      45 0 rmoveto pagenumstr show
    } ifelse

  grestore
} def

產出 postscript 的指令改為

find . -name '*.yml' -print | xargs enscript --fancy-header=my --header='$N||' --footer='|$%/%p|' --output=doc.ps
ps2pdf doc.ps doc.pdf

產出以後,會發現頁碼怪怪的,頁碼只有針對個別檔案,不是整份檔案,這下就傷腦筋了。經過Google 的幫忙,找到 pdftk 來幫忙。pdftk 是一個可以操作 pdf 的工具,可以作合併、加浮水印等等的功能。

最後的成果如下

DOC_PS=/tmp/doc.ps
RAW_DOC_PDF=/tmp/raw_doc.pdf
DOC_PDF=/tmp/doc.pdf

# 產出 postscript 檔案
find collections/ansible_collections/gov/twgcb/roles -name '*.yml' -print | xargs enscript \
  --fancy-header=my \
  --header='$N||' \
  --footer='| |' \
  --output=${DOC_PS}

# 前個步驟有產出 ps 檔案
if [[ -f ${DOC_PS} ]]; then
  # 先轉為 pdf
  ps2pdf ${DOC_PS} ${RAW_DOC_PDF}
  # 取得頁數
  number_of_pages=$(pdftk /tmp/doc.pdf dump_data | grep NumberOfPages | sed 's/NumberOfPages: //g')
  # 印出
  echo "number_of_pages=${number_of_pages}"
  # 先產生一份空白的 pdf ,頁次重新編排,然後把這份 pdf 當作是前面產生的 pdf 的浮水印
  # 這樣頁次就是對的了。
  enscript -L1 --fancy-header=my --header='||' --footer '|$% / $=|' -o- < \
  <(for i in $(seq 1 $number_of_pages); do echo; done) | \
  ps2pdf - | \
  pdftk ${RAW_DOC_PDF} multistamp - output ${DOC_PDF}
fi

參考資料

星期一, 10月 16, 2017

pdfkit/wkhtmltopdf

wkhtmltopdf 是一個可以將網址或是 HTML 檔案轉換為 PDF 的程式。
pdfkit 則是一個 python package (或 library),用來將網址或是 HTML 轉換為 PDF,底層用的是 wkhtmltopdf 。
django-pdfkit 則是給 Django 使用的 app,主要使用 pdfkit ,提供了 PDFView 。要提供產出 PDF 的網頁,只要寫一個繼承自 PDFView 的 View,撰寫 template ,就可以了。
以下是幾個試過以後的心得:
  1. 內部處理順序是先使用 Django template 輸出為 HTML,再用 pdfkit 輸出為 PDF。
  2. 預設用 PATH 去找 wkhtmltopdf,但如果有指定 WKHTMLTOPDF_BIN 這個環境變數的話,就用這裏面的。
  3. 在網址加入 html 參數,表示顯示 HTML,例如:http://server/show_pdf/?html
  4. 在網址加上 inline 參數 ,表示直接顯示 PDF,而非下載,例如:http://server/show_pdf/?inline
  5. 要自訂 pdfkit 使用 wkhtmltopdf 的參數,在繼承的 View 裡加入 pdfkit_options (型態為 dict) 或是自訂 get_pdfkit_options method。
  6. 要自訂輸出的檔名,可以在繼承的 View 裡加入 filename 或是自訂 get_filename method。
  7. wkhtmltopdf 預設不使用 print media-type ,所以在 css 裡加的 print media-type 相關樣式都沒用,除非自訂 pdfkit_options ,加入 {"print-media-type": ""}。雖然加了 print-media-type 可以強制讓 wkhtmltopdf 參考 print media-type,但是一般可以在網路上查到,使用 print media-type 在每頁加頁次的方法是行不通的,一樣要自訂 pdfkit_options 才行 (參考 wkhtmltopdf -h 說明):{ 'footer-center': '[page] / [toPage]'}。其他還有調頁面邊界、紙張大小的,也都是要看 wkhtmltopdf 的說明來調整 pdfkit_options 。
  8. bootstrap 3 本身就有支援 print media-type ,直接使用就會有不錯的效果。如果要更漂亮,可以參考 Natshah/bootstrap-print: To manage print media for Twitter Bootstrap v3.
  9. 表格跨頁標題主要是使用 table/thead/tbody 跟調整 css,之前參考的網頁找不到了,這裡直接貼相關的 css 跟 html:
    /* CSS */
    @media print {
      table {display:table;}
      thead {display:table-header-group!important;page-break-after:avoid!important;}
      tbody {display:table-row-group!important;page-break-after: auto!important;}
      tr, img {display:table-row!important;page-break-inside:avoid!important;page-break-after: auto!important;}
      td, th {display:table-cell!important;}
    }
    
    
    
    編號 姓名
    1 王小明

星期五, 1月 11, 2013

Firefox 18 的 PDF Viewer

看到新聞說 Firefox 18 已經有內置 PDF Viewer 了,找了選單,卻找不到怎麼開,用開新檔案,只會出現詢問下載位置的視窗。

找了一下,找到這篇 Show PDF inline Test Plan 才發現 Status 標為 Disabled until Firefox 19,所以是已經內置,但是功能沒打開。就心血來潮,在網址列輸入 about:config 找 pdf,果然看到 pdfjs.disabled 被標為 true,就把這個值改為 false,然後重新啟動 Firefox,就可以從「開新分頁」>「開啟檔案」去開啟 pdf 了。

不過,後來我還是把這個值給回復為 true 了,Mozilla 開發小組把這功能 disable 應該是有原因的,就等 Firefox 19 再說吧。

星期一, 5月 28, 2012

PDF 操作個人經驗談

整理一下使用 PDF 的經驗談,作為日後參考。
閱讀 PDF:Windows 上主要是用 Foxit Reader ,偶爾會用 Nitro PDF reader 。用 Foxit Reader 是求快,用 Nitro PDF reader 的好處是可以匯出 PDF 裡的圖片。Linux 上我也是用 Foxit Reader ,然後以預設的 GNOME evince 為輔。在 PDF 檔上下標記? 我沒這個需求,所以沒用過,不知道這幾套對這功能的支援如何。
產出 PDF:我有用過的幾套免費軟體,都是以虛擬印表機的形式存在,所以只要選定指定的印表機進行列印,就可以產出 PDF。在 Windows 下,我使用過的軟體有 PDF CreatordoPDF Nitro PDF Creator (好像是裝 Nitro PDF reader時裝上的),都不錯用,會用三套,是因為有時候會有字出不來的情況。在 Linux 上就最方便了,不必另外安裝,一樣也是列印時,指定列印到檔案即可。另外值得一提的是 Open/Libre Office ,裡面有提供獨立的選項,可以直接匯出 PDF。
合併與分割:如果只是簡單的合併跟分割,我是用 PDFSam ,這個可愛的工具是用 Java 寫的,Linux / Windows 上都通用。如果需要一次裁出好幾頁或是編排順序的話,Linux 上我是用 PDFMod ,Windows 上則是用從疑似從 PDFMod 分支出來的 Junko 。
編輯:我沒用到過,也就是說我到目前為止還沒有這個需求,等以後有遇到再說吧。我第一個會試試看的可能是 Open/Libre Office ,去年有聽說有加入這功能。