IMSLP:PDF-Komprimierung optimieren


Einige PDF-Dateien verwenden eine verbesserungsfähige Bilderkomprimierung; diese Seite listet einige Wege auf um dieses Problem bei der Neukomprimierung bzw. Neuerstellung der Datei zu verhindern. Die beschriebenen Methoden sollten verlustfrei sein; es ist besser, einen größere Datei einzustellen wenn sie ansonsten nicht verlustfrei komprimiert werden kann.

Contents

 [hide

Methoden

PDF Split and Merge verwenden

Siehe hier für Informationen zu diesem Programm.

pdfimages verwenden

Diese Methode versucht die PDF-Datei neu zu gestalten, indem Sie die Bilder herausschneidet und die PDF-Datei anschließend aus den Bildern neu erstellt. Nachfolgend ein Ruby-Skript, das diese Aufgabe erfüllt.

Systemvoraussetzungen

Wann diese Methode nicht angewandt werden kann

  • bei Graustufen und farbigen PDF-Dateien
  • bei PDF-Dateien, die keine Bilder enthalten (d.h. neu gesetzte PDF-Dateien)
  • bei anderen PDF-Dateien mit seltsamen Erzeugungsmethoden (eher selten)

Probleme und Lösungen

  • Die PDF-Ausgabe-Datei ist sehr groß
    • Lösung: Sehr viele Bilder von gescannten Noten oder Text lassen sich für den Ausdruck in Schwarz/Weiß (2 Farben) umwandeln. Dabei wird das Floyd-Steinberg-Dithering verwendet, das einen ähnlichen Effekt bei Schwarz/Weiß-Bildern erzeugt wie das Anti-Aliasing bei Farb-/Graustufenbildern. Ein gutes Ausgabe-Bildformat ist PNG (Portable Network Graphic) mit Huffman-Kompression. Alternativ bietet sich auch das GIF (Graphic Interchange Format) Bild-Format an, bei dem die Dateien geringfügig größer sind als bei PNG-Bildern. Die Dateigröße gegenüber dem Graustufenbild im JPG-Format verringert sich erheblich - auf 1/8 bis 1/10, und das daraus erzeugte PDF-File wird um den gleichen Faktor kleiner sein, ohne die Qualität des Ausdrucks zu verringern.
  • Die entstandene PDF-Datei hat invertierte Farben
    • Lösung: lassen Sie das Skript mit dem Zusatz -negate laufen, z.B. ./pdfcompress.rb somefile.pdf -negate für Unix und ruby pdfcompress.rb somefile.pdf -negate für Windows
  1. #!/usr/bin/ruby
  2. require( 'fileutils' )
  3.  
  4. BASICCONVERTOPTIONS = " -compress Group4"
  5. DELETEIGNOREFILE = false #Automatically delete files which grow in size after recompression?
  6. TMPDIRNAME = "tmpx139toslw"
  7.  
  8. if ARGV[0] === NIL
  9. $stderr.puts "Syntax: pdfcompress.rb <PDF file> ( <additional convert options> )"
  10. exit 1
  11. end
  12.  
  13. if ARGV[1] === NIL
  14. convertoptions = BASICCONVERTOPTIONS
  15. else
  16. convertoptions = ARGV[1] + BASICCONVERTOPTIONS
  17. end
  18.  
  19. begin
  20. Dir.mkdir( TMPDIRNAME )
  21. $stderr.puts "Processing file " + ( file = ARGV[0] ) + "..."
  22. #Convert to individual PDFs
  23. system( "pdfimages \"" + file +"\" " + File.join( TMPDIRNAME, "images" ) )
  24. Dir.glob( File.join( TMPDIRNAME, "*" ) ).each { |imagefile|
  25. $stderr.printf( "\rCompressing " + File.basename( imagefile ) + "..." );
  26. system( "convert #{convertoptions} \"" + imagefile + "\" \"" + imagefile.sub( /\.[^.]*$/, ".tiff" ) + "\"" )
  27. system( "tiff2pdf \"" + imagefile.sub( /\.[^.]*$/, ".tiff" ) + "\" -o \"" + imagefile.sub( /\.[^.]*$/, ".pdf" ) +"\"" )
  28. }
  29. $stderr.printf( "\n" );
  30. #Put them all together now
  31. $stderr.printf( "Combining PDF files... " );
  32. system( "pdftk \"" + Dir.glob( File.join( TMPDIRNAME, "*.pdf" ) ).join( "\" \"" ) + "\" cat output \"" + ( output_filename = File.basename( file ).sub( /#{File.extname( file )}$/, ".2.pdf" ) ) + "\"" )
  33. $stderr.printf( "Done\n" );
  34. #Compare the sizes
  35. if( File.size( file ) > File.size( output_filename ) )
  36. $stdout.puts "Compressed file " + File.basename( file ) + " - Compressed from " + File.size( file ).to_s + " to " + File.size( output_filename ).to_s
  37. else
  38. $stdout.puts "Ignored file " + File.basename( file ) + " - Changed from " + File.size( file ).to_s + " to " + File.size( output_filename ).to_s
  39. File.delete( output_filename ) if DELETEIGNOREFILE
  40. end
  41. ensure
  42. #Clean up temp dir
  43. Dir.glob( File.join( TMPDIRNAME, "*" ) ).each { |delfile| File.delete( delfile ) }
  44. Dir.delete( TMPDIRNAME );
  45. end