Como converter um pdf em cores para preto-branco?

18

Gostaria de transformar um pdf com texto e imagens coloridos em outro pdf apenas em preto e branco, a fim de reduzir suas dimensões. Além disso, gostaria de manter o texto como texto, sem transformar os elementos das páginas em figuras. Eu tentei o seguinte comando:

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

encontrado em outra pergunta, um link , mas ele faz o que não quero: o texto na saída é transformado em uma imagem ruim e não é mais selecionável. Eu tentei com o 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

mas me dá a seguinte mensagem de erro:

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

Existe alguma outra maneira de criar o arquivo?

BowPark
fonte
Isso parece tão bom superuser.com/questions/200378/...
slackmart
Cuidado ao usar algumas das abordagens de superusuário, elas convertem o PDF em uma versão rasterizada, para que não sejam mais gráficos vetoriais.
slm
11
Esse é o script inteiro que você executou? Não parece, você poderia postar o script inteiro?
terdon

Respostas:

23

O exemplo gs

O gscomando que você está executando acima possui um trailing, $1que normalmente significa passar argumentos de linha de comando para um script. Portanto, não tenho certeza do que você realmente tentou, mas acho que você tentou colocar esse comando em um 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

E execute-o assim:

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

Não sei como você configura esse script, mas ele precisa ser executável.

$ chmod +x script.sh

Algo definitivamente não parece certo com esse script. Quando tentei, recebi este erro:

Erro irrecuperável: rangecheck in .putdeviceprops

Uma alternativa

Em vez desse script, eu usaria esse da pergunta SU.

#!/bin/bash

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

Em seguida, execute-o assim:

$ ./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
slm
fonte
Você está certo, há algo errado com o script: "algo" nesse caso seria o sProcessColorModelque deveria ser dProcessColorModel.
Sora.
8

Encontrei um script aqui que pode fazer isso. Requer o gsque você parece ter, mas também pdftk. Você não mencionou sua distribuição, mas em sistemas baseados no Debian, você poderá instalá-la com

sudo apt-get install pdftk

Você pode encontrar RPMs para isso aqui .

Depois de instalar pdftk, salve o script como graypdf.she execute da seguinte forma:

./greypdf.sh input.pdf

Isso criará um arquivo chamado input-gray.pdf. Estou incluindo o script inteiro aqui para evitar o rot pod:

# 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). 
terdon
fonte
3

Eu também tinha alguns PDFs coloridos digitalizados e PDFs em escala de cinza que queria converter para bw. Tentei usar gscom o código listado aqui e a qualidade da imagem é boa com o texto em pdf ainda lá. No entanto, esse código gs é convertido apenas em escala de cinza (conforme solicitado na pergunta) e ainda possui um tamanho de arquivo grande. convertproduz resultados muito ruins quando usado diretamente.

Eu queria PDFs BW com boa qualidade de imagem e tamanho pequeno de arquivo. Eu teria tentado a solução de Terdon, mas não consegui pdftkacessar o centOS 7 usando o yum (no momento da redação).

Minha solução usa gspara extrair arquivos bmp em escala de cinza do pdf, convertpara limitar esses bmps a bw e salvá-los como arquivos tiff e, em seguida, img2pdf para compactar as imagens tiff e mesclá-las em um único pdf.

Eu tentei ir diretamente para tiff do pdf, mas a qualidade não é a mesma, então eu salvei cada página em bmp. Para um arquivo pdf de uma página, convertfaz um ótimo trabalho de bmp para pdf. Exemplo:

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

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

Para várias páginas, gspode mesclar vários arquivos pdf em um, mas img2pdfgera um tamanho de arquivo menor que o gs. Os arquivos tiff devem ser descompactados como entrada para img2pdf. Lembre-se de que, para um grande número de páginas, os arquivos intermediários bmp e tiff tendem a ser grandes. pdftkou joinpdfseria melhor se eles pudessem mesclar arquivos pdf compactados convert.

Imagino que exista uma solução mais elegante. No entanto, meu método produz resultados com qualidade de imagem muito boa e tamanho de arquivo muito menor. Para recuperar o texto no PDF bw, execute o OCR novamente.

Meu script de shell usa gs, convert e img2pdf. Altere os parâmetros (número de páginas, dpi de digitalização,% de limite etc.) listados no início, conforme necessário, e execute chmod +x ./pdf2bw.sh. Aqui está o 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
OccamsRazor
fonte
1

RHEL6 e RHEL5, que ambos Ghostscript na linha de base na versão 8.70, não podiam usar as formas do comando fornecido acima. Supondo que um script ou função espere o arquivo PDF como o primeiro argumento "$ 1", o seguinte deve ser mais portátil:

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

Onde o arquivo de saída será prefixado com "grey_".

RHEL6 e 5 podem usar CompatibilityLevel = 1.4, que é muito mais rápido, mas eu estava buscando portabilidade.

Rico
fonte
Os desenvolvedores dizem ( 1 , 2 , 3 , 4 ) que não há sColorConversionStrategyForImagesopção.
Igor
Obrigado, @Igor - não faço ideia de onde peguei esse trecho! Sei que o testei e funcionou na época . (E é isso, pessoal, é por isso que você sempre deve fornecer referências para o seu código.) #
1932 Rich Rich
11
Esse "parâmetro falso" parece ser incrivelmente popular entre a web. O GS ignora switches desconhecidos (o que é triste), portanto funciona de qualquer maneira.
Igor
1

Eu obtenho resultados confiáveis ​​limpando os PDFs digitalizados para contrastar com este 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*
Bijou Smith
fonte