Konwersja pliku PDF do PNG

83

Próbuję przekonwertować plik PDF na obraz PNG (przynajmniej okładkę jednego). Pomyślnie wyodrębniam pierwszą stronę pliku PDF za pomocą pdftk. Używam imagemagick do konwersji:

convert cover.pdf cover.png

To działa, ale niestety plik cover.png jest nieprawidłowo renderowany (niektóre obiekty alfa w pliku PDF nie są poprawnie renderowane). Wiem, że ImageMagick używa GhostScript do konwersji i jeśli zrobię to bezpośrednio z gs, mogę uzyskać pożądane wyniki, ale wolałbym użyć biblioteki konwertującej, ponieważ ma inne narzędzia, które chciałbym wykorzystać.

To polecenie w GhostScript wykonuje żądany obraz:

gs -sDEVICE=pngalpha -sOutputFile=cover.png -r144 cover.pdf

Zastanawiam się, czy istnieje sposób na przekazywanie argumentów przez konwersję do GhostScript, czy też utknąłem z bezpośrednim wywołaniem GhostScriptu?

Adam
źródło
2
Dlaczego wywołanie GhostScript bezpośrednio stanowi problem?
kquinn
To naprawdę nie jest taka wielka sprawa. Chciałbym w tym samym czasie przeprowadzić konwersję kilku innych parametrów i byłoby miło, gdybym mógł to wszystko zachować w jednym poleceniu. Sprawia, że ​​mój kod jest bardziej przejrzysty i spójny. Oznacza to również jeden plik tymczasowy mniej.
Adam
Jaka jest różnica między tym, jak nazywasz gs, a tym, jak nazywa to ImageMagick? Może warto zgłosić coś upstream do ImageMagick (uwaga dla obserwujących, aktualizacja ghostscriptu też może pomóc ...)
rogerdpack

Odpowiedzi:

71

Możesz użyć jednego wiersza poleceń z dwoma poleceniami ( gs, convert) połączonymi potokiem, jeśli pierwsze polecenie może zapisać swoje wyjście na stdout, a drugie może odczytać swoje wejście ze stdin.

  1. Na szczęście gs może pisać do stdout ( ... -o %stdout ...).
  2. Na szczęście convert może czytać ze stdin ( convert -background transparent - output.png).

Problem rozwiązany:

  • GS używany do obsługi kanału alfa specjalnego obrazu,
  • konwertuj używany do tworzenia przezroczystego tła,
  • potok używany do uniknięcia zapisywania pliku tymczasowego na dysku.

Kompletne rozwiązanie:

gs -sDEVICE=pngalpha       \
   -o %stdout              \
   -r144 cover.pdf         \
   |                       \
convert                    \
   -background transparent \
   -                       \
    cover.png

Aktualizacja

Jeśli chcesz mieć osobny plik PNG na stronę PDF, możesz użyć rozszerzenia %d składni:

gs -sDEVICE=pngalpha -o file-%03d.png -r144 cover.pdf

Spowoduje to utworzenie plików PNG o nazwach page-000.png,page-001.png ... (uwaga, że %d-counting jest od zera - file-000.pngodpowiada do strony 1 PDF,001 na stronie 2 ...

Lub, jeśli chcesz zachować przezroczyste tło, w przypadku 100-stronicowego pliku PDF, zrób to

for i in {1..100}; do        \
                             \
  gs -sDEVICE=pngalpha       \
     -dFirstPage="${i}"      \
     -dLastPage="${i}"       \
     -o %stdout              \
     -r144 input.pdf         \
     |                       \
  convert                    \
     -background transparent \
     -                       \
      page-${i}.png ;        \
                             \
done
Kurt Pfeifle
źródło
7
Działa to tylko dla mnie, jeśli dodam -dBATCH -dNOPAUSE -dQUIETdo opcji gs.
ford
@ford: To znaczy, że masz starą wersję Ghostscript. Najnowsze wersje mogą to zrobić, -o output.filea to automatycznie i cicho również ustawia -dBATCH -dNOPAUSE -dQUIETw tym samym czasie.
Kurt Pfeifle
@ford: Jednak w innym miejscu powyższej odpowiedzi miałem poważną literówkę. Zastanawiam się, dlaczego mimo to dostał 22 głosy poparcia :-)
Kurt Pfeifle 16.11.14
Znajdź pracę dla mnie, ale chciałbym automatycznie przekształcić wielostronicowy plik PDF do image_1.png, image_2.png ... Czy to łatwe w jednym poleceniu, czy najpierw wyodrębnić każdą stronę z pliku PDF?
Tarass
Ok, oddzieliłem zdjęcia. Ale chcę, aby podczas konwersji jako parametr „konwersja” był „biały przezroczysty”. Udało mi się to zrobić z fajką, ale bez?
Tarass
29

