random b&w image grain
When I convert images to B&W, I often add some artificial film grain to the image. When I do this by hand, I usually just grab a section of the grain source randomly and hardlight screen the original image with it. Tonight I needed to batch add grain to a number of B&W images and I didn’t want the grain to look consistent among them. After the jump is a perl script that selects a random source-image-sized selection of a grain source and hardlight screens the source image with it. This is done via imagemagick command line utils.
#!/usr/bin/perl
# All of the documentation and software included in this software distribution
# is copyrighted by Matthew C. Mead (m-web@goof.com).
#
# Copyright 2007, Matthew C. Mead. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Matthew C. Mead.
# 4. Neither the name of the author nor the names of any co-contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY MATTHEW C. MEAD ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL MATTHEW C. MEAD OR CO-CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
my $portraitGrain = "/Users/mmead/Desktop/grain-portrait.png";
my $landscapeGrain = "/Users/mmead/Desktop/grain-landscape.png";
my $composite = "composite";
my $identify = "identify";
if ($#ARGV != 1) {
print "Usage: addgrain.pl n";
exit 1;
}
my $source = shift;
my $dest = shift;
my $landscape = 0;
my $grainsource;
open ID, "$identify $source|";
my $id = ;
close ID;
my ($width, $height) = $id =~ /s(d+)x(d+)s/;
if ($width > $height) {
$landscape = 1;
$grainsource = $landscapeGrain;
} else {
$grainsource = $portraitGrain;
}
open ID, "$identify $grainsource|";
$id = ;
close ID;
my ($gwidth, $gheight) = $id =~ /s(d+)x(d+)s/;
if (($width > $gwidth) || ($height > $gheight)) {
print "Grain source not large enough for source image.";
exit 1;
}
my $deltaWidth = $gwidth - $width;
my $deltaHeight = $gheight - $height;
my $offsetWidth = int(rand($deltaWidth));
my $offsetHeight = int(rand($deltaHeight));
system $composite, "-extract", "${width}x${height}+${offsetWidth}+${offsetHeight}", $grainsource, "-compose", "hardlight", $source, "-quality", "90", "-depth", "8", $dest;