Como converter um pdf colorido em preto-branco?

14

Gostaria de transformar um pdf com alguns textos e imagens coloridas em outro pdf com apenas 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 imagens. Eu tentei o seguinte comando:

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

encontrado em outra pergunta, um link , mas faz o que eu 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 isso me dá a seguinte mensagem de erro:

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

Existe alguma outra maneira de criar o arquivo?

    
por BowPark 07.10.2013 / 18:46

4 respostas

19

O exemplo gs

O comando gs que você está executando acima tem um $1 à direita, que normalmente é usado para passar argumentos de linha de comando para um script. Então, eu não tenho certeza do que você realmente tentou, mas eu estou supondo 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 corra assim:

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

Não tenho certeza de como você configurou esse script, mas ele precisa ser executado.

$ chmod +x script.sh

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

Unrecoverable error: 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
    
por 07.10.2013 / 20:18
7

Eu encontrei um script aqui que pode fazer isso. Ele exige gs , o que parece ter, mas também pdftk . Você não mencionou sua distribuição, mas em sistemas baseados em Debian, você deve ser capaz de instalá-lo com

sudo apt-get install pdftk

Você pode encontrar RPMs para aqui .

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

./greypdf.sh input.pdf

Ele criará um arquivo chamado input-gray.pdf . Eu estou incluindo todo o script aqui para evitar a podridão do 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
# https://sobrelinux.info/questions/4455/renumber-pages-of-a-pdf"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). 
    
por 07.10.2013 / 20:14
2

Eu também tinha alguns pdfs digitalizados em cores e pdfs em tons de cinza que eu queria converter em bw. Eu tentei usar gs com o código listado aqui , e a qualidade da imagem é boa com o texto em PDF ainda disponível. No entanto, esse código gs só converte em escala de cinza (como solicitado na pergunta) e ainda tem tamanho de arquivo grande. convert produz resultados muito ruins quando usado diretamente.

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

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

Eu tentei ir diretamente para o tiff do pdf, mas a qualidade não é a mesma, então salvei cada página em bmp. Para um arquivo pdf de uma página, convert faz 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, gs pode mesclar vários arquivos PDF em um, mas img2pdf gera tamanho de arquivo menor que gs. Os arquivos tiff devem ser descompactados como entrada para img2pdf. Tenha em mente para um grande número de páginas, os arquivos intermediários bmp e tiff tendem a ser grandes em tamanho. pdftk ou joinpdf seria melhor se eles pudessem mesclar arquivos PDF compactados de convert .

Eu imagino que haja 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 obter o texto de volta no pdf do bw, execute o OCR novamente.

Meu shell script usa gs, convert e img2pdf. Altere os parâmetros (número de páginas, dpi digitalizado,% 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
    
por 13.01.2015 / 23:52
0

RHEL6 e RHEL5, que tanto o Ghostscript de linha de base no 8.70, não poderiam usar as formas do comando dado acima. Supondo que um script ou uma 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 "gray _".

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

    
por 19.02.2015 / 23:36