Archive

Posts Tagged ‘size’

Reduce pdf file size with GhostScript pdf compression under Linux/Unix

March 19, 2018 Leave a comment

We frequently need to mail pdf files that are too big for regular mail services, such as a 40MB pdf file with a maximum 10MB send restriction. In such situations quick and effective pdf compression comes in handy that does not reduce the quality to a level of the file becoming unusable.

GhostScript

GhostScript LogoUnder Linux and Unix-like systems GhostScript is one of the most powerful tools (probably the most powerful one) to manipulate files like pdf, ps, etc. If you are on a Linux/Unix-like system and need a job with pdf files done check out the “How to use GhostScript” site. It’s not unlikely that GhostScript already has a built in solution to your problem. Consequently it also features a way of effectively compressing pdf files with different options and settings.

GhostScript pdf compression

Effective pdf compression is possible with GhostScript using a single command (adapted from here and here):

gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dQUIET -sOutputFile=outputfile.pdf inputfile.pdf

-dPDFSETTINGS= specifies the quality level of the pdf file. This effects embedded pixel graphics (also adapts embedded color profiles) and is the main option for controlling the compression level, thereby the resulting file size:

  • -dPDFSETTINGS=/screen (72 dpi images)
  • -dPDFSETTINGS=/ebook (150 dpi images)
  • -dPDFSETTINGS=/printer (300 dpi images)
  • -dPDFSETTINGS=/prepress (300 dpi images, color preserving)
  • -dPDFSETTINGS=/default

Other switches: the output is written as pdf (-sDEVICE=pdfwrite), the pdf compatibility level is set to 1.4 (-dCompatibilityLevel=1.4), the process does not require user interaction (-dNOPAUSE and -dQUIET), and GhostScript skips the startup message (-dQUIET).

Categories: Linux, Misc Tags: , , , , , , , ,

Linux: remove files that got deleted while written – or how to lose track of files eating up your disk space

Just stumbled across why you should not simply delete files such as:

/var/log/syslog
/var/log/kern.log

These files get written permanently, therefore are opened. The application writing to the file has an according file handle, therefore deleting the file using

rm /var/log/syslog
rm /var/log/kern.log

deletes the representation of the data in the file system, not the data itself. As the file handle used by the application writing to these files uses the inode, not the file name, the file continues to exist. Therefore you do not free disk space – but lose track of the files eating up your space, if you don’t recognize the mistake. To recreate the access to the file via the file system simply recreate the files and restore their ownership:

touch /var/log/syslog
chown syslog:adm /var/log/syslog
touch /var/log/kern.log
chown syslog:adm /var/log/kern.log

You should see the files in the file system again then. If they stay empty (and you did not free any disk size), try:

reload rsyslog

Then you should see the log growing again – and your disk will finally be less occupied.

Categories: Linux Tags: , , , , ,

convertconditional: convert an image if it fulfills certain conditions

August 28, 2013 Leave a comment

Recently I needed a script to batch convert only those images amongst a large amount of images which fulfil certain criteria, namely of being exactly of a stated size. The script is based on ImageMagick’s convert and basically takes an arbitrary amount of convert parameters. I personally use this script to automatically reduce size and quality of photos taken with a specific camera in order to reduce their hard disk space coverage.

The script

#! /usr/bin/python
#
# convertconditional: Convert an image if it fulfills certain conditions, e.g. is of a certain size. Requires ImageMagick's convert.
# Rainhard Findling 2013/08
#
# example to convert all *JPG within the current directory with are of certain size to a reduced size and quality:
# find . -iname "*JPG" -exec ./convertconditional {} -filtersize 3888x2592 -convertparams "-resize 3500x3000 +repage -quality 80" \;
#
import argparse # check http://docs.python.org/2/howto/argparse.html for help
import subprocess
import sys
# specify arguments
parser = argparse.ArgumentParser()
parser.add_argument('inputfile', help='path to the file that will be converted.')
parser.add_argument('-convertparams', required=True, help='parameters handed to the convert command used internally, e.g. resize, repage, reduce quality etc. Example: "-resize 300x200 +replage -quality 92"')
parser.add_argument('-filtersize', help='only convert if original image is of this size, stated as WIDTHxHEIGHT, e.g. 3500x3200.')
parser.add_argument('-o', '--outputfile', help='path to where the converted image will be stored. if not specified, the original file will be overwritten.')
parser.add_argument('-v','--verbose',help='print verbose output.',action='store_true')
args = parser.parse_args()
# make sure we can process names with spaces
args.inputfile = '"' + args.inputfile + '"'
# check for correct arguments
if not args.outputfile:
args.outputfile = args.inputfile
if args.filtersize:
filter_x = int(args.filtersize.split('x')[0])
filter_y = int(args.filtersize.split('x')[1])
if args.verbose:
print 'inputfile=' + args.inputfile
print 'outputfile=' + args.outputfile
if args.filtersize:
print 'resizing only', str(filter_x) + 'x' + str(filter_y), 'images.'
print 'convertparams=' + args.convertparams
# get size of image
imagesize = subprocess.check_output(["identify -format '%wx%h' '" + args.inputfile + "'"],
stderr=subprocess.STDOUT,
shell=True)
imagesize_x = int(imagesize.split('x')[0])
imagesize_y = int(imagesize.split('x')[1])
# condition: filter for images of certain size
if args.filtersize:
if args.verbose:
print 'size of', args.inputfile, 'is', str(imagesize_x) + "x" + str(imagesize_y)
# check filter criteria
if not imagesize_x == filter_x or not imagesize_y == filter_y:
print 'leaving out ' + args.inputfile + ' as it is of size ' +  str(imagesize_x) + "x" + str(imagesize_y) + " (required: " + args.filtersize + ")"
sys.exit(0)
# passed all conditions: convert image
print 'converting ' + args.inputfile + ' (size: ' +  str(imagesize_x) + "x" + str(imagesize_y) + ')'
# convert image
command="convert '" + args.inputfile + "' " + args.convertparams + " '" + args.outputfile + "'"
if args.verbose:
print 'command:', command
imagesize = subprocess.check_output([command],
stderr=subprocess.STDOUT,
shell=True)

The script is written in Python, so all you need to do is save it (e.g. in a file called “convertconditional”) and make it executable:

chmod +x convertconditional

Then you can either call it with stating it’s path (e.g. “./convertconditional [parameters]”), or add it to your systems PATH to call it from everyhwere.

Script execution

In order to convert input.jpg to output.jpg, you can try

convertconditional input.jpg -filtersize 3888x2592 -convertparams "-resize 3500x3000 +repage -quality 85" -o output.jpg
  • -filtersize optional filtering: only convert the image  in case it is exactly of the stated size
  • -convertparams states parameters which should be handed to ImageMagick’s convert
  • -o states where to store the converted image (original image gets overwritten if omitted)

In case you want to conditionally convert multiple files (as with my usecase) you can combine convertconditional with find and overwrite the original files:

find . -iname "*JPG" -exec convertconditional {} -filtersize 3888x2592 -convertparams "-resize 3800x +repage -quality 85" \;