Come convertire un pdf a colori in bianco e nero?


18

Vorrei trasformare un pdf con del testo e delle immagini colorati in un altro pdf con solo bianco e nero, al fine di ridurne le dimensioni. Inoltre, vorrei mantenere il testo come testo, senza trasformare gli elementi delle pagine in immagini. Ho provato il seguente comando:

convert -density 150 -threshold 50% input.pdf output.pdf

trovato in un'altra domanda, un link , ma fa quello che non voglio: il testo nell'output viene trasformato in un'immagine scadente e non è più selezionabile. Ho provato con Ghostscript:

gs      -sOutputFile=output.pdf \
        -q -dNOPAUSE -dBATCH -dSAFER \
        -sDEVICE=pdfwrite \
        -dCompatibilityLevel=1.3 \
        -dPDFSETTINGS=/screen \
        -dEmbedAllFonts=true \
        -dSubsetFonts=true \
        -sColorConversionStrategy=/Mono \
        -sColorConversionStrategyForImages=/Mono \
        -sProcessColorModel=/DeviceGray \
        $1

ma mi dà il seguente messaggio di errore:

./script.sh: 19: ./script.sh: output.pdf: not found

C'è un altro modo per creare il file?




Attenzione quando si utilizzano alcuni degli approcci del superutente, convertono il PDF in una versione rasterizzata, quindi non è più una grafica vettoriale.
slm

1
È l'intero script che hai eseguito? Non sembra, potresti pubblicare l'intero script?
terdon

Risposte:


23

L'esempio gs

Il gscomando che stai eseguendo sopra ha un finale $1che in genere è pensato per passare argomenti della riga di comando in uno script. Quindi non sono sicuro di cosa tu abbia effettivamente provato, ma immagino che tu abbia provato a inserire quel comando in uno script script.sh:

#!/bin/bash

gs      -sOutputFile=output.pdf \
        -q -dNOPAUSE -dBATCH -dSAFER \
        -sDEVICE=pdfwrite \
        -dCompatibilityLevel=1.3 \
        -dPDFSETTINGS=/screen \
        -dEmbedAllFonts=true \
        -dSubsetFonts=true \
        -sColorConversionStrategy=/Mono \
        -sColorConversionStrategyForImages=/Mono \
        -sProcessColorModel=/DeviceGray \
        $1

Ed eseguilo in questo modo:

$ ./script.sh: 19: ./script.sh: output.pdf: not found

Non sono sicuro di come si imposta questo script ma deve essere eseguibile.

$ chmod +x script.sh

Qualcosa sicuramente non sembra giusto con quella sceneggiatura però. Quando l'ho provato ho ricevuto invece questo errore:

Errore irreversibile: rangecheck in .putdeviceprops

Un'alternativa

Invece di quello script userei invece questo dalla domanda SU.

#!/bin/bash

gs \
 -sOutputFile=output.pdf \
 -sDEVICE=pdfwrite \
 -sColorConversionStrategy=Gray \
 -dProcessColorModel=/DeviceGray \
 -dCompatibilityLevel=1.4 \
 -dNOPAUSE \
 -dBATCH \
 $1

Quindi eseguilo in questo modo:

$ ./script.bash LeaseContract.pdf 
GPL Ghostscript 8.71 (2010-02-10)
Copyright (C) 2010 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Processing pages 1 through 2.
Page 1
Page 2

Hai ragione, c'è qualcosa di sbagliato nello script: "qualcosa" in questo caso sarebbe quello sProcessColorModelche dovrebbe essere dProcessColorModelinvece.
Sora.

8

Ho trovato una sceneggiatura qui che può fare questo. Richiede gsciò che sembri avere ma anche pdftk. Non hai menzionato la tua distribuzione ma su sistemi basati su Debian, dovresti essere in grado di installarla con

sudo apt-get install pdftk

Puoi trovare RPM qui .

Una volta installato pdftk, salva lo script come graypdf.shed eseguilo in questo modo:

./greypdf.sh input.pdf