Spośród wszystkich dostępnych alternatyw znalazłem Inkscape, który zapewnia najdokładniejsze wyniki podczas konwersji plików PDF do PNG. Zwłaszcza gdy plik źródłowy miał przezroczyste warstwy, Inkscape odniósł sukces tam, gdzie zawiodły Imagemagick i inne narzędzia.

Oto polecenie, którego używam:

inkscape "$pdf" -z --export-dpi=600 --export-area-drawing --export-png="$pngfile"

I tutaj jest zaimplementowany w skrypcie:

#!/bin/bash

while [ $# -gt 0 ]; do

pdf=$1
echo "Converting "$pdf" ..."
pngfile=`echo "$pdf" | sed 's/\.\w*$/.png/'`
inkscape "$pdf" -z --export-dpi=600 --export-area-drawing --export-png="$pngfile"
echo "Converted to "$pngfile""
shift

done

echo "All jobs done. Exiting."
Glutanimate
źródło
21

Aby przekonwertować plik PDF na pliki graficzne, użyj następujących poleceń:

W przypadku PNG gs -sDEVICE=png16m -dTextAlphaBits=4 -r300 -o a.png a.pdf

W przypadku JPG gs -sDEVICE=jpeg -dTextAlphaBits=4 -r300 -o a.jpg a.pdf

Jeśli masz wiele stron, dodaj do nazwy % 03d gs -o a%03d.jpg a.pdf

Co oznacza każda opcja:

  • sDEVICE = {jpeg, pngalpha, png16m ...} - typ pliku
  • -o - plik wyjściowy (% stdout do stdout)
  • -dTextAlphaBits = 4 - wygładzanie czcionek.
  • -r300 - 300 dpi
yanpas
źródło
9

Można również skorzystać z narzędzi wiersza poleceń zawartych w poppler-utilspakiecie:

sudo apt-get install poppler-utils
pdftoppm --help
pdftocairo --help

Przykład:

pdftocairo -png mypage.pdf mypage.png
turdus-merula
źródło
1
To jest bardzo dobre. Jeśli plik PDF jest wielostronicowy, będzie wiele plików PNG.
Tomasz Gandor
5

Nie udało się uzyskać zaakceptowanej odpowiedzi. Potem okazało się, że w rzeczywistości rozwiązanie jest i tak znacznie prostsze, ponieważ Ghostscript nie tylko natywnie obsługuje PNG, ale nawet wiele różnych „kodowań” :

  • png256
  • png16
  • pnggray
  • pngmono
  • ...

Polecenie powłoki, które działa dla mnie, to:

gs -dNOPAUSE -q -sDEVICE=pnggray -r500 -dBATCH -dFirstPage=2 -dLastPage=2 -sOutputFile=test.png test.pdf

Spowoduje to zapisanie strony 2 pliku test.pdf do pliku test.png przy użyciu pnggraykodowania i rozdzielczości 500 DPI.

Raffael
źródło
2

Oto niemiecka dyskusja na temat takiego problemu z plikami SVG, w którym można go rozwiązać za pomocą

convert -background transparent

Być może to działa również dla Ciebie.

schnaader
źródło
Niestety nie, to nie rozwiązuje mojego problemu. W rzeczywistości jest to obraz w pliku PDF, który ma kanał alfa, który znajduje się nad wszystkim.
Adam
2

Dodam moje rozwiązanie, nawet myślałem, że jego nić jest stara. Może i tak komuś to pomoże.

Najpierw muszę wygenerować plik PDF. Do tego używam XeLaTeX :

xelatex test.tex

Teraz ImageMagick i GraphicMagic analizują oba parametry od lewej do prawej, więc parametr skrajny lewy zostanie wykonany jako pierwszy. Skończyło się na użyciu tej sekwencji do optymalnego przetwarzania:

gm convert -trim -transparent white -background transparent -density 1200x1200 -resize 25% test.pdf test.png

Daje ładną grafikę na przezroczystym tle, przyciętą do tego, co faktycznie znajduje się na stronie. -densityI -resizeparametry, dają lepszą szczegółowość i zwiększyć ogólną rozdzielczość.

Proponuję sprawdzić, czy dla Ciebie można zmniejszyć gęstość. Skróci to czas konwersji.

polemon
źródło
2

W przypadku pliku PDF, który ImageMagick podawał niedokładne kolory, stwierdziłem, że GraphicsMagick wykonał lepszą pracę:

$ gm convert -quality 100 -thumbnail x300 -flatten journal.pdf\[0\] cover.jpg
aorth
źródło
Za mało informacji, aby mieć pewność, ale może to być spowodowane nieprawidłowym zdefiniowaniem przestrzeni kolorów. Sprawdź opcję -colorspace IM.
rivimey
2

Ponieważ ta strona zawiera również listę alternatywnych narzędzi, wspomnę o xpdf, który ma gotowe narzędzia wiersza poleceń skompilowane dla systemu Linux / Windows / Mac. Obsługuje przejrzystość. Jest darmowy do użytku komercyjnego - w przeciwieństwie do Ghostscript, który ma naprawdę skandaliczne ceny.

W teście na dużym pliku PDF był o 7,5% szybszy niż Ghostscript.

(Posiada również konwertery PDF na tekst i HTML)

TheStoryCoder
źródło
Używałem tego przez chwilę i działa dobrze. Generalnie jest nieco wolniejszy niż Ghostscript, choć przy wyższych rozdzielczościach. Ale obrazy wyglądają o wiele ładniej (choć trochę ciemniej), a antyaliasing, który mogłem uzyskać w Ghostscript, działa świetnie w xpdf!
TheStoryCoder
2

Spróbuj wyodrębnić jedną stronę.

$ page = 4

gs -sDEVICE=pngalpha -dFirstPage="$page" -dLastPage="$page" -o thumb.png -r144 input.pdf
Ezequiel Fernandez
źródło
1

Moje rozwiązanie jest znacznie prostsze i bardziej bezpośrednie. Przynajmniej działa w ten sposób na moim komputerze (z następującymi specyfikacjami):

me@home: my.folder$ uname -a
Linux home 3.2.0-54-generic-pae #82-Ubuntu SMP Tue Sep 10 20:29:22 UTC 2013 i686 i686 i386 GNU/Linux

z

me@home: my.folder$ convert --version
Version: ImageMagick 6.6.9-7 2012-08-17 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2011 ImageMagick Studio LLC
Features: OpenMP

Oto, co uruchamiam na moim file.pdf:

me@home: my.folder$ convert -density 300 -quality 100 file.pdf file.png
polaryzować
źródło
Tak, to jest to, co początkowo próbował OP, ale nie mógł uzyskać czegoś innego do pracy pod spodem, gdy ImageMagick wywołuje ghostscript ... ale jeśli to
zadziała, zrób
0

Możesz użyć ImageMagick bez oddzielania pierwszej strony pliku PDF innymi narzędziami. Po prostu zrób

convert -density 288 cover.pdf[0] -resize 25% cover.png


Tutaj zwiększam gęstość nominalną o 400% (72 * 4 = 288), a następnie zmieniam rozmiar o 1/4 (25%). Daje to znacznie lepszą jakość wynikowego png.

Jeśli jednak plik PDF jest w formacie CMYK, format PNG tego nie obsługuje. Musiałby zostać przekonwertowany na sRGB, zwłaszcza jeśli ma przezroczystość, ponieważ Ghostscript nie obsługuje CMYK z alfa.

convert -density 288 -colorspace sRGB -resize 25% cover.pdf[0] cover.png
fmw42
źródło