#!/usr/bin/perl -w # # Script to scan a directory (presumed to be an exploded ebook of some kind) # and replace all grayscale .jpeg and .jpg images with .png images that use # transparency. The idea is that they will look identical on a white # background, but actually take on the background color or image if you set # something other than white in your ebook. # # Any text files in the directory are scanned for the names of the image # files and the references are changed to point to the new .png files. # # No arguments, just run it while sitting in the exploded ebook directory. # use strict; use File::Find; use File::Basename; my @jpgs; my @txts; my @opfs; my $tmpdir="png$$"; sub check_gray { my $jpg = shift; my $fh; open($fh, '-|', 'convert', $jpg, '(', '+clone', '-colorspace', 'gray', ')', '-compose', 'difference', '-composite', '-colorspace', 'gray', '-format', '%[maximum]', 'info:'); my $factor = <$fh>; close($fh); chomp($factor); return ($factor=~/^\d+$/) && (($factor + 0) < 5000) } sub scanfile { if (-f $_) { # want plain files only, no directories also get rid of the leading ./ my $dotfree = substr($File::Find::name,2); if ((/\.jpeg$/) || (/\.jpg$/)) { # This should be one of the .jpg files we are looking for. if (check_gray($_)) { push(@jpgs, $dotfree); } else { print "$dotfree is not grayscale\n"; } } elsif (-T $_) { # This is some other file in the book which might contain # the name of one of the files we are going to change. push(@txts, $dotfree); if ($_=~/\.opf$/) { push(@opfs, $_); } } } } find(\&scanfile, "."); if (scalar(@jpgs) == 0) { print "No jpg images found.\n"; exit(0); } sub fix_opfs { # Any .opf files may well have .png file references which claim # to have mime type image/jpeg. This final fix replaces those # image/jpeg mime types with image/png. my $opf = shift; my $temp = "tempopf.$$"; my $inf; my $outf; my $update=0; local $_; if (open($inf, '<', $opf)) { if (open($outf, '>', $temp)) { while (<$inf>) { if (/.*item.*\.png.*image\/jpeg/) { s/image\/jpeg/image\/png/; $update=1; } print $outf $_; } close($outf); } close($inf); } if ($update) { unlink($opf); rename($temp,$opf); } else { unlink($temp); } } # Link all the grayscale jpg files into a temp directory mkdir($tmpdir); my $f; foreach $f (@jpgs) { my $b = basename($f); # The gimp color to alpha filter only works on RGB images so make sure # any grayscale images get converted to RGB by using the convert command # to copy the RGB versions to the temp directory. system("convert", "$f", "-depth", "8", "-type", "TrueColor", "$tmpdir/$b"); } # Convert all the files in the temp directory chdir($tmpdir); system("gimp", '-i', '-b', '(batch-set-alpha "*" )', '-b', '(gimp-quit 0)'); chdir(".."); # Now rename all the temp files my @replacepats; foreach $f (@jpgs) { my($b,$d,$s) = fileparse($f, qr/\.[^.]*/); if (-f "$tmpdir/${b}$s.png") { link("$tmpdir/${b}$s.png", "${d}$b.png"); push(@replacepats, $f, "${d}$b.png"); unlink($f); print "$f replaced with ${d}$b.png\n"; } else { print "Hey! $f was not converted to a .png file!\n"; } } system("rm -rf $tmpdir"); push(@replacepats, '--', @txts); system("replace", @replacepats); if (scalar(@opfs) > 0) { foreach $f (@opfs) { fix_opfs($f); } }