Creerà un file chiamato input-gray.pdf. Sto includendo l'intero script qui per evitare il marcio dei link:

# convert pdf to grayscale, preserving metadata
# "AFAIK graphicx has no feature for manipulating colorspaces. " http://groups.google.com/group/latexusersgroup/browse_thread/thread/5ebbc3ff9978af05
# "> Is there an easy (or just standard) way with pdflatex to do a > conversion from color to grayscale when a PDF file is generated? No." ... "If you want to convert a multipage document then you better have pdftops from the xpdf suite installed because Ghostscript's pdf to ps doesn't produce nice Postscript." http://osdir.com/ml/tex.pdftex/2008-05/msg00006.html
# "Converting a color EPS to grayscale" - http://en.wikibooks.org/wiki/LaTeX/Importing_Graphics
# "\usepackage[monochrome]{color} .. I don't know of a neat automatic conversion to monochrome (there might be such a thing) although there was something in Tugboat a while back about mapping colors on the fly. I would probably make monochrome versions of the pictures, and name them consistently. Then conditionally load each one" http://newsgroups.derkeiler.com/Archive/Comp/comp.text.tex/2005-08/msg01864.html
# "Here comes optional.sty. By adding \usepackage{optional} ... \opt{color}{\includegraphics[width=0.4\textwidth]{intro/benzoCompounds_color}} \opt{grayscale}{\includegraphics[width=0.4\textwidth]{intro/benzoCompounds}} " - http://chem-bla-ics.blogspot.com/2008/01/my-phd-thesis-in-color-and-grayscale.html
# with gs:
# http://handyfloss.net/2008.09/making-a-pdf-grayscale-with-ghostscript/
# note - this strips metadata! so:
# http://etutorials.org/Linux+systems/pdf+hacks/Chapter+5.+Manipulating+PDF+Files/Hack+64+Get+and+Set+PDF+Metadata/
COLORFILENAME=$1
OVERWRITE=$2
FNAME=${COLORFILENAME%.pdf}
# NOTE: pdftk does not work with logical page numbers / pagination;
# gs kills it as well;
# so check for existence of 'pdfmarks' file in calling dir;
# if there, use it to correct gs logical pagination
# for example, see
# http://askubuntu.com/questions/32048/renumber-pages-of-a-pdf/65894#65894
PDFMARKS=
if [ -e pdfmarks ] ; then
PDFMARKS="pdfmarks"
echo "$PDFMARKS exists, using..."
# convert to gray pdf - this strips metadata!
gs -sOutputFile=$FNAME-gs-gray.pdf -sDEVICE=pdfwrite \
-sColorConversionStrategy=Gray -dProcessColorModel=/DeviceGray \
-dCompatibilityLevel=1.4 -dNOPAUSE -dBATCH "$COLORFILENAME" "$PDFMARKS"
else # not really needed ?!
gs -sOutputFile=$FNAME-gs-gray.pdf -sDEVICE=pdfwrite \
-sColorConversionStrategy=Gray -dProcessColorModel=/DeviceGray \
-dCompatibilityLevel=1.4 -dNOPAUSE -dBATCH "$COLORFILENAME"
fi
# dump metadata from original color pdf
## pdftk $COLORFILENAME dump_data output $FNAME.data.txt
# also: pdfinfo -meta $COLORFILENAME
# grep to avoid BookmarkTitle/Level/PageNumber:
pdftk $COLORFILENAME dump_data output | grep 'Info\|Pdf' > $FNAME.data.txt
# "pdftk can take a plain-text file of these same key/value pairs and update a PDF's Info dictionary to match. Currently, it does not update the PDF's XMP stream."
pdftk $FNAME-gs-gray.pdf update_info $FNAME.data.txt output $FNAME-gray.pdf
# (http://wiki.creativecommons.org/XMP_Implementations : Exempi ... allows reading/writing XMP metadata for various file formats, including PDF ... )
# clean up
rm $FNAME-gs-gray.pdf
rm $FNAME.data.txt
if [ "$OVERWRITE" == "y" ] ; then
echo "Overwriting $COLORFILENAME..."
mv $FNAME-gray.pdf $COLORFILENAME
fi
# BUT NOTE:
# Mixing TEX & PostScript : The GEX Model - http://www.tug.org/TUGboat/Articles/tb21-3/tb68kost.pdf
# VTEX is a (commercial) extended version of TEX, sold by MicroPress, Inc. Free versions of VTEX have recently been made available, that work under OS/2 and Linux. This paper describes GEX, a fast fully-integrated PostScript interpreter which functions as part of the VTEX code-generator. Unless specified otherwise, this article describes the functionality in the free- ware version of the VTEX compiler, as available on CTAN sites in systems/vtex.
# GEX is a graphics counterpart to TEX. .. Since GEX may exercise subtle influence on TEX (load fonts, or change TEX registers), GEX is op- tional in VTEX implementations: the default oper- ation of the program is with GEX off; it is enabled by a command-line switch.
# \includegraphics[width=1.3in, colorspace=grayscale 256]{macaw.jpg}
# http://mail.tug.org/texlive/Contents/live/texmf-dist/doc/generic/FAQ-en/html/FAQ-TeXsystems.html
# A free version of the commercial VTeX extended TeX system is available for use under Linux, which among other things specialises in direct production of PDF from (La)TeX input. Sadly, it���s no longer supported, and the ready-built images are made for use with a rather ancient Linux kernel.
# NOTE: another way to capture metadata; if converting via ghostscript:
# http://compgroups.net/comp.text.pdf/How-to-specify-metadata-using-Ghostscript
# first:
# grep -a 'Keywo' orig.pdf
# /Author(xxx)/Title(ttt)/Subject()/Creator(LaTeX)/Producer(pdfTeX-1.40.12)/Keywords(kkkk)
# then - copy this data in a file prologue.ini:
#/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse
#[/Author(xxx)
#/Title(ttt)
#/Subject()
#/Creator(LaTeX with hyperref package + gs w/ prologue)
#/Producer(pdfTeX-1.40.12)
#/Keywords(kkkk)
#/DOCINFO pdfmark
#
# finally, call gs on the orig file,
# asking to process pdfmarks in prologue.ini:
# gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 \
# -dPDFSETTINGS=/screen -dNOPAUSE -dQUIET -dBATCH -dDOPDFMARKS \
# -sOutputFile=out.pdf in.pdf prologue.ini
# then the metadata will be in output too (which is stripped otherwise;
# note bookmarks are preserved, however). 

3

Avevo anche alcuni PDF a colori digitalizzati e PDF in scala di grigi che volevo convertire in bw. Ho provato a utilizzare gscon il codice elencato qui e la qualità dell'immagine è buona con il testo pdf ancora lì. Tuttavia, quel codice gs viene convertito solo in scala di grigi (come richiesto nella domanda) e ha ancora file di grandi dimensioni. convertproduce risultati molto scarsi se usato direttamente.

Volevo pdf in bw con una buona qualità dell'immagine e dimensioni ridotte del file. Avrei provato la soluzione di Terdon, ma non sono riuscito pdftka utilizzare centOS 7 usando yum (al momento della stesura).

La mia soluzione utilizza gsper estrarre i file bmp in scala di grigi dal pdf, convertper sottrarre quei bmps a bw e salvarli come file tiff, quindi img2pdf per comprimere le immagini tiff e unirle tutte in un unico pdf.

Ho provato ad andare direttamente a TIFF dal pdf ma la qualità non è la stessa, quindi salvo ogni pagina in bmp. Per un file pdf di una pagina, convertfa un ottimo lavoro da bmp a pdf. Esempio:

gs -sDEVICE=bmpgray -dNOPAUSE -dBATCH -r300x300 \
   -sOutputFile=./pdf_image.bmp ./input.pdf

convert ./pdf_image.bmp -threshold 40% -compress zip ./bw_out.pdf

Per più pagine, è gspossibile unire più file pdf in uno, ma img2pdfproduce file di dimensioni inferiori rispetto a gs. I file tiff devono essere decompressi come input per img2pdf. Tieni presente che per un gran numero di pagine, i file intermedi bmp e tiff tendono ad essere di grandi dimensioni. pdftko joinpdfsarebbe meglio se possono unire file PDF compressi da convert.

Immagino che ci sia una soluzione più elegante. Tuttavia, il mio metodo produce risultati con una qualità dell'immagine molto buona e dimensioni del file molto inferiori. Per recuperare il testo nel pdf di bw, eseguire nuovamente OCR.

Il mio script shell utilizza gs, convert e img2pdf. Modificare i parametri (n. Di pagine, dpi di scansione, soglia%, ecc.) Elencati all'inizio come necessario ed eseguire chmod +x ./pdf2bw.sh. Ecco lo script completo (pdf2bw.sh):

#!/bin/bash

num_pages=12
dpi_res=300
input_pdf_name=color_or_grayscale.pdf
bw_threshold=40%
output_pdf_name=out_bw.pdf
#-------------------------------------------------------------------------
gs -sDEVICE=bmpgray -dNOPAUSE -dBATCH -q -r$dpi_res \
   -sOutputFile=./%d.bmp ./$input_pdf_name
#-------------------------------------------------------------------------
for file_num in `seq 1 $num_pages`
do
  convert ./$file_num.bmp -threshold $bw_threshold \
          ./$file_num.tif
done
#-------------------------------------------------------------------------
input_files=""

for file_num in `seq 1 $num_pages`
do
  input_files+="./$file_num.tif "
done

img2pdf -o ./$output_pdf_name --dpi $dpi_res $input_files
#-------------------------------------------------------------------------
# clean up bmp and tif files used in conversion

for file_num in `seq 1 $num_pages`
do
  rm ./$file_num.bmp
  rm ./$file_num.tif
done

1

RHEL6 e RHEL5, che entrambi basano Ghostscript su 8.70, non sono stati in grado di utilizzare le forme del comando indicato sopra. Supponendo che uno script o una funzione preveda il file PDF come primo argomento "$ 1", dovrebbe essere più portabile quanto segue:

gs \
    -sOutputFile="grey_$1" \
    -sDEVICE=pdfwrite \
    -sColorConversionStrategy=Mono \
    -sColorConversionStrategyForImages=/Mono \
    -dProcessColorModel=/DeviceGray \
    -dCompatibilityLevel=1.3 \
    -dNOPAUSE -dBATCH \
    "$1"

Dove il file di output sarà preceduto da "grey_".

RHEL6 e 5 possono usare CompatibilityLevel = 1.4 che è molto più veloce, ma stavo puntando alla portabilità.


Gli sviluppatori dicono ( 1 , 2 , 3 , 4 ) che non c'è sColorConversionStrategyForImagesinterruttore.
Igor

Grazie, @Igor - Non ho idea da dove ho preso quel frammento! So per certo che l'ho provato e ha funzionato in quel momento . (E quello, gente, è per questo che dovresti sempre fornire riferimenti per il tuo codice.)
Rich

1
Quel "parametro falso" sembra essere incredibilmente popolare tra il web. GS ignora gli switch sconosciuti (il che è triste), quindi funziona comunque.
Igor

1

Ottengo risultati affidabili ripulendo i PDF scansionati in buon contrasto con questo script;

#!/bin/bash
# 
# $ sudo apt install poppler-utils img2pdf pdftk imagemagick
#
# Output is still greyscale, but lots of scanner light tone fuzz removed.
#

pdfimages $1 pages

ls ./pages*.ppm | xargs -L1 -I {} convert {}  -quality 100 -density 400 \
  -fill white -fuzz 80% -auto-level -depth 4 +opaque "#000000" {}.jpg

ls -1 ./pages*jpg | xargs -L1 -I {} img2pdf {} -o {}.pdf

pdftk pages*.pdf cat output ${1/.pdf/}_bw.pdf

rm pages*
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.